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