2000-12-28 22:12:02 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
|
|
|
* 2000 Wim Taymans <wtay@chello.be>
|
|
|
|
*
|
|
|
|
* gsttype.c: Media-type management functions
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
|
|
|
* 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...
|
|
|
|
*/
|
|
|
|
|
2000-12-28 22:12:02 +00:00
|
|
|
#include "gst_private.h"
|
|
|
|
|
2000-12-15 01:57:34 +00:00
|
|
|
#include "gsttype.h"
|
|
|
|
#include "gstplugin.h"
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2000-12-28 22:12:02 +00:00
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
/* global list of registered types */
|
|
|
|
GList *_gst_types;
|
|
|
|
guint16 _gst_maxtype;
|
|
|
|
|
2000-12-11 00:04:25 +00:00
|
|
|
struct _GstTypeFindInfo {
|
|
|
|
GstTypeFindFunc typefindfunc; /* typefind function */
|
|
|
|
|
|
|
|
GstPlugin *plugin; /* the plugin with this typefind function */
|
|
|
|
};
|
|
|
|
|
2000-12-17 16:24:14 +00:00
|
|
|
static GstCaps* gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv);
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
void
|
|
|
|
_gst_type_initialize (void)
|
|
|
|
{
|
2000-01-30 09:03:00 +00:00
|
|
|
_gst_types = NULL;
|
|
|
|
_gst_maxtype = 1; /* type 0 is undefined */
|
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2000-01-30 09:03:00 +00:00
|
|
|
guint16 id;
|
|
|
|
GstType *type;
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
g_return_val_if_fail (factory != NULL, 0);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2001-01-01 03:14:40 +00:00
|
|
|
// GST_INFO (GST_CAT_TYPES,"type register %s", factory->mime);
|
2000-11-11 15:13:50 +00:00
|
|
|
id = gst_type_find_by_mime (factory->mime);
|
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
if (!id) {
|
2000-11-11 15:13:50 +00:00
|
|
|
type = g_new0 (GstType, 1);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
type->id = _gst_maxtype++;
|
|
|
|
type->mime = factory->mime;
|
|
|
|
type->exts = factory->exts;
|
|
|
|
_gst_types = g_list_prepend (_gst_types, type);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
|
|
|
id = type->id;
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
} else {
|
2000-11-11 15:13:50 +00:00
|
|
|
type = gst_type_find_by_id (id);
|
2000-01-30 09:03:00 +00:00
|
|
|
/* 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 */
|
2000-12-15 16:43:26 +00:00
|
|
|
}
|
|
|
|
if (factory->typefindfunc) {
|
|
|
|
type->typefindfuncs = g_slist_prepend (type->typefindfuncs, factory->typefindfunc);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
static
|
|
|
|
guint16 gst_type_find_by_mime_func (gchar *mime)
|
|
|
|
{
|
2000-08-28 20:20:55 +00:00
|
|
|
GList *walk;
|
2000-01-30 09:03:00 +00:00
|
|
|
GstType *type;
|
|
|
|
gint typelen,mimelen;
|
|
|
|
gchar *search, *found;
|
|
|
|
|
2000-12-12 19:29:43 +00:00
|
|
|
g_return_val_if_fail (mime != NULL, 0);
|
|
|
|
|
2000-08-28 20:20:55 +00:00
|
|
|
walk = _gst_types;
|
2001-01-01 03:14:40 +00:00
|
|
|
// GST_DEBUG (0,"searching for '%s'\n",mime);
|
2000-11-11 15:13:50 +00:00
|
|
|
mimelen = strlen (mime);
|
2000-01-30 09:03:00 +00:00
|
|
|
while (walk) {
|
|
|
|
type = (GstType *)walk->data;
|
|
|
|
search = type->mime;
|
2001-01-01 03:14:40 +00:00
|
|
|
// GST_DEBUG (0,"checking against '%s'\n",search);
|
2000-11-11 15:13:50 +00:00
|
|
|
typelen = strlen (search);
|
2000-01-30 09:03:00 +00:00
|
|
|
while ((search - type->mime) < typelen) {
|
2000-11-11 15:13:50 +00:00
|
|
|
found = strstr (search, mime);
|
2000-01-30 09:03:00 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2000-11-11 15:13:50 +00:00
|
|
|
walk = g_list_next (walk);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* 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 (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 (gchar *ext)
|
|
|
|
{
|
|
|
|
//FIXME
|
|
|
|
g_warning ("gsttype: find_by_ext not implemented");
|
|
|
|
return 0;
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2000-01-30 09:03:00 +00:00
|
|
|
GList *walk = _gst_types;
|
|
|
|
GstType *type;
|
|
|
|
|
|
|
|
while (walk) {
|
|
|
|
type = (GstType *)walk->data;
|
|
|
|
if (type->id == id)
|
|
|
|
return type;
|
2000-11-11 15:13:50 +00:00
|
|
|
walk = g_list_next (walk);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* gst_type_get_list:
|
|
|
|
*
|
|
|
|
* return a list of all registered types
|
|
|
|
*
|
|
|
|
* Returns: a list of GstTypes
|
|
|
|
*/
|
|
|
|
GList*
|
|
|
|
gst_type_get_list (void)
|
|
|
|
{
|
2000-01-30 09:03:00 +00:00
|
|
|
return _gst_types;
|
|
|
|
}
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
2000-08-28 20:20:55 +00:00
|
|
|
if (factory->exts) {
|
2000-11-11 15:13:50 +00:00
|
|
|
xmlNewChild (parent, NULL, "extensions", factory->exts);
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
|
|
|
if (factory->typefindfunc) {
|
2000-11-11 15:13:50 +00:00
|
|
|
xmlNewChild (parent, NULL, "typefind", NULL);
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
2000-12-17 16:24:14 +00:00
|
|
|
static GstCaps *
|
2000-11-11 15:13:50 +00:00
|
|
|
gst_type_typefind_dummy (GstBuffer *buffer, gpointer priv)
|
2000-08-28 20:20:55 +00:00
|
|
|
{
|
|
|
|
GstType *type = (GstType *)priv;
|
|
|
|
guint16 typeid;
|
2000-12-15 16:43:26 +00:00
|
|
|
GSList *funcs;
|
|
|
|
|
2001-01-01 03:14:40 +00:00
|
|
|
GST_DEBUG (0,"gsttype: need to load typefind function for %s\n", type->mime);
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-12-11 00:04:25 +00:00
|
|
|
type->typefindfuncs = NULL;
|
2000-11-11 15:13:50 +00:00
|
|
|
gst_plugin_load_typefactory (type->mime);
|
|
|
|
typeid = gst_type_find_by_mime (type->mime);
|
|
|
|
type = gst_type_find_by_id (typeid);
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-12-15 16:43:26 +00:00
|
|
|
funcs = type->typefindfuncs;
|
|
|
|
|
|
|
|
while (funcs) {
|
|
|
|
GstTypeFindFunc func = (GstTypeFindFunc) funcs->data;
|
|
|
|
|
|
|
|
if (func) {
|
2000-12-17 16:24:14 +00:00
|
|
|
GstCaps *res = func (buffer, type);
|
|
|
|
if (res) return res;
|
2000-12-15 16:43:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
funcs = g_slist_next (funcs);
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
{
|
2000-08-28 20:20:55 +00:00
|
|
|
|
2000-11-11 15:13:50 +00:00
|
|
|
GstTypeFactory *factory = g_new0 (GstTypeFactory, 1);
|
2000-08-28 20:20:55 +00:00
|
|
|
xmlNodePtr field = parent->childs;
|
|
|
|
factory->typefindfunc = NULL;
|
|
|
|
|
|
|
|
while (field) {
|
2000-11-11 15:13:50 +00:00
|
|
|
if (!strcmp (field->name, "mime")) {
|
|
|
|
factory->mime = g_strdup (xmlNodeGetContent (field));
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
2000-11-11 15:13:50 +00:00
|
|
|
else if (!strcmp (field->name, "extensions")) {
|
|
|
|
factory->exts = g_strdup (xmlNodeGetContent (field));
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
2000-11-11 15:13:50 +00:00
|
|
|
else if (!strcmp (field->name, "typefind")) {
|
2000-12-15 16:43:26 +00:00
|
|
|
factory->typefindfunc = gst_type_typefind_dummy;
|
2000-08-28 20:20:55 +00:00
|
|
|
}
|
|
|
|
field = field->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return factory;
|
|
|
|
}
|
|
|
|
|