7e43fe8124443c4171ef39f7873f2e9497dc6ab2
[platform/upstream/gstreamer.git] / gst / gstplugin.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstplugin.c: Plugin subsystem for loading elements, types, and libs
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 <sys/types.h>
24 #include <sys/stat.h>
25 #include <dirent.h>
26 #include <unistd.h>
27
28 #include "gst_private.h"
29 #include "gstplugin.h"
30 #include "config.h"
31
32
33 /* list of loaded modules and its sequence number */
34 GList *_gst_modules;
35 gint _gst_modules_seqno;
36 /* global list of plugins and its sequence number */
37 GList *_gst_plugins;
38 gint _gst_plugins_seqno;
39 gint _gst_plugin_elementfactories = 0;
40 gint _gst_plugin_types = 0;
41 /* list of paths to check for plugins */
42 GList *_gst_plugin_paths;
43
44 GList *_gst_libraries;
45 gint _gst_libraries_seqno;
46
47 /* whether or not to spew library load issues */
48 gboolean _gst_plugin_spew = FALSE;
49
50 /* whether or not to warn if registry needs rebuild (gstreamer-register sets
51  * this to false.) */
52 gboolean _gst_warn_old_registry = TRUE;
53
54 static gboolean plugin_times_older_than(time_t regtime);
55 static time_t get_time(const char * path);
56
57 void
58 _gst_plugin_initialize (void)
59 {
60   xmlDocPtr doc;
61   _gst_modules = NULL;
62   _gst_modules_seqno = 0;
63   _gst_plugins = NULL;
64   _gst_plugins_seqno = 0;
65   _gst_plugin_paths = NULL;
66   _gst_libraries = NULL;
67   _gst_libraries_seqno = 0;
68
69
70   /* if this is set, we add build-directory paths to the list */
71 #ifdef PLUGINS_USE_SRCDIR
72   /* the catch-all plugins directory */
73   _gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
74                                       PLUGINS_SRCDIR "/plugins");
75   /* the libreary directory */
76   _gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
77                                       PLUGINS_SRCDIR "/libs");
78   /* location libgstelements.so */
79   _gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
80                                       PLUGINS_SRCDIR "/gst/elements");
81   _gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
82                                       PLUGINS_SRCDIR "/gst/types");
83 #endif /* PLUGINS_USE_SRCDIR */
84
85   /* add the main (installed) library path */
86   _gst_plugin_paths = g_list_prepend (_gst_plugin_paths, PLUGINS_DIR);
87
88   doc = xmlParseFile (GST_CONFIG_DIR"/reg.xml");
89
90   if (!doc || strcmp (doc->xmlRootNode->name, "GST-PluginRegistry") ||
91       !plugin_times_older_than(get_time(GST_CONFIG_DIR"/reg.xml"))) {
92     if (_gst_warn_old_registry)
93         g_warning ("gstplugin: registry needs rebuild\n");
94     gst_plugin_load_all ();
95     return;
96   }
97   gst_plugin_load_thyself (doc->xmlRootNode);
98
99   xmlFreeDoc (doc);
100 }
101
102 static time_t
103 get_time(const char * path)
104 {
105   struct stat statbuf;
106   if (stat(path, &statbuf)) return 0;
107   if (statbuf.st_mtime > statbuf.st_ctime) return statbuf.st_mtime;
108   return statbuf.st_ctime;
109 }
110
111 static gboolean
112 plugin_times_older_than_recurse(gchar *path, time_t regtime)
113 {
114   DIR *dir;
115   struct dirent *dirent;
116   gchar *pluginname;
117
118   time_t pathtime = get_time(path);
119
120   if (pathtime > regtime) {
121     GST_INFO (GST_CAT_PLUGIN_LOADING,
122                "time for %s was %ld; more recent than registry time of %ld\n",
123                path, (long)pathtime, (long)regtime);
124     return FALSE;
125   }
126
127   dir = opendir(path);
128   if (dir) {
129     while ((dirent = readdir(dir))) {
130       /* don't want to recurse in place or backwards */
131       if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
132         pluginname = g_strjoin("/",path,dirent->d_name,NULL);
133         if (!plugin_times_older_than_recurse(pluginname , regtime)) {
134           g_free (pluginname);
135           closedir(dir);
136           return FALSE;
137         }
138         g_free (pluginname);
139       }
140     }
141     closedir(dir);
142   }
143   return TRUE;
144 }
145
146 static gboolean
147 plugin_times_older_than(time_t regtime)
148 {
149   // return true iff regtime is more recent than the times of all the files
150   // in the plugin dirs.
151   GList *path;
152   path = _gst_plugin_paths;
153   while (path != NULL) {
154     GST_DEBUG (GST_CAT_PLUGIN_LOADING,
155                "comparing plugin times from %s with %ld\n",
156                (gchar *)path->data, (long) regtime);
157     if(!plugin_times_older_than_recurse(path->data, regtime))
158         return FALSE;
159     path = g_list_next(path);
160   }
161   return TRUE;
162 }
163
164 static gboolean
165 gst_plugin_load_recurse (gchar *directory, gchar *name)
166 {
167   DIR *dir;
168   struct dirent *dirent;
169   gboolean loaded = FALSE;
170   gchar *dirname;
171
172   //g_print("recursive load of '%s' in '%s'\n", name, directory);
173   dir = opendir(directory);
174   if (dir) {
175     while ((dirent = readdir(dir))) {
176       /* don't want to recurse in place or backwards */
177       if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
178         dirname = g_strjoin("/",directory,dirent->d_name,NULL);
179         loaded = gst_plugin_load_recurse(dirname,name);
180         g_free(dirname);
181         if (loaded && name) {
182           closedir(dir);
183           return TRUE;
184         }
185       }
186     }
187     closedir(dir);
188   } else {
189     if (strstr(directory,".so")) {
190       gchar *temp;
191       if (name) {
192         if ((temp = strstr(directory,name)) &&
193             (!strcmp(temp,name))) {
194           loaded = gst_plugin_load_absolute(directory);
195         }
196       } else if ((temp = strstr(directory,".so")) &&
197                  (!strcmp(temp,".so"))) {
198         loaded = gst_plugin_load_absolute(directory);
199       }
200     }
201   }
202   return loaded;
203 }
204
205 /**
206  * gst_plugin_load_all:
207  *
208  * Load all plugins in the path.
209  */
210 void
211 gst_plugin_load_all(void)
212 {
213   GList *path;
214
215   path = _gst_plugin_paths;
216   while (path != NULL) {
217     GST_DEBUG (GST_CAT_PLUGIN_LOADING,"loading plugins from %s\n",(gchar *)path->data);
218     gst_plugin_load_recurse(path->data,NULL);
219     path = g_list_next(path);
220   }
221   GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded %d plugins with %d elements and %d types",
222        _gst_plugins_seqno,_gst_plugin_elementfactories,_gst_plugin_types);
223 }
224
225 /**
226  * gst_library_load:
227  * @name: name of library to load
228  *
229  * Load the named library.  Name should be given as
230  * &quot;liblibrary.so&quot;.
231  *
232  * Returns: whether the library was loaded or not
233  */
234 gboolean
235 gst_library_load (const gchar *name)
236 {
237   gboolean res;
238   GList *libraries = _gst_libraries;
239
240   while (libraries) {
241     if (!strcmp((gchar *)libraries->data, name)) return TRUE;
242
243     libraries = g_list_next(libraries);
244   }
245
246   // for now this is the same
247   res = gst_plugin_load(name);
248
249   if (res) {
250     _gst_libraries = g_list_prepend(_gst_libraries, g_strdup (name));
251   }
252
253   return res;
254 }
255
256 static void
257 gst_plugin_remove (GstPlugin *plugin)
258 {
259   GList *factories;
260
261   factories = plugin->elements;
262   while (factories) {
263     gst_elementfactory_destroy ((GstElementFactory*)(factories->data));
264     factories = g_list_next(factories);
265   }
266
267   _gst_plugins = g_list_remove(_gst_plugins, plugin);
268
269   // don't free the stuct because someone can have a handle to it
270 }
271
272 /**
273  * gst_plugin_load:
274  * @name: name of plugin to load
275  *
276  * Load the named plugin.  Name should be given as
277  * &quot;libplugin.so&quot;.
278  *
279  * Returns: whether the plugin was loaded or not
280  */
281 gboolean
282 gst_plugin_load (const gchar *name)
283 {
284   GList *path;
285   gchar *libspath;
286   GstPlugin *plugin;
287   gchar *pluginname;
288
289   //g_print("attempting to load plugin '%s'\n",name);
290
291   plugin = gst_plugin_find (name);
292
293   if (plugin && plugin->loaded) return TRUE;
294
295   path = _gst_plugin_paths;
296   while (path != NULL) {
297     pluginname = g_module_build_path(path->data,name);
298     if (gst_plugin_load_absolute(pluginname)) {
299       g_free(pluginname);
300       return TRUE;
301     }
302     g_free(pluginname);
303     libspath = g_strconcat(path->data,"/.libs",NULL);
304     //g_print("trying to load '%s'\n",g_module_build_path(libspath,name));
305     pluginname = g_module_build_path(libspath,name);
306     g_free(libspath);
307     if (gst_plugin_load_absolute(pluginname)) {
308       g_free(pluginname);
309       return TRUE;
310     }
311     g_free(pluginname);
312     //g_print("trying to load '%s' from '%s'\n",name,path->data);
313     pluginname = g_module_build_path("",name);
314     if (gst_plugin_load_recurse(path->data,pluginname)) {
315       g_free(pluginname);
316       return TRUE;
317     }
318     g_free(pluginname);
319     path = g_list_next(path);
320   }
321   return FALSE;
322 }
323
324 /**
325  * gst_plugin_load_absolute:
326  * @name: name of plugin to load
327  *
328  * Returns: whether or not the plugin loaded
329  */
330 gboolean
331 gst_plugin_load_absolute (const gchar *name)
332 {
333   GModule *module;
334   GstPluginInitFunc initfunc;
335   GstPlugin *plugin;
336   struct stat file_status;
337
338   if (g_module_supported() == FALSE) {
339     g_warning("gstplugin: wow, you built this on a platform without dynamic loading???\n");
340     return FALSE;
341   }
342
343   if (stat(name,&file_status)) {
344 //    g_print("problem opening file %s\n",name);
345     return FALSE;
346   }
347
348   module = g_module_open(name,G_MODULE_BIND_LAZY);
349   if (module != NULL) {
350     if (g_module_symbol(module,"plugin_init",(gpointer *)&initfunc)) {
351       if ((plugin = (initfunc)(module))) {
352         GST_INFO (GST_CAT_PLUGIN_LOADING,"plugin \"%s\" loaded: %d elements, %d types",
353              plugin->name,plugin->numelements,plugin->numtypes);
354         plugin->filename = g_strdup(name);
355         plugin->loaded = TRUE;
356         _gst_modules = g_list_prepend(_gst_modules,module);
357         _gst_modules_seqno++;
358         _gst_plugins = g_list_prepend(_gst_plugins,plugin);
359         _gst_plugins_seqno++;
360         _gst_plugin_elementfactories += plugin->numelements;
361         _gst_plugin_types += plugin->numtypes;
362         return TRUE;
363       }
364     }
365     return TRUE;
366   } else if (_gst_plugin_spew) {
367     gst_info("error loading plugin: %s, reason: %s\n", name, g_module_error());
368   }
369
370   return FALSE;
371 }
372
373 /**
374  * gst_plugin_new:
375  * @name: name of new plugin
376  *
377  * Create a new plugin with given name.
378  *
379  * Returns: new plugin
380  */
381 GstPlugin*
382 gst_plugin_new (const gchar *name)
383 {
384   GstPlugin *plugin;
385
386   // return NULL if the plugin is allready loaded
387   plugin = gst_plugin_find (name);
388   if (plugin) return NULL;
389
390   plugin = (GstPlugin *)g_malloc(sizeof(GstPlugin));
391
392   plugin->name = g_strdup(name);
393   plugin->longname = NULL;
394   plugin->elements = NULL;
395   plugin->numelements = 0;
396   plugin->types = NULL;
397   plugin->numtypes = 0;
398   plugin->loaded = TRUE;
399
400   return plugin;
401 }
402
403 /**
404  * gst_plugin_get_name:
405  * @plugin: plugin to get the name of
406  *
407  * Get the short name of the plugin
408  *
409  * Returns: the name of the plugin
410  */
411 const gchar*
412 gst_plugin_get_name (GstPlugin *plugin)
413 {
414   g_return_val_if_fail (plugin != NULL, NULL);
415
416   return plugin->name;
417 }
418
419 /**
420  * gst_plugin_set_name:
421  * @plugin: plugin to set name of
422  * @name: new name
423  *
424  * Sets the name (should be short) of the plugin.
425  */
426 void
427 gst_plugin_set_name (GstPlugin *plugin, const gchar *name)
428 {
429   g_return_if_fail (plugin != NULL);
430
431   if (plugin->name)
432     g_free (plugin->name);
433
434   plugin->name = g_strdup (name);
435 }
436
437 /**
438  * gst_plugin_set_longname:
439  * @plugin: plugin to set long name of
440  * @longname: new long name
441  *
442  * Sets the long name (should be descriptive) of the plugin.
443  */
444 void
445 gst_plugin_set_longname (GstPlugin *plugin, const gchar *longname)
446 {
447   g_return_if_fail(plugin != NULL);
448
449   if (plugin->longname)
450     g_free(plugin->longname);
451
452   plugin->longname = g_strdup(longname);
453 }
454
455 /**
456  * gst_plugin_get_longname:
457  * @plugin: plugin to get long name of
458  *
459  * Get the long descriptive name of the plugin
460  *
461  * Returns: the long name of the plugin
462  */
463 const gchar*
464 gst_plugin_get_longname (GstPlugin *plugin)
465 {
466   g_return_val_if_fail (plugin != NULL, NULL);
467
468   return plugin->longname;
469 }
470
471 /**
472  * gst_plugin_get_filename:
473  * @plugin: plugin to get the filename of
474  *
475  * get the filename of the plugin
476  *
477  * Returns: the filename of the plugin
478  */
479 const gchar*
480 gst_plugin_get_filename (GstPlugin *plugin)
481 {
482   g_return_val_if_fail (plugin != NULL, NULL);
483
484   return plugin->filename;
485 }
486
487 /**
488  * gst_plugin_is_loaded:
489  * @plugin: plugin to query
490  *
491  * queries if the plugin is loaded into memory
492  *
493  * Returns: TRUE is loaded, FALSE otherwise
494  */
495 gboolean
496 gst_plugin_is_loaded (GstPlugin *plugin)
497 {
498   g_return_val_if_fail (plugin != NULL, FALSE);
499
500   return plugin->loaded;
501 }
502
503
504 /**
505  * gst_plugin_find:
506  * @name: name of plugin to find
507  *
508  * Search the list of registered plugins for one of the given name
509  *
510  * Returns: pointer to the #GstPlugin if found, NULL otherwise
511  */
512 GstPlugin*
513 gst_plugin_find (const gchar *name)
514 {
515   GList *plugins = _gst_plugins;
516
517   g_return_val_if_fail(name != NULL, NULL);
518
519   while (plugins) {
520     GstPlugin *plugin = (GstPlugin *)plugins->data;
521 //    g_print("plugin name is '%s'\n",plugin->name);
522     if (plugin->name) {
523       if (!strcmp(plugin->name,name)) {
524         return plugin;
525       }
526     }
527     plugins = g_list_next(plugins);
528   }
529   return NULL;
530 }
531
532 /**
533  * gst_plugin_find_elementfactory:
534  * @name: name of elementfactory to find
535  *
536  * Find a registered elementfactory by name.
537  *
538  * Returns: @GstElementFactory if found, NULL if not
539  */
540 GstElementFactory*
541 gst_plugin_find_elementfactory (const gchar *name)
542 {
543   GList *plugins, *factories;
544   GstElementFactory *factory;
545
546   g_return_val_if_fail(name != NULL, NULL);
547
548   plugins = _gst_plugins;
549   while (plugins) {
550     factories = ((GstPlugin *)(plugins->data))->elements;
551     while (factories) {
552       factory = (GstElementFactory*)(factories->data);
553       if (!strcmp(factory->name, name))
554         return (GstElementFactory*)(factory);
555       factories = g_list_next(factories);
556     }
557     plugins = g_list_next(plugins);
558   }
559
560   return NULL;
561 }
562
563 /**
564  * gst_plugin_load_elementfactory:
565  * @name: name of elementfactory to load
566  *
567  * Load a registered elementfactory by name.
568  *
569  * Returns: @GstElementFactory if loaded, NULL if not
570  */
571 GstElementFactory*
572 gst_plugin_load_elementfactory (const gchar *name)
573 {
574   GList *plugins, *factories;
575   GstElementFactory *factory = NULL;
576   GstPlugin *plugin;
577
578   g_return_val_if_fail(name != NULL, NULL);
579
580   plugins = _gst_plugins;
581   while (plugins) {
582     plugin = (GstPlugin *)plugins->data;
583     factories = plugin->elements;
584
585     while (factories) {
586       factory = (GstElementFactory*)(factories->data);
587
588       if (!strcmp(factory->name,name)) {
589         if (!plugin->loaded) {
590           gchar *filename = g_strdup (plugin->filename);
591           gchar *pluginname = g_strdup (plugin->name);
592
593           GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded elementfactory %s from plugin %s",name,plugin->name);
594           gst_plugin_remove(plugin);
595           if (!gst_plugin_load_absolute(filename)) {
596             GST_DEBUG (0,"gstplugin: error loading element factory %s from plugin %s\n", name, pluginname);
597           }
598           g_free (pluginname);
599           g_free (filename);
600         }
601         factory = gst_plugin_find_elementfactory(name);
602         return factory;
603       }
604       factories = g_list_next(factories);
605     }
606     plugins = g_list_next(plugins);
607   }
608
609   return factory;
610 }
611
612 /**
613  * gst_plugin_load_typefactory:
614  * @mime: name of typefactory to load
615  *
616  * Load a registered typefactory by mime type.
617  */
618 void
619 gst_plugin_load_typefactory (const gchar *mime)
620 {
621   GList *plugins, *factories;
622   GstTypeFactory *factory;
623   GstPlugin *plugin;
624
625   g_return_if_fail (mime != NULL);
626
627   plugins = g_list_copy (_gst_plugins);
628   while (plugins) {
629     plugin = (GstPlugin *)plugins->data;
630     factories = g_list_copy (plugin->types);
631
632     while (factories) {
633       factory = (GstTypeFactory*)(factories->data);
634
635       if (!strcmp(factory->mime,mime)) {
636         if (!plugin->loaded) {
637           gchar *filename = g_strdup (plugin->filename);
638           gchar *pluginname = g_strdup (plugin->name);
639
640           GST_INFO (GST_CAT_PLUGIN_LOADING,"loading type factory for \"%s\" from plugin %s",mime,plugin->name);
641           plugin->loaded = TRUE;
642           gst_plugin_remove(plugin);
643           if (!gst_plugin_load_absolute(filename)) {
644             GST_DEBUG (0,"gstplugin: error loading type factory \"%s\" from plugin %s\n", mime, pluginname);
645           }
646           g_free (filename);
647           g_free (pluginname);
648         }
649         //return;
650       }
651       factories = g_list_next(factories);
652     }
653
654     g_list_free (factories);
655     plugins = g_list_next(plugins);
656   }
657   g_list_free (plugins);
658
659   return;
660 }
661
662 /**
663  * gst_plugin_add_factory:
664  * @plugin: plugin to add factory to
665  * @factory: factory to add
666  *
667  * Add factory to the list of those provided by the plugin.
668  */
669 void
670 gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory)
671 {
672   g_return_if_fail (plugin != NULL);
673   g_return_if_fail (factory != NULL);
674
675 //  g_print("adding factory to plugin\n");
676   plugin->elements = g_list_prepend (plugin->elements, factory);
677   plugin->numelements++;
678 }
679
680 /**
681  * gst_plugin_add_type:
682  * @plugin: plugin to add type to
683  * @factory: the typefactory to add
684  *
685  * Add a typefactory to the list of those provided by the plugin.
686  */
687 void
688 gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
689 {
690   g_return_if_fail (plugin != NULL);
691   g_return_if_fail (factory != NULL);
692
693 //  g_print("adding factory to plugin\n");
694   plugin->types = g_list_prepend (plugin->types, factory);
695   plugin->numtypes++;
696   gst_type_register (factory);
697 }
698
699 /**
700  * gst_plugin_get_list:
701  *
702  * get the currently loaded plugins
703  *
704  * Returns; a GList of GstPlugin elements
705  */
706 GList*
707 gst_plugin_get_list(void)
708 {
709   return _gst_plugins;
710 }
711
712 /**
713  * gst_plugin_save_thyself:
714  * @parent: the parent node to save the plugin to
715  *
716  * saves the plugin into an XML representation
717  *
718  * Returns: the new XML node
719  */
720 xmlNodePtr
721 gst_plugin_save_thyself (xmlNodePtr parent)
722 {
723   xmlNodePtr tree, subtree;
724   GList *plugins = NULL, *elements = NULL, *types = NULL;
725
726   plugins = gst_plugin_get_list();
727   while (plugins) {
728     GstPlugin *plugin = (GstPlugin *)plugins->data;
729     tree = xmlNewChild(parent,NULL,"plugin",NULL);
730     xmlNewChild(tree,NULL,"name",plugin->name);
731     xmlNewChild(tree,NULL,"longname",plugin->longname);
732     xmlNewChild(tree,NULL,"filename",plugin->filename);
733     types = plugin->types;
734     while (types) {
735       GstTypeFactory *factory = (GstTypeFactory *)types->data;
736       subtree = xmlNewChild(tree,NULL,"typefactory",NULL);
737
738       gst_typefactory_save_thyself(factory, subtree);
739
740       types = g_list_next(types);
741     }
742     elements = plugin->elements;
743     while (elements) {
744       GstElementFactory *factory = (GstElementFactory *)elements->data;
745       subtree = xmlNewChild(tree,NULL,"elementfactory",NULL);
746
747       gst_elementfactory_save_thyself(factory, subtree);
748
749       elements = g_list_next(elements);
750     }
751     plugins = g_list_next(plugins);
752   }
753   return parent;
754 }
755
756 /**
757  * gst_plugin_load_thyself:
758  * @parent: the parent node to load the plugin from
759  *
760  * load the plugin from an XML representation
761  */
762 void
763 gst_plugin_load_thyself (xmlNodePtr parent)
764 {
765   xmlNodePtr kinderen;
766   gint elementcount = 0;
767   gint typecount = 0;
768   gchar *pluginname;
769
770   kinderen = parent->xmlChildrenNode; // Dutch invasion :-)
771   while (kinderen) {
772     if (!strcmp(kinderen->name, "plugin")) {
773       xmlNodePtr field = kinderen->xmlChildrenNode;
774       GstPlugin *plugin = g_new0 (GstPlugin, 1);
775       plugin->elements = NULL;
776       plugin->types = NULL;
777       plugin->loaded = FALSE;
778
779       while (field) {
780         if (!strcmp(field->name, "name")) {
781           pluginname = xmlNodeGetContent(field);
782           if (gst_plugin_find(pluginname)) {
783             g_free(pluginname);
784             g_free(plugin);
785             plugin = NULL;
786             break;
787           } else {
788             plugin->name = pluginname;
789           }
790         }
791         else if (!strcmp(field->name, "longname")) {
792           plugin->longname = xmlNodeGetContent(field);
793         }
794         else if (!strcmp(field->name, "filename")) {
795           plugin->filename = xmlNodeGetContent(field);
796         }
797         else if (!strcmp(field->name, "elementfactory")) {
798           GstElementFactory *factory = gst_elementfactory_load_thyself(field);
799           gst_plugin_add_factory (plugin, factory);
800           elementcount++;
801         }
802         else if (!strcmp(field->name, "typefactory")) {
803           GstTypeFactory *factory = gst_typefactory_load_thyself(field);
804           gst_plugin_add_type (plugin, factory);
805           elementcount++;
806           typecount++;
807         }
808
809         field = field->next;
810       }
811
812       if (plugin) {
813         _gst_plugins = g_list_prepend(_gst_plugins, plugin);
814       }
815     }
816
817     kinderen = kinderen->next;
818   }
819   GST_INFO (GST_CAT_PLUGIN_LOADING,"added %d registered factories and %d types",elementcount,typecount);
820 }
821
822
823 /**
824  * gst_plugin_get_factory_list:
825  * @plugin: the plugin to get the factories from
826  *
827  * get a list of all the factories that this plugin provides
828  *
829  * Returns: a GList of factories
830  */
831 GList*
832 gst_plugin_get_factory_list (GstPlugin *plugin)
833 {
834   g_return_val_if_fail (plugin != NULL, NULL);
835
836   return plugin->elements;
837 }
838
839 /**
840  * gst_plugin_get_type_list:
841  * @plugin: the plugin to get the typefactories from
842  *
843  * get a list of all the typefactories that this plugin provides
844  *
845  * Returns: a GList of factories
846  */
847 GList*
848 gst_plugin_get_type_list (GstPlugin *plugin)
849 {
850   g_return_val_if_fail (plugin != NULL, NULL);
851
852   return plugin->types;
853 }