/* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * * gstscheduler.c: Default scheduling code for most cases * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "gst_private.h" #include "gstsystemclock.h" #include "gstscheduler.h" #include "gstinfo.h" #include "gstregistrypool.h" static void gst_scheduler_class_init (GstSchedulerClass * klass); static void gst_scheduler_init (GstScheduler * sched); static void gst_scheduler_dispose (GObject * object); static GstObjectClass *parent_class = NULL; static gchar *_default_name = NULL; GType gst_scheduler_get_type (void) { static GType _gst_scheduler_type = 0; if (!_gst_scheduler_type) { static const GTypeInfo scheduler_info = { sizeof (GstSchedulerClass), NULL, NULL, (GClassInitFunc) gst_scheduler_class_init, NULL, NULL, sizeof (GstScheduler), 0, (GInstanceInitFunc) gst_scheduler_init, NULL }; _gst_scheduler_type = g_type_register_static (GST_TYPE_OBJECT, "GstScheduler", &scheduler_info, G_TYPE_FLAG_ABSTRACT); } return _gst_scheduler_type; } static void gst_scheduler_class_init (GstSchedulerClass * klass) { GObjectClass *gobject_class; gobject_class = (GObjectClass *) klass; parent_class = g_type_class_ref (GST_TYPE_OBJECT); gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_scheduler_dispose); } static void gst_scheduler_init (GstScheduler * sched) { sched->parent = NULL; } static void gst_scheduler_dispose (GObject * object) { GstScheduler *sched = GST_SCHEDULER (object); G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (sched)); } /** * gst_scheduler_setup: * @sched: the scheduler * * Prepare the scheduler. */ void gst_scheduler_setup (GstScheduler * sched) { GstSchedulerClass *sclass; g_return_if_fail (GST_IS_SCHEDULER (sched)); sclass = GST_SCHEDULER_GET_CLASS (sched); if (sclass->setup) sclass->setup (sched); } /** * gst_scheduler_reset: * @sched: a #GstScheduler to reset. * * Reset the schedulers. */ void gst_scheduler_reset (GstScheduler * sched) { GstSchedulerClass *sclass; g_return_if_fail (GST_IS_SCHEDULER (sched)); sclass = GST_SCHEDULER_GET_CLASS (sched); if (sclass->reset) sclass->reset (sched); } GstTask * gst_scheduler_create_task (GstScheduler * sched, GstTaskFunction func, gpointer data) { GstSchedulerClass *sclass; GstTask *result = NULL; g_return_val_if_fail (GST_IS_SCHEDULER (sched), result); sclass = GST_SCHEDULER_GET_CLASS (sched); if (sclass->create_task) result = sclass->create_task (sched, func, data); return result; } /* * Factory stuff starts here * */ static void gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass); static void gst_scheduler_factory_init (GstSchedulerFactory * factory); static GstPluginFeatureClass *factory_parent_class = NULL; /* static guint gst_scheduler_factory_signals[LAST_SIGNAL] = { 0 }; */ GType gst_scheduler_factory_get_type (void) { static GType schedulerfactory_type = 0; if (!schedulerfactory_type) { static const GTypeInfo schedulerfactory_info = { sizeof (GstSchedulerFactoryClass), NULL, NULL, (GClassInitFunc) gst_scheduler_factory_class_init, NULL, NULL, sizeof (GstSchedulerFactory), 0, (GInstanceInitFunc) gst_scheduler_factory_init, NULL }; schedulerfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, "GstSchedulerFactory", &schedulerfactory_info, 0); } return schedulerfactory_type; } static void gst_scheduler_factory_class_init (GstSchedulerFactoryClass * klass) { GObjectClass *gobject_class; GstObjectClass *gstobject_class; GstPluginFeatureClass *gstpluginfeature_class; gobject_class = (GObjectClass *) klass; gstobject_class = (GstObjectClass *) klass; gstpluginfeature_class = (GstPluginFeatureClass *) klass; factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE); if (!_default_name) { if (g_getenv ("GST_SCHEDULER")) { _default_name = g_strdup (g_getenv ("GST_SCHEDULER")); } else { _default_name = g_strdup (GST_SCHEDULER_DEFAULT_NAME); } } g_assert (_default_name); } static void gst_scheduler_factory_init (GstSchedulerFactory * factory) { } /** * gst_scheduler_register: * @plugin: a #GstPlugin * @name: name of the scheduler to register * @longdesc: description of the scheduler * @type: #GType of the scheduler to register * * Registers a scheduler with GStreamer. * * Returns: TRUE, if the registering succeeded, FALSE on error. * * Since: 0.8.5 **/ gboolean gst_scheduler_register (GstPlugin * plugin, const gchar * name, const gchar * longdesc, GType type) { GstSchedulerFactory *factory; g_return_val_if_fail (plugin != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (longdesc != NULL, FALSE); g_return_val_if_fail (g_type_is_a (type, GST_TYPE_SCHEDULER), FALSE); factory = gst_scheduler_factory_find (name); if (factory) { g_return_val_if_fail (factory->type == 0, FALSE); g_free (factory->longdesc); factory->longdesc = g_strdup (longdesc); factory->type = type; } else { factory = gst_scheduler_factory_new (name, longdesc, type); g_return_val_if_fail (factory, FALSE); gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); } return TRUE; } /** * gst_scheduler_factory_new: * @name: name of schedulerfactory to create * @longdesc: long description of schedulerfactory to create * @type: the gtk type of the GstScheduler element of this factory * * Create a new schedulerfactory with the given parameters * * Returns: a new #GstSchedulerFactory. */ GstSchedulerFactory * gst_scheduler_factory_new (const gchar * name, const gchar * longdesc, GType type) { GstSchedulerFactory *factory; g_return_val_if_fail (name != NULL, NULL); factory = gst_scheduler_factory_find (name); if (!factory) { factory = GST_SCHEDULER_FACTORY (g_object_new (GST_TYPE_SCHEDULER_FACTORY, NULL)); GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name); } else { g_free (factory->longdesc); } factory->longdesc = g_strdup (longdesc); factory->type = type; return factory; } /** * gst_scheduler_factory_destroy: * @factory: factory to destroy * * Removes the scheduler from the global list. */ void gst_scheduler_factory_destroy (GstSchedulerFactory * factory) { g_return_if_fail (factory != NULL); /* we don't free the struct bacause someone might have a handle to it.. */ } /** * gst_scheduler_factory_find: * @name: name of schedulerfactory to find * * Search for an schedulerfactory of the given name. * * Returns: #GstSchedulerFactory if found, NULL otherwise */ GstSchedulerFactory * gst_scheduler_factory_find (const gchar * name) { GstPluginFeature *feature; g_return_val_if_fail (name != NULL, NULL); GST_DEBUG ("gstscheduler: find \"%s\"", name); feature = gst_registry_pool_find_feature (name, GST_TYPE_SCHEDULER_FACTORY); if (feature) return GST_SCHEDULER_FACTORY (feature); return NULL; } /** * gst_scheduler_factory_create: * @factory: the factory used to create the instance * @parent: the parent element of this scheduler * * Create a new #GstScheduler instance from the * given schedulerfactory with the given parent. @parent will * have its scheduler set to the returned #GstScheduler instance. * * Returns: A new #GstScheduler instance with a reference count of %1. */ GstScheduler * gst_scheduler_factory_create (GstSchedulerFactory * factory, GstElement * parent) { GstScheduler *sched = NULL; g_return_val_if_fail (factory != NULL, NULL); g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL); if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) { g_return_val_if_fail (factory->type != 0, NULL); sched = GST_SCHEDULER (g_object_new (factory->type, NULL)); sched->parent = parent; /* let's refcount the scheduler */ gst_object_ref (GST_OBJECT (sched)); gst_object_sink (GST_OBJECT (sched)); } return sched; } /** * gst_scheduler_factory_make: * @name: the name of the factory used to create the instance * @parent: the parent element of this scheduler * * Create a new #GstScheduler instance from the * schedulerfactory with the given name and parent. @parent will * have its scheduler set to the returned #GstScheduler instance. * If %NULL is passed as @name, the default scheduler name will * be used. * * Returns: A new #GstScheduler instance with a reference count of %1. */ GstScheduler * gst_scheduler_factory_make (const gchar * name, GstElement * parent) { GstSchedulerFactory *factory; const gchar *default_name = gst_scheduler_factory_get_default_name (); if (name) factory = gst_scheduler_factory_find (name); else { /* FIXME: do better error handling */ if (default_name == NULL) g_error ("No default scheduler name - do you have a registry ?"); factory = gst_scheduler_factory_find (default_name); } if (factory == NULL) return NULL; return gst_scheduler_factory_create (factory, parent); } /** * gst_scheduler_factory_set_default_name: * @name: the name of the factory used as a default * * Set the default schedulerfactory name. */ void gst_scheduler_factory_set_default_name (const gchar * name) { g_free (_default_name); _default_name = g_strdup (name); } /** * gst_scheduler_factory_get_default_name: * * Get the default schedulerfactory name. * * Returns: the name of the default scheduler. */ const gchar * gst_scheduler_factory_get_default_name (void) { return _default_name; }