diff --git a/gst/gstbin.c b/gst/gstbin.c index 173b8bc1ae..6f5e469a3f 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -4630,3 +4630,56 @@ gst_bin_iterate_all_by_interface (GstBin * bin, GType iface) return result; } + +static gint +compare_factory_names (const GValue * velement, GValue * factory_name_val) +{ + GstElement *element = g_value_get_object (velement); + GstElementFactory *factory = gst_element_get_factory (element); + const gchar *factory_name = g_value_get_string (factory_name_val); + + if (factory == NULL) + return -1; + + return g_strcmp0 (GST_OBJECT_NAME (factory), factory_name); +} + +/** + * gst_bin_iterate_all_by_element_factory_name: + * @bin: a #GstBin + * @factory_name: (not nullable): the name of the #GstElementFactory + * + * Looks for all elements inside the bin with the given element factory name. + * The function recurses inside child bins. The iterator will yield a series of + * #GstElement that should be unreffed after use. + * + * MT safe. Caller owns returned value. + * + * Returns: (transfer full) (nullable): a #GstIterator of #GstElement + * for all elements in the bin with the given element factory name, + * or %NULL. + * + * Since: 1.18 + */ +GstIterator * +gst_bin_iterate_all_by_element_factory_name (GstBin * bin, + const gchar * factory_name) +{ + GstIterator *children; + GstIterator *result; + GValue factory_name_val = G_VALUE_INIT; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (factory_name && *factory_name, NULL); + + g_value_init (&factory_name_val, G_TYPE_STRING); + g_value_set_string (&factory_name_val, factory_name); + + children = gst_bin_iterate_recurse (bin); + result = gst_iterator_filter (children, (GCompareFunc) compare_factory_names, + &factory_name_val); + + g_value_unset (&factory_name_val); + + return result; +} diff --git a/gst/gstbin.h b/gst/gstbin.h index 906097e64e..8d2af2ef61 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -237,6 +237,9 @@ GstIterator* gst_bin_iterate_sources (GstBin *bin); GST_API GstIterator* gst_bin_iterate_all_by_interface (GstBin *bin, GType iface); +GST_API +GstIterator* gst_bin_iterate_all_by_element_factory_name (GstBin * bin, const gchar * factory_name); + /* latency */ GST_API diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index 21e6043afd..ed4e916301 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -153,6 +153,82 @@ GST_START_TEST (test_interface) GST_END_TEST; +GST_START_TEST (test_iterate_all_by_element_factory_name) +{ + GstBin *bin, *bin2; + GstElement *filesrc; + GstIterator *it; + GValue item = { 0, }; + + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL, "Could not create bin"); + + filesrc = gst_element_factory_make ("filesrc", NULL); + fail_unless (filesrc != NULL, "Could not create filesrc"); + gst_bin_add (bin, filesrc); + + /* Test bin with single element */ + it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc"); + fail_unless (it != NULL); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + /* Negative test bin with single element */ + it = gst_bin_iterate_all_by_element_factory_name (bin, "filesink"); + fail_unless (it != NULL); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + /* Test bin with multiple other elements, 1 layer */ + gst_bin_add_many (bin, + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), NULL); + it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc"); + fail_unless (it != NULL); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + /* Test bin with multiple other elements in subbins */ + bin2 = bin; + bin = GST_BIN (gst_bin_new (NULL)); + fail_unless (bin != NULL); + gst_bin_add_many (bin, + gst_element_factory_make ("identity", NULL), + gst_element_factory_make ("identity", NULL), + GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL); + it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc"); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + fail_unless (g_value_get_object (&item) == (gpointer) filesrc); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + gst_iterator_free (it); + + /* Test bin with multiple other elements, multiple occurrences in subbins */ + gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL)); + gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL)); + it = gst_bin_iterate_all_by_element_factory_name (bin, "filesrc"); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK); + g_value_reset (&item); + fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE); + g_value_unset (&item); + gst_iterator_free (it); + + gst_object_unref (bin); +} + +GST_END_TEST; + GST_START_TEST (test_eos) { GstBus *bus; @@ -1789,6 +1865,7 @@ gst_bin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_interface); + tcase_add_test (tc_chain, test_iterate_all_by_element_factory_name); tcase_add_test (tc_chain, test_eos); tcase_add_test (tc_chain, test_stream_start); tcase_add_test (tc_chain, test_children_state_change_order_flagged_sink);