gst/gstbin.c: Use GST_STR_NULL to prevent NULL pointer to be passed to GST_CAT_DEBUG.
[platform/upstream/gstreamer.git] / gst / gstbin.c
1 /* GStreamer
2  *
3  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
4  *                    2004 Wim Taymans <wim@fluendo.com>
5  *
6  * gstbin.c: GstBin container object and support code
7  *
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.
12  *
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.
17  *
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.
22  *
23  * MT safe.
24  */
25
26 /**
27  * SECTION:gstbin
28  * @short_description: Base class and element that can contain other elements
29  *
30  * #GstBin is an element that can contain other #GstElement, allowing them to be
31  * managed as a group.
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.
35  *
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.
39  *
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().
42  *
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
46  * current bin.
47  *
48  * An iterator of elements in a bin can be retrieved with
49  * gst_bin_iterate_elements(). Various other iterators exist to retrieve the
50  * elements in a bin.
51  *
52  * gst_object_unref() is used to drop your reference to the bin.
53  *
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.
58  *
59  * <refsect2><title>Notes</title>
60  * <para>
61  * A #GstBin internally intercepts every #GstMessage posted by its children and
62  * implements the following default behaviour for each of them:
63  * <variablelist>
64  *   <varlistentry>
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>
69  *   </varlistentry>
70  *   <varlistentry>
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>
75  *   </varlistentry>
76  *   <varlistentry>
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>
80  *   </varlistentry>
81  *   <varlistentry>
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
88  *     query.
89  *     </para></listitem>
90  *   </varlistentry>
91  *   <varlistentry>
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
97  *     the bin parent.
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
101  *     distribution.
102  *     </para></listitem>
103  *   </varlistentry>
104  *   <varlistentry>
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.
113  *     </para></listitem>
114  *   </varlistentry>
115  *   <varlistentry>
116  *     <term>OTHERS</term>
117  *     <listitem><para> posted upwards.</para></listitem>
118  *   </varlistentry>
119  * </variablelist>
120  *
121  *
122  * A #GstBin implements the following default behaviour for answering to a
123  * #GstQuery:
124  * <variablelist>
125  *   <varlistentry>
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.
133  *     </para></listitem>
134  *   </varlistentry>
135  *   <varlistentry>
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,
139  *     the query fails.
140  *     </para></listitem>
141  *   </varlistentry>
142  *   <varlistentry>
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>
147  *   </varlistentry>
148  * </variablelist>
149  *
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.
153  *
154  * </para>
155  * </refsect2>
156  *
157  * Last reviewed on 2006-04-28 (0.10.6)
158  */
159
160 #include "gst_private.h"
161
162 #include "gstevent.h"
163 #include "gstbin.h"
164 #include "gstmarshal.h"
165 #include "gstxml.h"
166 #include "gstinfo.h"
167 #include "gsterror.h"
168
169 #include "gstindex.h"
170 #include "gstindexfactory.h"
171 #include "gstutils.h"
172 #include "gstchildproxy.h"
173
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
178
179 GST_DEBUG_CATEGORY_STATIC (bin_debug);
180 #define GST_CAT_DEFAULT bin_debug
181
182 static const GstElementDetails gst_bin_details =
183 GST_ELEMENT_DETAILS ("Generic bin",
184     "Generic/Bin",
185     "Simple container object",
186     "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
187
188 static void gst_bin_dispose (GObject * object);
189
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);
195
196 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
197 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
198
199 #ifndef GST_DISABLE_INDEX
200 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
201 #endif
202 static GstClock *gst_bin_provide_clock_func (GstElement * element);
203 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
204
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);
210
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);
214 #endif
215
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);
221
222 static GstIterator *gst_bin_sort_iterator_new (GstBin * bin);
223
224 /* Bin signals and properties */
225 enum
226 {
227   ELEMENT_ADDED,
228   ELEMENT_REMOVED,
229   LAST_SIGNAL
230 };
231
232 enum
233 {
234   PROP_0
235       /* FILL ME */
236 };
237
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);
242
243 static GstElementClass *parent_class = NULL;
244 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
245
246 /**
247  * gst_bin_get_type:
248  *
249  * Returns: the type of #GstBin
250  */
251 GType
252 gst_bin_get_type (void)
253 {
254   static GType gst_bin_type = 0;
255
256   if (G_UNLIKELY (gst_bin_type == 0)) {
257     static const GTypeInfo bin_info = {
258       sizeof (GstBinClass),
259       gst_bin_base_init,
260       NULL,
261       (GClassInitFunc) gst_bin_class_init,
262       NULL,
263       NULL,
264       sizeof (GstBin),
265       0,
266       (GInstanceInitFunc) gst_bin_init,
267       NULL
268     };
269     static const GInterfaceInfo child_proxy_info = {
270       gst_bin_child_proxy_init,
271       NULL,
272       NULL
273     };
274
275     gst_bin_type =
276         g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
277
278     g_type_add_interface_static (gst_bin_type, GST_TYPE_CHILD_PROXY,
279         &child_proxy_info);
280
281     GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
282         "debugging info for the 'bin' container element");
283   }
284   return gst_bin_type;
285 }
286
287 static void
288 gst_bin_base_init (gpointer g_class)
289 {
290   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
291
292   gst_element_class_set_details (gstelement_class, &gst_bin_details);
293 }
294
295 static GstObject *
296 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
297     guint index)
298 {
299   GstObject *res;
300   GstBin *bin;
301
302   bin = GST_BIN_CAST (child_proxy);
303
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);
308
309   return res;
310 }
311
312 guint
313 gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
314 {
315   guint num;
316   GstBin *bin;
317
318   bin = GST_BIN_CAST (child_proxy);
319
320   GST_OBJECT_LOCK (bin);
321   num = bin->numchildren;
322   GST_OBJECT_UNLOCK (bin);
323
324   return num;
325 }
326
327 static void
328 gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
329 {
330   GstChildProxyInterface *iface = g_iface;
331
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;
334 }
335
336 static void
337 gst_bin_class_init (GstBinClass * klass)
338 {
339   GObjectClass *gobject_class;
340   GstObjectClass *gstobject_class;
341   GstElementClass *gstelement_class;
342   GError *err;
343
344   gobject_class = (GObjectClass *) klass;
345   gstobject_class = (GstObjectClass *) klass;
346   gstelement_class = (GstElementClass *) klass;
347
348   parent_class = g_type_class_peek_parent (klass);
349
350   /**
351    * GstBin::element-added:
352    * @bin: the #GstBin
353    * @element: the #GstElement that was added to the bin
354    *
355    * Will be emitted after the element was added to the bin.
356    */
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);
361   /**
362    * GstBin::element-removed:
363    * @bin: the #GstBin
364    * @element: the #GstElement that was removed from the bin
365    *
366    * Will be emitted after the element was removed from the bin.
367    */
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);
372
373   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
374
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);
379 #endif
380
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);
386 #endif
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);
390
391   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
392   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
393
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);
397
398   GST_DEBUG ("creating bin thread pool");
399   err = NULL;
400   klass->pool =
401       g_thread_pool_new ((GFunc) gst_bin_recalc_func, NULL, -1, FALSE, &err);
402   if (err != NULL) {
403     g_critical ("could alloc threadpool %s", err->message);
404   }
405 }
406
407 static void
408 gst_bin_init (GstBin * bin)
409 {
410   GstBus *bus;
411
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;
420
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",
425       bus);
426   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
427 }
428
429 static void
430 gst_bin_dispose (GObject * object)
431 {
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;
436
437   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
438
439   bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
440
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);
444
445   while (bin->children) {
446     gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
447   }
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)));
451   }
452
453   G_OBJECT_CLASS (parent_class)->dispose (object);
454 }
455
456 /**
457  * gst_bin_new:
458  * @name: the name of the new bin
459  *
460  * Creates a new bin with the given name.
461  *
462  * Returns: a new #GstBin
463  */
464 GstElement *
465 gst_bin_new (const gchar * name)
466 {
467   return gst_element_factory_make ("bin", name);
468 }
469
470 /* set the index on all elements in this bin
471  *
472  * MT safe
473  */
474 #ifndef GST_DISABLE_INDEX
475 static void
476 gst_bin_set_index_func (GstElement * element, GstIndex * index)
477 {
478   GstBin *bin;
479   GList *children;
480
481   bin = GST_BIN (element);
482
483   GST_OBJECT_LOCK (bin);
484   for (children = bin->children; children; children = g_list_next (children)) {
485     GstElement *child = GST_ELEMENT (children->data);
486
487     gst_element_set_index (child, index);
488   }
489   GST_OBJECT_UNLOCK (bin);
490 }
491 #endif
492
493 /* set the clock on all elements in this bin
494  *
495  * MT safe
496  */
497 static gboolean
498 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
499 {
500   GList *children;
501   GstBin *bin;
502   gboolean res = TRUE;
503
504   bin = GST_BIN (element);
505
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);
510
511       res &= gst_element_set_clock (child, clock);
512     }
513   }
514   GST_OBJECT_UNLOCK (bin);
515
516   return res;
517 }
518
519 /* get the clock for this bin by asking all of the children in this bin
520  *
521  * The ref of the returned clock in increased so unref after usage.
522  *
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.
525  *
526  * MT safe
527  */
528 static GstClock *
529 gst_bin_provide_clock_func (GstElement * element)
530 {
531   GstClock *result = NULL;
532   GstElement *provider = NULL;
533   GstBin *bin;
534   GstIterator *it;
535   gpointer val;
536   GstClock **provided_clock_p;
537   GstElement **clock_provider_p;
538
539   bin = GST_BIN (element);
540
541   GST_OBJECT_LOCK (bin);
542   if (!bin->clock_dirty)
543     goto not_dirty;
544
545   GST_DEBUG_OBJECT (bin, "finding new clock");
546
547   it = gst_bin_sort_iterator_new (bin);
548
549   while (it->next (it, &val) == GST_ITERATOR_OK) {
550     GstElement *child = GST_ELEMENT_CAST (val);
551     GstClock *clock;
552
553     clock = gst_element_provide_clock (child);
554     if (clock) {
555       GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s",
556           clock, GST_ELEMENT_NAME (child));
557       if (result) {
558         gst_object_unref (result);
559         gst_object_unref (provider);
560       }
561       result = clock;
562       provider = child;
563     } else {
564       gst_object_unref (child);
565     }
566   }
567
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,
575       result, provider);
576   /* Provider is not being returned to caller, just the result */
577   if (provider)
578     gst_object_unref (provider);
579   GST_OBJECT_UNLOCK (bin);
580
581   gst_iterator_free (it);
582
583   return result;
584
585 not_dirty:
586   {
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);
591
592     return result;
593   }
594 }
595
596 /*
597  * functions for manipulating cached messages
598  */
599 typedef struct
600 {
601   GstObject *src;
602   GstMessageType types;
603 } MessageFind;
604
605 /* check if a message is of given src and type */
606 static gint
607 message_check (GstMessage * message, MessageFind * target)
608 {
609   gboolean eq = TRUE;
610
611   if (target->src)
612     eq &= GST_MESSAGE_SRC (message) == target->src;
613   if (target->types)
614     eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
615
616   return (eq ? 0 : 1);
617 }
618
619 /* with LOCK, returns TRUE if message had a valid SRC, takes ref on
620  * the message. 
621  *
622  * A message that is cached and has the same SRC and type is replaced
623  * by the given message.
624  */
625 static gboolean
626 bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
627 {
628   GList *previous;
629   GstObject *src;
630   gboolean res = TRUE;
631   const gchar *name;
632
633   name = GST_MESSAGE_TYPE_NAME (message);
634
635   if ((src = GST_MESSAGE_SRC (message))) {
636     MessageFind find;
637
638     find.src = src;
639     find.types = types;
640
641     /* first find the previous message posted by this element */
642     previous = g_list_find_custom (bin->messages, &find,
643         (GCompareFunc) message_check);
644     if (previous) {
645       /* if we found a previous message, replace it */
646       gst_message_unref (previous->data);
647       previous->data = message;
648
649       GST_DEBUG_OBJECT (bin, "replace old message %s from %s",
650           name, GST_ELEMENT_NAME (src));
651     } else {
652       /* keep new message */
653       bin->messages = g_list_prepend (bin->messages, message);
654
655       GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s",
656           message, name, GST_ELEMENT_NAME (src));
657     }
658   } else {
659     GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing", name);
660     res = FALSE;
661     gst_message_unref (message);
662   }
663   return res;
664 }
665
666 /* with LOCK. Remove all messages of given types */
667 static void
668 bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types)
669 {
670   MessageFind find;
671   GList *walk, *next;
672
673   find.src = src;
674   find.types = types;
675
676   for (walk = bin->messages; walk; walk = next) {
677     GstMessage *message = (GstMessage *) walk->data;
678
679     next = g_list_next (walk);
680
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);
686     } else {
687       GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
688           "not deleting message of type %d", GST_MESSAGE_TYPE (message));
689     }
690   }
691 }
692
693
694 /* Check if the bin is EOS. We do this by scanning all sinks and
695  * checking if they posted an EOS message.
696  *
697  * call with bin LOCK */
698 static gboolean
699 is_eos (GstBin * bin)
700 {
701   gboolean result;
702   GList *walk;
703
704   result = TRUE;
705   for (walk = bin->children; walk; walk = g_list_next (walk)) {
706     GstElement *element;
707
708     element = GST_ELEMENT_CAST (walk->data);
709     if (bin_element_is_sink (element, bin) == 0) {
710       MessageFind find;
711
712       /* check if element posted EOS */
713       find.src = GST_OBJECT_CAST (element);
714       find.types = GST_MESSAGE_EOS;
715
716       if (g_list_find_custom (bin->messages, &find,
717               (GCompareFunc) message_check)) {
718         GST_DEBUG ("element posted EOS");
719       } else {
720         GST_DEBUG ("element did not post EOS yet");
721         result = FALSE;
722         break;
723       }
724     }
725   }
726   return result;
727 }
728
729 static void
730 unlink_pads (GstPad * pad)
731 {
732   GstPad *peer;
733
734   if ((peer = gst_pad_get_peer (pad))) {
735     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
736       gst_pad_unlink (pad, peer);
737     else
738       gst_pad_unlink (peer, pad);
739     gst_object_unref (peer);
740   }
741   gst_object_unref (pad);
742 }
743
744 /* vmethod that adds an element to a bin
745  *
746  * MT safe
747  */
748 static gboolean
749 gst_bin_add_func (GstBin * bin, GstElement * element)
750 {
751   gchar *elem_name;
752   GstIterator *it;
753   gboolean is_sink;
754   GstMessage *clock_message = NULL;
755
756   /* we obviously can't add ourself to ourself */
757   if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
758     goto adding_itself;
759
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);
765
766   GST_OBJECT_LOCK (bin);
767
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)))
773     goto duplicate_name;
774
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))))
778     goto had_parent;
779
780   /* if we add a sink we become a sink */
781   if (is_sink) {
782     GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink",
783         elem_name);
784     GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
785   }
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;
789     clock_message =
790         gst_message_new_clock_provide (GST_OBJECT_CAST (bin), NULL, TRUE);
791   }
792
793   bin->children = g_list_prepend (bin->children, element);
794   bin->numchildren++;
795   bin->children_cookie++;
796
797   /* distribute the bus */
798   gst_element_set_bus (element, bin->child_bus);
799
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);
808
809   if (clock_message) {
810     gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
811   }
812
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);
817
818   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
819       elem_name);
820   g_free (elem_name);
821
822   g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
823
824   return TRUE;
825
826   /* ERROR handling here */
827 adding_itself:
828   {
829     GST_OBJECT_LOCK (bin);
830     g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
831     GST_OBJECT_UNLOCK (bin);
832     return FALSE;
833   }
834 duplicate_name:
835   {
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);
839     g_free (elem_name);
840     return FALSE;
841   }
842 had_parent:
843   {
844     g_warning ("Element %s already has parent", elem_name);
845     GST_OBJECT_UNLOCK (bin);
846     g_free (elem_name);
847     return FALSE;
848   }
849 }
850
851
852 /**
853  * gst_bin_add:
854  * @bin: a #GstBin
855  * @element: the #GstElement to add
856  *
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.
859  *
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.
862  *
863  * MT safe.
864  *
865  * Returns: TRUE if the element could be added, FALSE if
866  * the bin does not want to accept the element.
867  */
868 gboolean
869 gst_bin_add (GstBin * bin, GstElement * element)
870 {
871   GstBinClass *bclass;
872   gboolean result;
873
874   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
875   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
876
877   bclass = GST_BIN_GET_CLASS (bin);
878
879   if (G_UNLIKELY (bclass->add_element == NULL))
880     goto no_function;
881
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)));
885
886   result = bclass->add_element (bin, element);
887
888   return result;
889
890   /* ERROR handling */
891 no_function:
892   {
893     g_warning ("adding elements to bin %s is not supported",
894         GST_ELEMENT_NAME (bin));
895     return FALSE;
896   }
897 }
898
899 /* remove an element from the bin
900  *
901  * MT safe
902  */
903 static gboolean
904 gst_bin_remove_func (GstBin * bin, GstElement * element)
905 {
906   gchar *elem_name;
907   GstIterator *it;
908   gboolean is_sink;
909   GstMessage *clock_message = NULL;
910
911   GST_OBJECT_LOCK (element);
912   /* Check if the element is already being removed and immediately
913    * return */
914   if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_UNPARENTING)))
915     goto already_removing;
916
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);
922
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);
927
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))
931     goto not_in_bin;
932
933   /* now remove the element from the list of elements */
934   bin->children = g_list_remove (bin->children, element);
935   bin->numchildren--;
936   bin->children_cookie++;
937
938   /* check if we removed a sink */
939   if (is_sink) {
940     GList *other_sink;
941
942     /* check if we removed the last sink */
943     other_sink = g_list_find_custom (bin->children,
944         bin, (GCompareFunc) bin_element_is_sink);
945     if (!other_sink) {
946       /* yups, we're not a sink anymore */
947       GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
948     }
949   }
950
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;
957     clock_message =
958         gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
959   }
960
961   bin->state_dirty = TRUE;
962   GST_OBJECT_UNLOCK (bin);
963
964   if (clock_message) {
965     gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
966   }
967
968   GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
969       elem_name);
970   g_free (elem_name);
971
972   gst_element_set_bus (element, NULL);
973
974   /* Clear the clock we provided to the element */
975   gst_element_set_clock (element, NULL);
976
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));
981
982   GST_OBJECT_LOCK (element);
983   GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_UNPARENTING);
984   GST_OBJECT_UNLOCK (element);
985
986   g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
987
988   /* element is really out of our control now */
989   gst_object_unref (element);
990
991   return TRUE;
992
993   /* ERROR handling */
994 not_in_bin:
995   {
996     g_warning ("Element %s is not in bin %s", elem_name,
997         GST_ELEMENT_NAME (bin));
998     GST_OBJECT_UNLOCK (bin);
999     g_free (elem_name);
1000     return FALSE;
1001   }
1002 already_removing:
1003   {
1004     GST_OBJECT_UNLOCK (element);
1005     return FALSE;
1006   }
1007 }
1008
1009 /**
1010  * gst_bin_remove:
1011  * @bin: a #GstBin
1012  * @element: the #GstElement to remove
1013  *
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.
1020  *
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.
1023  *
1024  * MT safe.
1025  *
1026  * Returns: TRUE if the element could be removed, FALSE if
1027  * the bin does not want to remove the element.
1028  */
1029 gboolean
1030 gst_bin_remove (GstBin * bin, GstElement * element)
1031 {
1032   GstBinClass *bclass;
1033   gboolean result;
1034
1035   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
1036   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1037
1038   bclass = GST_BIN_GET_CLASS (bin);
1039
1040   if (G_UNLIKELY (bclass->remove_element == NULL))
1041     goto no_function;
1042
1043   GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
1044       GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
1045
1046   result = bclass->remove_element (bin, element);
1047
1048   return result;
1049
1050   /* ERROR handling */
1051 no_function:
1052   {
1053     g_warning ("removing elements from bin %s is not supported",
1054         GST_ELEMENT_NAME (bin));
1055     return FALSE;
1056   }
1057 }
1058
1059 static GstIteratorItem
1060 iterate_child (GstIterator * it, GstElement * child)
1061 {
1062   gst_object_ref (child);
1063   return GST_ITERATOR_ITEM_PASS;
1064 }
1065
1066 /**
1067  * gst_bin_iterate_elements:
1068  * @bin: a #GstBin
1069  *
1070  * Gets an iterator for the elements in this bin.
1071  *
1072  * Each element yielded by the iterator will have its refcount increased, so
1073  * unref after use.
1074  *
1075  * MT safe.  Caller owns returned value.
1076  *
1077  * Returns: a #GstIterator of #GstElement, or NULL
1078  */
1079 GstIterator *
1080 gst_bin_iterate_elements (GstBin * bin)
1081 {
1082   GstIterator *result;
1083
1084   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1085
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
1089    * function. */
1090   gst_object_ref (bin);
1091   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1092       GST_OBJECT_GET_LOCK (bin),
1093       &bin->children_cookie,
1094       &bin->children,
1095       bin,
1096       (GstIteratorItemFunction) iterate_child,
1097       (GstIteratorDisposeFunction) gst_object_unref);
1098   GST_OBJECT_UNLOCK (bin);
1099
1100   return result;
1101 }
1102
1103 static GstIteratorItem
1104 iterate_child_recurse (GstIterator * it, GstElement * child)
1105 {
1106   gst_object_ref (child);
1107   if (GST_IS_BIN (child)) {
1108     GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
1109
1110     gst_iterator_push (it, other);
1111   }
1112   return GST_ITERATOR_ITEM_PASS;
1113 }
1114
1115 /**
1116  * gst_bin_iterate_recurse:
1117  * @bin: a #GstBin
1118  *
1119  * Gets an iterator for the elements in this bin.
1120  * This iterator recurses into GstBin children.
1121  *
1122  * Each element yielded by the iterator will have its refcount increased, so
1123  * unref after use.
1124  *
1125  * MT safe.  Caller owns returned value.
1126  *
1127  * Returns: a #GstIterator of #GstElement, or NULL
1128  */
1129 GstIterator *
1130 gst_bin_iterate_recurse (GstBin * bin)
1131 {
1132   GstIterator *result;
1133
1134   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1135
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
1139    * function. */
1140   gst_object_ref (bin);
1141   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1142       GST_OBJECT_GET_LOCK (bin),
1143       &bin->children_cookie,
1144       &bin->children,
1145       bin,
1146       (GstIteratorItemFunction) iterate_child_recurse,
1147       (GstIteratorDisposeFunction) gst_object_unref);
1148   GST_OBJECT_UNLOCK (bin);
1149
1150   return result;
1151 }
1152
1153 /* returns 0 when TRUE because this is a GCompareFunc */
1154 /* MT safe */
1155 static gint
1156 bin_element_is_sink (GstElement * child, GstBin * bin)
1157 {
1158   gboolean is_sink;
1159
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);
1164
1165   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1166       "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
1167
1168   GST_OBJECT_UNLOCK (child);
1169   return is_sink ? 0 : 1;
1170 }
1171
1172 static gint
1173 sink_iterator_filter (GstElement * child, GstBin * bin)
1174 {
1175   if (bin_element_is_sink (child, bin) == 0) {
1176     /* returns 0 because this is a GCompareFunc */
1177     return 0;
1178   } else {
1179     /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
1180        through */
1181     gst_object_unref (child);
1182     return 1;
1183   }
1184 }
1185
1186 /**
1187  * gst_bin_iterate_sinks:
1188  * @bin: a #GstBin
1189  *
1190  * Gets an iterator for all elements in the bin that have the
1191  * #GST_ELEMENT_IS_SINK flag set.
1192  *
1193  * Each element yielded by the iterator will have its refcount increased, so
1194  * unref after use.
1195  *
1196  * MT safe.  Caller owns returned value.
1197  *
1198  * Returns: a #GstIterator of #GstElement, or NULL
1199  */
1200 GstIterator *
1201 gst_bin_iterate_sinks (GstBin * bin)
1202 {
1203   GstIterator *children;
1204   GstIterator *result;
1205
1206   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1207
1208   children = gst_bin_iterate_elements (bin);
1209   result = gst_iterator_filter (children,
1210       (GCompareFunc) sink_iterator_filter, bin);
1211
1212   return result;
1213 }
1214
1215 /* returns 0 when TRUE because this is a GCompareFunc */
1216 /* MT safe */
1217 static gint
1218 bin_element_is_src (GstElement * child, GstBin * bin)
1219 {
1220   gboolean is_src = FALSE;
1221
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) {
1227     is_src = TRUE;
1228   }
1229
1230   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1231       "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not");
1232
1233   GST_OBJECT_UNLOCK (child);
1234   return is_src ? 0 : 1;
1235 }
1236
1237 static gint
1238 src_iterator_filter (GstElement * child, GstBin * bin)
1239 {
1240   if (bin_element_is_src (child, bin) == 0) {
1241     /* returns 0 because this is a GCompareFunc */
1242     return 0;
1243   } else {
1244     /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
1245        through */
1246     gst_object_unref (child);
1247     return 1;
1248   }
1249 }
1250
1251 /**
1252  * gst_bin_iterate_sources:
1253  * @bin: a #GstBin
1254  *
1255  * Gets an iterator for all elements in the bin that have no sinkpads and have 
1256  * the #GST_ELEMENT_IS_SINK flag unset.
1257  *
1258  * Each element yielded by the iterator will have its refcount increased, so
1259  * unref after use.
1260  *
1261  * MT safe.  Caller owns returned value.
1262  *
1263  * Returns: a #GstIterator of #GstElement, or NULL
1264  */
1265 GstIterator *
1266 gst_bin_iterate_sources (GstBin * bin)
1267 {
1268   GstIterator *children;
1269   GstIterator *result;
1270
1271   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1272
1273   children = gst_bin_iterate_elements (bin);
1274   result = gst_iterator_filter (children,
1275       (GCompareFunc) src_iterator_filter, bin);
1276
1277   return result;
1278 }
1279
1280 /*
1281  * MT safe
1282  */
1283 static GstStateChangeReturn
1284 gst_bin_get_state_func (GstElement * element, GstState * state,
1285     GstState * pending, GstClockTime timeout)
1286 {
1287   GstBin *bin = GST_BIN (element);
1288   GstStateChangeReturn ret;
1289
1290   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "getting state");
1291
1292   /* do a non forced recalculation of the state */
1293   gst_bin_recalc_state (bin, FALSE);
1294
1295   ret = parent_class->get_state (element, state, pending, timeout);
1296
1297   return ret;
1298 }
1299
1300 static void
1301 gst_bin_recalc_state (GstBin * bin, gboolean force)
1302 {
1303   GstStateChangeReturn ret;
1304   GList *children;
1305   guint32 children_cookie;
1306   guint32 state_cookie;
1307   gboolean have_no_preroll;
1308   gboolean have_async;
1309
1310   ret = GST_STATE_CHANGE_SUCCESS;
1311
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 */
1315   if (force)
1316     bin->state_dirty = TRUE;
1317
1318   /* no point in scanning if nothing changed and it's no forced recalc */
1319   if (!bin->state_dirty)
1320     goto not_dirty;
1321
1322   /* no point in having two scans run concurrently */
1323   if (bin->polling)
1324     goto was_polling;
1325
1326   bin->polling = TRUE;
1327   state_cookie = GST_ELEMENT_CAST (bin)->state_cookie;
1328
1329   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "recalc state");
1330
1331 restart:
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;
1335
1336   have_no_preroll = FALSE;
1337   have_async = FALSE;
1338
1339   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "checking element states");
1340
1341   /* scan all element states with a zero timeout so we don't block on
1342    * anything */
1343   children = bin->children;
1344   children_cookie = bin->children_cookie;
1345   while (children) {
1346     GstElement *child = GST_ELEMENT_CAST (children->data);
1347
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);
1352
1353     ret = gst_element_get_state (child, NULL, NULL, 0);
1354
1355     gst_object_unref (child);
1356
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");
1364       goto restart;
1365     }
1366     if (state_cookie != GST_ELEMENT_CAST (bin)->state_cookie) {
1367       GST_DEBUG_OBJECT (bin, "concurrent state change");
1368       goto concurrent_state;
1369     }
1370     if (bin->state_dirty) {
1371       GST_DEBUG_OBJECT (bin, "state dirty again, restarting recalc");
1372       goto restart;
1373     }
1374
1375     switch (ret) {
1376       case GST_STATE_CHANGE_FAILURE:
1377         /* report FAILURE  immediatly */
1378         goto done;
1379       case GST_STATE_CHANGE_NO_PREROLL:
1380         /* we have to continue scanning as there might be
1381          * ERRORS too */
1382         have_no_preroll = TRUE;
1383         break;
1384       case GST_STATE_CHANGE_ASYNC:
1385         /* we have to continue scanning as there might be
1386          * ERRORS too */
1387         have_async = TRUE;
1388         break;
1389       default:
1390         break;
1391     }
1392     children = g_list_next (children);
1393   }
1394   /* if we get here, we have no FAILURES */
1395
1396   /* if we have NO_PREROLL, return that */
1397   if (have_no_preroll) {
1398     ret = GST_STATE_CHANGE_NO_PREROLL;
1399   }
1400   /* else return ASYNC if async elements where found. */
1401   else if (have_async) {
1402     ret = GST_STATE_CHANGE_ASYNC;
1403   }
1404
1405 done:
1406   bin->polling = FALSE;
1407   GST_OBJECT_UNLOCK (bin);
1408
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. */
1413   switch (ret) {
1414     case GST_STATE_CHANGE_SUCCESS:
1415     case GST_STATE_CHANGE_NO_PREROLL:
1416       ret = gst_element_continue_state (GST_ELEMENT_CAST (bin), ret);
1417       break;
1418     case GST_STATE_CHANGE_ASYNC:
1419       gst_element_lost_state (GST_ELEMENT_CAST (bin));
1420       break;
1421     case GST_STATE_CHANGE_FAILURE:
1422       gst_element_abort_state (GST_ELEMENT_CAST (bin));
1423       break;
1424     default:
1425       goto unknown_state;
1426   }
1427
1428   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "bin RETURN is now %s",
1429       gst_element_state_change_return_get_name (ret));
1430
1431   return;
1432
1433 not_dirty:
1434   {
1435     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "not dirty");
1436     GST_OBJECT_UNLOCK (bin);
1437     return;
1438   }
1439 was_polling:
1440   {
1441     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "was polling");
1442     GST_OBJECT_UNLOCK (bin);
1443     return;
1444   }
1445 concurrent_state:
1446   {
1447     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "concurrent_state");
1448     bin->polling = FALSE;
1449     GST_OBJECT_UNLOCK (bin);
1450     return;
1451   }
1452 unknown_state:
1453   {
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);
1460     return;
1461   }
1462 }
1463
1464 /***********************************************
1465  * Topologically sorted iterator
1466  * see http://en.wikipedia.org/wiki/Topological_sorting
1467  *
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
1473  * changed next.
1474  * When all elements are handled the algorithm stops.
1475  */
1476 typedef struct _GstBinSortIterator
1477 {
1478   GstIterator it;
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;
1486
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)
1492
1493 /* add element to queue of next elements in the iterator.
1494  * We push at the tail to give higher priority elements a
1495  * chance first */
1496 static void
1497 add_to_queue (GstBinSortIterator * bit, GstElement * element)
1498 {
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);
1503 }
1504
1505 /* clear the queue, unref all objects as we took a ref when
1506  * we added them to the queue */
1507 static void
1508 clear_queue (GQueue * queue)
1509 {
1510   gpointer p;
1511
1512   while ((p = g_queue_pop_head (queue)))
1513     gst_object_unref (p);
1514 }
1515
1516 /* set all degrees to 0. Elements marked as a sink are
1517  * added to the queue immediatly. */
1518 static void
1519 reset_degree (GstElement * element, GstBinSortIterator * bit)
1520 {
1521   gboolean is_sink;
1522
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);
1527
1528   if (is_sink) {
1529     add_to_queue (bit, element);
1530   } else {
1531     /* others are marked with 0 and handled when sinks are done */
1532     HASH_SET_DEGREE (bit, element, 0);
1533   }
1534 }
1535
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.
1539  *
1540  * We have to make sure not to cross the bin boundary this element
1541  * belongs to.
1542  */
1543 static void
1544 update_degree (GstElement * element, GstBinSortIterator * bit)
1545 {
1546   gboolean linked = FALSE;
1547
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 */
1553     GList *pads;
1554
1555     for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
1556       GstPad *peer;
1557
1558       if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
1559         GstElement *peer_element;
1560
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;
1567
1568             old_deg = HASH_GET_DEGREE (bit, peer_element);
1569             new_deg = old_deg + bit->mode;
1570
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));
1575
1576             /* update degree */
1577             if (new_deg == 0) {
1578               /* degree hit 0, add to queue */
1579               add_to_queue (bit, peer_element);
1580             } else {
1581               HASH_SET_DEGREE (bit, peer_element, new_deg);
1582             }
1583             linked = TRUE;
1584           }
1585           GST_OBJECT_UNLOCK (peer_element);
1586           gst_object_unref (peer_element);
1587         }
1588         gst_object_unref (peer);
1589       }
1590     }
1591   }
1592   if (!linked) {
1593     GST_DEBUG_OBJECT (bit->bin, "element %s not linked on any sinkpads",
1594         GST_ELEMENT_NAME (element));
1595   }
1596   GST_OBJECT_UNLOCK (element);
1597 }
1598
1599 /* find the next best element not handled yet. This is the one
1600  * with the lowest non-negative degree */
1601 static void
1602 find_element (GstElement * element, GstBinSortIterator * bit)
1603 {
1604   gint degree;
1605
1606   /* element is already handled */
1607   if ((degree = HASH_GET_DEGREE (bit, element)) < 0)
1608     return;
1609
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;
1614   }
1615 }
1616
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)
1621 {
1622   GstBin *bin = bit->bin;
1623
1624   /* empty queue, we have to find a next best element */
1625   if (g_queue_is_empty (bit->queue)) {
1626     GstElement *best;
1627
1628     bit->best = NULL;
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 !!");
1635       }
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);
1641       *result = best;
1642     } else {
1643       GST_DEBUG_OBJECT (bin, "queue empty, elements exhausted");
1644       /* no more unhandled elements, we are done */
1645       return GST_ITERATOR_DONE;
1646     }
1647   } else {
1648     /* everything added to the queue got reffed */
1649     *result = g_queue_pop_head (bit->queue);
1650   }
1651
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);
1655
1656   return GST_ITERATOR_OK;
1657 }
1658
1659 /* clear queues, recalculate the degrees and restart. */
1660 static void
1661 gst_bin_sort_iterator_resync (GstBinSortIterator * bit)
1662 {
1663   GstBin *bin = bit->bin;
1664
1665   GST_DEBUG_OBJECT (bin, "resync");
1666   clear_queue (bit->queue);
1667   /* reset degrees */
1668   g_list_foreach (bin->children, (GFunc) reset_degree, bit);
1669   /* calc degrees, incrementing */
1670   bit->mode = 1;
1671   g_list_foreach (bin->children, (GFunc) update_degree, bit);
1672   /* for the rest of the function we decrement the degrees */
1673   bit->mode = -1;
1674 }
1675
1676 /* clear queues, unref bin and free iterator. */
1677 static void
1678 gst_bin_sort_iterator_free (GstBinSortIterator * bit)
1679 {
1680   GstBin *bin = bit->bin;
1681
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);
1687   g_free (bit);
1688 }
1689
1690 /* should be called with the bin LOCK held */
1691 static GstIterator *
1692 gst_bin_sort_iterator_new (GstBin * bin)
1693 {
1694   GstBinSortIterator *result;
1695
1696   /* we don't need an ItemFunction because we ref the items in the _next
1697    * method already */
1698   result = (GstBinSortIterator *)
1699       gst_iterator_new (sizeof (GstBinSortIterator),
1700       GST_TYPE_ELEMENT,
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);
1710   result->bin = bin;
1711   gst_bin_sort_iterator_resync (result);
1712
1713   return (GstIterator *) result;
1714 }
1715
1716 /**
1717  * gst_bin_iterate_sorted:
1718  * @bin: a #GstBin
1719  *
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.
1723  *
1724  * This function is used internally to perform the state changes
1725  * of the bin elements.
1726  *
1727  * Each element yielded by the iterator will have its refcount increased, so
1728  * unref after use.
1729  *
1730  * MT safe.  Caller owns returned value.
1731  *
1732  * Returns: a #GstIterator of #GstElement, or NULL
1733  */
1734 GstIterator *
1735 gst_bin_iterate_sorted (GstBin * bin)
1736 {
1737   GstIterator *result;
1738
1739   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1740
1741   GST_OBJECT_LOCK (bin);
1742   result = gst_bin_sort_iterator_new (bin);
1743   GST_OBJECT_UNLOCK (bin);
1744
1745   return result;
1746 }
1747
1748 static GstStateChangeReturn
1749 gst_bin_element_set_state (GstBin * bin, GstElement * element, GstState pending)
1750 {
1751   GstStateChangeReturn ret;
1752   gboolean locked;
1753
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);
1758
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;
1764     goto done;
1765   }
1766
1767   /* change state */
1768   ret = gst_element_set_state (element, pending);
1769
1770 done:
1771   return ret;
1772 }
1773
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. */
1778 static gboolean
1779 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
1780 {
1781   if (!gst_pad_set_active (pad, *active))
1782     g_value_set_boolean (ret, FALSE);
1783   else if (!*active)
1784     gst_pad_set_caps (pad, NULL);
1785
1786   /* unref the object that was reffed for us by _fold */
1787   gst_object_unref (pad);
1788   return TRUE;
1789 }
1790
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. */
1794 static gboolean
1795 iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data)
1796 {
1797   GstIteratorResult ires;
1798   GValue ret = { 0 };
1799
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);
1803
1804   while (1) {
1805     ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) activate_pads,
1806         &ret, user_data);
1807     switch (ires) {
1808       case GST_ITERATOR_RESYNC:
1809         /* need to reset the result again */
1810         g_value_set_boolean (&ret, TRUE);
1811         gst_iterator_resync (iter);
1812         break;
1813       case GST_ITERATOR_DONE:
1814         /* all pads iterated, return collected value */
1815         goto done;
1816       default:
1817         /* iterator returned _ERROR or premature end with _OK, 
1818          * mark an error and exit */
1819         g_value_set_boolean (&ret, FALSE);
1820         goto done;
1821     }
1822   }
1823 done:
1824   /* return collected value */
1825   return g_value_get_boolean (&ret);
1826 }
1827
1828 /* is called with STATE_LOCK
1829  */
1830 static gboolean
1831 gst_bin_src_pads_activate (GstBin * bin, gboolean active)
1832 {
1833   GstIterator *iter;
1834   gboolean fold_ok;
1835
1836   GST_DEBUG_OBJECT (bin, "src_pads_activate with active %d", active);
1837
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))
1842     goto failed;
1843
1844   GST_DEBUG_OBJECT (bin, "pads_activate successful");
1845
1846   return TRUE;
1847
1848   /* ERRORS */
1849 failed:
1850   {
1851     GST_DEBUG_OBJECT (bin, "source pads_activate failed");
1852     return FALSE;
1853   }
1854 }
1855 static GstStateChangeReturn
1856 gst_bin_change_state_func (GstElement * element, GstStateChange transition)
1857 {
1858   GstBin *bin;
1859   GstStateChangeReturn ret;
1860   GstState current, next;
1861   gboolean have_async;
1862   gboolean have_no_preroll;
1863   GstClockTime base_time;
1864   GstIterator *it;
1865   gboolean done;
1866
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);
1870
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));
1874
1875   bin = GST_BIN_CAST (element);
1876
1877   switch (next) {
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;
1887       break;
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;
1897       break;
1898     case GST_STATE_NULL:
1899       if (current == GST_STATE_READY)
1900         if (!(gst_bin_src_pads_activate (bin, FALSE)))
1901           goto activate_failure;
1902       break;
1903     default:
1904       break;
1905   }
1906
1907   /* iterate in state change order */
1908   it = gst_bin_iterate_sorted (bin);
1909
1910 restart:
1911   /* take base_time */
1912   base_time = gst_element_get_base_time (element);
1913
1914   have_async = FALSE;
1915   have_no_preroll = FALSE;
1916
1917   done = FALSE;
1918   while (!done) {
1919     gpointer data;
1920
1921     switch (gst_iterator_next (it, &data)) {
1922       case GST_ITERATOR_OK:
1923       {
1924         GstElement *child;
1925
1926         child = GST_ELEMENT_CAST (data);
1927
1928         /* set base_time on child */
1929         gst_element_set_base_time (child, base_time);
1930
1931         /* set state now */
1932         ret = gst_bin_element_set_state (bin, child, next);
1933
1934         switch (ret) {
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));
1940             break;
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));
1945             have_async = TRUE;
1946             break;
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);
1953             goto done;
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;
1960             break;
1961           default:
1962             g_assert_not_reached ();
1963             break;
1964         }
1965         gst_object_unref (child);
1966         break;
1967       }
1968       case GST_ITERATOR_RESYNC:
1969         GST_CAT_DEBUG (GST_CAT_STATES, "iterator doing resync");
1970         gst_iterator_resync (it);
1971         goto restart;
1972       default:
1973       case GST_ITERATOR_DONE:
1974         GST_CAT_DEBUG (GST_CAT_STATES, "iterator done");
1975         done = TRUE;
1976         break;
1977     }
1978   }
1979
1980   ret = parent_class->change_state (element, transition);
1981   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
1982     goto done;
1983
1984   if (have_no_preroll) {
1985     ret = GST_STATE_CHANGE_NO_PREROLL;
1986   } else if (have_async) {
1987     ret = GST_STATE_CHANGE_ASYNC;
1988   }
1989
1990 done:
1991   gst_iterator_free (it);
1992
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);
1998
1999   return ret;
2000
2001   /* ERRORS */
2002 activate_failure:
2003   {
2004     GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element,
2005         "failure (de)activating src pads");
2006     return GST_STATE_CHANGE_FAILURE;
2007   }
2008 }
2009
2010 /*
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
2013  * event-direction.
2014  *
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.
2018  */
2019 static gboolean
2020 gst_bin_send_event (GstElement * element, GstEvent * event)
2021 {
2022   GstBin *bin = GST_BIN (element);
2023   GstIterator *iter;
2024   gboolean res = TRUE;
2025   gboolean done = FALSE;
2026
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));
2031   } else {
2032     iter = gst_bin_iterate_sinks (bin);
2033     GST_DEBUG_OBJECT (bin, "Sending %s event to sink children",
2034         GST_EVENT_TYPE_NAME (event));
2035   }
2036
2037   while (!done) {
2038     gpointer data;
2039
2040     switch (gst_iterator_next (iter, &data)) {
2041       case GST_ITERATOR_OK:
2042       {
2043         GstElement *child;
2044
2045         gst_event_ref (event);
2046         child = GST_ELEMENT_CAST (data);
2047         res &= gst_element_send_event (child, event);
2048         gst_object_unref (child);
2049         break;
2050       }
2051       case GST_ITERATOR_RESYNC:
2052         gst_iterator_resync (iter);
2053         res = TRUE;
2054         break;
2055       case GST_ITERATOR_DONE:
2056         done = TRUE;
2057         break;
2058       case GST_ITERATOR_ERROR:
2059         g_assert_not_reached ();
2060         break;
2061     }
2062   }
2063   gst_iterator_free (iter);
2064   gst_event_unref (event);
2065
2066   return res;
2067 }
2068
2069 static void
2070 gst_bin_recalc_func (GstBin * bin, gpointer data)
2071 {
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);
2078 }
2079
2080 static GstBusSyncReply
2081 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
2082 {
2083
2084   GstBinClass *bclass;
2085
2086   bclass = GST_BIN_GET_CLASS (bin);
2087   if (bclass->handle_message)
2088     bclass->handle_message (bin, message);
2089   else
2090     gst_message_unref (message);
2091
2092   return GST_BUS_DROP;
2093 }
2094
2095 /* handle child messages:
2096  *
2097  * This method is called synchronously when a child posts a message on
2098  * the internal bus. 
2099  *
2100  * GST_MESSAGE_EOS: This message is only posted by sinks
2101  *     in the PLAYING state. If all sinks posted the EOS message, post
2102  *     one upwards.
2103  *
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.
2108  *
2109  * GST_MESSAGE_SEGMENT_START: just collect, never forward upwards. If an
2110  *     element posts segment_start twice, only the last message is kept.
2111  *
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.
2115  *
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
2122  *     duration changes.
2123  *
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 
2128  *     our parent. 
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.
2133  *
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
2140  *     the parent.
2141  *
2142  * OTHER: post upwards.
2143  */
2144 static void
2145 gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
2146 {
2147   GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %s",
2148       message, GST_MESSAGE_TYPE_NAME (message));
2149
2150   switch (GST_MESSAGE_TYPE (message)) {
2151     case GST_MESSAGE_EOS:
2152     {
2153       gboolean eos;
2154
2155       /* collect all eos messages from the children */
2156       GST_OBJECT_LOCK (bin);
2157       bin_replace_message (bin, message, GST_MESSAGE_EOS);
2158       eos = is_eos (bin);
2159       GST_OBJECT_UNLOCK (bin);
2160
2161       /* if we are completely EOS, we forward an EOS message */
2162       if (eos) {
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)));
2166       }
2167       break;
2168     }
2169     case GST_MESSAGE_STATE_DIRTY:
2170     {
2171       GstObject *src;
2172       GstBinClass *klass;
2173
2174       src = GST_MESSAGE_SRC (message);
2175
2176       GST_DEBUG_OBJECT (bin, "%s gave state dirty", GST_ELEMENT_NAME (src));
2177
2178       /* mark the bin dirty */
2179       GST_OBJECT_LOCK (bin);
2180       GST_DEBUG_OBJECT (bin, "marking dirty");
2181       bin->state_dirty = TRUE;
2182
2183       if (GST_OBJECT_PARENT (bin))
2184         goto not_toplevel;
2185
2186       /* free message */
2187       gst_message_unref (message);
2188
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);
2194       } else {
2195         GST_DEBUG_OBJECT (bin,
2196             "state recalc already in progress, not pushing new recalc");
2197       }
2198       GST_OBJECT_UNLOCK (bin);
2199       break;
2200
2201       /* non toplevel bins just forward the message and don't start
2202        * a recalc themselves */
2203     not_toplevel:
2204       {
2205         GST_OBJECT_UNLOCK (bin);
2206         GST_DEBUG_OBJECT (bin, "not toplevel, forwarding");
2207         goto forward;
2208       }
2209     }
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);
2216       break;
2217     case GST_MESSAGE_SEGMENT_DONE:
2218     {
2219       MessageFind find;
2220       gboolean post = FALSE;
2221       GstFormat format;
2222       gint64 position;
2223
2224       gst_message_parse_segment_done (message, &format, &position);
2225
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. */
2230
2231       /* we don't care who still has a pending segment start */
2232       find.src = NULL;
2233       find.types = GST_MESSAGE_SEGMENT_START;
2234
2235       if (!g_list_find_custom (bin->messages, &find,
2236               (GCompareFunc) message_check)) {
2237         /* nothing found */
2238         post = TRUE;
2239         /* remove all old segment_done messages */
2240         bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
2241       }
2242       GST_OBJECT_UNLOCK (bin);
2243       if (post) {
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),
2247                 format, position));
2248       }
2249       break;
2250     }
2251     case GST_MESSAGE_DURATION:
2252     {
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);
2258       goto forward;
2259     }
2260     case GST_MESSAGE_CLOCK_LOST:
2261     {
2262       GstClock **provided_clock_p;
2263       GstElement **clock_provider_p;
2264       gboolean playing, provided, forward;
2265       GstClock *clock;
2266
2267       gst_message_parse_clock_lost (message, &clock);
2268
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;
2276       if (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);
2284       }
2285       GST_DEBUG_OBJECT (bin, "provided %d, playing %d, forward %d",
2286           provided, playing, forward);
2287       GST_OBJECT_UNLOCK (bin);
2288
2289       if (forward)
2290         goto forward;
2291
2292       /* free message */
2293       gst_message_unref (message);
2294       break;
2295     }
2296     case GST_MESSAGE_CLOCK_PROVIDE:
2297     {
2298       gboolean forward;
2299
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);
2306
2307       if (forward)
2308         goto forward;
2309
2310       /* free message */
2311       gst_message_unref (message);
2312       break;
2313     }
2314     default:
2315       goto forward;
2316   }
2317   return;
2318
2319 forward:
2320   {
2321     /* Send all other messages upward */
2322     GST_DEBUG_OBJECT (bin, "posting message upward");
2323     gst_element_post_message (GST_ELEMENT_CAST (bin), message);
2324     return;
2325   }
2326 }
2327
2328 /* generic struct passed to all query fold methods */
2329 typedef struct
2330 {
2331   GstQuery *query;
2332   gint64 min;
2333   gint64 max;
2334   gboolean live;
2335 } QueryFold;
2336
2337 typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold);
2338 typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold);
2339
2340 /* for duration/position we collect all durations/positions and take 
2341  * the MAX of all valid results */
2342 static void
2343 bin_query_min_max_init (GstBin * bin, QueryFold * fold)
2344 {
2345   fold->min = 0;
2346   fold->max = -1;
2347   fold->live = FALSE;
2348 }
2349
2350 static gboolean
2351 bin_query_duration_fold (GstElement * item, GValue * ret, QueryFold * fold)
2352 {
2353   if (gst_element_query (item, fold->query)) {
2354     gint64 duration;
2355
2356     g_value_set_boolean (ret, TRUE);
2357
2358     gst_query_parse_duration (fold->query, NULL, &duration);
2359
2360     GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
2361
2362     if (duration > fold->max)
2363       fold->max = duration;
2364   }
2365
2366   gst_object_unref (item);
2367   return TRUE;
2368 }
2369 static void
2370 bin_query_duration_done (GstBin * bin, QueryFold * fold)
2371 {
2372   GstFormat format;
2373
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);
2377
2378   GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
2379
2380 #ifdef DURATION_CACHING
2381   /* and cache now */
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);
2386 #endif
2387 }
2388
2389 static gboolean
2390 bin_query_position_fold (GstElement * item, GValue * ret, QueryFold * fold)
2391 {
2392   if (gst_element_query (item, fold->query)) {
2393     gint64 position;
2394
2395     g_value_set_boolean (ret, TRUE);
2396
2397     gst_query_parse_position (fold->query, NULL, &position);
2398
2399     GST_DEBUG_OBJECT (item, "got position %" G_GINT64_FORMAT, position);
2400
2401     if (position > fold->max)
2402       fold->max = position;
2403   }
2404
2405   gst_object_unref (item);
2406   return TRUE;
2407 }
2408 static void
2409 bin_query_position_done (GstBin * bin, QueryFold * fold)
2410 {
2411   GstFormat format;
2412
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);
2416
2417   GST_DEBUG_OBJECT (bin, "max position %" G_GINT64_FORMAT, fold->max);
2418 }
2419
2420 static gboolean
2421 bin_query_latency_fold (GstElement * item, GValue * ret, QueryFold * fold)
2422 {
2423   if (gst_element_query (item, fold->query)) {
2424     GstClockTime min, max;
2425     gboolean live;
2426
2427     g_value_set_boolean (ret, TRUE);
2428
2429     gst_query_parse_latency (fold->query, &live, &min, &max);
2430
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);
2434
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)
2438       fold->min = min;
2439     if (fold->max == -1)
2440       fold->max = max;
2441     else if (max < fold->max)
2442       fold->max = max;
2443     if (fold->live == FALSE)
2444       fold->live = live;
2445   }
2446
2447   gst_object_unref (item);
2448   return TRUE;
2449 }
2450 static void
2451 bin_query_latency_done (GstBin * bin, QueryFold * fold)
2452 {
2453   /* store max in query result */
2454   gst_query_set_latency (fold->query, fold->live, fold->min, fold->max);
2455
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),
2459       fold->live);
2460 }
2461
2462
2463 /* generic fold, return first valid result */
2464 static gboolean
2465 bin_query_generic_fold (GstElement * item, GValue * ret, QueryFold * fold)
2466 {
2467   gboolean res;
2468
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);
2472   }
2473
2474   gst_object_unref (item);
2475
2476   /* and stop as soon as we have a valid result */
2477   return !res;
2478 }
2479
2480 static gboolean
2481 gst_bin_query (GstElement * element, GstQuery * query)
2482 {
2483   GstBin *bin = GST_BIN (element);
2484   GstIterator *iter;
2485   gboolean res = FALSE;
2486   GstIteratorFoldFunction fold_func;
2487   QueryInitFunction fold_init = NULL;
2488   QueryDoneFunction fold_done = NULL;
2489   QueryFold fold_data;
2490   GValue ret = { 0 };
2491
2492   switch (GST_QUERY_TYPE (query)) {
2493     case GST_QUERY_DURATION:
2494     {
2495 #ifdef DURATION_CACHING
2496       GList *cached;
2497       GstFormat qformat;
2498
2499       gst_query_parse_duration (query, &qformat, NULL);
2500
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;
2505
2506         if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION &&
2507             GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) {
2508           GstFormat format;
2509           gint64 duration;
2510
2511           gst_message_parse_duration (message, &format, &duration);
2512
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,
2516                 duration);
2517             GST_OBJECT_UNLOCK (bin);
2518
2519             gst_query_set_duration (query, qformat, duration);
2520             res = TRUE;
2521             goto exit;
2522           }
2523         }
2524       }
2525       GST_OBJECT_UNLOCK (bin);
2526 #endif
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;
2531       break;
2532     }
2533     case GST_QUERY_POSITION:
2534     {
2535       fold_func = (GstIteratorFoldFunction) bin_query_position_fold;
2536       fold_init = bin_query_min_max_init;
2537       fold_done = bin_query_position_done;
2538       break;
2539     }
2540     case GST_QUERY_LATENCY:
2541     {
2542       fold_func = (GstIteratorFoldFunction) bin_query_latency_fold;
2543       fold_init = bin_query_min_max_init;
2544       fold_done = bin_query_latency_done;
2545       break;
2546     }
2547     default:
2548       fold_func = (GstIteratorFoldFunction) bin_query_generic_fold;
2549       break;
2550   }
2551
2552   fold_data.query = query;
2553
2554   g_value_init (&ret, G_TYPE_BOOLEAN);
2555   g_value_set_boolean (&ret, FALSE);
2556
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));
2560
2561   if (fold_init)
2562     fold_init (bin, &fold_data);
2563
2564   while (TRUE) {
2565     GstIteratorResult ires;
2566
2567     ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
2568
2569     switch (ires) {
2570       case GST_ITERATOR_RESYNC:
2571         gst_iterator_resync (iter);
2572         if (fold_init)
2573           fold_init (bin, &fold_data);
2574         g_value_set_boolean (&ret, FALSE);
2575         break;
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);
2581         goto done;
2582       default:
2583         res = FALSE;
2584         goto done;
2585     }
2586   }
2587 done:
2588   gst_iterator_free (iter);
2589
2590 #ifdef DURATION_CACHING
2591 exit:
2592 #endif
2593   GST_DEBUG_OBJECT (bin, "query %p result %d", query, res);
2594
2595   return res;
2596 }
2597
2598 static gint
2599 compare_name (GstElement * element, const gchar * name)
2600 {
2601   gint eq;
2602
2603   GST_OBJECT_LOCK (element);
2604   eq = strcmp (GST_ELEMENT_NAME (element), name);
2605   GST_OBJECT_UNLOCK (element);
2606
2607   if (eq != 0) {
2608     gst_object_unref (element);
2609   }
2610   return eq;
2611 }
2612
2613 /**
2614  * gst_bin_get_by_name:
2615  * @bin: a #GstBin
2616  * @name: the element name to search for
2617  *
2618  * Gets the element with the given name from a bin. This
2619  * function recurses into child bins.
2620  *
2621  * Returns NULL if no element with the given name is found in the bin.
2622  *
2623  * MT safe.  Caller owns returned reference.
2624  *
2625  * Returns: the #GstElement with the given name, or NULL
2626  */
2627 GstElement *
2628 gst_bin_get_by_name (GstBin * bin, const gchar * name)
2629 {
2630   GstIterator *children;
2631   GstIterator *result;
2632
2633   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2634
2635   GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
2636       GST_ELEMENT_NAME (bin), name);
2637
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);
2642
2643   return GST_ELEMENT_CAST (result);
2644 }
2645
2646 /**
2647  * gst_bin_get_by_name_recurse_up:
2648  * @bin: a #GstBin
2649  * @name: the element name to search for
2650  *
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.
2653  *
2654  * Returns NULL if:
2655  * - no element with the given name is found in the bin
2656  *
2657  * MT safe.  Caller owns returned reference.
2658  *
2659  * Returns: the #GstElement with the given name, or NULL
2660  */
2661 GstElement *
2662 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
2663 {
2664   GstElement *result;
2665
2666   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2667   g_return_val_if_fail (name != NULL, NULL);
2668
2669   result = gst_bin_get_by_name (bin, name);
2670
2671   if (!result) {
2672     GstObject *parent;
2673
2674     parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
2675     if (parent) {
2676       if (GST_IS_BIN (parent)) {
2677         result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
2678       }
2679       gst_object_unref (parent);
2680     }
2681   }
2682
2683   return result;
2684 }
2685
2686 static gint
2687 compare_interface (GstElement * element, gpointer interface)
2688 {
2689   GType interface_type = (GType) interface;
2690   gint ret;
2691
2692   if (G_TYPE_CHECK_INSTANCE_TYPE (element, interface_type)) {
2693     ret = 0;
2694   } else {
2695     /* we did not find the element, need to release the ref
2696      * added by the iterator */
2697     gst_object_unref (element);
2698     ret = 1;
2699   }
2700   return ret;
2701 }
2702
2703 /**
2704  * gst_bin_get_by_interface:
2705  * @bin: a #GstBin
2706  * @iface: the #GType of an interface
2707  *
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.
2713  *
2714  * MT safe.  Caller owns returned reference.
2715  *
2716  * Returns: A #GstElement inside the bin implementing the interface
2717  */
2718 GstElement *
2719 gst_bin_get_by_interface (GstBin * bin, GType iface)
2720 {
2721   GstIterator *children;
2722   gpointer result;
2723
2724   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2725   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
2726
2727   children = gst_bin_iterate_recurse (bin);
2728   result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
2729       (gpointer) iface);
2730   gst_iterator_free (children);
2731
2732   return GST_ELEMENT_CAST (result);
2733 }
2734
2735 /**
2736  * gst_bin_iterate_all_by_interface:
2737  * @bin: a #GstBin
2738  * @iface: the #GType of an interface
2739  *
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.
2744  *
2745  * Each element yielded by the iterator will have its refcount increased, so
2746  * unref after use.
2747  *
2748  * MT safe.  Caller owns returned value.
2749  *
2750  * Returns: a #GstIterator of #GstElement for all elements in the bin
2751  *          implementing the given interface, or NULL
2752  */
2753 GstIterator *
2754 gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
2755 {
2756   GstIterator *children;
2757   GstIterator *result;
2758
2759   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2760   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
2761
2762   children = gst_bin_iterate_recurse (bin);
2763   result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
2764       (gpointer) iface);
2765
2766   return result;
2767 }
2768
2769 #ifndef GST_DISABLE_LOADSAVE
2770 static xmlNodePtr
2771 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
2772 {
2773   GstBin *bin = GST_BIN (object);
2774   xmlNodePtr childlist, elementnode;
2775   GList *children;
2776   GstElement *child;
2777
2778   if (GST_OBJECT_CLASS (parent_class)->save_thyself)
2779     GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
2780
2781   childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
2782
2783   GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
2784       GST_ELEMENT_NAME (bin), bin->numchildren);
2785
2786   children = bin->children;
2787   while (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);
2792   }
2793   return childlist;
2794 }
2795
2796 static void
2797 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
2798 {
2799   GstBin *bin = GST_BIN (object);
2800   xmlNodePtr field = self->xmlChildrenNode;
2801   xmlNodePtr childlist;
2802
2803   while (field) {
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;
2808       while (childlist) {
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));
2812         }
2813         childlist = childlist->next;
2814       }
2815     }
2816
2817     field = field->next;
2818   }
2819   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
2820     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
2821 }
2822 #endif /* GST_DISABLE_LOADSAVE */