Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / gstpadtemplate.c
index dc87156..bf8d576 100644 (file)
  * @see_also: #GstPad, #GstElementFactory
  *
  * Padtemplates describe the possible media types a pad or an elementfactory can
- * handle.
+ * handle. This allows for both inspection of handled types before loading the
+ * element plugin as well as identifying pads on elements that are not yet
+ * created (request or sometimes pads).
  *
  * Pad and PadTemplates have #GstCaps attached to it to describe the media type
- * they are capable of dealing with. gst_pad_template_get_caps() is used to get
- * the caps of a padtemplate. It's not possible to modify the caps of a
- * padtemplate after creation.
+ * they are capable of dealing with. gst_pad_template_get_caps() or
+ * GST_PAD_TEMPLATE_CAPS() are used to get the caps of a padtemplate. It's not
+ * possible to modify the caps of a padtemplate after creation.
  *
- * Padtemplates can be created with gst_pad_template_new() or with the
- * convenient GST_PAD_TEMPLATE_FACTORY() macro. A padtemplate can be used to
- * create a pad or to add to an elementfactory.
+ * PadTemplates have a #GstPadPresence property which identifies the lifetime
+ * of the pad and that can be retrieved with GST_PAD_TEMPLATE_PRESENCE(). Also
+ * the direction of the pad can be retrieved from the #GstPadTemplate with
+ * GST_PAD_TEMPLATE_DIRECTION().
+ *
+ * The GST_PAD_TEMPLATE_NAME_TEMPLATE () is important for GST_PAD_REQUEST pads
+ * because it has to be used as the name in the gst_element_get_request_pad()
+ * call to instantiate a pad from this template.
+ *
+ * Padtemplates can be created with gst_pad_template_new() or with
+ * gst_static_pad_template_get (), which creates a #GstPadTemplate from a
+ * #GstStaticPadTemplate that can be filled with the
+ * convenient GST_STATIC_PAD_TEMPLATE() macro.
+ *
+ * A padtemplate can be used to create a pad (see gst_pad_new_from_template()
+ * or gst_pad_new_from_static_template ()) or to add to an element class
+ * (see gst_element_class_add_pad_template ()).
  *
  * The following code example shows the code to create a pad from a padtemplate.
  * <example>
  *       "audio/x-raw-int, "
  *         "channels = (int) [ 1, 6 ]"
  *     )
- *   )
+ *   );
  *   void
  *   my_method (void)
  *   {
  *     GstPad *pad;
- *     pad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (my_template_factory), "sink");
+ *     pad = gst_pad_new_from_static_template (&amp;my_template, "sink");
  *     ...
  *   }
  *   </programlisting>
  * </example>
  *
  * The following example shows you how to add the padtemplate to an
- * elementfactory:
+ * element class, this is usually done in the class_init of the class:
  * <informalexample>
  *   <programlisting>
- *   gboolean
- *   my_factory_init (GstPlugin *plugin)
+ *   static void
+ *   my_element_class_init (GstMyElementClass *klass)
  *   {
- *     GstElementFactory *factory;
- *     factory = gst_element_factory_new ("my_factory", GST_TYPE_MYFACTORY, &amp;gst_myfactory_details);
- *     g_return_val_if_fail (factory != NULL, FALSE);
- *     gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (my_template_factory));
- *     gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
- *     return TRUE;
+ *     GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+ *
+ *     gst_element_class_add_pad_template (gstelement_class,
+ *         gst_static_pad_template_get (&amp;my_template));
  *   }
  *   </programlisting>
  * </informalexample>
+ *
+ * Last reviewed on 2006-02-14 (0.10.3)
  */
 
 #include "gst_private.h"
 
 enum
 {
+  PROP_NAME_TEMPLATE = 1,
+  PROP_DIRECTION,
+  PROP_PRESENCE,
+  PROP_CAPS
+};
+
+enum
+{
   TEMPL_PAD_CREATED,
   /* FILL ME */
   LAST_SIGNAL
@@ -102,30 +126,13 @@ enum
 static GstObject *parent_class = NULL;
 static guint gst_pad_template_signals[LAST_SIGNAL] = { 0 };
 
-static void gst_pad_template_class_init (GstPadTemplateClass * klass);
-static void gst_pad_template_init (GstPadTemplate * templ);
 static void gst_pad_template_dispose (GObject * object);
+static void gst_pad_template_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_pad_template_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
 
-GType
-gst_pad_template_get_type (void)
-{
-  static GType padtemplate_type = 0;
-
-  if (!padtemplate_type) {
-    static const GTypeInfo padtemplate_info = {
-      sizeof (GstPadTemplateClass), NULL, NULL,
-      (GClassInitFunc) gst_pad_template_class_init, NULL, NULL,
-      sizeof (GstPadTemplate),
-      0,
-      (GInstanceInitFunc) gst_pad_template_init, NULL
-    };
-
-    padtemplate_type =
-        g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate",
-        &padtemplate_info, 0);
-  }
-  return padtemplate_type;
-}
+G_DEFINE_TYPE (GstPadTemplate, gst_pad_template, GST_TYPE_OBJECT);
 
 static void
 gst_pad_template_class_init (GstPadTemplateClass * klass)
