Renamed a local var to better state what its purpose is.
[platform/upstream/gstreamer.git] / gst / gstbin.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstbin.c: GstBin container object and support code
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
25
26 #include "gstbin.h"
27
28 #include "gstscheduler.h"
29
30 GstElementDetails gst_bin_details = {
31   "Generic bin",
32   "Bin",
33   "Simple container object",
34   VERSION,
35   "Erik Walthinsen <omega@cse.ogi.edu>",
36   "(C) 1999",
37 };
38
39 GType _gst_bin_type = 0;
40
41 static void                     gst_bin_dispose         (GObject *object);
42
43 static GstElementStateReturn    gst_bin_change_state            (GstElement *element);
44 static GstElementStateReturn    gst_bin_change_state_norecurse  (GstBin *bin);
45 static gboolean                 gst_bin_change_state_type       (GstBin *bin,
46                                                                  GstElementState state,
47                                                                  GType type);
48
49 static gboolean                 gst_bin_iterate_func            (GstBin *bin);
50
51 #ifndef GST_DISABLE_LOADSAVE
52 static xmlNodePtr               gst_bin_save_thyself            (GstObject *object, xmlNodePtr parent);
53 static void                     gst_bin_restore_thyself         (GstObject *object, xmlNodePtr self);
54 #endif
55
56 /* Bin signals and args */
57 enum {
58   OBJECT_ADDED,
59   LAST_SIGNAL
60 };
61
62 enum {
63   ARG_0,
64   /* FILL ME */
65 };
66
67
68 static void gst_bin_class_init  (GstBinClass *klass);
69 static void gst_bin_init        (GstBin *bin);
70
71
72 static GstElementClass *parent_class = NULL;
73 static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
74
75 GType
76 gst_bin_get_type (void)
77 {
78   if (!_gst_bin_type) {
79     static const GTypeInfo bin_info = {
80       sizeof(GstBinClass),
81       NULL,
82       NULL,
83       (GClassInitFunc)gst_bin_class_init,
84       NULL,
85       NULL,
86       sizeof(GstBin),
87       8,
88       (GInstanceInitFunc)gst_bin_init,
89       NULL
90     };
91     _gst_bin_type = g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
92   }
93   return _gst_bin_type;
94 }
95
96 static void
97 gst_bin_class_init (GstBinClass *klass)
98 {
99   GObjectClass *gobject_class;
100   GstObjectClass *gstobject_class;
101   GstElementClass *gstelement_class;
102
103   gobject_class = (GObjectClass*)klass;
104   gstobject_class = (GstObjectClass*)klass;
105   gstelement_class = (GstElementClass*)klass;
106
107   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
108
109   gst_bin_signals[OBJECT_ADDED] =
110     g_signal_new ("object_added", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST,
111                     G_STRUCT_OFFSET (GstBinClass, object_added), NULL, NULL,
112                     gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
113                     GST_TYPE_ELEMENT);
114
115   klass->change_state_type =            GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
116   klass->iterate =                      GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
117
118 #ifndef GST_DISABLE_LOADSAVE
119   gstobject_class->save_thyself =       GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
120   gstobject_class->restore_thyself =    GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
121 #endif
122
123   gstelement_class->change_state =      GST_DEBUG_FUNCPTR (gst_bin_change_state);
124
125   gobject_class->dispose =              GST_DEBUG_FUNCPTR (gst_bin_dispose);
126 }
127
128 static void
129 gst_bin_init (GstBin *bin)
130 {
131   // in general, we prefer to use cothreads for most things
132   GST_FLAG_SET (bin, GST_BIN_FLAG_PREFER_COTHREADS);
133
134   bin->numchildren = 0;
135   bin->children = NULL;
136   bin->eos_providers = NULL;
137   bin->num_eos_providers = 0;
138   bin->chains = NULL;
139   bin->eoscond = g_cond_new ();
140 }
141
142 /**
143  * gst_bin_new:
144  * @name: name of new bin
145  *
146  * Create a new bin with given name.
147  *
148  * Returns: new bin
149  */
150 GstElement*
151 gst_bin_new (const gchar *name)
152 {
153   return gst_elementfactory_make ("bin", name);
154 }
155
156 static inline void
157 gst_bin_reset_element_sched (GstElement *element, GstSchedule *sched)
158 {
159   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "resetting element's scheduler");
160
161   // first remove the element from its current schedule, if any
162 //  if (GST_ELEMENT_SCHED(element))
163 //    GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element);
164   // then set the new manager
165   gst_element_set_sched (element,sched);
166
167   // and add it to the new scheduler
168 //  if (sched)
169 //    GST_SCHEDULE_ADD_ELEMENT (sched, element);
170 }
171
172 static void
173 gst_bin_set_element_sched (GstElement *element,GstSchedule *sched)
174 {
175   GList *children;
176   GstElement *child;
177
178   g_return_if_fail (element != NULL);
179   g_return_if_fail (GST_IS_ELEMENT(element));
180   g_return_if_fail (sched != NULL);
181   g_return_if_fail (GST_IS_SCHEDULE(sched));
182
183   GST_INFO (GST_CAT_SCHEDULING, "setting element \"%s\" sched to %p",GST_ELEMENT_NAME(element),
184             sched);
185
186   // if it's actually a Bin
187   if (GST_IS_BIN(element)) {
188
189     if (GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) {
190       GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is already a manager, not resetting");
191       return;
192     }
193
194     GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "setting children's schedule to parent's");
195     GST_SCHEDULE_ADD_ELEMENT (sched, element);
196
197     // set the children's schedule
198     children = GST_BIN(element)->children;
199     while (children) {
200       child = GST_ELEMENT (children->data);
201       children = g_list_next(children);
202
203       gst_bin_set_element_sched (child, sched);
204     }
205
206   // otherwise, if it's just a regular old element
207   } else {
208     GST_SCHEDULE_ADD_ELEMENT (sched, element);
209   }
210 }
211
212
213 static void
214 gst_bin_unset_element_sched (GstElement *element)
215 {
216   GList *children;
217   GstElement *child;
218
219   g_return_if_fail (element != NULL);
220   g_return_if_fail (GST_IS_ELEMENT(element));
221
222   GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from it sched %p",
223             GST_ELEMENT_NAME(element),GST_ELEMENT_SCHED(element));
224
225   // if it's actually a Bin
226   if (GST_IS_BIN(element)) {
227
228     if (GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) {
229       GST_INFO_ELEMENT (GST_CAT_PARENTAGE, element, "child is already a manager, not unsetting sched");
230       return;
231     }
232
233     // FIXME this check should be irrelevant
234     if (GST_ELEMENT_SCHED (element))
235       GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element);
236
237     // for each child, remove them from their schedule
238     children = GST_BIN(element)->children;
239     while (children) {
240       child = GST_ELEMENT (children->data);
241       children = g_list_next(children);
242
243       gst_bin_unset_element_sched (child);
244     }
245
246   // otherwise, if it's just a regular old element
247   } else {
248     // FIXME this check should be irrelevant
249     if (GST_ELEMENT_SCHED (element))
250       GST_SCHEDULE_REMOVE_ELEMENT (GST_ELEMENT_SCHED(element), element);
251   }
252 }
253
254
255 /**
256  * gst_bin_add:
257  * @bin: #GstBin to add element to
258  * @element: #GstElement to add to bin
259  *
260  * Add the given element to the bin.  Set the elements parent, and thus
261  * add a reference.
262  */
263 void
264 gst_bin_add (GstBin *bin,
265              GstElement *element)
266 {
267   g_return_if_fail (bin != NULL);
268   g_return_if_fail (GST_IS_BIN (bin));
269   g_return_if_fail (element != NULL);
270   g_return_if_fail (GST_IS_ELEMENT (element));
271
272   GST_DEBUG (GST_CAT_PARENTAGE, "adding element \"%s\" to bin \"%s\"\n",
273              GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(bin));
274
275   // must be not be in PLAYING state in order to modify bin
276 //  g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING);
277
278   // the element must not already have a parent
279   g_return_if_fail (GST_ELEMENT_PARENT(element) == NULL);
280
281   // then check to see if the element's name is already taken in the bin
282   g_return_if_fail (gst_object_check_uniqueness (bin->children, GST_ELEMENT_NAME(element)) == TRUE);
283
284   // set the element's parent and add the element to the bin's list of children
285   gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
286   bin->children = g_list_append (bin->children, element);
287   bin->numchildren++;
288
289   ///// now we have to deal with manager stuff
290   // we can only do this if there's a scheduler:
291   // if we're not a manager, and aren't attached to anything, we have no sched (yet)
292   if (GST_ELEMENT_SCHED(bin) != NULL)
293     gst_bin_set_element_sched (element, GST_ELEMENT_SCHED(bin));
294
295   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "added child \"%s\"", GST_ELEMENT_NAME (element));
296
297   g_signal_emit (G_OBJECT (bin), gst_bin_signals[OBJECT_ADDED], 0, element);
298 }
299
300 /**
301  * gst_bin_remove:
302  * @bin: #GstBin to remove element from
303  * @element: #GstElement to remove
304  *
305  * Remove the element from its associated bin, unparenting as well.
306  */
307 void
308 gst_bin_remove (GstBin *bin,
309                 GstElement *element)
310 {
311   g_return_if_fail (bin != NULL);
312   g_return_if_fail (GST_IS_BIN (bin));
313   g_return_if_fail (element != NULL);
314   g_return_if_fail (GST_IS_ELEMENT (element));
315   g_return_if_fail (bin->children != NULL);
316
317   // must not be in PLAYING state in order to modify bin
318   g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING);
319
320   // the element must have its parent set to the current bin
321   g_return_if_fail (GST_ELEMENT_PARENT(element) == (GstObject *)bin);
322
323   // the element must be in the bin's list of children
324   if (g_list_find(bin->children, element) == NULL) {
325     // FIXME this should be a warning!!!
326     GST_ERROR_OBJECT(bin,element,"no such element in bin");
327     return;
328   }
329
330   // remove this element from the list of managed elements
331   gst_bin_unset_element_sched (element);
332
333   // now remove the element from the list of elements
334   bin->children = g_list_remove (bin->children, element);
335   bin->numchildren--;
336
337   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "removed child %s", GST_ELEMENT_NAME (element));
338
339   gst_object_unparent (GST_OBJECT (element));
340
341   /* if we're down to zero children, force state to NULL */
342   if (bin->numchildren == 0 && GST_ELEMENT_SCHED (bin) != NULL)
343     gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
344 }
345
346
347 static GstElementStateReturn
348 gst_bin_change_state (GstElement *element)
349 {
350   GstBin *bin;
351   GList *children;
352   GstElement *child;
353   GstElementStateReturn ret;
354
355 //  GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME  (element));
356
357   g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
358
359   bin = GST_BIN (element);
360
361 //  GST_DEBUG (GST_CAT_STATES,"currently %d(%s), %d(%s) pending\n",GST_STATE (element),
362 //          gst_element_statename (GST_STATE (element)), GST_STATE_PENDING (element),
363 //          gst_element_statename (GST_STATE_PENDING (element)));
364
365   GST_INFO_ELEMENT (GST_CAT_STATES, element, "changing childrens' state from %s to %s",
366                 gst_element_statename (GST_STATE (element)),
367                 gst_element_statename (GST_STATE_PENDING (element)));
368
369 //  g_return_val_if_fail(bin->numchildren != 0, GST_STATE_FAILURE);
370
371
372 //  g_print("-->\n");
373   children = bin->children;
374   while (children) {
375     child = GST_ELEMENT (children->data);
376 //    GST_DEBUG (GST_CAT_STATES,"setting state on '%s'\n",GST_ELEMENT_NAME  (child));
377     switch (gst_element_set_state (child, GST_STATE_PENDING (element))) {
378       case GST_STATE_FAILURE:
379         GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
380         GST_DEBUG (GST_CAT_STATES,"child '%s' failed to go to state %d(%s)\n", GST_ELEMENT_NAME (child),
381               GST_STATE_PENDING (element), gst_element_statename (GST_STATE_PENDING (element)));
382         return GST_STATE_FAILURE;
383         break;
384       case GST_STATE_ASYNC:
385         GST_DEBUG (GST_CAT_STATES,"child '%s' is changing state asynchronously\n", GST_ELEMENT_NAME (child));
386         break;
387     }
388 //    g_print("\n");
389     children = g_list_next (children);
390   }
391 //  g_print("<-- \"%s\"\n",GST_OBJECT_NAME(bin));
392
393   GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s",
394                 gst_element_statename (GST_STATE (element)),
395                 gst_element_statename (GST_STATE_PENDING (element)));
396   ret =  gst_bin_change_state_norecurse (bin);
397
398   return ret;
399 }
400
401
402 static GstElementStateReturn
403 gst_bin_change_state_norecurse (GstBin *bin)
404 {
405   if (GST_ELEMENT_CLASS (parent_class)->change_state) {
406     GST_DEBUG_ELEMENT (GST_CAT_STATES, bin, "setting bin's own state\n");
407     return GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT (bin));
408   } else
409     return GST_STATE_FAILURE;
410 }
411
412 static gboolean
413 gst_bin_change_state_type(GstBin *bin,
414                           GstElementState state,
415                           GType type)
416 {
417   GList *children;
418   GstElement *child;
419
420 //  g_print("gst_bin_change_state_type(\"%s\",%d,%d);\n",
421 //          GST_OBJECT_NAME(bin))),state,type);
422
423   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
424   g_return_val_if_fail (bin->numchildren != 0, FALSE);
425
426 //  g_print("-->\n");
427   children = bin->children;
428   while (children) {
429     child = GST_ELEMENT (children->data);
430     if (GST_IS_BIN (child)) {
431       if (!gst_bin_set_state_type (GST_BIN (child), state,type))
432         return FALSE;
433     } else if (G_TYPE_CHECK_INSTANCE_TYPE (child,type)) {
434       if (!gst_element_set_state (child,state))
435         return FALSE;
436     }
437 //    g_print("\n");
438     children = g_list_next (children);
439   }
440   if (type == GST_TYPE_BIN)
441     gst_element_set_state (GST_ELEMENT (bin),state);
442
443   return TRUE;
444 }
445
446 /**
447  * gst_bin_set_state_type:
448  * @bin: #GstBin to set the state
449  * @state: the new state to set the elements to
450  * @type: the type of elements to change
451  *
452  * Sets the state of only those objects of the given type.
453  *
454  * Returns: indication if the state change was successfull
455  */
456 gboolean
457 gst_bin_set_state_type (GstBin *bin,
458                         GstElementState state,
459                         GType type)
460 {
461   GstBinClass *oclass;
462
463   GST_DEBUG (GST_CAT_STATES,"gst_bin_set_state_type(\"%s\",%d,%d)\n",
464           GST_ELEMENT_NAME (bin), state,type);
465
466   g_return_val_if_fail (bin != NULL, FALSE);
467   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
468
469   oclass = GST_BIN_CLASS (G_OBJECT_GET_CLASS(bin));
470
471   if (oclass->change_state_type)
472     (oclass->change_state_type) (bin,state,type);
473   return TRUE;
474 }
475
476 static void
477 gst_bin_dispose (GObject *object)
478 {
479   GstBin *bin = GST_BIN (object);
480   GList *children, *orig;
481   GstElement *child;
482
483   GST_DEBUG (GST_CAT_REFCOUNTING,"dispose\n");
484
485   if (bin->children) {
486     orig = children = g_list_copy (bin->children);
487     while (children) {
488       child = GST_ELEMENT (children->data);
489       //gst_object_unref (GST_OBJECT (child));
490       //gst_object_unparent (GST_OBJECT (child));
491       gst_bin_remove (bin, child);
492       children = g_list_next (children);
493     }
494     g_list_free (orig);
495     g_list_free (bin->children);
496   }
497   bin->children = NULL;
498   bin->numchildren = 0;
499
500   g_cond_free (bin->eoscond);
501
502   G_OBJECT_CLASS (parent_class)->dispose (object);
503 }
504
505 /**
506  * gst_bin_get_by_name:
507  * @bin: #Gstbin to search
508  * @name: the element name to search for
509  *
510  * Get the element with the given name from this bin.
511  *
512  * Returns: the element with the given name
513  */
514 GstElement*
515 gst_bin_get_by_name (GstBin *bin,
516                      const gchar *name)
517 {
518   GList *children;
519   GstElement *child;
520
521   g_return_val_if_fail (bin != NULL, NULL);
522   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
523   g_return_val_if_fail (name != NULL, NULL);
524
525   GST_INFO_ELEMENT (GST_CAT_PARENTAGE, bin, "looking up child element %s", name);
526
527   children = bin->children;
528   while (children) {
529     child = GST_ELEMENT (children->data);
530     if (!strcmp (GST_OBJECT_NAME(child),name))
531       return child;
532     if (GST_IS_BIN (child)) {
533       GstElement *res = gst_bin_get_by_name (GST_BIN (child), name);
534       if (res)
535         return res;
536     }
537     children = g_list_next (children);
538   }
539
540   return NULL;
541 }
542
543 /**
544  * gst_bin_get_by_name_recurse_up:
545  * @bin: #Gstbin to search
546  * @name: the element name to search for
547  *
548  * Get the element with the given name from this bin. If the
549  * element is not found, a recursion is performed on the parent bin.
550  *
551  * Returns: the element with the given name
552  */
553 GstElement*
554 gst_bin_get_by_name_recurse_up (GstBin *bin,
555                                 const gchar *name)
556 {
557   GstElement *result = NULL;
558   GstObject *parent;
559
560   g_return_val_if_fail (bin != NULL, NULL);
561   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
562   g_return_val_if_fail (name != NULL, NULL);
563
564   result = gst_bin_get_by_name (bin, name);
565
566   if (result)
567     return result;
568
569   parent = gst_object_get_parent (GST_OBJECT (bin));
570
571   if (parent && GST_IS_BIN (parent)) {
572     result = gst_bin_get_by_name_recurse_up (GST_BIN (parent), name);
573   }
574
575   return result;
576 }
577
578 /**
579  * gst_bin_get_list:
580  * @bin: #Gstbin to get the list from
581  *
582  * Get the list of elements in this bin.
583  *
584  * Returns: a GList of elements
585  */
586 GList*
587 gst_bin_get_list (GstBin *bin)
588 {
589   g_return_val_if_fail (bin != NULL, NULL);
590   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
591
592   return bin->children;
593 }
594
595 #ifndef GST_DISABLE_LOADSAVE
596 static xmlNodePtr
597 gst_bin_save_thyself (GstObject *object,
598                       xmlNodePtr parent)
599 {
600   GstBin *bin = GST_BIN (object);
601   xmlNodePtr childlist, elementnode;
602   GList *children;
603   GstElement *child;
604
605   if (GST_OBJECT_CLASS (parent_class)->save_thyself)
606     GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
607
608   childlist = xmlNewChild (parent, NULL, "children", NULL);
609
610   GST_INFO_ELEMENT (GST_CAT_XML, bin, "saving %d children", bin->numchildren);
611
612   children = bin->children;
613   while (children) {
614     child = GST_ELEMENT (children->data);
615     elementnode = xmlNewChild (childlist, NULL, "element", NULL);
616     gst_object_save_thyself (GST_OBJECT (child), elementnode);
617     children = g_list_next (children);
618   }
619   return childlist;
620 }
621
622 static void
623 gst_bin_restore_thyself (GstObject *object,
624                          xmlNodePtr self)
625 {
626   GstBin *bin = GST_BIN (object);
627   xmlNodePtr field = self->xmlChildrenNode;
628   xmlNodePtr childlist;
629
630   while (field) {
631     if (!strcmp (field->name, "children")) {
632       GST_INFO_ELEMENT (GST_CAT_XML, GST_ELEMENT (object), "loading children");
633       childlist = field->xmlChildrenNode;
634       while (childlist) {
635         if (!strcmp (childlist->name, "element")) {
636           GstElement *element = gst_element_restore_thyself (childlist, GST_OBJECT (bin));
637
638           gst_bin_add (bin, element);
639         }
640         childlist = childlist->next;
641       }
642     }
643
644     field = field->next;
645   }
646 }
647 #endif /* GST_DISABLE_LOADSAVE */
648
649
650 /**
651  * gst_bin_iterate:
652  * @bin: #Gstbin to iterate
653  *
654  * Iterates over the elements in this bin.
655  *
656  * Returns: TRUE if the bin did something usefull. This value
657  *          can be used to determine it the bin is in EOS.
658  */
659 gboolean
660 gst_bin_iterate (GstBin *bin)
661 {
662   GstBinClass *oclass;
663   gboolean running = TRUE;
664
665   GST_DEBUG_ENTER("(\"%s\")",GST_ELEMENT_NAME (bin));
666
667   oclass = GST_BIN_CLASS (G_OBJECT_GET_CLASS(bin));
668
669   if (oclass->iterate)
670     running = (oclass->iterate) (bin);
671
672   GST_DEBUG_LEAVE("(\"%s\")",GST_ELEMENT_NAME (bin));
673
674 //  if (!running)
675  //   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
676
677   return running;
678 }
679
680 /* out internal element fired EOS, we decrement the number of pending EOS childs */
681 G_GNUC_UNUSED static void
682 gst_bin_received_eos (GstElement *element, GstBin *bin)
683 {
684   GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d", GST_ELEMENT_NAME (element),
685                   bin->num_eos_providers);
686
687   GST_LOCK (bin);
688   if (bin->num_eos_providers) {
689     bin->num_eos_providers--;
690     g_cond_signal (bin->eoscond);
691   }
692   GST_UNLOCK (bin);
693 }
694
695 typedef struct {
696   gulong offset;
697   gulong size;
698 } region_struct;
699
700
701 static gboolean
702 gst_bin_iterate_func (GstBin *bin)
703 {
704   // only iterate if this is the manager bin
705   if (GST_ELEMENT_SCHED(bin)->parent == GST_ELEMENT (bin)) {
706     return GST_SCHEDULE_ITERATE(GST_ELEMENT_SCHED(bin));
707   } else {
708     GST_DEBUG (GST_CAT_SCHEDULING, "this bin can't be iterated on!\n");
709   }
710
711   return FALSE;
712 }
713