gstreamer/gst/gsttype.c

289 lines
6.5 KiB
C
Raw Normal View History

/* 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 "gsttype.h"
#include "gstplugin.h"
/* global list of registered types */
GList *_gst_types;
guint16 _gst_maxtype;
struct _GstTypeFindInfo {
GstTypeFindFunc typefindfunc; /* typefind function */
GstPlugin *plugin; /* the plugin with this typefind function */
};
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
void
_gst_type_initialize (void)
{
_gst_types = NULL;
_gst_maxtype = 1; /* type 0 is undefined */
}
/**
* 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;
_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 */
}
if (factory->typefindfunc) {
type->typefindfuncs = g_slist_prepend (type->typefindfuncs, factory->typefindfunc);
}
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 (0,"searching for '%s'\n",mime);
mimelen = strlen (mime);
while (walk) {
type = (GstType *)walk->data;
search = type->mime;
// GST_DEBUG (0,"checking against '%s'\n",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
*/
GList*
gst_type_get_list (void)
{
return _gst_types;
}
/**
* gst_typefactory_save_thyself:
* @factory: the type factory to save
* @parent: the parent node to save into
*
* Save a typefactory into an XML representation.
*
* Returns: the new xmlNodePtr
*/
xmlNodePtr
gst_typefactory_save_thyself (GstTypeFactory *factory, xmlNodePtr parent)
{
xmlNewChild (parent, NULL, "mime", factory->mime);
if (factory->exts) {
xmlNewChild (parent, NULL, "extensions", factory->exts);
}
if (factory->typefindfunc) {
xmlNewChild (parent, NULL, "typefind", NULL);
}
return parent;
}
static GstCaps *
gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
{
GstType *type = (GstType *)priv;
guint16 typeid;
GSList *funcs;
GST_DEBUG (0,"gsttype: need to load typefind function for %s\n", type->mime);
type->typefindfuncs = NULL;
gst_plugin_load_typefactory (type->mime);
typeid = gst_type_find_by_mime (type->mime);
type = gst_type_find_by_id (typeid);
funcs = type->typefindfuncs;
while (funcs) {
GstTypeFindFunc func = (GstTypeFindFunc) funcs->data;
if (func) {
GstCaps *res = func (buffer, type);
if (res) return res;
}
funcs = g_slist_next (funcs);
}
return FALSE;
}
/**
* gst_typefactory_load_thyself:
* @parent: the parent node to load from
*
* Load a typefactory from an XML representation.
*
* Returns: the new typefactory
*/
GstTypeFactory*
gst_typefactory_load_thyself (xmlNodePtr parent)
{
GstTypeFactory *factory = g_new0 (GstTypeFactory, 1);
xmlNodePtr field = parent->xmlChildrenNode;
factory->typefindfunc = NULL;
while (field) {
if (!strcmp (field->name, "mime")) {
factory->mime = xmlNodeGetContent (field);
}
else if (!strcmp (field->name, "extensions")) {
factory->exts = xmlNodeGetContent (field);
}
else if (!strcmp (field->name, "typefind")) {
factory->typefindfunc = gst_type_typefind_dummy;
}
field = field->next;
}
return factory;
}