element: Inherit element metadata and pad templates from parent classes

This allows to add pad templates and set metadata in class_init instead of
base_init. base_init is a concept that is not supported by almost all
languages and copying the templates/metadata for subclasses is the more
intuitive way of doing things.

Subclasses can override pad templates of parent classes by adding a new
template with the same now.

Also gst_element_class_add_pad_template() now takes ownership of the
pad template, which was assumed by all code before anyway.

Fixes bug #491501.
This commit is contained in:
Sebastian Dröge 2011-04-16 15:03:33 +02:00
parent 8bfdd8c817
commit aad57970de
3 changed files with 51 additions and 28 deletions

View file

@ -45,6 +45,11 @@ The 0.11 porting guide
gstelementmetadata.h contains the keys for all standard metadata. gstelementmetadata.h contains the keys for all standard metadata.
Element metadata and pad templates are inherited from parent classes and
should be added in class_init instead of base_init.
gst_element_class_add_pad_template() takes ownership of the template
* GstPad: * GstPad:
gst_pad_get_caps() does not return writable caps anymore and an explicit gst_pad_get_caps() does not return writable caps anymore and an explicit
gst_caps_make_writable() needs to be performed. This was the functionality gst_caps_make_writable() needs to be performed. This was the functionality

View file

@ -238,18 +238,29 @@ static void
gst_element_base_class_init (gpointer g_class) gst_element_base_class_init (gpointer g_class)
{ {
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GList *node, *padtemplates;
/* FIXME 0.11: Instead of clearing the /* Copy the element details here so elements can inherit the
* pad template list copy the list and increase the refcount of * details from their base class and classes only need to set
* the pad templates by one. * the details in class_init instead of base_init */
* element_class->metadata =
* This will make it possible to add pad templates and set element element_class->metadata ? gst_structure_copy (element_class->metadata) :
* details in the class_init functions and is the real GObject way gst_structure_empty_new ("metadata");
* of doing things.
* See http://bugzilla.gnome.org/show_bug.cgi?id=491501 /* Copy the pad templates so elements inherit them
* from their base class but elements can add pad templates in class_init
* instead of base_init.
*/ */
element_class->metadata = gst_structure_empty_new ("metadata"); /* FIXME: Do we consider GstPadTemplates as immutable? If so we can
element_class->padtemplates = NULL; * simply ref them instead of copying.
*/
padtemplates = g_list_copy (element_class->padtemplates);
for (node = padtemplates; node != NULL; node = node->next) {
GstPadTemplate *tmpl = (GstPadTemplate *) node->data;
node->data = gst_pad_template_new (tmpl->name_template,
tmpl->direction, tmpl->presence, gst_caps_copy (tmpl->caps));
}
element_class->padtemplates = padtemplates;
/* set the factory, see gst_element_register() */ /* set the factory, see gst_element_register() */
element_class->elementfactory = element_class->elementfactory =
@ -1270,30 +1281,37 @@ gst_element_iterate_sink_pads (GstElement * element)
/** /**
* gst_element_class_add_pad_template: * gst_element_class_add_pad_template:
* @klass: the #GstElementClass to add the pad template to. * @klass: the #GstElementClass to add the pad template to.
* @templ: (transfer none): a #GstPadTemplate to add to the element class. * @templ: (transfer full): a #GstPadTemplate to add to the element class.
*
* Adds a padtemplate to an element class. This is mainly used in the _class_init
* functions of classes. If a pad template with the same name as an already
* existing one is added the old one is replaced by the new one.
* *
* Adds a padtemplate to an element class. This is mainly used in the _base_init
* functions of classes.
*/ */
void void
gst_element_class_add_pad_template (GstElementClass * klass, gst_element_class_add_pad_template (GstElementClass * klass,
GstPadTemplate * templ) GstPadTemplate * templ)
{ {
GList *template_list = klass->padtemplates;
g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
g_return_if_fail (GST_IS_PAD_TEMPLATE (templ)); g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
/* FIXME 0.11: allow replacing the pad templates by /* If we already have a pad template with the same name replace the
* calling this with the same name as an already existing pad * old one. */
* template. For this we _must_ _not_ ref the added pad template while (template_list) {
* a second time and _must_ document that this function takes GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data;
* ownership of the pad template. Otherwise we will leak pad templates
* or the caller unref's the pad template and it disappears */
/* avoid registering pad templates with the same name */
g_return_if_fail (gst_element_class_get_pad_template (klass,
templ->name_template) == NULL);
klass->padtemplates = g_list_append (klass->padtemplates, /* Found pad with the same name, replace and return */
gst_object_ref (templ)); if (strcmp (templ->name_template, padtempl->name_template) == 0) {
gst_object_unref (padtempl);
template_list->data = templ;
return;
}
template_list = g_list_next (template_list);
}
klass->padtemplates = g_list_append (klass->padtemplates, templ);
klass->numpadtemplates++; klass->numpadtemplates++;
} }
@ -1330,7 +1348,7 @@ gst_element_class_add_metadata (GstElementClass * klass,
* multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"
* *
* Sets the detailed information for a #GstElementClass. * Sets the detailed information for a #GstElementClass.
* <note>This function is for use in _base_init functions only.</note> * <note>This function is for use in _class_init functions only.</note>
*/ */
void void
gst_element_class_set_metadata (GstElementClass * klass, gst_element_class_set_metadata (GstElementClass * klass,

View file

@ -78,13 +78,13 @@
* </example> * </example>
* *
* The following example shows you how to add the padtemplate to an * The following example shows you how to add the padtemplate to an
* element class, this is usually done in the base_init of the class: * element class, this is usually done in the class_init of the class:
* <informalexample> * <informalexample>
* <programlisting> * <programlisting>
* static void * static void
* my_element_base_init (gpointer g_class) * my_element_class_init (GstMyElementClass *klass)
* { * {
* GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); * GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
* *
* gst_element_class_add_pad_template (gstelement_class, * gst_element_class_add_pad_template (gstelement_class,
* gst_static_pad_template_get (&amp;my_template)); * gst_static_pad_template_get (&amp;my_template));