element: Allow multiple conversion specifiers for request pads
authorWonchul Lee <wonchul.lee@collabora.com>
Fri, 29 Apr 2016 07:26:49 +0000 (16:26 +0900)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 1 Nov 2016 18:29:03 +0000 (20:29 +0200)
This allows pad template names like "src_%u_%u", but it does not allow
multiple specifiers of string type %s as that would lead to ambiguities.

https://bugzilla.gnome.org/show_bug.cgi?id=761225

gst/gstelement.c
gst/gstpadtemplate.c
tests/check/gst/gstelement.c
tests/check/gst/gstpad.c

index 73de61e..7eea64d 100644 (file)
@@ -920,53 +920,136 @@ gst_element_get_static_pad (GstElement * element, const gchar * name)
   return result;
 }
 
-static GstPad *
-_gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
-    const gchar * name, const GstCaps * caps)
+static gboolean
+gst_element_is_valid_request_template_name (const gchar * templ_name,
+    const gchar * name)
 {
-  GstPad *newpad = NULL;
-  GstElementClass *oclass;
+  gchar *endptr;
+  const gchar *templ_name_ptr, *name_ptr;
+  gboolean next_specifier;
+  guint templ_postfix_len = 0, name_postfix_len = 0;
 
-  oclass = GST_ELEMENT_GET_CLASS (element);
+  g_return_val_if_fail (templ_name != NULL, FALSE);
+  g_return_val_if_fail (name != NULL, FALSE);
 
-#ifndef G_DISABLE_CHECKS
-  /* Some sanity checking here */
-  if (name) {
-    GstPad *pad;
+  /* Is this the template name? */
+  if (strcmp (templ_name, name) == 0)
+    return TRUE;
 
-    /* Is this the template name? */
-    if (strstr (name, "%") || !strchr (templ->name_template, '%')) {
-      g_return_val_if_fail (strcmp (name, templ->name_template) == 0, NULL);
-    } else {
-      const gchar *str, *data;
-      gchar *endptr;
+  /* otherwise check all the specifiers */
+  do {
+    /* Because of sanity checks in gst_pad_template_new(), we know that %s
+     * and %d and %u, occurring at the template_name */
+    templ_name_ptr = strchr (templ_name, '%');
+
+    /* check characters ahead of the specifier */
+    if (!templ_name_ptr || strlen (name) <= templ_name_ptr - templ_name
+        || strncmp (templ_name, name, templ_name_ptr - templ_name) != 0) {
+      return FALSE;
+    }
+
+    /* %s is not allowed for multiple specifiers, just a single specifier can be
+     * accepted in gst_pad_template_new() and can not be mixed with other
+     * specifier '%u' and '%d' */
+    if (*(templ_name_ptr + 1) == 's' && g_strcmp0 (templ_name, name) == 0) {
+      return TRUE;
+    }
+
+    name_ptr = name + (templ_name_ptr - templ_name);
+
+    /* search next specifier, each of specifier should be separated by '_' */
+    templ_name = strchr (templ_name_ptr, '_');
+    name = strchr (name_ptr, '_');
+
+    /* don't match the number of specifiers */
+    if ((templ_name && !name) || (!templ_name && name))
+      return FALSE;
+
+    if (templ_name && name)
+      next_specifier = TRUE;
+    else
+      next_specifier = FALSE;
+
+    /* check characters followed by the specifier */
+    if (*(templ_name_ptr + 2) != '\0' && *(templ_name_ptr + 2) != '_') {
+      if (next_specifier) {
+        templ_postfix_len = templ_name - (templ_name_ptr + 2);
+        name_postfix_len = name - name_ptr;
+      } else {
+        templ_postfix_len = strlen (templ_name_ptr + 2);
+        name_postfix_len = strlen (name_ptr);
+      }
+
+      if (strncmp (templ_name_ptr + 2,
+              name_ptr + name_postfix_len - templ_postfix_len,
+              templ_postfix_len) != 0) {
+        return FALSE;
+      }
+    }
+
+    /* verify the specifier */
+    if (*(name_ptr) == '%') {
+      guint len;
 
-      /* Otherwise check if it's a valid name for the name template */
-      str = strchr (templ->name_template, '%');
-      g_return_val_if_fail (str != NULL, NULL);
-      g_return_val_if_fail (strncmp (templ->name_template, name,
-              str - templ->name_template) == 0, NULL);
-      g_return_val_if_fail (strlen (name) > str - templ->name_template, NULL);
+      len = (next_specifier) ? name - name_ptr : strlen (name_ptr);
 
-      data = name + (str - templ->name_template);
+      if (strncmp (name_ptr, templ_name_ptr, len) != 0)
+        return FALSE;
+
+    } else {
+      const gchar *specifier;
+      gchar *target = NULL;
 
-      /* Can either be %s or %d or %u, do sanity checking for %d */
-      if (*(str + 1) == 'd') {
+      /* extract specifier when it has postfix characters */
+      if (name_postfix_len > templ_postfix_len) {
+        target = g_strndup (name_ptr, name_postfix_len - templ_postfix_len);
+      }
+      specifier = target ? target : name_ptr;
+
+      if (*(templ_name_ptr + 1) == 'd') {
         gint64 tmp;
 
         /* it's an int */
-        tmp = g_ascii_strtoll (data, &endptr, 10);
-        g_return_val_if_fail (tmp >= G_MININT && tmp <= G_MAXINT
-            && *endptr == '\0', NULL);
-      } else if (*(str + 1) == 'u') {
+        tmp = g_ascii_strtoll (specifier, &endptr, 10);
+        if (tmp < G_MININT || tmp > G_MAXINT || (*endptr != '\0'
+                && *endptr != '_'))
+          return FALSE;
+      } else if (*(templ_name_ptr + 1) == 'u') {
         guint64 tmp;
 
         /* it's an int */
-        tmp = g_ascii_strtoull (data, &endptr, 10);
-        g_return_val_if_fail (tmp <= G_MAXUINT && *endptr == '\0', NULL);
+        tmp = g_ascii_strtoull (specifier, &endptr, 10);
+        if (tmp > G_MAXUINT || (*endptr != '\0' && *endptr != '_'))
+          return FALSE;
       }
+
+      g_free (target);
     }
 
+    templ_name++;
+    name++;
+  } while (next_specifier);
+
+  return TRUE;
+}
+
+static GstPad *
+_gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
+    const gchar * name, const GstCaps * caps)
+{
+  GstPad *newpad = NULL;
+  GstElementClass *oclass;
+
+  oclass = GST_ELEMENT_GET_CLASS (element);
+
+#ifndef G_DISABLE_CHECKS
+  /* Some sanity checking here */
+  if (name) {
+    GstPad *pad;
+
+    g_return_val_if_fail (gst_element_is_valid_request_template_name
+        (templ->name_template, name), NULL);
+
     pad = gst_element_get_static_pad (element, name);
     if (pad) {
       gst_object_unref (pad);
@@ -1011,8 +1094,6 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
   const gchar *req_name = NULL;
   gboolean templ_found = FALSE;
   GList *list;
-  const gchar *data;
-  gchar *str, *endptr = NULL;
   GstElementClass *class;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
@@ -1020,13 +1101,10 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
 
   class = GST_ELEMENT_GET_CLASS (element);
 
-  /* if the name contains a %, we assume it's the complete template name. Get
-   * the template and try to get a pad */
-  if (strstr (name, "%")) {
-    templ = gst_element_class_get_request_pad_template (class, name);
-    req_name = NULL;
-    if (templ)
-      templ_found = TRUE;
+  templ = gst_element_class_get_request_pad_template (class, name);
+  if (templ) {
+    req_name = strstr (name, "%") ? NULL : name;
+    templ_found = TRUE;
   } else {
     /* there is no % in the name, try to find a matching template */
     list = class->padtemplates;
@@ -1035,48 +1113,12 @@ gst_element_get_request_pad (GstElement * element, const gchar * name)
       if (templ->presence == GST_PAD_REQUEST) {
         GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
             templ->name_template);
-        /* see if we find an exact match */
-        if (strcmp (name, templ->name_template) == 0) {
+        if (gst_element_is_valid_request_template_name (templ->name_template,
+                name)) {
           templ_found = TRUE;
           req_name = name;
           break;
         }
-        /* Because of sanity checks in gst_pad_template_new(), we know that %s
-           and %d and %u, occurring at the end of the name_template, are the only
-           possibilities. */
-        else if ((str = strchr (templ->name_template, '%'))
-            && strncmp (templ->name_template, name,
-                str - templ->name_template) == 0
-            && strlen (name) > str - templ->name_template) {
-          data = name + (str - templ->name_template);
-          if (*(str + 1) == 'd') {
-            glong tmp;
-
-            /* it's an int */
-            tmp = strtol (data, &endptr, 10);
-            if (tmp != G_MINLONG && tmp != G_MAXLONG && endptr &&
-                *endptr == '\0') {
-              templ_found = TRUE;
-              req_name = name;
-              break;
-            }
-          } else if (*(str + 1) == 'u') {
-            gulong tmp;
-
-            /* it's an int */
-            tmp = strtoul (data, &endptr, 10);
-            if (tmp != G_MAXULONG && endptr && *endptr == '\0') {
-              templ_found = TRUE;
-              req_name = name;
-              break;
-            }
-          } else {
-            /* it's a string */
-            templ_found = TRUE;
-            req_name = name;
-            break;
-          }
-        }
       }
       list = list->next;
     }
index 4c834bb..453c2d1 100644 (file)
@@ -221,14 +221,14 @@ gst_pad_template_dispose (GObject * object)
  * since it doesn't make sense.
  * SOMETIMES padtemplates can do whatever they want, they are provided by the
  * element.
- * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the
- * 'sink%d' template is automatically selected), so we need to restrict their
- * naming.
+ * REQUEST padtemplates can have multiple specifiers in case of %d and %u, like
+ * src_%u_%u, but %s only can be used once in the template.
  */
 static gboolean
 name_is_valid (const gchar * name, GstPadPresence presence)
 {
-  const gchar *str;
+  const gchar *str, *underscore = NULL;
+  gboolean has_s = FALSE;
 
   if (presence == GST_PAD_ALWAYS) {
     if (strchr (name, '%')) {
@@ -237,20 +237,38 @@ name_is_valid (const gchar * name, GstPadPresence presence)
       return FALSE;
     }
   } else if (presence == GST_PAD_REQUEST) {
-    if ((str = strchr (name, '%')) && strchr (str + 1, '%')) {
-      g_warning ("invalid name template %s: only one conversion specification"
-          " allowed in GST_PAD_REQUEST padtemplate", name);
-      return FALSE;
-    }
-    if (str && (*(str + 1) != 's' && *(str + 1) != 'd' && *(str + 1) != 'u')) {
-      g_warning ("invalid name template %s: conversion specification must be of"
-          " type '%%d', '%%u' or '%%s' for GST_PAD_REQUEST padtemplate", name);
-      return FALSE;
-    }
-    if (str && (*(str + 2) != '\0')) {
-      g_warning ("invalid name template %s: conversion specification must"
-          " appear at the end of the GST_PAD_REQUEST padtemplate name", name);
-      return FALSE;
+    str = strchr (name, '%');
+
+    while (str) {
+      if (*(str + 1) != 's' && *(str + 1) != 'd' && *(str + 1) != 'u') {
+        g_warning
+            ("invalid name template %s: conversion specification must be of"
+            " type '%%d', '%%u' or '%%s' for GST_PAD_REQUEST padtemplate",
+            name);
+        return FALSE;
+      }
+
+      if (*(str + 1) == 's' && (*(str + 2) != '\0' || has_s)) {
+        g_warning
+            ("invalid name template %s: conversion specification of type '%%s'"
+            "only can be used once in the GST_PAD_REQUEST padtemplate at the "
+            "very end and not allowed any other characters with '%%s'", name);
+        return FALSE;
+      }
+
+      if (*(str + 1) == 's') {
+        has_s = TRUE;
+      }
+
+      underscore = strchr (str, '_');
+      str = strchr (str + 1, '%');
+
+      if (str && (!underscore || (underscore && str < underscore))) {
+        g_warning
+            ("invalid name template %s: each of conversion specifications "
+            "must be separated by an underscore", name);
+        return FALSE;
+      }
     }
   }
 
index e2505bb..d22471f 100644 (file)
  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
 
 #include <gst/check/gstcheck.h>
+#include <gst/gstelement.h>
 
 GST_START_TEST (test_add_remove_pad)
 {
@@ -477,6 +481,309 @@ GST_START_TEST (test_property_notify_message)
   gst_element_remove_property_notify_watch (pipeline, deep_watch_id1);
   gst_element_remove_property_notify_watch (pipeline, deep_watch_id2);
   gst_element_set_state (pipeline, GST_STATE_NULL);
+
+  gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
+typedef struct _GstTestElement3
+{
+  GstElement parent;
+
+} GstTestElement3;
+
+typedef struct _GstTestElement3Class
+{
+  GstElementClass parent;
+
+} GstTestElement3Class;
+
+static GstPad *
+gst_test_element3_request_new_pad (GstElement * element, GstPadTemplate * templ,
+    const gchar * name, const GstCaps * caps)
+{
+  GstPad *pad;
+  gchar *str;
+  gchar *pad_name;
+  gint n_conversion = 0;
+  static gint i = 0;
+
+  str = templ->name_template;
+  while ((str = strchr (str, '%'))) {
+    n_conversion++;
+    str++;
+  }
+
+  if (strcmp (templ->name_template, "src_%ublah_blah%ublah") == 0)
+    pad_name = g_strdup_printf ("src_%ublah_blah_%ublah", i, i + 1);
+  else if (n_conversion == 1) {
+    pad_name = g_strdup_printf ("src_%u", i);
+  } else if (n_conversion == 2) {
+    pad_name = g_strdup_printf ("src_%u_%u", i, i + 1);
+  } else if (n_conversion == 3) {
+    pad_name = g_strdup_printf ("src_%u_%u_%u", i, i + 1, i + 2);
+  } else {
+    pad_name = g_strdup (name);
+  }
+
+  pad = gst_pad_new_from_template (templ, pad_name);
+
+  gst_element_add_pad (element, pad);
+
+  i++;
+  g_free (pad_name);
+
+  return pad;
+}
+
+static void
+gst_test_element3_release_pad (GstElement * element, GstPad * pad)
+{
+  gst_element_remove_pad (element, pad);
+}
+
+static void
+gst_test_element3_init (GstTestElement3 * test)
+{
+  GstPadTemplate *pad_template;
+  GstPad *sinkpad;
+
+  pad_template =
+      gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (test), "sink");
+  g_return_if_fail (pad_template != NULL);
+  sinkpad = gst_pad_new_from_template (pad_template, "sink");
+
+  gst_element_add_pad (GST_ELEMENT (test), sinkpad);
+}
+
+static void
+gst_test_element3_class_init (GstTestElement3Class * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_metadata (element_class, "Test element 3",
+      "Element", "For testing request pad template", "Foo Bar <foo@bar.com>");
+
+  element_class->request_new_pad =
+      GST_DEBUG_FUNCPTR (gst_test_element3_request_new_pad);
+  element_class->release_pad =
+      GST_DEBUG_FUNCPTR (gst_test_element3_release_pad);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%u", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%u_%u", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%u_%u_%u", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%ublah_blah%ublah", GST_PAD_SRC,
+          GST_PAD_REQUEST, GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%d", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%d_%d", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%d_%d_%d", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%s", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("src_%u_%s", GST_PAD_SRC, GST_PAD_REQUEST,
+          GST_CAPS_ANY));
+
+  gst_element_class_add_pad_template (element_class,
+      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+          GST_CAPS_ANY));
+}
+
+static GType
+gst_test_element3_get_type (void)
+{
+  static GType gst_test_element3_type = G_TYPE_NONE;
+
+  if (gst_test_element3_type == G_TYPE_NONE) {
+    static const GTypeInfo gst_test_element3_info = {
+      sizeof (GstTestElement3Class),
+      NULL,                     /* base_init */
+      NULL,                     /* base_finalize */
+      (GClassInitFunc) gst_test_element3_class_init,
+      NULL,
+      NULL,
+      sizeof (GstTestElement3),
+      0,
+      (GInstanceInitFunc) gst_test_element3_init,
+      NULL
+    };
+
+    gst_test_element3_type =
+        g_type_register_static (gst_element_get_type (), "GstTestElement3",
+        &gst_test_element3_info, 0);
+  }
+  return gst_test_element3_type;
+}
+
+static gboolean
+gst_test_element3_plugin_init (GstPlugin * plugin)
+{
+  gst_element_register (plugin, "test3", GST_RANK_NONE,
+      gst_test_element3_get_type ());
+  return TRUE;
+}
+
+GST_START_TEST (test_request_pad_templates)
+{
+  GstTestElement3 *test;
+  GstElement *pipeline, *sink;
+  GstPad *pad;
+  GHashTable *padnames;
+  GHashTableIter iter;
+  gpointer key, value;
+  const gchar *pad_name, *templ_name;
+  GSList *padname_blacklists = NULL, *item;
+  GError *err = NULL;
+
+  padnames = g_hash_table_new (g_str_hash, g_str_equal);
+
+  g_hash_table_insert (padnames, (gpointer) "src_0", (gpointer) "src_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u", (gpointer) "src_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_%u",
+      (gpointer) "src_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_0_%u", (gpointer) "src_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_0", (gpointer) "src_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_0_1", (gpointer) "src_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_%u_%u",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_0_%u_%u",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_0_1_%u",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_0_1_2",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_0_%u",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_0_1",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_%u_0",
+      (gpointer) "src_%u_%u_%u");
+  g_hash_table_insert (padnames, (gpointer) "src_%ublah_blah%ublah",
+      (gpointer) "src_%ublah_blah%ublah");
+  g_hash_table_insert (padnames, (gpointer) "src_%d", (gpointer) "src_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%d_%d",
+      (gpointer) "src_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_1_%d", (gpointer) "src_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%d_%d_%d",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_1_2_%d",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_1_%d_2",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%d_2_1",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%d_%d_1",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%d_1_%d",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_1_%d_%d",
+      (gpointer) "src_%d_%d_%d");
+  g_hash_table_insert (padnames, (gpointer) "src_%s", (gpointer) "src_%s");
+  g_hash_table_insert (padnames, (gpointer) "src_%u_%s",
+      (gpointer) "src_%u_%s");
+
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%u%u");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%u_%d");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%u_%u_");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%u_%s_%s");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%s_%u");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%s_%s");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%s_%s_%s");
+  padname_blacklists =
+      g_slist_append (padname_blacklists, (gpointer) "src_%s_blah");
+
+  test = g_object_new (gst_test_element3_get_type (), NULL);
+
+  /* check available request pad names */
+  g_hash_table_iter_init (&iter, padnames);
+  while (g_hash_table_iter_next (&iter, &key, &value)) {
+    pad_name = (const gchar *) key;
+    templ_name = (const gchar *) value;
+
+    pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name);
+    fail_unless (pad != NULL);
+    gst_element_release_request_pad (GST_ELEMENT (test), pad);
+    gst_object_unref (pad);
+
+    pad = gst_element_request_pad (GST_ELEMENT (test),
+        gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (test),
+            templ_name), pad_name, NULL);
+    fail_unless (pad != NULL);
+    gst_element_release_request_pad (GST_ELEMENT (test), pad);
+    gst_object_unref (pad);
+  }
+
+  item = padname_blacklists;
+
+  /* check invalid request pad name */
+  while (item) {
+    pad_name = (const gchar *) (item->data);
+    item = g_slist_next (item);
+    pad = gst_element_get_request_pad (GST_ELEMENT (test), pad_name);
+    fail_unless (pad == NULL);
+  }
+
+  /* check it working with some APIs
+   * gst_element_link/link_pads */
+  sink = gst_element_factory_make ("fakesink", "sink");
+
+  fail_unless (gst_element_link (GST_ELEMENT (test), sink));
+  gst_element_unlink (GST_ELEMENT (test), sink);
+
+  fail_unless (gst_element_link_pads (GST_ELEMENT (test), "src_%u_%u", sink,
+          "sink"));
+  gst_element_unlink (GST_ELEMENT (test), sink);
+
+  g_object_unref (test);
+  g_object_unref (sink);
+
+  /* gst_parse_launch */
+  gst_plugin_register_static (GST_VERSION_MAJOR,
+      GST_VERSION_MINOR,
+      "test3",
+      "request pad template test",
+      gst_test_element3_plugin_init,
+      VERSION, GST_LICENSE, PACKAGE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
+
+  pipeline =
+      gst_parse_launch ("fakesrc ! test3 name=t ! fakesink t. ! fakesink",
+      &err);
+  fail_unless (pipeline && err == NULL);
+
+  if (err) {
+    g_error_free (err);
+  }
+  g_slist_free (padname_blacklists);
+  g_hash_table_unref (padnames);
   gst_object_unref (pipeline);
 }
 
@@ -496,6 +803,7 @@ gst_element_suite (void)
   tcase_add_test (tc_chain, test_link_no_pads);
   tcase_add_test (tc_chain, test_pad_templates);
   tcase_add_test (tc_chain, test_property_notify_message);
+  tcase_add_test (tc_chain, test_request_pad_templates);
 
   return s;
 }
index 4e098c2..7f50039 100644 (file)
@@ -584,7 +584,7 @@ GST_START_TEST (test_name_is_valid)
   ASSERT_WARNING (name_is_valid ("src%s%s", GST_PAD_REQUEST));
   ASSERT_WARNING (name_is_valid ("src%c", GST_PAD_REQUEST));
   ASSERT_WARNING (name_is_valid ("src%", GST_PAD_REQUEST));
-  ASSERT_WARNING (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
+  fail_unless (name_is_valid ("src%dsrc", GST_PAD_REQUEST));
 
   fail_unless (name_is_valid ("src", GST_PAD_SOMETIMES));
   fail_unless (name_is_valid ("src%c", GST_PAD_SOMETIMES));