3 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
4 * 2004 Wim Taymans <wim@fluendo.com>
6 * gstbin.c: GstBin container object and support code
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
27 * @short_description: Base class for elements that contain other elements
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.
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 scheduler
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().
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
46 * The list of elements in a bin can be retrieved with gst_bin_get_list().
48 * After the bin has been set to the PLAYING state (with gst_element_set_state()),
49 * gst_bin_iterate() is used to process the elements in the bin.
51 * The "element_added" signal is fired whenever a new element is added to the
52 * bin. Likewise the "element_removed" signal is fired whenever an element is
53 * removed from the bin.
55 * gst_bin_destroy() is used to destroy the bin.
57 * To control the selection of the clock in a bin, you can use the following
59 * gst_bin_auto_clock() to let the bin select a clock automatically,
60 * gst_bin_get_clock() to get the current clock of the bin and
61 * gst_bin_use_clock() to specify a clock explicitly.
62 * Note that the default behaviour is to automatically select a clock from one
63 * of the clock providers in the bin.
66 #include "gst_private.h"
70 #include "gstmarshal.h"
77 #include "gstchildproxy.h"
79 GST_DEBUG_CATEGORY_STATIC (bin_debug);
80 #define GST_CAT_DEFAULT bin_debug
81 #define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
82 text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
83 (bin)->numchildren, (guint) (bin)->child_states[3], \
84 (guint) (bin)->child_states[2], (bin)->child_states[1], \
85 (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
88 static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
90 "Simple container object",
91 "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
93 GType _gst_bin_type = 0;
95 static void gst_bin_dispose (GObject * object);
97 static GstElementStateReturn gst_bin_change_state (GstElement * element);
98 static GstElementStateReturn gst_bin_get_state (GstElement * element,
99 GstElementState * state, GstElementState * pending, GTimeVal * timeout);
101 static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
102 static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
104 #ifndef GST_DISABLE_INDEX
105 static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
107 static GstClock *gst_bin_get_clock_func (GstElement * element);
108 static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
110 static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
111 static GstBusSyncReply bin_bus_handler (GstBus * bus,
112 GstMessage * message, GstBin * bin);
113 static gboolean gst_bin_query (GstElement * element, GstQuery * query);
115 #ifndef GST_DISABLE_LOADSAVE
116 static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
117 static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
120 static gint bin_element_is_sink (GstElement * child, GstBin * bin);
122 /* Bin signals and args */
136 static void gst_bin_base_init (gpointer g_class);
137 static void gst_bin_class_init (GstBinClass * klass);
138 static void gst_bin_init (GstBin * bin);
139 static void gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data);
141 static GstElementClass *parent_class = NULL;
142 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
147 * Returns: the type of #GstBin
150 gst_bin_get_type (void)
152 if (!_gst_bin_type) {
153 static const GTypeInfo bin_info = {
154 sizeof (GstBinClass),
157 (GClassInitFunc) gst_bin_class_init,
162 (GInstanceInitFunc) gst_bin_init,
165 static const GInterfaceInfo child_proxy_info = {
166 gst_bin_child_proxy_init,
172 g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
174 g_type_add_interface_static (_gst_bin_type, GST_TYPE_CHILD_PROXY,
177 GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
178 "debugging info for the 'bin' container element");
180 return _gst_bin_type;
184 gst_bin_base_init (gpointer g_class)
186 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
188 gst_element_class_set_details (gstelement_class, &gst_bin_details);
192 gst_bin_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
195 return g_list_nth_data (GST_BIN (child_proxy)->children, index);
199 gst_bin_child_proxy_get_children_count (GstChildProxy * child_proxy)
201 return GST_BIN (child_proxy)->numchildren;
205 gst_bin_child_proxy_init (gpointer g_iface, gpointer iface_data)
207 GstChildProxyInterface *iface = g_iface;
209 iface->get_children_count = gst_bin_child_proxy_get_children_count;
210 iface->get_child_by_index = gst_bin_child_proxy_get_child_by_index;
214 gst_bin_class_init (GstBinClass * klass)
216 GObjectClass *gobject_class;
217 GstObjectClass *gstobject_class;
218 GstElementClass *gstelement_class;
220 gobject_class = (GObjectClass *) klass;
221 gstobject_class = (GstObjectClass *) klass;
222 gstelement_class = (GstElementClass *) klass;
224 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
227 * GstBin::element-added:
228 * @bin: the object which emitted the signal.
229 * @element: the element that was added to the bin
231 * Will be emitted if a new element was removed/added to this bin.
233 gst_bin_signals[ELEMENT_ADDED] =
234 g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
235 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
236 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
238 * GstBin::element-removed:
239 * @bin: the object which emitted the signal.
240 * @element: the element that was removed from the bin
242 * Will be emitted if an element was removed from this bin.
244 gst_bin_signals[ELEMENT_REMOVED] =
245 g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
246 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
247 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
249 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
251 #ifndef GST_DISABLE_LOADSAVE
252 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
253 gstobject_class->restore_thyself =
254 GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
257 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
258 gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
259 #ifndef GST_DISABLE_INDEX
260 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
262 gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
263 gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
265 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
266 gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
268 klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
269 klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
273 gst_bin_init (GstBin * bin)
277 bin->numchildren = 0;
278 bin->children = NULL;
279 bin->children_cookie = 0;
282 /* Set up a bus for listening to child elements,
283 * and one for sending messages up the hierarchy */
284 bus = g_object_new (gst_bus_get_type (), NULL);
285 bin->child_bus = bus;
286 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
288 bus = g_object_new (gst_bus_get_type (), NULL);
289 gst_element_set_bus (GST_ELEMENT (bin), bus);
290 /* set_bus refs the bus via gst_object_replace, we drop our ref */
291 gst_object_unref (bus);
296 * @name: name of new bin
298 * Create a new bin with given name.
303 gst_bin_new (const gchar * name)
305 return gst_element_factory_make ("bin", name);
308 /* set the index on all elements in this bin
312 #ifndef GST_DISABLE_INDEX
314 gst_bin_set_index_func (GstElement * element, GstIndex * index)
319 bin = GST_BIN (element);
322 for (children = bin->children; children; children = g_list_next (children)) {
323 GstElement *child = GST_ELEMENT (children->data);
325 gst_element_set_index (child, index);
331 /* set the clock on all elements in this bin
336 gst_bin_set_clock_func (GstElement * element, GstClock * clock)
341 bin = GST_BIN (element);
344 for (children = bin->children; children; children = g_list_next (children)) {
345 GstElement *child = GST_ELEMENT (children->data);
347 gst_element_set_clock (child, clock);
352 /* get the clock for this bin by asking all of the children in this bin
357 gst_bin_get_clock_func (GstElement * element)
359 GstClock *result = NULL;
363 bin = GST_BIN (element);
366 for (children = bin->children; children; children = g_list_next (children)) {
367 GstElement *child = GST_ELEMENT (children->data);
369 result = gst_element_get_clock (child);
379 is_eos (GstBin * bin)
382 gboolean result = TRUE;
383 gboolean done = FALSE;
385 sinks = gst_bin_iterate_sinks (bin);
389 switch (gst_iterator_next (sinks, &data)) {
390 case GST_ITERATOR_OK:
392 GstElement *element = GST_ELEMENT (data);
396 name = gst_element_get_name (element);
397 eosed = g_list_find (bin->eosed, element);
399 GST_DEBUG ("element %s did not post EOS yet", name);
403 GST_DEBUG ("element %s posted EOS", name);
406 gst_object_unref (element);
409 case GST_ITERATOR_RESYNC:
411 gst_iterator_resync (sinks);
413 case GST_ITERATOR_DONE:
417 g_assert_not_reached ();
421 gst_iterator_free (sinks);
426 unlink_pads (GstPad * pad)
430 if ((peer = gst_pad_get_peer (pad))) {
431 if (gst_pad_get_direction (pad) == GST_PAD_SRC)
432 gst_pad_unlink (pad, peer);
434 gst_pad_unlink (peer, pad);
435 gst_object_unref (peer);
437 gst_object_unref (pad);
440 /* add an element to this bin
445 gst_bin_add_func (GstBin * bin, GstElement * element)
450 /* we obviously can't add ourself to ourself */
451 if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
454 /* get the element name to make sure it is unique in this bin. */
456 elem_name = g_strdup (GST_ELEMENT_NAME (element));
457 GST_UNLOCK (element);
461 /* then check to see if the element's name is already taken in the bin,
462 * we can safely take the lock here. This check is probably bogus because
463 * you can safely change the element name after this check and before setting
464 * the object parent. The window is very small though... */
465 if (G_UNLIKELY (!gst_object_check_uniqueness (bin->children, elem_name)))
468 /* set the element's parent and add the element to the bin's list of children */
469 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
470 GST_OBJECT_CAST (bin))))
473 /* if we add a sink we become a sink */
474 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
475 GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
477 bin->children = g_list_prepend (bin->children, element);
479 bin->children_cookie++;
481 /* distribute the bus */
482 gst_element_set_bus (element, bin->child_bus);
484 /* propagate the current base time and clock */
485 gst_element_set_base_time (element, GST_ELEMENT (bin)->base_time);
486 gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
490 /* unlink all linked pads */
491 it = gst_element_iterate_pads (element);
492 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
493 gst_iterator_free (it);
495 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
499 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
503 /* ERROR handling here */
507 g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
513 g_warning ("Name %s is not unique in bin %s, not adding",
514 elem_name, GST_ELEMENT_NAME (bin));
521 g_warning ("Element %s already has parent", elem_name);
531 * @bin: #GstBin to add element to
532 * @element: #GstElement to add to bin
534 * Adds the given element to the bin. Sets the element's parent, and thus
535 * takes ownership of the element. An element can only be added to one bin.
537 * If the element's pads are linked to other pads, the pads will be unlinked
538 * before the element is added to the bin.
542 * Returns: TRUE if the element could be added, FALSE on wrong parameters or
543 * the bin does not want to accept the element.
546 gst_bin_add (GstBin * bin, GstElement * element)
551 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
552 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
554 bclass = GST_BIN_GET_CLASS (bin);
556 if (G_UNLIKELY (bclass->add_element == NULL))
559 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
560 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
562 result = bclass->add_element (bin, element);
569 g_warning ("adding elements to bin %s is not supported",
570 GST_ELEMENT_NAME (bin));
575 /* remove an element from the bin
580 gst_bin_remove_func (GstBin * bin, GstElement * element)
585 /* grab element name so we can print it */
587 elem_name = g_strdup (GST_ELEMENT_NAME (element));
588 GST_UNLOCK (element);
591 /* the element must be in the bin's list of children */
592 if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
595 /* now remove the element from the list of elements */
596 bin->children = g_list_remove (bin->children, element);
598 bin->children_cookie++;
600 /* check if we removed a sink */
601 if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
604 /* check if we removed the last sink */
605 other_sink = g_list_find_custom (bin->children,
606 bin, (GCompareFunc) bin_element_is_sink);
608 /* yups, we're not a sink anymore */
609 GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
614 GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
618 /* unlink all linked pads */
619 it = gst_element_iterate_pads (element);
620 gst_iterator_foreach (it, (GFunc) unlink_pads, element);
621 gst_iterator_free (it);
623 gst_element_set_bus (element, NULL);
625 /* unlock any waiters for the state change. It is possible that
626 * we are waiting for an ASYNC state change on this element. The
627 * element cannot be added to another bin yet as it is not yet
629 GST_STATE_LOCK (element);
630 GST_STATE_BROADCAST (element);
631 GST_STATE_UNLOCK (element);
633 /* we ref here because after the _unparent() the element can be disposed
634 * and we still need it to fire a signal. */
635 gst_object_ref (element);
636 gst_object_unparent (GST_OBJECT_CAST (element));
638 g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
639 /* element is really out of our control now */
640 gst_object_unref (element);
647 g_warning ("Element %s is not in bin %s", elem_name,
648 GST_ELEMENT_NAME (bin));
657 * @bin: #GstBin to remove element from
658 * @element: #GstElement to remove
660 * Remove the element from its associated bin, unparenting it as well.
661 * Unparenting the element means that the element will be dereferenced,
662 * so if the bin holds the only reference to the element, the element
663 * will be freed in the process of removing it from the bin. If you
664 * want the element to still exist after removing, you need to call
665 * #gst_object_ref before removing it from the bin.
667 * If the element's pads are linked to other pads, the pads will be unlinked
668 * before the element is removed from the bin.
672 * Returns: TRUE if the element could be removed, FALSE on wrong parameters or
673 * the bin does not want to remove the element.
676 gst_bin_remove (GstBin * bin, GstElement * element)
681 g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
682 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
684 bclass = GST_BIN_GET_CLASS (bin);
686 if (G_UNLIKELY (bclass->remove_element == NULL))
689 GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
690 GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
692 result = bclass->remove_element (bin, element);
699 g_warning ("removing elements from bin %s is not supported",
700 GST_ELEMENT_NAME (bin));
705 static GstIteratorItem
706 iterate_child (GstIterator * it, GstElement * child)
708 gst_object_ref (child);
709 return GST_ITERATOR_ITEM_PASS;
713 * gst_bin_iterate_elements:
714 * @bin: #Gstbin to iterate the elements of
716 * Get an iterator for the elements in this bin.
717 * Each element will have its refcount increased, so unref
722 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
723 * use. returns NULL when passing bad parameters.
726 gst_bin_iterate_elements (GstBin * bin)
730 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
733 /* add ref because the iterator refs the bin. When the iterator
734 * is freed it will unref the bin again using the provided dispose
736 gst_object_ref (bin);
737 result = gst_iterator_new_list (GST_GET_LOCK (bin),
738 &bin->children_cookie,
741 (GstIteratorItemFunction) iterate_child,
742 (GstIteratorDisposeFunction) gst_object_unref);
748 static GstIteratorItem
749 iterate_child_recurse (GstIterator * it, GstElement * child)
751 gst_object_ref (child);
752 if (GST_IS_BIN (child)) {
753 GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
755 gst_iterator_push (it, other);
757 return GST_ITERATOR_ITEM_PASS;
761 * gst_bin_iterate_recurse:
762 * @bin: #Gstbin to iterate the elements of
764 * Get an iterator for the elements in this bin.
765 * Each element will have its refcount increased, so unref
766 * after use. This iterator recurses into GstBin children.
770 * Returns: a #GstIterator of #GstElements. gst_iterator_free after
771 * use. returns NULL when passing bad parameters.
774 gst_bin_iterate_recurse (GstBin * bin)
778 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
781 /* add ref because the iterator refs the bin. When the iterator
782 * is freed it will unref the bin again using the provided dispose
784 gst_object_ref (bin);
785 result = gst_iterator_new_list (GST_GET_LOCK (bin),
786 &bin->children_cookie,
789 (GstIteratorItemFunction) iterate_child_recurse,
790 (GstIteratorDisposeFunction) gst_object_unref);
796 /* returns 0 when TRUE because this is a GCompareFunc */
799 bin_element_is_sink (GstElement * child, GstBin * bin)
803 /* we lock the child here for the remainder of the function to
804 * get its name safely. */
806 is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
808 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
809 "child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
812 return is_sink ? 0 : 1;
815 /* check if object has the given ancestor somewhere up in
819 has_ancestor (GstObject * object, GstObject * ancestor)
822 gboolean result = FALSE;
827 if (object == ancestor)
830 parent = gst_object_get_parent (object);
831 result = has_ancestor (parent, ancestor);
833 gst_object_unref (parent);
838 /* returns 0 when TRUE because this is a GCompareFunc.
839 * This function returns elements that have no connected srcpads and
840 * are therefore not reachable from a real sink. */
843 bin_element_is_semi_sink (GstElement * child, GstBin * bin)
847 /* we lock the child here for the remainder of the function to
848 * get its pads and name safely. */
851 /* check if this is a sink element, these are the elements
852 * without (linked) source pads. */
853 if (child->numsrcpads == 0) {
855 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
856 "adding child %s as sink", GST_OBJECT_NAME (child));
859 /* loop over all pads, try to figure out if this element
860 * is a semi sink because it has no linked source pads */
862 gboolean connected_src = FALSE;
864 for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
867 GST_DEBUG ("looking at pad %p", pads->data);
868 if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
870 has_ancestor (GST_OBJECT_CAST (peer), GST_OBJECT_CAST (bin));
871 gst_object_unref (peer);
878 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
879 "not adding child %s as sink: linked source pads",
880 GST_OBJECT_NAME (child));
882 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
883 "adding child %s as sink since it has unlinked source pads in this bin",
884 GST_OBJECT_NAME (child));
894 sink_iterator_filter (GstElement * child, GstBin * bin)
896 if (bin_element_is_sink (child, bin) == 0) {
897 /* returns 0 because this is a GCompareFunc */
900 /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
902 gst_object_unref ((GstObject *) child);
908 * gst_bin_iterate_sinks:
909 * @bin: #Gstbin to iterate on
911 * Get an iterator for the sink elements in this bin.
912 * Each element will have its refcount increased, so unref
915 * The sink elements are those without any linked srcpads.
919 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
922 gst_bin_iterate_sinks (GstBin * bin)
924 GstIterator *children;
927 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
929 children = gst_bin_iterate_elements (bin);
930 result = gst_iterator_filter (children,
931 (GCompareFunc) sink_iterator_filter, bin);
937 * 1) check state of all children with 0 timeout to find ERROR and
938 * NO_PREROLL elements. return if found.
939 * 2) perform full blocking wait with requested timeout.
941 * 2) cannot be performed when 1) returns results as the sinks might
942 * not be able to complete the state change making 2) block forever.
946 static GstElementStateReturn
947 gst_bin_get_state (GstElement * element, GstElementState * state,
948 GstElementState * pending, GTimeVal * timeout)
950 GstBin *bin = GST_BIN (element);
951 GstElementStateReturn ret = GST_STATE_SUCCESS;
953 guint32 children_cookie;
954 gboolean have_no_preroll;
956 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
958 /* lock bin, no element can be added or removed between going into
959 * the quick scan and the blocking wait. */
963 have_no_preroll = FALSE;
965 /* first we need to poll with a non zero timeout to make sure we don't block
966 * on the sinks when we have NO_PREROLL elements. This is why we do
967 * a quick check if there are still NO_PREROLL elements. We also
968 * catch the error elements this way. */
971 gboolean have_async = FALSE;
973 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
974 /* use 0 timeout so we don't block on the sinks */
975 GST_TIME_TO_TIMEVAL (0, tv);
976 children = bin->children;
977 children_cookie = bin->children_cookie;
979 GstElement *child = GST_ELEMENT_CAST (children->data);
981 gst_object_ref (child);
982 /* now we release the lock to enter a non blocking wait. We
983 * release the lock anyway since we can. */
986 ret = gst_element_get_state (child, NULL, NULL, &tv);
988 gst_object_unref (child);
990 /* now grab the lock to iterate to the next child */
992 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
993 /* child added/removed during state change, restart. We need
994 * to restart with the quick check as a no-preroll element could
995 * have been added here and we don't want to block on sinks then.*/
1000 /* report FAILURE immediatly */
1001 case GST_STATE_FAILURE:
1003 case GST_STATE_NO_PREROLL:
1004 /* we have to continue scanning as there might be
1006 have_no_preroll = TRUE;
1008 case GST_STATE_ASYNC:
1014 children = g_list_next (children);
1016 /* if we get here, we have no FAILURES, check for any NO_PREROLL
1018 if (have_no_preroll) {
1019 ret = GST_STATE_NO_PREROLL;
1023 /* if we get here, no NO_PREROLL elements are in the pipeline */
1024 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
1026 /* if no ASYNC elements exist we don't even have to poll with a
1029 ret = GST_STATE_SUCCESS;
1034 /* next we poll all children for their state to see if one of them
1035 * is still busy with its state change. We did not release the bin lock
1036 * yet so the elements are the same as the ones from the quick scan. */
1037 children = bin->children;
1038 children_cookie = bin->children_cookie;
1040 GstElement *child = GST_ELEMENT_CAST (children->data);
1042 gst_object_ref (child);
1043 /* now we release the lock to enter the potentialy blocking wait */
1046 /* ret is ASYNC if some child is still performing the state change
1047 * ater the timeout. */
1048 ret = gst_element_get_state (child, NULL, NULL, timeout);
1050 gst_object_unref (child);
1052 /* now grab the lock to iterate to the next child */
1054 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1055 /* child added/removed during state change, restart. We need
1056 * to restart with the quick check as a no-preroll element could
1057 * have been added here and we don't want to block on sinks then.*/
1062 case GST_STATE_SUCCESS:
1064 case GST_STATE_FAILURE:
1065 case GST_STATE_NO_PREROLL:
1066 /* report FAILURE and NO_PREROLL immediatly */
1068 case GST_STATE_ASYNC:
1071 g_assert_not_reached ();
1073 children = g_list_next (children);
1075 /* if we got here, all elements can do preroll */
1076 have_no_preroll = FALSE;
1081 /* now we can take the state lock, it is possible that new elements
1082 * are added now and we still report the old state. No problem though as
1083 * the return is still consistent, the effect is as if the element was
1084 * added after this function completed. */
1085 GST_STATE_LOCK (bin);
1087 case GST_STATE_SUCCESS:
1088 /* we can commit the state */
1089 gst_element_commit_state (element);
1091 case GST_STATE_FAILURE:
1092 /* some element failed, abort the state change */
1093 gst_element_abort_state (element);
1096 /* other cases are just passed along */
1100 /* and report the state if needed */
1102 *state = GST_STATE (element);
1104 *pending = GST_STATE_PENDING (element);
1106 GST_STATE_NO_PREROLL (element) = have_no_preroll;
1108 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1109 "state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
1110 gst_element_state_get_name (GST_STATE (element)),
1111 gst_element_state_get_name (GST_STATE_PENDING (element)),
1112 GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
1114 GST_STATE_UNLOCK (bin);
1120 append_child (gpointer child, GQueue * queue)
1122 g_queue_push_tail (queue, child);
1126 * gst_bin_iterate_state_order:
1127 * @bin: #Gstbin to iterate on
1129 * Get an iterator for the elements in this bin in the order
1130 * in which a state change should be performed on them. This
1131 * means that first the sinks and then the other elements will
1133 * Each element will have its refcount increased, so unref
1136 * Not implemented yet.
1140 * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
1143 gst_bin_iterate_state_order (GstBin * bin)
1145 GstIterator *result;
1147 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1155 clear_queue (GQueue * queue, gboolean unref)
1159 while ((p = g_queue_pop_head (queue)))
1161 gst_object_unref (p);
1165 remove_all_from_queue (GQueue * queue, gpointer elem, gboolean unref)
1169 while ((p = g_queue_find (queue, elem))) {
1171 gst_object_unref (elem);
1172 g_queue_delete_link (queue, p);
1176 /* this function is called with the STATE_LOCK held. It works
1179 * 1) put all sink elements on the queue.
1180 * 2) put all semisink elements on the queue.
1181 * 3) change state of elements in queue, put linked elements to queue.
1182 * 4) while queue not empty goto 3)
1184 * This will effectively change the state of all elements in the bin
1185 * from the sinks to the sources. We have to change the states this
1186 * way so that when a source element pushes data, the downstream element
1187 * is in the right state to receive the data.
1191 /* FIXME, make me more elegant, want to use a topological sort algorithm
1192 * based on indegrees (or outdegrees in our case) */
1193 static GstElementStateReturn
1194 gst_bin_change_state (GstElement * element)
1197 GstElementStateReturn ret;
1198 GstElementState old_state, pending;
1199 gboolean have_async = FALSE;
1200 gboolean have_no_preroll = FALSE;
1202 guint32 children_cookie;
1203 GQueue *elem_queue; /* list of elements waiting for a state change */
1204 GQueue *semi_queue; /* list of elements with no connected srcpads */
1205 GQueue *temp; /* queue of leftovers */
1206 GstClockTime base_time;
1208 bin = GST_BIN (element);
1210 /* we don't need to take the STATE_LOCK, it is already taken */
1211 old_state = GST_STATE (element);
1212 pending = GST_STATE_PENDING (element);
1214 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1215 "changing state of children from %s to %s",
1216 gst_element_state_get_name (old_state),
1217 gst_element_state_get_name (pending));
1219 if (pending == GST_STATE_VOID_PENDING)
1220 return GST_STATE_SUCCESS;
1222 /* Clear eosed element list on READY-> PAUSED */
1223 if (GST_STATE_TRANSITION (element) == GST_STATE_READY_TO_PAUSED) {
1224 g_list_free (bin->eosed);
1228 /* all elements added to these queues should have their refcount
1230 elem_queue = g_queue_new ();
1231 semi_queue = g_queue_new ();
1232 temp = g_queue_new ();
1234 /* first step, find all sink elements, these are the elements
1235 * without (linked) source pads. */
1239 /* take base time */
1240 base_time = element->base_time;
1242 /* make sure queues are empty, they could be filled when
1244 clear_queue (elem_queue, TRUE);
1245 clear_queue (semi_queue, TRUE);
1246 clear_queue (temp, TRUE);
1248 children = bin->children;
1249 children_cookie = bin->children_cookie;
1250 GST_DEBUG_OBJECT (bin, "reffing and examining children");
1252 GstElement *child = GST_ELEMENT_CAST (children->data);
1254 gst_object_ref (child);
1257 if (bin_element_is_sink (child, bin) == 0) {
1258 g_queue_push_tail (elem_queue, child);
1259 } else if (bin_element_is_semi_sink (child, bin) == 0) {
1260 g_queue_push_tail (semi_queue, child);
1262 g_queue_push_tail (temp, child);
1266 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1267 GST_INFO_OBJECT (bin, "bin->children_cookie changed, restarting");
1268 /* restart will unref the children in the queues so that we don't
1269 * leak refcounts. */
1272 children = g_list_next (children);
1274 GST_DEBUG_OBJECT (bin, "reffed and examined children");
1277 /* after this point new elements can be added/removed from the
1278 * bin. We operate on the snapshot taken above. Applications
1279 * should serialize their add/remove and set_state. */
1281 /* now change state for semi sink elements first so add them in
1282 * front of the other elements */
1283 g_queue_foreach (temp, (GFunc) append_child, semi_queue);
1284 clear_queue (temp, FALSE);
1286 /* if we don't have real sinks, we continue with the other elements */
1287 if (g_queue_is_empty (elem_queue) && !g_queue_is_empty (semi_queue)) {
1288 GQueue *q = elem_queue;
1290 /* we swap the queues as oposed to copy them over */
1291 elem_queue = semi_queue;
1295 /* second step, change state of elements in the queue */
1296 GST_DEBUG_OBJECT (bin, "change state of elements in the queue");
1297 while (!g_queue_is_empty (elem_queue)) {
1298 GstElement *qelement;
1303 qelement = g_queue_pop_head (elem_queue);
1304 /* we don't need any duplicates in the other queue anymore */
1305 remove_all_from_queue (semi_queue, qelement, TRUE);
1307 /* queue all elements connected to the sinkpads of this element */
1308 GST_LOCK (qelement);
1309 pads = qelement->sinkpads;
1311 GstPad *pad = GST_PAD_CAST (pads->data);
1314 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1315 "found sinkpad %s:%s", GST_DEBUG_PAD_NAME (pad));
1317 peer = gst_pad_get_peer (pad);
1319 GstObject *peer_parent;
1322 peer_parent = gst_object_get_parent (GST_OBJECT (peer));
1324 /* if we have an element parent, follow it */
1325 if (peer_parent && GST_IS_ELEMENT (peer_parent)) {
1328 /* see if this element is in the bin we are currently handling */
1329 parent = gst_object_get_parent (peer_parent);
1331 if (parent == GST_OBJECT_CAST (bin)) {
1332 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1333 "adding element %s to queue", GST_ELEMENT_NAME (peer_parent));
1335 /* make sure we don't have duplicates */
1336 remove_all_from_queue (semi_queue, peer_parent, TRUE);
1337 remove_all_from_queue (elem_queue, peer_parent, TRUE);
1339 /* was reffed before pushing on the queue by the
1340 * gst_object_get_parent() call we used to get the element. */
1341 g_queue_push_tail (elem_queue, peer_parent);
1342 /* so that we don't unref it */
1345 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1346 "not adding element %s to queue, it is in another bin",
1347 GST_ELEMENT_NAME (peer_parent));
1349 gst_object_unref (parent);
1353 gst_object_unref (peer_parent);
1355 gst_object_unref (peer);
1357 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1358 "pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));
1360 pads = g_list_next (pads);
1362 /* peel off the locked flag and release the element lock */
1363 locked = GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE);
1364 GST_UNLOCK (qelement);
1366 /* skip locked elements */
1367 if (G_UNLIKELY (locked))
1370 /* set base time on element */
1371 gst_element_set_base_time (qelement, base_time);
1373 /* then change state */
1374 ret = gst_element_set_state (qelement, pending);
1376 /* the set state could have cause elements to be added/removed,
1377 * we support that. */
1379 if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
1380 gst_object_unref (qelement);
1386 case GST_STATE_SUCCESS:
1387 GST_CAT_DEBUG (GST_CAT_STATES,
1388 "child '%s' changed state to %d(%s) successfully",
1389 GST_ELEMENT_NAME (qelement), pending,
1390 gst_element_state_get_name (pending));
1392 case GST_STATE_ASYNC:
1393 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1394 "child '%s' is changing state asynchronously",
1395 GST_ELEMENT_NAME (qelement));
1398 case GST_STATE_FAILURE:
1399 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
1400 "child '%s' failed to go to state %d(%s)",
1401 GST_ELEMENT_NAME (qelement),
1402 pending, gst_element_state_get_name (pending));
1403 ret = GST_STATE_FAILURE;
1404 /* release refcount of element we popped off the queue */
1405 gst_object_unref (qelement);
1407 case GST_STATE_NO_PREROLL:
1408 GST_CAT_DEBUG (GST_CAT_STATES,
1409 "child '%s' changed state to %d(%s) successfully without preroll",
1410 GST_ELEMENT_NAME (qelement), pending,
1411 gst_element_state_get_name (pending));
1412 have_no_preroll = TRUE;
1415 g_assert_not_reached ();
1419 gst_object_unref (qelement);
1421 /* if queue is empty now, continue with a non-sink */
1422 if (g_queue_is_empty (elem_queue)) {
1423 GstElement *non_sink;
1425 GST_DEBUG ("sinks and upstream elements exhausted");
1426 non_sink = g_queue_pop_head (semi_queue);
1428 GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
1429 g_queue_push_tail (elem_queue, non_sink);
1434 if (have_no_preroll) {
1435 ret = GST_STATE_NO_PREROLL;
1436 } else if (have_async) {
1437 ret = GST_STATE_ASYNC;
1439 ret = parent_class->change_state (element);
1442 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
1443 "done changing bin's state from %s to %s, now in %s, ret %d",
1444 gst_element_state_get_name (old_state),
1445 gst_element_state_get_name (pending),
1446 gst_element_state_get_name (GST_STATE (element)), ret);
1449 /* release refcounts in queue, should normally be empty unless we
1451 clear_queue (elem_queue, TRUE);
1452 clear_queue (semi_queue, TRUE);
1453 g_queue_free (elem_queue);
1454 g_queue_free (semi_queue);
1455 g_queue_free (temp);
1461 gst_bin_dispose (GObject * object)
1463 GstBin *bin = GST_BIN (object);
1465 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
1467 /* ref to not hit 0 again */
1468 gst_object_ref (object);
1470 g_list_free (bin->eosed);
1472 gst_object_unref (bin->child_bus);
1473 bin->child_bus = NULL;
1474 gst_element_set_bus (GST_ELEMENT (bin), NULL);
1476 while (bin->children) {
1477 gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
1479 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose no children");
1480 g_assert (bin->children == NULL);
1481 g_assert (bin->numchildren == 0);
1483 G_OBJECT_CLASS (parent_class)->dispose (object);
1487 * This function is a utility event handler for seek events.
1488 * It will send the event to all sinks.
1489 * Applications are free to override this behaviour and
1490 * implement their own seek handler, but this will work for
1491 * pretty much all cases in practice.
1494 gst_bin_send_event (GstElement * element, GstEvent * event)
1496 GstBin *bin = GST_BIN (element);
1498 gboolean res = TRUE;
1499 gboolean done = FALSE;
1501 iter = gst_bin_iterate_sinks (bin);
1502 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1507 switch (gst_iterator_next (iter, &data)) {
1508 case GST_ITERATOR_OK:
1512 gst_event_ref (event);
1513 sink = GST_ELEMENT_CAST (data);
1514 res &= gst_element_send_event (sink, event);
1515 gst_object_unref (sink);
1518 case GST_ITERATOR_RESYNC:
1519 gst_iterator_resync (iter);
1523 case GST_ITERATOR_DONE:
1528 gst_iterator_free (iter);
1529 gst_event_unref (event);
1534 static GstBusSyncReply
1535 bin_bus_handler (GstBus * bus, GstMessage * message, GstBin * bin)
1537 GST_DEBUG_OBJECT (bin, "[msg %p] handling child message of type %d",
1538 message, GST_MESSAGE_TYPE (message));
1540 switch (GST_MESSAGE_TYPE (message)) {
1541 case GST_MESSAGE_EOS:{
1542 GObject *src = GST_MESSAGE_SRC (message);
1545 if (src && GST_IS_OBJECT (src))
1546 name = gst_object_get_name (GST_OBJECT (src));
1548 name = g_strdup ("(null)");
1550 GST_DEBUG_OBJECT (bin, "got EOS message from %s", name);
1553 /* collect all eos messages from the children */
1554 GST_LOCK (bin->child_bus);
1555 bin->eosed = g_list_prepend (bin->eosed, GST_MESSAGE_SRC (message));
1556 GST_UNLOCK (bin->child_bus);
1558 /* if we are completely EOS, we forward an EOS message */
1560 GST_DEBUG_OBJECT (bin, "all sinks posted EOS");
1561 gst_element_post_message (GST_ELEMENT (bin),
1562 gst_message_new_eos (GST_OBJECT (bin)));
1565 /* we drop all EOS messages */
1566 gst_message_unref (message);
1570 /* Send all other messages upward */
1571 GST_DEBUG_OBJECT (bin, "posting message upward");
1572 gst_element_post_message (GST_ELEMENT (bin), message);
1576 return GST_BUS_DROP;
1580 gst_bin_query (GstElement * element, GstQuery * query)
1582 GstBin *bin = GST_BIN (element);
1584 gboolean res = FALSE, done = FALSE;
1586 iter = gst_bin_iterate_sinks (bin);
1587 GST_DEBUG_OBJECT (bin, "Sending event to sink children");
1589 while (!(res || done)) {
1592 switch (gst_iterator_next (iter, &data)) {
1593 case GST_ITERATOR_OK:
1597 sink = GST_ELEMENT_CAST (data);
1598 res = gst_element_query (sink, query);
1599 gst_object_unref (sink);
1602 case GST_ITERATOR_RESYNC:
1603 gst_iterator_resync (iter);
1606 case GST_ITERATOR_DONE:
1611 gst_iterator_free (iter);
1617 compare_name (GstElement * element, const gchar * name)
1622 eq = strcmp (GST_ELEMENT_NAME (element), name);
1623 GST_UNLOCK (element);
1626 gst_object_unref (element);
1632 * gst_bin_get_by_name:
1633 * @bin: #Gstbin to search
1634 * @name: the element name to search for
1636 * Get the element with the given name from this bin. This
1637 * function recurses into subbins.
1641 * Returns: the element with the given name. Returns NULL if the
1642 * element is not found or when bad parameters were given. Unref after
1646 gst_bin_get_by_name (GstBin * bin, const gchar * name)
1648 GstIterator *children;
1649 GstIterator *result;
1651 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1653 GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
1654 GST_ELEMENT_NAME (bin), name);
1656 children = gst_bin_iterate_recurse (bin);
1657 result = gst_iterator_find_custom (children,
1658 (GCompareFunc) compare_name, (gpointer) name);
1659 gst_iterator_free (children);
1661 return GST_ELEMENT_CAST (result);
1665 * gst_bin_get_by_name_recurse_up:
1666 * @bin: #Gstbin to search
1667 * @name: the element name to search for
1671 * Get the element with the given name from this bin. If the
1672 * element is not found, a recursion is performed on the parent bin.
1674 * Returns: the element with the given name or NULL when the element
1675 * was not found or bad parameters were given. Unref after use.
1678 gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
1682 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1683 g_return_val_if_fail (name != NULL, NULL);
1685 result = gst_bin_get_by_name (bin, name);
1690 parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
1692 if (GST_IS_BIN (parent)) {
1693 result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
1695 gst_object_unref (parent);
1703 compare_interface (GstElement * element, gpointer interface)
1707 if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
1710 /* we did not find the element, need to release the ref
1711 * added by the iterator */
1712 gst_object_unref (element);
1719 * gst_bin_get_by_interface:
1720 * @bin: bin to find element in
1721 * @interface: interface to be implemented by interface
1723 * Looks for the first element inside the bin that implements the given
1724 * interface. If such an element is found, it returns the element. You can
1725 * cast this element to the given interface afterwards.
1726 * If you want all elements that implement the interface, use
1727 * gst_bin_iterate_all_by_interface(). The function recurses inside bins.
1731 * Returns: An #GstElement inside the bin implementing the interface.
1735 gst_bin_get_by_interface (GstBin * bin, GType interface)
1737 GstIterator *children;
1738 GstIterator *result;
1740 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1742 children = gst_bin_iterate_recurse (bin);
1743 result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
1744 GINT_TO_POINTER (interface));
1745 gst_iterator_free (children);
1747 return GST_ELEMENT_CAST (result);
1751 * gst_bin_iterate_all_by_interface:
1752 * @bin: bin to find elements in
1753 * @interface: interface to be implemented by interface
1755 * Looks for all elements inside the bin that implements the given
1756 * interface. You can safely cast all returned elements to the given interface.
1757 * The function recurses bins inside bins. The iterator will return a series
1758 * of #GstElement that should be unreffed after use.
1762 * Returns: A #GstIterator for the elements inside the bin implementing the
1766 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
1768 GstIterator *children;
1769 GstIterator *result;
1771 g_return_val_if_fail (GST_IS_BIN (bin), NULL);
1773 children = gst_bin_iterate_recurse (bin);
1774 result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
1775 GINT_TO_POINTER (interface));
1780 #ifndef GST_DISABLE_LOADSAVE
1782 gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
1784 GstBin *bin = GST_BIN (object);
1785 xmlNodePtr childlist, elementnode;
1789 if (GST_OBJECT_CLASS (parent_class)->save_thyself)
1790 GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
1792 childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
1794 GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
1795 GST_ELEMENT_NAME (bin), bin->numchildren);
1797 children = bin->children;
1799 child = GST_ELEMENT (children->data);
1800 elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
1801 gst_object_save_thyself (GST_OBJECT (child), elementnode);
1802 children = g_list_next (children);
1808 gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
1810 GstBin *bin = GST_BIN (object);
1811 xmlNodePtr field = self->xmlChildrenNode;
1812 xmlNodePtr childlist;
1815 if (!strcmp ((char *) field->name, "children")) {
1816 GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
1817 GST_ELEMENT_NAME (object));
1818 childlist = field->xmlChildrenNode;
1820 if (!strcmp ((char *) childlist->name, "element")) {
1821 GstElement *element =
1822 gst_xml_make_element (childlist, GST_OBJECT (bin));
1824 /* it had to be parented to find the pads, now we ref and unparent so
1825 * we can add it to the bin */
1826 gst_object_ref (element);
1827 gst_object_unparent (GST_OBJECT (element));
1829 gst_bin_add (bin, element);
1831 childlist = childlist->next;
1835 field = field->next;
1837 if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
1838 (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
1840 #endif /* GST_DISABLE_LOADSAVE */