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.
25 * @short_description: Abstract base class for management of #GstPlugin objects
26 * @see_also: #GstPlugin, #GstPluginFeature
28 * One registry holds the metadata of a set of plugins.
29 * All registries build the #GstRegistryPool.
35 #include "gst_private.h"
37 #include <sys/types.h>
48 #include "gstregistry.h"
49 #include "gstmarshal.h"
50 #include "gstfilter.h"
52 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
54 /* the one instance of the default registry */
55 static GstRegistry *_gst_registry_default = NULL;
60 * The GstRegistry object is a list of plugins and some functions
61 * for dealing with them. Plugins are matched 1-1 with a file on
62 * disk, and may or may not be loaded at a given time. There may
63 * be multiple GstRegistry objects, but the "default registry" is
64 * the only object that has any meaning to the core.
66 * The registry.xml file in 0.9 is actually a cache of plugin
67 * information. This is unlike previous versions, where the registry
68 * file was the primary source of plugin information, and was created
69 * by the gst-register command.
71 * In 0.9, the primary source, at all times, of plugin information
72 * is each plugin file itself. Thus, if an application wants
73 * information about a particular plugin, or wants to search for
74 * a feature that satisfies given criteria, the primary means of
75 * doing so is to load every plugin and look at the resulting
76 * information that is gathered in the default registry. Clearly,
77 * this is a time consuming process, so we cache information in
78 * the registry.xml file.
80 * On startup, plugins are searched for in the plugin search path.
81 * This path can be set directly using the GST_PLUGIN_PATH
82 * environment variable. The registry file is loaded from
83 * ~/.gstreamer-0.9/registry.xml or the file listed in the
84 * GST_REGISTRY env var. The only reason to change the registry
85 * location is for testing.
87 * For each plugin that is found in the plugin search path, there
88 * could be 3 possibilities for cached information:
89 * - the cache may not contain information about a given file.
90 * - the cache may have stale information.
91 * - the cache may have current information.
92 * In the first two cases, the plugin is loaded and the cache
93 * updated. In addition to these cases, the cache may have entries
94 * for plugins that are not relevant to the current process. These
95 * are marked as not available to the current process. If the
96 * cache is updated for whatever reason, it is marked dirty.
98 * A dirty cache is written out at the end of initialization. Each
99 * entry is checked to make sure the information is minimally valid.
100 * If not, the entry is simply dropped.
102 * Implementation notes:
104 * The "cache" and "default registry" are different concepts and
105 * can represent different sets of plugins. For various reasons,
106 * at init time, the cache is stored in the default registry, and
107 * plugins not relevant to the current process are marked with the
108 * GST_PLUGIN_FLAG_CACHED bit. These plugins are removed at the
109 * end of intitialization.
113 /* Element signals and args */
121 static void gst_registry_class_init (GstRegistryClass * klass);
122 static void gst_registry_init (GstRegistry * registry);
123 static void gst_registry_finalize (GObject * object);
125 static guint gst_registry_signals[LAST_SIGNAL] = { 0 };
127 static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry *
128 registry, const char *name);
129 static GstPlugin *gst_registry_lookup_locked (GstRegistry * registry,
130 const char *filename);
132 G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT);
133 static GstObjectClass *parent_class = NULL;
136 gst_registry_class_init (GstRegistryClass * klass)
138 GObjectClass *gobject_class;
140 gobject_class = (GObjectClass *) klass;
142 parent_class = g_type_class_ref (GST_TYPE_OBJECT);
144 gst_registry_signals[PLUGIN_ADDED] =
145 g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass),
146 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL,
147 NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
148 gst_registry_signals[FEATURE_ADDED] =
149 g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass),
150 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, feature_added),
151 NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
153 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_registry_finalize);
157 gst_registry_init (GstRegistry * registry)
162 gst_registry_finalize (GObject * object)
164 GstRegistry *registry = GST_REGISTRY (object);
168 plugins = registry->plugins;
169 registry->plugins = NULL;
171 GST_DEBUG_OBJECT (registry, "registry finalize");
174 GstPlugin *plugin = p->data;
177 GST_DEBUG_OBJECT (registry, "removing plugin %s",
178 gst_plugin_get_name (plugin));
179 gst_registry_remove_plugin (registry, plugin);
183 g_list_free (plugins);
185 features = registry->features;
186 registry->features = NULL;
190 GstPluginFeature *feature = f->data;
193 gst_registry_remove_feature (registry, feature);
197 g_list_free (features);
200 G_OBJECT_CLASS (parent_class)->finalize (object);
204 * gst_registry_get_default:
206 * Retrieves the default registry. The caller does not own a reference on the
207 * registry, as it is alive as long as GStreamer is initialized.
210 gst_registry_get_default (void)
212 if (!_gst_registry_default) {
213 _gst_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL);
215 return _gst_registry_default;
219 * gst_registry_add_path:
220 * @registry: the registry to add the path to
221 * @path: the path to add to the registry
223 * Add the given path to the registry. The syntax of the
224 * path is specific to the registry. If the path has already been
228 gst_registry_add_path (GstRegistry * registry, const gchar * path)
230 g_return_if_fail (GST_IS_REGISTRY (registry));
231 g_return_if_fail (path != NULL);
233 if (strlen (path) == 0) {
234 GST_INFO ("Ignoring empty plugin path");
239 if (g_list_find_custom (registry->paths, path, (GCompareFunc) strcmp)) {
240 g_warning ("path %s already added to registry", path);
241 GST_UNLOCK (registry);
245 GST_INFO ("Adding plugin path: \"%s\"", path);
246 registry->paths = g_list_append (registry->paths, g_strdup (path));
247 GST_UNLOCK (registry);
251 * gst_registry_get_path_list:
252 * @registry: the registry to get the pathlist of
254 * Get the list of paths for the given registry.
256 * Returns: A Glist of paths as strings. g_list_free after use.
259 gst_registry_get_path_list (GstRegistry * registry)
263 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
266 /* We don't need to copy the strings, because they won't be deleted
267 * as long as the GstRegistry is around */
268 list = g_list_copy (registry->paths);
269 GST_UNLOCK (registry);
276 * gst_registry_add_plugin:
277 * @registry: the registry to add the plugin to
278 * @plugin: the plugin to add
280 * Add the plugin to the registry. The plugin-added signal will be emitted.
282 * Returns: TRUE on success.
285 gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
287 GstPlugin *existing_plugin;
289 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
292 existing_plugin = gst_registry_lookup_locked (registry, plugin->filename);
293 if (existing_plugin) {
294 GST_DEBUG_OBJECT (registry,
295 "Replacing existing plugin %p with new plugin %p for filename \"%s\"",
296 existing_plugin, plugin, plugin->filename);
297 registry->plugins = g_list_remove (registry->plugins, existing_plugin);
298 gst_object_unref (existing_plugin);
301 GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"",
302 plugin, plugin->filename);
304 registry->plugins = g_list_prepend (registry->plugins, plugin);
306 gst_object_ref (plugin);
307 gst_object_sink (plugin);
308 GST_UNLOCK (registry);
310 GST_DEBUG_OBJECT (registry, "emitting plugin-added for filename %s",
312 g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0,
319 * gst_registry_remove_plugin:
320 * @registry: the registry to remove the plugin from
321 * @plugin: the plugin to remove
323 * Remove the plugin from the registry.
326 gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
328 g_return_if_fail (GST_IS_REGISTRY (registry));
331 registry->plugins = g_list_remove (registry->plugins, plugin);
332 GST_UNLOCK (registry);
333 gst_object_unref (plugin);
337 * gst_registry_add_feature:
338 * @registry: the registry to add the plugin to
339 * @feature: the feature to add
341 * Add the feature to the registry. The feature-added signal will be emitted.
343 * Returns: TRUE on success.
346 gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
348 GstPluginFeature *existing_feature;
350 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
351 g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
352 g_return_val_if_fail (feature->name != NULL, FALSE);
353 g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
356 existing_feature = gst_registry_lookup_feature_locked (registry,
358 if (existing_feature) {
359 GST_DEBUG_OBJECT (registry, "Replacing existing feature %p (%s)",
360 existing_feature, feature->name);
361 registry->features = g_list_remove (registry->features, existing_feature);
362 gst_object_unref (existing_feature);
365 GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
367 registry->features = g_list_prepend (registry->features, feature);
369 gst_object_ref (feature);
370 gst_object_sink (feature);
371 GST_UNLOCK (registry);
373 GST_DEBUG_OBJECT (registry, "emitting feature-added for %s", feature->name);
374 g_signal_emit (G_OBJECT (registry), gst_registry_signals[FEATURE_ADDED], 0,
381 * gst_registry_remove_feature:
382 * @registry: the registry to remove the feature from
383 * @feature: the feature to remove
385 * Remove the feature from the registry.
388 gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
390 g_return_if_fail (GST_IS_REGISTRY (registry));
391 GST_DEBUG_OBJECT (registry, "removing feature %p (%s)",
392 feature, gst_plugin_feature_get_name (feature));
395 registry->features = g_list_remove (registry->features, feature);
396 GST_UNLOCK (registry);
397 gst_object_unref (feature);
401 * gst_registry_plugin_filter:
402 * @registry: registry to query
403 * @filter: the filter to use
404 * @first: only return first match
405 * @user_data: user data passed to the filter function
407 * Runs a filter against all plugins in the registry and returns a GList with
408 * the results. If the first flag is set, only the first match is
409 * returned (as a list with a single object).
410 * Every plugin is reffed; use gst_plugin_list_free() after use, which
413 * Returns: a #GList of #GstPlugin
416 gst_registry_plugin_filter (GstRegistry * registry,
417 GstPluginFilter filter, gboolean first, gpointer user_data)
422 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
425 list = gst_filter_run (registry->plugins, (GstFilterFunc) filter, first,
427 for (g = list; g; g = g->next) {
428 gst_object_ref (GST_PLUGIN (g->data));
430 GST_UNLOCK (registry);
436 * gst_registry_feature_filter:
437 * @registry: registry to query
438 * @filter: the filter to use
439 * @first: only return first match
440 * @user_data: user data passed to the filter function
442 * Runs a filter against all features of the plugins in the registry
443 * and returns a GList with the results.
444 * If the first flag is set, only the first match is
445 * returned (as a list with a single object).
447 * Returns: a GList of plugin features, gst_plugin_feature_list_free after use.
450 gst_registry_feature_filter (GstRegistry * registry,
451 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
456 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
459 list = gst_filter_run (registry->features, (GstFilterFunc) filter, first,
461 for (g = list; g; g = g->next) {
462 gst_object_ref (GST_PLUGIN_FEATURE (g->data));
464 GST_UNLOCK (registry);
470 * gst_registry_find_plugin:
471 * @registry: the registry to search
472 * @name: the plugin name to find
474 * Find the plugin with the given name in the registry.
475 * The plugin will be reffed; caller is responsible for unreffing.
477 * Returns: The plugin with the given name or NULL if the plugin was not found.
480 gst_registry_find_plugin (GstRegistry * registry, const gchar * name)
483 GstPlugin *result = NULL;
485 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
486 g_return_val_if_fail (name != NULL, NULL);
488 walk = gst_registry_plugin_filter (registry,
489 (GstPluginFilter) gst_plugin_name_filter, TRUE, (gpointer) name);
491 result = GST_PLUGIN (walk->data);
493 gst_object_ref (result);
494 gst_plugin_list_free (walk);
501 * gst_registry_find_feature:
502 * @registry: the registry to search
503 * @name: the pluginfeature name to find
504 * @type: the pluginfeature type to find
506 * Find the pluginfeature with the given name and type in the registry.
508 * Returns: The pluginfeature with the given name and type or NULL
509 * if the plugin was not found.
512 gst_registry_find_feature (GstRegistry * registry, const gchar * name,
515 GstPluginFeature *feature = NULL;
517 GstTypeNameData data;
519 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
520 g_return_val_if_fail (name != NULL, NULL);
525 walk = gst_registry_feature_filter (registry,
526 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
530 feature = GST_PLUGIN_FEATURE (walk->data);
532 gst_object_ref (feature);
533 gst_plugin_feature_list_free (walk);
540 gst_registry_get_feature_list (GstRegistry * registry, GType type)
542 GstTypeNameData data;
547 return gst_registry_feature_filter (registry,
548 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
553 gst_registry_get_plugin_list (GstRegistry * registry)
559 list = g_list_copy (registry->plugins);
560 for (g = list; g; g = g->next) {
561 gst_object_ref (GST_PLUGIN (g->data));
563 GST_UNLOCK (registry);
568 static GstPluginFeature *
569 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
572 GstPluginFeature *feature;
577 for (g = registry->features; g; g = g_list_next (g)) {
578 feature = GST_PLUGIN_FEATURE (g->data);
579 if (feature->name && strcmp (name, feature->name) == 0) {
588 gst_registry_lookup_feature (GstRegistry * registry, const char *name)
590 GstPluginFeature *feature;
593 feature = gst_registry_lookup_feature_locked (registry, name);
595 gst_object_ref (feature);
596 GST_UNLOCK (registry);
602 gst_registry_lookup_locked (GstRegistry * registry, const char *filename)
607 if (filename == NULL)
610 for (g = registry->plugins; g; g = g_list_next (g)) {
611 plugin = GST_PLUGIN (g->data);
612 if (plugin->filename && strcmp (filename, plugin->filename) == 0) {
621 * gst_registry_lookup:
622 * @registry: the registry to look up in
623 * @filename: the name of the file to look up
625 * Look up a plugin in the given registry with the given filename.
626 * If found, plugin is reffed. Caller must unref after use.
628 * Returns: the #GstPlugin if found, or NULL if not.
631 gst_registry_lookup (GstRegistry * registry, const char *filename)
636 plugin = gst_registry_lookup_locked (registry, filename);
638 gst_object_ref (plugin);
639 GST_UNLOCK (registry);
645 gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
652 GstPlugin *newplugin;
654 dir = g_dir_open (path, 0, NULL);
658 while ((dirent = g_dir_read_name (dir))) {
659 filename = g_strjoin ("/", path, dirent, NULL);
661 GST_LOG_OBJECT (registry, "examining file: %s", filename);
663 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
665 GST_LOG_OBJECT (registry, "found directory, recursing");
666 gst_registry_scan_path_level (registry, filename, level - 1);
668 GST_LOG_OBJECT (registry,
669 "found directory, but recursion level is too deep");
674 if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
675 GST_LOG_OBJECT (registry, "not a regular file, ignoring");
679 if (!g_str_has_suffix (filename, ".so") &&
680 !g_str_has_suffix (filename, ".dll") &&
681 !g_str_has_suffix (filename, ".dynlib")) {
682 GST_LOG_OBJECT (registry,
683 "extension is not recognized as module file, ignoring");
688 plugin = gst_registry_lookup (registry, filename);
690 struct stat file_status;
692 if (stat (filename, &file_status)) {
693 /* FIXME remove from cache */
698 if (plugin->file_mtime == file_status.st_mtime &&
699 plugin->file_size == file_status.st_size) {
700 GST_DEBUG_OBJECT (registry, "file %s cached", filename);
701 plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
703 GST_INFO_OBJECT (registry, "cached info for %s is stale", filename);
704 GST_DEBUG_OBJECT (registry, "mtime %ld != %ld or size %"
705 G_GSIZE_FORMAT " != %"
706 G_GSIZE_FORMAT, plugin->file_mtime, file_status.st_mtime,
707 plugin->file_size, file_status.st_size);
708 gst_registry_remove_plugin (gst_registry_get_default (), plugin);
709 newplugin = gst_plugin_load_file (filename, NULL);
711 gst_object_unref (newplugin);
713 gst_object_unref (plugin);
716 newplugin = gst_plugin_load_file (filename, NULL);
718 gst_object_unref (newplugin);
728 * gst_registry_scan_path:
729 * @registry: the registry to add the path to
730 * @path: the path to add to the registry
732 * Add the given path to the registry. The syntax of the
733 * path is specific to the registry. If the path has already been
737 gst_registry_scan_path (GstRegistry * registry, const gchar * path)
739 GST_DEBUG_OBJECT (registry, "scanning path %s", path);
740 gst_registry_scan_path_level (registry, path, 10);
744 _gst_registry_remove_cache_plugins (GstRegistry * registry)
750 GST_DEBUG_OBJECT (registry, "removing cached plugins");
751 g = registry->plugins;
755 if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
756 GST_DEBUG_OBJECT (registry, "removing cached plugin %s",
758 registry->plugins = g_list_remove (registry->plugins, plugin);
759 gst_object_unref (plugin);
767 _gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature,
770 return (strcmp (feature->plugin_name, (gchar *) user_data) == 0);
774 gst_registry_get_feature_list_by_plugin (GstRegistry * registry,
777 return gst_registry_feature_filter (registry,
778 _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name);
782 _gst_registry_cleanup ()
784 if (!_gst_registry_default)
787 gst_object_unref (_gst_registry_default);
788 _gst_registry_default = NULL;