2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include <sys/types.h>
27 #include <gst/gstplugin.h>
31 //#undef PLUGINS_USE_SRCDIR
33 /* list of loaded modules and its sequence number */
35 gint _gst_modules_seqno;
36 /* global list of plugins and its sequence number */
38 gint _gst_plugins_seqno;
39 /* list of paths to check for plugins */
40 GList *_gst_plugin_paths;
42 GList *_gst_libraries;
43 gint _gst_libraries_seqno;
45 /* whether or not to spew library load issues */
46 gboolean _gst_plugin_spew = TRUE;
49 void _gst_plugin_initialize() {
52 _gst_modules_seqno = 0;
54 _gst_plugins_seqno = 0;
55 _gst_plugin_paths = NULL;
56 _gst_libraries = NULL;
57 _gst_libraries_seqno = 0;
60 /* if this is set, we add build-directory paths to the list */
61 #ifdef PLUGINS_USE_SRCDIR
62 /* the catch-all plugins directory */
63 _gst_plugin_paths = g_list_append(_gst_plugin_paths,
64 PLUGINS_SRCDIR "/plugins");
65 /* the libreary directory */
66 _gst_plugin_paths = g_list_append(_gst_plugin_paths,
67 PLUGINS_SRCDIR "/libs");
68 /* location libgstelements.so */
69 _gst_plugin_paths = g_list_append(_gst_plugin_paths,
70 PLUGINS_SRCDIR "/gst/elements");
71 _gst_plugin_paths = g_list_append(_gst_plugin_paths,
72 PLUGINS_SRCDIR "/gst/types");
74 /* add the main (installed) library path */
75 _gst_plugin_paths = g_list_append(_gst_plugin_paths,PLUGINS_DIR);
76 #endif /* PLUGINS_USE_SRCDIR */
78 doc = xmlParseFile("/etc/gstreamer/reg.xml");
80 if (!doc || strcmp(doc->root->name, "GST-PluginRegistry")) {
81 g_print("gstplugin: registry needs rebuild\n");
82 gst_plugin_load_all();
85 gst_plugin_load_thyself(doc->root);
88 static gboolean gst_plugin_load_recurse(gchar *directory,gchar *name) {
90 struct dirent *dirent;
91 gboolean loaded = FALSE;
93 //g_print("recursive load of '%s' in '%s'\n", name, directory);
94 dir = opendir(directory);
96 while ((dirent = readdir(dir))) {
97 /* don't want to recurse in place or backwards */
98 if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
99 loaded = gst_plugin_load_recurse(g_strjoin("/",directory,dirent->d_name,
101 if (loaded && name) return TRUE;
106 if (strstr(directory,".so")) {
109 if ((temp = strstr(directory,name)) &&
110 (!strcmp(temp,name))) {
111 loaded = gst_plugin_load_absolute(directory);
114 } else if ((temp = strstr(directory,".so")) &&
115 (!strcmp(temp,".so"))) {
116 loaded = gst_plugin_load_absolute(directory);
125 * gst_plugin_load_all:
127 * Load all plugins in the path.
129 void gst_plugin_load_all() {
132 path = _gst_plugin_paths;
133 while (path != NULL) {
134 gst_plugin_load_recurse(path->data,NULL);
135 path = g_list_next(path);
141 * @name: name of library to load
143 * Load the named library. Name should be given as
144 * "liblibrary.so".
146 * Returns: whether the library was loaded or not
148 gboolean gst_library_load(gchar *name) {
150 GList *libraries = _gst_libraries;
153 if (!strcmp((gchar *)libraries->data, name)) return TRUE;
155 libraries = g_list_next(libraries);
158 // for now this is the same
159 res = gst_plugin_load(name);
162 _gst_libraries = g_list_prepend(_gst_libraries, name);
169 gst_plugin_remove(GstPlugin *plugin)
173 factories = plugin->elements;
175 gst_elementfactory_unregister((GstElementFactory*)(factories->data));
176 factories = g_list_next(factories);
178 _gst_plugins = g_list_remove(_gst_plugins, plugin);
184 * @name: name of plugin to load
186 * Load the named plugin. Name should be given as
187 * "libplugin.so".
189 * Returns: whether the plugin was loaded or not
191 gboolean gst_plugin_load(gchar *name) {
195 //g_print("attempting to load plugin '%s'\n",name);
197 path = _gst_plugin_paths;
198 while (path != NULL) {
199 if (gst_plugin_load_absolute(g_module_build_path(path->data,name)))
201 libspath = g_strconcat(path->data,"/.libs",NULL);
202 //g_print("trying to load '%s'\n",g_module_build_path(libspath,name));
203 if (gst_plugin_load_absolute(g_module_build_path(libspath,name))) {
208 //g_print("trying to load '%s' from '%s'\n",name,path->data);
209 if (gst_plugin_load_recurse(path->data,g_module_build_path("",name))) {
212 path = g_list_next(path);
218 * gst_plugin_load_absolute:
219 * @name: name of plugin to load
221 * Returns: whether or not the plugin loaded
223 gboolean gst_plugin_load_absolute(gchar *name) {
225 GstPluginInitFunc initfunc;
227 struct stat file_status;
229 if (g_module_supported() == FALSE) {
230 g_print("gstplugin: wow, you built this on a platform without dynamic loading???\n");
234 if (stat(name,&file_status)) {
235 // g_print("problem opening file %s\n",name);
239 module = g_module_open(name,G_MODULE_BIND_LAZY);
240 if (module != NULL) {
241 if (g_module_symbol(module,"plugin_init",(gpointer *)&initfunc)) {
242 if ((plugin = (initfunc)(module))) {
243 g_print("gstplugin: plugin %s loaded\n", plugin->name);
244 plugin->filename = g_strdup(name);
245 plugin->loaded = TRUE;
246 _gst_modules = g_list_append(_gst_modules,module);
247 _gst_modules_seqno++;
248 _gst_plugins = g_list_prepend(_gst_plugins,plugin);
249 _gst_plugins_seqno++;
254 } else if (_gst_plugin_spew) {
255 // if (strstr(g_module_error(),"No such") == NULL)
256 gst_info("error loading plugin: %s, reason: %s\n", name, g_module_error());
264 * @name: name of new plugin
266 * Create a new plugin with given name.
268 * Returns: new plugin
270 GstPlugin *gst_plugin_new(gchar *name) {
271 GstPlugin *plugin = (GstPlugin *)g_malloc(sizeof(GstPlugin));
273 // FIXME need to make sure the plugin hasn't already loaded
274 plugin->name = g_strdup(name);
275 plugin->longname = NULL;
276 plugin->types = NULL;
277 plugin->elements = NULL;
278 plugin->loaded = TRUE;
284 * gst_plugin_set_longname:
285 * @plugin: plugin to set long name of
286 * @longname: new long name
288 * Sets the long name (should be descriptive) of the plugin.
290 void gst_plugin_set_longname(GstPlugin *plugin,gchar *longname) {
291 g_return_if_fail(plugin != NULL);
293 if (plugin->longname) g_free(plugin->longname);
294 plugin->longname = g_strdup(longname);
299 * @name: name of plugin to find
301 * Search the list of registered plugins for one of the given name
303 * Returns: pointer to the #GstPlugin if found, NULL otherwise
305 GstPlugin *gst_plugin_find(const gchar *name) {
306 GList *plugins = _gst_plugins;
308 g_return_val_if_fail(name != NULL, NULL);
311 GstPlugin *plugin = (GstPlugin *)plugins->data;
312 // g_print("plugin name is '%s'\n",plugin->name);
314 if (!strcmp(plugin->name,name)) {
318 plugins = g_list_next(plugins);
324 * gst_plugin_find_elementfactory:
325 * @name: name of elementfactory to find
327 * Find a registered elementfactory by name.
329 * Returns: @GstElementFactory if found, NULL if not
331 GstElementFactory *gst_plugin_find_elementfactory(gchar *name) {
332 GList *plugins, *factories;
333 GstElementFactory *factory;
335 g_return_val_if_fail(name != NULL, NULL);
337 plugins = _gst_plugins;
339 factories = ((GstPlugin *)(plugins->data))->elements;
341 factory = (GstElementFactory*)(factories->data);
342 if (!strcmp(factory->name, name))
343 return (GstElementFactory*)(factory);
344 factories = g_list_next(factories);
346 plugins = g_list_next(plugins);
353 * gst_plugin_load_elementfactory:
354 * @name: name of elementfactory to load
356 * Load a registered elementfactory by name.
358 * Returns: @GstElementFactory if loaded, NULL if not
360 GstElementFactory *gst_plugin_load_elementfactory(gchar *name) {
361 GList *plugins, *factories;
362 GstElementFactory *factory = NULL;
365 g_return_val_if_fail(name != NULL, NULL);
367 plugins = _gst_plugins;
369 plugin = (GstPlugin *)plugins->data;
370 factories = plugin->elements;
372 factory = (GstElementFactory*)(factories->data);
373 if (!strcmp(factory->name,name)) {
374 if (!plugin->loaded) {
375 gchar *filename = g_strdup (plugin->filename);
376 g_print("gstplugin: loading element factory %s from plugin %s\n", name, plugin->name);
377 gst_plugin_remove(plugin);
378 if (!gst_plugin_load_absolute(filename)) {
379 g_print("gstplugin: error loading element factory %s from plugin %s\n", name, plugin->name);
382 factory = gst_plugin_find_elementfactory(name);
386 factories = g_list_next(factories);
388 plugins = g_list_next(plugins);
395 * gst_plugin_load_typefactory:
396 * @mime: name of typefactory to load
398 * Load a registered typefactory by mime type.
400 void gst_plugin_load_typefactory(gchar *mime) {
401 GList *plugins, *factories;
402 GstTypeFactory *factory;
405 g_return_if_fail(mime != NULL);
407 plugins = _gst_plugins;
409 plugin = (GstPlugin *)plugins->data;
410 factories = plugin->types;
412 factory = (GstTypeFactory*)(factories->data);
413 if (!strcmp(factory->mime,mime)) {
414 if (!plugin->loaded) {
415 gchar *filename = g_strdup (plugin->filename);
416 g_print("gstplugin: loading type factory for \"%s\" from plugin %s\n", mime, plugin->name);
417 gst_plugin_remove(plugin);
418 if (!gst_plugin_load_absolute(filename)) {
419 g_print("gstplugin: error loading type factory \"%s\" from plugin %s\n", mime, plugin->name);
425 factories = g_list_next(factories);
427 plugins = g_list_next(plugins);
434 * gst_plugin_add_factory:
435 * @plugin: plugin to add factory to
436 * @factory: factory to add
438 * Add factory to the list of those provided by the plugin.
440 void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory) {
441 g_return_if_fail(plugin != NULL);
442 g_return_if_fail(factory != NULL);
444 // g_print("adding factory to plugin\n");
445 plugin->elements = g_list_append(plugin->elements,factory);
446 gst_elementfactory_register (factory);
450 * gst_plugin_add_type:
451 * @plugin: plugin to add type to
452 * @factory: the typefactory to add
454 * Add a typefactory to the list of those provided by the plugin.
456 void gst_plugin_add_type(GstPlugin *plugin,GstTypeFactory *factory) {
457 g_return_if_fail(plugin != NULL);
458 g_return_if_fail(factory != NULL);
460 // g_print("adding factory to plugin\n");
461 plugin->types = g_list_append(plugin->types,factory);
465 * gst_plugin_get_list:
467 * get the currently loaded plugins
469 * Returns; a GList of GstPlugin elements
471 GList *gst_plugin_get_list() {
476 * gst_plugin_save_thyself:
477 * @parent: the parent node to save the plugin to
479 * saves the plugin into an XML representation
481 * Returns: the new XML node
483 xmlNodePtr gst_plugin_save_thyself(xmlNodePtr parent) {
484 xmlNodePtr tree, subtree;
485 GList *plugins = NULL, *elements = NULL, *types = NULL;
487 plugins = gst_plugin_get_list();
489 GstPlugin *plugin = (GstPlugin *)plugins->data;
490 tree = xmlNewChild(parent,NULL,"plugin",NULL);
491 xmlNewChild(tree,NULL,"name",plugin->name);
492 xmlNewChild(tree,NULL,"longname",plugin->longname);
493 xmlNewChild(tree,NULL,"filename",plugin->filename);
494 types = plugin->types;
496 GstTypeFactory *factory = (GstTypeFactory *)types->data;
497 subtree = xmlNewChild(tree,NULL,"type",NULL);
499 gst_typefactory_save_thyself(factory, subtree);
501 types = g_list_next(types);
503 elements = plugin->elements;
505 GstElementFactory *factory = (GstElementFactory *)elements->data;
506 subtree = xmlNewChild(tree,NULL,"element",NULL);
508 gst_elementfactory_save_thyself(factory, subtree);
510 elements = g_list_next(elements);
512 plugins = g_list_next(plugins);
518 * gst_plugin_load_thyself:
519 * @parent: the parent node to load the plugin from
521 * load the plugin from an XML representation
523 void gst_plugin_load_thyself(xmlNodePtr parent) {
525 gint elementcount = 0;
528 kinderen = parent->childs; // Dutch invasion :-)
530 if (!strcmp(kinderen->name, "plugin")) {
531 xmlNodePtr field = kinderen->childs;
532 GstPlugin *plugin = g_new0 (GstPlugin, 1);
533 plugin->elements = NULL;
534 plugin->types = NULL;
535 plugin->loaded = FALSE;
538 if (!strcmp(field->name, "name")) {
539 if (gst_plugin_find(xmlNodeGetContent(field))) {
545 plugin->name = g_strdup(xmlNodeGetContent(field));
548 else if (!strcmp(field->name, "longname")) {
549 plugin->longname = g_strdup(xmlNodeGetContent(field));
551 else if (!strcmp(field->name, "filename")) {
552 plugin->filename = g_strdup(xmlNodeGetContent(field));
554 else if (!strcmp(field->name, "element")) {
555 GstElementFactory *factory = gst_elementfactory_load_thyself(field);
556 gst_plugin_add_factory (plugin, factory);
559 else if (!strcmp(field->name, "type")) {
560 GstTypeFactory *factory = gst_typefactory_load_thyself(field);
561 gst_plugin_add_type (plugin, factory);
570 _gst_plugins = g_list_prepend(_gst_plugins, plugin);
574 kinderen = kinderen->next;
576 g_print("gstplugin: added %d registered factories and %d types\n", elementcount, typecount);