This is a megapatch with the following changes:
[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 = g_new0(GstElementFactory, 1);
114
115   g_return_val_if_fail(name != NULL, NULL);
116
117   factory->name = g_strdup(name);
118   factory->type = type;
119   factory->details = details;
120   factory->padtemplates = NULL;
121   factory->numpadtemplates = 0;
122
123   _gst_elementfactories = g_list_prepend (_gst_elementfactories, factory);
124
125   return factory;
126 }
127
128 /**
129  * gst_elementfactory_create:
130  * @factory: factory to instantiate
131  * @name: name of new element
132  *
133  * Create a new element of the type defined by the given elementfactory.
134  * It wll be given the name supplied, since all elements require a name as
135  * their first argument.
136  *
137  * Returns: new #GstElement
138  */
139 GstElement *
140 gst_elementfactory_create (GstElementFactory *factory,
141                            const gchar *name) 
142 {
143   GstElement *element;
144   GstElementClass *oclass;
145
146   g_return_val_if_fail(factory != NULL, NULL);
147   g_return_val_if_fail(name != NULL, NULL);
148
149   GST_DEBUG (0,"gstelementfactory: create \"%s\" \"%s\"\n", factory->name, name);
150
151   // it's not loaded, try to load the plugin
152   if (factory->type == 0) {
153     factory = gst_plugin_load_elementfactory(factory->name);
154   }
155   g_return_val_if_fail(factory != NULL, NULL);
156   g_return_val_if_fail(factory->type != 0, NULL);
157
158   // create an instance of the element
159   element = GST_ELEMENT(gtk_type_new(factory->type));
160   g_assert(element != NULL);
161   gst_object_ref(GST_OBJECT(element));
162
163   // attempt to set the elemenfactory class pointer if necessary
164   oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
165   if (oclass->elementfactory == NULL) {
166     GST_DEBUG (0,"gstelementfactory: class %s\n", factory->name);
167     oclass->elementfactory = factory;
168   }
169
170   gst_object_set_name (GST_OBJECT (element),name);
171
172   return element;
173 }
174
175 /**
176  * gst_elementfactory_make:
177  * @factoryname: a named factory to instantiate
178  * @name: name of new element
179  *
180  * Create a new element of the type defined by the given elementfactory.
181  * It wll be given the name supplied, since all elements require a name as
182  * their first argument.
183  *
184  * Returns: new #GstElement
185  */
186 GstElement*
187 gst_elementfactory_make (const gchar *factoryname, const gchar *name) 
188 {
189   GstElementFactory *factory;
190   GstElement *element;
191
192   g_return_val_if_fail(factoryname != NULL, NULL);
193   g_return_val_if_fail(name != NULL, NULL);
194
195   GST_DEBUG (0,"gstelementfactory: make \"%s\" \"%s\"\n", factoryname, name);
196
197   //gst_plugin_load_elementfactory(factoryname);
198   factory = gst_elementfactory_find(factoryname);
199   if (factory == NULL) return NULL;
200   element = gst_elementfactory_create(factory,name);
201   return element;
202 }
203
204 /**
205  * gst_elementfactory_add_padtemplate :
206  * @elementfactory: factory to add the src id to
207  * @templ: the padtemplate to add
208  *
209  * Add the given padtemplate to this elementfactory.
210  */
211 void
212 gst_elementfactory_add_padtemplate (GstElementFactory *factory,
213                                     GstPadTemplate *templ)
214 {
215   g_return_if_fail(factory != NULL);
216   g_return_if_fail(templ != NULL);
217
218   factory->padtemplates = g_list_append (factory->padtemplates, templ);
219   factory->numpadtemplates++;
220 }
221
222 /**
223  * gst_elementfactory_can_src_caps_list :
224  * @factory: factory to query
225  * @caps: the caps list to check
226  *
227  * Checks if the factory can source the given capability list.
228  *
229  * Returns: true if it can src the capabilities
230  */
231 gboolean
232 gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
233                                       GList *caps)
234 {
235   GList *templates;
236
237   g_return_val_if_fail(factory != NULL, FALSE);
238   g_return_val_if_fail(caps != NULL, FALSE);
239
240   templates = factory->padtemplates;
241
242   while (templates) {
243     GstPadTemplate *template = (GstPadTemplate *)templates->data;
244
245     if (template->direction == GST_PAD_SRC) {
246       if (gst_caps_list_check_compatibility (template->caps, caps))
247         return TRUE;
248     }
249     templates = g_list_next (templates);
250   }
251
252   return FALSE;
253 }
254
255 /**
256  * gst_elementfactory_can_sink_caps_list :
257  * @factory: factory to query
258  * @caps: the caps list to check
259  *
260  * Checks if the factory can sink the given capability list.
261  *
262  * Returns: true if it can sink the capabilities
263  */
264 gboolean
265 gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
266                                        GList *caps)
267 {
268   GList *templates;
269
270   g_return_val_if_fail(factory != NULL, FALSE);
271   g_return_val_if_fail(caps != NULL, FALSE);
272
273   templates = factory->padtemplates;
274
275   while (templates) {
276     GstPadTemplate *template = (GstPadTemplate *)templates->data;
277
278     if (template->direction == GST_PAD_SINK) {
279       if (gst_caps_list_check_compatibility (caps, template->caps))
280         return TRUE;
281     }
282     templates = g_list_next (templates);
283   }
284
285   return FALSE;
286 }
287
288 /**
289  * gst_elementfactory_can_src_caps :
290  * @factory: factory to query
291  * @caps: the caps to check
292  *
293  * Checks if the factory can src the given capability.
294  *
295  * Returns: true if it can sink the capability
296  */
297 gboolean
298 gst_elementfactory_can_src_caps (GstElementFactory *factory,
299                                  GstCaps *caps)
300 {
301   GList *dummy;
302   gboolean ret;
303
304   dummy = g_list_prepend (NULL, caps);
305
306   ret = gst_elementfactory_can_src_caps_list (factory, dummy);
307
308   g_list_free (dummy);
309
310   return ret;
311 }
312
313 /**
314  * gst_elementfactory_can_sink_caps :
315  * @factory: factory to query
316  * @caps: the caps to check
317  *
318  * Checks if the factory can sink the given capability.
319  *
320  * Returns: true if it can sink the capability
321  */
322 gboolean
323 gst_elementfactory_can_sink_caps (GstElementFactory *factory,
324                                   GstCaps *caps)
325 {
326   GList *dummy;
327   gboolean ret;
328
329   dummy = g_list_prepend (NULL, caps);
330
331   ret = gst_elementfactory_can_sink_caps_list (factory, dummy);
332
333   g_list_free (dummy);
334
335   return ret;
336 }
337
338 /**
339  * gst_elementfactory_save_thyself:
340  * @factory: factory to save
341  * @parent: the parent xmlNodePtr 
342  *
343  * Saves the factory into an XML tree.
344  * 
345  * Returns: the new xmlNodePtr
346  */
347 xmlNodePtr 
348 gst_elementfactory_save_thyself (GstElementFactory *factory, 
349                                  xmlNodePtr parent) 
350 {
351   GList *pads;
352
353   g_return_val_if_fail(factory != NULL, NULL);
354
355   xmlNewChild(parent,NULL,"name",factory->name);
356   xmlNewChild(parent,NULL,"longname", factory->details->longname);
357   xmlNewChild(parent,NULL,"class", factory->details->klass);
358   xmlNewChild(parent,NULL,"description", factory->details->description);
359   xmlNewChild(parent,NULL,"version", factory->details->version);
360   xmlNewChild(parent,NULL,"author", factory->details->author);
361   xmlNewChild(parent,NULL,"copyright", factory->details->copyright);
362
363   pads = factory->padtemplates;
364   if (pads) {
365     while (pads) {
366       xmlNodePtr subtree;
367       GstPadTemplate *padtemplate = (GstPadTemplate *)pads->data;
368
369       subtree = xmlNewChild(parent, NULL, "padtemplate", NULL);
370       gst_padtemplate_save_thyself(padtemplate, subtree);
371
372       pads = g_list_next (pads);
373     }
374   }
375   return parent;
376 }
377
378 /**
379  * gst_elementfactory_load_thyself:
380  * @parent: the parent xmlNodePtr 
381  *
382  * Creates a new factory from an xmlNodePtr.
383  * 
384  * Returns: the new factory
385  */
386 GstElementFactory *
387 gst_elementfactory_load_thyself (xmlNodePtr parent) 
388 {
389   GstElementFactory *factory = g_new0(GstElementFactory, 1);
390   xmlNodePtr children = parent->xmlChildrenNode;
391   factory->details = g_new0(GstElementDetails, 1);
392   factory->padtemplates = NULL;
393
394   while (children) {
395     if (!strcmp(children->name, "name")) {
396       factory->name = xmlNodeGetContent(children);
397     }
398     if (!strcmp(children->name, "longname")) {
399       factory->details->longname = xmlNodeGetContent(children);
400     }
401     if (!strcmp(children->name, "class")) {
402       factory->details->klass = xmlNodeGetContent(children);
403     }
404     if (!strcmp(children->name, "description")) {
405       factory->details->description = xmlNodeGetContent(children);
406     }
407     if (!strcmp(children->name, "version")) {
408       factory->details->version = xmlNodeGetContent(children);
409     }
410     if (!strcmp(children->name, "author")) {
411       factory->details->author = xmlNodeGetContent(children);
412     }
413     if (!strcmp(children->name, "copyright")) {
414       factory->details->copyright = xmlNodeGetContent(children);
415     }
416     if (!strcmp(children->name, "padtemplate")) {
417        GstPadTemplate *template;
418        
419        template = gst_padtemplate_load_thyself (children);
420
421        gst_elementfactory_add_padtemplate (factory, template);
422     }
423
424     children = children->next;
425   }
426
427   _gst_elementfactories = g_list_prepend (_gst_elementfactories, factory);
428
429   return factory;
430 }
431