changing default scheduler to wingo's spiffy standard one, since it doesn't look...
[platform/upstream/gstreamer.git] / gst / gstscheduler.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *
5  * gstscheduler.c: Default scheduling code for most cases
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 CLASS(obj)      GST_SCHEDULER_CLASS (G_OBJECT_GET_CLASS (obj))
24
25 #include "gst_private.h"
26
27 #include "gstsystemclock.h"
28 #include "gstscheduler.h"
29 #include "gstregistry.h"
30
31 static void     gst_scheduler_class_init        (GstSchedulerClass *klass);
32 static void     gst_scheduler_init              (GstScheduler *sched);
33
34 static GstObjectClass *parent_class = NULL;
35
36 static gchar *_default_name = NULL;
37
38 GType
39 gst_scheduler_get_type (void)
40 {
41   static GType _gst_scheduler_type = 0;
42
43   if (!_gst_scheduler_type) {
44     static const GTypeInfo scheduler_info = {
45       sizeof (GstSchedulerClass),
46       NULL,
47       NULL,
48       (GClassInitFunc) gst_scheduler_class_init,
49       NULL,
50       NULL,
51       sizeof (GstScheduler),
52       0,
53       (GInstanceInitFunc) gst_scheduler_init,
54       NULL
55     };
56
57     _gst_scheduler_type = g_type_register_static (GST_TYPE_OBJECT, "GstScheduler", 
58                     &scheduler_info, G_TYPE_FLAG_ABSTRACT);
59   }
60   return _gst_scheduler_type;
61 }
62
63 static void
64 gst_scheduler_class_init (GstSchedulerClass *klass)
65 {
66   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
67 }
68
69 static void
70 gst_scheduler_init (GstScheduler *sched)
71 {
72   sched->clock_providers = NULL;
73   sched->clock_receivers = NULL;
74   sched->schedulers = NULL;
75   sched->state = GST_SCHEDULER_STATE_NONE;
76   sched->parent = NULL;
77   sched->parent_sched = NULL;
78   sched->clock = NULL;
79 }
80
81 /**
82  * gst_scheduler_setup:
83  * @sched: the scheduler
84  *
85  * Prepare the scheduler.
86  */
87 void
88 gst_scheduler_setup (GstScheduler *sched)
89 {
90   g_return_if_fail (GST_IS_SCHEDULER (sched));
91
92   if (CLASS (sched)->setup)
93     CLASS (sched)->setup (sched);
94 }
95
96 /**
97  * gst_scheduler_reset:
98  * @sched: the scheduler
99  *
100  * Reset the scheduler
101  */
102 void
103 gst_scheduler_reset (GstScheduler *sched)
104 {
105   g_return_if_fail (GST_IS_SCHEDULER (sched));
106
107   if (CLASS (sched)->reset)
108     CLASS (sched)->reset (sched);
109 }
110
111 /**
112  * gst_scheduler_pad_connect:
113  * @sched: the scheduler
114  * @srcpad: the srcpad to connect
115  * @sinkpad: the sinkpad to connect to
116  *
117  * Connect the srcpad to the given sinkpad.
118  */
119 void
120 gst_scheduler_pad_connect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad)
121 {
122   g_return_if_fail (GST_IS_SCHEDULER (sched));
123   g_return_if_fail (GST_IS_PAD (srcpad));
124   g_return_if_fail (GST_IS_PAD (sinkpad));
125
126   if (CLASS (sched)->pad_connect)
127     CLASS (sched)->pad_connect (sched, srcpad, sinkpad);
128 }
129
130 /**
131  * gst_scheduler_pad_disconnect:
132  * @sched: the scheduler
133  * @srcpad: the srcpad to disconnect
134  * @sinkpad: the sinkpad to disconnect from
135  *
136  * Disconnect the srcpad to the given sinkpad.
137  */
138 void
139 gst_scheduler_pad_disconnect (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad)
140 {
141   g_return_if_fail (GST_IS_SCHEDULER (sched));
142   g_return_if_fail (GST_IS_PAD (srcpad));
143   g_return_if_fail (GST_IS_PAD (sinkpad));
144
145   if (CLASS (sched)->pad_disconnect)
146     CLASS (sched)->pad_disconnect (sched, srcpad, sinkpad);
147 }
148
149 /**
150  * gst_scheduler_pad_select:
151  * @sched: the scheduler
152  * @padlist: the padlist to select on
153  *
154  * register the given padlist for a select operation. 
155  *
156  * Returns: the pad which received a buffer.
157  */
158 GstPad *
159 gst_scheduler_pad_select (GstScheduler *sched, GList *padlist)
160 {
161   g_return_val_if_fail (GST_IS_SCHEDULER (sched), NULL);
162   g_return_val_if_fail (padlist != NULL, NULL);
163
164   if (CLASS (sched)->pad_select)
165     CLASS (sched)->pad_select (sched, padlist);
166
167   return NULL;
168 }
169
170 /**
171  * gst_scheduler_add_element:
172  * @sched: the scheduler
173  * @element: the element to add to the scheduler
174  *
175  * Add an element to the scheduler.
176  */
177 void
178 gst_scheduler_add_element (GstScheduler *sched, GstElement *element)
179 {
180   g_return_if_fail (GST_IS_SCHEDULER (sched));
181   g_return_if_fail (GST_IS_ELEMENT (element));
182
183   if (element->getclockfunc) {
184     sched->clock_providers = g_list_prepend (sched->clock_providers, element);
185     GST_DEBUG (GST_CAT_CLOCK, "added clock provider %s", GST_ELEMENT_NAME (element));
186   }
187   if (element->setclockfunc) {
188     sched->clock_receivers = g_list_prepend (sched->clock_receivers, element);
189     GST_DEBUG (GST_CAT_CLOCK, "added clock receiver %s", GST_ELEMENT_NAME (element));
190   }
191
192   if (CLASS (sched)->add_element)
193     CLASS (sched)->add_element (sched, element);
194 }
195
196 /**
197  * gst_scheduler_remove_element:
198  * @sched: the scheduler
199  * @element: the element to remove
200  *
201  * Remove an element from the scheduler.
202  */
203 void
204 gst_scheduler_remove_element (GstScheduler *sched, GstElement *element)
205 {
206   GList *pads;
207   
208   g_return_if_fail (GST_IS_SCHEDULER (sched));
209   g_return_if_fail (GST_IS_ELEMENT (element));
210
211   sched->clock_providers = g_list_remove (sched->clock_providers, element);
212   sched->clock_receivers = g_list_remove (sched->clock_receivers, element);
213
214   if (CLASS (sched)->remove_element)
215     CLASS (sched)->remove_element (sched, element);
216   
217   for (pads = element->pads; pads; pads = pads->next) {
218     GstPad *pad = GST_PAD (pads->data);
219     
220     if (GST_IS_REAL_PAD (pad)) {
221       gst_pad_unset_scheduler (GST_PAD (pads->data));
222     }
223   }
224 }
225
226 /**
227  * gst_scheduler_state_transition:
228  * @sched: the scheduler
229  * @element: the element with the state transition
230  * @transition: the state transition
231  *
232  * Tell the scheduler that an element changed its state.
233  *
234  * Returns: a GstElementStateReturn indicating success or failure
235  * of the state transition.
236  */
237 GstElementStateReturn
238 gst_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition)
239 {
240   g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_STATE_FAILURE);
241   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
242
243   if (element == sched->parent && sched->parent_sched == NULL) {
244
245     switch (transition) {
246       case GST_STATE_READY_TO_PAUSED:
247       {
248         GstClock *clock = gst_scheduler_get_clock (sched);
249
250         if (clock)
251           gst_clock_reset (clock);
252
253         GST_DEBUG (GST_CAT_CLOCK, "scheduler READY to PAUSED clock is %p (%s)", clock, 
254                         (clock ? GST_OBJECT_NAME (clock) : "nil"));
255
256         sched->current_clock = clock;
257         break;
258       }
259       case GST_STATE_PAUSED_TO_PLAYING:
260       {
261         GstClock *clock = gst_scheduler_get_clock (sched);
262
263         GST_DEBUG (GST_CAT_CLOCK, "scheduler PAUSED to PLAYING clock is %p (%s)", clock, 
264                         (clock ? GST_OBJECT_NAME (clock) : "nil"));
265
266         sched->current_clock = clock;
267
268         gst_scheduler_set_clock (sched, sched->current_clock);
269         if (sched->current_clock)
270           gst_clock_set_active (sched->current_clock, TRUE);
271         break;
272       }
273       case GST_STATE_PLAYING_TO_PAUSED:
274         if (sched->current_clock)
275           gst_clock_set_active (sched->current_clock, FALSE);
276         break;
277     }
278   }
279
280   if (CLASS (sched)->state_transition)
281     return CLASS (sched)->state_transition (sched, element, transition);
282
283   return GST_STATE_SUCCESS;
284 }
285
286 /**
287  * gst_scheduler_add_scheduler:
288  * @sched: a  #GstScheduler to add to
289  * @sched2: the #GstScheduler to add
290  *
291  * Notifies the scheduler that it has to monitor this scheduler.
292  */
293 void
294 gst_scheduler_add_scheduler (GstScheduler *sched, GstScheduler *sched2)
295 {
296   g_return_if_fail (GST_IS_SCHEDULER (sched));
297   g_return_if_fail (GST_IS_SCHEDULER (sched2));
298
299   sched->schedulers = g_list_prepend (sched->schedulers, sched2);
300   sched2->parent_sched = sched;
301
302   if (CLASS (sched)->add_scheduler)
303     CLASS (sched)->add_scheduler (sched, sched2);
304 }
305
306 /**
307  * gst_scheduler_remove_scheduler:
308  * @sched: the scheduler
309  * @sched2: the scheduler to remove
310  *
311  a Notifies the scheduler that it can stop monitoring this scheduler.
312  */
313 void
314 gst_scheduler_remove_scheduler (GstScheduler *sched, GstScheduler *sched2)
315 {
316   g_return_if_fail (GST_IS_SCHEDULER (sched));
317   g_return_if_fail (GST_IS_SCHEDULER (sched2));
318
319   sched->schedulers = g_list_remove (sched->schedulers, sched2);
320   sched2->parent_sched = NULL;
321
322   if (CLASS (sched)->remove_scheduler)
323     CLASS (sched)->remove_scheduler (sched, sched2);
324 }
325
326 /**
327  * gst_scheduler_lock_element:
328  * @sched: the scheduler
329  * @element: the element to lock
330  *
331  * Acquire a lock on the given element in the given scheduler.
332  */
333 void
334 gst_scheduler_lock_element (GstScheduler *sched, GstElement *element)
335 {
336   g_return_if_fail (GST_IS_SCHEDULER (sched));
337   g_return_if_fail (GST_IS_ELEMENT (element));
338
339   if (CLASS (sched)->lock_element)
340     CLASS (sched)->lock_element (sched, element);
341 }
342
343 /**
344  * gst_scheduler_unlock_element:
345  * @sched: the scheduler
346  * @element: the element to unlock
347  *
348  * Release the lock on the given element in the given scheduler.
349  */
350 void
351 gst_scheduler_unlock_element (GstScheduler *sched, GstElement *element)
352 {
353   g_return_if_fail (GST_IS_SCHEDULER (sched));
354   g_return_if_fail (GST_IS_ELEMENT (element));
355
356   if (CLASS (sched)->unlock_element)
357     CLASS (sched)->unlock_element (sched, element);
358 }
359
360 /**
361  * gst_scheduler_error:
362  * @sched: the scheduler
363  * @element: the element with the error
364  *
365  * Tell the scheduler an element was in error
366  */
367 void
368 gst_scheduler_error (GstScheduler *sched, GstElement *element)
369 {
370   g_return_if_fail (GST_IS_SCHEDULER (sched));
371   g_return_if_fail (GST_IS_ELEMENT (element));
372
373   if (CLASS (sched)->error)
374     CLASS (sched)->error (sched, element);
375 }
376
377 /**
378  * gst_scheduler_yield:
379  * @sched: the scheduler
380  * @element: the element requesting a yield
381  *
382  * Tell the scheduler to schedule another element.
383  */
384 void
385 gst_scheduler_yield (GstScheduler *sched, GstElement *element)
386 {
387   g_return_if_fail (GST_IS_SCHEDULER (sched));
388   g_return_if_fail (GST_IS_ELEMENT (element));
389
390   if (CLASS (sched)->yield)
391     CLASS (sched)->yield (sched, element);
392 }
393
394 /**
395  * gst_scheduler_interrupt:
396  * @sched: the scheduler
397  * @element: the element requesting an interrupt
398  *
399  * Tell the scheduler to interrupt execution of this element.
400  *
401  * Returns: TRUE if the element should return NULL from the chain/get
402  * function.
403  */
404 gboolean
405 gst_scheduler_interrupt (GstScheduler *sched, GstElement *element)
406 {
407   g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
408   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
409
410   if (CLASS (sched)->interrupt)
411     return CLASS (sched)->interrupt (sched, element);
412
413   return FALSE;
414 }
415
416 /**
417  * gst_scheduler_get_clock:
418  * @sched: the scheduler
419  *
420  * Get the current clock used by the scheduler
421  *
422  * Returns: a GstClock
423  */
424 GstClock*
425 gst_scheduler_get_clock (GstScheduler *sched)
426 {
427   GstClock *clock = NULL;
428   
429   /* if we have a fixed clock, use that one */
430   if (GST_FLAG_IS_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK)) {
431     clock = sched->clock;  
432
433     GST_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)", clock, 
434                         (clock ? GST_OBJECT_NAME (clock) : "nil"));
435   }
436   else {
437     GList *schedulers = sched->schedulers;
438     GList *providers = sched->clock_providers;
439
440     /* try to get a clock from one of the schedulers we manage first */
441     while (schedulers) {
442       GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
443       
444       clock = gst_scheduler_get_clock (scheduler);
445       if (clock)
446         break;
447
448       schedulers = g_list_next (schedulers);
449     }
450     /* still no clock, try to find one in the providers */
451     while (!clock && providers) {
452       clock = gst_element_get_clock (GST_ELEMENT (providers->data));
453
454       providers = g_list_next (providers);
455     }
456     /* still no clock, use a system clock */
457     if (!clock && sched->parent_sched == NULL) {
458       clock = gst_system_clock_obtain ();
459     }
460   }
461   GST_DEBUG (GST_CAT_CLOCK, "scheduler selected clock %p (%s)", clock, 
462                 (clock ? GST_OBJECT_NAME (clock) : "nil"));
463
464   return clock;
465 }
466
467 /**
468  * gst_scheduler_use_clock:
469  * @sched: the scheduler
470  * @clock: the clock to use
471  *
472  * Force the scheduler to use the given clock. The scheduler will
473  * always use the given clock even if new clock providers are added
474  * to this scheduler.
475  */
476 void
477 gst_scheduler_use_clock (GstScheduler *sched, GstClock *clock)
478 {
479   g_return_if_fail (sched != NULL);
480   g_return_if_fail (GST_IS_SCHEDULER (sched));
481
482   GST_FLAG_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
483   sched->clock = clock;
484
485   GST_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)", clock, 
486                 (clock ? GST_OBJECT_NAME (clock) : "nil"));
487 }
488
489 /**
490  * gst_scheduler_set_clock:
491  * @sched: the scheduler
492  * @clock: the clock to set
493  *
494  * Set the clock for the scheduler. The clock will be distributed 
495  * to all the elements managed by the scheduler. 
496  */
497 void
498 gst_scheduler_set_clock (GstScheduler *sched, GstClock *clock)
499 {
500   GList *receivers;
501   GList *schedulers;
502
503   g_return_if_fail (sched != NULL);
504   g_return_if_fail (GST_IS_SCHEDULER (sched));
505
506   receivers = sched->clock_receivers;
507   schedulers = sched->schedulers;
508
509   sched->current_clock = clock;
510
511   GST_DEBUG (GST_CAT_CLOCK, "scheduler setting clock %p (%s)", clock, 
512                 (clock ? GST_OBJECT_NAME (clock) : "nil"));
513
514   while (receivers) {
515     GstElement *element = GST_ELEMENT (receivers->data);
516
517     gst_element_set_clock (element, clock);
518     receivers = g_list_next (receivers);
519   }
520   while (schedulers) {
521     GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
522
523     gst_scheduler_set_clock (scheduler, clock);
524     schedulers = g_list_next (schedulers);
525   }
526 }
527
528 /**
529  * gst_scheduler_auto_clock:
530  * @sched: the scheduler
531  *
532  * Let the scheduler select a clock automatically.
533  */
534 void
535 gst_scheduler_auto_clock (GstScheduler *sched)
536 {
537   g_return_if_fail (sched != NULL);
538   g_return_if_fail (GST_IS_SCHEDULER (sched));
539
540   GST_FLAG_UNSET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
541   sched->clock = NULL;
542
543   GST_DEBUG (GST_CAT_CLOCK, "scheduler using automatic clock");
544 }
545
546 /**
547  * gst_scheduler_clock_wait:
548  * @sched: the scheduler
549  * @element: the element that wants to wait
550  * @clock: the clock to use
551  * @time: the time to wait for
552  * @jitter: the time difference between requested time and actual time
553  *
554  * Wait till the clock reaches a specific time
555  *
556  * Returns: the status of the operation
557  */
558 GstClockReturn
559 gst_scheduler_clock_wait (GstScheduler *sched, GstElement *element, GstClock *clock, GstClockTime time,
560                 GstClockTimeDiff *jitter)
561 {
562   g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
563
564   if (CLASS (sched)->clock_wait)
565     return CLASS (sched)->clock_wait (sched, element, clock, time, jitter);
566
567   return GST_CLOCK_TIMEOUT;
568 }
569
570 /**
571  * gst_scheduler_iterate:
572  * @sched: the scheduler
573  *
574  * Perform one iteration on the scheduler.
575  *
576  * Returns: a boolean indicating something usefull has happened.
577  */
578 gboolean
579 gst_scheduler_iterate (GstScheduler *sched)
580 {
581   g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
582
583   if (CLASS (sched)->iterate)
584     return CLASS (sched)->iterate (sched);
585
586   return FALSE;
587 }
588
589
590 /**
591  * gst_scheduler_show:
592  * @sched: the scheduler
593  *
594  * Dump the state of the scheduler
595  */
596 void
597 gst_scheduler_show (GstScheduler *sched)
598 {
599   g_return_if_fail (GST_IS_SCHEDULER (sched));
600
601   if (CLASS (sched)->show)
602     CLASS (sched)->show (sched);
603 }
604
605 /*
606  * Factory stuff starts here
607  *
608  */
609 static void             gst_scheduler_factory_class_init                (GstSchedulerFactoryClass *klass);
610 static void             gst_scheduler_factory_init              (GstSchedulerFactory *factory);
611
612 static GstPluginFeatureClass *factory_parent_class = NULL;
613 /* static guint gst_scheduler_factory_signals[LAST_SIGNAL] = { 0 }; */
614
615 GType 
616 gst_scheduler_factory_get_type (void) 
617 {
618   static GType schedulerfactory_type = 0;
619
620   if (!schedulerfactory_type) {
621     static const GTypeInfo schedulerfactory_info = {
622       sizeof (GstSchedulerFactoryClass),
623       NULL,
624       NULL,
625       (GClassInitFunc) gst_scheduler_factory_class_init,
626       NULL,
627       NULL,
628       sizeof(GstSchedulerFactory),
629       0,
630       (GInstanceInitFunc) gst_scheduler_factory_init,
631       NULL
632     };
633     schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, 
634                                                   "GstSchedulerFactory", &schedulerfactory_info, 0);
635   }
636   return schedulerfactory_type;
637 }
638
639 static void
640 gst_scheduler_factory_class_init (GstSchedulerFactoryClass *klass)
641 {
642   GObjectClass *gobject_class;
643   GstObjectClass *gstobject_class;
644   GstPluginFeatureClass *gstpluginfeature_class;
645
646   gobject_class = (GObjectClass*)klass;
647   gstobject_class = (GstObjectClass*)klass;
648   gstpluginfeature_class = (GstPluginFeatureClass*) klass;
649
650   factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
651
652   if (!_default_name)
653     _default_name = g_strdup ("standard");
654 }
655
656 static void
657 gst_scheduler_factory_init (GstSchedulerFactory *factory)
658 {
659 }
660         
661
662 /**
663  * gst_scheduler_factory_new:
664  * @name: name of schedulerfactory to create
665  * @longdesc: long description of schedulerfactory to create
666  * @type: the gtk type of the GstScheduler element of this factory
667  *
668  * Create a new schedulerfactory with the given parameters
669  *
670  * Returns: a new #GstSchedulerFactory.
671  */
672 GstSchedulerFactory*
673 gst_scheduler_factory_new (const gchar *name, const gchar *longdesc, GType type)
674 {
675   GstSchedulerFactory *factory;
676
677   g_return_val_if_fail(name != NULL, NULL);
678   factory = gst_scheduler_factory_find (name);
679   if (!factory) {
680     factory = GST_SCHEDULER_FACTORY (g_object_new (GST_TYPE_SCHEDULER_FACTORY, NULL));
681   }
682
683   GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
684   if (factory->longdesc)
685     g_free (factory->longdesc);
686   factory->longdesc = g_strdup (longdesc);
687   factory->type = type;
688
689   return factory;
690 }
691
692 /**
693  * gst_scheduler_factory_destroy:
694  * @factory: factory to destroy
695  *
696  * Removes the scheduler from the global list.
697  */
698 void
699 gst_scheduler_factory_destroy (GstSchedulerFactory *factory)
700 {
701   g_return_if_fail (factory != NULL);
702
703   /* we don't free the struct bacause someone might  have a handle to it.. */
704 }
705
706 /**
707  * gst_scheduler_factory_find:
708  * @name: name of schedulerfactory to find
709  *
710  * Search for an schedulerfactory of the given name.
711  *
712  * Returns: #GstSchedulerFactory if found, NULL otherwise
713  */
714 GstSchedulerFactory*
715 gst_scheduler_factory_find (const gchar *name)
716 {
717   GstPluginFeature *feature;
718
719   g_return_val_if_fail(name != NULL, NULL);
720
721   GST_DEBUG (0,"gstscheduler: find \"%s\"", name);
722
723   feature = gst_registry_pool_find_feature (name, GST_TYPE_SCHEDULER_FACTORY);
724   if (feature)
725     return GST_SCHEDULER_FACTORY (feature);
726
727   return NULL;
728 }
729
730 /**
731  * gst_scheduler_factory_create:
732  * @factory: the factory used to create the instance
733  * @parent: the parent element of this scheduler
734  *
735  * Create a new #GstScheduler instance from the 
736  * given schedulerfactory with the given parent. @parent will
737  * have its scheduler set to the returned #GstScheduler instance.
738  *
739  * Returns: A new #GstScheduler instance with a reference count of %1.
740  */
741 GstScheduler*
742 gst_scheduler_factory_create (GstSchedulerFactory *factory, GstElement *parent)
743 {
744   GstScheduler *new = NULL;
745
746   g_return_val_if_fail (factory != NULL, NULL);
747   g_return_val_if_fail (parent != NULL, NULL);
748
749   if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
750     g_return_val_if_fail (factory->type != 0, NULL);
751
752     new = GST_SCHEDULER (g_object_new (factory->type, NULL));
753     new->parent = parent;
754
755     GST_ELEMENT_SCHED (parent) = new;
756
757     /* let's refcount the scheduler */
758     gst_object_ref (GST_OBJECT (new));
759     gst_object_sink (GST_OBJECT (new));
760   }
761
762   return new;
763 }
764
765 /**
766  * gst_scheduler_factory_make:
767  * @name: the name of the factory used to create the instance
768  * @parent: the parent element of this scheduler
769  *
770  * Create a new #GstScheduler instance from the 
771  * schedulerfactory with the given name and parent. @parent will
772  * have its scheduler set to the returned #GstScheduler instance.
773  * If %NULL is passed as @name, the default scheduler name will
774  * be used.
775  *
776  * Returns: A new #GstScheduler instance with a reference count of %1.
777  */
778 GstScheduler*
779 gst_scheduler_factory_make (const gchar *name, GstElement *parent)
780 {
781   GstSchedulerFactory *factory;
782
783   if (name)
784     factory = gst_scheduler_factory_find (name);
785   else
786     factory = gst_scheduler_factory_find (gst_scheduler_factory_get_default_name ());
787
788   if (factory == NULL)
789     return NULL;
790
791   return gst_scheduler_factory_create (factory, parent);
792 }
793
794 /**
795  * gst_scheduler_factory_set_default_name:
796  * @name: the name of the factory used as a default
797  *
798  * Set the default schedulerfactory name.
799  */
800 void
801 gst_scheduler_factory_set_default_name (const gchar* name)
802 {
803   if (_default_name)
804     g_free (_default_name);
805
806   _default_name = g_strdup (name);
807 }
808
809 /**
810  * gst_scheduler_factory_get_default_name:
811  *
812  * Get the default schedulerfactory name.
813  *
814  * Returns: the name of the default scheduler.
815  */
816 const gchar*
817 gst_scheduler_factory_get_default_name (void)
818 {
819   return _default_name;
820 }