mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-16 19:25:18 +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>
|
2008-02-02 Sebastian Dröge <slomo@circular-chaos.org>
|
||||||
|
|
||||||
* tools/gst-inspect.c: (print_interfaces),
|
* 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)
|
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;
|
||||||
|
|
||||||
memset (&element_class->details, 0, sizeof (GstElementDetails));
|
/* Copy the element details here so elements can inherit the
|
||||||
element_class->padtemplates = NULL;
|
* 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
|
static void
|
||||||
|
@ -1102,22 +1127,38 @@ gst_element_iterate_sink_pads (GstElement * element)
|
||||||
* @klass: the #GstElementClass to add the pad template to.
|
* @klass: the #GstElementClass to add the pad template to.
|
||||||
* @templ: a #GstPadTemplate to add to the element class.
|
* @templ: a #GstPadTemplate to add to the element class.
|
||||||
*
|
*
|
||||||
* Adds a padtemplate to an element class. This is mainly used in the _base_init
|
* Adds a padtemplate to an element class. This is mainly used in the
|
||||||
* functions of classes.
|
* _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
|
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));
|
||||||
|
|
||||||
/* avoid registering pad templates with the same name */
|
/* If we already have a pad template with the same name replace the
|
||||||
g_return_if_fail (gst_element_class_get_pad_template (klass,
|
* old one. */
|
||||||
templ->name_template) == NULL);
|
while (template_list) {
|
||||||
|
GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data;
|
||||||
|
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found a pad with the same name so add it to the list */
|
||||||
|
klass->padtemplates = g_list_append (klass->padtemplates, templ);
|
||||||
klass->numpadtemplates++;
|
klass->numpadtemplates++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1168,7 @@ gst_element_class_add_pad_template (GstElementClass * klass,
|
||||||
* @details: details to set
|
* @details: details to set
|
||||||
*
|
*
|
||||||
* 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>
|
||||||
*
|
*
|
||||||
* The @details are copied.
|
* 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
|
* Sets the detailed information for a #GstElementClass. Simpler version of
|
||||||
* gst_element_class_set_details() that generates less linker overhead.
|
* 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 detail parameter strings are copied into the #GstElementDetails for
|
||||||
* the element class.
|
* the element class.
|
||||||
|
|
|
@ -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 (&my_template));
|
* gst_static_pad_template_get (&my_template));
|
||||||
|
|
|
@ -205,6 +205,189 @@ GST_START_TEST (test_class)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
Suite *
|
||||||
gst_element_suite (void)
|
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);
|
||||||
tcase_add_test (tc_chain, test_link_no_pads);
|
tcase_add_test (tc_chain, test_link_no_pads);
|
||||||
tcase_add_test (tc_chain, test_class);
|
tcase_add_test (tc_chain, test_class);
|
||||||
|
tcase_add_test (tc_chain, test_pad_templates);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue