mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-08 18:39:54 +00:00
gst/: Make it possible (and recommended) to set element details and add pad templates in the class_init functions by ...
Original commit message from CVS: * gst/gstelement.c: (gst_element_base_class_init), (gst_element_class_add_pad_template): * gst/gstpadtemplate.c: Make it possible (and recommended) to set element details and add pad templates in the class_init functions by copying the details/pad templates in GstElement's base_init. Also make it possible to replace existing pad templates by adding a new one with the same name. This was done in a hackish fashion in same elements before already. Don't reference pad templates that are added a second time. A new pad template has a refcount of one and is not floating anymore and to be owned by the element's class. Make this more explicit by mentioning it in the docs of gst_element_class_add_pad_template(). These changes are backwards compatible. Fixes bug #491501. * tests/check/gst/gstelement.c: Add unit test for setting element details, adding pad templates and replacing them in a subclass.
This commit is contained in:
parent
d7a94887b5
commit
86e45df860
5 changed files with 264 additions and 15 deletions
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
2008-02-03 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
* gst/gstelement.c: (gst_element_base_class_init),
|
||||
(gst_element_class_add_pad_template):
|
||||
* gst/gstpadtemplate.c:
|
||||
Make it possible (and recommended) to set element details and add
|
||||
pad templates in the class_init functions by copying the details/pad
|
||||
templates in GstElement's base_init.
|
||||
|
||||
Also make it possible to replace existing pad templates by adding
|
||||
a new one with the same name. This was done in a hackish fashion
|
||||
in same elements before already.
|
||||
|
||||
Don't reference pad templates that are added a second time. A
|
||||
new pad template has a refcount of one and is not floating anymore
|
||||
and to be owned by the element's class. Make this more explicit by
|
||||
mentioning it in the docs of gst_element_class_add_pad_template().
|
||||
|
||||
These changes are backwards compatible. Fixes bug #491501.
|
||||
|
||||
* tests/check/gst/gstelement.c:
|
||||
Add unit test for setting element details, adding pad templates and
|
||||
replacing them in a subclass.
|
||||
|
||||
2008-02-02 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
|
||||
* tools/gst-inspect.c: (print_interfaces),
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 571dce3335f9be76978009b3842c050dbb900e6f
|
||||
Subproject commit 3c5473161ce19a3530bad279b842d542895b1500
|
|
@ -238,9 +238,34 @@ static void
|
|||
gst_element_base_class_init (gpointer g_class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GList *node, *padtemplates;
|
||||
|
||||
memset (&element_class->details, 0, sizeof (GstElementDetails));
|
||||
element_class->padtemplates = NULL;
|
||||
/* 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 */
|
||||
/* FIXME: We probably need something like for copying
|
||||
* the details at a central place */
|
||||
element_class->details.longname = g_strdup (element_class->details.longname);
|
||||
element_class->details.klass = g_strdup (element_class->details.klass);
|
||||
element_class->details.description =
|
||||
g_strdup (element_class->details.description);
|
||||
element_class->details.author = g_strdup (element_class->details.author);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1102,22 +1127,38 @@ gst_element_iterate_sink_pads (GstElement * element)
|
|||
* @klass: the #GstElementClass to add the pad template to.
|
||||
* @templ: a #GstPadTemplate to add to the element class.
|
||||
*
|
||||
* Adds a padtemplate to an element class. This is mainly used in the _base_init
|
||||
* functions of classes.
|
||||
* 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.
|
||||
*
|
||||
* This function takes the ownership of the #GstPadTemplate.
|
||||
*/
|
||||
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));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Not found a pad with the same name so add it to the list */
|
||||
klass->padtemplates = g_list_append (klass->padtemplates, templ);
|
||||
klass->numpadtemplates++;
|
||||
}
|
||||
|
||||
|
@ -1127,7 +1168,7 @@ gst_element_class_add_pad_template (GstElementClass * klass,
|
|||
* @details: details to set
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
* The @details are copied.
|
||||
*/
|
||||
|
@ -1155,7 +1196,7 @@ gst_element_class_set_details (GstElementClass * klass,
|
|||
*
|
||||
* Sets the detailed information for a #GstElementClass. Simpler version of
|
||||
* gst_element_class_set_details() that generates less linker overhead.
|
||||
* <note>This function is for use in _base_init functions only.</note>
|
||||
* <note>This function is for use in _class_init functions only.</note>
|
||||
*
|
||||
* The detail parameter strings are copied into the #GstElementDetails for
|
||||
* the element class.
|
||||
|
|
|
@ -78,13 +78,13 @@
|
|||
* </example>
|
||||
*
|
||||
* 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>
|
||||
* <programlisting>
|
||||
* 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));
|
||||
|
|
|
@ -205,6 +205,189 @@ GST_START_TEST (test_class)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
typedef struct _GstTestElement
|
||||
{
|
||||
GstElement parent;
|
||||
|
||||
} GstTestElement;
|
||||
|
||||
typedef struct _GstTestElementClass
|
||||
{
|
||||
GstElementClass parent;
|
||||
|
||||
} GstTestElementClass;
|
||||
|
||||
static void
|
||||
gst_test_element_class_init (GstTestElementClass * klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "Test element",
|
||||
"Element", "Does nothing", "Foo Bar <foo@bar.com>");
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 0);
|
||||
|
||||
fail_unless (gst_element_class_get_pad_template (element_class,
|
||||
"test") == NULL);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 1);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test")) != NULL);
|
||||
fail_unless (gst_caps_is_any (templ->caps));
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("test2", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_CAPS_ANY));
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 2);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test2")) != NULL);
|
||||
fail_unless (gst_caps_is_any (templ->caps));
|
||||
|
||||
/* Add "test" again, with NONE caps this time */
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_CAPS_NONE));
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 2);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test")) != NULL);
|
||||
fail_unless (gst_caps_is_empty (templ->caps));
|
||||
}
|
||||
|
||||
GType
|
||||
gst_test_element_get_type (void)
|
||||
{
|
||||
static GType gst_test_element_type = G_TYPE_NONE;
|
||||
|
||||
if (gst_test_element_type == G_TYPE_NONE) {
|
||||
static const GTypeInfo gst_test_element_info = {
|
||||
sizeof (GstTestElementClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) gst_test_element_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstTestElement),
|
||||
0,
|
||||
NULL, /* instance_init */
|
||||
NULL
|
||||
};
|
||||
|
||||
gst_test_element_type = g_type_register_static (GST_TYPE_ELEMENT,
|
||||
"GstTestElement", &gst_test_element_info, 0);
|
||||
}
|
||||
return gst_test_element_type;
|
||||
}
|
||||
|
||||
typedef struct _GstTestElement2
|
||||
{
|
||||
GstTestElement parent;
|
||||
|
||||
} GstTestElement2;
|
||||
|
||||
typedef struct _GstTestElement2Class
|
||||
{
|
||||
GstTestElementClass parent;
|
||||
|
||||
} GstTestElement2Class;
|
||||
|
||||
static void
|
||||
gst_test_element2_class_init (GstTestElement2Class * klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
GstPadTemplate *templ;
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "Test element 2",
|
||||
"Element", "Does nothing", "Foo Bar <foo@bar.com>");
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 2);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test")) != NULL);
|
||||
fail_unless (gst_caps_is_empty (templ->caps));
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test2")) != NULL);
|
||||
fail_unless (gst_caps_is_any (templ->caps));
|
||||
|
||||
/* Add "test" pad with ANY caps, should have "test" pad with EMPTY caps before */
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 2);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test")) != NULL);
|
||||
fail_unless (gst_caps_is_any (templ->caps));
|
||||
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("test4", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_CAPS_ANY));
|
||||
|
||||
fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
|
||||
(element_class)), 3);
|
||||
|
||||
fail_unless ((templ =
|
||||
gst_element_class_get_pad_template (element_class, "test4")) != NULL);
|
||||
fail_unless (gst_caps_is_any (templ->caps));
|
||||
}
|
||||
|
||||
GType
|
||||
gst_test_element2_get_type (void)
|
||||
{
|
||||
static GType gst_test_element2_type = G_TYPE_NONE;
|
||||
|
||||
if (gst_test_element2_type == G_TYPE_NONE) {
|
||||
static const GTypeInfo gst_test_element2_info = {
|
||||
sizeof (GstTestElement2Class),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) gst_test_element2_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstTestElement2),
|
||||
0,
|
||||
NULL, /* instance_init */
|
||||
NULL
|
||||
};
|
||||
|
||||
gst_test_element2_type =
|
||||
g_type_register_static (gst_test_element_get_type (), "GstTestElement2",
|
||||
&gst_test_element2_info, 0);
|
||||
}
|
||||
return gst_test_element2_type;
|
||||
}
|
||||
|
||||
|
||||
GST_START_TEST (test_pad_templates)
|
||||
{
|
||||
GstTestElement *test;
|
||||
GstTestElement2 *test2;
|
||||
|
||||
test = g_object_new (gst_test_element_get_type (), NULL);
|
||||
test2 = g_object_new (gst_test_element2_get_type (), NULL);
|
||||
|
||||
g_object_unref (test);
|
||||
g_object_unref (test2);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
Suite *
|
||||
gst_element_suite (void)
|
||||
{
|
||||
|
@ -218,6 +401,7 @@ gst_element_suite (void)
|
|||
tcase_add_test (tc_chain, test_link);
|
||||
tcase_add_test (tc_chain, test_link_no_pads);
|
||||
tcase_add_test (tc_chain, test_class);
|
||||
tcase_add_test (tc_chain, test_pad_templates);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue