2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 * 2005 David A. Schleef <ds@schleef.org>
6 * gstregistry.c: handle registry
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
26 * @short_description: Abstract base class for management of #GstPlugin objects
27 * @see_also: #GstPlugin, #GstPluginFeature
29 * One registry holds the metadata of a set of plugins.
30 * All registries build the #GstRegistryPool.
36 #include "gst_private.h"
38 #include <sys/types.h>
49 #include "gstregistry.h"
50 #include "gstmarshal.h"
51 #include "gstfilter.h"
53 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
55 /* the one instance of the default registry */
56 static GstRegistry *_gst_registry_default = NULL;
61 * The GstRegistry object is a list of plugins and some functions
62 * for dealing with them. Plugins are matched 1-1 with a file on
63 * disk, and may or may not be loaded at a given time. There may
64 * be multiple GstRegistry objects, but the "default registry" is
65 * the only object that has any meaning to the core.
67 * The registry.xml file in 0.9 is actually a cache of plugin
68 * information. This is unlike previous versions, where the registry
69 * file was the primary source of plugin information, and was created
70 * by the gst-register command.
72 * In 0.9, the primary source, at all times, of plugin information
73 * is each plugin file itself. Thus, if an application wants
74 * information about a particular plugin, or wants to search for
75 * a feature that satisfies given criteria, the primary means of
76 * doing so is to load every plugin and look at the resulting
77 * information that is gathered in the default registry. Clearly,
78 * this is a time consuming process, so we cache information in
79 * the registry.xml file.
81 * On startup, plugins are searched for in the plugin search path.
82 * This path can be set directly using the GST_PLUGIN_PATH
83 * environment variable. The registry file is loaded from
84 * ~/.gstreamer-0.9/registry.xml or the file listed in the
85 * GST_REGISTRY env var. The only reason to change the registry
86 * location is for testing.
88 * For each plugin that is found in the plugin search path, there
89 * could be 3 possibilities for cached information:
90 * - the cache may not contain information about a given file.
91 * - the cache may have stale information.
92 * - the cache may have current information.
93 * In the first two cases, the plugin is loaded and the cache
94 * updated. In addition to these cases, the cache may have entries
95 * for plugins that are not relevant to the current process. These
96 * are marked as not available to the current process. If the
97 * cache is updated for whatever reason, it is marked dirty.
99 * A dirty cache is written out at the end of initialization. Each
100 * entry is checked to make sure the information is minimally valid.
101 * If not, the entry is simply dropped.
103 * Implementation notes:
105 * The "cache" and "default registry" are different concepts and
106 * can represent different sets of plugins. For various reasons,
107 * at init time, the cache is stored in the default registry, and
108 * plugins not relevant to the current process are marked with the
109 * GST_PLUGIN_FLAG_CACHED bit. These plugins are removed at the
110 * end of intitialization.
114 /* Element signals and args */
122 static void gst_registry_class_init (GstRegistryClass * klass);
123 static void gst_registry_init (GstRegistry * registry);
124 static void gst_registry_finalize (GObject * object);
126 static guint gst_registry_signals[LAST_SIGNAL] = { 0 };
128 static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry *
129 registry, const char *name);
130 static GstPlugin *gst_registry_lookup_locked (GstRegistry * registry,
131 const char *filename);
133 G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT);
134 static GstObjectClass *parent_class = NULL;
137 gst_registry_class_init (GstRegistryClass * klass)
139 GObjectClass *gobject_class;
141 gobject_class = (GObjectClass *) klass;
143 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
145 gst_registry_signals[PLUGIN_ADDED] =
146 g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass),
147 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL,
148 NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
149 gst_registry_signals[FEATURE_ADDED] =
150 g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass),
151 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, feature_added),
152 NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
154 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_registry_finalize);
158 gst_registry_init (GstRegistry * registry)
163 gst_registry_finalize (GObject * object)
165 GstRegistry *registry = GST_REGISTRY (object);
169 plugins = registry->plugins;
170 registry->plugins = NULL;
172 GST_DEBUG_OBJECT (registry, "registry finalize");
175 GstPlugin *plugin = p->data;
178 GST_DEBUG_OBJECT (registry, "removing plugin %s",
179 gst_plugin_get_name (plugin));
180 gst_registry_remove_plugin (registry, plugin);
184 g_list_free (plugins);
186 features = registry->features;
187 registry->features = NULL;
191 GstPluginFeature *feature = f->data;
194 gst_registry_remove_feature (registry, feature);
198 g_list_free (features);
201 G_OBJECT_CLASS (parent_class)->finalize (object);
205 * gst_registry_get_default:
207 * Retrieves the default registry. The caller does not own a reference on the
208 * registry, as it is alive as long as GStreamer is initialized.
211 gst_registry_get_default (void)
213 if (!_gst_registry_default) {
214 _gst_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL);
216 return _gst_registry_default;
220 * gst_registry_add_path:
221 * @registry: the registry to add the path to
222 * @path: the path to add to the registry
224 * Add the given path to the registry. The syntax of the
225 * path is specific to the registry. If the path has already been
229 gst_registry_add_path (GstRegistry * registry, const gchar * path)
231 g_return_if_fail (GST_IS_REGISTRY (registry));
232 g_return_if_fail (path != NULL);
234 if (strlen (path) == 0) {
235 GST_INFO ("Ignoring empty plugin path");
240 if (g_list_find_custom (registry->paths, path, (GCompareFunc) strcmp)) {
241 g_warning ("path %s already added to registry", path);
242 GST_UNLOCK (registry);
246 GST_INFO ("Adding plugin path: \"%s\"", path);
247 registry->paths = g_list_append (registry->paths, g_strdup (path));
248 GST_UNLOCK (registry);
252 * gst_registry_get_path_list:
253 * @registry: the registry to get the pathlist of
255 * Get the list of paths for the given registry.
257 * Returns: A Glist of paths as strings. g_list_free after use.
260 gst_registry_get_path_list (GstRegistry * registry)
264 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
267 /* We don't need to copy the strings, because they won't be deleted
268 * as long as the GstRegistry is around */
269 list = g_list_copy (registry->paths);
270 GST_UNLOCK (registry);
277 * gst_registry_add_plugin:
278 * @registry: the registry to add the plugin to
279 * @plugin: the plugin to add
281 * Add the plugin to the registry. The plugin-added signal will be emitted.
283 * Returns: TRUE on success.
286 gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
288 GstPlugin *existing_plugin;
290 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
293 existing_plugin = gst_registry_lookup_locked (registry, plugin->filename);
294 if (existing_plugin) {
295 GST_DEBUG_OBJECT (registry,
296 "Replacing existing plugin %p with new plugin %p for filename \"%s\"",
297 existing_plugin, plugin, GST_STR_NULL (plugin->filename));
298 registry->plugins = g_list_remove (registry->plugins, existing_plugin);
299 gst_object_unref (existing_plugin);
302 GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"",
303 plugin, GST_STR_NULL (plugin->filename));
305 registry->plugins = g_list_prepend (registry->plugins, plugin);
307 gst_object_ref (plugin);
308 gst_object_sink (plugin);
309 GST_UNLOCK (registry);
311 GST_DEBUG_OBJECT (registry, "emitting plugin-added for filename \"%s\"",
312 GST_STR_NULL (plugin->filename));
313 g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0,
320 * gst_registry_remove_plugin:
321 * @registry: the registry to remove the plugin from
322 * @plugin: the plugin to remove
324 * Remove the plugin from the registry.
327 gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
329 g_return_if_fail (GST_IS_REGISTRY (registry));
332 registry->plugins = g_list_remove (registry->plugins, plugin);
333 GST_UNLOCK (registry);
334 gst_object_unref (plugin);
338 * gst_registry_add_feature:
339 * @registry: the registry to add the plugin to
340 * @feature: the feature to add
342 * Add the feature to the registry. The feature-added signal will be emitted.
344 * Returns: TRUE on success.
347 gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
349 GstPluginFeature *existing_feature;
351 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
352 g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
353 g_return_val_if_fail (feature->name != NULL, FALSE);
354 g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
357 existing_feature = gst_registry_lookup_feature_locked (registry,
359 if (existing_feature) {
360 GST_DEBUG_OBJECT (registry, "Replacing existing feature %p (%s)",
361 existing_feature, feature->name);
362 registry->features = g_list_remove (registry->features, existing_feature);
363 gst_object_unref (existing_feature);
366 GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
368 registry->features = g_list_prepend (registry->features, feature);
370 gst_object_ref (feature);
371 gst_object_sink (feature);
372 GST_UNLOCK (registry);
374 GST_DEBUG_OBJECT (registry, "emitting feature-added for %s", feature->name);
375 g_signal_emit (G_OBJECT (registry), gst_registry_signals[FEATURE_ADDED], 0,
382 * gst_registry_remove_feature:
383 * @registry: the registry to remove the feature from
384 * @feature: the feature to remove
386 * Remove the feature from the registry.
389 gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
391 g_return_if_fail (GST_IS_REGISTRY (registry));
392 GST_DEBUG_OBJECT (registry, "removing feature %p (%s)",
393 feature, gst_plugin_feature_get_name (feature));
396 registry->features = g_list_remove (registry->features, feature);
397 GST_UNLOCK (registry);
398 gst_object_unref (feature);
402 * gst_registry_plugin_filter:
403 * @registry: registry to query
404 * @filter: the filter to use
405 * @first: only return first match
406 * @user_data: user data passed to the filter function
408 * Runs a filter against all plugins in the registry and returns a GList with
409 * the results. If the first flag is set, only the first match is
410 * returned (as a list with a single object).
411 * Every plugin is reffed; use gst_plugin_list_free() after use, which
414 * Returns: a #GList of #GstPlugin
417 gst_registry_plugin_filter (GstRegistry * registry,
418 GstPluginFilter filter, gboolean first, gpointer user_data)
423 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
426 list = gst_filter_run (registry->plugins, (GstFilterFunc) filter, first,
428 for (g = list; g; g = g->next) {
429 gst_object_ref (GST_PLUGIN (g->data));
431 GST_UNLOCK (registry);
437 * gst_registry_feature_filter:
438 * @registry: registry to query
439 * @filter: the filter to use
440 * @first: only return first match
441 * @user_data: user data passed to the filter function
443 * Runs a filter against all features of the plugins in the registry
444 * and returns a GList with the results.
445 * If the first flag is set, only the first match is
446 * returned (as a list with a single object).
448 * Returns: a GList of plugin features, gst_plugin_feature_list_free after use.
451 gst_registry_feature_filter (GstRegistry * registry,
452 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
457 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
460 list = gst_filter_run (registry->features, (GstFilterFunc) filter, first,
462 for (g = list; g; g = g->next) {
463 gst_object_ref (GST_PLUGIN_FEATURE (g->data));
465 GST_UNLOCK (registry);
471 * gst_registry_find_plugin:
472 * @registry: the registry to search
473 * @name: the plugin name to find
475 * Find the plugin with the given name in the registry.
476 * The plugin will be reffed; caller is responsible for unreffing.
478 * Returns: The plugin with the given name or NULL if the plugin was not found.
481 gst_registry_find_plugin (GstRegistry * registry, const gchar * name)
484 GstPlugin *result = NULL;
486 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
487 g_return_val_if_fail (name != NULL, NULL);
489 walk = gst_registry_plugin_filter (registry,
490 (GstPluginFilter) gst_plugin_name_filter, TRUE, (gpointer) name);
492 result = GST_PLUGIN (walk->data);
494 gst_object_ref (result);
495 gst_plugin_list_free (walk);
502 * gst_registry_find_feature:
503 * @registry: the registry to search
504 * @name: the pluginfeature name to find
505 * @type: the pluginfeature type to find
507 * Find the pluginfeature with the given name and type in the registry.
509 * Returns: The pluginfeature with the given name and type or NULL
510 * if the plugin was not found.
513 gst_registry_find_feature (GstRegistry * registry, const gchar * name,
516 GstPluginFeature *feature = NULL;
518 GstTypeNameData data;
520 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
521 g_return_val_if_fail (name != NULL, NULL);
526 walk = gst_registry_feature_filter (registry,
527 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
531 feature = GST_PLUGIN_FEATURE (walk->data);
533 gst_object_ref (feature);
534 gst_plugin_feature_list_free (walk);
541 gst_registry_get_feature_list (GstRegistry * registry, GType type)
543 GstTypeNameData data;
548 return gst_registry_feature_filter (registry,
549 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
554 gst_registry_get_plugin_list (GstRegistry * registry)
560 list = g_list_copy (registry->plugins);
561 for (g = list; g; g = g->next) {
562 gst_object_ref (GST_PLUGIN (g->data));
564 GST_UNLOCK (registry);
569 static GstPluginFeature *
570 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
573 GstPluginFeature *feature;
578 for (g = registry->features; g; g = g_list_next (g)) {
579 feature = GST_PLUGIN_FEATURE (g->data);
580 if (feature->name && strcmp (name, feature->name) == 0) {
589 gst_registry_lookup_feature (GstRegistry * registry, const char *name)
591 GstPluginFeature *feature;
594 feature = gst_registry_lookup_feature_locked (registry, name);
596 gst_object_ref (feature);
597 GST_UNLOCK (registry);
603 gst_registry_lookup_locked (GstRegistry * registry, const char *filename)
609 if (filename == NULL)
612 basename = g_path_get_basename (filename);
613 for (g = registry->plugins; g; g = g_list_next (g)) {
614 plugin = GST_PLUGIN (g->data);
615 if (plugin->basename && strcmp (basename, plugin->basename) == 0) {
626 * gst_registry_lookup:
627 * @registry: the registry to look up in
628 * @filename: the name of the file to look up
630 * Look up a plugin in the given registry with the given filename.
631 * If found, plugin is reffed. Caller must unref after use.
633 * Returns: the #GstPlugin if found, or NULL if not.
636 gst_registry_lookup (GstRegistry * registry, const char *filename)
641 plugin = gst_registry_lookup_locked (registry, filename);
643 gst_object_ref (plugin);
644 GST_UNLOCK (registry);
650 gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
657 GstPlugin *newplugin;
659 dir = g_dir_open (path, 0, NULL);
663 while ((dirent = g_dir_read_name (dir))) {
664 filename = g_strjoin ("/", path, dirent, NULL);
666 GST_LOG_OBJECT (registry, "examining file: %s", filename);
668 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
670 GST_LOG_OBJECT (registry, "found directory, recursing");
671 gst_registry_scan_path_level (registry, filename, level - 1);
673 GST_LOG_OBJECT (registry,
674 "found directory, but recursion level is too deep");
679 if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
680 GST_LOG_OBJECT (registry, "not a regular file, ignoring");
684 if (!g_str_has_suffix (filename, ".so") &&
685 !g_str_has_suffix (filename, ".dll") &&
686 !g_str_has_suffix (filename, ".dynlib")) {
687 GST_LOG_OBJECT (registry,
688 "extension is not recognized as module file, ignoring");
693 /* plug-ins are considered unique by basename; if the given name
694 * was already seen by the registry, we ignore it */
695 plugin = gst_registry_lookup (registry, filename);
697 struct stat file_status;
699 if (stat (filename, &file_status)) {
700 /* FIXME remove from cache */
704 if (plugin->registered) {
705 GST_DEBUG_OBJECT (registry,
706 "plugin already registered from path \"%s\"",
707 GST_STR_NULL (plugin->filename));
711 plugin->registered = TRUE;
712 if (plugin->file_mtime == file_status.st_mtime &&
713 plugin->file_size == file_status.st_size) {
714 GST_DEBUG_OBJECT (registry, "file %s cached", filename);
715 plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
717 GST_INFO_OBJECT (registry, "cached info for %s is stale", filename);
718 GST_DEBUG_OBJECT (registry, "mtime %ld != %ld or size %"
719 G_GSIZE_FORMAT " != %"
720 G_GSIZE_FORMAT, plugin->file_mtime, file_status.st_mtime,
721 plugin->file_size, file_status.st_size);
722 gst_registry_remove_plugin (gst_registry_get_default (), plugin);
723 newplugin = gst_plugin_load_file (filename, NULL);
725 gst_object_unref (newplugin);
727 gst_object_unref (plugin);
730 GST_DEBUG_OBJECT (registry, "file %s not yet in registry", filename);
731 newplugin = gst_plugin_load_file (filename, NULL);
733 newplugin->registered = TRUE;
734 gst_object_unref (newplugin);
745 * gst_registry_scan_path:
746 * @registry: the registry to add the path to
747 * @path: the path to add to the registry
749 * Add the given path to the registry. The syntax of the
750 * path is specific to the registry. If the path has already been
754 gst_registry_scan_path (GstRegistry * registry, const gchar * path)
756 GST_DEBUG_OBJECT (registry, "scanning path %s", path);
757 gst_registry_scan_path_level (registry, path, 10);
761 _gst_registry_remove_cache_plugins (GstRegistry * registry)
767 GST_DEBUG_OBJECT (registry, "removing cached plugins");
768 g = registry->plugins;
772 if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
773 GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"",
774 GST_STR_NULL (plugin->filename));
775 registry->plugins = g_list_remove (registry->plugins, plugin);
776 gst_object_unref (plugin);
784 _gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature,
787 return (strcmp (feature->plugin_name, (gchar *) user_data) == 0);
791 gst_registry_get_feature_list_by_plugin (GstRegistry * registry,
794 return gst_registry_feature_filter (registry,
795 _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name);
799 _gst_registry_cleanup ()
801 if (!_gst_registry_default)
804 gst_object_unref (_gst_registry_default);
805 _gst_registry_default = NULL;
809 * gst_default_registry_check_feature_version:
810 * @feature_name: the name of the feature (e.g. "oggdemux")
811 * @min_major: the minimum major version number
812 * @min_minor: the minimum minor version number
813 * @min_micro: the minimum micro version number
815 * Checks whether a plugin feature by the given name exists in the
816 * default registry and whether its version is at least the
819 * Returns: #TRUE if the feature could be found and the version is
820 * the same as the required version or newer, and #FALSE otherwise.
823 gst_default_registry_check_feature_version (const gchar * feature_name,
824 guint min_major, guint min_minor, guint min_micro)
826 GstPluginFeature *feature;
827 GstRegistry *registry;
828 gboolean ret = FALSE;
830 g_return_val_if_fail (feature_name != NULL, FALSE);
832 GST_DEBUG ("Looking up plugin feature '%s'", feature_name);
834 registry = gst_registry_get_default ();
835 feature = gst_registry_lookup_feature (registry, feature_name);
837 ret = gst_plugin_feature_check_version (feature, min_major, min_minor,
839 gst_object_unref (feature);
841 GST_DEBUG ("Could not find plugin feature '%s'", feature_name);