2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstplugin.c: Plugin subsystem for loading elements, types, and libs
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.
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.
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.
25 * @short_description: Container for features loaded from a shared object module
26 * @see_also: #GstPluginFeature, #GstElementFactory
28 * GStreamer is extensible, so #GstElement instances can be loaded at runtime.
29 * A plugin system can provide one or more of the basic
30 * <application>GStreamer</application> #GstPluginFeature subclasses.
32 * A plugin should export a symbol <symbol>plugin_desc</symbol> that is a
33 * struct of type #GstPluginDesc.
34 * the plugin loader will check the version of the core library the plugin was
35 * linked against and will create a new #GstPlugin. It will then call the
36 * #GstPluginInitFunc function that was provided in the plugin_desc.
38 * Once you have a handle to a #GstPlugin (e.g. from the #GstRegistryPool), you
39 * can add any object that subclasses #GstPluginFeature.
41 * Use gst_plugin_find_feature() and gst_plugin_get_feature_list() to find
42 * features in a plugin.
44 * Usually plugins are always automaticlly loaded so you don't need to call
45 * gst_plugin_load() explicitly to bring it into memory. There are options to
46 * statically link plugins to an app or even use GStreamer without a plugin
47 * repository in which case gst_plugin_load() can be needed to bring the plugin
54 #include <sys/types.h>
65 #include "gst_private.h"
67 #include "gstplugin.h"
68 #include "gstversion.h"
70 #include "gstfilter.h"
71 #include "gstregistry.h"
72 #include "gstmacros.h"
75 #define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING
77 static GModule *main_module = NULL;
78 static GList *_gst_plugin_static = NULL;
80 /* static variables for segfault handling of plugin loading */
81 static char *_gst_plugin_fault_handler_filename = NULL;
82 extern gboolean _gst_disable_segtrap; /* see gst.c */
85 static gboolean _gst_plugin_fault_handler_is_setup = FALSE;
88 /* list of valid licenses.
89 * One of these must be specified or the plugin won't be loaded
90 * Contact gstreamer-devel@lists.sourceforge.net if your license should be
93 * GPL: http://www.gnu.org/copyleft/gpl.html
94 * LGPL: http://www.gnu.org/copyleft/lesser.html
95 * QPL: http://www.trolltech.com/licenses/qpl.html
96 * MPL: http://www.opensource.org/licenses/mozilla1.1.php
98 static gchar *valid_licenses[] = {
99 "LGPL", /* GNU Lesser General Public License */
100 "GPL", /* GNU General Public License */
101 "QPL", /* Trolltech Qt Public License */
102 "GPL/QPL", /* Combi-license of GPL + QPL */
103 "MPL", /* MPL 1.1 license */
104 "Proprietary", /* Proprietary license */
105 GST_LICENSE_UNKNOWN, /* some other license */
109 static GstPlugin *gst_plugin_register_func (GstPlugin * plugin,
110 GModule * module, GstPluginDesc * desc);
112 gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src);
113 static void gst_plugin_desc_free (GstPluginDesc * desc);
116 G_DEFINE_TYPE (GstPlugin, gst_plugin, GST_TYPE_OBJECT);
118 static GstObjectClass *parent_class = NULL;
121 gst_plugin_init (GstPlugin * plugin)
127 gst_plugin_finalize (GObject * object)
129 GstPlugin *plugin = GST_PLUGIN (object);
130 GstRegistry *registry = gst_registry_get_default ();
133 GST_DEBUG ("finalizing plugin %p", plugin);
134 for (g = registry->plugins; g; g = g->next) {
135 if (g->data == (gpointer) plugin) {
136 g_warning ("removing plugin that is still in registry");
139 g_free (plugin->filename);
140 g_free (plugin->basename);
141 gst_plugin_desc_free (&plugin->desc);
143 G_OBJECT_CLASS (parent_class)->finalize (object);
147 gst_plugin_class_init (GstPluginClass * klass)
149 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
151 G_OBJECT_CLASS (klass)->finalize = GST_DEBUG_FUNCPTR (gst_plugin_finalize);
155 gst_plugin_error_quark (void)
157 static GQuark quark = 0;
160 quark = g_quark_from_static_string ("gst_plugin_error");
164 /* this function can be called in the GCC constructor extension, before
165 * the _gst_plugin_initialize() was called. In that case, we store the
166 * plugin description in a list to initialize it when we open the main
168 * When the main module is known, we can register the plugin right away.
171 _gst_plugin_register_static (GstPluginDesc * desc)
173 if (main_module == NULL) {
175 GST_LOG ("queueing static plugin \"%s\" for loading later on",
177 _gst_plugin_static = g_list_prepend (_gst_plugin_static, desc);
182 GST_LOG ("attempting to load static plugin \"%s\" now...", desc->name);
183 plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
184 if (gst_plugin_register_func (plugin, main_module, desc)) {
186 GST_INFO ("loaded static plugin \"%s\"", desc->name);
187 gst_default_registry_add_plugin (plugin);
193 _gst_plugin_initialize (void)
195 main_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
197 /* now register all static plugins */
198 g_list_foreach (_gst_plugin_static, (GFunc) _gst_plugin_register_static,
202 /* this function could be extended to check if the plugin license matches the
203 * applications license (would require the app to register its license somehow).
204 * We'll wait for someone who's interested in it to code it :)
207 gst_plugin_check_license (const gchar * license)
209 gchar **check_license = valid_licenses;
211 g_assert (check_license);
213 while (*check_license) {
214 if (strcmp (license, *check_license) == 0)
222 gst_plugin_check_version (gint major, gint minor)
224 /* return NULL if the major and minor version numbers are not compatible */
226 if (major != GST_VERSION_MAJOR || minor != GST_VERSION_MINOR)
233 gst_plugin_register_func (GstPlugin * plugin, GModule * module,
234 GstPluginDesc * desc)
236 if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
238 GST_WARNING ("plugin \"%s\" has incompatible version, not loading",
243 if (!desc->license || !desc->description || !desc->source ||
244 !desc->package || !desc->origin) {
246 GST_WARNING ("plugin \"%s\" has incorrect GstPluginDesc, not loading",
251 if (!gst_plugin_check_license (desc->license)) {
253 GST_WARNING ("plugin \"%s\" has invalid license \"%s\", not loading",
254 plugin->filename, desc->license);
259 GST_LOG ("plugin \"%s\" looks good", GST_STR_NULL (plugin->filename));
261 gst_plugin_desc_copy (&plugin->desc, desc);
263 if (!((desc->plugin_init) (plugin))) {
265 GST_WARNING ("plugin \"%s\" failed to initialise", plugin->filename);
266 plugin->module = NULL;
271 GST_LOG ("plugin \"%s\" initialised", GST_STR_NULL (plugin->filename));
278 * _gst_plugin_fault_handler_restore:
279 * segfault handler restorer
282 _gst_plugin_fault_handler_restore (void)
284 struct sigaction action;
286 memset (&action, 0, sizeof (action));
287 action.sa_handler = SIG_DFL;
289 sigaction (SIGSEGV, &action, NULL);
293 * _gst_plugin_fault_handler_sighandler:
294 * segfault handler implementation
297 _gst_plugin_fault_handler_sighandler (int signum)
299 /* We need to restore the fault handler or we'll keep getting it */
300 _gst_plugin_fault_handler_restore ();
304 g_print ("\nERROR: ");
305 g_print ("Caught a segmentation fault while loading plugin file:\n");
306 g_print ("%s\n\n", _gst_plugin_fault_handler_filename);
307 g_print ("Please either:\n");
308 g_print ("- remove it and restart.\n");
309 g_print ("- run with --gst-disable-segtrap and debug.\n");
313 g_print ("Caught unhandled signal on plugin loading\n");
319 * _gst_plugin_fault_handler_setup:
320 * sets up the segfault handler
323 _gst_plugin_fault_handler_setup (void)
325 struct sigaction action;
327 /* if asked to leave segfaults alone, just return */
328 if (_gst_disable_segtrap)
331 if (_gst_plugin_fault_handler_is_setup)
334 memset (&action, 0, sizeof (action));
335 action.sa_handler = _gst_plugin_fault_handler_sighandler;
337 sigaction (SIGSEGV, &action, NULL);
341 _gst_plugin_fault_handler_restore (void)
346 _gst_plugin_fault_handler_setup (void)
351 static void _gst_plugin_fault_handler_setup ();
353 GStaticMutex gst_plugin_loading_mutex = G_STATIC_MUTEX_INIT;
356 * gst_plugin_load_file:
357 * @filename: the plugin filename to load
358 * @error: pointer to a NULL-valued GError
360 * Loads the given plugin and refs it. Caller needs to unref after use.
362 * Returns: a reference to the existing loaded GstPlugin, a reference to the
363 * newly-loaded GstPlugin, or NULL if an error occurred.
366 gst_plugin_load_file (const gchar * filename, GError ** error)
372 struct stat file_status;
373 GstRegistry *registry;
375 g_return_val_if_fail (filename != NULL, NULL);
377 registry = gst_registry_get_default ();
378 g_static_mutex_lock (&gst_plugin_loading_mutex);
380 plugin = gst_registry_lookup (registry, filename);
382 if (plugin->module) {
383 g_static_mutex_unlock (&gst_plugin_loading_mutex);
386 gst_object_unref (plugin);
391 GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "attempt to load plugin \"%s\"",
394 if (g_module_supported () == FALSE) {
395 GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "module loading not supported");
398 GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported");
402 if (stat (filename, &file_status)) {
403 GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "problem accessing file");
406 GST_PLUGIN_ERROR_MODULE, "Problem accessing file %s: %s\n", filename,
411 module = g_module_open (filename, G_MODULE_BIND_LOCAL);
412 if (module == NULL) {
413 GST_CAT_WARNING (GST_CAT_PLUGIN_LOADING, "module_open failed: %s",
416 GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Opening module failed");
420 plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
422 plugin->module = module;
423 plugin->filename = g_strdup (filename);
424 plugin->basename = g_path_get_basename (filename);
425 plugin->file_mtime = file_status.st_mtime;
426 plugin->file_size = file_status.st_size;
428 ret = g_module_symbol (module, "gst_plugin_desc", &ptr);
430 GST_DEBUG ("Could not find plugin entry point in \"%s\"", filename);
433 GST_PLUGIN_ERROR_MODULE,
434 "File \"%s\" is not a GStreamer plugin", filename);
437 plugin->orig_desc = (GstPluginDesc *) ptr;
439 GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
442 /* this is where we load the actual .so, so let's trap SIGSEGV */
443 _gst_plugin_fault_handler_setup ();
444 _gst_plugin_fault_handler_filename = plugin->filename;
446 GST_LOG ("Plugin %p for file \"%s\" prepared, registering...",
449 if (!gst_plugin_register_func (plugin, module, plugin->orig_desc)) {
450 /* remove signal handler */
451 _gst_plugin_fault_handler_restore ();
452 GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename);
456 GST_PLUGIN_ERROR_MODULE,
457 "File \"%s\" appears to be a GStreamer plugin, but it failed to initialize",
459 g_module_close (module);
463 /* remove signal handler */
464 _gst_plugin_fault_handler_restore ();
465 _gst_plugin_fault_handler_filename = NULL;
466 GST_INFO ("plugin \"%s\" loaded", plugin->filename);
468 gst_object_ref (plugin);
469 gst_default_registry_add_plugin (plugin);
471 g_static_mutex_unlock (&gst_plugin_loading_mutex);
477 gst_object_unref (plugin);
478 g_static_mutex_unlock (&gst_plugin_loading_mutex);
484 gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src)
486 dest->major_version = src->major_version;
487 dest->minor_version = src->minor_version;
488 dest->name = g_strdup (src->name);
489 dest->description = g_strdup (src->description);
490 dest->plugin_init = src->plugin_init;
491 dest->version = g_strdup (src->version);
492 dest->license = g_strdup (src->license);
493 dest->source = g_strdup (src->source);
494 dest->package = g_strdup (src->package);
495 dest->origin = g_strdup (src->origin);
500 gst_plugin_desc_free (GstPluginDesc * desc)
503 g_free (desc->description);
504 g_free (desc->version);
505 g_free (desc->license);
506 g_free (desc->source);
507 g_free (desc->package);
508 g_free (desc->origin);
510 memset (desc, 0, sizeof (GstPluginDesc));
514 * gst_plugin_get_name:
515 * @plugin: plugin to get the name of
517 * Get the short name of the plugin
519 * Returns: the name of the plugin
522 gst_plugin_get_name (GstPlugin * plugin)
524 g_return_val_if_fail (plugin != NULL, NULL);
526 return plugin->desc.name;
530 * gst_plugin_get_description:
531 * @plugin: plugin to get long name of
533 * Get the long descriptive name of the plugin
535 * Returns: the long name of the plugin
537 G_CONST_RETURN gchar *
538 gst_plugin_get_description (GstPlugin * plugin)
540 g_return_val_if_fail (plugin != NULL, NULL);
542 return plugin->desc.description;
546 * gst_plugin_get_filename:
547 * @plugin: plugin to get the filename of
549 * get the filename of the plugin
551 * Returns: the filename of the plugin
553 G_CONST_RETURN gchar *
554 gst_plugin_get_filename (GstPlugin * plugin)
556 g_return_val_if_fail (plugin != NULL, NULL);
558 return plugin->filename;
562 * gst_plugin_get_version:
563 * @plugin: plugin to get the version of
565 * get the version of the plugin
567 * Returns: the version of the plugin
569 G_CONST_RETURN gchar *
570 gst_plugin_get_version (GstPlugin * plugin)
572 g_return_val_if_fail (plugin != NULL, NULL);
574 return plugin->desc.version;
578 * gst_plugin_get_license:
579 * @plugin: plugin to get the license of
581 * get the license of the plugin
583 * Returns: the license of the plugin
585 G_CONST_RETURN gchar *
586 gst_plugin_get_license (GstPlugin * plugin)
588 g_return_val_if_fail (plugin != NULL, NULL);
590 return plugin->desc.license;
594 * gst_plugin_get_source:
595 * @plugin: plugin to get the source of
597 * get the source module the plugin belongs to.
599 * Returns: the source of the plugin
601 G_CONST_RETURN gchar *
602 gst_plugin_get_source (GstPlugin * plugin)
604 g_return_val_if_fail (plugin != NULL, NULL);
606 return plugin->desc.source;
610 * gst_plugin_get_package:
611 * @plugin: plugin to get the package of
613 * get the package the plugin belongs to.
615 * Returns: the package of the plugin
617 G_CONST_RETURN gchar *
618 gst_plugin_get_package (GstPlugin * plugin)
620 g_return_val_if_fail (plugin != NULL, NULL);
622 return plugin->desc.package;
626 * gst_plugin_get_origin:
627 * @plugin: plugin to get the origin of
629 * get the URL where the plugin comes from
631 * Returns: the origin of the plugin
633 G_CONST_RETURN gchar *
634 gst_plugin_get_origin (GstPlugin * plugin)
636 g_return_val_if_fail (plugin != NULL, NULL);
638 return plugin->desc.origin;
642 * gst_plugin_get_module:
643 * @plugin: plugin to query
645 * Gets the #GModule of the plugin. If the plugin isn't loaded yet, NULL is
648 * Returns: module belonging to the plugin or NULL if the plugin isn't
652 gst_plugin_get_module (GstPlugin * plugin)
654 g_return_val_if_fail (plugin != NULL, NULL);
656 return plugin->module;
660 * gst_plugin_is_loaded:
661 * @plugin: plugin to query
663 * queries if the plugin is loaded into memory
665 * Returns: TRUE is loaded, FALSE otherwise
668 gst_plugin_is_loaded (GstPlugin * plugin)
670 g_return_val_if_fail (plugin != NULL, FALSE);
672 return (plugin->module != NULL || plugin->filename == NULL);
677 * gst_plugin_feature_list:
678 * @plugin: plugin to query
679 * @filter: the filter to use
680 * @first: only return first match
681 * @user_data: user data passed to the filter function
683 * Runs a filter against all plugin features and returns a GList with
684 * the results. If the first flag is set, only the first match is
685 * returned (as a list with a single object).
687 * Returns: a GList of features, g_list_free after use.
690 gst_plugin_feature_filter (GstPlugin * plugin,
691 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
696 list = gst_filter_run (plugin->features, (GstFilterFunc) filter, first,
698 for (g = list; g; g = g->next) {
699 gst_object_ref (plugin);
707 GstPluginFeatureFilter filter;
715 _feature_filter (GstPlugin * plugin, gpointer user_data)
718 FeatureFilterData *data = (FeatureFilterData *) user_data;
720 result = gst_plugin_feature_filter (plugin, data->filter, data->first,
723 data->result = g_list_concat (data->result, result);
730 * gst_plugin_list_feature_filter:
731 * @list: a #GList of plugins to query
732 * @filter: the filter function to use
733 * @first: only return first match
734 * @user_data: user data passed to the filter function
736 * Runs a filter against all plugin features of the plugins in the given
737 * list and returns a GList with the results.
738 * If the first flag is set, only the first match is
739 * returned (as a list with a single object).
741 * Returns: a GList of features, g_list_free after use.
744 gst_plugin_list_feature_filter (GList * list,
745 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
747 FeatureFilterData data;
750 data.filter = filter;
752 data.user_data = user_data;
755 result = gst_filter_run (list, (GstFilterFunc) _feature_filter, first, &data);
756 g_list_free (result);
763 * gst_plugin_name_filter:
764 * @plugin: the plugin to check
765 * @name: the name of the plugin
767 * A standard filter that returns TRUE when the plugin is of the
770 * Returns: TRUE if the plugin is of the given name.
773 gst_plugin_name_filter (GstPlugin * plugin, const gchar * name)
775 return (plugin->desc.name && !strcmp (plugin->desc.name, name));
780 * gst_plugin_find_feature:
781 * @plugin: plugin to get the feature from
782 * @name: The name of the feature to find
783 * @type: The type of the feature to find
785 * Find a feature of the given name and type in the given plugin.
787 * Returns: a GstPluginFeature or NULL if the feature was not found.
790 gst_plugin_find_feature (GstPlugin * plugin, const gchar * name, GType type)
793 GstPluginFeature *result = NULL;
794 GstTypeNameData data;
796 g_return_val_if_fail (name != NULL, NULL);
801 walk = gst_filter_run (plugin->features,
802 (GstFilterFunc) gst_plugin_feature_type_name_filter, TRUE, &data);
805 result = GST_PLUGIN_FEATURE (walk->data);
807 gst_object_ref (result);
808 gst_plugin_feature_list_free (walk);
817 gst_plugin_feature_name_filter (GstPluginFeature * feature, const gchar * name)
819 return !strcmp (name, GST_PLUGIN_FEATURE_NAME (feature));
825 * gst_plugin_find_feature_by_name:
826 * @plugin: plugin to get the feature from
827 * @name: The name of the feature to find
829 * Find a feature of the given name in the given plugin.
831 * Returns: a GstPluginFeature or NULL if the feature was not found.
834 gst_plugin_find_feature_by_name (GstPlugin * plugin, const gchar * name)
837 GstPluginFeature *result = NULL;
839 g_return_val_if_fail (name != NULL, NULL);
841 walk = gst_filter_run (plugin->features,
842 (GstFilterFunc) gst_plugin_feature_name_filter, TRUE, (void *) name);
845 result = GST_PLUGIN_FEATURE (walk->data);
847 gst_object_ref (result);
848 gst_plugin_feature_list_free (walk);
856 * gst_plugin_load_by_name:
857 * @name: name of plugin to load
859 * Load the named plugin. Refs the plugin.
861 * Returns: A reference to a loaded plugin, or NULL on error.
864 gst_plugin_load_by_name (const gchar * name)
866 GstPlugin *plugin, *newplugin;
867 GError *error = NULL;
869 GST_DEBUG ("looking up plugin %s in default registry", name);
870 plugin = gst_registry_find_plugin (gst_registry_get_default (), name);
872 GST_DEBUG ("loading plugin %s from file %s", name, plugin->filename);
873 newplugin = gst_plugin_load_file (plugin->filename, &error);
874 gst_object_unref (plugin);
877 GST_WARNING ("load_plugin error: %s\n", error->message);
878 g_error_free (error);
881 /* newplugin was reffed by load_file */
885 GST_DEBUG ("Could not find plugin %s in registry", name);
891 * @plugin: plugin to load
893 * Loads @plugin. Note that the *return value* is the loaded plugin; @plugin is
894 * untouched. The normal use pattern of this function goes like this:
897 * GstPlugin *loaded_plugin;
898 * loaded_plugin = gst_plugin_load (plugin);
899 * // presumably, we're no longer interested in the potentially-unloaded plugin
900 * gst_object_unref (plugin);
901 * plugin = loaded_plugin;
904 * Returns: A reference to a loaded plugin, or NULL on error.
907 gst_plugin_load (GstPlugin * plugin)
909 GError *error = NULL;
910 GstPlugin *newplugin;
912 if (gst_plugin_is_loaded (plugin)) {
916 if (!(newplugin = gst_plugin_load_file (plugin->filename, &error)))
923 GST_WARNING ("load_plugin error: %s\n", error->message);
924 g_error_free (error);
930 * gst_plugin_list_free:
931 * @list: list of #GstPlugin
933 * Unrefs each member of @list, then frees the list.
936 gst_plugin_list_free (GList * list)
940 for (g = list; g; g = g->next) {
941 gst_object_unref (GST_PLUGIN (g->data));