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