gstreamer/gst/gsttype.c
Ronald S. Bultje 6fbff1c106 New typefind system: bytestream is now part of the core all plugins have been modified to use this new typefind syste...
Original commit message from CVS:
New typefind system:
* bytestream is now part of the core
* all plugins have been modified to use this new typefind system
* asf typefinding added
* mpeg video stream typefiding removed because it's broken
* duplicate typefind entries removed
* extra id3 typefinding added, because we've seen 4 types of files
(riff/wav, flac, vorbis, mp3) with id3 headers and each of these needs
to work. Instead, I've added an id3 element and let it redo typefiding
after the id3 header. this needs a hack because spider only typefinds
once. We can remove this hack once spider supports multiple typefinds.
* with all this, mp3 typefinding is semi-rewritten
* id3 typefinding in flac/vorbis is removed, it's no longer needed
* fixed spider and gst-typefind to use this, too.
* Other general cleanups
2003-10-01 13:11:45 +00:00

336 lines
8.1 KiB
C

/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* 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 "gstbytestream.h"
#include "gsttype.h"
#include "gstregistrypool.h"
#include "gstobject.h"
#include "gstinfo.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 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_CAT_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_CAT_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_CAT_DEBUG (GST_CAT_TYPES,"searching for '%s'",mime); */
mimelen = strlen (mime);
while (walk) {
type = (GstType *)walk->data;
search = type->mime;
/* GST_CAT_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;
}
GstCaps*
gst_type_type_find_dummy (GstByteStream *bs, gpointer priv)
{
GstCaps *res = NULL;
GstTypeFactory *factory = (GstTypeFactory *)priv;
GST_CAT_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 == gst_type_type_find_dummy) {
/* looks like we didn't get a real typefind function */
g_warning ("could not load valid typefind function for %s\n", factory->mime);
}
else if (factory->typefindfunc) {
res = factory->typefindfunc (bs, priv);
}
}
return res;
}