4b00e04684512a5e84058b6c4c486716819f917f
[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 #include "gst_private.h"
24
25 #include "gstsystemclock.h"
26 #include "gstscheduler.h"
27 #include "gstinfo.h"
28 #include "gstregistrypool.h"
29
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);
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 =
58         g_type_register_static (GST_TYPE_OBJECT, "GstScheduler",
59         &scheduler_info, G_TYPE_FLAG_ABSTRACT);
60   }
61   return _gst_scheduler_type;
62 }
63
64 static void
65 gst_scheduler_class_init (GstSchedulerClass * klass)
66 {
67   GObjectClass *gobject_class;
68
69   gobject_class = (GObjectClass *) klass;
70
71   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
72
73   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_scheduler_dispose);
74 }
75
76 static void
77 gst_scheduler_init (GstScheduler * sched)
78 {
79   sched->parent = NULL;
80 }
81
82 static void
83 gst_scheduler_dispose (GObject * object)
84 {
85   GstScheduler *sched = GST_SCHEDULER (object);
86
87   G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (sched));
88 }
89
90 /**
91  * gst_scheduler_setup:
92  * @sched: the scheduler
93  *
94  * Prepare the scheduler.
95  */
96 void
97 gst_scheduler_setup (GstScheduler * sched)
98 {
99   GstSchedulerClass *sclass;
100
101   g_return_if_fail (GST_IS_SCHEDULER (sched));
102
103   sclass = GST_SCHEDULER_GET_CLASS (sched);
104
105   if (sclass->setup)
106     sclass->setup (sched);
107 }
108
109 /**
110  * gst_scheduler_reset:
111  * @sched: a #GstScheduler to reset.
112  *
113  * Reset the schedulers.
114  */
115 void
116 gst_scheduler_reset (GstScheduler * sched)
117 {
118   GstSchedulerClass *sclass;
119
120   g_return_if_fail (GST_IS_SCHEDULER (sched));
121
122   sclass = GST_SCHEDULER_GET_CLASS (sched);
123
124   if (sclass->reset)
125     sclass->reset (sched);
126 }
127
128 GstTask *
129 gst_scheduler_create_task (GstScheduler * sched, GstTaskFunction func,
130     gpointer data)
131 {
132   GstSchedulerClass *sclass;
133   GstTask *result = NULL;
134
135   g_return_val_if_fail (GST_IS_SCHEDULER (sched), result);
136
137   sclass = GST_SCHEDULER_GET_CLASS (sched);
138
139   if (sclass->create_task)
140     result = sclass->create_task (sched, func, data);
141
142   return result;
143 }
144
145 /*
146  * Factory stuff starts here
147  *
148  */
149 static void gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass);
150 static void gst_scheduler_factory_init (GstSchedulerFactory * factory);
151
152 static GstPluginFeatureClass *factory_parent_class = NULL;
153
154 /* static guint gst_scheduler_factory_signals[LAST_SIGNAL] = { 0 }; */
155
156 GType
157 gst_scheduler_factory_get_type (void)
158 {
159   static GType schedulerfactory_type = 0;
160
161   if (!schedulerfactory_type) {
162     static const GTypeInfo schedulerfactory_info = {
163       sizeof (GstSchedulerFactoryClass),
164       NULL,
165       NULL,
166       (GClassInitFunc) gst_scheduler_factory_class_init,
167       NULL,
168       NULL,
169       sizeof (GstSchedulerFactory),
170       0,
171       (GInstanceInitFunc) gst_scheduler_factory_init,
172       NULL
173     };
174
175     schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
176         "GstSchedulerFactory", &schedulerfactory_info, 0);
177   }
178   return schedulerfactory_type;
179 }
180
181 static void
182 gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass)
183 {
184   GObjectClass *gobject_class;
185   GstObjectClass *gstobject_class;
186   GstPluginFeatureClass *gstpluginfeature_class;
187
188   gobject_class = (GObjectClass *) klass;
189   gstobject_class = (GstObjectClass *) klass;
190   gstpluginfeature_class = (GstPluginFeatureClass *) klass;
191
192   factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
193
194   if (!_default_name) {
195     if (g_getenv ("GST_SCHEDULER")) {
196       _default_name = g_strdup (g_getenv ("GST_SCHEDULER"));
197     } else {
198       _default_name = g_strdup (GST_SCHEDULER_DEFAULT_NAME);
199     }
200   }
201   g_assert (_default_name);
202 }
203
204 static void
205 gst_scheduler_factory_init (GstSchedulerFactory * factory)
206 {
207 }
208
209
210 /**
211  * gst_scheduler_register:
212  * @plugin: a #GstPlugin
213  * @name: name of the scheduler to register
214  * @longdesc: description of the scheduler
215  * @type: #GType of the scheduler to register
216  *
217  * Registers a scheduler with GStreamer.
218  *
219  * Returns: TRUE, if the registering succeeded, FALSE on error.
220  *
221  * Since: 0.8.5
222  **/
223 gboolean
224 gst_scheduler_register (GstPlugin * plugin, const gchar * name,
225     const gchar * longdesc, GType type)
226 {
227   GstSchedulerFactory *factory;
228
229   g_return_val_if_fail (plugin != NULL, FALSE);
230   g_return_val_if_fail (name != NULL, FALSE);
231   g_return_val_if_fail (longdesc != NULL, FALSE);
232   g_return_val_if_fail (g_type_is_a (type, GST_TYPE_SCHEDULER), FALSE);
233
234   factory = gst_scheduler_factory_find (name);
235   if (factory) {
236     g_return_val_if_fail (factory->type == 0, FALSE);
237     g_free (factory->longdesc);
238     factory->longdesc = g_strdup (longdesc);
239     factory->type = type;
240   } else {
241     factory = gst_scheduler_factory_new (name, longdesc, type);
242     g_return_val_if_fail (factory, FALSE);
243     gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
244   }
245
246   return TRUE;
247 }
248
249 /**
250  * gst_scheduler_factory_new:
251  * @name: name of schedulerfactory to create
252  * @longdesc: long description of schedulerfactory to create
253  * @type: the gtk type of the GstScheduler element of this factory
254  *
255  * Create a new schedulerfactory with the given parameters
256  *
257  * Returns: a new #GstSchedulerFactory.
258  */
259 GstSchedulerFactory *
260 gst_scheduler_factory_new (const gchar * name, const gchar * longdesc,
261     GType type)
262 {
263   GstSchedulerFactory *factory;
264
265   g_return_val_if_fail (name != NULL, NULL);
266
267   factory = gst_scheduler_factory_find (name);
268
269   if (!factory) {
270     factory =
271         GST_SCHEDULER_FACTORY (g_object_new (GST_TYPE_SCHEDULER_FACTORY, NULL));
272     GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
273   } else {
274     g_free (factory->longdesc);
275   }
276
277   factory->longdesc = g_strdup (longdesc);
278   factory->type = type;
279
280   return factory;
281 }
282
283 /**
284  * gst_scheduler_factory_destroy:
285  * @factory: factory to destroy
286  *
287  * Removes the scheduler from the global list.
288  */
289 void
290 gst_scheduler_factory_destroy (GstSchedulerFactory * factory)
291 {
292   g_return_if_fail (factory != NULL);
293
294   /* we don't free the struct bacause someone might  have a handle to it.. */
295 }
296
297 /**
298  * gst_scheduler_factory_find:
299  * @name: name of schedulerfactory to find
300  *
301  * Search for an schedulerfactory of the given name.
302  *
303  * Returns: #GstSchedulerFactory if found, NULL otherwise
304  */
305 GstSchedulerFactory *
306 gst_scheduler_factory_find (const gchar * name)
307 {
308   GstPluginFeature *feature;
309
310   g_return_val_if_fail (name != NULL, NULL);
311
312   GST_DEBUG ("gstscheduler: find \"%s\"", name);
313
314   feature = gst_registry_pool_find_feature (name, GST_TYPE_SCHEDULER_FACTORY);
315
316   if (feature)
317     return GST_SCHEDULER_FACTORY (feature);
318
319   return NULL;
320 }
321
322 /**
323  * gst_scheduler_factory_create:
324  * @factory: the factory used to create the instance
325  * @parent: the parent element of this scheduler
326  *
327  * Create a new #GstScheduler instance from the 
328  * given schedulerfactory with the given parent. @parent will
329  * have its scheduler set to the returned #GstScheduler instance.
330  *
331  * Returns: A new #GstScheduler instance with a reference count of %1.
332  */
333 GstScheduler *
334 gst_scheduler_factory_create (GstSchedulerFactory * factory,
335     GstElement * parent)
336 {
337   GstScheduler *sched = NULL;
338
339   g_return_val_if_fail (factory != NULL, NULL);
340   g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL);
341
342   if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
343     g_return_val_if_fail (factory->type != 0, NULL);
344
345     sched = GST_SCHEDULER (g_object_new (factory->type, NULL));
346     sched->parent = parent;
347
348     /* let's refcount the scheduler */
349     gst_object_ref (GST_OBJECT (sched));
350     gst_object_sink (GST_OBJECT (sched));
351   }
352
353   return sched;
354 }
355
356 /**
357  * gst_scheduler_factory_make:
358  * @name: the name of the factory used to create the instance
359  * @parent: the parent element of this scheduler
360  *
361  * Create a new #GstScheduler instance from the 
362  * schedulerfactory with the given name and parent. @parent will
363  * have its scheduler set to the returned #GstScheduler instance.
364  * If %NULL is passed as @name, the default scheduler name will
365  * be used.
366  *
367  * Returns: A new #GstScheduler instance with a reference count of %1.
368  */
369 GstScheduler *
370 gst_scheduler_factory_make (const gchar * name, GstElement * parent)
371 {
372   GstSchedulerFactory *factory;
373   const gchar *default_name = gst_scheduler_factory_get_default_name ();
374
375   if (name)
376     factory = gst_scheduler_factory_find (name);
377   else {
378     /* FIXME: do better error handling */
379     if (default_name == NULL)
380       g_error ("No default scheduler name - do you have a registry ?");
381     factory = gst_scheduler_factory_find (default_name);
382   }
383
384   if (factory == NULL)
385     return NULL;
386
387   return gst_scheduler_factory_create (factory, parent);
388 }
389
390 /**
391  * gst_scheduler_factory_set_default_name:
392  * @name: the name of the factory used as a default
393  *
394  * Set the default schedulerfactory name.
395  */
396 void
397 gst_scheduler_factory_set_default_name (const gchar * name)
398 {
399   g_free (_default_name);
400
401   _default_name = g_strdup (name);
402 }
403
404 /**
405  * gst_scheduler_factory_get_default_name:
406  *
407  * Get the default schedulerfactory name.
408  *
409  * Returns: the name of the default scheduler.
410  */
411 const gchar *
412 gst_scheduler_factory_get_default_name (void)
413 {
414   return _default_name;
415 }