Merged the AUTOPLUG2 branch
[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 "gstplugin.h"
28
29
30 /* global list of registered elementfactories */
31 GList* _gst_elementfactories;
32
33 void
34 _gst_elementfactory_initialize (void)
35 {
36   _gst_elementfactories = NULL;
37 }
38
39 /**
40  * gst_elementfactory_destroy:
41  * @elementfactory: factory to destroy
42  *
43  * Removes the elementfactory from the global list.
44  */
45 void
46 gst_elementfactory_destroy (GstElementFactory *elementfactory)
47 {
48   g_return_if_fail (elementfactory != NULL);
49
50   _gst_elementfactories = g_list_remove (_gst_elementfactories, elementfactory);
51
52   // we don't free the struct bacause someone might  have a handle to it..
53 }
54
55 /**
56  * gst_elementfactory_find:
57  * @name: name of factory to find
58  *
59  * Search for an elementfactory of the given name.
60  *
61  * Returns: #GstElementFactory if found, NULL otherwise
62  */
63 GstElementFactory*
64 gst_elementfactory_find (const gchar *name)
65 {
66   GList *walk;
67   GstElementFactory *factory;
68
69   g_return_val_if_fail(name != NULL, NULL);
70
71   GST_DEBUG (0,"gstelementfactory: find \"%s\"\n", name);
72
73   walk = _gst_elementfactories;
74   while (walk) {
75     factory = (GstElementFactory *)(walk->data);
76     if (!strcmp(name,factory->name))
77       return factory;
78     walk = g_list_next(walk);
79   }
80
81   return NULL;
82 }
83
84 /**
85  * gst_elementfactory_get_list:
86  *
87  * Get the global list of elementfactories.
88  *
89  * Returns: GList of type #GstElementFactory
90  */
91 GList*
92 gst_elementfactory_get_list (void)
93 {
94   return _gst_elementfactories;
95 }
96
97
98 /**
99  * gst_elementfactory_new:
100  * @name: name of new elementfactory
101  * @type: GtkType of new element
102  * @details: #GstElementDetails structure with element details
103  *
104  * Create a new elementfactory capable of insantiating objects of the
105  * given type.
106  *
107  * Returns: new elementfactory
108  */
109 GstElementFactory*
110 gst_elementfactory_new (const gchar *name, GtkType type,
111                         GstElementDetails *details)
112 {
113   GstElementFactory *factory;
114
115   g_return_val_if_fail(name != NULL, NULL);
116
117   factory = g_new0(GstElementFactory, 1);
118
119   factory->name = g_strdup(name);
120   factory->type = type;
121   factory->details = details;
122   factory->padtemplates = NULL;
123   factory->numpadtemplates = 0;
124
125   _gst_elementfactories = g_list_prepend (_gst_elementfactories, factory);
126
127   return factory;
128 }
129
130 /**
131  * gst_elementfactory_create:
132  * @factory: factory to instantiate
133  * @name: name of new element
134  *
135  * Create a new element of the type defined by the given elementfactory.
136  * It wll be given the name supplied, since all elements require a name as
137  * their first argument.
138  *
139  * Returns: new #GstElement
140  */
141 GstElement *
142 gst_elementfactory_create (GstElementFactory *factory,
143                            const gchar *name)
144 {
145   GstElement *element;
146   GstElementClass *oclass;
147
148   g_return_val_if_fail(factory != NULL, NULL);
149   g_return_val_if_fail(name != NULL, NULL);
150
151   GST_DEBUG (0,"gstelementfactory: create \"%s\" \"%s\"\n", factory->name, name);
152
153   // it's not loaded, try to load the plugin
154   if (factory->type == 0) {
155     factory = gst_plugin_load_elementfactory(factory->name);
156   }
157   g_return_val_if_fail(factory != NULL, NULL);
158   g_return_val_if_fail(factory->type != 0, NULL);
159
160   // create an instance of the element
161   element = GST_ELEMENT(gtk_type_new(factory->type));
162   g_assert(element != NULL);
163   gst_object_ref(GST_OBJECT(element));
164
165   // attempt to set the elemenfactory class pointer if necessary
166   oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
167   if (oclass->elementfactory == NULL) {
168     GST_DEBUG (0,"gstelementfactory: class %s\n", factory->name);
169     oclass->elementfactory = factory;
170   }
171
172   gst_object_set_name (GST_OBJECT (element),name);
173
174   return element;
175 }
176
177 /**
178  * gst_elementfactory_make:
179  * @factoryname: a named factory to instantiate
180  * @name: name of new element
181  *
182  * Create a new element of the type defined by the given elementfactory.
183  * It wll be given the name supplied, since all elements require a name as
184  * their first argument.
185  *
186  * Returns: new #GstElement
187  */
188 GstElement*
189 gst_elementfactory_make (const gchar *factoryname, const gchar *name)
190 {
191   GstElementFactory *factory;
192   GstElement *element;
193
194   g_return_val_if_fail(factoryname != NULL, NULL);
195   g_return_val_if_fail(name != NULL, NULL);
196
197   GST_DEBUG (0,"gstelementfactory: make \"%s\" \"%s\"\n", factoryname, name);
198
199   //gst_plugin_load_elementfactory(factoryname);
200   factory = gst_elementfactory_find(factoryname);
201   if (factory == NULL) return NULL;
202   element = gst_elementfactory_create(factory,name);
203   return element;
204 }
205
206 /**
207  * gst_elementfactory_add_padtemplate :
208  * @elementfactory: factory to add the src id to
209  * @templ: the padtemplate to add
210  *
211  * Add the given padtemplate to this elementfactory.
212  */
213 void
214 gst_elementfactory_add_padtemplate (GstElementFactory *factory,
215                                     GstPadTemplate *templ)
216 {
217   g_return_if_fail(factory != NULL);
218   g_return_if_fail(templ != NULL);
219
220   factory->padtemplates = g_list_append (factory->padtemplates, templ);
221   factory->numpadtemplates++;
222 }
223
224 /**
225  * gst_elementfactory_can_src_caps_list :
226  * @factory: factory to query
227  * @caps: the caps list to check
228  *
229  * Checks if the factory can source the given capability list.
230  *
231  * Returns: true if it can src the capabilities
232  */
233 gboolean
234 gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
235                                       GList *caps)
236 {
237   GList *templates;
238
239   g_return_val_if_fail(factory != NULL, FALSE);
240   g_return_val_if_fail(caps != NULL, FALSE);
241
242   templates = factory->padtemplates;
243
244   while (templates) {
245     GstPadTemplate *template = (GstPadTemplate *)templates->data;
246
247     if (template->direction == GST_PAD_SRC) {
248       if (gst_caps_list_check_compatibility (template->caps, caps))
249         return TRUE;
250     }
251     templates = g_list_next (templates);
252   }
253
254   return FALSE;
255 }
256
257 /**
258  * gst_elementfactory_can_sink_caps_list :
259  * @factory: factory to query
260  * @caps: the caps list to check
261  *
262  * Checks if the factory can sink the given capability list.
263  *
264  * Returns: true if it can sink the capabilities
265  */
266 gboolean
267 gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
268                                        GList *caps)
269 {
270   GList *templates;
271
272   g_return_val_if_fail(factory != NULL, FALSE);
273   g_return_val_if_fail(caps != NULL, FALSE);
274
275   templates = factory->padtemplates;
276
277   while (templates) {
278     GstPadTemplate *template = (GstPadTemplate *)templates->data;
279
280     if (template->direction == GST_PAD_SINK) {
281       if (gst_caps_list_check_compatibility (caps, template->caps))
282         return TRUE;
283     }
284     templates = g_list_next (templates);
285   }
286
287   return FALSE;
288 }
289
290 /**
291  * gst_elementfactory_can_src_caps :
292  * @factory: factory to query
293  * @caps: the caps to check
294  *
295  * Checks if the factory can src the given capability.
296  *
297  * Returns: true if it can sink the capability
298  */
299 gboolean
300 gst_elementfactory_can_src_caps (GstElementFactory *factory,
301                                  GstCaps *caps)
302 {
303   GList *dummy;
304   gboolean ret;
305
306   dummy = g_list_prepend (NULL, caps);
307
308   ret = gst_elementfactory_can_src_caps_list (factory, dummy);
309
310   g_list_free (dummy);
311
312   return ret;
313 }
314
315 /**
316  * gst_elementfactory_can_sink_caps :
317  * @factory: factory to query
318  * @caps: the caps to check
319  *
320  * Checks if the factory can sink the given capability.
321  *
322  * Returns: true if it can sink the capability
323  */
324 gboolean
325 gst_elementfactory_can_sink_caps (GstElementFactory *factory,
326                                   GstCaps *caps)
327 {
328   GList *dummy;
329   gboolean ret;
330
331   dummy = g_list_prepend (NULL, caps);
332
333   ret = gst_elementfactory_can_sink_caps_list (factory, dummy);
334
335   g_list_free (dummy);
336
337   return ret;
338 }
339
340 /**
341  * gst_elementfactory_save_thyself:
342  * @factory: factory to save
343  * @parent: the parent xmlNodePtr
344  *
345  * Saves the factory into an XML tree.
346  *
347  * Returns: the new xmlNodePtr
348  */
349 xmlNodePtr
350 gst_elementfactory_save_thyself (GstElementFactory *factory,
351                                  xmlNodePtr parent)
352 {
353   GList *pads;
354
355   g_return_val_if_fail(factory != NULL, NULL);
356
357   xmlNewChild(parent,NULL,"name",factory->name);
358   xmlNewChild(parent,NULL,"longname", factory->details->longname);
359   xmlNewChild(parent,NULL,"class", factory->details->klass);
360   xmlNewChild(parent,NULL,"description", factory->details->description);
361   xmlNewChild(parent,NULL,"version", factory->details->version);
362   xmlNewChild(parent,NULL,"author", factory->details->author);
363   xmlNewChild(parent,NULL,"copyright", factory->details->copyright);
364
365   pads = factory->padtemplates;
366   if (pads) {
367     while (pads) {
368       xmlNodePtr subtree;
369       GstPadTemplate *padtemplate = (GstPadTemplate *)pads->data;
370
371       subtree = xmlNewChild(parent, NULL, "padtemplate", NULL);
372       gst_padtemplate_save_thyself(padtemplate, subtree);
373
374       pads = g_list_next (pads);
375     }
376   }
377   return parent;
378 }
379
380 /**
381  * gst_elementfactory_load_thyself:
382  * @parent: the parent xmlNodePtr
383  *
384  * Creates a new factory from an xmlNodePtr.
385  *
386  * Returns: the new factory
387  */
388 GstElementFactory *
389 gst_elementfactory_load_thyself (xmlNodePtr parent)
390 {
391   GstElementFactory *factory = g_new0(GstElementFactory, 1);
392   xmlNodePtr children = parent->xmlChildrenNode;
393   factory->details = g_new0(GstElementDetails, 1);
394   factory->padtemplates = NULL;
395
396   while (children) {
397     if (!strcmp(children->name, "name")) {
398       factory->name = xmlNodeGetContent(children);
399     }
400     if (!strcmp(children->name, "longname")) {
401       factory->details->longname = xmlNodeGetContent(children);
402     }
403     if (!strcmp(children->name, "class")) {
404       factory->details->klass = xmlNodeGetContent(children);
405     }
406     if (!strcmp(children->name, "description")) {
407       factory->details->description = xmlNodeGetContent(children);
408     }
409     if (!strcmp(children->name, "version")) {
410       factory->details->version = xmlNodeGetContent(children);
411     }
412     if (!strcmp(children->name, "author")) {
413       factory->details->author = xmlNodeGetContent(children);
414     }
415     if (!strcmp(children->name, "copyright")) {
416       factory->details->copyright = xmlNodeGetContent(children);
417     }
418     if (!strcmp(children->name, "padtemplate")) {
419        GstPadTemplate *template;
420
421        template = gst_padtemplate_load_thyself (children);
422
423        gst_elementfactory_add_padtemplate (factory, template);
424     }
425
426     children = children->next;
427   }
428
429   _gst_elementfactories = g_list_prepend (_gst_elementfactories, factory);
430
431   return factory;
432 }
433