- Removed unused locking from the cothreads
[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   GST_DEBUG (GST_CAT_ELEMENT_FACTORY,"creating element from factory \"%s\" with name \"%s\" and type %d", 
194              GST_OBJECT_NAME (factory), name, (gint) factory->type);
195
196   if (!gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory)))
197     return NULL;
198
199   if (factory->type == 0) {
200       g_critical ("Factory for `%s' has no type",
201                   GST_PLUGIN_FEATURE_NAME (factory));
202       return NULL;
203   }
204
205   /* create an instance of the element */
206   element = GST_ELEMENT(g_object_new(factory->type,NULL));
207   g_assert(element != NULL);
208
209   /* attempt to set the elemenfactory class pointer if necessary */
210   oclass = GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(element));
211   if (oclass->elementfactory == NULL) {
212     GST_DEBUG (GST_CAT_ELEMENT_FACTORY,"class %s", GST_OBJECT_NAME (factory));
213     oclass->elementfactory = factory;
214
215     /* copy pad template pointers to the element class, allow for custom padtemplates */
216     oclass->padtemplates = g_list_concat (oclass->padtemplates, 
217                     g_list_copy (factory->padtemplates));
218     oclass->numpadtemplates += factory->numpadtemplates;
219   }
220
221   gst_object_set_name (GST_OBJECT (element), name);
222
223   return element;
224 }
225
226 /**
227  * gst_element_factory_make:
228  * @factoryname: a named factory to instantiate
229  * @name: name of new element
230  *
231  * Create a new element of the type defined by the given element factory.
232  * If name is NULL, then the element will receive a guaranteed unique name,
233  * consisting of the element factory name and a number.
234  * If name is given, it will be given the name supplied.
235  *
236  * Returns: new #GstElement (or NULL if unable to create element)
237  */
238 GstElement*
239 gst_element_factory_make (const gchar *factoryname, const gchar *name)
240 {
241   GstElementFactory *factory;
242   GstElement *element;
243
244   g_return_val_if_fail (factoryname != NULL, NULL);
245
246   GST_DEBUG (GST_CAT_ELEMENT_FACTORY, "gstelementfactory: make \"%s\" \"%s\"", factoryname, name);
247
248   /* gst_plugin_load_element_factory(factoryname); */
249   factory = gst_element_factory_find(factoryname);
250   if (factory == NULL) {
251     GST_INFO (GST_CAT_ELEMENT_FACTORY,"no such elementfactory \"%s\"!",factoryname);
252     return NULL;
253   }
254   element = gst_element_factory_create (factory, name);
255   if (element == NULL) {
256     GST_INFO (GST_CAT_ELEMENT_FACTORY,"couldn't create instance of elementfactory \"%s\"!",factoryname);
257     return NULL;
258   }
259
260   return element;
261 }
262
263 /**
264  * gst_element_factory_make_or_warn:
265  * @factoryname: a named factory to instantiate
266  * @name: name of new element
267  *
268  * Create a new element of the type defined by the given element factory
269  * using #gst_element_factory_make.
270  * Will use g_warning if the element could not be created.
271  *
272  * Returns: new #GstElement (or NULL if unable to create element)
273  */
274 GstElement*
275 gst_element_factory_make_or_warn (const gchar *factoryname, const gchar *name)
276 {
277   GstElement *element = gst_element_factory_make (factoryname, name);
278
279   if (element == NULL) 
280     g_warning ("Could not create element from factory %s !\n", factoryname);
281
282   return element;
283 }
284     
285 /**
286  * gst_element_factory_add_pad_template :
287  * @elementfactory: factory to add the src id to
288  * @templ: the padtemplate to add
289  *
290  * Add the given padtemplate to this elementfactory.
291  */
292 void
293 gst_element_factory_add_pad_template (GstElementFactory *factory,
294                                     GstPadTemplate *templ)
295 {
296   GList *padtemplates;
297   
298   g_return_if_fail(factory != NULL);
299   g_return_if_fail(templ != NULL);
300
301   padtemplates = factory->padtemplates;
302
303   gst_object_ref (GST_OBJECT (templ));
304
305   while (padtemplates) {
306     GstPadTemplate *oldtempl = GST_PAD_TEMPLATE (padtemplates->data);
307     
308     if (!strcmp (oldtempl->name_template, templ->name_template)) {
309       gst_object_unref (GST_OBJECT (oldtempl));
310       padtemplates->data = templ;
311       return;
312     }
313     
314     padtemplates = g_list_next (padtemplates);
315   }
316   factory->padtemplates = g_list_append (factory->padtemplates, templ);
317   factory->numpadtemplates++;
318 }
319
320 /**
321  * gst_element_factory_can_src_caps :
322  * @factory: factory to query
323  * @caps: the caps to check
324  *
325  * Checks if the factory can source the given capability.
326  *
327  * Returns: true if it can src the capabilities
328  */
329 gboolean
330 gst_element_factory_can_src_caps (GstElementFactory *factory,
331                                  GstCaps *caps)
332 {
333   GList *templates;
334
335   g_return_val_if_fail(factory != NULL, FALSE);
336   g_return_val_if_fail(caps != NULL, FALSE);
337
338   templates = factory->padtemplates;
339
340   while (templates) {
341     GstPadTemplate *template = (GstPadTemplate *)templates->data;
342
343     if (template->direction == GST_PAD_SRC) {
344       if (gst_caps_check_compatibility (GST_PAD_TEMPLATE_CAPS (template), caps))
345         return TRUE;
346     }
347     templates = g_list_next (templates);
348   }
349
350   return FALSE;
351 }
352
353 /**
354  * gst_element_factory_can_sink_caps :
355  * @factory: factory to query
356  * @caps: the caps to check
357  *
358  * Checks if the factory can sink the given capability.
359  *
360  * Returns: true if it can sink the capabilities
361  */
362 gboolean
363 gst_element_factory_can_sink_caps (GstElementFactory *factory,
364                                   GstCaps *caps)
365 {
366   GList *templates;
367
368   g_return_val_if_fail(factory != NULL, FALSE);
369   g_return_val_if_fail(caps != NULL, FALSE);
370
371   templates = factory->padtemplates;
372
373   while (templates) {
374     GstPadTemplate *template = (GstPadTemplate *)templates->data;
375
376     if (template->direction == GST_PAD_SINK) {
377       if (gst_caps_check_compatibility (caps, GST_PAD_TEMPLATE_CAPS (template)))
378         return TRUE;
379     }
380     templates = g_list_next (templates);
381   }
382
383   return FALSE;
384 }
385
386 /**
387  * gst_element_factory_set_rank  :
388  * @factory: factory to rank
389  * @rank: rank value - higher number means more priority rank
390  *
391  * Specifies a rank for the element so that 
392  * autoplugging uses the most appropriate elements.
393  *
394  */
395 void
396 gst_element_factory_set_rank (GstElementFactory *factory, guint16 rank)
397 {
398   g_return_if_fail(factory != NULL);
399   factory->rank = rank;
400 }
401
402 static void
403 gst_element_factory_unload_thyself (GstPluginFeature *feature)
404 {
405   GstElementFactory *factory;
406
407   factory = GST_ELEMENT_FACTORY (feature);
408
409   factory->type = 0;
410 }