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 * SECTION:gstbin
27 * @short_description: Base class for elements that contain other elements
28 *
29 * GstBin is the simplest of the container elements, allowing elements to
30 * become children of itself. Pads from the child elements can be ghosted to
31 * the bin, making the bin itself look transparently like any other element,
32 * allowing for deep nesting of predefined sub-pipelines.
33 *
34 * A new GstBin is created with gst_bin_new(). Use a #GstPipeline instead if you
35 * want to create a toplevel bin because a normal bin doesn't have a bus or
36 * handle clock distribution of its own.
37 *
38 * After the bin has been created you will typically add elements to it with
39 * gst_bin_add(). You can remove elements with gst_bin_remove().
40 *
41 * An element can be retrieved from a bin with gst_bin_get_by_name(), using the
42 * elements name. gst_bin_get_by_name_recurse_up() is mainly used for internal
43 * purposes and will query the parent bins when the element is not found in the
44 * current bin.
45 *
46 * An iterator of elements in a bin can be retrieved with
47 * gst_bin_iterate_elements(). Various other iterators exist to retrieve the
48 * elements in a bin.
49 *
50 * The "element_added" signal is fired whenever a new element is added to the
51 * bin. Likewise the "element_removed" signal is fired whenever an element is
52 * removed from the bin.
53 *
54 * gst_bin_unref() is used to destroy the bin.
55 */
57 #include "gst_private.h"
59 #include "gstevent.h"
60 #include "gstbin.h"
61 #include "gstmarshal.h"
62 #include "gstxml.h"
63 #include "gstinfo.h"
64 #include "gsterror.h"
66 #include "gstindex.h"
67 #include "gstindexfactory.h"
68 #include "gstutils.h"
69 #include "gstchildproxy.h"
71 GST_DEBUG_CATEGORY_STATIC (bin_debug);
72 #define GST_CAT_DEFAULT bin_debug
73 #define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
74 text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
75 (bin)->numchildren, (guint) (bin)->child_states[3], \
76 (guint) (bin)->child_states[2], (bin)->child_states[1], \
77 (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
80 static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
81 "Generic/Bin",
82 "Simple container object",
83 "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
85 GType _gst_bin_type = 0;
87 static void gst_bin_dispose (GObject * object);
89 static GstStateChangeReturn gst_bin_change_state (GstElement * element,
90 GstStateChange transition);
91 static GstStateChangeReturn gst_bin_get_state (GstElement * element,
92 GstState * state, GstState * pending, GTimeVal * timeout);
94 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
95 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
97 #ifndef GST_DISABLE_INDEX
98 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
99 #endif
100 static GstClock *gst_bin_provide_clock_func (GstElement * element);
101 static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
103 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
104 static GstBusSyncReply bin_bus_handler (GstBus * bus,
105 GstMessage * message, GstBin * bin);
106 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
108 #ifndef GST_DISABLE_LOADSAVE
109 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
110 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
111 #endif
113 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
115 /* Bin signals and properties */
116 enum
117 {
118 ELEMENT_ADDED,
119 ELEMENT_REMOVED,
120 LAST_SIGNAL
121 };
123 enum
124 {
125 PROP_0
126 /* FILL ME */
127 };
129 static void gst_bin_base_init (gpointer g_class);
130 static void gst_bin_class_init (GstBinClass * klass);
131 static void gst_bin_init (GstBin * bin);
132 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
134 static GstElementClass *parent_class = NULL;
135 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
137 /**
138 * gst_bin_get_type:
139 *
140 * Returns: the type of #GstBin
141 */
142 GType
143 gst_bin_get_type (void)
144 {
145 if (!_gst_bin_type) {
146 static const GTypeInfo bin_info = {
147 sizeof (GstBinClass),
148 gst_bin_base_init,
149 NULL,
150 (GClassInitFunc) gst_bin_class_init,
151 NULL,
152 NULL,
153 sizeof (GstBin),
154 0,
155 (GInstanceInitFunc) gst_bin_init,
156 NULL
157 };
158 static const GInterfaceInfo child_proxy_info = {
159 gst_bin_child_proxy_init,
160 NULL,
161 NULL
162 };
164 _gst_bin_type =
165 g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
167 g_type_add_interface_static (_gst_bin_type, GST_TYPE_CHILD_PROXY,
168 &child_proxy_info);
170 GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
171 "debugging info for the 'bin' container element");
172 }
173 return _gst_bin_type;
174 }
176 static void
177 gst_bin_base_init (gpointer g_class)
178 {
179 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
181 gst_element_class_set_details (gstelement_class, &gst_bin_details);
182 }
184 static GstObject *
185 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
186 guint index)
187 {
188 GstObject *res;
189 GstBin *bin;
191 bin = GST_BIN_CAST (child_proxy);
193 GST_LOCK (bin);
194 if ((res = g_list_nth_data (bin->children, index)))
195 gst_object_ref (res);
196 GST_UNLOCK (bin);
198 return res;
199 }
201 guint
202 gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
203 {
204 guint num;
205 GstBin *bin;
207 bin = GST_BIN_CAST (child_proxy);
209 GST_LOCK (bin);
210 num = bin->numchildren;
211 GST_UNLOCK (bin);
213 return num;
214 }
216 static void
217 gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
218 {
219 GstChildProxyInterface *iface = g_iface;
221 iface->get_children_count = gst_bin_child_proxy_get_children_count;
222 iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
223 }
225 static void
226 gst_bin_class_init (GstBinClass * klass)
227 {
228 GObjectClass *gobject_class;
229 GstObjectClass *gstobject_class;
230 GstElementClass *gstelement_class;
232 gobject_class = (GObjectClass *) klass;
233 gstobject_class = (GstObjectClass *) klass;
234 gstelement_class = (GstElementClass *) klass;
236 parent_class = g_type_class_peek_parent (klass);
238 /**
239 * GstBin::element-added:
240 * @bin: the object which emitted the signal.
241 * @element: the element that was added to the bin
242 *
243 * Will be emitted if a new element was removed/added to this bin.
244 */
245 gst_bin_signals[ELEMENT_ADDED] =
246 g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
247 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
248 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
249 /**
250 * GstBin::element-removed:
251 * @bin: the object which emitted the signal.
252 * @element: the element that was removed from the bin
253 *
254 * Will be emitted if an element was removed from this bin.
255 */
256 gst_bin_signals[ELEMENT_REMOVED] =
257 g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
258 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
259 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
261 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
263 #ifndef GST_DISABLE_LOADSAVE
264 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
265 gstobject_class->restore_thyself =
266 GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
267 #endif
269 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
270 gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
271 #ifndef GST_DISABLE_INDEX
272 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
273 #endif
274 gstelement_class->provide_clock =
275 GST_DEBUG_FUNCPTR (gst_bin_provide_clock_func);
276 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
278 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
279 gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
281 klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
282 klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
283 }
285 static void
286 gst_bin_init (GstBin * bin)
287 {
288 GstBus *bus;
290 bin->numchildren = 0;
291 bin->children = NULL;
292 bin->children_cookie = 0;
293 bin->eosed = NULL;
295 /* Set up a bus for listening to child elements */
296 bus = g_object_new (gst_bus_get_type (), NULL);
297 bin->child_bus = bus;
298 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
299 }
301 /**
302 * gst_bin_new:
303 * @name: name of new bin
304 *
305 * Create a new bin with given name.
306 *
307 * Returns: new bin
308 */
309 GstElement *
310 gst_bin_new (const gchar * name)
311 {
312 return gst_element_factory_make ("bin", name);
313 }
315 /* set the index on all elements in this bin
316 *
317 * MT safe
318 */
319 #ifndef GST_DISABLE_INDEX
320 static void
321 gst_bin_set_index_func (GstElement * element, GstIndex * index)
322 {
323 GstBin *bin;
324 GList *children;
326 bin = GST_BIN (element);
328 GST_LOCK (bin);
329 for (children = bin->children; children; children = g_list_next (children)) {
330 GstElement *child = GST_ELEMENT (children->data);
332 gst_element_set_index (child, index);
333 }
334 GST_UNLOCK (bin);
335 }
336 #endif
338 /* set the clock on all elements in this bin
339 *
340 * MT safe
341 */
342 static void
343 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
344 {
345 GList *children;
346 GstBin *bin;
348 bin = GST_BIN (element);
350 GST_LOCK (bin);
351 for (children = bin->children; children; children = g_list_next (children)) {
352 GstElement *child = GST_ELEMENT (children->data);
354 gst_element_set_clock (child, clock);
355 }
356 GST_UNLOCK (bin);
357 }
359 /* get the clock for this bin by asking all of the children in this bin
360 *
361 * The ref of the returned clock in increased so unref after usage.
362 *
363 * MT safe
364 *
365 * FIXME, clock selection is not correct here.
366 */
367 static GstClock *
368 gst_bin_provide_clock_func (GstElement * element)
369 {
370 GstClock *result = NULL;
371 GstBin *bin;
372 GList *children;
374 bin = GST_BIN (element);
376 GST_LOCK (bin);
377 for (children = bin->children; children; children = g_list_next (children)) {
378 GstElement *child = GST_ELEMENT (children->data);
380 result = gst_element_provide_clock (child);
381 if (result)
382 break;
383 }
384 GST_UNLOCK (bin);
386 return result;
387 }
389 static gboolean
390 is_eos (GstBin * bin)
391 {
392 GstIterator *sinks;
393 gboolean result = TRUE;
394 gboolean done = FALSE;
396 sinks = gst_bin_iterate_sinks (bin);
397 while (!done) {
398 gpointer data;
400 switch (gst_iterator_next (sinks, &data)) {
401 case GST_ITERATOR_OK:
402 {
403 GstElement *element = GST_ELEMENT (data);
404 GList *eosed;
405 gchar *name;
407 name = gst_element_get_name (element);
408 eosed = g_list_find (bin->eosed, element);
409 if (!eosed) {
410 GST_DEBUG ("element %s did not post EOS yet", name);
411 result = FALSE;
412 done = TRUE;
413 } else {
414 GST_DEBUG ("element %s posted EOS", name);
415 }
416 g_free (name);
417 gst_object_unref (element);
418 break;
419 }
420 case GST_ITERATOR_RESYNC:
421 result = TRUE;
422 gst_iterator_resync (sinks);
423 break;
424 case GST_ITERATOR_DONE:
425 done = TRUE;
426 break;
427 default:
428 g_assert_not_reached ();
429 break;
430 }
431 }
432 gst_iterator_free (sinks);
433 return result;
434 }
436 static void
437 unlink_pads (GstPad * pad)
438 {
439 GstPad *peer;
441 if ((peer = gst_pad_get_peer (pad))) {
442 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
443 gst_pad_unlink (pad, peer);
444 else
445 gst_pad_unlink (peer, pad);
446 gst_object_unref (peer);
447 }
448 gst_object_unref (pad);
449 }
451 /* add an element to this bin
452 *
453 * MT safe
454 */
455 static gboolean
456 gst_bin_add_func (GstBin * bin, GstElement * element)
457 {
458 gchar *elem_name;
459 GstIterator *it;
461 /* we obviously can't add ourself to ourself */
462 if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
463 goto adding_itself;
465 /* get the element name to make sure it is unique in this bin. */
466 GST_LOCK (element);
467 elem_name = g_strdup (GST_ELEMENT_NAME (element));
468 GST_UNLOCK (element);
470 GST_LOCK (bin);
472 /* then check to see if the element's name is already taken in the bin,
473 * we can safely take the lock here. This check is probably bogus because
474 * you can safely change the element name after this check and before setting
475 * the object parent. The window is very small though... */
476 if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name)))
477 goto duplicate_name;
479 /* set the element's parent and add the element to the bin's list of children */
480 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
481 GST_OBJECT_CAST (bin))))
482 goto had_parent;
484 /* if we add a sink we become a sink */
485 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
486 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "element \"%s\" was sink",
487 elem_name);
488 GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
489 }
491 bin->children = g_list_prepend (bin->children, element);
492 bin->numchildren++;
493 bin->children_cookie++;
495 /* distribute the bus */
496 gst_element_set_bus (element, bin->child_bus);
498 /* propagate the current base time and clock */
499 GST_DEBUG_OBJECT (element, "setting base time %" GST_TIME_FORMAT,
500 GST_TIME_ARGS (GST_ELEMENT (bin)->base_time));
501 gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
502 GST_DEBUG_OBJECT (element, "setting clock %p", GST_ELEMENT_CLOCK (bin));
503 gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
505 GST_UNLOCK (bin);
507 /* unlink all linked pads */
508 it = gst_element_iterate_pads (element);
509 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
510 gst_iterator_free (it);
512 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
513 elem_name);
514 g_free (elem_name);
516 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
518 return TRUE;
520 /* ERROR handling here */
521 adding_itself:
522 {
523 GST_LOCK (bin);
524 g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
525 GST_UNLOCK (bin);
526 return FALSE;
527 }
528 duplicate_name:
529 {
530 g_warning ("Name %s is not unique in bin %s, not adding",
531 elem_name, GST_ELEMENT_NAME (bin));
532 GST_UNLOCK (bin);
533 g_free (elem_name);
534 return FALSE;
535 }
536 had_parent:
537 {
538 g_warning ("Element %s already has parent", elem_name);
539 GST_UNLOCK (bin);
540 g_free (elem_name);
541 return FALSE;
542 }
543 }
546 /**
547 * gst_bin_add:
548 * @bin: #GstBin to add element to
549 * @element: #GstElement to add to bin
550 *
551 * Adds the given element to the bin. Sets the element's parent, and thus
552 * takes ownership of the element. An element can only be added to one bin.
553 *
554 * If the element's pads are linked to other pads, the pads will be unlinked
555 * before the element is added to the bin.
556 *
557 * MT safe.
558 *
559 * Returns: TRUE if the element could be added, FALSE on wrong parameters or
560 * the bin does not want to accept the element.
561 */
562 gboolean
563 gst_bin_add (GstBin * bin, GstElement * element)
564 {
565 GstBinClass *bclass;
566 gboolean result;
568 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
569 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
571 bclass = GST_BIN_GET_CLASS (bin);
573 if (G_UNLIKELY (bclass->add_element == NULL))
574 goto no_function;
576 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
577 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
579 result = bclass->add_element (bin, element);
581 return result;
583 /* ERROR handling */
584 no_function:
585 {
586 g_warning ("adding elements to bin %s is not supported",
587 GST_ELEMENT_NAME (bin));
588 return FALSE;
589 }
590 }
592 /* remove an element from the bin
593 *
594 * MT safe
595 */
596 static gboolean
597 gst_bin_remove_func (GstBin * bin, GstElement * element)
598 {
599 gchar *elem_name;
600 GstIterator *it;
602 GST_LOCK (element);
603 /* Check if the element is already being removed and immediately
604 * return */
605 if (G_UNLIKELY (GST_FLAG_IS_SET (element, GST_ELEMENT_UNPARENTING)))
606 goto already_removing;
608 GST_FLAG_SET (element, GST_ELEMENT_UNPARENTING);
609 /* grab element name so we can print it */
610 elem_name = g_strdup (GST_ELEMENT_NAME (element));
611 GST_UNLOCK (element);
613 /* unlink all linked pads */
614 it = gst_element_iterate_pads (element);
615 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
616 gst_iterator_free (it);
618 GST_LOCK (bin);
619 /* the element must be in the bin's list of children */
620 if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
621 goto not_in_bin;
623 /* now remove the element from the list of elements */
624 bin->children = g_list_remove (bin->children, element);
625 bin->numchildren--;
626 bin->children_cookie++;
628 /* check if we removed a sink */
629 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
630 GList *other_sink;
632 /* check if we removed the last sink */
633 other_sink = g_list_find_custom (bin->children,
634 bin, (GCompareFunc) bin_element_is_sink);
635 if (!other_sink) {
636 /* yups, we're not a sink anymore */
637 GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
638 }
639 }
640 GST_UNLOCK (bin);
642 GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
643 elem_name);
644 g_free (elem_name);
646 gst_element_set_bus (element, NULL);
648 /* unlock any waiters for the state change. It is possible that
649 * we are waiting for an ASYNC state change on this element. The
650 * element cannot be added to another bin yet as it is not yet
651 * unparented. */
652 GST_STATE_LOCK (element);
653 GST_STATE_BROADCAST (element);
654 GST_STATE_UNLOCK (element);
656 /* we ref here because after the _unparent() the element can be disposed
657 * and we still need it to reset the UNPARENTING flag and fire a signal. */
658 gst_object_ref (element);
659 gst_object_unparent (GST_OBJECT_CAST (element));
661 GST_LOCK (element);
662 GST_FLAG_UNSET (element, GST_ELEMENT_UNPARENTING);
663 GST_UNLOCK (element);
665 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
667 /* element is really out of our control now */
668 gst_object_unref (element);
670 return TRUE;
672 /* ERROR handling */
673 not_in_bin:
674 {
675 g_warning ("Element %s is not in bin %s", elem_name,
676 GST_ELEMENT_NAME (bin));
677 GST_UNLOCK (bin);
678 g_free (elem_name);
679 return FALSE;
680 }
681 already_removing:
682 {
683 GST_UNLOCK (element);
684 return FALSE;
685 }
686 }
688 /**
689 * gst_bin_remove:
690 * @bin: #GstBin to remove element from
691 * @element: #GstElement to remove
692 *
693 * Remove the element from its associated bin, unparenting it as well.
694 * Unparenting the element means that the element will be dereferenced,
695 * so if the bin holds the only reference to the element, the element
696 * will be freed in the process of removing it from the bin. If you
697 * want the element to still exist after removing, you need to call
698 * gst_object_ref() before removing it from the bin.
699 *
700 * If the element's pads are linked to other pads, the pads will be unlinked
701 * before the element is removed from the bin.
702 *
703 * MT safe.
704 *
705 * Returns: TRUE if the element could be removed, FALSE on wrong parameters or
706 * the bin does not want to remove the element.
707 */
708 gboolean
709 gst_bin_remove (GstBin * bin, GstElement * element)
710 {
711 GstBinClass *bclass;
712 gboolean result;
714 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
715 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
717 bclass = GST_BIN_GET_CLASS (bin);
719 if (G_UNLIKELY (bclass->remove_element == NULL))
720 goto no_function;
722 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
723 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
725 result = bclass->remove_element (bin, element);
727 return result;
729 /* ERROR handling */
730 no_function:
731 {
732 g_warning ("removing elements from bin %s is not supported",
733 GST_ELEMENT_NAME (bin));
734 return FALSE;
735 }
736 }
738 static GstIteratorItem
739 iterate_child (GstIterator * it, GstElement * child)
740 {
741 gst_object_ref (child);
742 return GST_ITERATOR_ITEM_PASS;
743 }
745 /**
746 * gst_bin_iterate_elements:
747 * @bin: #Gstbin to iterate the elements of
748 *
749 * Get an iterator for the elements in this bin.
750 * Each element will have its refcount increased, so unref
751 * after use.
752 *
753 * MT safe.
754 *
755 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
756 * use. returns NULL when passing bad parameters.
757 */
758 GstIterator *
759 gst_bin_iterate_elements (GstBin * bin)
760 {
761 GstIterator *result;
763 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
765 GST_LOCK (bin);
766 /* add ref because the iterator refs the bin. When the iterator
767 * is freed it will unref the bin again using the provided dispose
768 * function. */
769 gst_object_ref (bin);
770 result = gst_iterator_new_list (GST_TYPE_ELEMENT,
771 GST_GET_LOCK (bin),
772 &bin->children_cookie,
773 &bin->children,
774 bin,
775 (GstIteratorItemFunction) iterate_child,
776 (GstIteratorDisposeFunction) gst_object_unref);
777 GST_UNLOCK (bin);
779 return result;
780 }
782 static GstIteratorItem
783 iterate_child_recurse (GstIterator * it, GstElement * child)
784 {
785 gst_object_ref (child);
786 if (GST_IS_BIN (child)) {
787 GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
789 gst_iterator_push (it, other);
790 }
791 return GST_ITERATOR_ITEM_PASS;
792 }
794 /**
795 * gst_bin_iterate_recurse:
796 * @bin: #Gstbin to iterate the elements of
797 *
798 * Get an iterator for the elements in this bin.
799 * Each element will have its refcount increased, so unref
800 * after use. This iterator recurses into GstBin children.
801 *
802 * MT safe.
803 *
804 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
805 * use. returns NULL when passing bad parameters.
806 */
807 GstIterator *
808 gst_bin_iterate_recurse (GstBin * bin)
809 {
810 GstIterator *result;
812 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
814 GST_LOCK (bin);
815 /* add ref because the iterator refs the bin. When the iterator
816 * is freed it will unref the bin again using the provided dispose
817 * function. */
818 gst_object_ref (bin);
819 result = gst_iterator_new_list (GST_TYPE_ELEMENT,
820 GST_GET_LOCK (bin),
821 &bin->children_cookie,
822 &bin->children,
823 bin,
824 (GstIteratorItemFunction) iterate_child_recurse,
825 (GstIteratorDisposeFunction) gst_object_unref);
826 GST_UNLOCK (bin);
828 return result;
829 }
831 /* returns 0 when TRUE because this is a GCompareFunc */
832 /* MT safe */
833 static gint
834 bin_element_is_sink (GstElement * child, GstBin * bin)
835 {
836 gboolean is_sink;
838 /* we lock the child here for the remainder of the function to
839 * get its name safely. */
840 GST_LOCK (child);
841 is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
843 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
844 "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
846 GST_UNLOCK (child);
847 return is_sink ? 0 : 1;
848 }
850 static gint
851 sink_iterator_filter (GstElement * child, GstBin * bin)
852 {
853 if (bin_element_is_sink (child, bin) == 0) {
854 /* returns 0 because this is a GCompareFunc */
855 return 0;
856 } else {
857 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
858 through */
859 gst_object_unref ((GstObject *) child);
860 return 1;
861 }
862 }
864 /**
865 * gst_bin_iterate_sinks:
866 * @bin: #Gstbin to iterate on
867 *
868 * Get an iterator for the sink elements in this bin.
869 * Each element will have its refcount increased, so unref
870 * after use.
871 *
872 * The sink elements are those without any linked srcpads.
873 *
874 * MT safe.
875 *
876 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
877 */
878 GstIterator *
879 gst_bin_iterate_sinks (GstBin * bin)
880 {
881 GstIterator *children;
882 GstIterator *result;
884 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
886 children = gst_bin_iterate_elements (bin);
887 result = gst_iterator_filter (children,
888 (GCompareFunc) sink_iterator_filter, bin);
890 return result;
891 }
893 /* 2 phases:
894 * 1) check state of all children with 0 timeout to find ERROR and
895 * NO_PREROLL elements. return if found.
896 * 2) perform full blocking wait with requested timeout.
897 *
898 * 2) cannot be performed when 1) returns results as the sinks might
899 * not be able to complete the state change making 2) block forever.
900 *
901 * MT safe
902 */
903 static GstStateChangeReturn
904 gst_bin_get_state (GstElement * element, GstState * state,
905 GstState * pending, GTimeVal * timeout)
906 {
907 GstBin *bin = GST_BIN (element);
908 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
909 GList *children;
910 guint32 children_cookie;
911 gboolean have_no_preroll;
913 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
915 /* lock bin, no element can be added or removed between going into
916 * the quick scan and the blocking wait. */
917 GST_LOCK (bin);
919 restart:
920 have_no_preroll = FALSE;
922 /* first we need to poll with a non zero timeout to make sure we don't block
923 * on the sinks when we have NO_PREROLL elements. This is why we do
924 * a quick check if there are still NO_PREROLL elements. We also
925 * catch the error elements this way. */
926 {
927 GTimeVal tv;
928 gboolean have_async = FALSE;
930 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
931 /* use 0 timeout so we don't block on the sinks */
932 GST_TIME_TO_TIMEVAL (0, tv);
933 children = bin->children;
934 children_cookie = bin->children_cookie;
935 while (children) {
936 GstElement *child = GST_ELEMENT_CAST (children->data);
938 gst_object_ref (child);
939 /* now we release the lock to enter a non blocking wait. We
940 * release the lock anyway since we can. */
941 GST_UNLOCK (bin);
943 ret = gst_element_get_state (child, NULL, NULL, &tv);
945 gst_object_unref (child);
947 /* now grab the lock to iterate to the next child */
948 GST_LOCK (bin);
949 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
950 /* child added/removed during state change, restart. We need
951 * to restart with the quick check as a no-preroll element could
952 * have been added here and we don't want to block on sinks then.*/
953 goto restart;
954 }
956 switch (ret) {
957 /* report FAILURE immediatly */
958 case GST_STATE_CHANGE_FAILURE:
959 goto done;
960 case GST_STATE_CHANGE_NO_PREROLL:
961 /* we have to continue scanning as there might be
962 * ERRORS too */
963 have_no_preroll = TRUE;
964 break;
965 case GST_STATE_CHANGE_ASYNC:
966 have_async = TRUE;
967 break;
968 default:
969 break;
970 }
971 children = g_list_next (children);
972 }
973 /* if we get here, we have no FAILURES, check for any NO_PREROLL
974 * elements then. */
975 if (have_no_preroll) {
976 ret = GST_STATE_CHANGE_NO_PREROLL;
977 goto done;
978 }
980 /* if we get here, no NO_PREROLL elements are in the pipeline */
981 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
983 /* if no ASYNC elements exist we don't even have to poll with a
984 * timeout again */
985 if (!have_async) {
986 ret = GST_STATE_CHANGE_SUCCESS;
987 goto done;
988 }
989 }
991 /* next we poll all children for their state to see if one of them
992 * is still busy with its state change. We did not release the bin lock
993 * yet so the elements are the same as the ones from the quick scan. */
994 children = bin->children;
995 children_cookie = bin->children_cookie;
996 while (children) {
997 GstElement *child = GST_ELEMENT_CAST (children->data);
999 gst_object_ref (child);
1000 /* now we release the lock to enter the potentialy blocking wait */
1001 GST_UNLOCK (bin);
1003 /* ret is ASYNC if some child is still performing the state change
1004 * ater the timeout. */
1005 ret = gst_element_get_state (child, NULL, NULL, timeout);
1007 gst_object_unref (child);
1009 /* now grab the lock to iterate to the next child */
1010 GST_LOCK (bin);
1011 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1012 /* child added/removed during state change, restart. We need
1013 * to restart with the quick check as a no-preroll element could
1014 * have been added here and we don't want to block on sinks then.*/
1015 goto restart;
1016 }
1018 switch (ret) {
1019 case GST_STATE_CHANGE_SUCCESS:
1020 break;
1021 case GST_STATE_CHANGE_FAILURE:
1022 case GST_STATE_CHANGE_NO_PREROLL:
1023 /* report FAILURE and NO_PREROLL immediatly */
1024 goto done;
1025 case GST_STATE_CHANGE_ASYNC:
1026 goto done;
1027 default:
1028 g_assert_not_reached ();
1029 }
1030 children = g_list_next (children);
1031 }
1032 /* if we got here, all elements can do preroll */
1033 have_no_preroll = FALSE;
1035 done:
1036 GST_UNLOCK (bin);
1038 /* now we can take the state lock, it is possible that new elements
1039 * are added now and we still report the old state. No problem though as
1040 * the return is still consistent, the effect is as if the element was
1041 * added after this function completed. */
1042 GST_STATE_LOCK (bin);
1043 switch (ret) {
1044 case GST_STATE_CHANGE_SUCCESS:
1045 /* we can commit the state */
1046 gst_element_commit_state (element);
1047 break;
1048 case GST_STATE_CHANGE_FAILURE:
1049 /* some element failed, abort the state change */
1050 gst_element_abort_state (element);
1051 break;
1052 default:
1053 /* other cases are just passed along */
1054 break;
1055 }
1057 /* and report the state if needed */
1058 if (state)
1059 *state = GST_STATE (element);
1060 if (pending)
1061 *pending = GST_STATE_PENDING (element);
1063 GST_STATE_NO_PREROLL (element) = have_no_preroll;
1065 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1066 "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1067 gst_element_state_get_name (GST_STATE (element)),
1068 gst_element_state_get_name (GST_STATE_PENDING (element)),
1069 GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1071 GST_STATE_UNLOCK (bin);
1073 return ret;
1074 }
1076 /***********************************************
1077 * Topologically sorted iterator
1078 * see http://en.wikipedia.org/wiki/Topological_sorting
1079 *
1080 * For each element in the graph, an entry is kept in a HashTable
1081 * with its number of srcpad connections (degree).
1082 * We then change state of all elements without dependencies
1083 * (degree 0) and decrement the degree of all elements connected
1084 * on the sinkpads. When an element reaches degree 0, its state is
1085 * changed next.
1086 * When all elements are handled the algorithm stops.
1087 */
1088 typedef struct _GstBinSortIterator
1089 {
1090 GstIterator it;
1091 GQueue *queue; /* elements queued for state change */
1092 GstBin *bin; /* bin we iterate */
1093 gint mode; /* adding or removing dependency */
1094 GstElement *best; /* next element with least dependencies */
1095 gint best_deg; /* best degree */
1096 GHashTable *hash; /* has table with element dependencies */
1097 } GstBinSortIterator;
1099 /* we add and subtract 1 to make sure we don't confuse NULL and 0 */
1100 #define HASH_SET_DEGREE(bit, elem, deg) \
1101 g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1))
1102 #define HASH_GET_DEGREE(bit, elem) \
1103 (GPOINTER_TO_INT(g_hash_table_lookup (bit->hash, elem))-1)
1105 /* add element to queue of next elements in the iterator.
1106 * We push at the tail to give higher priority elements a
1107 * chance first */
1108 static void
1109 add_to_queue (GstBinSortIterator * bit, GstElement * element)
1110 {
1111 GST_DEBUG ("%s add to queue", GST_ELEMENT_NAME (element));
1112 gst_object_ref (element);
1113 g_queue_push_tail (bit->queue, element);
1114 HASH_SET_DEGREE (bit, element, -1);
1115 }
1117 /* clear the queue, unref all objects as we took a ref when
1118 * we added them to the queue */
1119 static void
1120 clear_queue (GQueue * queue)
1121 {
1122 gpointer p;
1124 while ((p = g_queue_pop_head (queue)))
1125 gst_object_unref (p);
1126 }
1128 /* set all degrees to 0. Elements marked as a sink are
1129 * added to the queue immediatly. */
1130 static void
1131 reset_degree (GstElement * element, GstBinSortIterator * bit)
1132 {
1133 /* sinks are added right away */
1134 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
1135 add_to_queue (bit, element);
1136 } else {
1137 /* others are marked with 0 and handled when sinks are done */
1138 HASH_SET_DEGREE (bit, element, 0);
1139 }
1140 }
1142 /* adjust the degree of all elements connected to the given
1143 * element. If an degree of an element drops to 0, it is
1144 * added to the queue of elements to schedule next.
1145 *
1146 * We have to make sure not to cross the bin boundary this element
1147 * belongs to.
1148 */
1149 static void
1150 update_degree (GstElement * element, GstBinSortIterator * bit)
1151 {
1152 gboolean linked = FALSE;
1154 GST_LOCK (element);
1155 /* don't touch degree is element has no sourcepads */
1156 if (element->numsinkpads != 0) {
1157 /* loop over all sinkpads, decrement degree for all connected
1158 * elements in this bin */
1159 GList *pads;
1161 for (pads = element->sinkpads; pads; pads = g_list_next (pads)) {
1162 GstPad *peer;
1164 if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
1165 GstElement *peer_element;
1167 if ((peer_element = gst_pad_get_parent_element (peer))) {
1168 GST_LOCK (peer_element);
1169 if (GST_OBJECT_CAST (peer_element)->parent ==
1170 GST_OBJECT_CAST (bit->bin)) {
1171 gint old_deg, new_deg;
1173 old_deg = HASH_GET_DEGREE (bit, peer_element);
1174 new_deg = old_deg + bit->mode;
1176 GST_DEBUG ("change element %s, degree %d->%d, linked to %s",
1177 GST_ELEMENT_NAME (peer_element),
1178 old_deg, new_deg, GST_ELEMENT_NAME (element));
1180 /* update degree */
1181 if (new_deg == 0) {
1182 /* degree hit 0, add to queue */
1183 add_to_queue (bit, peer_element);
1184 } else {
1185 HASH_SET_DEGREE (bit, peer_element, new_deg);
1186 }
1187 linked = TRUE;
1188 }
1189 GST_UNLOCK (peer_element);
1190 gst_object_unref (peer_element);
1191 }
1192 gst_object_unref (peer);
1193 }
1194 }
1195 }
1196 if (!linked) {
1197 GST_DEBUG ("element %s not linked to anything", GST_ELEMENT_NAME (element));
1198 }
1199 GST_UNLOCK (element);
1200 }
1202 /* find the next best element not handled yet. This is the one
1203 * with the lowest non-negative degree */
1204 static void
1205 find_element (GstElement * element, GstBinSortIterator * bit)
1206 {
1207 gint degree;
1209 /* element is already handled */
1210 if ((degree = HASH_GET_DEGREE (bit, element)) < 0)
1211 return;
1213 /* first element or element with smaller degree */
1214 if (bit->best == NULL || bit->best_deg > degree) {
1215 bit->best = element;
1216 bit->best_deg = degree;
1217 }
1218 }
1220 /* get next element in iterator. the returned element has the
1221 * refcount increased */
1222 static GstIteratorResult
1223 gst_bin_sort_iterator_next (GstBinSortIterator * bit, gpointer * result)
1224 {
1225 /* empty queue, we have to find a next best element */
1226 if (g_queue_is_empty (bit->queue)) {
1227 bit->best = NULL;
1228 bit->best_deg = G_MAXINT;
1229 g_list_foreach (bit->bin->children, (GFunc) find_element, bit);
1230 if (bit->best) {
1231 if (bit->best_deg != 0) {
1232 /* we don't fail on this one yet */
1233 g_warning ("loop detected in the graph !!");
1234 }
1235 /* best unhandled element, schedule as next element */
1236 GST_DEBUG ("queue empty, next best: %s", GST_ELEMENT_NAME (bit->best));
1237 gst_object_ref (bit->best);
1238 HASH_SET_DEGREE (bit, bit->best, -1);
1239 *result = bit->best;
1240 } else {
1241 GST_DEBUG ("queue empty, elements exhausted");
1242 /* no more unhandled elements, we are done */
1243 return GST_ITERATOR_DONE;
1244 }
1245 } else {
1246 /* everything added to the queue got reffed */
1247 *result = g_queue_pop_head (bit->queue);
1248 }
1250 GST_DEBUG ("queue head gives %s", GST_ELEMENT_NAME (*result));
1251 /* update degrees of linked elements */
1252 update_degree (GST_ELEMENT_CAST (*result), bit);
1254 return GST_ITERATOR_OK;
1255 }
1257 /* clear queues, recalculate the degrees and restart. */
1258 static void
1259 gst_bin_sort_iterator_resync (GstBinSortIterator * bit)
1260 {
1261 clear_queue (bit->queue);
1262 /* reset degrees */
1263 g_list_foreach (bit->bin->children, (GFunc) reset_degree, bit);
1264 /* calc degrees, incrementing */
1265 bit->mode = 1;
1266 g_list_foreach (bit->bin->children, (GFunc) update_degree, bit);
1267 /* for the rest of the function we decrement the degrees */
1268 bit->mode = -1;
1269 }
1271 /* clear queues, unref bin and free iterator. */
1272 static void
1273 gst_bin_sort_iterator_free (GstBinSortIterator * bit)
1274 {
1275 clear_queue (bit->queue);
1276 g_queue_free (bit->queue);
1277 g_hash_table_destroy (bit->hash);
1278 gst_object_unref (bit->bin);
1279 g_free (bit);
1280 }
1282 /**
1283 * gst_bin_iterate_sorted:
1284 * @bin: #Gstbin to iterate on
1285 *
1286 * Get an iterator for the elements in this bin in topologically
1287 * sorted order. This means that the elements are returned from
1288 * the most downstream elements (sinks) to the sources.
1289 *
1290 * This function is used internally to perform the state changes
1291 * of the bin elements.
1292 *
1293 * Each element will have its refcount increased, so unref
1294 * after use.
1295 *
1296 * MT safe.
1297 *
1298 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
1299 */
1300 GstIterator *
1301 gst_bin_iterate_sorted (GstBin * bin)
1302 {
1303 GstBinSortIterator *result;
1305 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1307 GST_LOCK (bin);
1308 gst_object_ref (bin);
1309 /* we don't need a NextFunction because we ref the items in the _next
1310 * method already */
1311 result = (GstBinSortIterator *)
1312 gst_iterator_new (GST_TYPE_ELEMENT,
1313 sizeof (GstBinSortIterator),
1314 GST_GET_LOCK (bin),
1315 &bin->children_cookie,
1316 (GstIteratorNextFunction) gst_bin_sort_iterator_next,
1317 (GstIteratorItemFunction) NULL,
1318 (GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
1319 (GstIteratorFreeFunction) gst_bin_sort_iterator_free);
1320 result->queue = g_queue_new ();
1321 result->hash = g_hash_table_new (NULL, NULL);
1322 result->bin = bin;
1323 gst_bin_sort_iterator_resync (result);
1324 GST_UNLOCK (bin);
1326 return (GstIterator *) result;
1327 }
1329 static GstStateChangeReturn
1330 gst_bin_element_set_state (GstBin * bin, GstElement * element, GstState pending)
1331 {
1332 GstStateChangeReturn ret;
1333 gboolean locked;
1335 /* peel off the locked flag */
1336 GST_LOCK (element);
1337 locked = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
1338 GST_UNLOCK (element);
1340 /* skip locked elements */
1341 if (G_UNLIKELY (locked)) {
1342 ret = GST_STATE_CHANGE_SUCCESS;
1343 goto done;
1344 }
1346 /* change state */
1347 ret = gst_element_set_state (element, pending);
1349 done:
1350 return ret;
1351 }
1353 static GstStateChangeReturn
1354 gst_bin_change_state (GstElement * element, GstStateChange transition)
1355 {
1356 GstBin *bin;
1357 GstStateChangeReturn ret;
1358 GstState old_state, pending;
1359 gboolean have_async;
1360 gboolean have_no_preroll;
1361 GstClockTime base_time;
1362 GstIterator *it;
1363 gboolean done;
1365 /* we don't need to take the STATE_LOCK, it is already taken */
1366 old_state = GST_STATE (element);
1367 pending = GST_STATE_PENDING (element);
1369 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1370 "changing state of children from %s to %s",
1371 gst_element_state_get_name (old_state),
1372 gst_element_state_get_name (pending));
1374 if (pending == GST_STATE_VOID_PENDING)
1375 return GST_STATE_CHANGE_SUCCESS;
1377 bin = GST_BIN_CAST (element);
1379 /* Clear eosed element list on READY-> PAUSED */
1380 if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
1381 g_list_free (bin->eosed);
1382 bin->eosed = NULL;
1383 }
1385 /* iterate in state change order */
1386 it = gst_bin_iterate_sorted (bin);
1388 restart:
1389 /* take base time */
1390 base_time = element->base_time;
1392 have_async = FALSE;
1393 have_no_preroll = FALSE;
1395 done = FALSE;
1396 while (!done) {
1397 gpointer data;
1399 switch (gst_iterator_next (it, &data)) {
1400 case GST_ITERATOR_OK:
1401 {
1402 GstElement *element;
1404 element = GST_ELEMENT_CAST (data);
1406 /* set base time on element */
1407 gst_element_set_base_time (element, base_time);
1409 /* set state now */
1410 ret = gst_bin_element_set_state (bin, element, pending);
1412 switch (ret) {
1413 case GST_STATE_CHANGE_SUCCESS:
1414 GST_CAT_DEBUG (GST_CAT_STATES,
1415 "child '%s' changed state to %d(%s) successfully",
1416 GST_ELEMENT_NAME (element), pending,
1417 gst_element_state_get_name (pending));
1418 break;
1419 case GST_STATE_CHANGE_ASYNC:
1420 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1421 "child '%s' is changing state asynchronously",
1422 GST_ELEMENT_NAME (element));
1423 have_async = TRUE;
1424 break;
1425 case GST_STATE_CHANGE_FAILURE:
1426 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1427 "child '%s' failed to go to state %d(%s)",
1428 GST_ELEMENT_NAME (element),
1429 pending, gst_element_state_get_name (pending));
1430 gst_object_unref (element);
1431 goto done;
1432 case GST_STATE_CHANGE_NO_PREROLL:
1433 GST_CAT_DEBUG (GST_CAT_STATES,
1434 "child '%s' changed state to %d(%s) successfully without preroll",
1435 GST_ELEMENT_NAME (element), pending,
1436 gst_element_state_get_name (pending));
1437 have_no_preroll = TRUE;
1438 break;
1439 default:
1440 g_assert_not_reached ();
1441 break;
1442 }
1443 gst_object_unref (element);
1444 break;
1445 }
1446 case GST_ITERATOR_RESYNC:
1447 GST_CAT_DEBUG (GST_CAT_STATES, "iterator doing resync");
1448 gst_iterator_resync (it);
1449 goto restart;
1450 break;
1451 default:
1452 case GST_ITERATOR_DONE:
1453 GST_CAT_DEBUG (GST_CAT_STATES, "iterator done");
1454 done = TRUE;
1455 break;
1456 }
1457 }
1459 if (have_no_preroll) {
1460 ret = GST_STATE_CHANGE_NO_PREROLL;
1461 } else if (have_async) {
1462 ret = GST_STATE_CHANGE_ASYNC;
1463 } else {
1464 ret = parent_class->change_state (element, transition);
1465 }
1467 done:
1468 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1469 "done changing bin's state from %s to %s, now in %s, ret %d",
1470 gst_element_state_get_name (old_state),
1471 gst_element_state_get_name (pending),
1472 gst_element_state_get_name (GST_STATE (element)), ret);
1474 gst_iterator_free (it);
1476 return ret;
1477 }
1479 static void
1480 gst_bin_dispose (GObject * object)
1481 {
1482 GstBin *bin = GST_BIN (object);
1484 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
1486 g_list_free (bin->eosed);
1487 bin->eosed = NULL;
1488 gst_object_unref (bin->child_bus);
1489 bin->child_bus = NULL;
1491 while (bin->children) {
1492 gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
1493 }
1494 if (G_UNLIKELY (bin->children != NULL)) {
1495 g_critical ("could not remove elements from bin %s",
1496 GST_STR_NULL (GST_OBJECT_NAME (object)));
1497 }
1499 G_OBJECT_CLASS (parent_class)->dispose (object);
1500 }
1502 /*
1503 * This function is a utility event handler for seek events.
1504 * It will send the event to all sinks.
1505 * Applications are free to override this behaviour and
1506 * implement their own seek handler, but this will work for
1507 * pretty much all cases in practice.
1508 */
1509 static gboolean
1510 gst_bin_send_event (GstElement * element, GstEvent * event)
1511 {
1512 GstBin *bin = GST_BIN (element);
1513 GstIterator *iter;
1514 gboolean res = TRUE;
1515 gboolean done = FALSE;
1517 iter = gst_bin_iterate_sinks (bin);
1518 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1520 while (!done) {
1521 gpointer data;
1523 switch (gst_iterator_next (iter, &data)) {
1524 case GST_ITERATOR_OK:
1525 {
1526 GstElement *sink;
1528 gst_event_ref (event);
1529 sink = GST_ELEMENT_CAST (data);
1530 res &= gst_element_send_event (sink, event);
1531 gst_object_unref (sink);
1532 break;
1533 }
1534 case GST_ITERATOR_RESYNC:
1535 gst_iterator_resync (iter);
1536 res = TRUE;
1537 break;
1538 default:
1539 case GST_ITERATOR_DONE:
1540 done = TRUE;
1541 break;
1542 }
1543 }
1544 gst_iterator_free (iter);
1545 gst_event_unref (event);
1547 return res;
1548 }
1550 static GstBusSyncReply
1551 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
1552 {
1553 GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %s",
1554 message, gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
1556 switch (GST_MESSAGE_TYPE (message)) {
1557 case GST_MESSAGE_EOS:{
1558 GstObject *src = GST_MESSAGE_SRC (message);
1560 if (src) {
1561 gchar *name;
1563 name = gst_object_get_name (src);
1564 GST_DEBUG_OBJECT (bin, "got EOS message from %s", name);
1565 g_free (name);
1567 /* collect all eos messages from the children */
1568 GST_LOCK (bin->child_bus);
1569 bin->eosed = g_list_prepend (bin->eosed, src);
1570 GST_UNLOCK (bin->child_bus);
1572 /* if we are completely EOS, we forward an EOS message */
1573 if (is_eos (bin)) {
1574 GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
1575 gst_element_post_message (GST_ELEMENT (bin),
1576 gst_message_new_eos (GST_OBJECT (bin)));
1577 }
1578 } else {
1579 GST_DEBUG_OBJECT (bin, "got EOS message from (NULL), not processing");
1580 }
1582 /* we drop all EOS messages */
1583 gst_message_unref (message);
1584 break;
1585 }
1586 default:
1587 /* Send all other messages upward */
1588 GST_DEBUG_OBJECT (bin, "posting message upward");
1589 gst_element_post_message (GST_ELEMENT (bin), message);
1590 break;
1591 }
1593 return GST_BUS_DROP;
1594 }
1596 static gboolean
1597 gst_bin_query (GstElement * element, GstQuery * query)
1598 {
1599 GstBin *bin = GST_BIN (element);
1600 GstIterator *iter;
1601 gboolean res = FALSE, done = FALSE;
1603 iter = gst_bin_iterate_sinks (bin);
1604 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1606 while (!(res || done)) {
1607 gpointer data;
1609 switch (gst_iterator_next (iter, &data)) {
1610 case GST_ITERATOR_OK:
1611 {
1612 GstElement *sink;
1614 sink = GST_ELEMENT_CAST (data);
1615 res = gst_element_query (sink, query);
1616 gst_object_unref (sink);
1617 break;
1618 }
1619 case GST_ITERATOR_RESYNC:
1620 gst_iterator_resync (iter);
1621 break;
1622 default:
1623 case GST_ITERATOR_DONE:
1624 done = TRUE;
1625 break;
1626 }
1627 }
1628 gst_iterator_free (iter);
1630 return res;
1631 }
1633 static gint
1634 compare_name (GstElement * element, const gchar * name)
1635 {
1636 gint eq;
1638 GST_LOCK (element);
1639 eq = strcmp (GST_ELEMENT_NAME (element), name);
1640 GST_UNLOCK (element);
1642 if (eq != 0) {
1643 gst_object_unref (element);
1644 }
1645 return eq;
1646 }
1648 /**
1649 * gst_bin_get_by_name:
1650 * @bin: #Gstbin to search
1651 * @name: the element name to search for
1652 *
1653 * Get the element with the given name from this bin. This
1654 * function recurses into subbins.
1655 *
1656 * MT safe.
1657 *
1658 * Returns: the element with the given name. Returns NULL if the
1659 * element is not found or when bad parameters were given. Unref after
1660 * use.
1661 */
1662 GstElement *
1663 gst_bin_get_by_name (GstBin * bin, const gchar * name)
1664 {
1665 GstIterator *children;
1666 GstIterator *result;
1668 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1670 GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
1671 GST_ELEMENT_NAME (bin), name);
1673 children = gst_bin_iterate_recurse (bin);
1674 result = gst_iterator_find_custom (children,
1675 (GCompareFunc) compare_name, (gpointer) name);
1676 gst_iterator_free (children);
1678 return GST_ELEMENT_CAST (result);
1679 }
1681 /**
1682 * gst_bin_get_by_name_recurse_up:
1683 * @bin: #Gstbin to search
1684 * @name: the element name to search for
1685 *
1686 * MT safe.
1687 *
1688 * Get the element with the given name from this bin. If the
1689 * element is not found, a recursion is performed on the parent bin.
1690 *
1691 * Returns: the element with the given name or NULL when the element
1692 * was not found or bad parameters were given. Unref after use.
1693 */
1694 GstElement *
1695 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
1696 {
1697 GstElement *result;
1699 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1700 g_return_val_if_fail (name != NULL, NULL);
1702 result = gst_bin_get_by_name (bin, name);
1704 if (!result) {
1705 GstObject *parent;
1707 parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
1708 if (parent) {
1709 if (GST_IS_BIN (parent)) {
1710 result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
1711 }
1712 gst_object_unref (parent);
1713 }
1714 }
1716 return result;
1717 }
1719 static gint
1720 compare_interface (GstElement * element, gpointer interface)
1721 {
1722 gint ret;
1724 if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
1725 ret = 0;
1726 } else {
1727 /* we did not find the element, need to release the ref
1728 * added by the iterator */
1729 gst_object_unref (element);
1730 ret = 1;
1731 }
1732 return ret;
1733 }
1735 /**
1736 * gst_bin_get_by_interface:
1737 * @bin: bin to find element in
1738 * @interface: interface to be implemented by interface
1739 *
1740 * Looks for the first element inside the bin that implements the given
1741 * interface. If such an element is found, it returns the element. You can
1742 * cast this element to the given interface afterwards.
1743 * If you want all elements that implement the interface, use
1744 * gst_bin_iterate_all_by_interface(). The function recurses inside bins.
1745 *
1746 * MT safe.
1747 *
1748 * Returns: An #GstElement inside the bin implementing the interface.
1749 * Unref after use.
1750 */
1751 GstElement *
1752 gst_bin_get_by_interface (GstBin * bin, GType interface)
1753 {
1754 GstIterator *children;
1755 GstIterator *result;
1757 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1759 children = gst_bin_iterate_recurse (bin);
1760 result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
1761 GINT_TO_POINTER (interface));
1762 gst_iterator_free (children);
1764 return GST_ELEMENT_CAST (result);
1765 }
1767 /**
1768 * gst_bin_iterate_all_by_interface:
1769 * @bin: bin to find elements in
1770 * @interface: interface to be implemented by interface
1771 *
1772 * Looks for all elements inside the bin that implements the given
1773 * interface. You can safely cast all returned elements to the given interface.
1774 * The function recurses bins inside bins. The iterator will return a series
1775 * of #GstElement that should be unreffed after use.
1776 *
1777 * MT safe.
1778 *
1779 * Returns: A #GstIterator for the elements inside the bin implementing the
1780 * given interface.
1781 */
1782 GstIterator *
1783 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
1784 {
1785 GstIterator *children;
1786 GstIterator *result;
1788 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1790 children = gst_bin_iterate_recurse (bin);
1791 result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
1792 GINT_TO_POINTER (interface));
1794 return result;
1795 }
1797 #ifndef GST_DISABLE_LOADSAVE
1798 static xmlNodePtr
1799 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
1800 {
1801 GstBin *bin = GST_BIN (object);
1802 xmlNodePtr childlist, elementnode;
1803 GList *children;
1804 GstElement *child;
1806 if (GST_OBJECT_CLASS (parent_class)->save_thyself)
1807 GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
1809 childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
1811 GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
1812 GST_ELEMENT_NAME (bin), bin->numchildren);
1814 children = bin->children;
1815 while (children) {
1816 child = GST_ELEMENT (children->data);
1817 elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
1818 gst_object_save_thyself (GST_OBJECT (child), elementnode);
1819 children = g_list_next (children);
1820 }
1821 return childlist;
1822 }
1824 static void
1825 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
1826 {
1827 GstBin *bin = GST_BIN (object);
1828 xmlNodePtr field = self->xmlChildrenNode;
1829 xmlNodePtr childlist;
1831 while (field) {
1832 if (!strcmp ((char *) field->name, "children")) {
1833 GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
1834 GST_ELEMENT_NAME (object));
1835 childlist = field->xmlChildrenNode;
1836 while (childlist) {
1837 if (!strcmp ((char *) childlist->name, "element")) {
1838 GstElement *element =
1839 gst_xml_make_element (childlist, GST_OBJECT (bin));
1841 /* it had to be parented to find the pads, now we ref and unparent so
1842 * we can add it to the bin */
1843 gst_object_ref (element);
1844 gst_object_unparent (GST_OBJECT (element));
1846 gst_bin_add (bin, element);
1847 }
1848 childlist = childlist->next;
1849 }
1850 }
1852 field = field->next;
1853 }
1854 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
1855 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
1856 }
1857 #endif /* GST_DISABLE_LOADSAVE */