@@ -136,7 +143,7 @@ gst_pad_template_class_init (GstPadTemplateClass * klass)
   gobject_class = (GObjectClass *) klass;
   gstobject_class = (GstObjectClass *) klass;
 
-  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+  parent_class = g_type_class_peek_parent (klass);
 
   /**
    * GstPadTemplate::pad-created:
@@ -152,6 +159,60 @@ gst_pad_template_class_init (GstPadTemplateClass * klass)
 
   gobject_class->dispose = gst_pad_template_dispose;
 
+  gobject_class->get_property = gst_pad_template_get_property;
+  gobject_class->set_property = gst_pad_template_set_property;
+
+  /**
+   * GstPadTemplate:name-template
+   *
+   * The name template of the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_NAME_TEMPLATE,
+      g_param_spec_string ("name-template", "Name template",
+          "The name template of the pad template", NULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:direction
+   *
+   * The direction of the pad described by the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_DIRECTION,
+      g_param_spec_enum ("direction", "Direction",
+          "The direction of the pad described by the pad template",
+          GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:presence
+   *
+   * When the pad described by the pad template will become available.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_PRESENCE,
+      g_param_spec_enum ("presence", "Presence",
+          "When the pad described by the pad template will become available",
+          GST_TYPE_PAD_PRESENCE, GST_PAD_ALWAYS,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstPadTemplate:caps
+   *
+   * The capabilities of the pad described by the pad template.
+   *
+   * Since: 0.10.21
+   */
+  g_object_class_install_property (gobject_class, PROP_CAPS,
+      g_param_spec_boxed ("caps", "Caps",
+          "The capabilities of the pad described by the pad template",
+          GST_TYPE_CAPS,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
   gstobject_class->path_string_separator = "*";
 }
 
@@ -198,9 +259,9 @@ name_is_valid (const gchar * name, GstPadPresence presence)
           " allowed in GST_PAD_REQUEST padtemplate", name);
       return FALSE;
     }
