3 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
4 * 2004 Wim Taymans <wim@fluendo.com>
6 * gstbin.c: GstBin container object and support code
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 * @short_description: Base class and element that can contain other elements
30 * #GstBin is an element that can contain other #GstElement, allowing them to be
32 * Pads from the child elements can be ghosted to the bin, see #GstGhostPad.
33 * This makes the bin look like any other elements and enables creation of
34 * higher-level abstraction elements.
36 * A new #GstBin is created with gst_bin_new(). Use a #GstPipeline instead if you
37 * want to create a toplevel bin because a normal bin doesn't have a bus or
38 * handle clock distribution of its own.
40 * After the bin has been created you will typically add elements to it with
41 * gst_bin_add(). You can remove elements with gst_bin_remove().
43 * An element can be retrieved from a bin with gst_bin_get_by_name(), using the
44 * elements name. gst_bin_get_by_name_recurse_up() is mainly used for internal
45 * purposes and will query the parent bins when the element is not found in the
48 * An iterator of elements in a bin can be retrieved with
49 * gst_bin_iterate_elements(). Various other iterators exist to retrieve the
52 * gst_object_unref() is used to drop your reference to the bin.
54 * The <link linkend="GstBin-element-added">element-added</link> signal is
55 * fired whenever a new element is added to the bin. Likewise the <link
56 * linkend="GstBin-element-removed">element-removed</link> signal is fired
57 * whenever an element is removed from the bin.
59 * <refsect2><title>Notes</title>
61 * A #GstBin internally intercepts every #GstMessage posted by its children and
62 * implements the following default behaviour for each of them:
65 * <term>GST_MESSAGE_EOS</term>
66 * <listitem><para>This message is only posted by sinks in the PLAYING
67 * state. If all sinks posted the EOS message, this bin will post and EOS
68 * message upwards.</para></listitem>
71 * <term>GST_MESSAGE_SEGMENT_START</term>
72 * <listitem><para>just collected and never forwarded upwards.
73 * The messages are used to decide when all elements have completed playback
74 * of their segment.</para></listitem>
77 * <term>GST_MESSAGE_SEGMENT_DONE</term>
78 * <listitem><para> Is posted by #GstBin when all elements that posted
79 * a SEGMENT_START have posted a SEGMENT_DONE.</para></listitem>
82 * <term>GST_MESSAGE_DURATION</term>
83 * <listitem><para> Is posted by an element that detected a change
84 * in the stream duration. The default bin behaviour is to clear any
85 * cached duration values so that the next duration query will perform
86 * a full duration recalculation. The duration change is posted to the
87 * application so that it can refetch the new duration with a duration
92 * <term>GST_MESSAGE_CLOCK_LOST</term>
93 * <listitem><para> This message is posted by an element when it
94 * can no longer provide a clock. The default bin behaviour is to
95 * check if the lost clock was the one provided by the bin. If so and
96 * the bin is currently in the PLAYING state, the message is forwarded to
98 * This message is also generated when a clock provider is removed from
99 * the bin. If this message is received by the application, it should
100 * PAUSE the pipeline and set it back to PLAYING to force a new clock
105 * <term>GST_MESSAGE_CLOCK_PROVIDE</term>
106 * <listitem><para> This message is generated when an element
107 * can provide a clock. This mostly happens when a new clock
108 * provider is added to the bin. The default behaviour of the bin is to
109 * mark the currently selected clock as dirty, which will perform a clock
110 * recalculation the next time the bin is asked to provide a clock.
111 * This message is never sent tot the application but is forwarded to
112 * the parent of the bin.
116 * <term>OTHERS</term>
117 * <listitem><para> posted upwards.</para></listitem>
122 * A #GstBin implements the following default behaviour for answering to a
126 * <term>GST_QUERY_DURATION</term>
127 * <listitem><para>If the query has been asked before with the same format
128 * and the bin is a toplevel bin (ie. has no parent),
129 * use the cached previous value. If no previous value was cached, the
130 * query is sent to all sink elements in the bin and the MAXIMUM of all
131 * values is returned. If the bin is a toplevel bin the value is cached.
132 * If no sinks are available in the bin, the query fails.
136 * <term>GST_QUERY_POSITION</term>
137 * <listitem><para>The query is sent to all sink elements in the bin and the
138 * MAXIMUM of all values is returned. If no sinks are available in the bin,
143 * <term>OTHERS</term>
144 * <listitem><para>the query is forwarded to all sink elements, the result
145 * of the first sink that answers the query successfully is returned. If no
146 * sink is in the bin, the query fails.</para></listitem>
150 * A #GstBin will by default forward any event sent to it to all sink elements.
151 * If all the sinks return TRUE, the bin will also return TRUE, else FALSE is
152 * returned. If no sinks are in the bin, the event handler will return TRUE.
157 * Last reviewed on 2006-04-28 (0.10.6)
160 #include "gst_private.h"
162 #include "gstevent.h"
164 #include "gstmarshal.h"
167 #include "gsterror.h"
169 #include "gstindex.h"
170 #include "gstindexfactory.h"
171 #include "gstutils.h"
172 #include "gstchildproxy.h"
174 /* enable for DURATION caching.
175 * FIXME currently too many elements don't update
176 * their duration when it changes so we return inaccurate values. */
177 #undef DURATION_CACHING
179 GST_DEBUG_CATEGORY_STATIC (bin_debug);
180 #define GST_CAT_DEFAULT bin_debug
182 static const GstElementDetails gst_bin_details =
183 GST_ELEMENT_DETAILS ("Generic bin",
185 "Simple container object",
186 "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
188 static void gst_bin_dispose (GObject * object);
190 static void gst_bin_recalc_state (GstBin * bin, gboolean force);
191 static GstStateChangeReturn gst_bin_change_state_func (GstElement * element,
192 GstStateChange transition);
193 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
194 GstState * state, GstState * pending, GstClockTime timeout);
196 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
197 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
199 #ifndef GST_DISABLE_INDEX
200 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
202 static GstClock *gst_bin_provide_clock_func (GstElement * element);
203 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
205 static void gst_bin_handle_message_func (GstBin * bin, GstMessage * message);
206 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
207 static GstBusSyncReply bin_bus_handler (GstBus * bus,
208 GstMessage * message, GstBin * bin);
209 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
211 #ifndef GST_DISABLE_LOADSAVE
212 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
213 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
216 static void bin_remove_messages (GstBin * bin, GstObject * src,
217 GstMessageType types);
218 static void gst_bin_recalc_func (GstBin * child, gpointer data);
219 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
220 static gint bin_element_is_src (GstElement * child, GstBin * bin);
222 static GstIterator *gst_bin_sort_iterator_new (GstBin * bin);
224 /* Bin signals and properties */
238 static void gst_bin_base_init (gpointer g_class);
239 static void gst_bin_class_init (GstBinClass * klass);
240 static void gst_bin_init (GstBin * bin);
241 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
243 static GstElementClass *parent_class = NULL;
244 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
249 * Returns: the type of #GstBin
252 gst_bin_get_type (void)
254 static GType gst_bin_type = 0;
256 if (G_UNLIKELY (gst_bin_type == 0)) {
257 static const GTypeInfo bin_info = {
258 sizeof (GstBinClass),
261 (GClassInitFunc) gst_bin_class_init,
266 (GInstanceInitFunc) gst_bin_init,
269 static const GInterfaceInfo child_proxy_info = {
270 gst_bin_child_proxy_init,
276 g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
278 g_type_add_interface_static (gst_bin_type, GST_TYPE_CHILD_PROXY,
281 GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
282 "debugging info for the 'bin' container element");
288 gst_bin_base_init (gpointer g_class)
290 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
292 gst_element_class_set_details (gstelement_class, &gst_bin_details);
296 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
302 bin = GST_BIN_CAST (child_proxy);
304 GST_OBJECT_LOCK (bin);
305 if ((res = g_list_nth_data (bin->children, index)))
306 gst_object_ref (res);
307 GST_OBJECT_UNLOCK (bin);
313 gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
318 bin = GST_BIN_CAST (child_proxy);
320 GST_OBJECT_LOCK (bin);
321 num = bin->numchildren;
322 GST_OBJECT_UNLOCK (bin);
328 gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
330 GstChildProxyInterface *iface = g_iface;
332 iface->get_children_count = gst_bin_child_proxy_get_children_count;
333 iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
337 gst_bin_class_init (GstBinClass * klass)
339 GObjectClass *gobject_class;
340 GstObjectClass *gstobject_class;
341 GstElementClass *gstelement_class;
344 gobject_class = (GObjectClass *) klass;
345 gstobject_class = (GstObjectClass *) klass;
346 gstelement_class = (GstElementClass *) klass;
348 parent_class = g_type_class_peek_parent (klass);
351 * GstBin::element-added:
353 * @element: the #GstElement that was added to the bin
355 * Will be emitted after the element was added to the bin.
357 gst_bin_signals[ELEMENT_ADDED] =
358 g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
359 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
360 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
362 * GstBin::element-removed:
364 * @element: the #GstElement that was removed from the bin
366 * Will be emitted after the element was removed from the bin.
368 gst_bin_signals[ELEMENT_REMOVED] =
369 g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
370 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
371 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
373 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
375 #ifndef GST_DISABLE_LOADSAVE
376 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
377 gstobject_class->restore_thyself =
378 GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
381 gstelement_class->change_state =
382 GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
383 gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
384 #ifndef GST_DISABLE_INDEX
385 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
387 gstelement_class->provide_clock =
388 GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
389 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
391 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
392 gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
394 klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
395 klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
396 klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func);
398 GST_DEBUG ("creating bin thread pool");
401 g_thread_pool_new ((GFunc) gst_bin_recalc_func, NULL, -1, FALSE, &err);
403 g_critical ("could alloc threadpool %s", err->message);
408 gst_bin_init (GstBin * bin)
412 bin->numchildren = 0;
413 bin->children = NULL;
414 bin->children_cookie = 0;
415 bin->messages = NULL;
416 bin->polling = FALSE;
417 bin->state_dirty = FALSE;
418 bin->provided_clock = NULL;
419 bin->clock_dirty = FALSE;
421 /* Set up a bus for listening to child elements */
422 bus = gst_bus_new ();
423 bin->child_bus = bus;
424 GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
426 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
430 gst_bin_dispose (GObject * object)
432 GstBin *bin = GST_BIN (object);
433 GstBus **child_bus_p = &bin->child_bus;
434 GstClock **provided_clock_p = &bin->provided_clock;
435 GstElement **clock_provider_p = &bin->clock_provider;
437 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
439 bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
441 gst_object_replace ((GstObject **) child_bus_p, NULL);
442 gst_object_replace ((GstObject **) provided_clock_p, NULL);
443 gst_object_replace ((GstObject **) clock_provider_p, NULL);
445 while (bin->children) {
446 gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
448 if (G_UNLIKELY (bin->children != NULL)) {
449 g_critical ("could not remove elements from bin %s",
450 GST_STR_NULL (GST_OBJECT_NAME (object)));
453 G_OBJECT_CLASS (parent_class)->dispose (object);
458 * @name: the name of the new bin
460 * Creates a new bin with the given name.
462 * Returns: a new #GstBin
465 gst_bin_new (const gchar * name)
467 return gst_element_factory_make ("bin", name);
470 /* set the index on all elements in this bin
474 #ifndef GST_DISABLE_INDEX
476 gst_bin_set_index_func (GstElement * element, GstIndex * index)
481 bin = GST_BIN (element);
483 GST_OBJECT_LOCK (bin);
484 for (children = bin->children; children; children = g_list_next (children)) {
485 GstElement *child = GST_ELEMENT (children->data);
487 gst_element_set_index (child, index);
489 GST_OBJECT_UNLOCK (bin);
493 /* set the clock on all elements in this bin
498 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
504 bin = GST_BIN (element);
506 GST_OBJECT_LOCK (bin);
507 if (element->clock != clock) {
508 for (children = bin->children; children; children = g_list_next (children)) {
509 GstElement *child = GST_ELEMENT (children->data);
511 res &= gst_element_set_clock (child, clock);
514 GST_OBJECT_UNLOCK (bin);
519 /* get the clock for this bin by asking all of the children in this bin
521 * The ref of the returned clock in increased so unref after usage.
523 * We loop the elements in state order and pick the last clock we can
524 * get. This makes sure we get a clock from the source.
529 gst_bin_provide_clock_func (GstElement * element)
531 GstClock *result = NULL;
532 GstElement *provider = NULL;
536 GstClock **provided_clock_p;
537 GstElement **clock_provider_p;
539 bin = GST_BIN (element);
541 GST_OBJECT_LOCK (bin);
542 if (!bin->clock_dirty)
545 GST_DEBUG_OBJECT (bin, "finding new clock");
547 it = gst_bin_sort_iterator_new (bin);
549 while (it->next (it, &val) == GST_ITERATOR_OK) {
550 GstElement *child = GST_ELEMENT_CAST (val);
553 clock = gst_element_provide_clock (child);
555 GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s",
556 clock, GST_ELEMENT_NAME (child));
558 gst_object_unref (result);
559 gst_object_unref (provider);
564 gst_object_unref (child);
568 provided_clock_p = &bin->provided_clock;
569 clock_provider_p = &bin->clock_provider;
570 gst_object_replace ((GstObject **) provided_clock_p, (GstObject *) result);
571 gst_object_replace ((GstObject **) clock_provider_p, (GstObject *) provider);
572 bin->clock_dirty = FALSE;
573 GST_DEBUG_OBJECT (bin,
574 "provided new clock %" GST_PTR_FORMAT " by provider %" GST_PTR_FORMAT,
576 /* Provider is not being returned to caller, just the result */
578 gst_object_unref (provider);
579 GST_OBJECT_UNLOCK (bin);
581 gst_iterator_free (it);
587 if ((result = bin->provided_clock))
588 gst_object_ref (result);
589 GST_DEBUG_OBJECT (bin, "returning old clock %p", result);
590 GST_OBJECT_UNLOCK (bin);
597 * functions for manipulating cached messages
602 GstMessageType types;
605 /* check if a message is of given src and type */
607 message_check (GstMessage * message, MessageFind * target)
612 eq &= GST_MESSAGE_SRC (message) == target->src;
614 eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
619 /* with LOCK, returns TRUE if message had a valid SRC, takes ref on
622 * A message that is cached and has the same SRC and type is replaced
623 * by the given message.
626 bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
633 name = GST_MESSAGE_TYPE_NAME (message);
635 if ((src = GST_MESSAGE_SRC (message))) {
641 /* first find the previous message posted by this element */
642 previous = g_list_find_custom (bin->messages, &find,
643 (GCompareFunc) message_check);
645 /* if we found a previous message, replace it */
646 gst_message_unref (previous->data);
647 previous->data = message;
649 GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
650 name, GST_ELEMENT_NAME (src));
652 /* keep new message */
653 bin->messages = g_list_prepend (bin->messages, message);
655 GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s",
656 message, name, GST_ELEMENT_NAME (src));
659 GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing", name);
661 gst_message_unref (message);
666 /* with LOCK. Remove all messages of given types */
668 bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types)
676 for (walk = bin->messages; walk; walk = next) {
677 GstMessage *message = (GstMessage *) walk->data;
679 next = g_list_next (walk);
681 if (message_check (message, &find) == 0) {
682 GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
683 "deleting message of types %d", types);
684 bin->messages = g_list_delete_link (bin->messages, walk);
685 gst_message_unref (message);
687 GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
688 "not deleting message of type %d", GST_MESSAGE_TYPE (message));
694 /* Check if the bin is EOS. We do this by scanning all sinks and
695 * checking if they posted an EOS message.
697 * call with bin LOCK */
699 is_eos (GstBin * bin)
705 for (walk = bin->children; walk; walk = g_list_next (walk)) {
708 element = GST_ELEMENT_CAST (walk->data);
709 if (bin_element_is_sink (element, bin) == 0) {
712 /* check if element posted EOS */
713 find.src = GST_OBJECT_CAST (element);
714 find.types = GST_MESSAGE_EOS;
716 if (g_list_find_custom (bin->messages, &find,
717 (GCompareFunc) message_check)) {
718 GST_DEBUG ("element posted EOS");
720 GST_DEBUG ("element did not post EOS yet");
730 unlink_pads (GstPad * pad)
734 if ((peer = gst_pad_get_peer (pad))) {
735 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
736 gst_pad_unlink (pad, peer);
738 gst_pad_unlink (peer, pad);
739 gst_object_unref (peer);
741 gst_object_unref (pad);
744 /* vmethod that adds an element to a bin
749 gst_bin_add_func (GstBin * bin, GstElement * element)
754 GstMessage *clock_message = NULL;
756 /* we obviously can't add ourself to ourself */
757 if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
760 /* get the element name to make sure it is unique in this bin. */
761 GST_OBJECT_LOCK (element);
762 elem_name = g_strdup (GST_ELEMENT_NAME (element));
763 is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
764 GST_OBJECT_UNLOCK (element);
766 GST_OBJECT_LOCK (bin);
768 /* then check to see if the element's name is already taken in the bin,
769 * we can safely take the lock here. This check is probably bogus because
770 * you can safely change the element name after this check and before setting
771 * the object parent. The window is very small though... */
772 if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name)))
775 /* set the element's parent and add the element to the bin's list of children */
776 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
777 GST_OBJECT_CAST (bin))))
780 /* if we add a sink we become a sink */
782 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink",
784 GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
786 if (gst_element_provides_clock (element)) {
787 GST_DEBUG_OBJECT (bin, "element \"%s\" can provide a clock", elem_name);
788 bin->clock_dirty = TRUE;
790 gst_message_new_clock_provide (GST_OBJECT_CAST (bin), NULL, TRUE);
793 bin->children = g_list_prepend (bin->children, element);
795 bin->children_cookie++;
797 /* distribute the bus */
798 gst_element_set_bus (element, bin->child_bus);
800 /* propagate the current base_time and clock */
801 gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
802 /* it's possible that the element did not accept the clock but
803 * that is not important right now. When the pipeline goes to PLAYING,
804 * a new clock will be selected */
805 gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
806 bin->state_dirty = TRUE;
807 GST_OBJECT_UNLOCK (bin);
810 gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
813 /* unlink all linked pads */
814 it = gst_element_iterate_pads (element);
815 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
816 gst_iterator_free (it);
818 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
822 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
826 /* ERROR handling here */
829 GST_OBJECT_LOCK (bin);
830 g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
831 GST_OBJECT_UNLOCK (bin);
836 g_warning ("Name %s is not unique in bin %s, not adding",
837 elem_name, GST_ELEMENT_NAME (bin));
838 GST_OBJECT_UNLOCK (bin);
844 g_warning ("Element %s already has parent", elem_name);
845 GST_OBJECT_UNLOCK (bin);
855 * @element: the #GstElement to add
857 * Adds the given element to the bin. Sets the element's parent, and thus
858 * takes ownership of the element. An element can only be added to one bin.
860 * If the element's pads are linked to other pads, the pads will be unlinked
861 * before the element is added to the bin.
865 * Returns: TRUE if the element could be added, FALSE if
866 * the bin does not want to accept the element.
869 gst_bin_add (GstBin * bin, GstElement * element)
874 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
875 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
877 bclass = GST_BIN_GET_CLASS (bin);
879 if (G_UNLIKELY (bclass->add_element == NULL))
882 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
883 GST_STR_NULL (GST_ELEMENT_NAME (element)),
884 GST_STR_NULL (GST_ELEMENT_NAME (bin)));
886 result = bclass->add_element (bin, element);
893 g_warning ("adding elements to bin %s is not supported",
894 GST_ELEMENT_NAME (bin));
899 /* remove an element from the bin
904 gst_bin_remove_func (GstBin * bin, GstElement * element)
909 GstMessage *clock_message = NULL;
911 GST_OBJECT_LOCK (element);
912 /* Check if the element is already being removed and immediately
914 if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_UNPARENTING)))
915 goto already_removing;
917 GST_OBJECT_FLAG_SET (element, GST_ELEMENT_UNPARENTING);
918 /* grab element name so we can print it */
919 elem_name = g_strdup (GST_ELEMENT_NAME (element));
920 is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
921 GST_OBJECT_UNLOCK (element);
923 /* unlink all linked pads */
924 it = gst_element_iterate_pads (element);
925 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
926 gst_iterator_free (it);
928 GST_OBJECT_LOCK (bin);
929 /* the element must be in the bin's list of children */
930 if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
933 /* now remove the element from the list of elements */
934 bin->children = g_list_remove (bin->children, element);
936 bin->children_cookie++;
938 /* check if we removed a sink */
942 /* check if we removed the last sink */
943 other_sink = g_list_find_custom (bin->children,
944 bin, (GCompareFunc) bin_element_is_sink);
946 /* yups, we're not a sink anymore */
947 GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
951 /* if the clock provider for this element is removed, we lost
952 * the clock as well, we need to inform the parent of this
953 * so that it can select a new clock */
954 if (bin->clock_provider == element) {
955 GST_DEBUG_OBJECT (bin, "element \"%s\" provided the clock", elem_name);
956 bin->clock_dirty = TRUE;
958 gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
961 bin->state_dirty = TRUE;
962 GST_OBJECT_UNLOCK (bin);
965 gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
968 GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
972 gst_element_set_bus (element, NULL);
974 /* Clear the clock we provided to the element */
975 gst_element_set_clock (element, NULL);
977 /* we ref here because after the _unparent() the element can be disposed
978 * and we still need it to reset the UNPARENTING flag and fire a signal. */
979 gst_object_ref (element);
980 gst_object_unparent (GST_OBJECT_CAST (element));
982 GST_OBJECT_LOCK (element);
983 GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_UNPARENTING);
984 GST_OBJECT_UNLOCK (element);
986 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
988 /* element is really out of our control now */
989 gst_object_unref (element);
996 g_warning ("Element %s is not in bin %s", elem_name,
997 GST_ELEMENT_NAME (bin));
998 GST_OBJECT_UNLOCK (bin);
1004 GST_OBJECT_UNLOCK (element);
1012 * @element: the #GstElement to remove
1014 * Removes the element from the bin, unparenting it as well.
1015 * Unparenting the element means that the element will be dereferenced,
1016 * so if the bin holds the only reference to the element, the element
1017 * will be freed in the process of removing it from the bin. If you
1018 * want the element to still exist after removing, you need to call
1019 * gst_object_ref() before removing it from the bin.
1021 * If the element's pads are linked to other pads, the pads will be unlinked
1022 * before the element is removed from the bin.
1026 * Returns: TRUE if the element could be removed, FALSE if
1027 * the bin does not want to remove the element.
1030 gst_bin_remove (GstBin * bin, GstElement * element)
1032 GstBinClass *bclass;
1035 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
1036 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1038 bclass = GST_BIN_GET_CLASS (bin);
1040 if (G_UNLIKELY (bclass->remove_element == NULL))
1043 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
1044 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
1046 result = bclass->remove_element (bin, element);
1050 /* ERROR handling */
1053 g_warning ("removing elements from bin %s is not supported",
1054 GST_ELEMENT_NAME (bin));
1059 static GstIteratorItem
1060 iterate_child (GstIterator * it, GstElement * child)
1062 gst_object_ref (child);
1063 return GST_ITERATOR_ITEM_PASS;
1067 * gst_bin_iterate_elements:
1070 * Gets an iterator for the elements in this bin.
1072 * Each element yielded by the iterator will have its refcount increased, so
1075 * MT safe. Caller owns returned value.
1077 * Returns: a #GstIterator of #GstElement, or NULL
1080 gst_bin_iterate_elements (GstBin * bin)
1082 GstIterator *result;
1084 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1086 GST_OBJECT_LOCK (bin);
1087 /* add ref because the iterator refs the bin. When the iterator
1088 * is freed it will unref the bin again using the provided dispose
1090 gst_object_ref (bin);
1091 result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1092 GST_OBJECT_GET_LOCK (bin),
1093 &bin->children_cookie,
1096 (GstIteratorItemFunction) iterate_child,
1097 (GstIteratorDisposeFunction) gst_object_unref);
1098 GST_OBJECT_UNLOCK (bin);
1103 static GstIteratorItem
1104 iterate_child_recurse (GstIterator * it, GstElement * child)
1106 gst_object_ref (child);
1107 if (GST_IS_BIN (child)) {
1108 GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
1110 gst_iterator_push (it, other);
1112 return GST_ITERATOR_ITEM_PASS;
1116 * gst_bin_iterate_recurse:
1119 * Gets an iterator for the elements in this bin.
1120 * This iterator recurses into GstBin children.
1122 * Each element yielded by the iterator will have its refcount increased, so
1125 * MT safe. Caller owns returned value.
1127 * Returns: a #GstIterator of #GstElement, or NULL
1130 gst_bin_iterate_recurse (GstBin * bin)
1132 GstIterator *result;
1134 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1136 GST_OBJECT_LOCK (bin);
1137 /* add ref because the iterator refs the bin. When the iterator
1138 * is freed it will unref the bin again using the provided dispose
1140 gst_object_ref (bin);
1141 result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1142 GST_OBJECT_GET_LOCK (bin),
1143 &bin->children_cookie,
1146 (GstIteratorItemFunction) iterate_child_recurse,
1147 (GstIteratorDisposeFunction) gst_object_unref);
1148 GST_OBJECT_UNLOCK (bin);
1153 /* returns 0 when TRUE because this is a GCompareFunc */
1156 bin_element_is_sink (GstElement * child, GstBin * bin)
1160 /* we lock the child here for the remainder of the function to
1161 * get its name and flag safely. */
1162 GST_OBJECT_LOCK (child);
1163 is_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
1165 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1166 "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
1168 GST_OBJECT_UNLOCK (child);
1169 return is_sink ? 0 : 1;
1173 sink_iterator_filter (GstElement * child, GstBin * bin)
1175 if (bin_element_is_sink (child, bin) == 0) {
1176 /* returns 0 because this is a GCompareFunc */
1179 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
1181 gst_object_unref (child);
1187 * gst_bin_iterate_sinks:
1190 * Gets an iterator for all elements in the bin that have the
1191 * #GST_ELEMENT_IS_SINK flag set.
1193 * Each element yielded by the iterator will have its refcount increased, so
1196 * MT safe. Caller owns returned value.
1198 * Returns: a #GstIterator of #GstElement, or NULL
1201 gst_bin_iterate_sinks (GstBin * bin)
1203 GstIterator *children;
1204 GstIterator *result;
1206 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1208 children = gst_bin_iterate_elements (bin);
1209 result = gst_iterator_filter (children,
1210 (GCompareFunc) sink_iterator_filter, bin);
1215 /* returns 0 when TRUE because this is a GCompareFunc */
1218 bin_element_is_src (GstElement * child, GstBin * bin)
1220 gboolean is_src = FALSE;
1222 /* we lock the child here for the remainder of the function to
1223 * get its name and flag safely. */
1224 GST_OBJECT_LOCK (child);
1225 if (!GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK) &&
1226 !child->numsinkpads) {
1230 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1231 "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not");
1233 GST_OBJECT_UNLOCK (child);
1234 return is_src ? 0 : 1;
1238 src_iterator_filter (GstElement * child, GstBin * bin)
1240 if (bin_element_is_src (child, bin) == 0) {
1241 /* returns 0 because this is a GCompareFunc */
1244 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
1246 gst_object_unref (child);
1252 * gst_bin_iterate_sources:
1255 * Gets an iterator for all elements in the bin that have no sinkpads and have
1256 * the #GST_ELEMENT_IS_SINK flag unset.
1258 * Each element yielded by the iterator will have its refcount increased, so
1261 * MT safe. Caller owns returned value.
1263 * Returns: a #GstIterator of #GstElement, or NULL
1266 gst_bin_iterate_sources (GstBin * bin)
1268 GstIterator *children;
1269 GstIterator *result;
1271 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1273 children = gst_bin_iterate_elements (bin);
1274 result = gst_iterator_filter (children,
1275 (GCompareFunc) src_iterator_filter, bin);
1283 static GstStateChangeReturn
1284 gst_bin_get_state_func (GstElement * element, GstState * state,
1285 GstState * pending, GstClockTime timeout)
1287 GstBin *bin = GST_BIN (element);
1288 GstStateChangeReturn ret;
1290 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "getting state");
1292 /* do a non forced recalculation of the state */
1293 gst_bin_recalc_state (bin, FALSE);
1295 ret = parent_class->get_state (element, state, pending, timeout);
1301 gst_bin_recalc_state (GstBin * bin, gboolean force)
1303 GstStateChangeReturn ret;
1305 guint32 children_cookie;
1306 guint32 state_cookie;
1307 gboolean have_no_preroll;
1308 gboolean have_async;
1310 ret = GST_STATE_CHANGE_SUCCESS;
1312 /* lock bin, no element can be added or removed while we have this lock */
1313 GST_OBJECT_LOCK (bin);
1314 /* forced recalc, make state dirty again */
1316 bin->state_dirty = TRUE;
1318 /* no point in scanning if nothing changed and it's no forced recalc */
1319 if (!bin->state_dirty)
1322 /* no point in having two scans run concurrently */
1326 bin->polling = TRUE;
1327 state_cookie = GST_ELEMENT_CAST (bin)->state_cookie;
1329 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "recalc state");
1332 /* when we leave this function, the state must not be dirty, whenever
1333 * we are scanning and the state becomes dirty again, we restart. */
1334 bin->state_dirty = FALSE;
1336 have_no_preroll = FALSE;
1339 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "checking element states");
1341 /* scan all element states with a zero timeout so we don't block on
1343 children = bin->children;
1344 children_cookie = bin->children_cookie;
1346 GstElement *child = GST_ELEMENT_CAST (children->data);
1348 gst_object_ref (child);
1349 /* now we release the lock to enter a non blocking wait. We
1350 * release the lock anyway since we can. */
1351 GST_OBJECT_UNLOCK (bin);
1353 ret = gst_element_get_state (child, NULL, NULL, 0);
1355 gst_object_unref (child);
1357 /* now grab the lock to iterate to the next child */
1358 GST_OBJECT_LOCK (bin);
1359 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1360 /* child added/removed during state change, restart. We need
1361 * to restart with the quick check as a no-preroll element could
1362 * have been added here and we don't want to block on sinks then.*/
1363 GST_DEBUG_OBJECT (bin, "children added or removed, restarting recalc");
1366 if (state_cookie != GST_ELEMENT_CAST (bin)->state_cookie) {
1367 GST_DEBUG_OBJECT (bin, "concurrent state change");
1368 goto concurrent_state;
1370 if (bin->state_dirty) {
1371 GST_DEBUG_OBJECT (bin, "state dirty again, restarting recalc");
1376 case GST_STATE_CHANGE_FAILURE:
1377 /* report FAILURE immediatly */
1379 case GST_STATE_CHANGE_NO_PREROLL:
1380 /* we have to continue scanning as there might be
1382 have_no_preroll = TRUE;
1384 case GST_STATE_CHANGE_ASYNC:
1385 /* we have to continue scanning as there might be
1392 children = g_list_next (children);
1394 /* if we get here, we have no FAILURES */
1396 /* if we have NO_PREROLL, return that */
1397 if (have_no_preroll) {
1398 ret = GST_STATE_CHANGE_NO_PREROLL;
1400 /* else return ASYNC if async elements where found. */
1401 else if (have_async) {
1402 ret = GST_STATE_CHANGE_ASYNC;
1406 bin->polling = FALSE;
1407 GST_OBJECT_UNLOCK (bin);
1409 /* now we can take the state lock, it is possible that new elements
1410 * are added now and we still report the old state. No problem though as
1411 * the return is still consistent, the effect is as if the element was
1412 * added after this function completed. */
1414 case GST_STATE_CHANGE_SUCCESS:
1415 case GST_STATE_CHANGE_NO_PREROLL:
1416 ret = gst_element_continue_state (GST_ELEMENT_CAST (bin), ret);
1418 case GST_STATE_CHANGE_ASYNC:
1419 gst_element_lost_state (GST_ELEMENT_CAST (bin));
1421 case GST_STATE_CHANGE_FAILURE:
1422 gst_element_abort_state (GST_ELEMENT_CAST (bin));
1428 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "bin RETURN is now %s",
1429 gst_element_state_change_return_get_name (ret));
1435 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "not dirty");
1436 GST_OBJECT_UNLOCK (bin);
1441 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "was polling");
1442 GST_OBJECT_UNLOCK (bin);
1447 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "concurrent_state");
1448 bin->polling = FALSE;
1449 GST_OBJECT_UNLOCK (bin);
1454 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
1455 GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
1456 "unknown return value %d from a state change function", ret);
1457 g_critical ("unknown return value %d from a state change function", ret);
1458 GST_STATE_RETURN (bin) = GST_STATE_CHANGE_FAILURE;
1459 GST_STATE_UNLOCK (bin);
1464 /***********************************************
1465 * Topologically sorted iterator
1466 * see http://en.wikipedia.org/wiki/Topological_sorting
1468 * For each element in the graph, an entry is kept in a HashTable
1469 * with its number of srcpad connections (degree).
1470 * We then change state of all elements without dependencies
1471 * (degree 0) and decrement the degree of all elements connected
1472 * on the sinkpads. When an element reaches degree 0, its state is
1474 * When all elements are handled the algorithm stops.
1476 typedef struct _GstBinSortIterator
1479 GQueue *queue; /* elements queued for state change */
1480 GstBin *bin; /* bin we iterate */
1481 gint mode; /* adding or removing dependency */
1482 GstElement *best; /* next element with least dependencies */
1483 gint best_deg; /* best degree */
1484 GHashTable *hash; /* hashtable with element dependencies */
1485 } GstBinSortIterator;
1487 /* we add and subtract 1 to make sure we don't confuse NULL and 0 */
1488 #define HASH_SET_DEGREE(bit, elem, deg) \
1489 g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1))
1490 #define HASH_GET_DEGREE(bit, elem) \
1491 (GPOINTER_TO_INT(g_hash_table_lookup (bit->hash, elem))-1)
1493 /* add element to queue of next elements in the iterator.
1494 * We push at the tail to give higher priority elements a
1497 add_to_queue (GstBinSortIterator * bit, GstElement * element)
1499 GST_DEBUG_OBJECT (bit->bin, "%s add to queue", GST_ELEMENT_NAME (element));
1500 gst_object_ref (element);
1501 g_queue_push_tail (bit->queue, element);
1502 HASH_SET_DEGREE (bit, element, -1);
1505 /* clear the queue, unref all objects as we took a ref when
1506 * we added them to the queue */
1508 clear_queue (GQueue * queue)
1512 while ((p = g_queue_pop_head (queue)))
1513 gst_object_unref (p);
1516 /* set all degrees to 0. Elements marked as a sink are
1517 * added to the queue immediatly. */
1519 reset_degree (GstElement * element, GstBinSortIterator * bit)
1523 /* sinks are added right away */
1524 GST_OBJECT_LOCK (element);
1525 is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK);
1526 GST_OBJECT_UNLOCK (element);
1529 add_to_queue (bit, element);
1531 /* others are marked with 0 and handled when sinks are done */
1532 HASH_SET_DEGREE (bit, element, 0);
1536 /* adjust the degree of all elements connected to the given
1537 * element. If an degree of an element drops to 0, it is
1538 * added to the queue of elements to schedule next.
1540 * We have to make sure not to cross the bin boundary this element
1544 update_degree (GstElement * element, GstBinSortIterator * bit)
1546 gboolean linked = FALSE;
1548 GST_OBJECT_LOCK (element);
1549 /* don't touch degree if element has no sourcepads */
1550 if (element->numsinkpads != 0) {
1551 /* loop over all sinkpads, decrement degree for all connected
1552 * elements in this bin */
1555 for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
1558 if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
1559 GstElement *peer_element;
1561 if ((peer_element = gst_pad_get_parent_element (peer))) {
1562 GST_OBJECT_LOCK (peer_element);
1563 /* check that we don't go outside of this bin */
1564 if (GST_OBJECT_CAST (peer_element)->parent ==
1565 GST_OBJECT_CAST (bit->bin)) {
1566 gint old_deg, new_deg;
1568 old_deg = HASH_GET_DEGREE (bit, peer_element);
1569 new_deg = old_deg + bit->mode;
1571 GST_DEBUG_OBJECT (bit->bin,
1572 "change element %s, degree %d->%d, linked to %s",
1573 GST_ELEMENT_NAME (peer_element), old_deg, new_deg,
1574 GST_ELEMENT_NAME (element));
1578 /* degree hit 0, add to queue */
1579 add_to_queue (bit, peer_element);
1581 HASH_SET_DEGREE (bit, peer_element, new_deg);
1585 GST_OBJECT_UNLOCK (peer_element);
1586 gst_object_unref (peer_element);
1588 gst_object_unref (peer);
1593 GST_DEBUG_OBJECT (bit->bin, "element %s not linked on any sinkpads",
1594 GST_ELEMENT_NAME (element));
1596 GST_OBJECT_UNLOCK (element);
1599 /* find the next best element not handled yet. This is the one
1600 * with the lowest non-negative degree */
1602 find_element (GstElement * element, GstBinSortIterator * bit)
1606 /* element is already handled */
1607 if ((degree = HASH_GET_DEGREE (bit, element)) < 0)
1610 /* first element or element with smaller degree */
1611 if (bit->best == NULL || bit->best_deg > degree) {
1612 bit->best = element;
1613 bit->best_deg = degree;
1617 /* get next element in iterator. the returned element has the
1618 * refcount increased */
1619 static GstIteratorResult
1620 gst_bin_sort_iterator_next (GstBinSortIterator * bit, gpointer * result)
1622 GstBin *bin = bit->bin;
1624 /* empty queue, we have to find a next best element */
1625 if (g_queue_is_empty (bit->queue)) {
1629 bit->best_deg = G_MAXINT;
1630 g_list_foreach (bin->children, (GFunc) find_element, bit);
1631 if ((best = bit->best)) {
1632 if (bit->best_deg != 0) {
1633 /* we don't fail on this one yet */
1634 g_warning ("loop detected in the graph !!");
1636 /* best unhandled element, schedule as next element */
1637 GST_DEBUG_OBJECT (bin, "queue empty, next best: %s",
1638 GST_ELEMENT_NAME (best));
1639 gst_object_ref (best);
1640 HASH_SET_DEGREE (bit, best, -1);
1643 GST_DEBUG_OBJECT (bin, "queue empty, elements exhausted");
1644 /* no more unhandled elements, we are done */
1645 return GST_ITERATOR_DONE;
1648 /* everything added to the queue got reffed */
1649 *result = g_queue_pop_head (bit->queue);
1652 GST_DEBUG_OBJECT (bin, "queue head gives %s", GST_ELEMENT_NAME (*result));
1653 /* update degrees of linked elements */
1654 update_degree (GST_ELEMENT_CAST (*result), bit);
1656 return GST_ITERATOR_OK;
1659 /* clear queues, recalculate the degrees and restart. */
1661 gst_bin_sort_iterator_resync (GstBinSortIterator * bit)
1663 GstBin *bin = bit->bin;
1665 GST_DEBUG_OBJECT (bin, "resync");
1666 clear_queue (bit->queue);
1668 g_list_foreach (bin->children, (GFunc) reset_degree, bit);
1669 /* calc degrees, incrementing */
1671 g_list_foreach (bin->children, (GFunc) update_degree, bit);
1672 /* for the rest of the function we decrement the degrees */
1676 /* clear queues, unref bin and free iterator. */
1678 gst_bin_sort_iterator_free (GstBinSortIterator * bit)
1680 GstBin *bin = bit->bin;
1682 GST_DEBUG_OBJECT (bin, "free");
1683 clear_queue (bit->queue);
1684 g_queue_free (bit->queue);
1685 g_hash_table_destroy (bit->hash);
1686 gst_object_unref (bin);
1690 /* should be called with the bin LOCK held */
1691 static GstIterator *
1692 gst_bin_sort_iterator_new (GstBin * bin)
1694 GstBinSortIterator *result;
1696 /* we don't need an ItemFunction because we ref the items in the _next
1698 result = (GstBinSortIterator *)
1699 gst_iterator_new (sizeof (GstBinSortIterator),
1701 GST_OBJECT_GET_LOCK (bin),
1702 &bin->children_cookie,
1703 (GstIteratorNextFunction) gst_bin_sort_iterator_next,
1704 (GstIteratorItemFunction) NULL,
1705 (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
1706 (GstIteratorFreeFunction) gst_bin_sort_iterator_free);
1707 result->queue = g_queue_new ();
1708 result->hash = g_hash_table_new (NULL, NULL);
1709 gst_object_ref (bin);
1711 gst_bin_sort_iterator_resync (result);
1713 return (GstIterator *) result;
1717 * gst_bin_iterate_sorted:
1720 * Gets an iterator for the elements in this bin in topologically
1721 * sorted order. This means that the elements are returned from
1722 * the most downstream elements (sinks) to the sources.
1724 * This function is used internally to perform the state changes
1725 * of the bin elements.
1727 * Each element yielded by the iterator will have its refcount increased, so
1730 * MT safe. Caller owns returned value.
1732 * Returns: a #GstIterator of #GstElement, or NULL
1735 gst_bin_iterate_sorted (GstBin * bin)
1737 GstIterator *result;
1739 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1741 GST_OBJECT_LOCK (bin);
1742 result = gst_bin_sort_iterator_new (bin);
1743 GST_OBJECT_UNLOCK (bin);
1748 static GstStateChangeReturn
1749 gst_bin_element_set_state (GstBin * bin, GstElement * element, GstState pending)
1751 GstStateChangeReturn ret;
1754 /* peel off the locked flag */
1755 GST_OBJECT_LOCK (element);
1756 locked = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1757 GST_OBJECT_UNLOCK (element);
1759 /* skip locked elements */
1760 if (G_UNLIKELY (locked)) {
1761 GST_DEBUG_OBJECT (element,
1762 "element is locked, pretending state change succeeded");
1763 ret = GST_STATE_CHANGE_SUCCESS;
1768 ret = gst_element_set_state (element, pending);
1774 /* gst_iterator_fold functions for pads_activate
1775 * Note how we don't stop the iterator when we fail an activation. This is
1776 * probably a FIXME since when one pad activation fails, we don't want to
1777 * continue our state change. */
1779 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1781 if (!gst_pad_set_active (pad, *active))
1782 g_value_set_boolean (ret, FALSE);
1784 gst_pad_set_caps (pad, NULL);
1786 /* unref the object that was reffed for us by _fold */
1787 gst_object_unref (pad);
1791 /* returns false on error or early cutout (will never happen because the fold
1792 * function always returns TRUE, see FIXME above) of the fold, true if all
1793 * pads in @iter were (de)activated successfully. */
1795 iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data)
1797 GstIteratorResult ires;
1800 /* no need to unset this later, it's just a boolean */
1801 g_value_init (&ret, G_TYPE_BOOLEAN);
1802 g_value_set_boolean (&ret, TRUE);
1805 ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) activate_pads,
1808 case GST_ITERATOR_RESYNC:
1809 /* need to reset the result again */
1810 g_value_set_boolean (&ret, TRUE);
1811 gst_iterator_resync (iter);
1813 case GST_ITERATOR_DONE:
1814 /* all pads iterated, return collected value */
1817 /* iterator returned _ERROR or premature end with _OK,
1818 * mark an error and exit */
1819 g_value_set_boolean (&ret, FALSE);
1824 /* return collected value */
1825 return g_value_get_boolean (&ret);
1828 /* is called with STATE_LOCK
1831 gst_bin_src_pads_activate (GstBin * bin, gboolean active)
1836 GST_DEBUG_OBJECT (bin, "src_pads_activate with active %d", active);
1838 iter = gst_element_iterate_src_pads ((GstElement *) bin);
1839 fold_ok = iterator_activate_fold_with_resync (iter, &active);
1840 gst_iterator_free (iter);
1841 if (G_UNLIKELY (!fold_ok))
1844 GST_DEBUG_OBJECT (bin, "pads_activate successful");
1851 GST_DEBUG_OBJECT (bin, "source pads_activate failed");
1855 static GstStateChangeReturn
1856 gst_bin_change_state_func (GstElement * element, GstStateChange transition)
1859 GstStateChangeReturn ret;
1860 GstState current, next;
1861 gboolean have_async;
1862 gboolean have_no_preroll;
1863 GstClockTime base_time;
1867 /* we don't need to take the STATE_LOCK, it is already taken */
1868 current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
1869 next = (GstState) GST_STATE_TRANSITION_NEXT (transition);
1871 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1872 "changing state of children from %s to %s",
1873 gst_element_state_get_name (current), gst_element_state_get_name (next));
1875 bin = GST_BIN_CAST (element);
1878 case GST_STATE_PAUSED:
1879 /* Clear EOS list on next PAUSED */
1880 GST_OBJECT_LOCK (bin);
1881 GST_DEBUG_OBJECT (element, "clearing EOS elements");
1882 bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
1883 GST_OBJECT_UNLOCK (bin);
1884 if (current == GST_STATE_READY)
1885 if (!(gst_bin_src_pads_activate (bin, TRUE)))
1886 goto activate_failure;
1888 case GST_STATE_READY:
1889 /* Clear message list on next READY */
1890 GST_OBJECT_LOCK (bin);
1891 GST_DEBUG_OBJECT (element, "clearing all cached messages");
1892 bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
1893 GST_OBJECT_UNLOCK (bin);
1894 if (current == GST_STATE_PAUSED)
1895 if (!(gst_bin_src_pads_activate (bin, FALSE)))
1896 goto activate_failure;
1898 case GST_STATE_NULL:
1899 if (current == GST_STATE_READY)
1900 if (!(gst_bin_src_pads_activate (bin, FALSE)))
1901 goto activate_failure;
1907 /* iterate in state change order */
1908 it = gst_bin_iterate_sorted (bin);
1911 /* take base_time */
1912 base_time = gst_element_get_base_time (element);
1915 have_no_preroll = FALSE;
1921 switch (gst_iterator_next (it, &data)) {
1922 case GST_ITERATOR_OK:
1926 child = GST_ELEMENT_CAST (data);
1928 /* set base_time on child */
1929 gst_element_set_base_time (child, base_time);
1932 ret = gst_bin_element_set_state (bin, child, next);
1935 case GST_STATE_CHANGE_SUCCESS:
1936 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1937 "child '%s' changed state to %d(%s) successfully",
1938 GST_ELEMENT_NAME (child), next,
1939 gst_element_state_get_name (next));
1941 case GST_STATE_CHANGE_ASYNC:
1942 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1943 "child '%s' is changing state asynchronously to %s",
1944 GST_ELEMENT_NAME (child), gst_element_state_get_name (next));
1947 case GST_STATE_CHANGE_FAILURE:
1948 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1949 "child '%s' failed to go to state %d(%s)",
1950 GST_ELEMENT_NAME (child),
1951 next, gst_element_state_get_name (next));
1952 gst_object_unref (child);
1954 case GST_STATE_CHANGE_NO_PREROLL:
1955 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1956 "child '%s' changed state to %d(%s) successfully without preroll",
1957 GST_ELEMENT_NAME (child), next,
1958 gst_element_state_get_name (next));
1959 have_no_preroll = TRUE;
1962 g_assert_not_reached ();
1965 gst_object_unref (child);
1968 case GST_ITERATOR_RESYNC:
1969 GST_CAT_DEBUG (GST_CAT_STATES, "iterator doing resync");
1970 gst_iterator_resync (it);
1973 case GST_ITERATOR_DONE:
1974 GST_CAT_DEBUG (GST_CAT_STATES, "iterator done");
1980 ret = parent_class->change_state (element, transition);
1981 if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
1984 if (have_no_preroll) {
1985 ret = GST_STATE_CHANGE_NO_PREROLL;
1986 } else if (have_async) {
1987 ret = GST_STATE_CHANGE_ASYNC;
1991 gst_iterator_free (it);
1993 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1994 "done changing bin's state from %s to %s, now in %s, ret %d",
1995 gst_element_state_get_name (current),
1996 gst_element_state_get_name (next),
1997 gst_element_state_get_name (GST_STATE (element)), ret);
2004 GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element,
2005 "failure (de)activating src pads");
2006 return GST_STATE_CHANGE_FAILURE;
2011 * This function is a utility event handler for seek events.
2012 * It will send the event to all sinks or sources depending on the
2015 * Applications are free to override this behaviour and
2016 * implement their own seek handler, but this will work for
2017 * pretty much all cases in practice.
2020 gst_bin_send_event (GstElement * element, GstEvent * event)
2022 GstBin *bin = GST_BIN (element);
2024 gboolean res = TRUE;
2025 gboolean done = FALSE;
2027 if (GST_EVENT_IS_DOWNSTREAM (event)) {
2028 iter = gst_bin_iterate_sources (bin);
2029 GST_DEBUG_OBJECT (bin, "Sending %s event to src children",
2030 GST_EVENT_TYPE_NAME (event));
2032 iter = gst_bin_iterate_sinks (bin);
2033 GST_DEBUG_OBJECT (bin, "Sending %s event to sink children",
2034 GST_EVENT_TYPE_NAME (event));
2040 switch (gst_iterator_next (iter, &data)) {
2041 case GST_ITERATOR_OK:
2045 gst_event_ref (event);
2046 child = GST_ELEMENT_CAST (data);
2047 res &= gst_element_send_event (child, event);
2048 gst_object_unref (child);
2051 case GST_ITERATOR_RESYNC:
2052 gst_iterator_resync (iter);
2055 case GST_ITERATOR_DONE:
2058 case GST_ITERATOR_ERROR:
2059 g_assert_not_reached ();
2063 gst_iterator_free (iter);
2064 gst_event_unref (event);
2070 gst_bin_recalc_func (GstBin * bin, gpointer data)
2072 GST_DEBUG_OBJECT (bin, "doing state recalc");
2073 GST_STATE_LOCK (bin);
2074 gst_bin_recalc_state (bin, FALSE);
2075 GST_STATE_UNLOCK (bin);
2076 GST_DEBUG_OBJECT (bin, "state recalc done");
2077 gst_object_unref (bin);
2080 static GstBusSyncReply
2081 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
2084 GstBinClass *bclass;
2086 bclass = GST_BIN_GET_CLASS (bin);
2087 if (bclass->handle_message)
2088 bclass->handle_message (bin, message);
2090 gst_message_unref (message);
2092 return GST_BUS_DROP;
2095 /* handle child messages:
2097 * This method is called synchronously when a child posts a message on
2100 * GST_MESSAGE_EOS: This message is only posted by sinks
2101 * in the PLAYING state. If all sinks posted the EOS message, post
2104 * GST_MESSAGE_STATE_DIRTY: if we are the toplevel bin we do a state
2105 * recalc. If we are not toplevel (we have a parent) we just post
2106 * the message upwards. This makes sure only the toplevel bin will
2107 * run over all its children to check if a state change happened.
2109 * GST_MESSAGE_SEGMENT_START: just collect, never forward upwards. If an
2110 * element posts segment_start twice, only the last message is kept.
2112 * GST_MESSAGE_SEGMENT_DONE: replace SEGMENT_START message from same poster
2113 * with the segment_done message. If there are no more segment_start
2114 * messages, post segment_done message upwards.
2116 * GST_MESSAGE_DURATION: remove all previously cached duration messages.
2117 * Whenever someone performs a duration query on the bin, we store the
2118 * result so we can answer it quicker the next time. Any element that
2119 * changes its duration marks our cached values invalid.
2120 * This message is also posted upwards. This is currently disabled
2121 * because too many elements don't post DURATION messages when the
2124 * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it
2125 * can no longer provide a clock. The default bin behaviour is to
2126 * check if the lost clock was the one provided by the bin. If so and
2127 * we are currently in the PLAYING state, we forward the message to
2129 * This message is also generated when we remove a clock provider from
2130 * a bin. If this message is received by the application, it should
2131 * PAUSE the pipeline and set it back to PLAYING to force a new clock
2132 * and a new base_time distribution.
2134 * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element
2135 * can provide a clock. This mostly happens when we add a new clock
2136 * provider to the bin. The default behaviour of the bin is to mark the
2137 * currently selected clock as dirty, which will perform a clock
2138 * recalculation the next time we are asked to provide a clock.
2139 * This message is never sent to the application but is forwarded to
2142 * OTHER: post upwards.
2145 gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
2147 GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %s",
2148 message, GST_MESSAGE_TYPE_NAME (message));
2150 switch (GST_MESSAGE_TYPE (message)) {
2151 case GST_MESSAGE_EOS:
2155 /* collect all eos messages from the children */
2156 GST_OBJECT_LOCK (bin);
2157 bin_replace_message (bin, message, GST_MESSAGE_EOS);
2159 GST_OBJECT_UNLOCK (bin);
2161 /* if we are completely EOS, we forward an EOS message */
2163 GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
2164 gst_element_post_message (GST_ELEMENT_CAST (bin),
2165 gst_message_new_eos (GST_OBJECT_CAST (bin)));
2169 case GST_MESSAGE_STATE_DIRTY:
2174 src = GST_MESSAGE_SRC (message);
2176 GST_DEBUG_OBJECT (bin, "%s gave state dirty", GST_ELEMENT_NAME (src));
2178 /* mark the bin dirty */
2179 GST_OBJECT_LOCK (bin);
2180 GST_DEBUG_OBJECT (bin, "marking dirty");
2181 bin->state_dirty = TRUE;
2183 if (GST_OBJECT_PARENT (bin))
2187 gst_message_unref (message);
2189 klass = GST_BIN_GET_CLASS (bin);
2190 if (!bin->polling) {
2191 GST_DEBUG_OBJECT (bin, "pushing recalc on thread pool");
2192 gst_object_ref (bin);
2193 g_thread_pool_push (klass->pool, bin, NULL);
2195 GST_DEBUG_OBJECT (bin,
2196 "state recalc already in progress, not pushing new recalc");
2198 GST_OBJECT_UNLOCK (bin);
2201 /* non toplevel bins just forward the message and don't start
2202 * a recalc themselves */
2205 GST_OBJECT_UNLOCK (bin);
2206 GST_DEBUG_OBJECT (bin, "not toplevel, forwarding");
2210 case GST_MESSAGE_SEGMENT_START:
2211 GST_OBJECT_LOCK (bin);
2212 /* replace any previous segment_start message from this source
2213 * with the new segment start message */
2214 bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
2215 GST_OBJECT_UNLOCK (bin);
2217 case GST_MESSAGE_SEGMENT_DONE:
2220 gboolean post = FALSE;
2224 gst_message_parse_segment_done (message, &format, &position);
2226 GST_OBJECT_LOCK (bin);
2227 bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
2228 /* if there are no more segment_start messages, everybody posted
2229 * a segment_done and we can post one on the bus. */
2231 /* we don't care who still has a pending segment start */
2233 find.types = GST_MESSAGE_SEGMENT_START;
2235 if (!g_list_find_custom (bin->messages, &find,
2236 (GCompareFunc) message_check)) {
2239 /* remove all old segment_done messages */
2240 bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
2242 GST_OBJECT_UNLOCK (bin);
2244 /* post segment done with latest format and position. */
2245 gst_element_post_message (GST_ELEMENT_CAST (bin),
2246 gst_message_new_segment_done (GST_OBJECT_CAST (bin),
2251 case GST_MESSAGE_DURATION:
2253 /* remove all cached duration messages, next time somebody asks
2254 * for duration, we will recalculate. */
2255 GST_OBJECT_LOCK (bin);
2256 bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION);
2257 GST_OBJECT_UNLOCK (bin);
2260 case GST_MESSAGE_CLOCK_LOST:
2262 GstClock **provided_clock_p;
2263 GstElement **clock_provider_p;
2264 gboolean playing, provided, forward;
2267 gst_message_parse_clock_lost (message, &clock);
2269 GST_OBJECT_LOCK (bin);
2270 bin->clock_dirty = TRUE;
2271 /* if we lost the clock that we provided, post to parent but
2272 * only if we are PLAYING. */
2273 provided = (clock == bin->provided_clock);
2274 playing = (GST_STATE (bin) == GST_STATE_PLAYING);
2275 forward = playing & provided;
2277 GST_DEBUG_OBJECT (bin,
2278 "Lost clock %" GST_PTR_FORMAT " provided by %" GST_PTR_FORMAT,
2279 bin->provided_clock, bin->clock_provider);
2280 provided_clock_p = &bin->provided_clock;
2281 clock_provider_p = &bin->clock_provider;
2282 gst_object_replace ((GstObject **) provided_clock_p, NULL);
2283 gst_object_replace ((GstObject **) clock_provider_p, NULL);
2285 GST_DEBUG_OBJECT (bin, "provided %d, playing %d, forward %d",
2286 provided, playing, forward);
2287 GST_OBJECT_UNLOCK (bin);
2293 gst_message_unref (message);
2296 case GST_MESSAGE_CLOCK_PROVIDE:
2300 GST_OBJECT_LOCK (bin);
2301 bin->clock_dirty = TRUE;
2302 /* a new clock is available, post to parent but not
2303 * to the application */
2304 forward = GST_OBJECT_PARENT (bin) != NULL;
2305 GST_OBJECT_UNLOCK (bin);
2311 gst_message_unref (message);
2321 /* Send all other messages upward */
2322 GST_DEBUG_OBJECT (bin, "posting message upward");
2323 gst_element_post_message (GST_ELEMENT_CAST (bin), message);
2328 /* generic struct passed to all query fold methods */
2337 typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold);
2338 typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold);
2340 /* for duration/position we collect all durations/positions and take
2341 * the MAX of all valid results */
2343 bin_query_min_max_init (GstBin * bin, QueryFold * fold)
2351 bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
2353 if (gst_element_query (item, fold->query)) {
2356 g_value_set_boolean (ret, TRUE);
2358 gst_query_parse_duration (fold->query, NULL, &duration);
2360 GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
2362 if (duration > fold->max)
2363 fold->max = duration;
2366 gst_object_unref (item);
2370 bin_query_duration_done (GstBin * bin, QueryFold * fold)
2374 gst_query_parse_duration (fold->query, &format, NULL);
2375 /* store max in query result */
2376 gst_query_set_duration (fold->query, format, fold->max);
2378 GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
2380 #ifdef DURATION_CACHING
2382 GST_OBJECT_LOCK (bin);
2383 bin->messages = g_list_prepend (bin->messages,
2384 gst_message_new_duration (GST_OBJECT_CAST (bin), format, fold->max));
2385 GST_OBJECT_UNLOCK (bin);
2390 bin_query_position_fold (GstElement * item, GValue * ret, QueryFold * fold)
2392 if (gst_element_query (item, fold->query)) {
2395 g_value_set_boolean (ret, TRUE);
2397 gst_query_parse_position (fold->query, NULL, &position);
2399 GST_DEBUG_OBJECT (item, "got position %" G_GINT64_FORMAT, position);
2401 if (position > fold->max)
2402 fold->max = position;
2405 gst_object_unref (item);
2409 bin_query_position_done (GstBin * bin, QueryFold * fold)
2413 gst_query_parse_position (fold->query, &format, NULL);
2414 /* store max in query result */
2415 gst_query_set_position (fold->query, format, fold->max);
2417 GST_DEBUG_OBJECT (bin, "max position %" G_GINT64_FORMAT, fold->max);
2421 bin_query_latency_fold (GstElement * item, GValue * ret, QueryFold * fold)
2423 if (gst_element_query (item, fold->query)) {
2424 GstClockTime min, max;
2427 g_value_set_boolean (ret, TRUE);
2429 gst_query_parse_latency (fold->query, &live, &min, &max);
2431 GST_DEBUG_OBJECT (item,
2432 "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
2433 ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
2435 /* for the combined latency we collect the MAX of all min latencies and
2436 * the MIN of all max latencies */
2437 if (min > fold->min)
2439 if (fold->max == -1)
2441 else if (max < fold->max)
2443 if (fold->live == FALSE)
2447 gst_object_unref (item);
2451 bin_query_latency_done (GstBin * bin, QueryFold * fold)
2453 /* store max in query result */
2454 gst_query_set_latency (fold->query, fold->live, fold->min, fold->max);
2456 GST_DEBUG_OBJECT (bin,
2457 "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
2458 ", live %d", GST_TIME_ARGS (fold->min), GST_TIME_ARGS (fold->max),
2463 /* generic fold, return first valid result */
2465 bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
2469 if ((res = gst_element_query (item, fold->query))) {
2470 g_value_set_boolean (ret, TRUE);
2471 GST_DEBUG_OBJECT (item, "answered query %p", fold->query);
2474 gst_object_unref (item);
2476 /* and stop as soon as we have a valid result */
2481 gst_bin_query (GstElement * element, GstQuery * query)
2483 GstBin *bin = GST_BIN (element);
2485 gboolean res = FALSE;
2486 GstIteratorFoldFunction fold_func;
2487 QueryInitFunction fold_init = NULL;
2488 QueryDoneFunction fold_done = NULL;
2489 QueryFold fold_data;
2492 switch (GST_QUERY_TYPE (query)) {
2493 case GST_QUERY_DURATION:
2495 #ifdef DURATION_CACHING
2499 gst_query_parse_duration (query, &qformat, NULL);
2501 /* find cached duration query */
2502 GST_OBJECT_LOCK (bin);
2503 for (cached = bin->messages; cached; cached = g_list_next (cached)) {
2504 GstMessage *message = (GstMessage *) cached->data;
2506 if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION &&
2507 GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) {
2511 gst_message_parse_duration (message, &format, &duration);
2513 /* if cached same format, copy duration in query result */
2514 if (format == qformat) {
2515 GST_DEBUG_OBJECT (bin, "return cached duration %" G_GINT64_FORMAT,
2517 GST_OBJECT_UNLOCK (bin);
2519 gst_query_set_duration (query, qformat, duration);
2525 GST_OBJECT_UNLOCK (bin);
2527 /* no cached value found, iterate and collect durations */
2528 fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
2529 fold_init = bin_query_min_max_init;
2530 fold_done = bin_query_duration_done;
2533 case GST_QUERY_POSITION:
2535 fold_func = (GstIteratorFoldFunction) bin_query_position_fold;
2536 fold_init = bin_query_min_max_init;
2537 fold_done = bin_query_position_done;
2540 case GST_QUERY_LATENCY:
2542 fold_func = (GstIteratorFoldFunction) bin_query_latency_fold;
2543 fold_init = bin_query_min_max_init;
2544 fold_done = bin_query_latency_done;
2548 fold_func = (GstIteratorFoldFunction) bin_query_generic_fold;
2552 fold_data.query = query;
2554 g_value_init (&ret, G_TYPE_BOOLEAN);
2555 g_value_set_boolean (&ret, FALSE);
2557 iter = gst_bin_iterate_sinks (bin);
2558 GST_DEBUG_OBJECT (bin, "Sending query %p (type %d) to sink children",
2559 query, GST_QUERY_TYPE (query));
2562 fold_init (bin, &fold_data);
2565 GstIteratorResult ires;
2567 ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
2570 case GST_ITERATOR_RESYNC:
2571 gst_iterator_resync (iter);
2573 fold_init (bin, &fold_data);
2574 g_value_set_boolean (&ret, FALSE);
2576 case GST_ITERATOR_OK:
2577 case GST_ITERATOR_DONE:
2578 res = g_value_get_boolean (&ret);
2579 if (fold_done != NULL && res)
2580 fold_done (bin, &fold_data);
2588 gst_iterator_free (iter);
2590 #ifdef DURATION_CACHING
2593 GST_DEBUG_OBJECT (bin, "query %p result %d", query, res);
2599 compare_name (GstElement * element, const gchar * name)
2603 GST_OBJECT_LOCK (element);
2604 eq = strcmp (GST_ELEMENT_NAME (element), name);
2605 GST_OBJECT_UNLOCK (element);
2608 gst_object_unref (element);
2614 * gst_bin_get_by_name:
2616 * @name: the element name to search for
2618 * Gets the element with the given name from a bin. This
2619 * function recurses into child bins.
2621 * Returns NULL if no element with the given name is found in the bin.
2623 * MT safe. Caller owns returned reference.
2625 * Returns: the #GstElement with the given name, or NULL
2628 gst_bin_get_by_name (GstBin * bin, const gchar * name)
2630 GstIterator *children;
2631 GstIterator *result;
2633 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2635 GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
2636 GST_ELEMENT_NAME (bin), name);
2638 children = gst_bin_iterate_recurse (bin);
2639 result = gst_iterator_find_custom (children,
2640 (GCompareFunc) compare_name, (gpointer) name);
2641 gst_iterator_free (children);
2643 return GST_ELEMENT_CAST (result);
2647 * gst_bin_get_by_name_recurse_up:
2649 * @name: the element name to search for
2651 * Gets the element with the given name from this bin. If the
2652 * element is not found, a recursion is performed on the parent bin.
2655 * - no element with the given name is found in the bin
2657 * MT safe. Caller owns returned reference.
2659 * Returns: the #GstElement with the given name, or NULL
2662 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
2666 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2667 g_return_val_if_fail (name != NULL, NULL);
2669 result = gst_bin_get_by_name (bin, name);
2674 parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
2676 if (GST_IS_BIN (parent)) {
2677 result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
2679 gst_object_unref (parent);
2687 compare_interface (GstElement * element, gpointer interface)
2689 GType interface_type = (GType) interface;
2692 if (G_TYPE_CHECK_INSTANCE_TYPE (element, interface_type)) {
2695 /* we did not find the element, need to release the ref
2696 * added by the iterator */
2697 gst_object_unref (element);
2704 * gst_bin_get_by_interface:
2706 * @iface: the #GType of an interface
2708 * Looks for an element inside the bin that implements the given
2709 * interface. If such an element is found, it returns the element.
2710 * You can cast this element to the given interface afterwards. If you want
2711 * all elements that implement the interface, use
2712 * gst_bin_iterate_all_by_interface(). This function recurses into child bins.
2714 * MT safe. Caller owns returned reference.
2716 * Returns: A #GstElement inside the bin implementing the interface
2719 gst_bin_get_by_interface (GstBin * bin, GType iface)
2721 GstIterator *children;
2724 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2725 g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
2727 children = gst_bin_iterate_recurse (bin);
2728 result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
2730 gst_iterator_free (children);
2732 return GST_ELEMENT_CAST (result);
2736 * gst_bin_iterate_all_by_interface:
2738 * @iface: the #GType of an interface
2740 * Looks for all elements inside the bin that implements the given
2741 * interface. You can safely cast all returned elements to the given interface.
2742 * The function recurses inside child bins. The iterator will yield a series
2743 * of #GstElement that should be unreffed after use.
2745 * Each element yielded by the iterator will have its refcount increased, so
2748 * MT safe. Caller owns returned value.
2750 * Returns: a #GstIterator of #GstElement for all elements in the bin
2751 * implementing the given interface, or NULL
2754 gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
2756 GstIterator *children;
2757 GstIterator *result;
2759 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2760 g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
2762 children = gst_bin_iterate_recurse (bin);
2763 result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
2769 #ifndef GST_DISABLE_LOADSAVE
2771 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
2773 GstBin *bin = GST_BIN (object);
2774 xmlNodePtr childlist, elementnode;
2778 if (GST_OBJECT_CLASS (parent_class)->save_thyself)
2779 GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
2781 childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
2783 GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
2784 GST_ELEMENT_NAME (bin), bin->numchildren);
2786 children = bin->children;
2788 child = GST_ELEMENT (children->data);
2789 elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
2790 gst_object_save_thyself (GST_OBJECT (child), elementnode);
2791 children = g_list_next (children);
2797 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
2799 GstBin *bin = GST_BIN (object);
2800 xmlNodePtr field = self->xmlChildrenNode;
2801 xmlNodePtr childlist;
2804 if (!strcmp ((char *) field->name, "children")) {
2805 GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
2806 GST_ELEMENT_NAME (object));
2807 childlist = field->xmlChildrenNode;
2809 if (!strcmp ((char *) childlist->name, "element")) {
2810 /* gst_xml_make_element will gst_bin_add() the element to ourself */
2811 gst_xml_make_element (childlist, GST_OBJECT (bin));
2813 childlist = childlist->next;
2817 field = field->next;
2819 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2820 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2822 #endif /* GST_DISABLE_LOADSAVE */