remove
[platform/upstream/gstreamer.git] / gst / gsttypefindfactory.c
1 /* GStreamer
2  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  *
4  * gsttypefindfactory.c: typefinding subsystem
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /**
22  * SECTION:gsttypefindfactory
23  * @short_description: Information about registered typefind functions
24  *
25  * These functions allow querying informations about registered typefind 
26  * functions. How to create and register these functions is described in
27  * the section <link linkend="gstreamer-Writing-typefind-functions">
28  * "Writing typefind functions"</link>.
29  *
30  * <example>
31  *   <title>how to write a simple typefinder</title>
32  *   <programlisting>
33  *   typedef struct {
34  *     guint8 *data;
35  *     guint size;
36  *     guint probability;
37  *     GstCaps *data;
38  *   } MyTypeFind;
39  *   static void
40  *   my_peek (gpointer data, gint64 offset, guint size)
41  *   {
42  *     MyTypeFind *find = (MyTypeFind *) data;
43  *     if (offset &gt;= 0 &amp;&amp; offset + size &lt;= find->size) {
44  *       return find->data + offset;
45  *     }
46  *     return NULL;
47  *   }
48  *   static void
49  *   my_suggest (gpointer data, guint probability, GstCaps *caps)
50  *   {
51  *     MyTypeFind *find = (MyTypeFind *) data;
52  *     if (probability &gt; find->probability) {
53  *       find->probability = probability;
54  *       gst_caps_replace (&amp;find->caps, caps);
55  *     }
56  *   }
57  *   static GstCaps *
58  *   find_type (guint8 *data, guint size)
59  *   {
60  *     GList *walk, *type_list;
61  *     MyTypeFind find = {data, size, 0, NULL};
62  *     GstTypeFind gst_find = {my_peek, my_suggest, &amp;find, };
63  *     
64  *     walk = type_list = gst_type_find_factory_get_list ();
65  *     while (walk) {
66  *       GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
67  *       walk = g_list_next (walk)
68  *       gst_type_find_factory_call_function (factory, &amp;gst_find);
69  *     }
70  *     g_list_free (type_list);
71  *     return find.caps;
72  *   };
73  *   </programlisting>
74  * </example>
75  *
76  * The above example shows how to write a very simple typefinder that identifies
77  * the given data. You can get quite a bit more complicated than that though.
78  */
79
80 #include "gst_private.h"
81 #include "gstinfo.h"
82 #include "gsttypefind.h"
83 #include "gsttypefindfactory.h"
84 #include "gstregistry.h"
85
86 GST_DEBUG_CATEGORY (gst_type_find_debug);
87 #define GST_CAT_DEFAULT gst_type_find_debug
88
89 static void gst_type_find_factory_class_init (gpointer g_class,
90     gpointer class_data);
91 static void gst_type_find_factory_init (GTypeInstance * instance,
92     gpointer g_class);
93 static void gst_type_find_factory_dispose (GObject * object);
94
95 static void gst_type_find_load_plugin (GstTypeFind * find, gpointer data);
96
97 static GstPluginFeatureClass *parent_class = NULL;
98
99 GType
100 gst_type_find_factory_get_type (void)
101 {
102   static GType typefind_type = 0;
103
104   if (!typefind_type) {
105     static const GTypeInfo typefind_info = {
106       sizeof (GstTypeFindFactoryClass),
107       NULL,
108       NULL,
109       gst_type_find_factory_class_init,
110       NULL,
111       NULL,
112       sizeof (GstTypeFindFactory),
113       0,
114       gst_type_find_factory_init,
115       NULL
116     };
117
118     typefind_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
119         "GstTypeFindFactory", &typefind_info, 0);
120     GST_DEBUG_CATEGORY_INIT (gst_type_find_debug, "GST_TYPEFIND",
121         GST_DEBUG_FG_GREEN, "typefinding subsystem");
122   }
123
124   return typefind_type;
125 }
126 static void
127 gst_type_find_factory_class_init (gpointer g_class, gpointer class_data)
128 {
129   GObjectClass *object_class = G_OBJECT_CLASS (g_class);
130
131   parent_class = g_type_class_peek_parent (g_class);
132
133   object_class->dispose = gst_type_find_factory_dispose;
134 }
135 static void
136 gst_type_find_factory_init (GTypeInstance * instance, gpointer g_class)
137 {
138   GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (instance);
139
140   factory->user_data = factory;
141   factory->function = gst_type_find_load_plugin;
142 }
143 static void
144 gst_type_find_factory_dispose (GObject * object)
145 {
146   GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (object);
147
148   if (factory->caps) {
149     gst_caps_unref (factory->caps);
150     factory->caps = NULL;
151   }
152   if (factory->extensions) {
153     g_strfreev (factory->extensions);
154     factory->extensions = NULL;
155   }
156 }
157 static void
158 gst_type_find_load_plugin (GstTypeFind * find, gpointer data)
159 {
160   GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (data);
161
162   GST_DEBUG_OBJECT (factory, "need to load typefind function %s",
163       GST_PLUGIN_FEATURE_NAME (factory));
164
165   factory =
166       GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
167           (factory)));
168   if (factory) {
169     if (factory->function == gst_type_find_load_plugin) {
170       /* looks like we didn't get a real typefind function */
171       g_warning ("could not load valid typefind function for feature '%s'\n",
172           GST_PLUGIN_FEATURE_NAME (factory));
173     } else {
174       g_assert (factory->function);
175       gst_type_find_factory_call_function (factory, find);
176     }
177   }
178 }
179
180 /**
181  * gst_type_find_factory_get_list:
182  *
183  * Gets the list of all registered typefind factories. You must free the
184  * list using g_list_free.
185  * 
186  * Returns: the list of all registered typefind factories
187  */
188 GList *
189 gst_type_find_factory_get_list (void)
190 {
191   return gst_registry_get_feature_list (gst_registry_get_default (),
192       GST_TYPE_TYPE_FIND_FACTORY);
193 }
194
195 /**
196  * gst_type_find_factory_get_caps:
197  * @factory: a factory
198  * 
199  * Gets the caps associated with a typefind factory.
200  *
201  * Returns: the #GstCaps associated with this factory
202  */
203 const GstCaps *
204 gst_type_find_factory_get_caps (const GstTypeFindFactory * factory)
205 {
206   g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL);
207
208   return factory->caps;
209 }
210
211 /**
212  * gst_type_find_factory_get_extensions:
213  * @factory: a factory
214  * 
215  * Gets the extensions associated with a typefind factory. The returned
216  * array should not be changed. If you need to change stuff in it, you should
217  * copy it using g_stdupv().  This function may return NULL to indicate
218  * a 0-length list.
219  *
220  * Returns: a NULL-terminated array of extensions associated with this factory
221  */
222 gchar **
223 gst_type_find_factory_get_extensions (const GstTypeFindFactory * factory)
224 {
225   g_return_val_if_fail (GST_IS_TYPE_FIND_FACTORY (factory), NULL);
226
227   return factory->extensions;
228 }
229
230 /**
231  * gst_type_find_factory_call_function:
232  * @factory: a factory
233  * @find: a properly setup #GstTypeFind entry. The get_data and suggest_type
234  *        members must be set.
235  * 
236  * Calls the typefinding function associated with this factory.
237  */
238 void
239 gst_type_find_factory_call_function (const GstTypeFindFactory * factory,
240     GstTypeFind * find)
241 {
242   g_return_if_fail (GST_IS_TYPE_FIND_FACTORY (factory));
243   g_return_if_fail (find != NULL);
244   g_return_if_fail (find->peek != NULL);
245   g_return_if_fail (find->suggest != NULL);
246
247   /* should never happen */
248   g_assert (factory->function != NULL);
249
250   factory->function (find, factory->user_data);
251 }