-    if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) {
+    if (str && (*(str + 1) != 's' && *(str + 1) != 'd' && *(str + 1) != 'u')) {
       g_warning ("invalid name template %s: conversion specification must be of"
-          " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name);
+          " type '%%d', '%%u' or '%%s' for GST_PAD_REQUEST padtemplate", name);
       return FALSE;
     }
     if (str && (*(str + 2) != '\0')) {
@@ -218,7 +279,7 @@ gst_static_pad_template_get_type (void)
 {
   static GType staticpadtemplate_type = 0;
 
-  if (!staticpadtemplate_type) {
+  if (G_UNLIKELY (staticpadtemplate_type == 0)) {
     staticpadtemplate_type =
         g_pointer_type_register_static ("GstStaticPadTemplate");
   }
@@ -231,25 +292,27 @@ gst_static_pad_template_get_type (void)
  *
  * Converts a #GstStaticPadTemplate into a #GstPadTemplate.
  *
- * Returns: a new #GstPadTemplate.
+ * Returns: (transfer full): a new #GstPadTemplate.
  */
+/* FIXME0.11: rename to gst_pad_template_new_from_static_pad_template() */
 GstPadTemplate *
 gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
 {
   GstPadTemplate *new;
+  GstCaps *caps;
 
   if (!name_is_valid (pad_template->name_template, pad_template->presence))
     return NULL;
 
-  new = g_object_new (gst_pad_template_get_type (),
-      "name", pad_template->name_template, NULL);
+  caps = gst_static_caps_get (&pad_template->static_caps);
 
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence;
+  new = g_object_new (gst_pad_template_get_type (),
+      "name", pad_template->name_template,
+      "name-template", pad_template->name_template,
+      "direction", pad_template->direction,
+      "presence", pad_template->presence, "caps", caps, NULL);
 
-  GST_PAD_TEMPLATE_CAPS (new) =
-      gst_caps_copy (gst_static_caps_get (&pad_template->static_caps));
+  gst_caps_unref (caps);
 
   return new;
 }
@@ -259,13 +322,12 @@ gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
  * @name_template: the name template.
  * @direction: the #GstPadDirection of the template.
  * @presence: the #GstPadPresence of the pad.
- * @caps: a #GstCaps set for the template. The caps are taken ownership of.
+ * @caps: a #GstCaps set for the template.
  *
  * Creates a new pad template with a name according to the given template
- * and with the given arguments. This functions takes ownership of the provided
- * caps, so be sure to not use them afterwards.
+ * and with the given arguments.
  *
- * Returns: a new #GstPadTemplate.
+ * Returns: (transfer full): a new #GstPadTemplate.
  */
 GstPadTemplate *
 gst_pad_template_new (const gchar * name_template,
@@ -281,17 +343,12 @@ gst_pad_template_new (const gchar * name_template,
       || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL);
 
   if (!name_is_valid (name_template, presence)) {
-    gst_caps_unref (caps);
     return NULL;
   }
 
   new = g_object_new (gst_pad_template_get_type (),
-      "name", name_template, NULL);
-
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = presence;
-  GST_PAD_TEMPLATE_CAPS (new) = caps;
+      "name", name_template, "name-template", name_template,
+      "direction", direction, "presence", presence, "caps", caps, NULL);
 
   return new;
 }
@@ -302,8 +359,10 @@ gst_pad_template_new (const gchar * name_template,
  *
  * Gets the capabilities of the static pad template.
  *
- * Returns: the #GstCaps of the static pad template. If you need to keep a
- * reference to the caps, take a ref (see gst_caps_ref ()).
+ * Returns: (transfer full): the #GstCaps of the static pad template.
+ * Unref after usage. Since the core holds an additional
+ * ref to the returned caps, use gst_caps_make_writable()
+ * on the returned caps to modify it.
  */
 GstCaps *
 gst_static_pad_template_get_caps (GstStaticPadTemplate * templ)
@@ -319,21 +378,79 @@ gst_static_pad_template_get_caps (GstStaticPadTemplate * templ)
  *
  * Gets the capabilities of the pad template.
  *
- * Returns: the #GstCaps of the pad template. If you need to keep a reference to
- * the caps, take a ref (see gst_caps_ref ()).
+ * Returns: (transfer full): the #GstCaps of the pad template.
+ * Unref after usage.
  */
 GstCaps *
 gst_pad_template_get_caps (GstPadTemplate * templ)
 {
+  GstCaps *caps;
   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
 
-  return GST_PAD_TEMPLATE_CAPS (templ);
+  caps = GST_PAD_TEMPLATE_CAPS (templ);
+
+  return (caps ? gst_caps_ref (caps) : NULL);
 }
 
+/**
+ * gst_pad_template_pad_created:
+ * @templ: a #GstPadTemplate that has been created
+ * @pad:   the #GstPad that created it
+ *
+ * Emit the pad-created signal for this template when created by this pad.
+ */
 void
 gst_pad_template_pad_created (GstPadTemplate * templ, GstPad * pad)
 {
-  gst_object_sink (GST_OBJECT (templ));
-  g_signal_emit (G_OBJECT (templ),
-      gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
+  g_signal_emit (templ, gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
+}
+
+static void
+gst_pad_template_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  /* these properties are all construct-only */
+  switch (prop_id) {
+    case PROP_NAME_TEMPLATE:
+      GST_PAD_TEMPLATE_NAME_TEMPLATE (object) = g_value_dup_string (value);
+      break;
+    case PROP_DIRECTION:
+      GST_PAD_TEMPLATE_DIRECTION (object) =
+          (GstPadDirection) g_value_get_enum (value);
+      break;
+    case PROP_PRESENCE:
+      GST_PAD_TEMPLATE_PRESENCE (object) =
+          (GstPadPresence) g_value_get_enum (value);
+      break;
+    case PROP_CAPS:
+      GST_PAD_TEMPLATE_CAPS (object) = g_value_dup_boxed (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_pad_template_get_property (GObject * object, guint prop_id, GValue * value,
+    GParamSpec * pspec)
+{
+  /* these properties are all construct-only */
+  switch (prop_id) {
+    case PROP_NAME_TEMPLATE:
+      g_value_set_string (value, GST_PAD_TEMPLATE_NAME_TEMPLATE (object));
+      break;
+    case PROP_DIRECTION:
+      g_value_set_enum (value, GST_PAD_TEMPLATE_DIRECTION (object));
+      break;
+    case PROP_PRESENCE:
+      g_value_set_enum (value, GST_PAD_TEMPLATE_PRESENCE (object));
+      break;
+    case PROP_CAPS:
+      g_value_set_boxed (value, GST_PAD_TEMPLATE_CAPS (object));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }