New typefind system: bytestream is now part of the core all plugins have been modifie...
[platform/upstream/gstreamer.git] / gst / gsttype.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gsttype.c: Media-type management functions
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /* TODO:
24  * probably should set up a hash table for the type id's, since currently
25  * it's a rather pathetic linear search.  Eventually there may be dozens
26  * of id's, but in reality there are only so many instances of lookup, so
27  * I'm not overly worried yet...
28  */
29
30 #include "gst_private.h"
31
32 #include "gstbytestream.h"
33 #include "gsttype.h"
34 #include "gstregistrypool.h"
35 #include "gstobject.h"
36 #include "gstinfo.h"
37
38
39 /* global list of registered types */
40 static GList *_gst_types;
41 static guint16 _gst_maxtype;
42
43 static void             gst_type_factory_class_init     (GstTypeFactoryClass *klass);
44 static void             gst_type_factory_init           (GstTypeFactory *factory);
45
46 static void             gst_type_factory_unload_thyself (GstPluginFeature *feature);
47
48 static GstPluginFeatureClass *parent_class = NULL;
49 /* static guint gst_type_factory_signals[LAST_SIGNAL] = { 0 }; */
50
51 GType
52 gst_type_factory_get_type (void)
53 {
54   static GType typefactory_type = 0;
55
56   if (!typefactory_type) {
57     static const GTypeInfo typefactory_info = {
58       sizeof (GstTypeFactoryClass),
59       NULL,
60       NULL,
61       (GClassInitFunc) gst_type_factory_class_init,
62       NULL,
63       NULL,
64       sizeof(GstTypeFactory),
65       0,
66       (GInstanceInitFunc) gst_type_factory_init,
67       NULL
68     };
69     typefactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
70                                                "GstTypeFactory", &typefactory_info, 0);
71   }
72   return typefactory_type;
73 }
74
75 static void
76 gst_type_factory_class_init (GstTypeFactoryClass *klass)
77 {
78   GObjectClass *gobject_class;
79   GstObjectClass *gstobject_class;
80   GstPluginFeatureClass *gstpluginfeature_class;
81
82   gobject_class = (GObjectClass*)klass;
83   gstobject_class = (GstObjectClass*)klass;
84   gstpluginfeature_class = (GstPluginFeatureClass*) klass;
85
86   parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
87
88   gstpluginfeature_class->unload_thyself = GST_DEBUG_FUNCPTR (gst_type_factory_unload_thyself);
89
90   _gst_types = NULL;
91   _gst_maxtype = 1;             /* type 0 is undefined */
92
93 }
94
95 static void
96 gst_type_factory_init (GstTypeFactory *factory)
97 {
98 }
99
100 /**
101  * gst_type_factory_new:
102  * @definition: the definition to use
103  *
104  * Creata a new typefactory from the given definition.
105  *
106  * Returns: the new typefactory
107  */
108 GstTypeFactory* 
109 gst_type_factory_new (GstTypeDefinition *definition)
110 {
111   GstTypeFactory *factory;
112
113   g_return_val_if_fail (definition != NULL, NULL);
114   g_return_val_if_fail (definition->name != NULL, NULL);
115   g_return_val_if_fail (definition->mime != NULL, NULL);
116
117   factory = gst_type_factory_find (definition->name);
118
119   if (!factory) {
120     factory = GST_TYPE_FACTORY (g_object_new (GST_TYPE_TYPE_FACTORY, NULL));
121   }
122
123
124   GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (definition->name);
125   factory->mime = g_strdup (definition->mime);
126   factory->exts = g_strdup (definition->exts);
127   factory->typefindfunc = definition->typefindfunc;
128
129   return factory;
130 }
131
132 /**
133  * gst_type_register:
134  * @factory: the type factory to register
135  *
136  * Register a new type factory to the system.
137  *
138  * Returns: the new type id
139  */
140 guint16
141 gst_type_register (GstTypeFactory *factory)
142 {
143   guint16 id;
144   GstType *type;
145
146   g_return_val_if_fail (factory != NULL, 0);
147
148 /*  GST_CAT_INFO (GST_CAT_TYPES,"type register %s", factory->mime); */
149   id = gst_type_find_by_mime (factory->mime);
150
151   if (!id) {
152     type = g_new0 (GstType, 1);
153
154     type->id =          _gst_maxtype++;
155     type->mime =        factory->mime;
156     type->exts =        factory->exts;
157     type->factories =   NULL;
158     _gst_types =        g_list_prepend (_gst_types, type);
159
160     id = type->id;
161
162   } else {
163     type = gst_type_find_by_id (id);
164     /* now we want to try to merge the types and return the original */
165
166     /* FIXME: do extension merging here, not that easy */
167
168     /* if there is no existing typefind function, try to use new one  */
169   }
170   GST_CAT_DEBUG (GST_CAT_TYPES,"gsttype: %s(%p) gave new mime type '%s', id %d", 
171                     GST_OBJECT_NAME (factory), factory, type->mime, type->id);
172   type->factories = g_slist_prepend (type->factories, factory);
173
174   return id;
175 }
176
177 static guint16 
178 gst_type_find_by_mime_func (const gchar *mime)
179 {
180   GList *walk;
181   GstType *type;
182   gint typelen,mimelen;
183   gchar *search, *found;
184
185   g_return_val_if_fail (mime != NULL, 0);
186
187   walk = _gst_types;
188 /*  GST_CAT_DEBUG (GST_CAT_TYPES,"searching for '%s'",mime); */
189   mimelen = strlen (mime);
190   while (walk) {
191     type = (GstType *)walk->data;
192     search = type->mime;
193 /*    GST_CAT_DEBUG (GST_CAT_TYPES,"checking against '%s'",search); */
194     typelen = strlen (search);
195     while ((search - type->mime) < typelen) {
196       found = strstr (search, mime);
197       /* if the requested mime is in the list */
198       if (found) {
199         if ((*(found + mimelen) == ' ') ||
200             (*(found + mimelen) == ',') ||
201             (*(found + mimelen) == '\0')) {
202           return type->id;
203         } else {
204           search = found + mimelen;
205         }
206       } else
207         search += mimelen;
208     }
209     walk = g_list_next (walk);
210   }
211
212   return 0;
213 }
214
215 /**
216  * gst_type_find_by_mime:
217  * @mime: the mime type to find
218  *
219  * Find the type id of a given mime type.
220  *
221  * Returns: the type id
222  */
223 guint16
224 gst_type_find_by_mime (const gchar *mime)
225 {
226   return gst_type_find_by_mime_func (mime);
227 }
228
229 /**
230  * gst_type_find_by_ext:
231  * @ext: the extension to find
232  *
233  * Find the type id of a given extention.
234  *
235  * Returns: the type id
236  */
237 guint16
238 gst_type_find_by_ext (const gchar *ext)
239 {
240   /* FIXME */
241   g_warning ("gsttype: find_by_ext not implemented");
242   return 0;
243 }
244
245 /**
246  * gst_type_find_by_id:
247  * @id: the type id to lookup
248  *
249  * Find the type of a given type id.
250  *
251  * Returns: the type
252  */
253 GstType*
254 gst_type_find_by_id (guint16 id)
255 {
256   GList *walk = _gst_types;
257   GstType *type;
258
259   while (walk) {
260     type = (GstType *)walk->data;
261     if (type->id == id)
262       return type;
263     walk = g_list_next (walk);
264   }
265
266   return NULL;
267 }
268
269 /**
270  * gst_type_get_list:
271  *
272  * Return a list of all registered types.
273  *
274  * Returns: a list of GstTypes
275  */
276 const GList*
277 gst_type_get_list (void)
278 {
279   return _gst_types;
280 }
281
282 /**
283  * gst_type_factory_find:
284  * @name: the name of the typefactory to find
285  *
286  * Return the TypeFactory with the given name. 
287  *
288  * Returns: a GstTypeFactory with the given name;
289  */
290 GstTypeFactory*
291 gst_type_factory_find (const gchar *name)
292 {
293   GstPluginFeature *feature;
294
295   g_return_val_if_fail (name != NULL, NULL);
296
297   feature = gst_registry_pool_find_feature (name, GST_TYPE_TYPE_FACTORY);
298   if (feature)
299     return GST_TYPE_FACTORY (feature);
300
301   return NULL;
302 }
303
304 static void
305 gst_type_factory_unload_thyself (GstPluginFeature *feature)
306 {
307   GstTypeFactory *factory;
308
309   g_return_if_fail (GST_IS_TYPE_FACTORY (feature));
310
311   factory = GST_TYPE_FACTORY (feature);
312
313   if (factory->typefindfunc)
314     factory->typefindfunc = gst_type_type_find_dummy;
315 }
316
317 GstCaps*
318 gst_type_type_find_dummy (GstByteStream *bs, gpointer priv)
319 {
320   GstCaps *res = NULL;
321   GstTypeFactory *factory = (GstTypeFactory *)priv;
322
323   GST_CAT_DEBUG (GST_CAT_TYPES,"gsttype: need to load typefind function for %s", factory->mime);
324
325   if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
326     if (factory->typefindfunc == gst_type_type_find_dummy) {
327       /* looks like we didn't get a real typefind function */
328       g_warning ("could not load valid typefind function for %s\n", factory->mime);
329     }
330     else if (factory->typefindfunc) {
331       res = factory->typefindfunc (bs, priv);
332     }
333   }
334
335   return res;
336 }