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 (void)
206 if (!_gst_registry_default) {
207 _gst_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL);
209 return _gst_registry_default;
213 * gst_registry_add_path:
214 * @registry: the registry to add the path to
215 * @path: the path to add to the registry
217 * Add the given path to the registry. The syntax of the
218 * path is specific to the registry. If the path has already been
222 gst_registry_add_path (GstRegistry * registry, const gchar * path)
224 g_return_if_fail (GST_IS_REGISTRY (registry));
225 g_return_if_fail (path != NULL);
227 if (strlen (path) == 0) {
228 GST_INFO ("Ignoring empty plugin path");
233 if (g_list_find_custom (registry->paths, path, (GCompareFunc) strcmp)) {
234 g_warning ("path %s already added to registry", path);
235 GST_UNLOCK (registry);
239 GST_INFO ("Adding plugin path: \"%s\"", path);
240 registry->paths = g_list_append (registry->paths, g_strdup (path));
241 GST_UNLOCK (registry);
245 * gst_registry_get_path_list:
246 * @registry: the registry to get the pathlist of
248 * Get the list of paths for the given registry.
250 * Returns: A Glist of paths as strings. g_list_free after use.
253 gst_registry_get_path_list (GstRegistry * registry)
257 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
260 /* We don't need to copy the strings, because they won't be deleted
261 * as long as the GstRegistry is around */
262 list = g_list_copy (registry->paths);
263 GST_UNLOCK (registry);
270 * gst_registry_add_plugin:
271 * @registry: the registry to add the plugin to
272 * @plugin: the plugin to add
274 * Add the plugin to the registry. The plugin-added signal will be emitted.
276 * Returns: TRUE on success.
279 gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
281 GstPlugin *existing_plugin;
283 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
286 existing_plugin = gst_registry_lookup_locked (registry, plugin->filename);
287 if (existing_plugin) {
289 ("Replacing existing plugin %p with new plugin %p for filename \"%s\"",
290 existing_plugin, plugin, plugin->filename);
291 registry->plugins = g_list_remove (registry->plugins, existing_plugin);
292 gst_object_unref (existing_plugin);
295 GST_DEBUG ("adding plugin %p for filename \"%s\"", plugin, plugin->filename);
297 registry->plugins = g_list_prepend (registry->plugins, plugin);
299 gst_object_ref (plugin);
300 gst_object_sink (plugin);
301 GST_UNLOCK (registry);
303 GST_DEBUG ("emitting plugin-added for filename %s", plugin->filename);
304 g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0,
311 * gst_registry_remove_plugin:
312 * @registry: the registry to remove the plugin from
313 * @plugin: the plugin to remove
315 * Remove the plugin from the registry.
318 gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
320 g_return_if_fail (GST_IS_REGISTRY (registry));
323 registry->plugins = g_list_remove (registry->plugins, plugin);
324 GST_UNLOCK (registry);
325 gst_object_unref (plugin);
329 * gst_registry_add_feature:
330 * @registry: the registry to add the plugin to
331 * @feature: the feature to add
333 * Add the feature to the registry. The feature-added signal will be emitted.
335 * Returns: TRUE on success.
338 gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
340 GstPluginFeature *existing_feature;
342 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
343 g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
344 g_return_val_if_fail (feature->name != NULL, FALSE);
345 g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
348 existing_feature = gst_registry_lookup_feature_locked (registry,
350 if (existing_feature) {
351 GST_DEBUG_OBJECT (registry, "Replacing existing feature %p (%s)",
352 existing_feature, feature->name);
353 registry->features = g_list_remove (registry->features, existing_feature);
354 gst_object_unref (existing_feature);
357 GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
359 registry->features = g_list_prepend (registry->features, feature);
361 gst_object_ref (feature);
362 gst_object_sink (feature);
363 GST_UNLOCK (registry);
365 GST_DEBUG_OBJECT (registry, "emitting feature-added for %s", feature->name);
366 g_signal_emit (G_OBJECT (registry), gst_registry_signals[FEATURE_ADDED], 0,
373 * gst_registry_remove_feature:
374 * @registry: the registry to remove the feature from
375 * @feature: the feature to remove
377 * Remove the feature from the registry.
380 gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
382 g_return_if_fail (GST_IS_REGISTRY (registry));
383 GST_DEBUG_OBJECT (registry, "removing feature %p (%s)",
384 feature, gst_plugin_feature_get_name (feature));
387 registry->features = g_list_remove (registry->features, feature);
388 GST_UNLOCK (registry);
389 gst_object_unref (feature);
393 * gst_registry_plugin_filter:
394 * @registry: registry to query
395 * @filter: the filter to use
396 * @first: only return first match
397 * @user_data: user data passed to the filter function
399 * Runs a filter against all plugins in the registry and returns a GList with
400 * the results. If the first flag is set, only the first match is
401 * returned (as a list with a single object).
402 * Every plugin is reffed; use gst_plugin_list_free() after use, which
405 * Returns: a #GList of #GstPlugin
408 gst_registry_plugin_filter (GstRegistry * registry,
409 GstPluginFilter filter, gboolean first, gpointer user_data)
414 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
417 list = gst_filter_run (registry->plugins, (GstFilterFunc) filter, first,
419 for (g = list; g; g = g->next) {
420 gst_object_ref (GST_PLUGIN (g->data));
422 GST_UNLOCK (registry);
428 * gst_registry_feature_filter:
429 * @registry: registry to query
430 * @filter: the filter to use
431 * @first: only return first match
432 * @user_data: user data passed to the filter function
434 * Runs a filter against all features of the plugins in the registry
435 * and returns a GList with the results.
436 * If the first flag is set, only the first match is
437 * returned (as a list with a single object).
439 * Returns: a GList of plugin features, gst_plugin_feature_list_free after use.
442 gst_registry_feature_filter (GstRegistry * registry,
443 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
448 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
451 list = gst_filter_run (registry->features, (GstFilterFunc) filter, first,
453 for (g = list; g; g = g->next) {
454 gst_object_ref (GST_PLUGIN_FEATURE (g->data));
456 GST_UNLOCK (registry);
462 * gst_registry_find_plugin:
463 * @registry: the registry to search
464 * @name: the plugin name to find
466 * Find the plugin with the given name in the registry.
467 * The plugin will be reffed; caller is responsible for unreffing.
469 * Returns: The plugin with the given name or NULL if the plugin was not found.
472 gst_registry_find_plugin (GstRegistry * registry, const gchar * name)
475 GstPlugin *result = NULL;
477 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
478 g_return_val_if_fail (name != NULL, NULL);
480 walk = gst_registry_plugin_filter (registry,
481 (GstPluginFilter) gst_plugin_name_filter, TRUE, (gpointer) name);
483 result = GST_PLUGIN (walk->data);
485 gst_object_ref (result);
486 gst_plugin_list_free (walk);
493 * gst_registry_find_feature:
494 * @registry: the registry to search
495 * @name: the pluginfeature name to find
496 * @type: the pluginfeature type to find
498 * Find the pluginfeature with the given name and type in the registry.
500 * Returns: The pluginfeature with the given name and type or NULL
501 * if the plugin was not found.
504 gst_registry_find_feature (GstRegistry * registry, const gchar * name,
507 GstPluginFeature *feature = NULL;
509 GstTypeNameData data;
511 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
512 g_return_val_if_fail (name != NULL, NULL);
517 walk = gst_registry_feature_filter (registry,
518 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
522 feature = GST_PLUGIN_FEATURE (walk->data);
524 gst_object_ref (feature);
525 gst_plugin_feature_list_free (walk);
532 gst_registry_get_feature_list (GstRegistry * registry, GType type)
534 GstTypeNameData data;
539 return gst_registry_feature_filter (registry,
540 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
545 gst_registry_get_plugin_list (GstRegistry * registry)
551 list = g_list_copy (registry->plugins);
552 for (g = list; g; g = g->next) {
553 gst_object_ref (GST_PLUGIN (g->data));
555 GST_UNLOCK (registry);
560 static GstPluginFeature *
561 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
564 GstPluginFeature *feature;
569 for (g = registry->features; g; g = g_list_next (g)) {
570 feature = GST_PLUGIN_FEATURE (g->data);
571 if (feature->name && strcmp (name, feature->name) == 0) {
580 gst_registry_lookup_feature (GstRegistry * registry, const char *name)
582 GstPluginFeature *feature;
585 feature = gst_registry_lookup_feature_locked (registry, name);
587 gst_object_ref (feature);
588 GST_UNLOCK (registry);
594 gst_registry_lookup_locked (GstRegistry * registry, const char *filename)
599 if (filename == NULL)
602 for (g = registry->plugins; g; g = g_list_next (g)) {
603 plugin = GST_PLUGIN (g->data);
604 if (plugin->filename && strcmp (filename, plugin->filename) == 0) {
613 * gst_registry_lookup:
614 * @registry: the registry to look up in
615 * @filename: the name of the file to look up
617 * Look up a plugin in the given registry with the given filename.
618 * If found, plugin is reffed. Caller must unref after use.
620 * Returns: the #GstPlugin if found, or NULL if not.
623 gst_registry_lookup (GstRegistry * registry, const char *filename)
628 plugin = gst_registry_lookup_locked (registry, filename);
630 gst_object_ref (plugin);
631 GST_UNLOCK (registry);
637 gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
644 GstPlugin *newplugin;
646 dir = g_dir_open (path, 0, NULL);
650 while ((dirent = g_dir_read_name (dir))) {
651 filename = g_strjoin ("/", path, dirent, NULL);
653 GST_DEBUG ("examining file: %s", filename);
655 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
657 GST_DEBUG ("found directory, recursing");
658 gst_registry_scan_path_level (registry, filename, level - 1);
660 GST_DEBUG ("found directory, but recursion level is too deep");
665 if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
666 GST_DEBUG ("not a regular file, ignoring");
670 if (!g_str_has_suffix (filename, ".so") &&
671 !g_str_has_suffix (filename, ".dll") &&
672 !g_str_has_suffix (filename, ".dynlib")) {
673 GST_DEBUG ("extension is not recognized as module file, ignoring");
678 plugin = gst_registry_lookup (registry, filename);
680 struct stat file_status;
682 if (stat (filename, &file_status)) {
683 /* FIXME remove from cache */
688 if (plugin->file_mtime == file_status.st_mtime &&
689 plugin->file_size == file_status.st_size) {
690 GST_DEBUG ("file %s cached", filename);
691 plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
693 GST_DEBUG ("cached info for %s is stale", filename);
694 GST_DEBUG ("mtime %ld != %ld or size %" G_GSIZE_FORMAT " != %"
695 G_GSIZE_FORMAT, plugin->file_mtime, file_status.st_mtime,
696 plugin->file_size, file_status.st_size);
697 gst_registry_remove_plugin (gst_registry_get_default (), plugin);
698 newplugin = gst_plugin_load_file (filename, NULL);
700 gst_object_unref (newplugin);
702 gst_object_unref (plugin);
705 newplugin = gst_plugin_load_file (filename, NULL);
707 gst_object_unref (newplugin);
717 * gst_registry_scan_path:
718 * @registry: the registry to add the path to
719 * @path: the path to add to the registry
721 * Add the given path to the registry. The syntax of the
722 * path is specific to the registry. If the path has already been
726 gst_registry_scan_path (GstRegistry * registry, const gchar * path)
728 gst_registry_scan_path_level (registry, path, 10);
732 _gst_registry_remove_cache_plugins (GstRegistry * registry)
738 GST_DEBUG_OBJECT (registry, "removing cached plugins");
739 g = registry->plugins;
743 if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
744 GST_DEBUG_OBJECT (registry, "removing cached plugin %s",
746 registry->plugins = g_list_remove (registry->plugins, plugin);
747 gst_object_unref (plugin);
755 _gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature,
758 return (strcmp (feature->plugin_name, (gchar *) user_data) == 0);
762 gst_registry_get_feature_list_by_plugin (GstRegistry * registry,
765 return gst_registry_feature_filter (registry,
766 _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name);
770 _gst_registry_cleanup ()
772 if (!_gst_registry_default)
775 gst_object_unref (_gst_registry_default);
776 _gst_registry_default = NULL;