Merge branch 'master' into 0.11
[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.taymans@gmail.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 #GstBin::element-added signal is fired whenever a new element is added to
55  * the bin. Likewise the #GstBin::element-removed signal is fired whenever an
56  * element is removed from the bin.
57  *
58  * <refsect2><title>Notes</title>
59  * <para>
60  * A #GstBin internally intercepts every #GstMessage posted by its children and
61  * implements the following default behaviour for each of them:
62  * <variablelist>
63  *   <varlistentry>
64  *     <term>GST_MESSAGE_EOS</term>
65  *     <listitem><para>This message is only posted by sinks in the PLAYING
66  *     state. If all sinks posted the EOS message, this bin will post and EOS
67  *     message upwards.</para></listitem>
68  *   </varlistentry>
69  *   <varlistentry>
70  *     <term>GST_MESSAGE_SEGMENT_START</term>
71  *     <listitem><para>just collected and never forwarded upwards.
72  *     The messages are used to decide when all elements have completed playback
73  *     of their segment.</para></listitem>
74  *   </varlistentry>
75  *   <varlistentry>
76  *     <term>GST_MESSAGE_SEGMENT_DONE</term>
77  *     <listitem><para> Is posted by #GstBin when all elements that posted
78  *     a SEGMENT_START have posted a SEGMENT_DONE.</para></listitem>
79  *   </varlistentry>
80  *   <varlistentry>
81  *     <term>GST_MESSAGE_DURATION</term>
82  *     <listitem><para> Is posted by an element that detected a change
83  *     in the stream duration. The default bin behaviour is to clear any
84  *     cached duration values so that the next duration query will perform
85  *     a full duration recalculation. The duration change is posted to the
86  *     application so that it can refetch the new duration with a duration
87  *     query. Note that these messages can be posted before the bin is
88  *     prerolled, in which case the duration query might fail.
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 "gstinfo.h"
165 #include "gsterror.h"
166
167 #include "gstutils.h"
168 #include "gstchildproxy.h"
169
170 /* latency is by default enabled now.
171  * live-preroll and no-live-preroll in the environment var GST_COMPAT
172  * to enables or disable it respectively.
173  */
174 static gboolean enable_latency = TRUE;
175
176 GST_DEBUG_CATEGORY_STATIC (bin_debug);
177 #define GST_CAT_DEFAULT bin_debug
178
179 /* a bin is toplevel if it has no parent or when it is configured to behave like
180  * a toplevel bin */
181 #define BIN_IS_TOPLEVEL(bin) ((GST_OBJECT_PARENT (bin) == NULL) || bin->priv->asynchandling)
182
183 #define GST_BIN_GET_PRIVATE(obj)  \
184    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BIN, GstBinPrivate))
185
186 struct _GstBinPrivate
187 {
188   gboolean asynchandling;
189   /* if we get an ASYNC_DONE message from ourselves, this means that the
190    * subclass will simulate ASYNC behaviour without having ASYNC children. When
191    * such an ASYNC_DONE message is posted while we are doing a state change, we
192    * have to process the message after finishing the state change even when no
193    * child returned GST_STATE_CHANGE_ASYNC. */
194   gboolean pending_async_done;
195
196   guint32 structure_cookie;
197
198 #if 0
199   /* cached index */
200   GstIndex *index;
201 #endif
202
203   /* forward messages from our children */
204   gboolean message_forward;
205
206   gboolean posted_eos;
207 };
208
209 typedef struct
210 {
211   GstBin *bin;
212   guint32 cookie;
213   GstState pending;
214 } BinContinueData;
215
216 static void gst_bin_dispose (GObject * object);
217
218 static void gst_bin_set_property (GObject * object, guint prop_id,
219     const GValue * value, GParamSpec * pspec);
220 static void gst_bin_get_property (GObject * object, guint prop_id,
221     GValue * value, GParamSpec * pspec);
222
223 static GstStateChangeReturn gst_bin_change_state_func (GstElement * element,
224     GstStateChange transition);
225 static void gst_bin_state_changed (GstElement * element, GstState oldstate,
226     GstState newstate, GstState pending);
227 static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
228     GstState * state, GstState * pending, GstClockTime timeout);
229 static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
230     gboolean flag_pending, gboolean reset_time);
231 static void bin_handle_async_start (GstBin * bin);
232 static void bin_push_state_continue (BinContinueData * data);
233 static void bin_do_eos (GstBin * bin);
234
235 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
236 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
237
238 #if 0
239 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
240 static GstIndex *gst_bin_get_index_func (GstElement * element);
241 #endif
242
243 static GstClock *gst_bin_provide_clock_func (GstElement * element);
244 static gboolean gst_bin_set_clock_func (GstElement * element, GstClock * clock);
245
246 static void gst_bin_handle_message_func (GstBin * bin, GstMessage * message);
247 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
248 static GstBusSyncReply bin_bus_handler (GstBus * bus,
249     GstMessage * message, GstBin * bin);
250 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
251
252 static gboolean gst_bin_do_latency_func (GstBin * bin);
253
254 static void bin_remove_messages (GstBin * bin, GstObject * src,
255     GstMessageType types);
256 static void gst_bin_continue_func (BinContinueData * data);
257 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
258 static gint bin_element_is_src (GstElement * child, GstBin * bin);
259
260 static GstIterator *gst_bin_sort_iterator_new (GstBin * bin);
261
262 /* Bin signals and properties */
263 enum
264 {
265   ELEMENT_ADDED,
266   ELEMENT_REMOVED,
267   DO_LATENCY,
268   LAST_SIGNAL
269 };
270
271 #define DEFAULT_ASYNC_HANDLING  FALSE
272 #define DEFAULT_MESSAGE_FORWARD FALSE
273
274 enum
275 {
276   PROP_0,
277   PROP_ASYNC_HANDLING,
278   PROP_MESSAGE_FORWARD,
279   PROP_LAST
280 };
281
282 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
283
284 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
285
286 #define _do_init \
287 { \
288   const gchar *compat; \
289   static const GInterfaceInfo iface_info = { \
290     gst_bin_child_proxy_init, \
291     NULL, \
292     NULL}; \
293   \
294   g_type_add_interface_static (g_define_type_id, GST_TYPE_CHILD_PROXY, &iface_info); \
295   \
296   GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD, \
297       "debugging info for the 'bin' container element"); \
298   \
299   /* compatibility stuff */ \
300   compat = g_getenv ("GST_COMPAT"); \
301   if (compat != NULL) { \
302     if (strstr (compat, "no-live-preroll")) \
303       enable_latency = FALSE; \
304     else if (strstr (compat, "live-preroll")) \
305       enable_latency = TRUE; \
306   } \
307 }
308
309 #define gst_bin_parent_class parent_class
310 G_DEFINE_TYPE_WITH_CODE (GstBin, gst_bin, GST_TYPE_ELEMENT, _do_init);
311
312 static GstObject *
313 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
314     guint index)
315 {
316   GstObject *res;
317   GstBin *bin;
318
319   bin = GST_BIN_CAST (child_proxy);
320
321   GST_OBJECT_LOCK (bin);
322   if ((res = g_list_nth_data (bin->children, index)))
323     gst_object_ref (res);
324   GST_OBJECT_UNLOCK (bin);
325
326   return res;
327 }
328
329 static guint
330 gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
331 {
332   guint num;
333   GstBin *bin;
334
335   bin = GST_BIN_CAST (child_proxy);
336
337   GST_OBJECT_LOCK (bin);
338   num = bin->numchildren;
339   GST_OBJECT_UNLOCK (bin);
340
341   return num;
342 }
343
344 static void
345 gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
346 {
347   GstChildProxyInterface *iface = g_iface;
348
349   iface->get_children_count = gst_bin_child_proxy_get_children_count;
350   iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
351 }
352
353 static gboolean
354 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
355     GValue * return_accu, const GValue * handler_return, gpointer dummy)
356 {
357   gboolean myboolean;
358
359   myboolean = g_value_get_boolean (handler_return);
360   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
361     g_value_set_boolean (return_accu, myboolean);
362
363   GST_DEBUG ("invocation %d, %d", ihint->run_type, myboolean);
364
365   /* stop emission */
366   return FALSE;
367 }
368
369 static void
370 gst_bin_class_init (GstBinClass * klass)
371 {
372   GObjectClass *gobject_class;
373   GstElementClass *gstelement_class;
374   GError *err;
375
376   gobject_class = (GObjectClass *) klass;
377   gstelement_class = (GstElementClass *) klass;
378
379   g_type_class_add_private (klass, sizeof (GstBinPrivate));
380
381   gobject_class->set_property = gst_bin_set_property;
382   gobject_class->get_property = gst_bin_get_property;
383
384   /**
385    * GstBin:async-handling
386    *
387    * If set to #TRUE, the bin will handle asynchronous state changes.
388    * This should be used only if the bin subclass is modifying the state
389    * of its children on its own.
390    *
391    * Since: 0.10.13
392    */
393   g_object_class_install_property (gobject_class, PROP_ASYNC_HANDLING,
394       g_param_spec_boolean ("async-handling", "Async Handling",
395           "The bin will handle Asynchronous state changes",
396           DEFAULT_ASYNC_HANDLING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
397
398   /**
399    * GstBin::element-added:
400    * @bin: the #GstBin
401    * @element: the #GstElement that was added to the bin
402    *
403    * Will be emitted after the element was added to the bin.
404    */
405   gst_bin_signals[ELEMENT_ADDED] =
406       g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
407       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
408       NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
409   /**
410    * GstBin::element-removed:
411    * @bin: the #GstBin
412    * @element: the #GstElement that was removed from the bin
413    *
414    * Will be emitted after the element was removed from the bin.
415    */
416   gst_bin_signals[ELEMENT_REMOVED] =
417       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
418       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
419       NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
420   /**
421    * GstBin::do-latency:
422    * @bin: the #GstBin
423    *
424    * Will be emitted when the bin needs to perform latency calculations. This
425    * signal is only emited for toplevel bins or when async-handling is
426    * enabled.
427    *
428    * Only one signal handler is invoked. If no signals are connected, the
429    * default handler is invoked, which will query and distribute the lowest
430    * possible latency to all sinks.
431    *
432    * Connect to this signal if the default latency calculations are not
433    * sufficient, like when you need different latencies for different sinks in
434    * the same pipeline.
435    *
436    * Since: 0.10.22
437    */
438   gst_bin_signals[DO_LATENCY] =
439       g_signal_new ("do-latency", G_TYPE_FROM_CLASS (klass),
440       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstBinClass, do_latency),
441       _gst_boolean_accumulator, NULL, g_cclosure_marshal_generic,
442       G_TYPE_BOOLEAN, 0, G_TYPE_NONE);
443
444   /**
445    * GstBin:message-forward
446    *
447    * Forward all children messages, even those that would normally be filtered by
448    * the bin. This can be interesting when one wants to be notified of the EOS
449    * state of individual elements, for example.
450    *
451    * The messages are converted to an ELEMENT message with the bin as the
452    * source. The structure of the message is named 'GstBinForwarded' and contains
453    * a field named 'message' of type GST_TYPE_MESSAGE that contains the original
454    * forwarded message.
455    *
456    * Since: 0.10.31
457    */
458   g_object_class_install_property (gobject_class, PROP_MESSAGE_FORWARD,
459       g_param_spec_boolean ("message-forward", "Message Forward",
460           "Forwards all children messages",
461           DEFAULT_MESSAGE_FORWARD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
462
463   gobject_class->dispose = gst_bin_dispose;
464
465   gst_element_class_set_metadata (gstelement_class, "Generic bin",
466       "Generic/Bin",
467       "Simple container object",
468       "Erik Walthinsen <omega@cse.ogi.edu>,"
469       "Wim Taymans <wim.taymans@gmail.com>");
470
471   gstelement_class->change_state =
472       GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
473   gstelement_class->state_changed = GST_DEBUG_FUNCPTR (gst_bin_state_changed);
474   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
475 #if 0
476   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_bin_get_index_func);
477   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
478 #endif
479   gstelement_class->provide_clock =
480       GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
481   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
482
483   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
484   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
485
486   klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
487   klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
488   klass->handle_message = GST_DEBUG_FUNCPTR (gst_bin_handle_message_func);
489
490   klass->do_latency = GST_DEBUG_FUNCPTR (gst_bin_do_latency_func);
491
492   GST_DEBUG ("creating bin thread pool");
493   err = NULL;
494   klass->pool =
495       g_thread_pool_new ((GFunc) gst_bin_continue_func, NULL, -1, FALSE, &err);
496   if (err != NULL) {
497     g_critical ("could alloc threadpool %s", err->message);
498   }
499 }
500
501 static void
502 gst_bin_init (GstBin * bin)
503 {
504   GstBus *bus;
505
506   bin->numchildren = 0;
507   bin->children = NULL;
508   bin->children_cookie = 0;
509   bin->messages = NULL;
510   bin->provided_clock = NULL;
511   bin->clock_dirty = FALSE;
512
513   /* Set up a bus for listening to child elements */
514   bus = g_object_new (GST_TYPE_BUS, "enable-async", FALSE, NULL);
515   bin->child_bus = bus;
516   GST_DEBUG_OBJECT (bin, "using bus %" GST_PTR_FORMAT " to listen to children",
517       bus);
518   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
519
520   bin->priv = GST_BIN_GET_PRIVATE (bin);
521   bin->priv->asynchandling = DEFAULT_ASYNC_HANDLING;
522   bin->priv->structure_cookie = 0;
523   bin->priv->message_forward = DEFAULT_MESSAGE_FORWARD;
524 }
525
526 static void
527 gst_bin_dispose (GObject * object)
528 {
529   GstBin *bin = GST_BIN_CAST (object);
530   GstBus **child_bus_p = &bin->child_bus;
531   GstClock **provided_clock_p = &bin->provided_clock;
532   GstElement **clock_provider_p = &bin->clock_provider;
533
534   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
535
536   GST_OBJECT_LOCK (object);
537   gst_object_replace ((GstObject **) child_bus_p, NULL);
538   gst_object_replace ((GstObject **) provided_clock_p, NULL);
539   gst_object_replace ((GstObject **) clock_provider_p, NULL);
540   bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
541   GST_OBJECT_UNLOCK (object);
542
543   while (bin->children) {
544     gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
545   }
546   if (G_UNLIKELY (bin->children != NULL)) {
547     g_critical ("could not remove elements from bin '%s'",
548         GST_STR_NULL (GST_OBJECT_NAME (object)));
549   }
550
551   G_OBJECT_CLASS (parent_class)->dispose (object);
552 }
553
554 /**
555  * gst_bin_new:
556  * @name: the name of the new bin
557  *
558  * Creates a new bin with the given name.
559  *
560  * Returns: (transfer floating): a new #GstBin
561  */
562 GstElement *
563 gst_bin_new (const gchar * name)
564 {
565   return gst_element_factory_make ("bin", name);
566 }
567
568 static void
569 gst_bin_set_property (GObject * object, guint prop_id,
570     const GValue * value, GParamSpec * pspec)
571 {
572   GstBin *gstbin;
573
574   gstbin = GST_BIN_CAST (object);
575
576   switch (prop_id) {
577     case PROP_ASYNC_HANDLING:
578       GST_OBJECT_LOCK (gstbin);
579       gstbin->priv->asynchandling = g_value_get_boolean (value);
580       GST_OBJECT_UNLOCK (gstbin);
581       break;
582     case PROP_MESSAGE_FORWARD:
583       GST_OBJECT_LOCK (gstbin);
584       gstbin->priv->message_forward = g_value_get_boolean (value);
585       GST_OBJECT_UNLOCK (gstbin);
586       break;
587     default:
588       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
589       break;
590   }
591 }
592
593 static void
594 gst_bin_get_property (GObject * object, guint prop_id,
595     GValue * value, GParamSpec * pspec)
596 {
597   GstBin *gstbin;
598
599   gstbin = GST_BIN_CAST (object);
600
601   switch (prop_id) {
602     case PROP_ASYNC_HANDLING:
603       GST_OBJECT_LOCK (gstbin);
604       g_value_set_boolean (value, gstbin->priv->asynchandling);
605       GST_OBJECT_UNLOCK (gstbin);
606       break;
607     case PROP_MESSAGE_FORWARD:
608       GST_OBJECT_LOCK (gstbin);
609       g_value_set_boolean (value, gstbin->priv->message_forward);
610       GST_OBJECT_UNLOCK (gstbin);
611       break;
612     default:
613       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
614       break;
615   }
616 }
617
618 #if 0
619 /* return the cached index */
620 static GstIndex *
621 gst_bin_get_index_func (GstElement * element)
622 {
623   GstBin *bin;
624   GstIndex *result;
625
626   bin = GST_BIN_CAST (element);
627
628   GST_OBJECT_LOCK (bin);
629   if ((result = bin->priv->index))
630     gst_object_ref (result);
631   GST_OBJECT_UNLOCK (bin);
632
633   return result;
634 }
635
636 /* set the index on all elements in this bin
637  *
638  * MT safe
639  */
640 static void
641 gst_bin_set_index_func (GstElement * element, GstIndex * index)
642 {
643   GstBin *bin;
644   gboolean done;
645   GstIterator *it;
646   GstIndex *old;
647   GValue data = { 0, };
648
649   bin = GST_BIN_CAST (element);
650
651   GST_OBJECT_LOCK (bin);
652   old = bin->priv->index;
653   if (G_UNLIKELY (old == index))
654     goto was_set;
655   if (index)
656     gst_object_ref (index);
657   bin->priv->index = index;
658   GST_OBJECT_UNLOCK (bin);
659
660   if (old)
661     gst_object_unref (old);
662
663   it = gst_bin_iterate_elements (bin);
664
665   /* set the index on all elements in the bin */
666   done = FALSE;
667   while (!done) {
668     switch (gst_iterator_next (it, &data)) {
669       case GST_ITERATOR_OK:
670       {
671         GstElement *child = g_value_get_object (&data);
672
673         GST_DEBUG_OBJECT (bin, "setting index on '%s'",
674             GST_ELEMENT_NAME (child));
675         gst_element_set_index (child, index);
676
677         g_value_reset (&data);
678         break;
679       }
680       case GST_ITERATOR_RESYNC:
681         GST_DEBUG_OBJECT (bin, "iterator doing resync");
682         gst_iterator_resync (it);
683         break;
684       default:
685       case GST_ITERATOR_DONE:
686         GST_DEBUG_OBJECT (bin, "iterator done");
687         done = TRUE;
688         break;
689     }
690   }
691   g_value_unset (&data);
692   gst_iterator_free (it);
693   return;
694
695 was_set:
696   {
697     GST_DEBUG_OBJECT (bin, "index was already set");
698     GST_OBJECT_UNLOCK (bin);
699     return;
700   }
701 }
702 #endif
703
704 /* set the clock on all elements in this bin
705  *
706  * MT safe
707  */
708 static gboolean
709 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
710 {
711   GstBin *bin;
712   gboolean done;
713   GstIterator *it;
714   gboolean res = TRUE;
715   GValue data = { 0, };
716
717   bin = GST_BIN_CAST (element);
718
719   it = gst_bin_iterate_elements (bin);
720
721   done = FALSE;
722   while (!done) {
723     switch (gst_iterator_next (it, &data)) {
724       case GST_ITERATOR_OK:
725       {
726         GstElement *child = g_value_get_object (&data);
727
728         res &= gst_element_set_clock (child, clock);
729
730         g_value_reset (&data);
731         break;
732       }
733       case GST_ITERATOR_RESYNC:
734         GST_DEBUG_OBJECT (bin, "iterator doing resync");
735         gst_iterator_resync (it);
736         res = TRUE;
737         break;
738       default:
739       case GST_ITERATOR_DONE:
740         GST_DEBUG_OBJECT (bin, "iterator done");
741         done = TRUE;
742         break;
743     }
744   }
745   g_value_unset (&data);
746   gst_iterator_free (it);
747
748   if (res)
749     res = GST_ELEMENT_CLASS (parent_class)->set_clock (element, clock);
750
751   return res;
752 }
753
754 /* get the clock for this bin by asking all of the children in this bin
755  *
756  * The ref of the returned clock in increased so unref after usage.
757  *
758  * We loop the elements in state order and pick the last clock we can
759  * get. This makes sure we get a clock from the source.
760  *
761  * MT safe
762  */
763 static GstClock *
764 gst_bin_provide_clock_func (GstElement * element)
765 {
766   GstClock *result = NULL;
767   GstElement *provider = NULL;
768   GstBin *bin;
769   GstIterator *it;
770   gboolean done;
771   GValue val = { 0, };
772   GstClock **provided_clock_p;
773   GstElement **clock_provider_p;
774
775   bin = GST_BIN_CAST (element);
776
777   GST_OBJECT_LOCK (bin);
778   if (!bin->clock_dirty)
779     goto not_dirty;
780
781   GST_DEBUG_OBJECT (bin, "finding new clock");
782
783   it = gst_bin_sort_iterator_new (bin);
784   GST_OBJECT_UNLOCK (bin);
785
786   done = FALSE;
787   while (!done) {
788     switch (gst_iterator_next (it, &val)) {
789       case GST_ITERATOR_OK:
790       {
791         GstElement *child = g_value_get_object (&val);
792         GstClock *clock;
793
794         clock = gst_element_provide_clock (child);
795         if (clock) {
796           GST_DEBUG_OBJECT (bin, "found candidate clock %p by element %s",
797               clock, GST_ELEMENT_NAME (child));
798           if (result) {
799             gst_object_unref (result);
800             gst_object_unref (provider);
801           }
802           result = clock;
803           provider = gst_object_ref (child);
804         }
805
806         g_value_reset (&val);
807         break;
808       }
809       case GST_ITERATOR_RESYNC:
810         gst_iterator_resync (it);
811         break;
812       default:
813       case GST_ITERATOR_DONE:
814         done = TRUE;
815         break;
816     }
817   }
818   g_value_unset (&val);
819   gst_iterator_free (it);
820
821   GST_OBJECT_LOCK (bin);
822   if (!bin->clock_dirty) {
823     if (provider)
824       gst_object_unref (provider);
825     if (result)
826       gst_object_unref (result);
827     result = NULL;
828
829     goto not_dirty;
830   }
831
832   provided_clock_p = &bin->provided_clock;
833   clock_provider_p = &bin->clock_provider;
834   gst_object_replace ((GstObject **) provided_clock_p, (GstObject *) result);
835   gst_object_replace ((GstObject **) clock_provider_p, (GstObject *) provider);
836   bin->clock_dirty = FALSE;
837   GST_DEBUG_OBJECT (bin,
838       "provided new clock %" GST_PTR_FORMAT " by provider %" GST_PTR_FORMAT,
839       result, provider);
840   /* Provider is not being returned to caller, just the result */
841   if (provider)
842     gst_object_unref (provider);
843   GST_OBJECT_UNLOCK (bin);
844
845   return result;
846
847 not_dirty:
848   {
849     if ((result = bin->provided_clock))
850       gst_object_ref (result);
851     GST_DEBUG_OBJECT (bin, "returning old clock %p", result);
852     GST_OBJECT_UNLOCK (bin);
853
854     return result;
855   }
856 }
857
858 /*
859  * functions for manipulating cached messages
860  */
861 typedef struct
862 {
863   GstObject *src;
864   GstMessageType types;
865 } MessageFind;
866
867 /* check if a message is of given src and type */
868 static gint
869 message_check (GstMessage * message, MessageFind * target)
870 {
871   gboolean eq = TRUE;
872
873   if (target->src)
874     eq &= GST_MESSAGE_SRC (message) == target->src;
875   if (target->types)
876     eq &= (GST_MESSAGE_TYPE (message) & target->types) != 0;
877   GST_LOG ("looking at message %p: %d", message, eq);
878
879   return (eq ? 0 : 1);
880 }
881
882 static GList *
883 find_message (GstBin * bin, GstObject * src, GstMessageType types)
884 {
885   GList *result;
886   MessageFind find;
887
888   find.src = src;
889   find.types = types;
890
891   result = g_list_find_custom (bin->messages, &find,
892       (GCompareFunc) message_check);
893
894   if (result) {
895     GST_DEBUG_OBJECT (bin, "we found a message %p from %s matching types %08x",
896         result->data, GST_OBJECT_NAME (GST_MESSAGE_CAST (result->data)->src),
897         types);
898   } else {
899     GST_DEBUG_OBJECT (bin, "no message found matching types %08x", types);
900 #ifndef GST_DISABLE_GST_DEBUG
901     {
902       guint i;
903
904       for (i = 0; i < 32; i++)
905         if (types & (1 << i))
906           GST_DEBUG_OBJECT (bin, "  %s", gst_message_type_get_name (1 << i));
907     }
908 #endif
909   }
910
911   return result;
912 }
913
914 /* with LOCK, returns TRUE if message had a valid SRC, takes ownership of
915  * the message.
916  *
917  * A message that is cached and has the same SRC and type is replaced
918  * by the given message.
919  */
920 static gboolean
921 bin_replace_message (GstBin * bin, GstMessage * message, GstMessageType types)
922 {
923   GList *previous;
924   GstObject *src;
925   gboolean res = TRUE;
926
927   if ((src = GST_MESSAGE_SRC (message))) {
928     /* first find the previous message posted by this element */
929     if ((previous = find_message (bin, src, types))) {
930       GstMessage *previous_msg;
931
932       /* if we found a previous message, replace it */
933       previous_msg = previous->data;
934       previous->data = message;
935
936       GST_DEBUG_OBJECT (bin, "replace old message %s from %s with %s message",
937           GST_MESSAGE_TYPE_NAME (previous_msg), GST_ELEMENT_NAME (src),
938           GST_MESSAGE_TYPE_NAME (message));
939
940       gst_message_unref (previous_msg);
941     } else {
942       /* keep new message */
943       bin->messages = g_list_prepend (bin->messages, message);
944
945       GST_DEBUG_OBJECT (bin, "got new message %p, %s from %s",
946           message, GST_MESSAGE_TYPE_NAME (message), GST_ELEMENT_NAME (src));
947     }
948   } else {
949     GST_DEBUG_OBJECT (bin, "got message %s from (NULL), not processing",
950         GST_MESSAGE_TYPE_NAME (message));
951     res = FALSE;
952     gst_message_unref (message);
953   }
954   return res;
955 }
956
957 /* with LOCK. Remove all messages of given types */
958 static void
959 bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types)
960 {
961   MessageFind find;
962   GList *walk, *next;
963
964   find.src = src;
965   find.types = types;
966
967   for (walk = bin->messages; walk; walk = next) {
968     GstMessage *message = (GstMessage *) walk->data;
969
970     next = g_list_next (walk);
971
972     if (message_check (message, &find) == 0) {
973       GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
974           "deleting message %p of types 0x%08x", message, types);
975       bin->messages = g_list_delete_link (bin->messages, walk);
976       gst_message_unref (message);
977     } else {
978       GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message),
979           "not deleting message %p of type 0x%08x", message,
980           GST_MESSAGE_TYPE (message));
981     }
982   }
983 }
984
985
986 /* Check if the bin is EOS. We do this by scanning all sinks and
987  * checking if they posted an EOS message.
988  *
989  * call with bin LOCK */
990 static gboolean
991 is_eos (GstBin * bin, guint32 * seqnum)
992 {
993   gboolean result;
994   gint n_eos = 0;
995   GList *walk, *msgs;
996
997   result = TRUE;
998   for (walk = bin->children; walk; walk = g_list_next (walk)) {
999     GstElement *element;
1000
1001     element = GST_ELEMENT_CAST (walk->data);
1002     if (bin_element_is_sink (element, bin) == 0) {
1003       /* check if element posted EOS */
1004       if ((msgs =
1005               find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS))) {
1006         GST_DEBUG ("sink '%s' posted EOS", GST_ELEMENT_NAME (element));
1007         *seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data));
1008         n_eos++;
1009       } else {
1010         GST_DEBUG ("sink '%s' did not post EOS yet",
1011             GST_ELEMENT_NAME (element));
1012         result = FALSE;
1013         break;
1014       }
1015     }
1016   }
1017   /* FIXME: Some tests (e.g. elements/capsfilter) use
1018    * pipelines with a dangling sinkpad but no sink element.
1019    * These tests assume that no EOS message is ever
1020    * posted on the bus so let's keep that behaviour.
1021    * In valid pipelines this doesn't make a difference.
1022    */
1023   return result && n_eos > 0;
1024 }
1025
1026 static void
1027 unlink_pads (const GValue * item, gpointer user_data)
1028 {
1029   GstPad *pad;
1030   GstPad *peer;
1031
1032   pad = g_value_get_object (item);
1033
1034   if ((peer = gst_pad_get_peer (pad))) {
1035     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
1036       gst_pad_unlink (pad, peer);
1037     else
1038       gst_pad_unlink (peer, pad);
1039     gst_object_unref (peer);
1040   }
1041 }
1042
1043 /* vmethod that adds an element to a bin
1044  *
1045  * MT safe
1046  */
1047 static gboolean
1048 gst_bin_add_func (GstBin * bin, GstElement * element)
1049 {
1050   gchar *elem_name;
1051   GstIterator *it;
1052   gboolean is_sink, is_source, provides_clock, requires_clock;
1053   GstMessage *clock_message = NULL, *async_message = NULL;
1054   GstStateChangeReturn ret;
1055
1056   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
1057
1058   /* we obviously can't add ourself to ourself */
1059   if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
1060     goto adding_itself;
1061
1062   /* get the element name to make sure it is unique in this bin. */
1063   GST_OBJECT_LOCK (element);
1064   elem_name = g_strdup (GST_ELEMENT_NAME (element));
1065   is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
1066   is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE);
1067   provides_clock =
1068       GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1069   requires_clock =
1070       GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1071   GST_OBJECT_UNLOCK (element);
1072
1073   GST_OBJECT_LOCK (bin);
1074
1075   /* then check to see if the element's name is already taken in the bin,
1076    * we can safely take the lock here. This check is probably bogus because
1077    * you can safely change the element name after this check and before setting
1078    * the object parent. The window is very small though... */
1079   if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name)))
1080     goto duplicate_name;
1081
1082   /* set the element's parent and add the element to the bin's list of children */
1083   if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
1084               GST_OBJECT_CAST (bin))))
1085     goto had_parent;
1086
1087   /* if we add a sink we become a sink */
1088   if (is_sink) {
1089     GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink",
1090         elem_name);
1091     GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SINK);
1092   }
1093   if (is_source) {
1094     GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was source",
1095         elem_name);
1096     GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_SOURCE);
1097   }
1098   if (provides_clock) {
1099     GST_DEBUG_OBJECT (bin, "element \"%s\" can provide a clock", elem_name);
1100     clock_message =
1101         gst_message_new_clock_provide (GST_OBJECT_CAST (element), NULL, TRUE);
1102     GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1103   }
1104   if (requires_clock) {
1105     GST_DEBUG_OBJECT (bin, "element \"%s\" requires a clock", elem_name);
1106     GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1107   }
1108
1109   bin->children = g_list_prepend (bin->children, element);
1110   bin->numchildren++;
1111   bin->children_cookie++;
1112   bin->priv->structure_cookie++;
1113
1114   /* distribute the bus */
1115   gst_element_set_bus (element, bin->child_bus);
1116
1117   /* propagate the current base_time, start_time and clock */
1118   gst_element_set_base_time (element, GST_ELEMENT_CAST (bin)->base_time);
1119   gst_element_set_start_time (element, GST_ELEMENT_START_TIME (bin));
1120   /* it's possible that the element did not accept the clock but
1121    * that is not important right now. When the pipeline goes to PLAYING,
1122    * a new clock will be selected */
1123   gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
1124
1125 #if 0
1126   /* set the cached index on the children */
1127   if (bin->priv->index)
1128     gst_element_set_index (element, bin->priv->index);
1129 #endif
1130
1131   ret = GST_STATE_RETURN (bin);
1132   /* no need to update the state if we are in error */
1133   if (ret == GST_STATE_CHANGE_FAILURE)
1134     goto no_state_recalc;
1135
1136   /* update the bin state, the new element could have been an ASYNC or
1137    * NO_PREROLL element */
1138   ret = GST_STATE_RETURN (element);
1139   GST_DEBUG_OBJECT (bin, "added %s element",
1140       gst_element_state_change_return_get_name (ret));
1141
1142   switch (ret) {
1143     case GST_STATE_CHANGE_ASYNC:
1144     {
1145       /* create message to track this aync element when it posts an async-done
1146        * message */
1147       async_message = gst_message_new_async_start (GST_OBJECT_CAST (element));
1148       break;
1149     }
1150     case GST_STATE_CHANGE_NO_PREROLL:
1151       /* ignore all async elements we might have and commit our state */
1152       bin_handle_async_done (bin, ret, FALSE, FALSE);
1153       break;
1154     case GST_STATE_CHANGE_FAILURE:
1155       break;
1156     default:
1157       break;
1158   }
1159
1160 no_state_recalc:
1161   GST_OBJECT_UNLOCK (bin);
1162
1163   /* post the messages on the bus of the element so that the bin can handle
1164    * them */
1165   if (clock_message)
1166     gst_element_post_message (GST_ELEMENT_CAST (element), clock_message);
1167
1168   if (async_message)
1169     gst_element_post_message (GST_ELEMENT_CAST (element), async_message);
1170
1171   /* unlink all linked pads */
1172   it = gst_element_iterate_pads (element);
1173   gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, NULL);
1174   gst_iterator_free (it);
1175
1176   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
1177       elem_name);
1178   g_free (elem_name);
1179
1180   g_signal_emit (bin, gst_bin_signals[ELEMENT_ADDED], 0, element);
1181   gst_child_proxy_child_added ((GstObject *) bin, (GstObject *) element);
1182
1183   return TRUE;
1184
1185   /* ERROR handling here */
1186 adding_itself:
1187   {
1188     GST_OBJECT_LOCK (bin);
1189     g_warning ("Cannot add bin '%s' to itself", GST_ELEMENT_NAME (bin));
1190     GST_OBJECT_UNLOCK (bin);
1191     return FALSE;
1192   }
1193 duplicate_name:
1194   {
1195     g_warning ("Name '%s' is not unique in bin '%s', not adding",
1196         elem_name, GST_ELEMENT_NAME (bin));
1197     GST_OBJECT_UNLOCK (bin);
1198     g_free (elem_name);
1199     return FALSE;
1200   }
1201 had_parent:
1202   {
1203     g_warning ("Element '%s' already has parent", elem_name);
1204     GST_OBJECT_UNLOCK (bin);
1205     g_free (elem_name);
1206     return FALSE;
1207   }
1208 }
1209
1210 /**
1211  * gst_bin_add:
1212  * @bin: a #GstBin
1213  * @element: (transfer full): the #GstElement to add
1214  *
1215  * Adds the given element to the bin.  Sets the element's parent, and thus
1216  * takes ownership of the element. An element can only be added to one bin.
1217  *
1218  * If the element's pads are linked to other pads, the pads will be unlinked
1219  * before the element is added to the bin.
1220  *
1221  * <note>
1222  * When you add an element to an already-running pipeline, you will have to
1223  * take care to set the state of the newly-added element to the desired
1224  * state (usually PLAYING or PAUSED, same you set the pipeline to originally)
1225  * with gst_element_set_state(), or use gst_element_sync_state_with_parent().
1226  * The bin or pipeline will not take care of this for you.
1227  * </note>
1228  *
1229  * MT safe.
1230  *
1231  * Returns: TRUE if the element could be added, FALSE if
1232  * the bin does not want to accept the element.
1233  */
1234 gboolean
1235 gst_bin_add (GstBin * bin, GstElement * element)
1236 {
1237   GstBinClass *bclass;
1238   gboolean result;
1239
1240   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
1241   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1242
1243   bclass = GST_BIN_GET_CLASS (bin);
1244
1245   if (G_UNLIKELY (bclass->add_element == NULL))
1246     goto no_function;
1247
1248   GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
1249       GST_STR_NULL (GST_ELEMENT_NAME (element)),
1250       GST_STR_NULL (GST_ELEMENT_NAME (bin)));
1251
1252   result = bclass->add_element (bin, element);
1253
1254   return result;
1255
1256   /* ERROR handling */
1257 no_function:
1258   {
1259     g_warning ("adding elements to bin '%s' is not supported",
1260         GST_ELEMENT_NAME (bin));
1261     return FALSE;
1262   }
1263 }
1264
1265 /* remove an element from the bin
1266  *
1267  * MT safe
1268  */
1269 static gboolean
1270 gst_bin_remove_func (GstBin * bin, GstElement * element)
1271 {
1272   gchar *elem_name;
1273   GstIterator *it;
1274   gboolean is_sink, is_source, provides_clock, requires_clock;
1275   gboolean othersink, othersource, otherprovider, otherrequirer, found;
1276   GstMessage *clock_message = NULL;
1277   GstClock **provided_clock_p;
1278   GstElement **clock_provider_p;
1279   GList *walk, *next;
1280   gboolean other_async, this_async, have_no_preroll;
1281   GstStateChangeReturn ret;
1282
1283   GST_DEBUG_OBJECT (bin, "element :%s", GST_ELEMENT_NAME (element));
1284
1285   GST_OBJECT_LOCK (element);
1286   /* Check if the element is already being removed and immediately
1287    * return */
1288   if (G_UNLIKELY (GST_OBJECT_FLAG_IS_SET (element,
1289               GST_ELEMENT_FLAG_UNPARENTING)))
1290     goto already_removing;
1291
1292   GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_UNPARENTING);
1293   /* grab element name so we can print it */
1294   elem_name = g_strdup (GST_ELEMENT_NAME (element));
1295   is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
1296   is_source = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE);
1297   provides_clock =
1298       GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1299   requires_clock =
1300       GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1301   GST_OBJECT_UNLOCK (element);
1302
1303   /* unlink all linked pads */
1304   it = gst_element_iterate_pads (element);
1305   gst_iterator_foreach (it, (GstIteratorForeachFunction) unlink_pads, NULL);
1306   gst_iterator_free (it);
1307
1308   GST_OBJECT_LOCK (bin);
1309   found = FALSE;
1310   othersink = FALSE;
1311   othersource = FALSE;
1312   otherprovider = FALSE;
1313   otherrequirer = FALSE;
1314   have_no_preroll = FALSE;
1315   /* iterate the elements, we collect which ones are async and no_preroll. We
1316    * also remove the element when we find it. */
1317   for (walk = bin->children; walk; walk = next) {
1318     GstElement *child = GST_ELEMENT_CAST (walk->data);
1319
1320     next = g_list_next (walk);
1321
1322     if (child == element) {
1323       found = TRUE;
1324       /* remove the element */
1325       bin->children = g_list_delete_link (bin->children, walk);
1326     } else {
1327       gboolean child_sink, child_source, child_provider, child_requirer;
1328
1329       GST_OBJECT_LOCK (child);
1330       child_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK);
1331       child_source = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE);
1332       child_provider =
1333           GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1334       child_requirer =
1335           GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1336       /* when we remove a sink, check if there are other sinks. */
1337       if (is_sink && !othersink && child_sink)
1338         othersink = TRUE;
1339       if (is_source && !othersource && child_source)
1340         othersource = TRUE;
1341       if (provides_clock && !otherprovider && child_provider)
1342         otherprovider = TRUE;
1343       if (requires_clock && !otherrequirer && child_requirer)
1344         otherrequirer = TRUE;
1345       /* check if we have NO_PREROLL children */
1346       if (GST_STATE_RETURN (child) == GST_STATE_CHANGE_NO_PREROLL)
1347         have_no_preroll = TRUE;
1348       GST_OBJECT_UNLOCK (child);
1349     }
1350   }
1351
1352   /* the element must have been in the bin's list of children */
1353   if (G_UNLIKELY (!found))
1354     goto not_in_bin;
1355
1356   /* we now removed the element from the list of elements, increment the cookie
1357    * so that others can detect a change in the children list. */
1358   bin->numchildren--;
1359   bin->children_cookie++;
1360   bin->priv->structure_cookie++;
1361
1362   if (is_sink && !othersink) {
1363     /* we're not a sink anymore */
1364     GST_DEBUG_OBJECT (bin, "we removed the last sink");
1365     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SINK);
1366   }
1367   if (is_source && !othersource) {
1368     /* we're not a source anymore */
1369     GST_DEBUG_OBJECT (bin, "we removed the last source");
1370     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_SOURCE);
1371   }
1372   if (provides_clock && !otherprovider) {
1373     /* we're not a clock provider anymore */
1374     GST_DEBUG_OBJECT (bin, "we removed the last clock provider");
1375     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
1376   }
1377   if (requires_clock && !otherrequirer) {
1378     /* we're not a clock requirer anymore */
1379     GST_DEBUG_OBJECT (bin, "we removed the last clock requirer");
1380     GST_OBJECT_FLAG_UNSET (bin, GST_ELEMENT_FLAG_REQUIRE_CLOCK);
1381   }
1382
1383   /* if the clock provider for this element is removed, we lost
1384    * the clock as well, we need to inform the parent of this
1385    * so that it can select a new clock */
1386   if (bin->clock_provider == element) {
1387     GST_DEBUG_OBJECT (bin, "element \"%s\" provided the clock", elem_name);
1388     bin->clock_dirty = TRUE;
1389     clock_message =
1390         gst_message_new_clock_lost (GST_OBJECT_CAST (bin), bin->provided_clock);
1391     provided_clock_p = &bin->provided_clock;
1392     clock_provider_p = &bin->clock_provider;
1393     gst_object_replace ((GstObject **) provided_clock_p, NULL);
1394     gst_object_replace ((GstObject **) clock_provider_p, NULL);
1395   }
1396
1397   /* remove messages for the element, if there was a pending ASYNC_START
1398    * message we must see if removing the element caused the bin to lose its
1399    * async state. */
1400   this_async = FALSE;
1401   other_async = FALSE;
1402   for (walk = bin->messages; walk; walk = next) {
1403     GstMessage *message = (GstMessage *) walk->data;
1404     GstElement *src = GST_ELEMENT_CAST (GST_MESSAGE_SRC (message));
1405     gboolean remove;
1406
1407     next = g_list_next (walk);
1408     remove = FALSE;
1409
1410     switch (GST_MESSAGE_TYPE (message)) {
1411       case GST_MESSAGE_ASYNC_START:
1412         if (src == element)
1413           this_async = TRUE;
1414         else
1415           other_async = TRUE;
1416
1417         GST_DEBUG_OBJECT (src, "looking at message %p", message);
1418         break;
1419       case GST_MESSAGE_STRUCTURE_CHANGE:
1420       {
1421         GstElement *owner;
1422
1423         GST_DEBUG_OBJECT (src, "looking at structure change message %p",
1424             message);
1425         /* it's unlikely that this message is still in the list of messages
1426          * because this would mean that a link/unlink is busy in another thread
1427          * while we remove the element. We still have to remove the message
1428          * because we might not receive the done message anymore when the element
1429          * is removed from the bin. */
1430         gst_message_parse_structure_change (message, NULL, &owner, NULL);
1431         if (owner == element)
1432           remove = TRUE;
1433         break;
1434       }
1435       default:
1436         break;
1437     }
1438     if (src == element)
1439       remove = TRUE;
1440
1441     if (remove) {
1442       /* delete all message types */
1443       GST_DEBUG_OBJECT (src, "deleting message %p of element \"%s\"",
1444           message, elem_name);
1445       bin->messages = g_list_delete_link (bin->messages, walk);
1446       gst_message_unref (message);
1447     }
1448   }
1449
1450   /* get last return */
1451   ret = GST_STATE_RETURN (bin);
1452
1453   /* no need to update the state if we are in error */
1454   if (ret == GST_STATE_CHANGE_FAILURE)
1455     goto no_state_recalc;
1456
1457   if (!other_async && this_async) {
1458     /* all other elements were not async and we removed the async one,
1459      * handle the async-done case because we are not async anymore now. */
1460     GST_DEBUG_OBJECT (bin,
1461         "we removed the last async element, have no_preroll %d",
1462         have_no_preroll);
1463
1464     /* the current state return of the bin depends on if there are no_preroll
1465      * elements in the pipeline or not */
1466     if (have_no_preroll)
1467       ret = GST_STATE_CHANGE_NO_PREROLL;
1468     else
1469       ret = GST_STATE_CHANGE_SUCCESS;
1470
1471     bin_handle_async_done (bin, ret, FALSE, FALSE);
1472   } else {
1473     GST_DEBUG_OBJECT (bin,
1474         "recalc state preroll: %d, other async: %d, this async %d",
1475         have_no_preroll, other_async, this_async);
1476
1477     if (have_no_preroll) {
1478       ret = GST_STATE_CHANGE_NO_PREROLL;
1479     } else if (other_async) {
1480       /* there are other async elements and we were not doing an async state
1481        * change, change our pending state and go async */
1482       if (GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING) {
1483         GST_STATE_NEXT (bin) = GST_STATE (bin);
1484         GST_STATE_PENDING (bin) = GST_STATE (bin);
1485       }
1486       ret = GST_STATE_CHANGE_ASYNC;
1487     }
1488     GST_STATE_RETURN (bin) = ret;
1489   }
1490 no_state_recalc:
1491   GST_OBJECT_UNLOCK (bin);
1492
1493   if (clock_message)
1494     gst_element_post_message (GST_ELEMENT_CAST (bin), clock_message);
1495
1496   GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
1497       elem_name);
1498   g_free (elem_name);
1499
1500   gst_element_set_bus (element, NULL);
1501
1502   /* Clear the clock we provided to the element */
1503   gst_element_set_clock (element, NULL);
1504
1505   /* we ref here because after the _unparent() the element can be disposed
1506    * and we still need it to reset the UNPARENTING flag and fire a signal. */
1507   gst_object_ref (element);
1508   gst_object_unparent (GST_OBJECT_CAST (element));
1509
1510   GST_OBJECT_LOCK (element);
1511   GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_UNPARENTING);
1512   GST_OBJECT_UNLOCK (element);
1513
1514   g_signal_emit (bin, gst_bin_signals[ELEMENT_REMOVED], 0, element);
1515   gst_child_proxy_child_removed ((GstObject *) bin, (GstObject *) element);
1516
1517   /* element is really out of our control now */
1518   gst_object_unref (element);
1519
1520   return TRUE;
1521
1522   /* ERROR handling */
1523 not_in_bin:
1524   {
1525     g_warning ("Element '%s' is not in bin '%s'", elem_name,
1526         GST_ELEMENT_NAME (bin));
1527     GST_OBJECT_UNLOCK (bin);
1528     g_free (elem_name);
1529     return FALSE;
1530   }
1531 already_removing:
1532   {
1533     GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "already removing child");
1534     GST_OBJECT_UNLOCK (element);
1535     return FALSE;
1536   }
1537 }
1538
1539 /**
1540  * gst_bin_remove:
1541  * @bin: a #GstBin
1542  * @element: (transfer none): the #GstElement to remove
1543  *
1544  * Removes the element from the bin, unparenting it as well.
1545  * Unparenting the element means that the element will be dereferenced,
1546  * so if the bin holds the only reference to the element, the element
1547  * will be freed in the process of removing it from the bin.  If you
1548  * want the element to still exist after removing, you need to call
1549  * gst_object_ref() before removing it from the bin.
1550  *
1551  * If the element's pads are linked to other pads, the pads will be unlinked
1552  * before the element is removed from the bin.
1553  *
1554  * MT safe.
1555  *
1556  * Returns: TRUE if the element could be removed, FALSE if
1557  * the bin does not want to remove the element.
1558  */
1559 gboolean
1560 gst_bin_remove (GstBin * bin, GstElement * element)
1561 {
1562   GstBinClass *bclass;
1563   gboolean result;
1564
1565   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
1566   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1567
1568   bclass = GST_BIN_GET_CLASS (bin);
1569
1570   if (G_UNLIKELY (bclass->remove_element == NULL))
1571     goto no_function;
1572
1573   GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
1574       GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
1575
1576   result = bclass->remove_element (bin, element);
1577
1578   return result;
1579
1580   /* ERROR handling */
1581 no_function:
1582   {
1583     g_warning ("removing elements from bin '%s' is not supported",
1584         GST_ELEMENT_NAME (bin));
1585     return FALSE;
1586   }
1587 }
1588
1589 /**
1590  * gst_bin_iterate_elements:
1591  * @bin: a #GstBin
1592  *
1593  * Gets an iterator for the elements in this bin.
1594  *
1595  * Each element yielded by the iterator will have its refcount increased, so
1596  * unref after use.
1597  *
1598  * MT safe.  Caller owns returned value.
1599  *
1600  * Returns: (transfer full): a #GstIterator of #GstElement, or NULL
1601  */
1602 GstIterator *
1603 gst_bin_iterate_elements (GstBin * bin)
1604 {
1605   GstIterator *result;
1606
1607   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1608
1609   GST_OBJECT_LOCK (bin);
1610   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1611       GST_OBJECT_GET_LOCK (bin),
1612       &bin->children_cookie, &bin->children, (GObject *) bin, NULL);
1613   GST_OBJECT_UNLOCK (bin);
1614
1615   return result;
1616 }
1617
1618 static GstIteratorItem
1619 iterate_child_recurse (GstIterator * it, const GValue * item)
1620 {
1621   GstElement *child = g_value_get_object (item);
1622
1623   if (GST_IS_BIN (child)) {
1624     GstIterator *other = gst_bin_iterate_recurse (GST_BIN_CAST (child));
1625
1626     gst_iterator_push (it, other);
1627   }
1628   return GST_ITERATOR_ITEM_PASS;
1629 }
1630
1631 /**
1632  * gst_bin_iterate_recurse:
1633  * @bin: a #GstBin
1634  *
1635  * Gets an iterator for the elements in this bin.
1636  * This iterator recurses into GstBin children.
1637  *
1638  * Each element yielded by the iterator will have its refcount increased, so
1639  * unref after use.
1640  *
1641  * MT safe.  Caller owns returned value.
1642  *
1643  * Returns: (transfer full): a #GstIterator of #GstElement, or NULL
1644  */
1645 GstIterator *
1646 gst_bin_iterate_recurse (GstBin * bin)
1647 {
1648   GstIterator *result;
1649
1650   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1651
1652   GST_OBJECT_LOCK (bin);
1653   result = gst_iterator_new_list (GST_TYPE_ELEMENT,
1654       GST_OBJECT_GET_LOCK (bin),
1655       &bin->children_cookie,
1656       &bin->children,
1657       (GObject *) bin, (GstIteratorItemFunction) iterate_child_recurse);
1658   GST_OBJECT_UNLOCK (bin);
1659
1660   return result;
1661 }
1662
1663 /* returns 0 when TRUE because this is a GCompareFunc */
1664 /* MT safe */
1665 static gint
1666 bin_element_is_sink (GstElement * child, GstBin * bin)
1667 {
1668   gboolean is_sink;
1669
1670   /* we lock the child here for the remainder of the function to
1671    * get its name and flag safely. */
1672   GST_OBJECT_LOCK (child);
1673   is_sink = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SINK);
1674
1675   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1676       "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
1677
1678   GST_OBJECT_UNLOCK (child);
1679   return is_sink ? 0 : 1;
1680 }
1681
1682 static gint
1683 sink_iterator_filter (const GValue * vchild, GValue * vbin)
1684 {
1685   GstBin *bin = g_value_get_object (vbin);
1686   GstElement *child = g_value_get_object (vchild);
1687
1688   return (bin_element_is_sink (child, bin));
1689 }
1690
1691 /**
1692  * gst_bin_iterate_sinks:
1693  * @bin: a #GstBin
1694  *
1695  * Gets an iterator for all elements in the bin that have the
1696  * #GST_ELEMENT_FLAG_SINK flag set.
1697  *
1698  * Each element yielded by the iterator will have its refcount increased, so
1699  * unref after use.
1700  *
1701  * MT safe.  Caller owns returned value.
1702  *
1703  * Returns: (transfer full): a #GstIterator of #GstElement, or NULL
1704  */
1705 GstIterator *
1706 gst_bin_iterate_sinks (GstBin * bin)
1707 {
1708   GstIterator *children;
1709   GstIterator *result;
1710   GValue vbin = { 0, };
1711
1712   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1713
1714   g_value_init (&vbin, GST_TYPE_BIN);
1715   g_value_set_object (&vbin, bin);
1716
1717   children = gst_bin_iterate_elements (bin);
1718   result = gst_iterator_filter (children,
1719       (GCompareFunc) sink_iterator_filter, &vbin);
1720
1721   g_value_unset (&vbin);
1722
1723   return result;
1724 }
1725
1726 /* returns 0 when TRUE because this is a GCompareFunc */
1727 /* MT safe */
1728 static gint
1729 bin_element_is_src (GstElement * child, GstBin * bin)
1730 {
1731   gboolean is_src;
1732
1733   /* we lock the child here for the remainder of the function to
1734    * get its name and other info safely. */
1735   GST_OBJECT_LOCK (child);
1736   is_src = GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_FLAG_SOURCE);
1737
1738   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
1739       "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not");
1740
1741   GST_OBJECT_UNLOCK (child);
1742   return is_src ? 0 : 1;
1743 }
1744
1745 static gint
1746 src_iterator_filter (const GValue * vchild, GValue * vbin)
1747 {
1748   GstBin *bin = g_value_get_object (vbin);
1749   GstElement *child = g_value_get_object (vchild);
1750
1751   return (bin_element_is_src (child, bin));
1752 }
1753
1754 /**
1755  * gst_bin_iterate_sources:
1756  * @bin: a #GstBin
1757  *
1758  * Gets an iterator for all elements in the bin that have the
1759  * #GST_ELEMENT_FLAG_SOURCE flag set.
1760  *
1761  * Each element yielded by the iterator will have its refcount increased, so
1762  * unref after use.
1763  *
1764  * MT safe.  Caller owns returned value.
1765  *
1766  * Returns: (transfer full): a #GstIterator of #GstElement, or NULL
1767  */
1768 GstIterator *
1769 gst_bin_iterate_sources (GstBin * bin)
1770 {
1771   GstIterator *children;
1772   GstIterator *result;
1773   GValue vbin = { 0, };
1774
1775   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1776
1777   g_value_init (&vbin, GST_TYPE_BIN);
1778   g_value_set_object (&vbin, bin);
1779
1780   children = gst_bin_iterate_elements (bin);
1781   result = gst_iterator_filter (children,
1782       (GCompareFunc) src_iterator_filter, &vbin);
1783
1784   g_value_unset (&vbin);
1785
1786   return result;
1787 }
1788
1789 /*
1790  * MT safe
1791  */
1792 static GstStateChangeReturn
1793 gst_bin_get_state_func (GstElement * element, GstState * state,
1794     GstState * pending, GstClockTime timeout)
1795 {
1796   GstStateChangeReturn ret;
1797
1798   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
1799
1800   ret =
1801       GST_ELEMENT_CLASS (parent_class)->get_state (element, state, pending,
1802       timeout);
1803
1804   return ret;
1805 }
1806
1807 /***********************************************
1808  * Topologically sorted iterator
1809  * see http://en.wikipedia.org/wiki/Topological_sorting
1810  *
1811  * For each element in the graph, an entry is kept in a HashTable
1812  * with its number of srcpad connections (degree).
1813  * We then change state of all elements without dependencies
1814  * (degree 0) and decrement the degree of all elements connected
1815  * on the sinkpads. When an element reaches degree 0, its state is
1816  * changed next.
1817  * When all elements are handled the algorithm stops.
1818  */
1819 typedef struct _GstBinSortIterator
1820 {
1821   GstIterator it;
1822   GQueue queue;                 /* elements queued for state change */
1823   GstBin *bin;                  /* bin we iterate */
1824   gint mode;                    /* adding or removing dependency */
1825   GstElement *best;             /* next element with least dependencies */
1826   gint best_deg;                /* best degree */
1827   GHashTable *hash;             /* hashtable with element dependencies */
1828   gboolean dirty;               /* we detected structure change */
1829 } GstBinSortIterator;
1830
1831 static void
1832 gst_bin_sort_iterator_copy (const GstBinSortIterator * it,
1833     GstBinSortIterator * copy)
1834 {
1835   GHashTableIter iter;
1836   gpointer key, value;
1837
1838   copy->queue = it->queue;
1839   g_queue_foreach (&copy->queue, (GFunc) gst_object_ref, NULL);
1840
1841   copy->bin = gst_object_ref (it->bin);
1842   if (it->best)
1843     copy->best = gst_object_ref (it->best);
1844
1845   copy->hash = g_hash_table_new (NULL, NULL);
1846   g_hash_table_iter_init (&iter, it->hash);
1847   while (g_hash_table_iter_next (&iter, &key, &value))
1848     g_hash_table_insert (copy->hash, key, value);
1849 }
1850
1851 /* we add and subtract 1 to make sure we don't confuse NULL and 0 */
1852 #define HASH_SET_DEGREE(bit, elem, deg) \
1853     g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1))
1854 #define HASH_GET_DEGREE(bit, elem) \
1855     (GPOINTER_TO_INT(g_hash_table_lookup (bit->hash, elem))-1)
1856
1857 /* add element to queue of next elements in the iterator.
1858  * We push at the tail to give higher priority elements a
1859  * chance first */
1860 static void
1861 add_to_queue (GstBinSortIterator * bit, GstElement * element)
1862 {
1863   GST_DEBUG_OBJECT (bit->bin, "adding '%s' to queue",
1864       GST_ELEMENT_NAME (element));
1865   gst_object_ref (element);
1866   g_queue_push_tail (&bit->queue, element);
1867   HASH_SET_DEGREE (bit, element, -1);
1868 }
1869
1870 static void
1871 remove_from_queue (GstBinSortIterator * bit, GstElement * element)
1872 {
1873   GList *find;
1874
1875   if ((find = g_queue_find (&bit->queue, element))) {
1876     GST_DEBUG_OBJECT (bit->bin, "removing '%s' from queue",
1877         GST_ELEMENT_NAME (element));
1878
1879     g_queue_delete_link (&bit->queue, find);
1880     gst_object_unref (element);
1881   } else {
1882     GST_DEBUG_OBJECT (bit->bin, "unable to remove '%s' from queue",
1883         GST_ELEMENT_NAME (element));
1884   }
1885 }
1886
1887 /* clear the queue, unref all objects as we took a ref when
1888  * we added them to the queue */
1889 static void
1890 clear_queue (GQueue * queue)
1891 {
1892   gpointer p;
1893
1894   while ((p = g_queue_pop_head (queue)))
1895     gst_object_unref (p);
1896 }
1897
1898 /* set all degrees to 0. Elements marked as a sink are
1899  * added to the queue immediately. Since we only look at the SINK flag of the
1900  * element, it is possible that we add non-sinks to the queue. These will be
1901  * removed from the queue again when we can prove that it provides data for some
1902  * other element. */
1903 static void
1904 reset_degree (GstElement * element, GstBinSortIterator * bit)
1905 {
1906   gboolean is_sink;
1907
1908   /* sinks are added right away */
1909   GST_OBJECT_LOCK (element);
1910   is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK);
1911   GST_OBJECT_UNLOCK (element);
1912
1913   if (is_sink) {
1914     add_to_queue (bit, element);
1915   } else {
1916     /* others are marked with 0 and handled when sinks are done */
1917     HASH_SET_DEGREE (bit, element, 0);
1918   }
1919 }
1920
1921 /* adjust the degree of all elements connected to the given
1922  * element. If a degree of an element drops to 0, it is
1923  * added to the queue of elements to schedule next.
1924  *
1925  * We have to make sure not to cross the bin boundary this element
1926  * belongs to.
1927  */
1928 static void
1929 update_degree (GstElement * element, GstBinSortIterator * bit)
1930 {
1931   gboolean linked = FALSE;
1932
1933   GST_OBJECT_LOCK (element);
1934   /* don't touch degree if element has no sinkpads */
1935   if (element->numsinkpads != 0) {
1936     /* loop over all sinkpads, decrement degree for all connected
1937      * elements in this bin */
1938     GList *pads;
1939
1940     for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
1941       GstPad *pad, *peer;
1942
1943       pad = GST_PAD_CAST (pads->data);
1944
1945       /* we're iterating over the sinkpads, check if it's busy in a link/unlink */
1946       if (G_UNLIKELY (find_message (bit->bin, GST_OBJECT_CAST (pad),
1947                   GST_MESSAGE_STRUCTURE_CHANGE))) {
1948         /* mark the iterator as dirty because we won't be updating the degree
1949          * of the peer parent now. This would result in the 'loop detected'
1950          * later on because the peer parent element could become the best next
1951          * element with a degree > 0. We will simply continue our state
1952          * changes and we'll eventually resync when the unlink completed and
1953          * the iterator cookie is updated. */
1954         bit->dirty = TRUE;
1955         continue;
1956       }
1957
1958       if ((peer = gst_pad_get_peer (pad))) {
1959         GstElement *peer_element;
1960
1961         if ((peer_element = gst_pad_get_parent_element (peer))) {
1962           GST_OBJECT_LOCK (peer_element);
1963           /* check that we don't go outside of this bin */
1964           if (GST_OBJECT_CAST (peer_element)->parent ==
1965               GST_OBJECT_CAST (bit->bin)) {
1966             gint old_deg, new_deg;
1967
1968             old_deg = HASH_GET_DEGREE (bit, peer_element);
1969
1970             /* check to see if we added an element as sink that was not really a
1971              * sink because it was connected to some other element. */
1972             if (old_deg == -1) {
1973               remove_from_queue (bit, peer_element);
1974               old_deg = 0;
1975             }
1976             new_deg = old_deg + bit->mode;
1977
1978             GST_DEBUG_OBJECT (bit->bin,
1979                 "change element %s, degree %d->%d, linked to %s",
1980                 GST_ELEMENT_NAME (peer_element), old_deg, new_deg,
1981                 GST_ELEMENT_NAME (element));
1982
1983             /* update degree, it is possible that an element was in 0 and
1984              * reaches -1 here. This would mean that the element had no sinkpads
1985              * but became linked while the state change was happening. We will
1986              * resync on this with the structure change message. */
1987             if (new_deg == 0) {
1988               /* degree hit 0, add to queue */
1989               add_to_queue (bit, peer_element);
1990             } else {
1991               HASH_SET_DEGREE (bit, peer_element, new_deg);
1992             }
1993             linked = TRUE;
1994           }
1995           GST_OBJECT_UNLOCK (peer_element);
1996           gst_object_unref (peer_element);
1997         }
1998         gst_object_unref (peer);
1999       }
2000     }
2001   }
2002   if (!linked) {
2003     GST_DEBUG_OBJECT (bit->bin, "element %s not linked on any sinkpads",
2004         GST_ELEMENT_NAME (element));
2005   }
2006   GST_OBJECT_UNLOCK (element);
2007 }
2008
2009 /* find the next best element not handled yet. This is the one
2010  * with the lowest non-negative degree */
2011 static void
2012 find_element (GstElement * element, GstBinSortIterator * bit)
2013 {
2014   gint degree;
2015
2016   /* element is already handled */
2017   if ((degree = HASH_GET_DEGREE (bit, element)) < 0)
2018     return;
2019
2020   /* first element or element with smaller degree */
2021   if (bit->best == NULL || bit->best_deg > degree) {
2022     bit->best = element;
2023     bit->best_deg = degree;
2024   }
2025 }
2026
2027 /* get next element in iterator. the returned element has the
2028  * refcount increased */
2029 static GstIteratorResult
2030 gst_bin_sort_iterator_next (GstBinSortIterator * bit, GValue * result)
2031 {
2032   GstElement *best;
2033   GstBin *bin = bit->bin;
2034
2035   /* empty queue, we have to find a next best element */
2036   if (g_queue_is_empty (&bit->queue)) {
2037     bit->best = NULL;
2038     bit->best_deg = G_MAXINT;
2039     g_list_foreach (bin->children, (GFunc) find_element, bit);
2040     if ((best = bit->best)) {
2041       /* when we detected an unlink, don't warn because our degrees might be
2042        * screwed up. We will resync later */
2043       if (bit->best_deg != 0 && !bit->dirty) {
2044         /* we don't fail on this one yet */
2045         GST_WARNING_OBJECT (bin, "loop dected in graph");
2046         g_warning ("loop detected in the graph of bin '%s'!!",
2047             GST_ELEMENT_NAME (bin));
2048       }
2049       /* best unhandled element, schedule as next element */
2050       GST_DEBUG_OBJECT (bin, "queue empty, next best: %s",
2051           GST_ELEMENT_NAME (best));
2052       HASH_SET_DEGREE (bit, best, -1);
2053       g_value_set_object (result, best);
2054     } else {
2055       GST_DEBUG_OBJECT (bin, "queue empty, elements exhausted");
2056       /* no more unhandled elements, we are done */
2057       return GST_ITERATOR_DONE;
2058     }
2059   } else {
2060     /* everything added to the queue got reffed */
2061     best = g_queue_pop_head (&bit->queue);
2062     g_value_set_object (result, best);
2063     gst_object_unref (best);
2064   }
2065
2066   GST_DEBUG_OBJECT (bin, "queue head gives %s", GST_ELEMENT_NAME (best));
2067   /* update degrees of linked elements */
2068   update_degree (best, bit);
2069
2070   return GST_ITERATOR_OK;
2071 }
2072
2073 /* clear queues, recalculate the degrees and restart. */
2074 static void
2075 gst_bin_sort_iterator_resync (GstBinSortIterator * bit)
2076 {
2077   GstBin *bin = bit->bin;
2078
2079   GST_DEBUG_OBJECT (bin, "resync");
2080   bit->dirty = FALSE;
2081   clear_queue (&bit->queue);
2082   /* reset degrees */
2083   g_list_foreach (bin->children, (GFunc) reset_degree, bit);
2084   /* calc degrees, incrementing */
2085   bit->mode = 1;
2086   g_list_foreach (bin->children, (GFunc) update_degree, bit);
2087   /* for the rest of the function we decrement the degrees */
2088   bit->mode = -1;
2089 }
2090
2091 /* clear queues, unref bin and free iterator. */
2092 static void
2093 gst_bin_sort_iterator_free (GstBinSortIterator * bit)
2094 {
2095   GstBin *bin = bit->bin;
2096
2097   GST_DEBUG_OBJECT (bin, "free");
2098   clear_queue (&bit->queue);
2099   g_hash_table_destroy (bit->hash);
2100   gst_object_unref (bin);
2101 }
2102
2103 /* should be called with the bin LOCK held */
2104 static GstIterator *
2105 gst_bin_sort_iterator_new (GstBin * bin)
2106 {
2107   GstBinSortIterator *result;
2108
2109   /* we don't need an ItemFunction because we ref the items in the _next
2110    * method already */
2111   result = (GstBinSortIterator *)
2112       gst_iterator_new (sizeof (GstBinSortIterator),
2113       GST_TYPE_ELEMENT,
2114       GST_OBJECT_GET_LOCK (bin),
2115       &bin->priv->structure_cookie,
2116       (GstIteratorCopyFunction) gst_bin_sort_iterator_copy,
2117       (GstIteratorNextFunction) gst_bin_sort_iterator_next,
2118       (GstIteratorItemFunction) NULL,
2119       (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
2120       (GstIteratorFreeFunction) gst_bin_sort_iterator_free);
2121   g_queue_init (&result->queue);
2122   result->hash = g_hash_table_new (NULL, NULL);
2123   gst_object_ref (bin);
2124   result->bin = bin;
2125   gst_bin_sort_iterator_resync (result);
2126
2127   return (GstIterator *) result;
2128 }
2129
2130 /**
2131  * gst_bin_iterate_sorted:
2132  * @bin: a #GstBin
2133  *
2134  * Gets an iterator for the elements in this bin in topologically
2135  * sorted order. This means that the elements are returned from
2136  * the most downstream elements (sinks) to the sources.
2137  *
2138  * This function is used internally to perform the state changes
2139  * of the bin elements and for clock selection.
2140  *
2141  * Each element yielded by the iterator will have its refcount increased, so
2142  * unref after use.
2143  *
2144  * MT safe.  Caller owns returned value.
2145  *
2146  * Returns: (transfer full): a #GstIterator of #GstElement, or NULL
2147  */
2148 GstIterator *
2149 gst_bin_iterate_sorted (GstBin * bin)
2150 {
2151   GstIterator *result;
2152
2153   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
2154
2155   GST_OBJECT_LOCK (bin);
2156   result = gst_bin_sort_iterator_new (bin);
2157   GST_OBJECT_UNLOCK (bin);
2158
2159   return result;
2160 }
2161
2162 static GstStateChangeReturn
2163 gst_bin_element_set_state (GstBin * bin, GstElement * element,
2164     GstClockTime base_time, GstClockTime start_time, GstState current,
2165     GstState next)
2166 {
2167   GstStateChangeReturn ret;
2168   GstState pending, child_current, child_pending;
2169   gboolean locked;
2170   GList *found;
2171
2172   GST_STATE_LOCK (element);
2173
2174   GST_OBJECT_LOCK (element);
2175   /* set base_time and start time on child */
2176   GST_ELEMENT_START_TIME (element) = start_time;
2177   element->base_time = base_time;
2178   /* peel off the locked flag */
2179   locked = GST_ELEMENT_IS_LOCKED_STATE (element);
2180   /* Get the previous set_state result to preserve NO_PREROLL and ASYNC */
2181   ret = GST_STATE_RETURN (element);
2182   child_current = GST_STATE (element);
2183   child_pending = GST_STATE_PENDING (element);
2184   GST_OBJECT_UNLOCK (element);
2185
2186   /* skip locked elements */
2187   if (G_UNLIKELY (locked))
2188     goto locked;
2189
2190   /* if the element was no preroll, just start changing the state regardless
2191    * if it had async elements (in the case of a bin) because they won't preroll
2192    * anyway. */
2193   if (G_UNLIKELY (ret == GST_STATE_CHANGE_NO_PREROLL)) {
2194     GST_DEBUG_OBJECT (element, "element is NO_PREROLL, ignore async elements");
2195     goto no_preroll;
2196   }
2197
2198   GST_OBJECT_LOCK (bin);
2199   pending = GST_STATE_PENDING (bin);
2200
2201   /* Try not to change the state of elements that are already in the state we're
2202    * going to */
2203   if (!(next == GST_STATE_PLAYING || child_pending != GST_STATE_VOID_PENDING ||
2204           (child_pending == GST_STATE_VOID_PENDING &&
2205               ((pending > child_current && next > child_current) ||
2206                   (pending < child_current && next < child_current)))))
2207     goto unneeded;
2208
2209   /* the element was busy with an upwards async state change, we must wait for
2210    * an ASYNC_DONE message before we attemp to change the state. */
2211   if ((found =
2212           find_message (bin, GST_OBJECT_CAST (element),
2213               GST_MESSAGE_ASYNC_START))) {
2214 #ifndef GST_DISABLE_GST_DEBUG
2215     GstMessage *message = GST_MESSAGE_CAST (found->data);
2216
2217     GST_DEBUG_OBJECT (element, "element message %p, %s async busy",
2218         message, GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)));
2219 #endif
2220     /* only wait for upward state changes */
2221     if (next > current) {
2222       /* We found an async element check if we can force its state to change or
2223        * if we have to wait for it to preroll. */
2224       if (G_UNLIKELY (!enable_latency)) {
2225         g_warning ("Future versions of GStreamer will wait for element \"%s\"\n"
2226             "\tto preroll in order to perform correct latency calculations.\n"
2227             "\tPlease verify that the application continues to work correctly by\n"
2228             "\tsetting the environment variable GST_COMPAT to a value containing\n"
2229             "\tthe string 'live-preroll'.", GST_ELEMENT_NAME (element));
2230         goto no_latency;
2231       }
2232       goto was_busy;
2233     }
2234   }
2235 no_latency:
2236   GST_OBJECT_UNLOCK (bin);
2237
2238 no_preroll:
2239   GST_DEBUG_OBJECT (bin,
2240       "setting element %s to %s, base_time %" GST_TIME_FORMAT,
2241       GST_ELEMENT_NAME (element), gst_element_state_get_name (next),
2242       GST_TIME_ARGS (base_time));
2243
2244   /* change state */
2245   ret = gst_element_set_state (element, next);
2246
2247   GST_STATE_UNLOCK (element);
2248
2249   return ret;
2250
2251 locked:
2252   {
2253     GST_DEBUG_OBJECT (element,
2254         "element is locked, return previous return %s",
2255         gst_element_state_change_return_get_name (ret));
2256     GST_STATE_UNLOCK (element);
2257     return ret;
2258   }
2259 was_busy:
2260   {
2261     GST_DEBUG_OBJECT (element, "element was busy, delaying state change");
2262     GST_OBJECT_UNLOCK (bin);
2263     GST_STATE_UNLOCK (element);
2264     return GST_STATE_CHANGE_ASYNC;
2265   }
2266 unneeded:
2267   {
2268     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2269         "skipping transition from %s to  %s, since bin pending"
2270         " is %s : last change state return follows",
2271         gst_element_state_get_name (child_current),
2272         gst_element_state_get_name (next),
2273         gst_element_state_get_name (pending));
2274     GST_OBJECT_UNLOCK (bin);
2275     GST_STATE_UNLOCK (element);
2276     return ret;
2277   }
2278 }
2279
2280 /* gst_iterator_fold functions for pads_activate
2281  * Stop the iterator if activating one pad failed. */
2282 static gboolean
2283 activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
2284 {
2285   GstPad *pad = g_value_get_object (vpad);
2286   gboolean cont = TRUE;
2287
2288   if (!(cont = gst_pad_set_active (pad, *active)))
2289     g_value_set_boolean (ret, FALSE);
2290
2291   return cont;
2292 }
2293
2294 /* returns false on error or early cutout of the fold, true if all
2295  * pads in @iter were (de)activated successfully. */
2296 static gboolean
2297 iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data)
2298 {
2299   GstIteratorResult ires;
2300   GValue ret = { 0 };
2301
2302   /* no need to unset this later, it's just a boolean */
2303   g_value_init (&ret, G_TYPE_BOOLEAN);
2304   g_value_set_boolean (&ret, TRUE);
2305
2306   while (1) {
2307     ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) activate_pads,
2308         &ret, user_data);
2309     switch (ires) {
2310       case GST_ITERATOR_RESYNC:
2311         /* need to reset the result again */
2312         g_value_set_boolean (&ret, TRUE);
2313         gst_iterator_resync (iter);
2314         break;
2315       case GST_ITERATOR_DONE:
2316         /* all pads iterated, return collected value */
2317         goto done;
2318       default:
2319         /* iterator returned _ERROR or premature end with _OK,
2320          * mark an error and exit */
2321         g_value_set_boolean (&ret, FALSE);
2322         goto done;
2323     }
2324   }
2325 done:
2326   /* return collected value */
2327   return g_value_get_boolean (&ret);
2328 }
2329
2330 /* is called with STATE_LOCK
2331  */
2332 static gboolean
2333 gst_bin_src_pads_activate (GstBin * bin, gboolean active)
2334 {
2335   GstIterator *iter;
2336   gboolean fold_ok;
2337
2338   GST_DEBUG_OBJECT (bin, "src_pads_activate with active %d", active);
2339
2340   iter = gst_element_iterate_src_pads ((GstElement *) bin);
2341   fold_ok = iterator_activate_fold_with_resync (iter, &active);
2342   gst_iterator_free (iter);
2343   if (G_UNLIKELY (!fold_ok))
2344     goto failed;
2345
2346   GST_DEBUG_OBJECT (bin, "pads_activate successful");
2347
2348   return TRUE;
2349
2350   /* ERRORS */
2351 failed:
2352   {
2353     GST_DEBUG_OBJECT (bin, "source pads_activate failed");
2354     return FALSE;
2355   }
2356 }
2357
2358 /**
2359  * gst_bin_recalculate_latency:
2360  * @bin: a #GstBin
2361  *
2362  * Query @bin for the current latency using and reconfigures this latency to all the
2363  * elements with a LATENCY event.
2364  *
2365  * This method is typically called on the pipeline when a #GST_MESSAGE_LATENCY
2366  * is posted on the bus.
2367  *
2368  * This function simply emits the 'do-latency' signal so any custom latency
2369  * calculations will be performed.
2370  *
2371  * Returns: %TRUE if the latency could be queried and reconfigured.
2372  *
2373  * Since: 0.10.22.
2374  */
2375 gboolean
2376 gst_bin_recalculate_latency (GstBin * bin)
2377 {
2378   gboolean res;
2379
2380   g_signal_emit (bin, gst_bin_signals[DO_LATENCY], 0, &res);
2381   GST_DEBUG_OBJECT (bin, "latency returned %d", res);
2382
2383   return res;
2384 }
2385
2386 static gboolean
2387 gst_bin_do_latency_func (GstBin * bin)
2388 {
2389   GstQuery *query;
2390   GstElement *element;
2391   GstClockTime min_latency, max_latency;
2392   gboolean res;
2393
2394   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
2395
2396   element = GST_ELEMENT_CAST (bin);
2397
2398   GST_DEBUG_OBJECT (element, "querying latency");
2399
2400   query = gst_query_new_latency ();
2401   if ((res = gst_element_query (element, query))) {
2402     gboolean live;
2403
2404     gst_query_parse_latency (query, &live, &min_latency, &max_latency);
2405
2406     GST_DEBUG_OBJECT (element,
2407         "got min latency %" GST_TIME_FORMAT ", max latency %"
2408         GST_TIME_FORMAT ", live %d", GST_TIME_ARGS (min_latency),
2409         GST_TIME_ARGS (max_latency), live);
2410
2411     if (max_latency < min_latency) {
2412       /* this is an impossible situation, some parts of the pipeline might not
2413        * work correctly. We post a warning for now. */
2414       GST_ELEMENT_WARNING (element, CORE, CLOCK, (NULL),
2415           ("Impossible to configure latency: max %" GST_TIME_FORMAT " < min %"
2416               GST_TIME_FORMAT ". Add queues or other buffering elements.",
2417               GST_TIME_ARGS (max_latency), GST_TIME_ARGS (min_latency)));
2418     }
2419
2420     /* configure latency on elements */
2421     res = gst_element_send_event (element, gst_event_new_latency (min_latency));
2422     if (res) {
2423       GST_INFO_OBJECT (element, "configured latency of %" GST_TIME_FORMAT,
2424           GST_TIME_ARGS (min_latency));
2425     } else {
2426       GST_WARNING_OBJECT (element,
2427           "did not really configure latency of %" GST_TIME_FORMAT,
2428           GST_TIME_ARGS (min_latency));
2429     }
2430   } else {
2431     /* this is not a real problem, we just don't configure any latency. */
2432     GST_WARNING_OBJECT (element, "failed to query latency");
2433   }
2434   gst_query_unref (query);
2435
2436   return res;
2437 }
2438
2439 static void
2440 gst_bin_state_changed (GstElement * element, GstState oldstate,
2441     GstState newstate, GstState pending)
2442 {
2443   GstElementClass *pklass = (GstElementClass *) parent_class;
2444
2445   if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING)
2446     bin_do_eos (GST_BIN_CAST (element));
2447
2448   if (pklass->state_changed)
2449     pklass->state_changed (element, oldstate, newstate, pending);
2450 }
2451
2452 static GstStateChangeReturn
2453 gst_bin_change_state_func (GstElement * element, GstStateChange transition)
2454 {
2455   GstBin *bin;
2456   GstStateChangeReturn ret;
2457   GstState current, next;
2458   gboolean have_async;
2459   gboolean have_no_preroll;
2460   GstClockTime base_time, start_time;
2461   GstIterator *it;
2462   gboolean done;
2463   GValue data = { 0, };
2464
2465   /* we don't need to take the STATE_LOCK, it is already taken */
2466   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
2467   next = (GstState) GST_STATE_TRANSITION_NEXT (transition);
2468
2469   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2470       "changing state of children from %s to %s",
2471       gst_element_state_get_name (current), gst_element_state_get_name (next));
2472
2473   bin = GST_BIN_CAST (element);
2474
2475   switch (next) {
2476     case GST_STATE_PLAYING:
2477     {
2478       gboolean toplevel;
2479
2480       GST_OBJECT_LOCK (bin);
2481       toplevel = BIN_IS_TOPLEVEL (bin);
2482       GST_OBJECT_UNLOCK (bin);
2483
2484       if (toplevel)
2485         gst_bin_recalculate_latency (bin);
2486       break;
2487     }
2488     case GST_STATE_PAUSED:
2489       /* Clear EOS list on next PAUSED */
2490       GST_OBJECT_LOCK (bin);
2491       GST_DEBUG_OBJECT (element, "clearing EOS elements");
2492       bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
2493       bin->priv->posted_eos = FALSE;
2494       GST_OBJECT_UNLOCK (bin);
2495       if (current == GST_STATE_READY)
2496         if (!(gst_bin_src_pads_activate (bin, TRUE)))
2497           goto activate_failure;
2498       break;
2499     case GST_STATE_READY:
2500       /* Clear message list on next READY */
2501       GST_OBJECT_LOCK (bin);
2502       GST_DEBUG_OBJECT (element, "clearing all cached messages");
2503       bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
2504       GST_OBJECT_UNLOCK (bin);
2505       if (current == GST_STATE_PAUSED)
2506         if (!(gst_bin_src_pads_activate (bin, FALSE)))
2507           goto activate_failure;
2508       break;
2509     case GST_STATE_NULL:
2510       if (current == GST_STATE_READY)
2511         if (!(gst_bin_src_pads_activate (bin, FALSE)))
2512           goto activate_failure;
2513       break;
2514     default:
2515       break;
2516   }
2517
2518   /* this flag is used to make the async state changes return immediately. We
2519    * don't want them to interfere with this state change */
2520   GST_OBJECT_LOCK (bin);
2521   bin->polling = TRUE;
2522   GST_OBJECT_UNLOCK (bin);
2523
2524   /* iterate in state change order */
2525   it = gst_bin_iterate_sorted (bin);
2526
2527   /* mark if we've seen an ASYNC element in the bin when we did a state change.
2528    * Note how we don't reset this value when a resync happens, the reason being
2529    * that the async element posted ASYNC_START and we want to post ASYNC_DONE
2530    * even after a resync when the async element is gone */
2531   have_async = FALSE;
2532
2533 restart:
2534   /* take base_time */
2535   base_time = gst_element_get_base_time (element);
2536   start_time = gst_element_get_start_time (element);
2537
2538   have_no_preroll = FALSE;
2539
2540   done = FALSE;
2541   while (!done) {
2542     switch (gst_iterator_next (it, &data)) {
2543       case GST_ITERATOR_OK:
2544       {
2545         GstElement *child;
2546
2547         child = g_value_get_object (&data);
2548
2549         /* set state and base_time now */
2550         ret = gst_bin_element_set_state (bin, child, base_time, start_time,
2551             current, next);
2552
2553         switch (ret) {
2554           case GST_STATE_CHANGE_SUCCESS:
2555             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2556                 "child '%s' changed state to %d(%s) successfully",
2557                 GST_ELEMENT_NAME (child), next,
2558                 gst_element_state_get_name (next));
2559             break;
2560           case GST_STATE_CHANGE_ASYNC:
2561           {
2562             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2563                 "child '%s' is changing state asynchronously to %s",
2564                 GST_ELEMENT_NAME (child), gst_element_state_get_name (next));
2565             have_async = TRUE;
2566             break;
2567           }
2568           case GST_STATE_CHANGE_FAILURE:{
2569             GstObject *parent;
2570
2571             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2572                 "child '%s' failed to go to state %d(%s)",
2573                 GST_ELEMENT_NAME (child),
2574                 next, gst_element_state_get_name (next));
2575
2576             /* Only fail if the child is still inside
2577              * this bin. It might've been removed already
2578              * because of the error by the bin subclass
2579              * to ignore the error.  */
2580             parent = gst_object_get_parent (GST_OBJECT_CAST (child));
2581             if (parent == GST_OBJECT_CAST (element)) {
2582               /* element is still in bin, really error now */
2583               gst_object_unref (parent);
2584               goto done;
2585             }
2586             /* child removed from bin, let the resync code redo the state
2587              * change */
2588             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2589                 "child '%s' was removed from the bin",
2590                 GST_ELEMENT_NAME (child));
2591
2592             if (parent)
2593               gst_object_unref (parent);
2594
2595             break;
2596           }
2597           case GST_STATE_CHANGE_NO_PREROLL:
2598             GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2599                 "child '%s' changed state to %d(%s) successfully without preroll",
2600                 GST_ELEMENT_NAME (child), next,
2601                 gst_element_state_get_name (next));
2602             have_no_preroll = TRUE;
2603             break;
2604           default:
2605             g_assert_not_reached ();
2606             break;
2607         }
2608         g_value_reset (&data);
2609         break;
2610       }
2611       case GST_ITERATOR_RESYNC:
2612         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "iterator doing resync");
2613         gst_iterator_resync (it);
2614         goto restart;
2615       default:
2616       case GST_ITERATOR_DONE:
2617         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "iterator done");
2618         done = TRUE;
2619         break;
2620     }
2621   }
2622
2623   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2624   if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
2625     goto done;
2626
2627   if (have_no_preroll) {
2628     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
2629         "we have NO_PREROLL elements %s -> NO_PREROLL",
2630         gst_element_state_change_return_get_name (ret));
2631     ret = GST_STATE_CHANGE_NO_PREROLL;
2632   } else if (have_async) {
2633     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
2634         "we have ASYNC elements %s -> ASYNC",
2635         gst_element_state_change_return_get_name (ret));
2636     ret = GST_STATE_CHANGE_ASYNC;
2637   }
2638
2639 done:
2640   g_value_unset (&data);
2641   gst_iterator_free (it);
2642
2643   GST_OBJECT_LOCK (bin);
2644   bin->polling = FALSE;
2645   /* it's possible that we did not get ASYNC from the children while the bin is
2646    * simulating ASYNC behaviour by posting an ASYNC_DONE message on the bus with
2647    * itself as the source. In that case we still want to check if the state
2648    * change completed. */
2649   if (ret != GST_STATE_CHANGE_ASYNC && !bin->priv->pending_async_done) {
2650     /* no element returned ASYNC and there are no pending async_done messages,
2651      * we can just complete. */
2652     GST_DEBUG_OBJECT (bin, "no async elements");
2653     goto state_end;
2654   }
2655   /* when we get here an ASYNC element was found */
2656   if (GST_STATE_TARGET (bin) <= GST_STATE_READY) {
2657     /* we ignore ASYNC state changes when we go to READY or NULL */
2658     GST_DEBUG_OBJECT (bin, "target state %s <= READY",
2659         gst_element_state_get_name (GST_STATE_TARGET (bin)));
2660     goto state_end;
2661   }
2662
2663   GST_DEBUG_OBJECT (bin, "check async elements");
2664   /* check if all elements managed to commit their state already */
2665   if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) {
2666     /* nothing found, remove all old ASYNC_DONE messages. This can happen when
2667      * all the elements commited their state while we were doing the state
2668      * change. We will still return ASYNC for consistency but we commit the
2669      * state already so that a _get_state() will return immediately. */
2670     bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
2671
2672     GST_DEBUG_OBJECT (bin, "async elements commited");
2673     bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, FALSE, FALSE);
2674   }
2675
2676 state_end:
2677   bin->priv->pending_async_done = FALSE;
2678   GST_OBJECT_UNLOCK (bin);
2679
2680   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2681       "done changing bin's state from %s to %s, now in %s, ret %s",
2682       gst_element_state_get_name (current),
2683       gst_element_state_get_name (next),
2684       gst_element_state_get_name (GST_STATE (element)),
2685       gst_element_state_change_return_get_name (ret));
2686
2687   return ret;
2688
2689   /* ERRORS */
2690 activate_failure:
2691   {
2692     GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element,
2693         "failure (de)activating src pads");
2694     return GST_STATE_CHANGE_FAILURE;
2695   }
2696 }
2697
2698 /*
2699  * This function is a utility event handler for seek events.
2700  * It will send the event to all sinks or sources depending on the
2701  * event-direction.
2702  *
2703  * Applications are free to override this behaviour and
2704  * implement their own seek handler, but this will work for
2705  * pretty much all cases in practice.
2706  */
2707 static gboolean
2708 gst_bin_send_event (GstElement * element, GstEvent * event)
2709 {
2710   GstBin *bin = GST_BIN_CAST (element);
2711   GstIterator *iter;
2712   gboolean res = TRUE;
2713   gboolean done = FALSE;
2714   GValue data = { 0, };
2715
2716   if (GST_EVENT_IS_DOWNSTREAM (event)) {
2717     iter = gst_bin_iterate_sources (bin);
2718     GST_DEBUG_OBJECT (bin, "Sending %s event to src children",
2719         GST_EVENT_TYPE_NAME (event));
2720   } else {
2721     iter = gst_bin_iterate_sinks (bin);
2722     GST_DEBUG_OBJECT (bin, "Sending %s event to sink children",
2723         GST_EVENT_TYPE_NAME (event));
2724   }
2725
2726   while (!done) {
2727     switch (gst_iterator_next (iter, &data)) {
2728       case GST_ITERATOR_OK:
2729       {
2730         GstElement *child = g_value_get_object (&data);;
2731
2732         gst_event_ref (event);
2733         res &= gst_element_send_event (child, event);
2734         GST_LOG_OBJECT (child, "After handling %s event: %d",
2735             GST_EVENT_TYPE_NAME (event), res);
2736         break;
2737       }
2738       case GST_ITERATOR_RESYNC:
2739         gst_iterator_resync (iter);
2740         res = TRUE;
2741         break;
2742       case GST_ITERATOR_DONE:
2743         done = TRUE;
2744         break;
2745       case GST_ITERATOR_ERROR:
2746         g_assert_not_reached ();
2747         break;
2748     }
2749   }
2750   g_value_unset (&data);
2751   gst_iterator_free (iter);
2752   gst_event_unref (event);
2753
2754   return res;
2755 }
2756
2757 /* this is the function called by the threadpool. When async elements commit
2758  * their state, this function will attempt to bring the bin to the next state.
2759  */
2760 static void
2761 gst_bin_continue_func (BinContinueData * data)
2762 {
2763   GstBin *bin;
2764   GstState current, next, pending;
2765   GstStateChange transition;
2766
2767   bin = data->bin;
2768   pending = data->pending;
2769
2770   GST_DEBUG_OBJECT (bin, "waiting for state lock");
2771   GST_STATE_LOCK (bin);
2772
2773   GST_DEBUG_OBJECT (bin, "doing state continue");
2774   GST_OBJECT_LOCK (bin);
2775
2776   /* if a new state change happened after this thread was scheduled, we return
2777    * immediately. */
2778   if (data->cookie != GST_ELEMENT_CAST (bin)->state_cookie)
2779     goto interrupted;
2780
2781   current = GST_STATE (bin);
2782   next = GST_STATE_GET_NEXT (current, pending);
2783   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2784
2785   GST_STATE_NEXT (bin) = next;
2786   GST_STATE_PENDING (bin) = pending;
2787   /* mark busy */
2788   GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
2789   GST_OBJECT_UNLOCK (bin);
2790
2791   GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
2792       "continue state change %s to %s, final %s",
2793       gst_element_state_get_name (current),
2794       gst_element_state_get_name (next), gst_element_state_get_name (pending));
2795
2796   gst_element_change_state (GST_ELEMENT_CAST (bin), transition);
2797
2798   GST_STATE_UNLOCK (bin);
2799   GST_DEBUG_OBJECT (bin, "state continue done");
2800
2801   gst_object_unref (bin);
2802   g_slice_free (BinContinueData, data);
2803   return;
2804
2805 interrupted:
2806   {
2807     GST_OBJECT_UNLOCK (bin);
2808     GST_STATE_UNLOCK (bin);
2809     GST_DEBUG_OBJECT (bin, "state continue aborted due to intervening change");
2810     gst_object_unref (bin);
2811     g_slice_free (BinContinueData, data);
2812     return;
2813   }
2814 }
2815
2816 static GstBusSyncReply
2817 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
2818 {
2819   GstBinClass *bclass;
2820
2821   bclass = GST_BIN_GET_CLASS (bin);
2822   if (bclass->handle_message)
2823     bclass->handle_message (bin, message);
2824   else
2825     gst_message_unref (message);
2826
2827   return GST_BUS_DROP;
2828 }
2829
2830 static void
2831 bin_push_state_continue (BinContinueData * data)
2832 {
2833   GstBinClass *klass;
2834   GstBin *bin;
2835
2836   /* ref was taken */
2837   bin = data->bin;
2838   klass = GST_BIN_GET_CLASS (bin);
2839
2840   GST_DEBUG_OBJECT (bin, "pushing continue on thread pool");
2841   g_thread_pool_push (klass->pool, data, NULL);
2842 }
2843
2844 /* an element started an async state change, if we were not busy with a state
2845  * change, we perform a lost state.
2846  * This function is called with the OBJECT lock.
2847  */
2848 static void
2849 bin_handle_async_start (GstBin * bin)
2850 {
2851   GstState old_state, new_state;
2852   gboolean toplevel;
2853   GstMessage *amessage = NULL;
2854
2855   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE)
2856     goto had_error;
2857
2858   /* get our toplevel state */
2859   toplevel = BIN_IS_TOPLEVEL (bin);
2860
2861   /* prepare an ASYNC_START message, we always post the start message even if we
2862    * are busy with a state change or when we are NO_PREROLL. */
2863   if (!toplevel)
2864     /* non toplevel bin, prepare async-start for the parent */
2865     amessage = gst_message_new_async_start (GST_OBJECT_CAST (bin));
2866
2867   if (bin->polling || GST_STATE_PENDING (bin) != GST_STATE_VOID_PENDING)
2868     goto was_busy;
2869
2870   /* async starts are ignored when we are NO_PREROLL */
2871   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_NO_PREROLL)
2872     goto was_no_preroll;
2873
2874   old_state = GST_STATE (bin);
2875
2876   /* when we PLAYING we go back to PAUSED, when preroll happens, we go back to
2877    * PLAYING after optionally redistributing the base_time. */
2878   if (old_state > GST_STATE_PAUSED)
2879     new_state = GST_STATE_PAUSED;
2880   else
2881     new_state = old_state;
2882
2883   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
2884       "lost state of %s, new %s", gst_element_state_get_name (old_state),
2885       gst_element_state_get_name (new_state));
2886
2887   GST_STATE (bin) = new_state;
2888   GST_STATE_NEXT (bin) = new_state;
2889   GST_STATE_PENDING (bin) = new_state;
2890   GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
2891   GST_OBJECT_UNLOCK (bin);
2892
2893   /* post message */
2894   _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), new_state, new_state,
2895       new_state);
2896
2897 post_start:
2898   if (amessage) {
2899     /* post our ASYNC_START. */
2900     GST_DEBUG_OBJECT (bin, "posting ASYNC_START to parent");
2901     gst_element_post_message (GST_ELEMENT_CAST (bin), amessage);
2902   }
2903   GST_OBJECT_LOCK (bin);
2904
2905   return;
2906
2907 had_error:
2908   {
2909     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "we had an error");
2910     return;
2911   }
2912 was_busy:
2913   {
2914     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy");
2915     GST_OBJECT_UNLOCK (bin);
2916     goto post_start;
2917   }
2918 was_no_preroll:
2919   {
2920     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "ignoring, we are NO_PREROLL");
2921     GST_OBJECT_UNLOCK (bin);
2922     goto post_start;
2923   }
2924 }
2925
2926 /* this function is called when there are no more async elements in the bin. We
2927  * post a state changed message and an ASYNC_DONE message.
2928  * This function is called with the OBJECT lock.
2929  */
2930 static void
2931 bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
2932     gboolean flag_pending, gboolean reset_time)
2933 {
2934   GstState current, pending, target;
2935   GstStateChangeReturn old_ret;
2936   GstState old_state, old_next;
2937   gboolean toplevel, state_changed = FALSE;
2938   GstMessage *amessage = NULL;
2939   BinContinueData *cont = NULL;
2940
2941   if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE)
2942     goto had_error;
2943
2944   pending = GST_STATE_PENDING (bin);
2945
2946   if (bin->polling)
2947     goto was_busy;
2948
2949   /* check if there is something to commit */
2950   if (pending == GST_STATE_VOID_PENDING)
2951     goto nothing_pending;
2952
2953   old_ret = GST_STATE_RETURN (bin);
2954   GST_STATE_RETURN (bin) = ret;
2955
2956   /* move to the next target state */
2957   target = GST_STATE_TARGET (bin);
2958   pending = GST_STATE_PENDING (bin) = target;
2959
2960   amessage = gst_message_new_async_done (GST_OBJECT_CAST (bin), reset_time);
2961
2962   old_state = GST_STATE (bin);
2963   /* this is the state we should go to next */
2964   old_next = GST_STATE_NEXT (bin);
2965
2966   if (old_next != GST_STATE_PLAYING) {
2967     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
2968         "committing state from %s to %s, old pending %s",
2969         gst_element_state_get_name (old_state),
2970         gst_element_state_get_name (old_next),
2971         gst_element_state_get_name (pending));
2972
2973     /* update current state */
2974     current = GST_STATE (bin) = old_next;
2975   } else {
2976     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
2977         "setting state from %s to %s, pending %s",
2978         gst_element_state_get_name (old_state),
2979         gst_element_state_get_name (old_state),
2980         gst_element_state_get_name (pending));
2981     current = old_state;
2982   }
2983
2984   /* get our toplevel state */
2985   toplevel = BIN_IS_TOPLEVEL (bin);
2986
2987   /* see if we reached the final state. If we are not toplevel, we also have to
2988    * stop here, the parent will continue our state. */
2989   if ((pending == current) || !toplevel) {
2990     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
2991         "completed state change, pending VOID");
2992
2993     /* mark VOID pending */
2994     pending = GST_STATE_VOID_PENDING;
2995     GST_STATE_PENDING (bin) = pending;
2996     GST_STATE_NEXT (bin) = GST_STATE_VOID_PENDING;
2997   } else {
2998     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin,
2999         "continue state change, pending %s",
3000         gst_element_state_get_name (pending));
3001
3002     cont = g_slice_new (BinContinueData);
3003
3004     /* ref to the bin */
3005     cont->bin = gst_object_ref (bin);
3006     /* cookie to detect concurrent state change */
3007     cont->cookie = GST_ELEMENT_CAST (bin)->state_cookie;
3008     /* pending target state */
3009     cont->pending = pending;
3010     /* mark busy */
3011     GST_STATE_RETURN (bin) = GST_STATE_CHANGE_ASYNC;
3012     GST_STATE_NEXT (bin) = GST_STATE_GET_NEXT (old_state, pending);
3013   }
3014
3015   if (old_next != GST_STATE_PLAYING) {
3016     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
3017       state_changed = TRUE;
3018     }
3019   }
3020   GST_OBJECT_UNLOCK (bin);
3021
3022   if (state_changed) {
3023     _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), old_state,
3024         old_next, pending);
3025   }
3026   if (amessage) {
3027     /* post our combined ASYNC_DONE when all is ASYNC_DONE. */
3028     GST_DEBUG_OBJECT (bin, "posting ASYNC_DONE to parent");
3029     gst_element_post_message (GST_ELEMENT_CAST (bin), amessage);
3030   }
3031
3032   GST_OBJECT_LOCK (bin);
3033   if (cont) {
3034     /* toplevel, start continue state */
3035     GST_DEBUG_OBJECT (bin, "all async-done, starting state continue");
3036     bin_push_state_continue (cont);
3037   } else {
3038     GST_DEBUG_OBJECT (bin, "state change complete");
3039     GST_STATE_BROADCAST (bin);
3040   }
3041   return;
3042
3043 had_error:
3044   {
3045     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "we had an error");
3046     return;
3047   }
3048 was_busy:
3049   {
3050     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, "state change busy");
3051     /* if we were busy with a state change and we are requested to flag a
3052      * pending async done, we do so here */
3053     if (flag_pending)
3054       bin->priv->pending_async_done = TRUE;
3055     return;
3056   }
3057 nothing_pending:
3058   {
3059     GST_CAT_INFO_OBJECT (GST_CAT_STATES, bin, "nothing pending");
3060     return;
3061   }
3062 }
3063
3064 static void
3065 bin_do_eos (GstBin * bin)
3066 {
3067   guint32 seqnum = 0;
3068   gboolean eos;
3069
3070   GST_OBJECT_LOCK (bin);
3071   /* If all sinks are EOS, we're in PLAYING and no state change is pending
3072    * we forward the EOS message to the parent bin or application
3073    */
3074   eos = GST_STATE (bin) == GST_STATE_PLAYING
3075       && GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING
3076       && is_eos (bin, &seqnum);
3077   GST_OBJECT_UNLOCK (bin);
3078
3079   if (eos
3080       && g_atomic_int_compare_and_exchange (&bin->priv->posted_eos, FALSE,
3081           TRUE)) {
3082     GstMessage *tmessage;
3083
3084     /* Clear out any further messages, and reset posted_eos so we can
3085        detect any new EOS that happens (eg, after a seek). Since all
3086        sinks have now posted an EOS, there will be no further EOS events
3087        seen unless there is a new logical EOS */
3088     GST_OBJECT_LOCK (bin);
3089     bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
3090     bin->priv->posted_eos = FALSE;
3091     GST_OBJECT_UNLOCK (bin);
3092
3093     tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
3094     gst_message_set_seqnum (tmessage, seqnum);
3095     GST_DEBUG_OBJECT (bin,
3096         "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
3097     gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
3098   }
3099 }
3100
3101 /* must be called with the object lock. This function releases the lock to post
3102  * the message. */
3103 static void
3104 bin_do_message_forward (GstBin * bin, GstMessage * message)
3105 {
3106   if (bin->priv->message_forward) {
3107     GstMessage *forwarded;
3108
3109     GST_DEBUG_OBJECT (bin, "pass %s message upward",
3110         GST_MESSAGE_TYPE_NAME (message));
3111     GST_OBJECT_UNLOCK (bin);
3112
3113     /* we need to convert these messages to element messages so that our parent
3114      * bin can easily ignore them and so that the application can easily
3115      * distinguish between the internally forwarded and the real messages. */
3116     forwarded = gst_message_new_element (GST_OBJECT_CAST (bin),
3117         gst_structure_new ("GstBinForwarded",
3118             "message", GST_TYPE_MESSAGE, message, NULL));
3119
3120     gst_element_post_message (GST_ELEMENT_CAST (bin), forwarded);
3121
3122     GST_OBJECT_LOCK (bin);
3123   }
3124 }
3125
3126 /* handle child messages:
3127  *
3128  * This method is called synchronously when a child posts a message on
3129  * the internal bus.
3130  *
3131  * GST_MESSAGE_EOS: This message is only posted by sinks
3132  *     in the PLAYING state. If all sinks posted the EOS message, post
3133  *     one upwards.
3134  *
3135  * GST_MESSAGE_STATE_DIRTY: Deprecated
3136  *
3137  * GST_MESSAGE_SEGMENT_START: just collect, never forward upwards. If an
3138  *     element posts segment_start twice, only the last message is kept.
3139  *
3140  * GST_MESSAGE_SEGMENT_DONE: replace SEGMENT_START message from same poster
3141  *     with the segment_done message. If there are no more segment_start
3142  *     messages, post segment_done message upwards.
3143  *
3144  * GST_MESSAGE_DURATION: remove all previously cached duration messages.
3145  *     Whenever someone performs a duration query on the bin, we store the
3146  *     result so we can answer it quicker the next time. Any element that
3147  *     changes its duration marks our cached values invalid.
3148  *     This message is also posted upwards. This is currently disabled
3149  *     because too many elements don't post DURATION messages when the
3150  *     duration changes.
3151  *
3152  * GST_MESSAGE_CLOCK_LOST: This message is posted by an element when it
3153  *     can no longer provide a clock. The default bin behaviour is to
3154  *     check if the lost clock was the one provided by the bin. If so and
3155  *     we are currently in the PLAYING state, we forward the message to
3156  *     our parent.
3157  *     This message is also generated when we remove a clock provider from
3158  *     a bin. If this message is received by the application, it should
3159  *     PAUSE the pipeline and set it back to PLAYING to force a new clock
3160  *     and a new base_time distribution.
3161  *
3162  * GST_MESSAGE_CLOCK_PROVIDE: This message is generated when an element
3163  *     can provide a clock. This mostly happens when we add a new clock
3164  *     provider to the bin. The default behaviour of the bin is to mark the
3165  *     currently selected clock as dirty, which will perform a clock
3166  *     recalculation the next time we are asked to provide a clock.
3167  *     This message is never sent to the application but is forwarded to
3168  *     the parent.
3169  *
3170  * GST_MESSAGE_ASYNC_START: Create an internal ELEMENT message that stores
3171  *     the state of the element and the fact that the element will need a
3172  *     new base_time. This message is not forwarded to the application.
3173  *
3174  * GST_MESSAGE_ASYNC_DONE: Find the internal ELEMENT message we kept for the
3175  *     element when it posted ASYNC_START. If all elements are done, post a
3176  *     ASYNC_DONE message to the parent.
3177  *
3178  * OTHER: post upwards.
3179  */
3180 static void
3181 gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
3182 {
3183   GstObject *src;
3184   GstMessageType type;
3185   GstMessage *tmessage;
3186   guint32 seqnum;
3187
3188   src = GST_MESSAGE_SRC (message);
3189   type = GST_MESSAGE_TYPE (message);
3190
3191   GST_DEBUG_OBJECT (bin, "[msg %p] handling child %s message of type %s",
3192       message, src ? GST_ELEMENT_NAME (src) : "(NULL)",
3193       GST_MESSAGE_TYPE_NAME (message));
3194
3195   switch (type) {
3196     case GST_MESSAGE_ERROR:
3197     {
3198       GST_OBJECT_LOCK (bin);
3199       /* flag error */
3200       GST_DEBUG_OBJECT (bin, "got ERROR message, unlocking state change");
3201       GST_STATE_RETURN (bin) = GST_STATE_CHANGE_FAILURE;
3202       GST_STATE_BROADCAST (bin);
3203       GST_OBJECT_UNLOCK (bin);
3204
3205       goto forward;
3206     }
3207     case GST_MESSAGE_EOS:
3208     {
3209
3210       /* collect all eos messages from the children */
3211       GST_OBJECT_LOCK (bin);
3212       bin_do_message_forward (bin, message);
3213       /* ref message for future use  */
3214       bin_replace_message (bin, message, GST_MESSAGE_EOS);
3215       GST_OBJECT_UNLOCK (bin);
3216
3217       bin_do_eos (bin);
3218       break;
3219     }
3220     case GST_MESSAGE_STATE_DIRTY:
3221     {
3222       GST_WARNING_OBJECT (bin, "received deprecated STATE_DIRTY message");
3223
3224       /* free message */
3225       gst_message_unref (message);
3226       break;
3227     }
3228     case GST_MESSAGE_SEGMENT_START:{
3229       gboolean post = FALSE;
3230       GstFormat format;
3231       gint64 position;
3232
3233       gst_message_parse_segment_start (message, &format, &position);
3234       seqnum = gst_message_get_seqnum (message);
3235
3236       GST_OBJECT_LOCK (bin);
3237       bin_do_message_forward (bin, message);
3238       /* if this is the first segment-start, post to parent but not to the
3239        * application */
3240       if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START) &&
3241           (GST_OBJECT_PARENT (bin) != NULL)) {
3242         post = TRUE;
3243       }
3244       /* replace any previous segment_start message from this source
3245        * with the new segment start message */
3246       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
3247       GST_OBJECT_UNLOCK (bin);
3248       if (post) {
3249         tmessage = gst_message_new_segment_start (GST_OBJECT_CAST (bin),
3250             format, position);
3251         gst_message_set_seqnum (tmessage, seqnum);
3252
3253         /* post segment start with initial format and position. */
3254         GST_DEBUG_OBJECT (bin, "posting SEGMENT_START (%u) bus message: %p",
3255             seqnum, message);
3256         gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
3257       }
3258       break;
3259     }
3260     case GST_MESSAGE_SEGMENT_DONE:
3261     {
3262       gboolean post = FALSE;
3263       GstFormat format;
3264       gint64 position;
3265
3266       gst_message_parse_segment_done (message, &format, &position);
3267       seqnum = gst_message_get_seqnum (message);
3268
3269       GST_OBJECT_LOCK (bin);
3270       bin_do_message_forward (bin, message);
3271       bin_replace_message (bin, message, GST_MESSAGE_SEGMENT_START);
3272       /* if there are no more segment_start messages, everybody posted
3273        * a segment_done and we can post one on the bus. */
3274
3275       /* we don't care who still has a pending segment start */
3276       if (!find_message (bin, NULL, GST_MESSAGE_SEGMENT_START)) {
3277         /* nothing found */
3278         post = TRUE;
3279         /* remove all old segment_done messages */
3280         bin_remove_messages (bin, NULL, GST_MESSAGE_SEGMENT_DONE);
3281       }
3282       GST_OBJECT_UNLOCK (bin);
3283       if (post) {
3284         tmessage = gst_message_new_segment_done (GST_OBJECT_CAST (bin),
3285             format, position);
3286         gst_message_set_seqnum (tmessage, seqnum);
3287
3288         /* post segment done with latest format and position. */
3289         GST_DEBUG_OBJECT (bin, "posting SEGMENT_DONE (%u) bus message: %p",
3290             seqnum, message);
3291         gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
3292       }
3293       break;
3294     }
3295     case GST_MESSAGE_DURATION:
3296     {
3297       /* remove all cached duration messages, next time somebody asks
3298        * for duration, we will recalculate. */
3299       GST_OBJECT_LOCK (bin);
3300       bin_remove_messages (bin, NULL, GST_MESSAGE_DURATION);
3301       GST_OBJECT_UNLOCK (bin);
3302       goto forward;
3303     }
3304     case GST_MESSAGE_CLOCK_LOST:
3305     {
3306       GstClock **provided_clock_p;
3307       GstElement **clock_provider_p;
3308       gboolean playing, provided, forward;
3309       GstClock *clock;
3310
3311       gst_message_parse_clock_lost (message, &clock);
3312
3313       GST_OBJECT_LOCK (bin);
3314       bin->clock_dirty = TRUE;
3315       /* if we lost the clock that we provided, post to parent but
3316        * only if we are PLAYING. */
3317       provided = (clock == bin->provided_clock);
3318       playing = (GST_STATE (bin) == GST_STATE_PLAYING);
3319       forward = playing & provided;
3320       if (provided) {
3321         GST_DEBUG_OBJECT (bin,
3322             "Lost clock %" GST_PTR_FORMAT " provided by %" GST_PTR_FORMAT,
3323             bin->provided_clock, bin->clock_provider);
3324         provided_clock_p = &bin->provided_clock;
3325         clock_provider_p = &bin->clock_provider;
3326         gst_object_replace ((GstObject **) provided_clock_p, NULL);
3327         gst_object_replace ((GstObject **) clock_provider_p, NULL);
3328       }
3329       GST_DEBUG_OBJECT (bin, "provided %d, playing %d, forward %d",
3330           provided, playing, forward);
3331       GST_OBJECT_UNLOCK (bin);
3332
3333       if (forward)
3334         goto forward;
3335
3336       /* free message */
3337       gst_message_unref (message);
3338       break;
3339     }
3340     case GST_MESSAGE_CLOCK_PROVIDE:
3341     {
3342       gboolean forward;
3343
3344       GST_OBJECT_LOCK (bin);
3345       bin->clock_dirty = TRUE;
3346       /* a new clock is available, post to parent but not
3347        * to the application */
3348       forward = GST_OBJECT_PARENT (bin) != NULL;
3349       GST_OBJECT_UNLOCK (bin);
3350
3351       if (forward)
3352         goto forward;
3353
3354       /* free message */
3355       gst_message_unref (message);
3356       break;
3357     }
3358     case GST_MESSAGE_ASYNC_START:
3359     {
3360       GstState target;
3361
3362       GST_DEBUG_OBJECT (bin, "ASYNC_START message %p, %s", message,
3363           src ? GST_OBJECT_NAME (src) : "(NULL)");
3364
3365       GST_OBJECT_LOCK (bin);
3366       bin_do_message_forward (bin, message);
3367
3368       /* we ignore the message if we are going to <= READY */
3369       if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY)
3370         goto ignore_start_message;
3371
3372       /* takes ownership of the message */
3373       bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START);
3374
3375       bin_handle_async_start (bin);
3376       GST_OBJECT_UNLOCK (bin);
3377       break;
3378
3379     ignore_start_message:
3380       {
3381         GST_DEBUG_OBJECT (bin, "ignoring message, target %s",
3382             gst_element_state_get_name (target));
3383         GST_OBJECT_UNLOCK (bin);
3384         gst_message_unref (message);
3385         break;
3386       }
3387     }
3388     case GST_MESSAGE_ASYNC_DONE:
3389     {
3390       gboolean reset_time;
3391       GstState target;
3392
3393       GST_DEBUG_OBJECT (bin, "ASYNC_DONE message %p, %s", message,
3394           src ? GST_OBJECT_NAME (src) : "(NULL)");
3395
3396       gst_message_parse_async_done (message, &reset_time);
3397
3398       GST_OBJECT_LOCK (bin);
3399       bin_do_message_forward (bin, message);
3400
3401       /* ignore messages if we are shutting down */
3402       if ((target = GST_STATE_TARGET (bin)) <= GST_STATE_READY)
3403         goto ignore_done_message;
3404
3405       bin_replace_message (bin, message, GST_MESSAGE_ASYNC_START);
3406       /* if there are no more ASYNC_START messages, everybody posted
3407        * a ASYNC_DONE and we can post one on the bus. When checking, we
3408        * don't care who still has a pending ASYNC_START */
3409       if (!find_message (bin, NULL, GST_MESSAGE_ASYNC_START)) {
3410         /* nothing found, remove all old ASYNC_DONE messages */
3411         bin_remove_messages (bin, NULL, GST_MESSAGE_ASYNC_DONE);
3412
3413         GST_DEBUG_OBJECT (bin, "async elements commited");
3414         /* when we get an async done message when a state change was busy, we
3415          * need to set the pending_done flag so that at the end of the state
3416          * change we can see if we need to verify pending async elements, hence
3417          * the TRUE argument here. */
3418         bin_handle_async_done (bin, GST_STATE_CHANGE_SUCCESS, TRUE, reset_time);
3419       } else {
3420         GST_DEBUG_OBJECT (bin, "there are more async elements pending");
3421       }
3422       GST_OBJECT_UNLOCK (bin);
3423       break;
3424
3425     ignore_done_message:
3426       {
3427         GST_DEBUG_OBJECT (bin, "ignoring message, target %s",
3428             gst_element_state_get_name (target));
3429         GST_OBJECT_UNLOCK (bin);
3430         gst_message_unref (message);
3431         break;
3432       }
3433     }
3434     case GST_MESSAGE_STRUCTURE_CHANGE:
3435     {
3436       gboolean busy;
3437
3438       gst_message_parse_structure_change (message, NULL, NULL, &busy);
3439
3440       GST_OBJECT_LOCK (bin);
3441       if (busy) {
3442         /* while the pad is busy, avoid following it when doing state changes.
3443          * Don't update the cookie yet, we will do that after the structure
3444          * change finished and we are ready to inspect the new updated
3445          * structure. */
3446         bin_replace_message (bin, message, GST_MESSAGE_STRUCTURE_CHANGE);
3447         message = NULL;
3448       } else {
3449         /* a pad link/unlink ended, signal the state change iterator that we
3450          * need to resync by updating the structure_cookie. */
3451         bin_remove_messages (bin, GST_MESSAGE_SRC (message),
3452             GST_MESSAGE_STRUCTURE_CHANGE);
3453         bin->priv->structure_cookie++;
3454       }
3455       GST_OBJECT_UNLOCK (bin);
3456
3457       if (message)
3458         gst_message_unref (message);
3459
3460       break;
3461     }
3462     default:
3463       goto forward;
3464   }
3465   return;
3466
3467 forward:
3468   {
3469     /* Send all other messages upward */
3470     GST_DEBUG_OBJECT (bin, "posting message upward");
3471     gst_element_post_message (GST_ELEMENT_CAST (bin), message);
3472     return;
3473   }
3474 }
3475
3476 /* generic struct passed to all query fold methods */
3477 typedef struct
3478 {
3479   GstQuery *query;
3480   gint64 min;
3481   gint64 max;
3482   gboolean live;
3483 } QueryFold;
3484
3485 typedef void (*QueryInitFunction) (GstBin * bin, QueryFold * fold);
3486 typedef void (*QueryDoneFunction) (GstBin * bin, QueryFold * fold);
3487
3488 /* for duration/position we collect all durations/positions and take
3489  * the MAX of all valid results */
3490 static void
3491 bin_query_min_max_init (GstBin * bin, QueryFold * fold)
3492 {
3493   fold->min = 0;
3494   fold->max = -1;
3495   fold->live = FALSE;
3496 }
3497
3498 static gboolean
3499 bin_query_duration_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
3500 {
3501   GstElement *item = g_value_get_object (vitem);
3502
3503   if (gst_element_query (item, fold->query)) {
3504     gint64 duration;
3505
3506     g_value_set_boolean (ret, TRUE);
3507
3508     gst_query_parse_duration (fold->query, NULL, &duration);
3509
3510     GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
3511
3512     if (duration > fold->max)
3513       fold->max = duration;
3514   }
3515
3516   return TRUE;
3517 }
3518
3519 static void
3520 bin_query_duration_done (GstBin * bin, QueryFold * fold)
3521 {
3522   GstFormat format;
3523
3524   gst_query_parse_duration (fold->query, &format, NULL);
3525   /* store max in query result */
3526   gst_query_set_duration (fold->query, format, fold->max);
3527
3528   GST_DEBUG_OBJECT (bin, "max duration %" G_GINT64_FORMAT, fold->max);
3529
3530   /* and cache now */
3531   GST_OBJECT_LOCK (bin);
3532   bin->messages = g_list_prepend (bin->messages,
3533       gst_message_new_duration (GST_OBJECT_CAST (bin), format, fold->max));
3534   GST_OBJECT_UNLOCK (bin);
3535 }
3536
3537 static gboolean
3538 bin_query_position_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
3539 {
3540   GstElement *item = g_value_get_object (vitem);
3541
3542   if (gst_element_query (item, fold->query)) {
3543     gint64 position;
3544
3545     g_value_set_boolean (ret, TRUE);
3546
3547     gst_query_parse_position (fold->query, NULL, &position);
3548
3549     GST_DEBUG_OBJECT (item, "got position %" G_GINT64_FORMAT, position);
3550
3551     if (position > fold->max)
3552       fold->max = position;
3553   }
3554
3555   return TRUE;
3556 }
3557
3558 static void
3559 bin_query_position_done (GstBin * bin, QueryFold * fold)
3560 {
3561   GstFormat format;
3562
3563   gst_query_parse_position (fold->query, &format, NULL);
3564   /* store max in query result */
3565   gst_query_set_position (fold->query, format, fold->max);
3566
3567   GST_DEBUG_OBJECT (bin, "max position %" G_GINT64_FORMAT, fold->max);
3568 }
3569
3570 static gboolean
3571 bin_query_latency_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
3572 {
3573   GstElement *item = g_value_get_object (vitem);
3574
3575   if (gst_element_query (item, fold->query)) {
3576     GstClockTime min, max;
3577     gboolean live;
3578
3579     gst_query_parse_latency (fold->query, &live, &min, &max);
3580
3581     GST_DEBUG_OBJECT (item,
3582         "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
3583         ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
3584
3585     /* for the combined latency we collect the MAX of all min latencies and
3586      * the MIN of all max latencies */
3587     if (live) {
3588       if (min > fold->min)
3589         fold->min = min;
3590       if (fold->max == -1)
3591         fold->max = max;
3592       else if (max < fold->max)
3593         fold->max = max;
3594       if (fold->live == FALSE)
3595         fold->live = live;
3596     }
3597   } else {
3598     g_value_set_boolean (ret, FALSE);
3599     GST_DEBUG_OBJECT (item, "failed query");
3600   }
3601
3602   return TRUE;
3603 }
3604
3605 static void
3606 bin_query_latency_done (GstBin * bin, QueryFold * fold)
3607 {
3608   /* store max in query result */
3609   gst_query_set_latency (fold->query, fold->live, fold->min, fold->max);
3610
3611   GST_DEBUG_OBJECT (bin,
3612       "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
3613       ", live %d", GST_TIME_ARGS (fold->min), GST_TIME_ARGS (fold->max),
3614       fold->live);
3615 }
3616
3617 /* generic fold, return first valid result */
3618 static gboolean
3619 bin_query_generic_fold (const GValue * vitem, GValue * ret, QueryFold * fold)
3620 {
3621   GstElement *item = g_value_get_object (vitem);
3622   gboolean res;
3623
3624   if ((res = gst_element_query (item, fold->query))) {
3625     g_value_set_boolean (ret, TRUE);
3626     GST_DEBUG_OBJECT (item, "answered query %p", fold->query);
3627   }
3628
3629   /* and stop as soon as we have a valid result */
3630   return !res;
3631 }
3632
3633 static gboolean
3634 gst_bin_query (GstElement * element, GstQuery * query)
3635 {
3636   GstBin *bin = GST_BIN_CAST (element);
3637   GstIterator *iter;
3638   gboolean res = FALSE;
3639   GstIteratorFoldFunction fold_func;
3640   QueryInitFunction fold_init = NULL;
3641   QueryDoneFunction fold_done = NULL;
3642   QueryFold fold_data;
3643   GValue ret = { 0 };
3644
3645   switch (GST_QUERY_TYPE (query)) {
3646     case GST_QUERY_DURATION:
3647     {
3648       GList *cached;
3649       GstFormat qformat;
3650
3651       gst_query_parse_duration (query, &qformat, NULL);
3652
3653       /* find cached duration query */
3654       GST_OBJECT_LOCK (bin);
3655       for (cached = bin->messages; cached; cached = g_list_next (cached)) {
3656         GstMessage *message = (GstMessage *) cached->data;
3657
3658         if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DURATION &&
3659             GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (bin)) {
3660           GstFormat format;
3661           gint64 duration;
3662
3663           gst_message_parse_duration (message, &format, &duration);
3664
3665           /* if cached same format, copy duration in query result */
3666           if (format == qformat) {
3667             GST_DEBUG_OBJECT (bin, "return cached duration %" G_GINT64_FORMAT,
3668                 duration);
3669             GST_OBJECT_UNLOCK (bin);
3670
3671             gst_query_set_duration (query, qformat, duration);
3672             res = TRUE;
3673             goto exit;
3674           }
3675         }
3676       }
3677       GST_OBJECT_UNLOCK (bin);
3678       /* no cached value found, iterate and collect durations */
3679       fold_func = (GstIteratorFoldFunction) bin_query_duration_fold;
3680       fold_init = bin_query_min_max_init;
3681       fold_done = bin_query_duration_done;
3682       break;
3683     }
3684     case GST_QUERY_POSITION:
3685     {
3686       fold_func = (GstIteratorFoldFunction) bin_query_position_fold;
3687       fold_init = bin_query_min_max_init;
3688       fold_done = bin_query_position_done;
3689       break;
3690     }
3691     case GST_QUERY_LATENCY:
3692     {
3693       fold_func = (GstIteratorFoldFunction) bin_query_latency_fold;
3694       fold_init = bin_query_min_max_init;
3695       fold_done = bin_query_latency_done;
3696       res = TRUE;
3697       break;
3698     }
3699     default:
3700       fold_func = (GstIteratorFoldFunction) bin_query_generic_fold;
3701       break;
3702   }
3703
3704   fold_data.query = query;
3705
3706   /* set the result of the query to FALSE initially */
3707   g_value_init (&ret, G_TYPE_BOOLEAN);
3708   g_value_set_boolean (&ret, res);
3709
3710   iter = gst_bin_iterate_sinks (bin);
3711   GST_DEBUG_OBJECT (bin, "Sending query %p (type %s) to sink children",
3712       query, GST_QUERY_TYPE_NAME (query));
3713
3714   if (fold_init)
3715     fold_init (bin, &fold_data);
3716
3717   while (TRUE) {
3718     GstIteratorResult ires;
3719
3720     ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
3721
3722     switch (ires) {
3723       case GST_ITERATOR_RESYNC:
3724         gst_iterator_resync (iter);
3725         if (fold_init)
3726           fold_init (bin, &fold_data);
3727         g_value_set_boolean (&ret, res);
3728         break;
3729       case GST_ITERATOR_OK:
3730       case GST_ITERATOR_DONE:
3731         res = g_value_get_boolean (&ret);
3732         if (fold_done != NULL && res)
3733           fold_done (bin, &fold_data);
3734         goto done;
3735       default:
3736         res = FALSE;
3737         goto done;
3738     }
3739   }
3740 done:
3741   gst_iterator_free (iter);
3742
3743 exit:
3744   GST_DEBUG_OBJECT (bin, "query %p result %d", query, res);
3745
3746   return res;
3747 }
3748
3749 static gint
3750 compare_name (const GValue * velement, const gchar * name)
3751 {
3752   gint eq;
3753   GstElement *element = g_value_get_object (velement);
3754
3755   GST_OBJECT_LOCK (element);
3756   eq = strcmp (GST_ELEMENT_NAME (element), name);
3757   GST_OBJECT_UNLOCK (element);
3758
3759   return eq;
3760 }
3761
3762 /**
3763  * gst_bin_get_by_name:
3764  * @bin: a #GstBin
3765  * @name: the element name to search for
3766  *
3767  * Gets the element with the given name from a bin. This
3768  * function recurses into child bins.
3769  *
3770  * Returns NULL if no element with the given name is found in the bin.
3771  *
3772  * MT safe.  Caller owns returned reference.
3773  *
3774  * Returns: (transfer full): the #GstElement with the given name, or NULL
3775  */
3776 GstElement *
3777 gst_bin_get_by_name (GstBin * bin, const gchar * name)
3778 {
3779   GstIterator *children;
3780   GValue result = { 0, };
3781   GstElement *element;
3782   gboolean found;
3783
3784   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
3785
3786   GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
3787       GST_ELEMENT_NAME (bin), name);
3788
3789   children = gst_bin_iterate_recurse (bin);
3790   found = gst_iterator_find_custom (children,
3791       (GCompareFunc) compare_name, &result, (gpointer) name);
3792   gst_iterator_free (children);
3793
3794   if (found) {
3795     element = g_value_dup_object (&result);
3796     g_value_unset (&result);
3797   } else {
3798     element = NULL;
3799   }
3800
3801   return element;
3802 }
3803
3804 /**
3805  * gst_bin_get_by_name_recurse_up:
3806  * @bin: a #GstBin
3807  * @name: the element name to search for
3808  *
3809  * Gets the element with the given name from this bin. If the
3810  * element is not found, a recursion is performed on the parent bin.
3811  *
3812  * Returns NULL if:
3813  * - no element with the given name is found in the bin
3814  *
3815  * MT safe.  Caller owns returned reference.
3816  *
3817  * Returns: (transfer full): the #GstElement with the given name, or NULL
3818  */
3819 GstElement *
3820 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
3821 {
3822   GstElement *result;
3823
3824   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
3825   g_return_val_if_fail (name != NULL, NULL);
3826
3827   result = gst_bin_get_by_name (bin, name);
3828
3829   if (!result) {
3830     GstObject *parent;
3831
3832     parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
3833     if (parent) {
3834       if (GST_IS_BIN (parent)) {
3835         result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
3836       }
3837       gst_object_unref (parent);
3838     }
3839   }
3840
3841   return result;
3842 }
3843
3844 static gint
3845 compare_interface (const GValue * velement, GValue * interface)
3846 {
3847   GstElement *element = g_value_get_object (velement);
3848   GType interface_type = (GType) g_value_get_pointer (interface);
3849   gint ret;
3850
3851   if (G_TYPE_CHECK_INSTANCE_TYPE (element, interface_type)) {
3852     ret = 0;
3853   } else {
3854     ret = 1;
3855   }
3856   return ret;
3857 }
3858
3859 /**
3860  * gst_bin_get_by_interface:
3861  * @bin: a #GstBin
3862  * @iface: the #GType of an interface
3863  *
3864  * Looks for an element inside the bin that implements the given
3865  * interface. If such an element is found, it returns the element.
3866  * You can cast this element to the given interface afterwards.  If you want
3867  * all elements that implement the interface, use
3868  * gst_bin_iterate_all_by_interface(). This function recurses into child bins.
3869  *
3870  * MT safe.  Caller owns returned reference.
3871  *
3872  * Returns: (transfer full): A #GstElement inside the bin implementing the interface
3873  */
3874 GstElement *
3875 gst_bin_get_by_interface (GstBin * bin, GType iface)
3876 {
3877   GstIterator *children;
3878   GValue result = { 0, };
3879   GstElement *element;
3880   gboolean found;
3881   GValue viface = { 0, };
3882
3883   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
3884   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
3885
3886   g_value_init (&viface, G_TYPE_POINTER);
3887   g_value_set_pointer (&viface, (gpointer) iface);
3888
3889   children = gst_bin_iterate_recurse (bin);
3890   found = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
3891       &result, &viface);
3892   gst_iterator_free (children);
3893
3894   if (found) {
3895     element = g_value_dup_object (&result);
3896     g_value_unset (&result);
3897   } else {
3898     element = NULL;
3899   }
3900   g_value_unset (&viface);
3901
3902   return element;
3903 }
3904
3905 /**
3906  * gst_bin_iterate_all_by_interface:
3907  * @bin: a #GstBin
3908  * @iface: the #GType of an interface
3909  *
3910  * Looks for all elements inside the bin that implements the given
3911  * interface. You can safely cast all returned elements to the given interface.
3912  * The function recurses inside child bins. The iterator will yield a series
3913  * of #GstElement that should be unreffed after use.
3914  *
3915  * Each element yielded by the iterator will have its refcount increased, so
3916  * unref after use.
3917  *
3918  * MT safe.  Caller owns returned value.
3919  *
3920  * Returns: (transfer full): a #GstIterator of #GstElement for all elements
3921  *          in the bin implementing the given interface, or NULL
3922  */
3923 GstIterator *
3924 gst_bin_iterate_all_by_interface (GstBin * bin, GType iface)
3925 {
3926   GstIterator *children;
3927   GstIterator *result;
3928   GValue viface = { 0, };
3929
3930   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
3931   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface), NULL);
3932
3933   g_value_init (&viface, G_TYPE_POINTER);
3934   g_value_set_pointer (&viface, (gpointer) iface);
3935
3936   children = gst_bin_iterate_recurse (bin);
3937   result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
3938       &viface);
3939
3940   g_value_unset (&viface);
3941
3942   return result;
3943 }