From aad57970deb6a6212dbd0a7c046d656d37dc9c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 16 Apr 2011 15:03:33 +0200 Subject: [PATCH] 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. --- docs/random/porting-to-0.11.txt | 5 +++ gst/gstelement.c | 68 +++++++++++++++++++++------------ gst/gstpadtemplate.c | 6 +-- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/docs/random/porting-to-0.11.txt b/docs/random/porting-to-0.11.txt index 9c221cf613..9d601d29b4 100644 --- a/docs/random/porting-to-0.11.txt +++ b/docs/random/porting-to-0.11.txt @@ -45,6 +45,11 @@ The 0.11 porting guide 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: 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 diff --git a/gst/gstelement.c b/gst/gstelement.c index a52788d789..2e8028b24f 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -238,18 +238,29 @@ static void gst_element_base_class_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GList *node, *padtemplates; - /* FIXME 0.11: Instead of clearing the - * pad template list copy the list and increase the refcount of - * the pad templates by one. - * - * This will make it possible to add pad templates and set element - * details in the class_init functions and is the real GObject way - * of doing things. - * See http://bugzilla.gnome.org/show_bug.cgi?id=491501 + /* Copy the element details here so elements can inherit the + * details from their base class and classes only need to set + * the details in class_init instead of base_init */ + element_class->metadata = + element_class->metadata ? gst_structure_copy (element_class->metadata) : + gst_structure_empty_new ("metadata"); + + /* 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"); - element_class->padtemplates = NULL; + /* FIXME: Do we consider GstPadTemplates as immutable? If so we can + * 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() */ element_class->elementfactory = @@ -1270,30 +1281,37 @@ gst_element_iterate_sink_pads (GstElement * element) /** * gst_element_class_add_pad_template: * @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 gst_element_class_add_pad_template (GstElementClass * klass, GstPadTemplate * templ) { + GList *template_list = klass->padtemplates; + g_return_if_fail (GST_IS_ELEMENT_CLASS (klass)); g_return_if_fail (GST_IS_PAD_TEMPLATE (templ)); - /* FIXME 0.11: allow replacing the pad templates by - * calling this with the same name as an already existing pad - * template. For this we _must_ _not_ ref the added pad template - * a second time and _must_ document that this function takes - * 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); + /* If we already have a pad template with the same name replace the + * old one. */ + while (template_list) { + GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data; - klass->padtemplates = g_list_append (klass->padtemplates, - gst_object_ref (templ)); + /* Found pad with the same name, replace and return */ + 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++; } @@ -1330,7 +1348,7 @@ gst_element_class_add_metadata (GstElementClass * klass, * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>" * * Sets the detailed information for a #GstElementClass. - * This function is for use in _base_init functions only. + * This function is for use in _class_init functions only. */ void gst_element_class_set_metadata (GstElementClass * klass, diff --git a/gst/gstpadtemplate.c b/gst/gstpadtemplate.c index 20def770cd..06c4d55cda 100644 --- a/gst/gstpadtemplate.c +++ b/gst/gstpadtemplate.c @@ -78,13 +78,13 @@ * * * 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: * * * 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_static_pad_template_get (&my_template));