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 */
23 #include "gst_private.h"
25 #include "gstsystemclock.h"
26 #include "gstscheduler.h"
27 #include "gstinfo.h"
28 #include "gstregistrypool.h"
30 static void gst_scheduler_class_init (GstSchedulerClass * klass);
31 static void gst_scheduler_init (GstScheduler * sched);
32 static void gst_scheduler_dispose (GObject * object);
34 static GstObjectClass *parent_class = NULL;
36 static gchar *_default_name = NULL;
38 GType
39 gst_scheduler_get_type (void)
40 {
41 static GType _gst_scheduler_type = 0;
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 };
57 _gst_scheduler_type =
58 g_type_register_static (GST_TYPE_OBJECT, "GstScheduler",
59 &scheduler_info, G_TYPE_FLAG_ABSTRACT);
60 }
61 return _gst_scheduler_type;
62 }
64 static void
65 gst_scheduler_class_init (GstSchedulerClass * klass)
66 {
67 GObjectClass *gobject_class;
69 gobject_class = (GObjectClass *) klass;
71 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
73 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_scheduler_dispose);
74 }
76 static void
77 gst_scheduler_init (GstScheduler * sched)
78 {
79 sched->clock_providers = NULL;
80 sched->clock_receivers = NULL;
81 sched->schedulers = NULL;
82 sched->state = GST_SCHEDULER_STATE_NONE;
83 sched->parent = NULL;
84 sched->parent_sched = NULL;
85 sched->clock = NULL;
86 }
88 static void
89 gst_scheduler_dispose (GObject * object)
90 {
91 GstScheduler *sched = GST_SCHEDULER (object);
93 /* thse lists should all be NULL */
94 GST_DEBUG ("scheduler %p dispose %p %p %p",
95 object,
96 sched->clock_providers, sched->clock_receivers, sched->schedulers);
98 gst_object_replace ((GstObject **) & sched->current_clock, NULL);
99 gst_object_replace ((GstObject **) & sched->clock, NULL);
101 G_OBJECT_CLASS (parent_class)->dispose (object);
102 }
104 /**
105 * gst_scheduler_setup:
106 * @sched: the scheduler
107 *
108 * Prepare the scheduler.
109 */
110 void
111 gst_scheduler_setup (GstScheduler * sched)
112 {
113 GstSchedulerClass *sclass;
115 g_return_if_fail (GST_IS_SCHEDULER (sched));
117 sclass = GST_SCHEDULER_GET_CLASS (sched);
119 if (sclass->setup)
120 sclass->setup (sched);
121 }
123 /**
124 * gst_scheduler_reset:
125 * @sched: a #GstScheduler to reset.
126 *
127 * Reset the schedulers.
128 */
129 void
130 gst_scheduler_reset (GstScheduler * sched)
131 {
132 GstSchedulerClass *sclass;
134 g_return_if_fail (GST_IS_SCHEDULER (sched));
136 sclass = GST_SCHEDULER_GET_CLASS (sched);
138 if (sclass->reset)
139 sclass->reset (sched);
140 }
142 /**
143 * gst_scheduler_pad_link:
144 * @sched: the scheduler
145 * @srcpad: the srcpad to link
146 * @sinkpad: the sinkpad to link to
147 *
148 * Links the srcpad to the given sinkpad.
149 */
150 void
151 gst_scheduler_pad_link (GstScheduler * sched, GstPad * srcpad, GstPad * sinkpad)
152 {
153 GstSchedulerClass *sclass;
155 g_return_if_fail (GST_IS_SCHEDULER (sched));
156 g_return_if_fail (GST_IS_PAD (srcpad));
157 g_return_if_fail (GST_IS_PAD (sinkpad));
159 sclass = GST_SCHEDULER_GET_CLASS (sched);
161 if (sclass->pad_link)
162 sclass->pad_link (sched, srcpad, sinkpad);
163 }
165 /**
166 * gst_scheduler_pad_unlink:
167 * @sched: the scheduler
168 * @srcpad: the srcpad to unlink
169 * @sinkpad: the sinkpad to unlink from
170 *
171 * Unlinks the srcpad from the given sinkpad.
172 */
173 void
174 gst_scheduler_pad_unlink (GstScheduler * sched, GstPad * srcpad,
175 GstPad * sinkpad)
176 {
177 GstSchedulerClass *sclass;
179 g_return_if_fail (GST_IS_SCHEDULER (sched));
180 g_return_if_fail (GST_IS_PAD (srcpad));
181 g_return_if_fail (GST_IS_PAD (sinkpad));
183 sclass = GST_SCHEDULER_GET_CLASS (sched);
185 if (sclass->pad_unlink)
186 sclass->pad_unlink (sched, srcpad, sinkpad);
187 }
189 /**
190 * gst_scheduler_pad_select:
191 * @sched: the scheduler
192 * @padlist: the padlist to select on
193 *
194 * register the given padlist for a select operation.
195 *
196 * Returns: the pad which received a buffer.
197 */
198 GstPad *
199 gst_scheduler_pad_select (GstScheduler * sched, GList * padlist)
200 {
201 GstSchedulerClass *sclass;
203 g_return_val_if_fail (GST_IS_SCHEDULER (sched), NULL);
204 g_return_val_if_fail (padlist != NULL, NULL);
206 sclass = GST_SCHEDULER_GET_CLASS (sched);
208 if (sclass->pad_select)
209 sclass->pad_select (sched, padlist);
211 return NULL;
212 }
214 /**
215 * gst_scheduler_add_element:
216 * @sched: the scheduler
217 * @element: the element to add to the scheduler
218 *
219 * Add an element to the scheduler.
220 */
221 void
222 gst_scheduler_add_element (GstScheduler * sched, GstElement * element)
223 {
224 GstSchedulerClass *sclass;
226 g_return_if_fail (GST_IS_SCHEDULER (sched));
227 g_return_if_fail (GST_IS_ELEMENT (element));
229 /* if it's already in this scheduler, don't bother doing anything */
230 if (GST_ELEMENT_SCHED (element) == sched) {
231 GST_CAT_DEBUG (GST_CAT_SCHEDULING, "element %s already in scheduler %p",
232 GST_ELEMENT_NAME (element), sched);
233 return;
234 }
236 /* if it's not inside this scheduler, it has to be NULL */
237 g_assert (GST_ELEMENT_SCHED (element) == NULL);
239 if (gst_element_provides_clock (element)) {
240 sched->clock_providers = g_list_prepend (sched->clock_providers, element);
241 GST_CAT_DEBUG (GST_CAT_CLOCK, "added clock provider %s",
242 GST_ELEMENT_NAME (element));
243 }
244 if (gst_element_requires_clock (element)) {
245 sched->clock_receivers = g_list_prepend (sched->clock_receivers, element);
246 GST_CAT_DEBUG (GST_CAT_CLOCK, "added clock receiver %s",
247 GST_ELEMENT_NAME (element));
248 }
250 gst_element_set_scheduler (element, sched);
252 sclass = GST_SCHEDULER_GET_CLASS (sched);
254 if (sclass->add_element)
255 sclass->add_element (sched, element);
256 }
258 /**
259 * gst_scheduler_remove_element:
260 * @sched: the scheduler
261 * @element: the element to remove
262 *
263 * Remove an element from the scheduler.
264 */
265 void
266 gst_scheduler_remove_element (GstScheduler * sched, GstElement * element)
267 {
268 GstSchedulerClass *sclass;
270 g_return_if_fail (GST_IS_SCHEDULER (sched));
271 g_return_if_fail (GST_IS_ELEMENT (element));
273 sched->clock_providers = g_list_remove (sched->clock_providers, element);
274 sched->clock_receivers = g_list_remove (sched->clock_receivers, element);
276 sclass = GST_SCHEDULER_GET_CLASS (sched);
278 if (sclass->remove_element)
279 sclass->remove_element (sched, element);
281 gst_element_set_scheduler (element, NULL);
282 }
284 /**
285 * gst_scheduler_state_transition:
286 * @sched: the scheduler
287 * @element: the element with the state transition
288 * @transition: the state transition
289 *
290 * Tell the scheduler that an element changed its state.
291 *
292 * Returns: a GstElementStateReturn indicating success or failure
293 * of the state transition.
294 */
295 GstElementStateReturn
296 gst_scheduler_state_transition (GstScheduler * sched, GstElement * element,
297 gint transition)
298 {
299 GstSchedulerClass *sclass;
301 g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_STATE_FAILURE);
302 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
304 if (element == sched->parent && sched->parent_sched == NULL) {
305 switch (transition) {
306 case GST_STATE_READY_TO_PAUSED:
307 {
308 GstClock *clock = gst_scheduler_get_clock (sched);
310 GST_CAT_DEBUG (GST_CAT_CLOCK,
311 "scheduler READY to PAUSED clock is %p (%s)", clock,
312 (clock ? GST_OBJECT_NAME (clock) : "nil"));
314 gst_scheduler_set_clock (sched, clock);
315 break;
316 }
317 }
318 }
320 sclass = GST_SCHEDULER_GET_CLASS (sched);
322 if (sclass->state_transition)
323 return sclass->state_transition (sched, element, transition);
325 return GST_STATE_SUCCESS;
326 }
328 /**
329 * gst_scheduler_scheduling_change:
330 * @sched: the scheduler
331 * @element: the element that changed its scheduling strategy
332 *
333 * Tell the scheduler that an element changed its scheduling strategy.
334 * An element could, for example, change its loop function or changes
335 * from a loop based element to a chain based element.
336 */
337 void
338 gst_scheduler_scheduling_change (GstScheduler * sched, GstElement * element)
339 {
340 GstSchedulerClass *sclass;
342 g_return_if_fail (GST_IS_SCHEDULER (sched));
343 g_return_if_fail (GST_IS_ELEMENT (element));
345 sclass = GST_SCHEDULER_GET_CLASS (sched);
347 if (sclass->scheduling_change)
348 sclass->scheduling_change (sched, element);
349 }
351 /**
352 * gst_scheduler_add_scheduler:
353 * @sched: a #GstScheduler to add to
354 * @sched2: the #GstScheduler to add
355 *
356 * Notifies the scheduler that it has to monitor this scheduler.
357 */
358 void
359 gst_scheduler_add_scheduler (GstScheduler * sched, GstScheduler * sched2)
360 {
361 GstSchedulerClass *sclass;
363 g_return_if_fail (GST_IS_SCHEDULER (sched));
364 g_return_if_fail (GST_IS_SCHEDULER (sched2));
365 g_return_if_fail (sched2->parent_sched == NULL);
367 GST_DEBUG ("gstscheduler: %p add scheduler %p", sched, sched2);
369 gst_object_ref (GST_OBJECT (sched2));
370 gst_object_ref (GST_OBJECT (sched));
372 sched->schedulers = g_list_prepend (sched->schedulers, sched2);
373 sched2->parent_sched = sched;
375 sclass = GST_SCHEDULER_GET_CLASS (sched);
377 if (sclass->add_scheduler)
378 sclass->add_scheduler (sched, sched2);
379 }
381 /**
382 * gst_scheduler_remove_scheduler:
383 * @sched: the scheduler
384 * @sched2: the scheduler to remove
385 *
386 a Notifies the scheduler that it can stop monitoring this scheduler.
387 */
388 void
389 gst_scheduler_remove_scheduler (GstScheduler * sched, GstScheduler * sched2)
390 {
391 GstSchedulerClass *sclass;
393 g_return_if_fail (GST_IS_SCHEDULER (sched));
394 g_return_if_fail (GST_IS_SCHEDULER (sched2));
395 g_return_if_fail (sched2->parent_sched == sched);
397 GST_DEBUG ("gstscheduler: %p remove scheduler %p", sched, sched2);
399 sclass = GST_SCHEDULER_GET_CLASS (sched);
401 if (sclass->remove_scheduler)
402 sclass->remove_scheduler (sched, sched2);
404 sched->schedulers = g_list_remove (sched->schedulers, sched2);
405 sched2->parent_sched = NULL;
407 gst_object_unref (GST_OBJECT (sched2));
408 gst_object_unref (GST_OBJECT (sched));
409 }
411 /**
412 * gst_scheduler_lock_element:
413 * @sched: the scheduler
414 * @element: the element to lock
415 *
416 * Acquire a lock on the given element in the given scheduler.
417 */
418 void
419 gst_scheduler_lock_element (GstScheduler * sched, GstElement * element)
420 {
421 GstSchedulerClass *sclass;
423 g_return_if_fail (GST_IS_SCHEDULER (sched));
424 g_return_if_fail (GST_IS_ELEMENT (element));
426 sclass = GST_SCHEDULER_GET_CLASS (sched);
428 if (sclass->lock_element)
429 sclass->lock_element (sched, element);
430 }
432 /**
433 * gst_scheduler_unlock_element:
434 * @sched: the scheduler
435 * @element: the element to unlock
436 *
437 * Release the lock on the given element in the given scheduler.
438 */
439 void
440 gst_scheduler_unlock_element (GstScheduler * sched, GstElement * element)
441 {
442 GstSchedulerClass *sclass;
444 g_return_if_fail (GST_IS_SCHEDULER (sched));
445 g_return_if_fail (GST_IS_ELEMENT (element));
447 sclass = GST_SCHEDULER_GET_CLASS (sched);
449 if (sclass->unlock_element)
450 sclass->unlock_element (sched, element);
451 }
453 /**
454 * gst_scheduler_error:
455 * @sched: the scheduler
456 * @element: the element with the error
457 *
458 * Tell the scheduler an element was in error
459 */
460 void
461 gst_scheduler_error (GstScheduler * sched, GstElement * element)
462 {
463 GstSchedulerClass *sclass;
465 g_return_if_fail (GST_IS_SCHEDULER (sched));
466 g_return_if_fail (GST_IS_ELEMENT (element));
468 sclass = GST_SCHEDULER_GET_CLASS (sched);
470 if (sclass->error)
471 sclass->error (sched, element);
472 }
474 /**
475 * gst_scheduler_yield:
476 * @sched: the scheduler
477 * @element: the element requesting a yield
478 *
479 * Tell the scheduler to schedule another element.
480 *
481 * Returns: TRUE if the element should save its state, FALSE
482 * if the scheduler can perform this action itself.
483 */
484 gboolean
485 gst_scheduler_yield (GstScheduler * sched, GstElement * element)
486 {
487 GstSchedulerClass *sclass;
489 g_return_val_if_fail (GST_IS_SCHEDULER (sched), TRUE);
490 g_return_val_if_fail (GST_IS_ELEMENT (element), TRUE);
492 sclass = GST_SCHEDULER_GET_CLASS (sched);
494 if (sclass->yield)
495 return sclass->yield (sched, element);
497 return TRUE;
498 }
500 /**
501 * gst_scheduler_interrupt:
502 * @sched: the scheduler
503 * @element: the element requesting an interrupt
504 *
505 * Tell the scheduler to interrupt execution of this element.
506 *
507 * Returns: TRUE if the element should return NULL from the chain/get
508 * function.
509 */
510 gboolean
511 gst_scheduler_interrupt (GstScheduler * sched, GstElement * element)
512 {
513 GstSchedulerClass *sclass;
515 g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
516 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
518 sclass = GST_SCHEDULER_GET_CLASS (sched);
520 if (sclass->interrupt)
521 return sclass->interrupt (sched, element);
523 return FALSE;
524 }
526 /**
527 * gst_scheduler_get_clock:
528 * @sched: the scheduler
529 *
530 * Get the current clock used by the scheduler
531 *
532 * Returns: a GstClock
533 */
534 GstClock *
535 gst_scheduler_get_clock (GstScheduler * sched)
536 {
537 GstClock *clock = NULL;
539 /* if we have a fixed clock, use that one */
540 if (GST_FLAG_IS_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK)) {
541 clock = sched->clock;
543 GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)", clock,
544 (clock ? GST_OBJECT_NAME (clock) : "nil"));
545 } else {
546 GList *schedulers = sched->schedulers;
547 GList *providers = sched->clock_providers;
549 /* try to get a clock from one of the schedulers we manage first */
550 while (schedulers) {
551 GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
553 clock = gst_scheduler_get_clock (scheduler);
554 if (clock)
555 break;
557 schedulers = g_list_next (schedulers);
558 }
559 /* still no clock, try to find one in the providers */
560 while (!clock && providers) {
561 clock = gst_element_get_clock (GST_ELEMENT (providers->data));
563 providers = g_list_next (providers);
564 }
565 /* still no clock, use a system clock */
566 if (!clock && sched->parent_sched == NULL) {
567 clock = gst_system_clock_obtain ();
568 }
569 }
570 GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, sched, "scheduler selected clock %p (%s)",
571 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
573 return clock;
574 }
576 /**
577 * gst_scheduler_use_clock:
578 * @sched: the scheduler
579 * @clock: the clock to use
580 *
581 * Force the scheduler to use the given clock. The scheduler will
582 * always use the given clock even if new clock providers are added
583 * to this scheduler.
584 */
585 void
586 gst_scheduler_use_clock (GstScheduler * sched, GstClock * clock)
587 {
588 g_return_if_fail (sched != NULL);
589 g_return_if_fail (GST_IS_SCHEDULER (sched));
591 GST_FLAG_SET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
593 gst_object_replace ((GstObject **) & sched->clock, (GstObject *) clock);
595 GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using fixed clock %p (%s)", clock,
596 (clock ? GST_OBJECT_NAME (clock) : "nil"));
597 }
599 /**
600 * gst_scheduler_set_clock:
601 * @sched: the scheduler
602 * @clock: the clock to set
603 *
604 * Set the clock for the scheduler. The clock will be distributed
605 * to all the elements managed by the scheduler.
606 */
607 void
608 gst_scheduler_set_clock (GstScheduler * sched, GstClock * clock)
609 {
610 GList *receivers;
611 GList *schedulers;
613 g_return_if_fail (sched != NULL);
614 g_return_if_fail (GST_IS_SCHEDULER (sched));
616 receivers = sched->clock_receivers;
617 schedulers = sched->schedulers;
619 gst_object_replace ((GstObject **) & sched->current_clock,
620 (GstObject *) clock);
622 while (receivers) {
623 GstElement *element = GST_ELEMENT (receivers->data);
625 GST_CAT_DEBUG (GST_CAT_CLOCK,
626 "scheduler setting clock %p (%s) on element %s", clock,
627 (clock ? GST_OBJECT_NAME (clock) : "nil"), GST_ELEMENT_NAME (element));
629 gst_element_set_clock (element, clock);
630 receivers = g_list_next (receivers);
631 }
632 while (schedulers) {
633 GstScheduler *scheduler = GST_SCHEDULER (schedulers->data);
635 GST_CAT_DEBUG (GST_CAT_CLOCK,
636 "scheduler setting clock %p (%s) on scheduler %p", clock,
637 (clock ? GST_OBJECT_NAME (clock) : "nil"), scheduler);
638 gst_scheduler_set_clock (scheduler, clock);
639 schedulers = g_list_next (schedulers);
640 }
641 }
643 /**
644 * gst_scheduler_auto_clock:
645 * @sched: the scheduler
646 *
647 * Let the scheduler select a clock automatically.
648 */
649 void
650 gst_scheduler_auto_clock (GstScheduler * sched)
651 {
652 g_return_if_fail (sched != NULL);
653 g_return_if_fail (GST_IS_SCHEDULER (sched));
655 GST_FLAG_UNSET (sched, GST_SCHEDULER_FLAG_FIXED_CLOCK);
657 gst_object_replace ((GstObject **) & sched->clock, NULL);
659 GST_CAT_DEBUG (GST_CAT_CLOCK, "scheduler using automatic clock");
660 }
662 GstClockReturn gst_clock_id_wait (GstClockID id, GstClockTimeDiff * jitter);
664 /**
665 * gst_scheduler_clock_wait:
666 * @sched: the scheduler
667 * @element: the element that wants to wait
668 * @id: the clockid to use
669 * @jitter: the time difference between requested time and actual time
670 *
671 * Wait till the clock reaches a specific time. The ClockID can
672 * be obtained from #gst_clock_new_single_shot_id.
673 *
674 * Returns: the status of the operation
675 */
676 GstClockReturn
677 gst_scheduler_clock_wait (GstScheduler * sched, GstElement * element,
678 GstClockID id, GstClockTimeDiff * jitter)
679 {
680 GstSchedulerClass *sclass;
682 g_return_val_if_fail (GST_IS_SCHEDULER (sched), GST_CLOCK_ERROR);
683 g_return_val_if_fail (id != NULL, GST_CLOCK_ERROR);
685 sclass = GST_SCHEDULER_GET_CLASS (sched);
687 if (sclass->clock_wait)
688 return sclass->clock_wait (sched, element, id, jitter);
689 else
690 return gst_clock_id_wait (id, jitter);
691 }
693 /**
694 * gst_scheduler_iterate:
695 * @sched: the scheduler
696 *
697 * Perform one iteration on the scheduler.
698 *
699 * Returns: a boolean indicating something usefull has happened.
700 */
701 gboolean
702 gst_scheduler_iterate (GstScheduler * sched)
703 {
704 GstSchedulerClass *sclass;
705 gboolean res = FALSE;
707 g_return_val_if_fail (GST_IS_SCHEDULER (sched), FALSE);
709 sclass = GST_SCHEDULER_GET_CLASS (sched);
711 if (sclass->iterate) {
712 res = sclass->iterate (sched);
713 }
715 return res;
716 }
719 /**
720 * gst_scheduler_show:
721 * @sched: the scheduler
722 *
723 * Dump the state of the scheduler
724 */
725 void
726 gst_scheduler_show (GstScheduler * sched)
727 {
728 GstSchedulerClass *sclass;
730 g_return_if_fail (GST_IS_SCHEDULER (sched));
732 sclass = GST_SCHEDULER_GET_CLASS (sched);
734 if (sclass->show)
735 sclass->show (sched);
736 }
738 /*
739 * Factory stuff starts here
740 *
741 */
742 static void gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass);
743 static void gst_scheduler_factory_init (GstSchedulerFactory * factory);
745 static GstPluginFeatureClass *factory_parent_class = NULL;
747 /* static guint gst_scheduler_factory_signals[LAST_SIGNAL] = { 0 }; */
749 GType
750 gst_scheduler_factory_get_type (void)
751 {
752 static GType schedulerfactory_type = 0;
754 if (!schedulerfactory_type) {
755 static const GTypeInfo schedulerfactory_info = {
756 sizeof (GstSchedulerFactoryClass),
757 NULL,
758 NULL,
759 (GClassInitFunc) gst_scheduler_factory_class_init,
760 NULL,
761 NULL,
762 sizeof (GstSchedulerFactory),
763 0,
764 (GInstanceInitFunc) gst_scheduler_factory_init,
765 NULL
766 };
767 schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
768 "GstSchedulerFactory", &schedulerfactory_info, 0);
769 }
770 return schedulerfactory_type;
771 }
773 static void
774 gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass)
775 {
776 GObjectClass *gobject_class;
777 GstObjectClass *gstobject_class;
778 GstPluginFeatureClass *gstpluginfeature_class;
780 gobject_class = (GObjectClass *) klass;
781 gstobject_class = (GstObjectClass *) klass;
782 gstpluginfeature_class = (GstPluginFeatureClass *) klass;
784 factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
786 if (!_default_name) {
787 if (g_getenv ("GST_SCHEDULER")) {
788 _default_name = g_strdup (g_getenv ("GST_SCHEDULER"));
789 } else {
790 _default_name = g_strdup (GST_SCHEDULER_DEFAULT_NAME);
791 }
792 }
793 g_assert (_default_name);
794 }
796 static void
797 gst_scheduler_factory_init (GstSchedulerFactory * factory)
798 {
799 }
802 /**
803 * gst_scheduler_factory_new:
804 * @name: name of schedulerfactory to create
805 * @longdesc: long description of schedulerfactory to create
806 * @type: the gtk type of the GstScheduler element of this factory
807 *
808 * Create a new schedulerfactory with the given parameters
809 *
810 * Returns: a new #GstSchedulerFactory.
811 */
812 GstSchedulerFactory *
813 gst_scheduler_factory_new (const gchar * name, const gchar * longdesc,
814 GType type)
815 {
816 GstSchedulerFactory *factory;
818 g_return_val_if_fail (name != NULL, NULL);
820 factory = gst_scheduler_factory_find (name);
822 if (!factory) {
823 factory =
824 GST_SCHEDULER_FACTORY (g_object_new (GST_TYPE_SCHEDULER_FACTORY, NULL));
825 GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
826 } else {
827 g_free (factory->longdesc);
828 }
830 factory->longdesc = g_strdup (longdesc);
831 factory->type = type;
833 return factory;
834 }
836 /**
837 * gst_scheduler_factory_destroy:
838 * @factory: factory to destroy
839 *
840 * Removes the scheduler from the global list.
841 */
842 void
843 gst_scheduler_factory_destroy (GstSchedulerFactory * factory)
844 {
845 g_return_if_fail (factory != NULL);
847 /* we don't free the struct bacause someone might have a handle to it.. */
848 }
850 /**
851 * gst_scheduler_factory_find:
852 * @name: name of schedulerfactory to find
853 *
854 * Search for an schedulerfactory of the given name.
855 *
856 * Returns: #GstSchedulerFactory if found, NULL otherwise
857 */
858 GstSchedulerFactory *
859 gst_scheduler_factory_find (const gchar * name)
860 {
861 GstPluginFeature *feature;
863 g_return_val_if_fail (name != NULL, NULL);
865 GST_DEBUG ("gstscheduler: find \"%s\"", name);
867 feature = gst_registry_pool_find_feature (name, GST_TYPE_SCHEDULER_FACTORY);
869 if (feature)
870 return GST_SCHEDULER_FACTORY (feature);
872 return NULL;
873 }
875 /**
876 * gst_scheduler_factory_create:
877 * @factory: the factory used to create the instance
878 * @parent: the parent element of this scheduler
879 *
880 * Create a new #GstScheduler instance from the
881 * given schedulerfactory with the given parent. @parent will
882 * have its scheduler set to the returned #GstScheduler instance.
883 *
884 * Returns: A new #GstScheduler instance with a reference count of %1.
885 */
886 GstScheduler *
887 gst_scheduler_factory_create (GstSchedulerFactory * factory,
888 GstElement * parent)
889 {
890 GstScheduler *sched = NULL;
892 g_return_val_if_fail (factory != NULL, NULL);
893 g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
895 if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
896 g_return_val_if_fail (factory->type != 0, NULL);
898 sched = GST_SCHEDULER (g_object_new (factory->type, NULL));
899 sched->parent = parent;
901 GST_ELEMENT_SCHED (parent) = sched;
903 /* let's refcount the scheduler */
904 gst_object_ref (GST_OBJECT (sched));
905 gst_object_sink (GST_OBJECT (sched));
906 }
908 return sched;
909 }
911 /**
912 * gst_scheduler_factory_make:
913 * @name: the name of the factory used to create the instance
914 * @parent: the parent element of this scheduler
915 *
916 * Create a new #GstScheduler instance from the
917 * schedulerfactory with the given name and parent. @parent will
918 * have its scheduler set to the returned #GstScheduler instance.
919 * If %NULL is passed as @name, the default scheduler name will
920 * be used.
921 *
922 * Returns: A new #GstScheduler instance with a reference count of %1.
923 */
924 GstScheduler *
925 gst_scheduler_factory_make (const gchar * name, GstElement * parent)
926 {
927 GstSchedulerFactory *factory;
928 const gchar *default_name = gst_scheduler_factory_get_default_name ();
930 if (name)
931 factory = gst_scheduler_factory_find (name);
932 else {
933 /* FIXME: do better error handling */
934 if (default_name == NULL)
935 g_error ("No default scheduler name - do you have a registry ?");
936 factory = gst_scheduler_factory_find (default_name);
937 }
939 if (factory == NULL)
940 return NULL;
942 return gst_scheduler_factory_create (factory, parent);
943 }
945 /**
946 * gst_scheduler_factory_set_default_name:
947 * @name: the name of the factory used as a default
948 *
949 * Set the default schedulerfactory name.
950 */
951 void
952 gst_scheduler_factory_set_default_name (const gchar * name)
953 {
954 g_free (_default_name);
956 _default_name = g_strdup (name);
957 }
959 /**
960 * gst_scheduler_factory_get_default_name:
961 *
962 * Get the default schedulerfactory name.
963 *
964 * Returns: the name of the default scheduler.
965 */
966 const gchar *
967 gst_scheduler_factory_get_default_name (void)
968 {
969 return _default_name;
970 }