check/Makefile.am: clean up environment for when registry gets built versus when...
[platform/upstream/gstreamer.git] / gst / gstbin.c
1 /* GStreamer
2  *
3  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
4  *                    2004 Wim Taymans <wim@fluendo.com>
5  *
6  * gstbin.c: GstBin container object and support code
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  * MT safe.
24  */
25
26 #include "gst_private.h"
27
28 #include "gstevent.h"
29 #include "gstbin.h"
30 #include "gstmarshal.h"
31 #include "gstxml.h"
32 #include "gstinfo.h"
33 #include "gsterror.h"
34
35 #include "gstindex.h"
36 #include "gstutils.h"
37
38 GST_DEBUG_CATEGORY_STATIC (bin_debug);
39 #define GST_CAT_DEFAULT bin_debug
40 #define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
41         text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
42         (bin)->numchildren, (guint) (bin)->child_states[3], \
43         (guint) (bin)->child_states[2], (bin)->child_states[1], \
44         (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
45
46
47 static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
48     "Generic/Bin",
49     "Simple container object",
50     "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
51
52 GType _gst_bin_type = 0;
53
54 static void gst_bin_dispose (GObject * object);
55
56 static GstElementStateReturn gst_bin_change_state (GstElement * element);
57 static GstElementStateReturn gst_bin_get_state (GstElement * element,
58     GstElementState * state, GstElementState * pending, GTimeVal * timeout);
59
60 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
61 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
62
63 #ifndef GST_DISABLE_INDEX
64 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
65 #endif
66 static GstClock *gst_bin_get_clock_func (GstElement * element);
67 static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
68
69 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
70 static GstBusSyncReply bin_bus_handler (GstBus * bus,
71     GstMessage * message, GstBin * bin);
72 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
73
74 #ifndef GST_DISABLE_LOADSAVE
75 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
76 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
77 #endif
78
79 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
80
81 /* Bin signals and args */
82 enum
83 {
84   ELEMENT_ADDED,
85   ELEMENT_REMOVED,
86   LAST_SIGNAL
87 };
88
89 enum
90 {
91   ARG_0
92       /* FILL ME */
93 };
94
95 static void gst_bin_base_init (gpointer g_class);
96 static void gst_bin_class_init (GstBinClass * klass);
97 static void gst_bin_init (GstBin * bin);
98
99 static GstElementClass *parent_class = NULL;
100 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
101
102 /**
103  * gst_bin_get_type:
104  *
105  * Returns: the type of #GstBin
106  */
107 GType
108 gst_bin_get_type (void)
109 {
110   if (!_gst_bin_type) {
111     static const GTypeInfo bin_info = {
112       sizeof (GstBinClass),
113       gst_bin_base_init,
114       NULL,
115       (GClassInitFunc) gst_bin_class_init,
116       NULL,
117       NULL,
118       sizeof (GstBin),
119       0,
120       (GInstanceInitFunc) gst_bin_init,
121       NULL
122     };
123
124     _gst_bin_type =
125         g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
126
127     GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
128         "debugging info for the 'bin' container element");
129   }
130   return _gst_bin_type;
131 }
132
133 static void
134 gst_bin_base_init (gpointer g_class)
135 {
136   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
137
138   gst_element_class_set_details (gstelement_class, &gst_bin_details);
139 }
140
141 static void
142 gst_bin_class_init (GstBinClass * klass)
143 {
144   GObjectClass *gobject_class;
145   GstObjectClass *gstobject_class;
146   GstElementClass *gstelement_class;
147
148   gobject_class = (GObjectClass *) klass;
149   gstobject_class = (GstObjectClass *) klass;
150   gstelement_class = (GstElementClass *) klass;
151
152   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
153
154   gst_bin_signals[ELEMENT_ADDED] =
155       g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
156       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
157       NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
158   gst_bin_signals[ELEMENT_REMOVED] =
159       g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
160       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
161       NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
162
163   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
164
165 #ifndef GST_DISABLE_LOADSAVE
166   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
167   gstobject_class->restore_thyself =
168       GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
169 #endif
170
171   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
172   gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
173 #ifndef GST_DISABLE_INDEX
174   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
175 #endif
176   gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
177   gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
178
179   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
180   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
181
182   klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
183   klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
184 }
185
186 static void
187 gst_bin_init (GstBin * bin)
188 {
189   GstBus *bus;
190
191   bin->numchildren = 0;
192   bin->children = NULL;
193   bin->children_cookie = 0;
194   bin->eosed = NULL;
195
196   /* Set up a bus for listening to child elements,
197    * and one for sending messages up the hierarchy */
198   bus = g_object_new (gst_bus_get_type (), NULL);
199   bin->child_bus = bus;
200   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
201
202   bus = g_object_new (gst_bus_get_type (), NULL);
203   gst_element_set_bus (GST_ELEMENT (bin), bus);
204   /* set_bus refs the bus via gst_object_replace, we drop our ref */
205   gst_object_unref (bus);
206 }
207
208 /**
209  * gst_bin_new:
210  * @name: name of new bin
211  *
212  * Create a new bin with given name.
213  *
214  * Returns: new bin
215  */
216 GstElement *
217 gst_bin_new (const gchar * name)
218 {
219   return gst_element_factory_make ("bin", name);
220 }
221
222 /* set the index on all elements in this bin
223  *
224  * MT safe
225  */
226 #ifndef GST_DISABLE_INDEX
227 static void
228 gst_bin_set_index_func (GstElement * element, GstIndex * index)
229 {
230   GstBin *bin;
231   GList *children;
232
233   bin = GST_BIN (element);
234
235   GST_LOCK (bin);
236   for (children = bin->children; children; children = g_list_next (children)) {
237     GstElement *child = GST_ELEMENT (children->data);
238
239     gst_element_set_index (child, index);
240   }
241   GST_UNLOCK (bin);
242 }
243 #endif
244
245 /* set the clock on all elements in this bin
246  *
247  * MT safe
248  */
249 static void
250 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
251 {
252   GList *children;
253   GstBin *bin;
254
255   bin = GST_BIN (element);
256
257   GST_LOCK (bin);
258   for (children = bin->children; children; children = g_list_next (children)) {
259     GstElement *child = GST_ELEMENT (children->data);
260
261     gst_element_set_clock (child, clock);
262   }
263   GST_UNLOCK (bin);
264 }
265
266 /* get the clock for this bin by asking all of the children in this bin
267  *
268  * MT safe
269  */
270 static GstClock *
271 gst_bin_get_clock_func (GstElement * element)
272 {
273   GstClock *result = NULL;
274   GstBin *bin;
275   GList *children;
276
277   bin = GST_BIN (element);
278
279   GST_LOCK (bin);
280   for (children = bin->children; children; children = g_list_next (children)) {
281     GstElement *child = GST_ELEMENT (children->data);
282
283     result = gst_element_get_clock (child);
284     if (result)
285       break;
286   }
287   GST_UNLOCK (bin);
288
289   return result;
290 }
291
292 static gboolean
293 is_eos (GstBin * bin)
294 {
295   GstIterator *sinks;
296   gboolean result = TRUE;
297   gboolean done = FALSE;
298
299   sinks = gst_bin_iterate_sinks (bin);
300   while (!done) {
301     gpointer data;
302
303     switch (gst_iterator_next (sinks, &data)) {
304       case GST_ITERATOR_OK:
305       {
306         GstElement *element = GST_ELEMENT (data);
307         GList *eosed;
308         gchar *name;
309
310         name = gst_element_get_name (element);
311         eosed = g_list_find (bin->eosed, element);
312         if (!eosed) {
313           GST_DEBUG ("element %s did not post EOS yet", name);
314           result = FALSE;
315           done = TRUE;
316         } else {
317           GST_DEBUG ("element %s posted EOS", name);
318         }
319         g_free (name);
320         gst_object_unref (element);
321         break;
322       }
323       case GST_ITERATOR_RESYNC:
324         result = TRUE;
325         gst_iterator_resync (sinks);
326         break;
327       case GST_ITERATOR_DONE:
328         done = TRUE;
329         break;
330       default:
331         g_assert_not_reached ();
332         break;
333     }
334   }
335   gst_iterator_free (sinks);
336   return result;
337 }
338
339 static void
340 unlink_pads (GstPad * pad)
341 {
342   GstPad *peer;
343
344   if ((peer = gst_pad_get_peer (pad))) {
345     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
346       gst_pad_unlink (pad, peer);
347     else
348       gst_pad_unlink (peer, pad);
349     gst_object_unref (peer);
350   }
351   gst_object_unref (pad);
352 }
353
354 /* add an element to this bin
355  *
356  * MT safe
357  */
358 static gboolean
359 gst_bin_add_func (GstBin * bin, GstElement * element)
360 {
361   gchar *elem_name;
362   GstIterator *it;
363
364   /* we obviously can't add ourself to ourself */
365   if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
366     goto adding_itself;
367
368   /* get the element name to make sure it is unique in this bin. */
369   GST_LOCK (element);
370   elem_name = g_strdup (GST_ELEMENT_NAME (element));
371   GST_UNLOCK (element);
372
373   GST_LOCK (bin);
374
375   /* then check to see if the element's name is already taken in the bin,
376    * we can safely take the lock here. This check is probably bogus because
377    * you can safely change the element name after this check and before setting
378    * the object parent. The window is very small though... */
379   if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name)))
380     goto duplicate_name;
381
382   /* set the element's parent and add the element to the bin's list of children */
383   if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
384               GST_OBJECT_CAST (bin))))
385     goto had_parent;
386
387   /* if we add a sink we become a sink */
388   if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
389     GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
390
391   bin->children = g_list_prepend (bin->children, element);
392   bin->numchildren++;
393   bin->children_cookie++;
394
395   /* distribute the bus */
396   gst_element_set_bus (element, bin->child_bus);
397
398   /* propagate the current base time and clock */
399   gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
400   gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
401
402   GST_UNLOCK (bin);
403
404   /* unlink all linked pads */
405   it = gst_element_iterate_pads (element);
406   gst_iterator_foreach (it, (GFunc) unlink_pads, element);
407   gst_iterator_free (it);
408
409   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
410       elem_name);
411   g_free (elem_name);
412
413   g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
414
415   return TRUE;
416
417   /* ERROR handling here */
418 adding_itself:
419   {
420     GST_LOCK (bin);
421     g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
422     GST_UNLOCK (bin);
423     return FALSE;
424   }
425 duplicate_name:
426   {
427     g_warning ("Name %s is not unique in bin %s, not adding",
428         elem_name, GST_ELEMENT_NAME (bin));
429     GST_UNLOCK (bin);
430     g_free (elem_name);
431     return FALSE;
432   }
433 had_parent:
434   {
435     g_warning ("Element %s already has parent", elem_name);
436     GST_UNLOCK (bin);
437     g_free (elem_name);
438     return FALSE;
439   }
440 }
441
442
443 /**
444  * gst_bin_add:
445  * @bin: #GstBin to add element to
446  * @element: #GstElement to add to bin
447  *
448  * Adds the given element to the bin.  Sets the element's parent, and thus
449  * takes ownership of the element. An element can only be added to one bin.
450  *
451  * If the element's pads are linked to other pads, the pads will be unlinked
452  * before the element is added to the bin.
453  *
454  * MT safe.
455  *
456  * Returns: TRUE if the element could be added, FALSE on wrong parameters or
457  * the bin does not want to accept the element.
458  */
459 gboolean
460 gst_bin_add (GstBin * bin, GstElement * element)
461 {
462   GstBinClass *bclass;
463   gboolean result;
464
465   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
466   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
467
468   bclass = GST_BIN_GET_CLASS (bin);
469
470   if (G_UNLIKELY (bclass->add_element == NULL))
471     goto no_function;
472
473   GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
474       GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
475
476   result = bclass->add_element (bin, element);
477
478   return result;
479
480   /* ERROR handling */
481 no_function:
482   {
483     g_warning ("adding elements to bin %s is not supported",
484         GST_ELEMENT_NAME (bin));
485     return FALSE;
486   }
487 }
488
489 /* remove an element from the bin
490  *
491  * MT safe
492  */
493 static gboolean
494 gst_bin_remove_func (GstBin * bin, GstElement * element)
495 {
496   gchar *elem_name;
497   GstIterator *it;
498
499   /* grab element name so we can print it */
500   GST_LOCK (element);
501   elem_name = g_strdup (GST_ELEMENT_NAME (element));
502   GST_UNLOCK (element);
503
504   GST_LOCK (bin);
505   /* the element must be in the bin's list of children */
506   if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
507     goto not_in_bin;
508
509   /* now remove the element from the list of elements */
510   bin->children = g_list_remove (bin->children, element);
511   bin->numchildren--;
512   bin->children_cookie++;
513
514   /* check if we removed a sink */
515   if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
516     GList *other_sink;
517
518     /* check if we removed the last sink */
519     other_sink = g_list_find_custom (bin->children,
520         bin, (GCompareFunc) bin_element_is_sink);
521     if (!other_sink) {
522       /* yups, we're not a sink anymore */
523       GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
524     }
525   }
526   GST_UNLOCK (bin);
527
528   GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
529       elem_name);
530   g_free (elem_name);
531
532   /* unlink all linked pads */
533   it = gst_element_iterate_pads (element);
534   gst_iterator_foreach (it, (GFunc) unlink_pads, element);
535   gst_iterator_free (it);
536
537   gst_element_set_bus (element, NULL);
538
539   /* unlock any waiters for the state change. It is possible that
540    * we are waiting for an ASYNC state change on this element. The
541    * element cannot be added to another bin yet as it is not yet
542    * unparented. */
543   GST_STATE_LOCK (element);
544   GST_STATE_BROADCAST (element);
545   GST_STATE_UNLOCK (element);
546
547   /* we ref here because after the _unparent() the element can be disposed
548    * and we still need it to fire a signal. */
549   gst_object_ref (element);
550   gst_object_unparent (GST_OBJECT_CAST (element));
551
552   g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
553   /* element is really out of our control now */
554   gst_object_unref (element);
555
556   return TRUE;
557
558   /* ERROR handling */
559 not_in_bin:
560   {
561     g_warning ("Element %s is not in bin %s", elem_name,
562         GST_ELEMENT_NAME (bin));
563     GST_UNLOCK (bin);
564     g_free (elem_name);
565     return FALSE;
566   }
567 }
568
569 /**
570  * gst_bin_remove:
571  * @bin: #GstBin to remove element from
572  * @element: #GstElement to remove
573  *
574  * Remove the element from its associated bin, unparenting it as well.
575  * Unparenting the element means that the element will be dereferenced,
576  * so if the bin holds the only reference to the element, the element
577  * will be freed in the process of removing it from the bin.  If you
578  * want the element to still exist after removing, you need to call
579  * #gst_object_ref before removing it from the bin.
580  *
581  * If the element's pads are linked to other pads, the pads will be unlinked
582  * before the element is removed from the bin.
583  *
584  * MT safe.
585  *
586  * Returns: TRUE if the element could be removed, FALSE on wrong parameters or
587  * the bin does not want to remove the element.
588  */
589 gboolean
590 gst_bin_remove (GstBin * bin, GstElement * element)
591 {
592   GstBinClass *bclass;
593   gboolean result;
594
595   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
596   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
597
598   bclass = GST_BIN_GET_CLASS (bin);
599
600   if (G_UNLIKELY (bclass->remove_element == NULL))
601     goto no_function;
602
603   GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
604       GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
605
606   result = bclass->remove_element (bin, element);
607
608   return result;
609
610   /* ERROR handling */
611 no_function:
612   {
613     g_warning ("removing elements from bin %s is not supported",
614         GST_ELEMENT_NAME (bin));
615     return FALSE;
616   }
617 }
618
619 static GstIteratorItem
620 iterate_child (GstIterator * it, GstElement * child)
621 {
622   gst_object_ref (child);
623   return GST_ITERATOR_ITEM_PASS;
624 }
625
626 /**
627  * gst_bin_iterate_elements:
628  * @bin: #Gstbin to iterate the elements of
629  *
630  * Get an iterator for the elements in this bin.
631  * Each element will have its refcount increased, so unref
632  * after use.
633  *
634  * MT safe.
635  *
636  * Returns: a #GstIterator of #GstElements. gst_iterator_free after
637  * use. returns NULL when passing bad parameters.
638  */
639 GstIterator *
640 gst_bin_iterate_elements (GstBin * bin)
641 {
642   GstIterator *result;
643
644   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
645
646   GST_LOCK (bin);
647   /* add ref because the iterator refs the bin. When the iterator
648    * is freed it will unref the bin again using the provided dispose
649    * function. */
650   gst_object_ref (bin);
651   result = gst_iterator_new_list (GST_GET_LOCK (bin),
652       &bin->children_cookie,
653       &bin->children,
654       bin,
655       (GstIteratorItemFunction) iterate_child,
656       (GstIteratorDisposeFunction) gst_object_unref);
657   GST_UNLOCK (bin);
658
659   return result;
660 }
661
662 static GstIteratorItem
663 iterate_child_recurse (GstIterator * it, GstElement * child)
664 {
665   gst_object_ref (child);
666   if (GST_IS_BIN (child)) {
667     GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
668
669     gst_iterator_push (it, other);
670   }
671   return GST_ITERATOR_ITEM_PASS;
672 }
673
674 /**
675  * gst_bin_iterate_recurse:
676  * @bin: #Gstbin to iterate the elements of
677  *
678  * Get an iterator for the elements in this bin.
679  * Each element will have its refcount increased, so unref
680  * after use. This iterator recurses into GstBin children.
681  *
682  * MT safe.
683  *
684  * Returns: a #GstIterator of #GstElements. gst_iterator_free after
685  * use. returns NULL when passing bad parameters.
686  */
687 GstIterator *
688 gst_bin_iterate_recurse (GstBin * bin)
689 {
690   GstIterator *result;
691
692   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
693
694   GST_LOCK (bin);
695   /* add ref because the iterator refs the bin. When the iterator
696    * is freed it will unref the bin again using the provided dispose
697    * function. */
698   gst_object_ref (bin);
699   result = gst_iterator_new_list (GST_GET_LOCK (bin),
700       &bin->children_cookie,
701       &bin->children,
702       bin,
703       (GstIteratorItemFunction) iterate_child_recurse,
704       (GstIteratorDisposeFunction) gst_object_unref);
705   GST_UNLOCK (bin);
706
707   return result;
708 }
709
710 /* returns 0 when TRUE because this is a GCompareFunc */
711 /* MT safe */
712 static gint
713 bin_element_is_sink (GstElement * child, GstBin * bin)
714 {
715   gboolean is_sink;
716
717   /* we lock the child here for the remainder of the function to
718    * get its name safely. */
719   GST_LOCK (child);
720   is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
721
722   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
723       "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
724
725   GST_UNLOCK (child);
726   return is_sink ? 0 : 1;
727 }
728
729 /* check if object has the given ancestor somewhere up in
730  * the hierarchy
731  */
732 static gboolean
733 has_ancestor (GstObject * object, GstObject * ancestor)
734 {
735   GstObject *parent;
736   gboolean result = FALSE;
737
738   if (object == NULL)
739     return FALSE;
740
741   if (object == ancestor)
742     return TRUE;
743
744   parent = gst_object_get_parent (object);
745   result = has_ancestor (parent, ancestor);
746   if (parent)
747     gst_object_unref (parent);
748
749   return result;
750 }
751
752 /* returns 0 when TRUE because this is a GCompareFunc.
753  * This function returns elements that have no connected srcpads and
754  * are therefore not reachable from a real sink. */
755 /* MT safe */
756 static gint
757 bin_element_is_semi_sink (GstElement * child, GstBin * bin)
758 {
759   int ret = 1;
760
761   /* we lock the child here for the remainder of the function to
762    * get its pads and name safely. */
763   GST_LOCK (child);
764
765   /* check if this is a sink element, these are the elements
766    * without (linked) source pads. */
767   if (child->numsrcpads == 0) {
768     /* shortcut */
769     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
770         "adding child %s as sink", GST_OBJECT_NAME (child));
771     ret = 0;
772   } else {
773     /* loop over all pads, try to figure out if this element
774      * is a semi sink because it has no linked source pads */
775     GList *pads;
776     gboolean connected_src = FALSE;
777
778     for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
779       GstPad *peer;
780
781       GST_DEBUG ("looking at pad %p", pads->data);
782       if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
783         connected_src =
784             has_ancestor (GST_OBJECT_CAST (peer), GST_OBJECT_CAST (bin));
785         gst_object_unref (peer);
786         if (connected_src) {
787           break;
788         }
789       }
790     }
791     if (connected_src) {
792       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
793           "not adding child %s as sink: linked source pads",
794           GST_OBJECT_NAME (child));
795     } else {
796       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
797           "adding child %s as sink since it has unlinked source pads in this bin",
798           GST_OBJECT_NAME (child));
799       ret = 0;
800     }
801   }
802   GST_UNLOCK (child);
803
804   return ret;
805 }
806
807 static gint
808 sink_iterator_filter (GstElement * child, GstBin * bin)
809 {
810   if (bin_element_is_sink (child, bin) == 0) {
811     /* returns 0 because this is a GCompareFunc */
812     return 0;
813   } else {
814     /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
815        through */
816     gst_object_unref ((GstObject *) child);
817     return 1;
818   }
819 }
820
821 /**
822  * gst_bin_iterate_sinks:
823  * @bin: #Gstbin to iterate on
824  *
825  * Get an iterator for the sink elements in this bin.
826  * Each element will have its refcount increased, so unref
827  * after use.
828  *
829  * The sink elements are those without any linked srcpads.
830  *
831  * MT safe.
832  *
833  * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
834  */
835 GstIterator *
836 gst_bin_iterate_sinks (GstBin * bin)
837 {
838   GstIterator *children;
839   GstIterator *result;
840
841   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
842
843   children = gst_bin_iterate_elements (bin);
844   result = gst_iterator_filter (children,
845       (GCompareFunc) sink_iterator_filter, bin);
846
847   return result;
848 }
849
850 /* 2 phases:
851  *  1) check state of all children with 0 timeout to find ERROR and
852  *     NO_PREROLL elements. return if found.
853  *  2) perform full blocking wait with requested timeout.
854  *
855  * 2) cannot be performed when 1) returns results as the sinks might
856  *    not be able to complete the state change making 2) block forever.
857  *
858  * MT safe
859  */
860 static GstElementStateReturn
861 gst_bin_get_state (GstElement * element, GstElementState * state,
862     GstElementState * pending, GTimeVal * timeout)
863 {
864   GstBin *bin = GST_BIN (element);
865   GstElementStateReturn ret = GST_STATE_SUCCESS;
866   GList *children;
867   guint32 children_cookie;
868   gboolean have_no_preroll;
869
870   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
871
872   /* lock bin, no element can be added or removed between going into
873    * the quick scan and the blocking wait. */
874   GST_LOCK (bin);
875
876 restart:
877   have_no_preroll = FALSE;
878
879   /* first we need to poll with a non zero timeout to make sure we don't block
880    * on the sinks when we have NO_PREROLL elements. This is why we do
881    * a quick check if there are still NO_PREROLL elements. We also
882    * catch the error elements this way. */
883   {
884     GTimeVal tv;
885     gboolean have_async = FALSE;
886
887     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
888     /* use 0 timeout so we don't block on the sinks */
889     GST_TIME_TO_TIMEVAL (0, tv);
890     children = bin->children;
891     children_cookie = bin->children_cookie;
892     while (children) {
893       GstElement *child = GST_ELEMENT_CAST (children->data);
894
895       gst_object_ref (child);
896       /* now we release the lock to enter a non blocking wait. We
897        * release the lock anyway since we can. */
898       GST_UNLOCK (bin);
899
900       ret = gst_element_get_state (child, NULL, NULL, &tv);
901
902       gst_object_unref (child);
903
904       /* now grab the lock to iterate to the next child */
905       GST_LOCK (bin);
906       if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
907         /* child added/removed during state change, restart. We need
908          * to restart with the quick check as a no-preroll element could
909          * have been added here and we don't want to block on sinks then.*/
910         goto restart;
911       }
912
913       switch (ret) {
914           /* report FAILURE  immediatly */
915         case GST_STATE_FAILURE:
916           goto done;
917         case GST_STATE_NO_PREROLL:
918           /* we have to continue scanning as there might be
919            * ERRORS too */
920           have_no_preroll = TRUE;
921           break;
922         case GST_STATE_ASYNC:
923           have_async = TRUE;
924           break;
925         default:
926           break;
927       }
928       children = g_list_next (children);
929     }
930     /* if we get here, we have no FAILURES, check for any NO_PREROLL
931      * elements then. */
932     if (have_no_preroll) {
933       ret = GST_STATE_NO_PREROLL;
934       goto done;
935     }
936
937     /* if we get here, no NO_PREROLL elements are in the pipeline */
938     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
939
940     /* if no ASYNC elements exist we don't even have to poll with a
941      * timeout again */
942     if (!have_async) {
943       ret = GST_STATE_SUCCESS;
944       goto done;
945     }
946   }
947
948   /* next we poll all children for their state to see if one of them
949    * is still busy with its state change. We did not release the bin lock
950    * yet so the elements are the same as the ones from the quick scan. */
951   children = bin->children;
952   children_cookie = bin->children_cookie;
953   while (children) {
954     GstElement *child = GST_ELEMENT_CAST (children->data);
955
956     gst_object_ref (child);
957     /* now we release the lock to enter the potentialy blocking wait */
958     GST_UNLOCK (bin);
959
960     /* ret is ASYNC if some child is still performing the state change
961      * ater the timeout. */
962     ret = gst_element_get_state (child, NULL, NULL, timeout);
963
964     gst_object_unref (child);
965
966     /* now grab the lock to iterate to the next child */
967     GST_LOCK (bin);
968     if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
969       /* child added/removed during state change, restart. We need
970        * to restart with the quick check as a no-preroll element could
971        * have been added here and we don't want to block on sinks then.*/
972       goto restart;
973     }
974
975     switch (ret) {
976       case GST_STATE_SUCCESS:
977         break;
978       case GST_STATE_FAILURE:
979       case GST_STATE_NO_PREROLL:
980         /* report FAILURE and NO_PREROLL immediatly */
981         goto done;
982       case GST_STATE_ASYNC:
983         goto done;
984       default:
985         g_assert_not_reached ();
986     }
987     children = g_list_next (children);
988   }
989   /* if we got here, all elements can do preroll */
990   have_no_preroll = FALSE;
991
992 done:
993   GST_UNLOCK (bin);
994
995   /* now we can take the state lock, it is possible that new elements
996    * are added now and we still report the old state. No problem though as
997    * the return is still consistent, the effect is as if the element was
998    * added after this function completed. */
999   GST_STATE_LOCK (bin);
1000   switch (ret) {
1001     case GST_STATE_SUCCESS:
1002       /* we can commit the state */
1003       gst_element_commit_state (element);
1004       break;
1005     case GST_STATE_FAILURE:
1006       /* some element failed, abort the state change */
1007       gst_element_abort_state (element);
1008       break;
1009     default:
1010       /* other cases are just passed along */
1011       break;
1012   }
1013
1014   /* and report the state if needed */
1015   if (state)
1016     *state = GST_STATE (element);
1017   if (pending)
1018     *pending = GST_STATE_PENDING (element);
1019
1020   GST_STATE_NO_PREROLL (element) = have_no_preroll;
1021
1022   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1023       "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1024       gst_element_state_get_name (GST_STATE (element)),
1025       gst_element_state_get_name (GST_STATE_PENDING (element)),
1026       GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1027
1028   GST_STATE_UNLOCK (bin);
1029
1030   return ret;
1031 }
1032
1033 static void
1034 append_child (gpointer child, GQueue * queue)
1035 {
1036   g_queue_push_tail (queue, child);
1037 }
1038
1039 /**
1040  * gst_bin_iterate_state_order:
1041  * @bin: #Gstbin to iterate on
1042  *
1043  * Get an iterator for the elements in this bin in the order
1044  * in which a state change should be performed on them. This 
1045  * means that first the sinks and then the other elements will
1046  * be returned.
1047  * Each element will have its refcount increased, so unref
1048  * after use.
1049  *
1050  * Not implemented yet.
1051  *
1052  * MT safe.
1053  *
1054  * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
1055  */
1056 GstIterator *
1057 gst_bin_iterate_state_order (GstBin * bin)
1058 {
1059   GstIterator *result;
1060
1061   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1062
1063   result = NULL;
1064
1065   return result;
1066 }
1067
1068 static void
1069 clear_queue (GQueue * queue, gboolean unref)
1070 {
1071   gpointer p;
1072
1073   while ((p = g_queue_pop_head (queue)))
1074     if (unref)
1075       gst_object_unref (p);
1076 }
1077
1078 static void
1079 remove_all_from_queue (GQueue * queue, gpointer elem, gboolean unref)
1080 {
1081   gpointer p;
1082
1083   while ((p = g_queue_find (queue, elem))) {
1084     if (unref)
1085       gst_object_unref (elem);
1086     g_queue_delete_link (queue, p);
1087   }
1088 }
1089
1090 /* this function is called with the STATE_LOCK held. It works
1091  * as follows:
1092  *
1093  * 1) put all sink elements on the queue.
1094  * 2) put all semisink elements on the queue.
1095  * 3) change state of elements in queue, put linked elements to queue.
1096  * 4) while queue not empty goto 3)
1097  *
1098  * This will effectively change the state of all elements in the bin
1099  * from the sinks to the sources. We have to change the states this
1100  * way so that when a source element pushes data, the downstream element
1101  * is in the right state to receive the data.
1102  *
1103  * MT safe.
1104  */
1105 /* FIXME,  make me more elegant, want to use a topological sort algorithm
1106  * based on indegrees (or outdegrees in our case) */
1107 static GstElementStateReturn
1108 gst_bin_change_state (GstElement * element)
1109 {
1110   GstBin *bin;
1111   GstElementStateReturn ret;
1112   GstElementState old_state, pending;
1113   gboolean have_async = FALSE;
1114   gboolean have_no_preroll = FALSE;
1115   GList *children;
1116   guint32 children_cookie;
1117   GQueue *elem_queue;           /* list of elements waiting for a state change */
1118   GQueue *semi_queue;           /* list of elements with no connected srcpads */
1119   GQueue *temp;                 /* queue of leftovers */
1120   GstClockTime base_time;
1121
1122   bin = GST_BIN (element);
1123
1124   /* we don't need to take the STATE_LOCK, it is already taken */
1125   old_state = GST_STATE (element);
1126   pending = GST_STATE_PENDING (element);
1127
1128   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1129       "changing state of children from %s to %s",
1130       gst_element_state_get_name (old_state),
1131       gst_element_state_get_name (pending));
1132
1133   if (pending == GST_STATE_VOID_PENDING)
1134     return GST_STATE_SUCCESS;
1135
1136   /* Clear eosed element list on READY-> PAUSED */
1137   if (GST_STATE_TRANSITION (element) == GST_STATE_READY_TO_PAUSED) {
1138     g_list_free (bin->eosed);
1139     bin->eosed = NULL;
1140   }
1141
1142   /* all elements added to these queues should have their refcount
1143    * incremented */
1144   elem_queue = g_queue_new ();
1145   semi_queue = g_queue_new ();
1146   temp = g_queue_new ();
1147
1148   /* first step, find all sink elements, these are the elements
1149    * without (linked) source pads. */
1150   GST_LOCK (bin);
1151
1152 restart:
1153   /* take base time */
1154   base_time = element->base_time;
1155
1156   /* make sure queues are empty, they could be filled when
1157    * restarting. */
1158   clear_queue (elem_queue, TRUE);
1159   clear_queue (semi_queue, TRUE);
1160   clear_queue (temp, TRUE);
1161
1162   children = bin->children;
1163   children_cookie = bin->children_cookie;
1164   GST_DEBUG_OBJECT (bin, "reffing and examining children");
1165   while (children) {
1166     GstElement *child = GST_ELEMENT_CAST (children->data);
1167
1168     gst_object_ref (child);
1169     GST_UNLOCK (bin);
1170
1171     if (bin_element_is_sink (child, bin) == 0) {
1172       g_queue_push_tail (elem_queue, child);
1173     } else if (bin_element_is_semi_sink (child, bin) == 0) {
1174       g_queue_push_tail (semi_queue, child);
1175     } else {
1176       g_queue_push_tail (temp, child);
1177     }
1178
1179     GST_LOCK (bin);
1180     if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1181       GST_INFO_OBJECT (bin, "bin->children_cookie changed, restarting");
1182       /* restart will unref the children in the queues so that we don't
1183        * leak refcounts. */
1184       goto restart;
1185     }
1186     children = g_list_next (children);
1187   }
1188   GST_DEBUG_OBJECT (bin, "reffed and examined children");
1189   GST_UNLOCK (bin);
1190
1191   /* after this point new elements can be added/removed from the
1192    * bin. We operate on the snapshot taken above. Applications
1193    * should serialize their add/remove and set_state. */
1194
1195   /* now change state for semi sink elements first so add them in
1196    * front of the other elements */
1197   g_queue_foreach (temp, (GFunc) append_child, semi_queue);
1198   clear_queue (temp, FALSE);
1199
1200   /* if we don't have real sinks, we continue with the other elements */
1201   if (g_queue_is_empty (elem_queue) && !g_queue_is_empty (semi_queue)) {
1202     GQueue *q = elem_queue;
1203
1204     /* we swap the queues as oposed to copy them over */
1205     elem_queue = semi_queue;
1206     semi_queue = q;
1207   }
1208
1209   /* second step, change state of elements in the queue */
1210   GST_DEBUG_OBJECT (bin, "change state of elements in the queue");
1211   while (!g_queue_is_empty (elem_queue)) {
1212     GstElement *qelement;
1213     GList *pads;
1214     gboolean locked;
1215
1216     /* take element */
1217     qelement = g_queue_pop_head (elem_queue);
1218     /* we don't need any duplicates in the other queue anymore */
1219     remove_all_from_queue (semi_queue, qelement, TRUE);
1220
1221     /* queue all elements connected to the sinkpads of this element */
1222     GST_LOCK (qelement);
1223     pads = qelement->sinkpads;
1224     while (pads) {
1225       GstPad *pad = GST_PAD_CAST (pads->data);
1226       GstPad *peer;
1227
1228       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1229           "found sinkpad %s:%s", GST_DEBUG_PAD_NAME (pad));
1230
1231       peer = gst_pad_get_peer (pad);
1232       if (peer) {
1233         GstObject *peer_parent;
1234
1235         /*  get parent */
1236         peer_parent = gst_object_get_parent (GST_OBJECT (peer));
1237
1238         /* if we have an element parent, follow it */
1239         if (peer_parent && GST_IS_ELEMENT (peer_parent)) {
1240           GstObject *parent;
1241
1242           /* see if this element is in the bin we are currently handling */
1243           parent = gst_object_get_parent (peer_parent);
1244           if (parent) {
1245             if (parent == GST_OBJECT_CAST (bin)) {
1246               GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1247                   "adding element %s to queue", GST_ELEMENT_NAME (peer_parent));
1248
1249               /* make sure we don't have duplicates */
1250               remove_all_from_queue (semi_queue, peer_parent, TRUE);
1251               remove_all_from_queue (elem_queue, peer_parent, TRUE);
1252
1253               /* was reffed before pushing on the queue by the
1254                * gst_object_get_parent() call we used to get the element. */
1255               g_queue_push_tail (elem_queue, peer_parent);
1256               /* so that we don't unref it */
1257               peer_parent = NULL;
1258             } else {
1259               GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1260                   "not adding element %s to queue, it is in another bin",
1261                   GST_ELEMENT_NAME (peer_parent));
1262             }
1263             gst_object_unref (parent);
1264           }
1265         }
1266         if (peer_parent)
1267           gst_object_unref (peer_parent);
1268
1269         gst_object_unref (peer);
1270       } else {
1271         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1272             "pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));
1273       }
1274       pads = g_list_next (pads);
1275     }
1276     /* peel off the locked flag and release the element lock */
1277     locked = GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE);
1278     GST_UNLOCK (qelement);
1279
1280     /* skip locked elements */
1281     if (G_UNLIKELY (locked))
1282       goto next_element;
1283
1284     /* set base time on element */
1285     gst_element_set_base_time (qelement, base_time);
1286
1287     /* then change state */
1288     ret = gst_element_set_state (qelement, pending);
1289
1290     /* the set state could have cause elements to be added/removed,
1291      * we support that. */
1292     GST_LOCK (bin);
1293     if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1294       gst_object_unref (qelement);
1295       goto restart;
1296     }
1297     GST_UNLOCK (bin);
1298
1299     switch (ret) {
1300       case GST_STATE_SUCCESS:
1301         GST_CAT_DEBUG (GST_CAT_STATES,
1302             "child '%s' changed state to %d(%s) successfully",
1303             GST_ELEMENT_NAME (qelement), pending,
1304             gst_element_state_get_name (pending));
1305         break;
1306       case GST_STATE_ASYNC:
1307         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1308             "child '%s' is changing state asynchronously",
1309             GST_ELEMENT_NAME (qelement));
1310         have_async = TRUE;
1311         break;
1312       case GST_STATE_FAILURE:
1313         GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1314             "child '%s' failed to go to state %d(%s)",
1315             GST_ELEMENT_NAME (qelement),
1316             pending, gst_element_state_get_name (pending));
1317         ret = GST_STATE_FAILURE;
1318         /* release refcount of element we popped off the queue */
1319         gst_object_unref (qelement);
1320         goto exit;
1321       case GST_STATE_NO_PREROLL:
1322         GST_CAT_DEBUG (GST_CAT_STATES,
1323             "child '%s' changed state to %d(%s) successfully without preroll",
1324             GST_ELEMENT_NAME (qelement), pending,
1325             gst_element_state_get_name (pending));
1326         have_no_preroll = TRUE;
1327         break;
1328       default:
1329         g_assert_not_reached ();
1330         break;
1331     }
1332   next_element:
1333     gst_object_unref (qelement);
1334
1335     /* if queue is empty now, continue with a non-sink */
1336     if (g_queue_is_empty (elem_queue)) {
1337       GstElement *non_sink;
1338
1339       GST_DEBUG ("sinks and upstream elements exhausted");
1340       non_sink = g_queue_pop_head (semi_queue);
1341       if (non_sink) {
1342         GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
1343         g_queue_push_tail (elem_queue, non_sink);
1344       }
1345     }
1346   }
1347
1348   if (have_no_preroll) {
1349     ret = GST_STATE_NO_PREROLL;
1350   } else if (have_async) {
1351     ret = GST_STATE_ASYNC;
1352   } else {
1353     ret = parent_class->change_state (element);
1354   }
1355
1356   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1357       "done changing bin's state from %s to %s, now in %s, ret %d",
1358       gst_element_state_get_name (old_state),
1359       gst_element_state_get_name (pending),
1360       gst_element_state_get_name (GST_STATE (element)), ret);
1361
1362 exit:
1363   /* release refcounts in queue, should normally be empty unless we
1364    * had an error. */
1365   clear_queue (elem_queue, TRUE);
1366   clear_queue (semi_queue, TRUE);
1367   g_queue_free (elem_queue);
1368   g_queue_free (semi_queue);
1369   g_queue_free (temp);
1370
1371   return ret;
1372 }
1373
1374 static void
1375 gst_bin_dispose (GObject * object)
1376 {
1377   GstBin *bin = GST_BIN (object);
1378
1379   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
1380
1381   /* ref to not hit 0 again */
1382   gst_object_ref (object);
1383
1384   g_list_free (bin->eosed);
1385   bin->eosed = NULL;
1386   gst_object_unref (bin->child_bus);
1387   bin->child_bus = NULL;
1388   gst_element_set_bus (GST_ELEMENT (bin), NULL);
1389
1390   while (bin->children) {
1391     gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
1392   }
1393   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose no children");
1394   g_assert (bin->children == NULL);
1395   g_assert (bin->numchildren == 0);
1396
1397   G_OBJECT_CLASS (parent_class)->dispose (object);
1398 }
1399
1400 /*
1401  * This function is a utility event handler for seek events.
1402  * It will send the event to all sinks.
1403  * Applications are free to override this behaviour and
1404  * implement their own seek handler, but this will work for
1405  * pretty much all cases in practice.
1406  */
1407 static gboolean
1408 gst_bin_send_event (GstElement * element, GstEvent * event)
1409 {
1410   GstBin *bin = GST_BIN (element);
1411   GstIterator *iter;
1412   gboolean res = TRUE;
1413   gboolean done = FALSE;
1414
1415   iter = gst_bin_iterate_sinks (bin);
1416   GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1417
1418   while (!done) {
1419     gpointer data;
1420
1421     switch (gst_iterator_next (iter, &data)) {
1422       case GST_ITERATOR_OK:
1423       {
1424         GstElement *sink;
1425
1426         gst_event_ref (event);
1427         sink = GST_ELEMENT_CAST (data);
1428         res &= gst_element_send_event (sink, event);
1429         gst_object_unref (sink);
1430         break;
1431       }
1432       case GST_ITERATOR_RESYNC:
1433         gst_iterator_resync (iter);
1434         res = TRUE;
1435         break;
1436       default:
1437       case GST_ITERATOR_DONE:
1438         done = TRUE;
1439         break;
1440     }
1441   }
1442   gst_iterator_free (iter);
1443   gst_event_unref (event);
1444
1445   return res;
1446 }
1447
1448 static GstBusSyncReply
1449 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
1450 {
1451   GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %d",
1452       message, GST_MESSAGE_TYPE (message));
1453
1454   switch (GST_MESSAGE_TYPE (message)) {
1455     case GST_MESSAGE_EOS:{
1456       gchar *name = gst_object_get_name (GST_MESSAGE_SRC (message));
1457
1458       GST_DEBUG_OBJECT (bin, "got EOS message from %s", name);
1459       g_free (name);
1460
1461       /* collect all eos messages from the children */
1462       GST_LOCK (bin->child_bus);
1463       bin->eosed = g_list_prepend (bin->eosed, GST_MESSAGE_SRC (message));
1464       GST_UNLOCK (bin->child_bus);
1465
1466       /* if we are completely EOS, we forward an EOS message */
1467       if (is_eos (bin)) {
1468         GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
1469         gst_element_post_message (GST_ELEMENT (bin),
1470             gst_message_new_eos (GST_OBJECT (bin)));
1471       }
1472
1473       /* we drop all EOS messages */
1474       gst_message_unref (message);
1475       break;
1476     }
1477     default:
1478       /* Send all other messages upward */
1479       GST_DEBUG_OBJECT (bin, "posting message upward");
1480       gst_element_post_message (GST_ELEMENT (bin), message);
1481       break;
1482   }
1483
1484   return GST_BUS_DROP;
1485 }
1486
1487 static gboolean
1488 gst_bin_query (GstElement * element, GstQuery * query)
1489 {
1490   GstBin *bin = GST_BIN (element);
1491   GstIterator *iter;
1492   gboolean res = FALSE, done = FALSE;
1493
1494   iter = gst_bin_iterate_sinks (bin);
1495   GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1496
1497   while (!(res || done)) {
1498     gpointer data;
1499
1500     switch (gst_iterator_next (iter, &data)) {
1501       case GST_ITERATOR_OK:
1502       {
1503         GstElement *sink;
1504
1505         sink = GST_ELEMENT_CAST (data);
1506         res = gst_element_query (sink, query);
1507         gst_object_unref (sink);
1508         break;
1509       }
1510       case GST_ITERATOR_RESYNC:
1511         gst_iterator_resync (iter);
1512         break;
1513       default:
1514       case GST_ITERATOR_DONE:
1515         done = TRUE;
1516         break;
1517     }
1518   }
1519   gst_iterator_free (iter);
1520
1521   return res;
1522 }
1523
1524 static gint
1525 compare_name (GstElement * element, const gchar * name)
1526 {
1527   gint eq;
1528
1529   GST_LOCK (element);
1530   eq = strcmp (GST_ELEMENT_NAME (element), name);
1531   GST_UNLOCK (element);
1532
1533   if (eq != 0) {
1534     gst_object_unref (element);
1535   }
1536   return eq;
1537 }
1538
1539 /**
1540  * gst_bin_get_by_name:
1541  * @bin: #Gstbin to search
1542  * @name: the element name to search for
1543  *
1544  * Get the element with the given name from this bin. This
1545  * function recurses into subbins.
1546  *
1547  * MT safe.
1548  *
1549  * Returns: the element with the given name. Returns NULL if the
1550  * element is not found or when bad parameters were given. Unref after
1551  * use.
1552  */
1553 GstElement *
1554 gst_bin_get_by_name (GstBin * bin, const gchar * name)
1555 {
1556   GstIterator *children;
1557   GstIterator *result;
1558
1559   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1560
1561   GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
1562       GST_ELEMENT_NAME (bin), name);
1563
1564   children = gst_bin_iterate_recurse (bin);
1565   result = gst_iterator_find_custom (children,
1566       (GCompareFunc) compare_name, (gpointer) name);
1567   gst_iterator_free (children);
1568
1569   return GST_ELEMENT_CAST (result);
1570 }
1571
1572 /**
1573  * gst_bin_get_by_name_recurse_up:
1574  * @bin: #Gstbin to search
1575  * @name: the element name to search for
1576  *
1577  * MT safe.
1578  *
1579  * Get the element with the given name from this bin. If the
1580  * element is not found, a recursion is performed on the parent bin.
1581  *
1582  * Returns: the element with the given name or NULL when the element
1583  * was not found or bad parameters were given. Unref after use.
1584  */
1585 GstElement *
1586 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
1587 {
1588   GstElement *result;
1589
1590   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1591   g_return_val_if_fail (name != NULL, NULL);
1592
1593   result = gst_bin_get_by_name (bin, name);
1594
1595   if (!result) {
1596     GstObject *parent;
1597
1598     parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
1599     if (parent) {
1600       if (GST_IS_BIN (parent)) {
1601         result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
1602       }
1603       gst_object_unref (parent);
1604     }
1605   }
1606
1607   return result;
1608 }
1609
1610 static gint
1611 compare_interface (GstElement * element, gpointer interface)
1612 {
1613   gint ret;
1614
1615   if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
1616     ret = 0;
1617   } else {
1618     /* we did not find the element, need to release the ref
1619      * added by the iterator */
1620     gst_object_unref (element);
1621     ret = 1;
1622   }
1623   return ret;
1624 }
1625
1626 /**
1627  * gst_bin_get_by_interface:
1628  * @bin: bin to find element in
1629  * @interface: interface to be implemented by interface
1630  *
1631  * Looks for the first element inside the bin that implements the given
1632  * interface. If such an element is found, it returns the element. You can
1633  * cast this element to the given interface afterwards.
1634  * If you want all elements that implement the interface, use
1635  * gst_bin_iterate_all_by_interface(). The function recurses inside bins.
1636  *
1637  * MT safe.
1638  *
1639  * Returns: An #GstElement inside the bin implementing the interface.
1640  *          Unref after use.
1641  */
1642 GstElement *
1643 gst_bin_get_by_interface (GstBin * bin, GType interface)
1644 {
1645   GstIterator *children;
1646   GstIterator *result;
1647
1648   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1649
1650   children = gst_bin_iterate_recurse (bin);
1651   result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
1652       GINT_TO_POINTER (interface));
1653   gst_iterator_free (children);
1654
1655   return GST_ELEMENT_CAST (result);
1656 }
1657
1658 /**
1659  * gst_bin_get_all_by_interface:
1660  * @bin: bin to find elements in
1661  * @interface: interface to be implemented by interface
1662  *
1663  * Looks for all elements inside the bin that implements the given
1664  * interface. You can safely cast all returned elements to the given interface.
1665  * The function recurses bins inside bins. The iterator will return a series
1666  * of #GstElement that should be unreffed after use.
1667  *
1668  * MT safe.
1669  *
1670  * Returns: A #GstIterator for the elements inside the bin implementing the
1671  *          given interface.
1672  */
1673 GstIterator *
1674 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
1675 {
1676   GstIterator *children;
1677   GstIterator *result;
1678
1679   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1680
1681   children = gst_bin_iterate_recurse (bin);
1682   result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
1683       GINT_TO_POINTER (interface));
1684
1685   return result;
1686 }
1687
1688 #ifndef GST_DISABLE_LOADSAVE
1689 static xmlNodePtr
1690 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
1691 {
1692   GstBin *bin = GST_BIN (object);
1693   xmlNodePtr childlist, elementnode;
1694   GList *children;
1695   GstElement *child;
1696
1697   if (GST_OBJECT_CLASS (parent_class)->save_thyself)
1698     GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
1699
1700   childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
1701
1702   GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
1703       GST_ELEMENT_NAME (bin), bin->numchildren);
1704
1705   children = bin->children;
1706   while (children) {
1707     child = GST_ELEMENT (children->data);
1708     elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
1709     gst_object_save_thyself (GST_OBJECT (child), elementnode);
1710     children = g_list_next (children);
1711   }
1712   return childlist;
1713 }
1714
1715 static void
1716 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
1717 {
1718   GstBin *bin = GST_BIN (object);
1719   xmlNodePtr field = self->xmlChildrenNode;
1720   xmlNodePtr childlist;
1721
1722   while (field) {
1723     if (!strcmp ((char *) field->name, "children")) {
1724       GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
1725           GST_ELEMENT_NAME (object));
1726       childlist = field->xmlChildrenNode;
1727       while (childlist) {
1728         if (!strcmp ((char *) childlist->name, "element")) {
1729           GstElement *element =
1730               gst_xml_make_element (childlist, GST_OBJECT (bin));
1731
1732           /* it had to be parented to find the pads, now we ref and unparent so
1733            * we can add it to the bin */
1734           gst_object_ref (element);
1735           gst_object_unparent (GST_OBJECT (element));
1736
1737           gst_bin_add (bin, element);
1738         }
1739         childlist = childlist->next;
1740       }
1741     }
1742
1743     field = field->next;
1744   }
1745   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
1746     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
1747 }
1748 #endif /* GST_DISABLE_LOADSAVE */