/* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * * gsttype.c: Media-type management functions * * 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. */ /* TODO: * probably should set up a hash table for the type id's, since currently * it's a rather pathetic linear search. Eventually there may be dozens * of id's, but in reality there are only so many instances of lookup, so * I'm not overly worried yet... */ #include "gst_private.h" #include "gsttype.h" #include "gstregistry.h" #include "gstobject.h" #include "gstlog.h" /* global list of registered types */ static GList *_gst_types; static guint16 _gst_maxtype; static void gst_type_factory_class_init (GstTypeFactoryClass *klass); static void gst_type_factory_init (GstTypeFactory *factory); static GstCaps* gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv); static void gst_type_factory_unload_thyself (GstPluginFeature *feature); static GstPluginFeatureClass *parent_class = NULL; /* static guint gst_type_factory_signals[LAST_SIGNAL] = { 0 }; */ GType gst_type_factory_get_type (void) { static GType typefactory_type = 0; if (!typefactory_type) { static const GTypeInfo typefactory_info = { sizeof (GstTypeFactoryClass), NULL, NULL, (GClassInitFunc) gst_type_factory_class_init, NULL, NULL, sizeof(GstTypeFactory), 0, (GInstanceInitFunc) gst_type_factory_init, NULL }; typefactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, "GstTypeFactory", &typefactory_info, 0); } return typefactory_type; } static void gst_type_factory_class_init (GstTypeFactoryClass *klass) { GObjectClass *gobject_class; GstObjectClass *gstobject_class; GstPluginFeatureClass *gstpluginfeature_class; gobject_class = (GObjectClass*)klass; gstobject_class = (GstObjectClass*)klass; gstpluginfeature_class = (GstPluginFeatureClass*) klass; parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE); gstpluginfeature_class->unload_thyself = GST_DEBUG_FUNCPTR (gst_type_factory_unload_thyself); _gst_types = NULL; _gst_maxtype = 1; /* type 0 is undefined */ } static void gst_type_factory_init (GstTypeFactory *factory) { } /** * gst_type_factory_new: * @definition: the definition to use * * Creata a new typefactory from the given definition. * * Returns: the new typefactory */ GstTypeFactory* gst_type_factory_new (GstTypeDefinition *definition) { GstTypeFactory *factory; g_return_val_if_fail (definition != NULL, NULL); g_return_val_if_fail (definition->name != NULL, NULL); g_return_val_if_fail (definition->mime != NULL, NULL); factory = gst_type_factory_find (definition->name); if (!factory) { factory = GST_TYPE_FACTORY (g_object_new (GST_TYPE_TYPE_FACTORY, NULL)); } GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (definition->name); factory->mime = g_strdup (definition->mime); factory->exts = g_strdup (definition->exts); factory->typefindfunc = definition->typefindfunc; return factory; } /** * gst_type_register: * @factory: the type factory to register * * Register a new type factory to the system. * * Returns: the new type id */ guint16 gst_type_register (GstTypeFactory *factory) { guint16 id; GstType *type; g_return_val_if_fail (factory != NULL, 0); /* GST_INFO (GST_CAT_TYPES,"type register %s", factory->mime); */ id = gst_type_find_by_mime (factory->mime); if (!id) { type = g_new0 (GstType, 1); type->id = _gst_maxtype++; type->mime = factory->mime; type->exts = factory->exts; type->factories = NULL; _gst_types = g_list_prepend (_gst_types, type); id = type->id; } else { type = gst_type_find_by_id (id); /* now we want to try to merge the types and return the original */ /* FIXME: do extension merging here, not that easy */ /* if there is no existing typefind function, try to use new one */ } GST_DEBUG (GST_CAT_TYPES,"gsttype: %s(%p) gave new mime type '%s', id %d", GST_OBJECT_NAME (factory), factory, type->mime, type->id); type->factories = g_slist_prepend (type->factories, factory); return id; } static guint16 gst_type_find_by_mime_func (const gchar *mime) { GList *walk; GstType *type; gint typelen,mimelen; gchar *search, *found; g_return_val_if_fail (mime != NULL, 0); walk = _gst_types; /* GST_DEBUG (GST_CAT_TYPES,"searching for '%s'",mime); */ mimelen = strlen (mime); while (walk) { type = (GstType *)walk->data; search = type->mime; /* GST_DEBUG (GST_CAT_TYPES,"checking against '%s'",search); */ typelen = strlen (search); while ((search - type->mime) < typelen) { found = strstr (search, mime); /* if the requested mime is in the list */ if (found) { if ((*(found + mimelen) == ' ') || (*(found + mimelen) == ',') || (*(found + mimelen) == '\0')) { return type->id; } else { search = found + mimelen; } } else search += mimelen; } walk = g_list_next (walk); } return 0; } /** * gst_type_find_by_mime: * @mime: the mime type to find * * Find the type id of a given mime type. * * Returns: the type id */ guint16 gst_type_find_by_mime (const gchar *mime) { return gst_type_find_by_mime_func (mime); } /** * gst_type_find_by_ext: * @ext: the extension to find * * Find the type id of a given extention. * * Returns: the type id */ guint16 gst_type_find_by_ext (const gchar *ext) { /* FIXME */ g_warning ("gsttype: find_by_ext not implemented"); return 0; } /** * gst_type_find_by_id: * @id: the type id to lookup * * Find the type of a given type id. * * Returns: the type */ GstType* gst_type_find_by_id (guint16 id) { GList *walk = _gst_types; GstType *type; while (walk) { type = (GstType *)walk->data; if (type->id == id) return type; walk = g_list_next (walk); } return NULL; } /** * gst_type_get_list: * * Return a list of all registered types. * * Returns: a list of GstTypes */ const GList* gst_type_get_list (void) { return _gst_types; } /** * gst_type_factory_find: * @name: the name of the typefactory to find * * Return the TypeFactory with the given name. * * Returns: a GstTypeFactory with the given name; */ GstTypeFactory* gst_type_factory_find (const gchar *name) { GstPluginFeature *feature; g_return_val_if_fail (name != NULL, NULL); feature = gst_registry_pool_find_feature (name, GST_TYPE_TYPE_FACTORY); if (feature) return GST_TYPE_FACTORY (feature); return NULL; } static void gst_type_factory_unload_thyself (GstPluginFeature *feature) { GstTypeFactory *factory; g_return_if_fail (GST_IS_TYPE_FACTORY (feature)); factory = GST_TYPE_FACTORY (feature); if (factory->typefindfunc) factory->typefindfunc = gst_type_type_find_dummy; } static GstCaps* gst_type_type_find_dummy (GstBuffer *buffer, gpointer priv) { GstTypeFactory *factory = (GstTypeFactory *)priv; GST_DEBUG (GST_CAT_TYPES,"gsttype: need to load typefind function for %s", factory->mime); if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) { if (factory->typefindfunc) { GstCaps *res = factory->typefindfunc (buffer, factory); if (res) return res; } } return NULL; }