3884049454a2396bcfa1c4607ea3dd49990c0f09
[platform/upstream/gstreamer.git] / gst / gstelementfactory.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstelementfactory.c: GstElementFactory object, support routines
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 /* #define DEBUG_ENABLED */
24 #include "gst_private.h"
25
26 #include "gstelement.h"
27 #include "gstregistry.h"
28 #include "gstlog.h"
29
30 static void             gst_element_factory_class_init          (GstElementFactoryClass *klass);
31 static void             gst_element_factory_init                (GstElementFactory *factory);
32
33 static void             gst_element_factory_unload_thyself      (GstPluginFeature *feature);
34
35 static GstPluginFeatureClass *parent_class = NULL;
36 /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */
37
38 GType 
39 gst_element_factory_get_type (void) 
40 {
41   static GType elementfactory_type = 0;
42
43   if (!elementfactory_type) {
44     static const GTypeInfo elementfactory_info = {
45       sizeof (GstElementFactoryClass),
46       NULL,
47       NULL,
48       (GClassInitFunc) gst_element_factory_class_init,
49       NULL,
50       NULL,
51       sizeof(GstElementFactory),
52       0,
53       (GInstanceInitFunc) gst_element_factory_init,
54       NULL
55     };
56     elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, 
57                                                   "GstElementFactory", &elementfactory_info, 0);
58   }
59   return elementfactory_type;
60 }
61
62 static void
63 gst_element_factory_class_init (GstElementFactoryClass *klass)
64 {
65   GObjectClass *gobject_class;
66   GstObjectClass *gstobject_class;
67   GstPluginFeatureClass *gstpluginfeature_class;
68
69   gobject_class = (GObjectClass*)klass;
70   gstobject_class = (GstObjectClass*)klass;
71   gstpluginfeature_class = (GstPluginFeatureClass*) klass;
72
73   parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
74
75   gstpluginfeature_class->unload_thyself =      GST_DEBUG_FUNCPTR (gst_element_factory_unload_thyself);
76
77 }
78
79 static void
80 gst_element_factory_init (GstElementFactory *factory)
81 {
82   factory->padtemplates = NULL;
83   factory->numpadtemplates = 0;
84 }
85
86 /**
87  * gst_element_factory_find:
88  * @name: name of factory to find
89  *
90  * Search for an element factory of the given name.
91  *
92  * Returns: #GstElementFactory if found, NULL otherwise
93  */
94 GstElementFactory*
95 gst_element_factory_find (const gchar *name)
96 {
97   GstPluginFeature *feature;
98
99   g_return_val_if_fail(name != NULL, NULL);
100
101   feature = gst_registry_pool_find_feature (name, GST_TYPE_ELEMENT_FACTORY);
102   if (feature)
103     return GST_ELEMENT_FACTORY (feature);
104
105   /* this should be an ERROR */
106   GST_DEBUG (GST_CAT_ELEMENT_FACTORY,"no such elementfactory \"%s\"", name);
107   return NULL;
108 }
109
110 static void
111 gst_element_details_free (GstElementDetails *dp)
112 {
113   g_return_if_fail (dp);
114
115   if (dp->longname)
116     g_free (dp->longname);
117   if (dp->klass)
118     g_free (dp->klass);
119   if (dp->description)
120     g_free (dp->description);
121   if (dp->version)
122     g_free (dp->version);
123   if (dp->author)
124     g_free (dp->author);
125   if (dp->copyright)
126     g_free (dp->copyright);
127   g_free (dp);
128 }
129
130 /**
131  * gst_element_factory_new:
132  * @name: name of new elementfactory
133  * @type: GType of new element
134  * @details: #GstElementDetails structure with element details
135  *
136  * Create a new elementfactory capable of insantiating objects of the
137  * given type.
138  *
139  * Returns: new elementfactory
140  */
141 GstElementFactory*
142 gst_element_factory_new (const gchar *name, GType type,
143                         GstElementDetails *details)
144 {
145   GstElementFactory *factory;
146
147   g_return_val_if_fail (name != NULL, NULL);
148   g_return_val_if_fail (type, NULL);
149   g_return_val_if_fail (details, NULL);
150
151   factory = gst_element_factory_find (name);
152
153   if (!factory)
154     factory = GST_ELEMENT_FACTORY (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL));
155
156   if (factory->details_dynamic) {
157     gst_element_details_free (factory->details);
158     factory->details_dynamic = FALSE;
159   }
160
161   factory->details = details;
162
163   if (!factory->type)
164     factory->type = type;
165   else if (factory->type != type)
166     g_critical ("`%s' requested type change (!)", name);
167
168   GST_PLUGIN_FEATURE (factory)->name = g_strdup (name);
169
170   return factory;
171 }
172
173 /**
174  * gst_element_factory_create:
175  * @factory: factory to instantiate
176  * @name: name of new element
177  *
178  * Create a new element of the type defined by the given elementfactory.
179  * It will be given the name supplied, since all elements require a name as
180  * their first argument.
181  *
182  * Returns: new #GstElement
183  */
184 GstElement *
185 gst_element_factory_create (GstElementFactory *factory,
186                            const gchar *name)
187 {
188   GstElement *element;
189   GstElementClass *oclass;
190
191   g_return_val_if_fail (factory != NULL, NULL);
192
193   if (!gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory)))
194     return NULL;
195
196   GST_DEBUG (GST_CAT_ELEMENT_FACTORY,
197              "creating element from factory \"%s\" (name \"%s\", type %d)", 
198              GST_OBJECT_NAME (factory), name, (gint) factory->type);
199
200   if (factory->type == 0) {
201       g_critical ("Factory for `%s' has no type",
202                   GST_PLUGIN_FEATURE_NAME (factory));
203       return NULL;
204   }
205
206   /* create an instance of the element */
207   element = GST_ELEMENT (g_object_new (factory->type, NULL));
208   g_assert (element != NULL);
209
210   /* attempt to set the elemenfactory class pointer if necessary */
211   oclass = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
212   if (oclass->elementfactory == NULL) {
213     GST_DEBUG (GST_CAT_ELEMENT_FACTORY, "class %s", GST_OBJECT_NAME (factory));
214     oclass->elementfactory = factory;
215
216     /* copy pad template pointers to the element class, 
217      * allow for custom padtemplates */
218     oclass->padtemplates = g_list_concat (oclass->padtemplates, 
219                     g_list_copy (factory->padtemplates));
220     oclass->numpadtemplates += factory->numpadtemplates;
221   }
222
223   gst_object_set_name (GST_OBJECT (element), name);
224
225   return element;
226 }
227
228 /**
229  * gst_element_factory_make:
230  * @factoryname: a named factory to instantiate
231  * @name: name of new element
232  *
233  * Create a new element of the type defined by the given element factory.
234  * If name is NULL, then the element will receive a guaranteed unique name,
235  * consisting of the element factory name and a number.
236  * If name is given, it will be given the name supplied.
237  *
238  * Returns: new #GstElement (or NULL if unable to create element)
239  */
240 GstElement*
241 gst_element_factory_make (const gchar *factoryname, const gchar *name)
242 {
243   GstElementFactory *factory;
244   GstElement *element;
245
246   g_return_val_if_fail (factoryname != NULL, NULL);
247
248   GST_DEBUG (GST_CAT_ELEMENT_FACTORY, "gstelementfactory: make \"%s\" \"%s\"", 
249              factoryname, name);
250
251   /* gst_plugin_load_element_factory (factoryname); */
252   factory = gst_element_factory_find (factoryname);
253   if (factory == NULL) {
254     GST_INFO (GST_CAT_ELEMENT_FACTORY,"no such element factory \"%s\"!",
255               factoryname);
256     return NULL;
257   }
258   element = gst_element_factory_create (factory, name);
259   if (element == NULL) {
260     GST_INFO (GST_CAT_ELEMENT_FACTORY,
261               "couldn't create instance of element factory \"%s\"!",
262               factoryname);
263     return NULL;
264   }
265
266   return element;
267 }
268
269 /**
270  * gst_element_factory_make_or_warn:
271  * @factoryname: a named factory to instantiate
272  * @name: name of new element
273  *
274  * Create a new element of the type defined by the given element factory
275  * using #gst_element_factory_make.
276  * Will use g_warning if the element could not be created.
277  *
278  * Returns: new #GstElement (or NULL if unable to create element)
279  */
280 GstElement*
281 gst_element_factory_make_or_warn (const gchar *factoryname, const gchar *name)
282 {
283   GstElement *element = gst_element_factory_make (factoryname, name);
284
285   if (element == NULL) 
286     g_warning ("Could not create element from factory %s !\n", factoryname);
287
288   return element;
289 }
290     
291 /**
292  * gst_element_factory_add_pad_template :
293  * @elementfactory: factory to add the src id to
294  * @templ: the padtemplate to add
295  *
296  * Add the given padtemplate to this elementfactory.
297  */
298 void
299 gst_element_factory_add_pad_template (GstElementFactory *factory,
300                                     GstPadTemplate *templ)
301 {
302   GList *padtemplates;
303   
304   g_return_if_fail(factory != NULL);
305   g_return_if_fail(templ != NULL);
306
307   padtemplates = factory->padtemplates;
308
309   gst_object_ref (GST_OBJECT (templ));
310
311   while (padtemplates) {
312     GstPadTemplate *oldtempl = GST_PAD_TEMPLATE (padtemplates->data);
313     
314     if (!strcmp (oldtempl->name_template, templ->name_template)) {
315       gst_object_unref (GST_OBJECT (oldtempl));
316       padtemplates->data = templ;
317       return;
318     }
319     
320     padtemplates = g_list_next (padtemplates);
321   }
322   factory->padtemplates = g_list_append (factory->padtemplates, templ);
323   factory->numpadtemplates++;
324 }
325
326 /**
327  * gst_element_factory_can_src_caps :
328  * @factory: factory to query
329  * @caps: the caps to check
330  *
331  * Checks if the factory can source the given capability.
332  *
333  * Returns: true if it can src the capabilities
334  */
335 gboolean
336 gst_element_factory_can_src_caps (GstElementFactory *factory,
337                                  GstCaps *caps)
338 {
339   GList *templates;
340
341   g_return_val_if_fail(factory != NULL, FALSE);
342   g_return_val_if_fail(caps != NULL, FALSE);
343
344   templates = factory->padtemplates;
345
346   while (templates) {
347     GstPadTemplate *template = (GstPadTemplate *)templates->data;
348
349     if (template->direction == GST_PAD_SRC) {
350       if (gst_caps_check_compatibility (GST_PAD_TEMPLATE_CAPS (template), caps))
351         return TRUE;
352     }
353     templates = g_list_next (templates);
354   }
355
356   return FALSE;
357 }
358
359 /**
360  * gst_element_factory_can_sink_caps :
361  * @factory: factory to query
362  * @caps: the caps to check
363  *
364  * Checks if the factory can sink the given capability.
365  *
366  * Returns: true if it can sink the capabilities
367  */
368 gboolean
369 gst_element_factory_can_sink_caps (GstElementFactory *factory,
370                                   GstCaps *caps)
371 {
372   GList *templates;
373
374   g_return_val_if_fail(factory != NULL, FALSE);
375   g_return_val_if_fail(caps != NULL, FALSE);
376
377   templates = factory->padtemplates;
378
379   while (templates) {
380     GstPadTemplate *template = (GstPadTemplate *)templates->data;
381
382     if (template->direction == GST_PAD_SINK) {
383       if (gst_caps_check_compatibility (caps, GST_PAD_TEMPLATE_CAPS (template)))
384         return TRUE;
385     }
386     templates = g_list_next (templates);
387   }
388
389   return FALSE;
390 }
391
392 /**
393  * gst_element_factory_set_rank  :
394  * @factory: factory to rank
395  * @rank: rank value - higher number means more priority rank
396  *
397  * Specifies a rank for the element so that 
398  * autoplugging uses the most appropriate elements.
399  *
400  */
401 void
402 gst_element_factory_set_rank (GstElementFactory *factory, guint16 rank)
403 {
404   g_return_if_fail(factory != NULL);
405   factory->rank = rank;
406 }
407
408 static void
409 gst_element_factory_unload_thyself (GstPluginFeature *feature)
410 {
411   GstElementFactory *factory;
412
413   factory = GST_ELEMENT_FACTORY (feature);
414
415   factory->type = 0;
416 }