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