diff --git a/ChangeLog b/ChangeLog index 4bc811f4a1..a1cf9e3ee3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-02-02 Tim-Philipp Müller + + * docs/gst/gstreamer-sections.txt: + * gst/gstutils.c: (element_find_unconnected_pad), + (gst_bin_find_unconnected_pad), (gst_parse_bin_from_description): + * gst/gstutils.h: + Add new API: gst_parse_bin_from_description() and + gst_bin_find_unconnected_pad() (#329069). + 2006-02-01 Stefan Kost * docs/manual/README: diff --git a/common b/common index 0b93085188..1140eabed8 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 0b93085188e83fe678ec5ded2823cd7c24dfa843 +Subproject commit 1140eabed84dd1d8d6df7df88f5c8bdf20a8faa1 diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index cb7890bc5e..b423205cac 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -52,6 +52,7 @@ gst_bin_iterate_all_by_interface gst_bin_add_many gst_bin_remove_many +gst_bin_find_unconnected_pad GstBinFlags @@ -1383,6 +1384,7 @@ GST_PARSE_ERROR GstParseError gst_parse_launch gst_parse_launchv +gst_parse_bin_from_description GST_TYPE_PARSE_ERROR diff --git a/gst/gstutils.c b/gst/gstutils.c index 8191d9f58f..b6cc533697 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -1,6 +1,7 @@ /* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans + * 2002 Thomas Vander Stichele * * gstutils.c: Utility functions: gtk_get_property stuff, etc. * @@ -34,6 +35,7 @@ #include "gstghostpad.h" #include "gstutils.h" #include "gstinfo.h" +#include "gstparse.h" #include "gst-i18n-lib.h" @@ -2850,3 +2852,177 @@ gst_element_found_tags (GstElement * element, GstTagList * list) gst_element_post_message (element, gst_message_new_tag (GST_OBJECT (element), list)); } + +static GstPad * +element_find_unconnected_pad (GstElement * element, GstPadDirection direction) +{ + GstIterator *iter; + GstPad *unconnected_pad = NULL; + gboolean done; + + switch (direction) { + case GST_PAD_SRC: + iter = gst_element_iterate_src_pads (element); + break; + case GST_PAD_SINK: + iter = gst_element_iterate_sink_pads (element); + break; + default: + g_assert_not_reached (); + } + + done = FALSE; + while (!done) { + gpointer pad; + + switch (gst_iterator_next (iter, &pad)) { + case GST_ITERATOR_OK:{ + GstPad *peer; + + GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + peer = gst_pad_get_peer (GST_PAD (pad)); + if (peer == NULL) { + unconnected_pad = pad; + done = TRUE; + GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, + "found existing unlinked pad %s:%s", + GST_DEBUG_PAD_NAME (unconnected_pad)); + } else { + gst_object_unref (pad); + gst_object_unref (peer); + } + break; + } + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + g_return_val_if_reached (NULL); + break; + } + } + + gst_iterator_free (iter); + + return unconnected_pad; +} + +/** + * gst_bin_find_unconnected_pad: + * @bin: bin in which to look for elements with unconnected pads + * @direction: whether to look for an unconnected source or sink pad + * + * Recursively looks for elements with an unconnected pad of the given + * direction within the specified bin and returns an unconnected pad + * if one is found, or NULL otherwise. If a pad is found, the caller + * owns a reference to it and should use gst_object_unref() on the + * pad when it is not needed any longer. + * + * Returns: unconnected pad of the given direction, or NULL. + * + * Since: 0.10.3 + */ +GstPad * +gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction) +{ + GstIterator *iter; + gboolean done; + GstPad *pad = NULL; + + g_return_val_if_fail (GST_IS_BIN (bin), NULL); + g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL); + + done = FALSE; + iter = gst_bin_iterate_recurse (bin); + while (!done) { + gpointer element; + + switch (gst_iterator_next (iter, &element)) { + case GST_ITERATOR_OK: + pad = element_find_unconnected_pad (GST_ELEMENT (element), direction); + gst_object_unref (element); + if (pad != NULL) + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + g_return_val_if_reached (NULL); + break; + } + } + + gst_iterator_free (iter); + + return pad; +} + +/** + * gst_parse_bin_from_description: + * @bin_description: command line describing the bin + * @ghost_unconnected_pads: whether to automatically create ghost pads + * for unconnected source or sink pads within + * the bin + * @err: where to store the error message in case of an error, or NULL + * + * This is a convenience wrapper around gst_parse_launch() to create a + * #GstBin from a gst-launch-style pipeline description. See + * gst_parse_launch() and the gst-launch man page for details about the + * syntax. Ghost pads on the bin for unconnected source or sink pads + * within the bin can automatically be created (but only a maximum of + * one ghost pad for each direction will be created; if you expect + * multiple unconnected source pads or multiple unconnected sink pads + * and want them all ghosted, you will have to create the ghost pads + * yourself). + * + * Returns: a newly-created bin, or NULL if an error occurred. + * + * Since: 0.10.3 + */ +GstElement * +gst_parse_bin_from_description (const gchar * bin_description, + gboolean ghost_unconnected_pads, GError ** err) +{ + GstPad *pad = NULL; + GstBin *bin; + gchar *desc; + + g_return_val_if_fail (bin_description != NULL, NULL); + g_return_val_if_fail (err == NULL || *err == NULL, NULL); + + GST_DEBUG ("Making bin from description '%s'", bin_description); + + /* parse the pipeline to a bin */ + desc = g_strdup_printf ("bin.( %s )", bin_description); + bin = (GstBin *) gst_parse_launch (desc, err); + g_free (desc); + + if (bin == NULL || (err && *err != NULL)) { + if (bin) + gst_object_unref (bin); + return NULL; + } + + /* find pads and ghost them if necessary */ + if (ghost_unconnected_pads) { + if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad)); + gst_object_unref (pad); + } + if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) { + gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + } + } + + return GST_ELEMENT (bin); +} diff --git a/gst/gstutils.h b/gst/gstutils.h index 273295cd8b..f170d87806 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -1,6 +1,7 @@ /* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans + * 2002 Thomas Vander Stichele * * gstutils.h: Header for various utility functions * @@ -565,8 +566,9 @@ gboolean gst_pad_query_convert (GstPad *pad, GstFormat GstFormat *dest_format, gint64 *dest_val); /* bin functions */ -void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; -void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; +void gst_bin_add_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; +void gst_bin_remove_many (GstBin *bin, GstElement *element_1, ...) G_GNUC_NULL_TERMINATED; +GstPad * gst_bin_find_unconnected_pad (GstBin *bin, GstPadDirection direction); /* buffer functions */ GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2); @@ -597,6 +599,11 @@ void gst_element_found_tags_for_pad (GstElement * element, void gst_element_found_tags (GstElement * element, GstTagList * list); +/* parse utility functions */ +GstElement * gst_parse_bin_from_description (const gchar * bin_description, + gboolean ghost_unconnected_pads, + GError ** err); + G_END_DECLS #endif /* __GST_UTILS_H__ */