1 /* GStreamer
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>
5 *
6 * gstregistry.c: handle registry
7 *
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.
12 *
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.
17 *
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.
22 */
24 /**
25 * SECTION:gstregistry
26 * @short_description: Abstract base class for management of #GstPlugin objects
27 * @see_also: #GstPlugin, #GstPluginFeature
28 *
29 * One registry holds the metadata of a set of plugins.
30 *
31 * <emphasis role="bold">Design:</emphasis>
32 *
33 * The #GstRegistry object is a list of plugins and some functions for dealing
34 * with them. #GstPlugins are matched 1-1 with a file on disk, and may or may
35 * not be loaded at a given time. There may be multiple #GstRegistry objects,
36 * but the "default registry" is the only object that has any meaning to the
37 * core.
38 *
39 * The registry.xml file is actually a cache of plugin information. This is
40 * unlike versions prior to 0.10, where the registry file was the primary source
41 * of plugin information, and was created by the gst-register command.
42 *
43 * The primary source, at all times, of plugin information is each plugin file
44 * itself. Thus, if an application wants information about a particular plugin,
45 * or wants to search for a feature that satisfies given criteria, the primary
46 * means of doing so is to load every plugin and look at the resulting
47 * information that is gathered in the default registry. Clearly, this is a time
48 * consuming process, so we cache information in the registry.xml file.
49 *
50 * On startup, plugins are searched for in the plugin search path. This path can
51 * be set directly using the %GST_PLUGIN_PATH environment variable. The registry
52 * file is loaded from ~/.gstreamer-$GST_MAJORMINOR/registry-$ARCH.xml or the
53 * file listed in the %GST_REGISTRY env var. The only reason to change the
54 * registry location is for testing.
55 *
56 * For each plugin that is found in the plugin search path, there could be 3
57 * possibilities for cached information:
58 * <itemizedlist>
59 * <listitem>
60 * <para>the cache may not contain information about a given file.</para>
61 * </listitem>
62 * <listitem>
63 * <para>the cache may have stale information.</para>
64 * </listitem>
65 * <listitem>
66 * <para>the cache may have current information.</para>
67 * </listitem>
68 * </itemizedlist>
69 *
70 * In the first two cases, the plugin is loaded and the cache updated. In
71 * addition to these cases, the cache may have entries for plugins that are not
72 * relevant to the current process. These are marked as not available to the
73 * current process. If the cache is updated for whatever reason, it is marked
74 * dirty.
75 *
76 * A dirty cache is written out at the end of initialization. Each entry is
77 * checked to make sure the information is minimally valid. If not, the entry is
78 * simply dropped.
79 *
80 * <emphasis role="bold">Implementation notes:</emphasis>
81 *
82 * The "cache" and "default registry" are different concepts and can represent
83 * different sets of plugins. For various reasons, at init time, the cache is
84 * stored in the default registry, and plugins not relevant to the current
85 * process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are
86 * removed at the end of intitialization.
87 */
89 #ifdef HAVE_CONFIG_H
90 #include "config.h"
91 #endif
92 #include "gstconfig.h"
93 #include "gst_private.h"
94 #include <glib.h>
95 #include <sys/types.h>
96 #include <sys/stat.h>
97 #ifdef HAVE_UNISTD_H
98 #include <unistd.h>
99 #endif
100 #include <errno.h>
101 #include <stdio.h>
102 #include <string.h>
104 /* For g_stat () */
105 #include <glib/gstdio.h>
107 #include "gstinfo.h"
108 #include "gsterror.h"
109 #include "gstregistry.h"
110 #include "gstmarshal.h"
111 #include "gstfilter.h"
113 #include "gstpluginloader.h"
115 #include "gst-i18n-lib.h"
117 /* needed for fast retrieval of element and typefind factory lists */
118 extern GType gst_type_find_factory_get_type (void);
119 #define GST_TYPE_TYPE_FIND_FACTORY (gst_type_find_factory_get_type())
120 extern GType gst_element_factory_get_type (void);
121 #define GST_TYPE_ELEMENT_FACTORY (gst_element_factory_get_type())
124 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
126 struct _GstRegistryPrivate
127 {
128 /* updated whenever the feature list changes */
129 guint32 cookie;
130 /* speedup for searching features */
131 GList *element_factory_list;
132 guint32 efl_cookie;
133 GList *typefind_factory_list;
134 guint32 tfl_cookie;
135 };
137 /* the one instance of the default registry and the mutex protecting the
138 * variable. */
139 static GStaticMutex _gst_registry_mutex = G_STATIC_MUTEX_INIT;
140 static GstRegistry *_gst_registry_default = NULL;
142 /* defaults */
143 #define DEFAULT_FORK TRUE
145 /* control the behaviour of registry rebuild */
146 static gboolean _gst_enable_registry_fork = DEFAULT_FORK;
147 /* List of plugins that need preloading/reloading after scanning registry */
148 extern GSList *_priv_gst_preload_plugins;
150 #ifndef GST_DISABLE_REGISTRY
151 /*set to TRUE when registry needn't to be updated */
152 gboolean _priv_gst_disable_registry_update = FALSE;
153 extern GList *_priv_gst_plugin_paths;
155 /* Set to TRUE when the registry cache should be disabled */
156 gboolean _gst_disable_registry_cache = FALSE;
157 #endif
159 /* Element signals and args */
160 enum
161 {
162 PLUGIN_ADDED,
163 FEATURE_ADDED,
164 LAST_SIGNAL
165 };
167 static void gst_registry_finalize (GObject * object);
169 static guint gst_registry_signals[LAST_SIGNAL] = { 0 };
171 static GstPluginFeature *gst_registry_lookup_feature_locked (GstRegistry *
172 registry, const char *name);
173 static GstPlugin *gst_registry_lookup_bn_locked (GstRegistry * registry,
174 const char *basename);
176 G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT);
177 static GstObjectClass *parent_class = NULL;
179 static void
180 gst_registry_class_init (GstRegistryClass * klass)
181 {
182 GObjectClass *gobject_class;
184 gobject_class = (GObjectClass *) klass;
186 parent_class = g_type_class_peek_parent (klass);
187 g_type_class_add_private (klass, sizeof (GstRegistryPrivate));
189 /**
190 * GstRegistry::plugin-added:
191 * @registry: the registry that emitted the signal
192 * @plugin: the plugin that has been added
193 *
194 * Signals that a plugin has been added to the registry (possibly
195 * replacing a previously-added one by the same name)
196 */
197 gst_registry_signals[PLUGIN_ADDED] =
198 g_signal_new ("plugin-added", G_TYPE_FROM_CLASS (klass),
199 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL,
200 NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
202 /**
203 * GstRegistry::feature-added:
204 * @registry: the registry that emitted the signal
205 * @feature: the feature that has been added
206 *
207 * Signals that a feature has been added to the registry (possibly
208 * replacing a previously-added one by the same name)
209 */
210 gst_registry_signals[FEATURE_ADDED] =
211 g_signal_new ("feature-added", G_TYPE_FROM_CLASS (klass),
212 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRegistryClass, feature_added),
213 NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
215 gobject_class->finalize = gst_registry_finalize;
216 }
218 static void
219 gst_registry_init (GstRegistry * registry)
220 {
221 registry->feature_hash = g_hash_table_new (g_str_hash, g_str_equal);
222 registry->basename_hash = g_hash_table_new (g_str_hash, g_str_equal);
223 registry->priv =
224 G_TYPE_INSTANCE_GET_PRIVATE (registry, GST_TYPE_REGISTRY,
225 GstRegistryPrivate);
226 }
228 static void
229 gst_registry_finalize (GObject * object)
230 {
231 GstRegistry *registry = GST_REGISTRY (object);
232 GList *plugins, *p;
233 GList *features, *f;
235 plugins = registry->plugins;
236 registry->plugins = NULL;
238 GST_DEBUG_OBJECT (registry, "registry finalize");
239 p = plugins;
240 while (p) {
241 GstPlugin *plugin = p->data;
243 if (plugin) {
244 GST_LOG_OBJECT (registry, "removing plugin %s",
245 gst_plugin_get_name (plugin));
246 gst_object_unref (plugin);
247 }
248 p = g_list_next (p);
249 }
250 g_list_free (plugins);
252 features = registry->features;
253 registry->features = NULL;
255 f = features;
256 while (f) {
257 GstPluginFeature *feature = f->data;
259 if (feature) {
260 GST_LOG_OBJECT (registry, "removing feature %p (%s)",
261 feature, gst_plugin_feature_get_name (feature));
262 gst_object_unref (feature);
263 }
264 f = g_list_next (f);
265 }
266 g_list_free (features);
268 g_hash_table_destroy (registry->feature_hash);
269 registry->feature_hash = NULL;
270 g_hash_table_destroy (registry->basename_hash);
271 registry->basename_hash = NULL;
273 if (registry->priv->element_factory_list) {
274 GST_DEBUG_OBJECT (registry, "Cleaning up cached element factory list");
275 gst_plugin_feature_list_free (registry->priv->element_factory_list);
276 }
278 if (registry->priv->typefind_factory_list) {
279 GST_DEBUG_OBJECT (registry, "Cleaning up cached typefind factory list");
280 gst_plugin_feature_list_free (registry->priv->typefind_factory_list);
281 }
283 G_OBJECT_CLASS (parent_class)->finalize (object);
284 }
286 /**
287 * gst_registry_get_default:
288 *
289 * Retrieves the default registry. The caller does not own a reference on the
290 * registry, as it is alive as long as GStreamer is initialized.
291 *
292 * Returns: The default #GstRegistry.
293 */
294 GstRegistry *
295 gst_registry_get_default (void)
296 {
297 GstRegistry *registry;
299 g_static_mutex_lock (&_gst_registry_mutex);
300 if (G_UNLIKELY (!_gst_registry_default)) {
301 _gst_registry_default = g_object_newv (GST_TYPE_REGISTRY, 0, NULL);
302 gst_object_ref_sink (GST_OBJECT_CAST (_gst_registry_default));
303 }
304 registry = _gst_registry_default;
305 g_static_mutex_unlock (&_gst_registry_mutex);
307 return registry;
308 }
310 /**
311 * gst_registry_add_path:
312 * @registry: the registry to add the path to
313 * @path: the path to add to the registry
314 *
315 * Add the given path to the registry. The syntax of the
316 * path is specific to the registry. If the path has already been
317 * added, do nothing.
318 */
319 void
320 gst_registry_add_path (GstRegistry * registry, const gchar * path)
321 {
322 g_return_if_fail (GST_IS_REGISTRY (registry));
323 g_return_if_fail (path != NULL);
325 if (strlen (path) == 0)
326 goto empty_path;
328 GST_OBJECT_LOCK (registry);
329 if (g_list_find_custom (registry->paths, path, (GCompareFunc) strcmp))
330 goto was_added;
332 GST_INFO ("Adding plugin path: \"%s\"", path);
333 registry->paths = g_list_append (registry->paths, g_strdup (path));
334 GST_OBJECT_UNLOCK (registry);
336 return;
338 empty_path:
339 {
340 GST_INFO ("Ignoring empty plugin path");
341 return;
342 }
343 was_added:
344 {
345 g_warning ("path %s already added to registry", path);
346 GST_OBJECT_UNLOCK (registry);
347 return;
348 }
349 }
351 /**
352 * gst_registry_get_path_list:
353 * @registry: the registry to get the pathlist of
354 *
355 * Get the list of paths for the given registry.
356 *
357 * Returns: A Glist of paths as strings. g_list_free after use.
358 *
359 * MT safe.
360 */
361 GList *
362 gst_registry_get_path_list (GstRegistry * registry)
363 {
364 GList *list;
366 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
368 GST_OBJECT_LOCK (registry);
369 /* We don't need to copy the strings, because they won't be deleted
370 * as long as the GstRegistry is around */
371 list = g_list_copy (registry->paths);
372 GST_OBJECT_UNLOCK (registry);
374 return list;
375 }
378 /**
379 * gst_registry_add_plugin:
380 * @registry: the registry to add the plugin to
381 * @plugin: the plugin to add
382 *
383 * Add the plugin to the registry. The plugin-added signal will be emitted.
384 * This function will sink @plugin.
385 *
386 * Returns: TRUE on success.
387 *
388 * MT safe.
389 */
390 gboolean
391 gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
392 {
393 GstPlugin *existing_plugin;
395 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
396 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
398 GST_OBJECT_LOCK (registry);
399 if (G_LIKELY (plugin->basename)) {
400 /* we have a basename, see if we find the plugin */
401 existing_plugin =
402 gst_registry_lookup_bn_locked (registry, plugin->basename);
403 if (existing_plugin) {
404 GST_DEBUG_OBJECT (registry,
405 "Replacing existing plugin %p with new plugin %p for filename \"%s\"",
406 existing_plugin, plugin, GST_STR_NULL (plugin->filename));
407 registry->plugins = g_list_remove (registry->plugins, existing_plugin);
408 if (G_LIKELY (existing_plugin->basename))
409 g_hash_table_remove (registry->basename_hash,
410 existing_plugin->basename);
411 gst_object_unref (existing_plugin);
412 }
413 }
415 GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"",
416 plugin, GST_STR_NULL (plugin->filename));
418 registry->plugins = g_list_prepend (registry->plugins, plugin);
419 if (G_LIKELY (plugin->basename))
420 g_hash_table_replace (registry->basename_hash, plugin->basename, plugin);
422 gst_object_ref_sink (plugin);
423 GST_OBJECT_UNLOCK (registry);
425 GST_LOG_OBJECT (registry, "emitting plugin-added for filename \"%s\"",
426 GST_STR_NULL (plugin->filename));
427 g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin);
429 return TRUE;
430 }
432 static void
433 gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry,
434 GstPlugin * plugin)
435 {
436 GList *f;
437 const gchar *name;
439 g_return_if_fail (GST_IS_REGISTRY (registry));
440 g_return_if_fail (GST_IS_PLUGIN (plugin));
442 name = gst_plugin_get_name (plugin);
444 /* Remove all features for this plugin */
445 f = registry->features;
446 while (f != NULL) {
447 GList *next = g_list_next (f);
448 GstPluginFeature *feature = f->data;
450 if (G_UNLIKELY (feature && !strcmp (feature->plugin_name, name))) {
451 GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %s",
452 feature, gst_plugin_feature_get_name (feature), name);
454 registry->features = g_list_delete_link (registry->features, f);
455 g_hash_table_remove (registry->feature_hash, feature->name);
456 gst_object_unref (feature);
457 }
458 f = next;
459 }
460 registry->priv->cookie++;
461 }
463 /**
464 * gst_registry_remove_plugin:
465 * @registry: the registry to remove the plugin from
466 * @plugin: the plugin to remove
467 *
468 * Remove the plugin from the registry.
469 *
470 * MT safe.
471 */
472 void
473 gst_registry_remove_plugin (GstRegistry * registry, GstPlugin * plugin)
474 {
475 g_return_if_fail (GST_IS_REGISTRY (registry));
476 g_return_if_fail (GST_IS_PLUGIN (plugin));
478 GST_DEBUG_OBJECT (registry, "removing plugin %p (%s)",
479 plugin, gst_plugin_get_name (plugin));
481 GST_OBJECT_LOCK (registry);
482 registry->plugins = g_list_remove (registry->plugins, plugin);
483 if (G_LIKELY (plugin->basename))
484 g_hash_table_remove (registry->basename_hash, plugin->basename);
485 gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
486 GST_OBJECT_UNLOCK (registry);
487 gst_object_unref (plugin);
488 }
490 /**
491 * gst_registry_add_feature:
492 * @registry: the registry to add the plugin to
493 * @feature: the feature to add
494 *
495 * Add the feature to the registry. The feature-added signal will be emitted.
496 * This function sinks @feature.
497 *
498 * Returns: TRUE on success.
499 *
500 * MT safe.
501 */
502 gboolean
503 gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
504 {
505 GstPluginFeature *existing_feature;
507 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
508 g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
509 g_return_val_if_fail (feature->name != NULL, FALSE);
510 g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
512 GST_OBJECT_LOCK (registry);
513 existing_feature = gst_registry_lookup_feature_locked (registry,
514 feature->name);
515 if (G_UNLIKELY (existing_feature)) {
516 GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)",
517 existing_feature, feature->name);
518 /* Remove the existing feature from the list now, before we insert the new
519 * one, but don't unref yet because the hash is still storing a reference to
520 * it. */
521 registry->features = g_list_remove (registry->features, existing_feature);
522 }
524 GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
526 registry->features = g_list_prepend (registry->features, feature);
527 g_hash_table_replace (registry->feature_hash, feature->name, feature);
529 if (G_UNLIKELY (existing_feature)) {
530 /* We unref now. No need to remove the feature name from the hash table, it
531 * got replaced by the new feature */
532 gst_object_unref (existing_feature);
533 }
535 gst_object_ref_sink (feature);
537 registry->priv->cookie++;
538 GST_OBJECT_UNLOCK (registry);
540 GST_LOG_OBJECT (registry, "emitting feature-added for %s", feature->name);
541 g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature);
543 return TRUE;
544 }
546 /**
547 * gst_registry_remove_feature:
548 * @registry: the registry to remove the feature from
549 * @feature: the feature to remove
550 *
551 * Remove the feature from the registry.
552 *
553 * MT safe.
554 */
555 void
556 gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
557 {
558 g_return_if_fail (GST_IS_REGISTRY (registry));
559 g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
561 GST_DEBUG_OBJECT (registry, "removing feature %p (%s)",
562 feature, gst_plugin_feature_get_name (feature));
564 GST_OBJECT_LOCK (registry);
565 registry->features = g_list_remove (registry->features, feature);
566 g_hash_table_remove (registry->feature_hash, feature->name);
567 registry->priv->cookie++;
568 GST_OBJECT_UNLOCK (registry);
569 gst_object_unref (feature);
570 }
572 /**
573 * gst_registry_plugin_filter:
574 * @registry: registry to query
575 * @filter: the filter to use
576 * @first: only return first match
577 * @user_data: user data passed to the filter function
578 *
579 * Runs a filter against all plugins in the registry and returns a #GList with
580 * the results. If the first flag is set, only the first match is
581 * returned (as a list with a single object).
582 * Every plugin is reffed; use gst_plugin_list_free() after use, which
583 * will unref again.
584 *
585 * Returns: a #GList of #GstPlugin. Use gst_plugin_list_free() after usage.
586 *
587 * MT safe.
588 */
589 GList *
590 gst_registry_plugin_filter (GstRegistry * registry,
591 GstPluginFilter filter, gboolean first, gpointer user_data)
592 {
593 GList *list;
594 GList *g;
596 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
598 GST_OBJECT_LOCK (registry);
599 list = gst_filter_run (registry->plugins, (GstFilterFunc) filter, first,
600 user_data);
601 for (g = list; g; g = g->next) {
602 gst_object_ref (GST_PLUGIN_CAST (g->data));
603 }
604 GST_OBJECT_UNLOCK (registry);
606 return list;
607 }
609 /* returns TRUE if the list was changed
610 *
611 * Must be called with the object lock taken */
612 static gboolean
613 gst_registry_get_feature_list_or_create (GstRegistry * registry,
614 GList ** previous, guint32 * cookie, GType type)
615 {
616 gboolean res = FALSE;
617 GstRegistryPrivate *priv = registry->priv;
619 if (G_UNLIKELY (!*previous || priv->cookie != *cookie)) {
620 GstTypeNameData data;
622 if (*previous)
623 gst_plugin_feature_list_free (*previous);
625 data.type = type;
626 data.name = NULL;
627 *previous =
628 gst_filter_run (registry->features,
629 (GstFilterFunc) gst_plugin_feature_type_name_filter, FALSE, &data);
630 g_list_foreach (*previous, (GFunc) gst_object_ref, NULL);
631 *cookie = priv->cookie;
632 res = TRUE;
633 }
635 return res;
636 }
638 static gint
639 type_find_factory_rank_cmp (const GstPluginFeature * fac1,
640 const GstPluginFeature * fac2)
641 {
642 if (G_LIKELY (fac1->rank != fac2->rank))
643 return fac2->rank - fac1->rank;
645 /* to make the order in which things happen more deterministic,
646 * sort by name when the ranks are the same. */
647 return strcmp (fac1->name, fac2->name);
648 }
650 static GList *
651 gst_registry_get_element_factory_list (GstRegistry * registry)
652 {
653 GList *list;
655 GST_OBJECT_LOCK (registry);
657 gst_registry_get_feature_list_or_create (registry,
658 ®istry->priv->element_factory_list, ®istry->priv->efl_cookie,
659 GST_TYPE_ELEMENT_FACTORY);
661 /* Return reffed copy */
662 list = gst_plugin_feature_list_copy (registry->priv->element_factory_list);
664 GST_OBJECT_UNLOCK (registry);
666 return list;
667 }
669 static GList *
670 gst_registry_get_typefind_factory_list (GstRegistry * registry)
671 {
672 GList *list;
674 GST_OBJECT_LOCK (registry);
676 if (G_UNLIKELY (gst_registry_get_feature_list_or_create (registry,
677 ®istry->priv->typefind_factory_list,
678 ®istry->priv->tfl_cookie, GST_TYPE_TYPE_FIND_FACTORY)))
679 registry->priv->typefind_factory_list =
680 g_list_sort (registry->priv->typefind_factory_list,
681 (GCompareFunc) type_find_factory_rank_cmp);
683 /* Return reffed copy */
684 list = gst_plugin_feature_list_copy (registry->priv->typefind_factory_list);
686 GST_OBJECT_UNLOCK (registry);
688 return list;
689 }
691 /**
692 * gst_registry_feature_filter:
693 * @registry: registry to query
694 * @filter: the filter to use
695 * @first: only return first match
696 * @user_data: user data passed to the filter function
697 *
698 * Runs a filter against all features of the plugins in the registry
699 * and returns a GList with the results.
700 * If the first flag is set, only the first match is
701 * returned (as a list with a single object).
702 *
703 * Returns: a #GList of #GstPluginFeature. Use gst_plugin_feature_list_free()
704 * after usage.
705 *
706 * MT safe.
707 */
708 GList *
709 gst_registry_feature_filter (GstRegistry * registry,
710 GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
711 {
712 GList *list;
713 GList *g;
715 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
717 GST_OBJECT_LOCK (registry);
718 list = gst_filter_run (registry->features, (GstFilterFunc) filter, first,
719 user_data);
720 for (g = list; g; g = g->next) {
721 gst_object_ref (GST_PLUGIN_FEATURE_CAST (g->data));
722 }
723 GST_OBJECT_UNLOCK (registry);
725 return list;
726 }
728 /**
729 * gst_registry_find_plugin:
730 * @registry: the registry to search
731 * @name: the plugin name to find
732 *
733 * Find the plugin with the given name in the registry.
734 * The plugin will be reffed; caller is responsible for unreffing.
735 *
736 * Returns: The plugin with the given name or NULL if the plugin was not found.
737 * gst_object_unref() after usage.
738 *
739 * MT safe.
740 */
741 GstPlugin *
742 gst_registry_find_plugin (GstRegistry * registry, const gchar * name)
743 {
744 GList *walk;
745 GstPlugin *result = NULL;
747 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
748 g_return_val_if_fail (name != NULL, NULL);
750 walk = gst_registry_plugin_filter (registry,
751 (GstPluginFilter) gst_plugin_name_filter, TRUE, (gpointer) name);
752 if (walk) {
753 result = GST_PLUGIN_CAST (walk->data);
755 gst_object_ref (result);
756 gst_plugin_list_free (walk);
757 }
759 return result;
760 }
762 /**
763 * gst_registry_find_feature:
764 * @registry: the registry to search
765 * @name: the pluginfeature name to find
766 * @type: the pluginfeature type to find
767 *
768 * Find the pluginfeature with the given name and type in the registry.
769 *
770 * Returns: The pluginfeature with the given name and type or NULL
771 * if the plugin was not found. gst_object_unref() after usage.
772 *
773 * MT safe.
774 */
775 GstPluginFeature *
776 gst_registry_find_feature (GstRegistry * registry, const gchar * name,
777 GType type)
778 {
779 GstPluginFeature *feature = NULL;
781 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
782 g_return_val_if_fail (name != NULL, NULL);
783 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL);
785 feature = gst_registry_lookup_feature (registry, name);
786 if (feature && !g_type_is_a (G_TYPE_FROM_INSTANCE (feature), type)) {
787 gst_object_unref (feature);
788 feature = NULL;
789 }
791 return feature;
792 }
794 /**
795 * gst_registry_get_feature_list:
796 * @registry: a #GstRegistry
797 * @type: a #GType.
798 *
799 * Retrieves a #GList of #GstPluginFeature of @type.
800 *
801 * Returns: a #GList of #GstPluginFeature of @type. Use
802 * gst_plugin_feature_list_free() after usage.
803 *
804 * MT safe.
805 */
806 GList *
807 gst_registry_get_feature_list (GstRegistry * registry, GType type)
808 {
809 GstTypeNameData data;
811 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
812 g_return_val_if_fail (g_type_is_a (type, GST_TYPE_PLUGIN_FEATURE), NULL);
814 /* Speed up */
815 if (type == GST_TYPE_ELEMENT_FACTORY)
816 return gst_registry_get_element_factory_list (registry);
817 else if (type == GST_TYPE_TYPE_FIND_FACTORY)
818 return gst_registry_get_typefind_factory_list (registry);
820 data.type = type;
821 data.name = NULL;
823 return gst_registry_feature_filter (registry,
824 (GstPluginFeatureFilter) gst_plugin_feature_type_name_filter,
825 FALSE, &data);
826 }
828 /**
829 * gst_registry_get_plugin_list:
830 * @registry: the registry to search
831 *
832 * Get a copy of all plugins registered in the given registry. The refcount
833 * of each element in the list in incremented.
834 *
835 * Returns: a #GList of #GstPlugin. Use gst_plugin_list_free() after usage.
836 *
837 * MT safe.
838 */
839 GList *
840 gst_registry_get_plugin_list (GstRegistry * registry)
841 {
842 GList *list;
843 GList *g;
845 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
847 GST_OBJECT_LOCK (registry);
848 list = g_list_copy (registry->plugins);
849 for (g = list; g; g = g->next) {
850 gst_object_ref (GST_PLUGIN_CAST (g->data));
851 }
852 GST_OBJECT_UNLOCK (registry);
854 return list;
855 }
857 static GstPluginFeature *
858 gst_registry_lookup_feature_locked (GstRegistry * registry, const char *name)
859 {
860 return g_hash_table_lookup (registry->feature_hash, name);
861 }
863 /**
864 * gst_registry_lookup_feature:
865 * @registry: a #GstRegistry
866 * @name: a #GstPluginFeature name
867 *
868 * Find a #GstPluginFeature with @name in @registry.
869 *
870 * Returns: a #GstPluginFeature with its refcount incremented, use
871 * gst_object_unref() after usage.
872 *
873 * MT safe.
874 */
875 GstPluginFeature *
876 gst_registry_lookup_feature (GstRegistry * registry, const char *name)
877 {
878 GstPluginFeature *feature;
880 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
881 g_return_val_if_fail (name != NULL, NULL);
883 GST_OBJECT_LOCK (registry);
884 feature = gst_registry_lookup_feature_locked (registry, name);
885 if (feature)
886 gst_object_ref (feature);
887 GST_OBJECT_UNLOCK (registry);
889 return feature;
890 }
892 static GstPlugin *
893 gst_registry_lookup_bn_locked (GstRegistry * registry, const char *basename)
894 {
895 return g_hash_table_lookup (registry->basename_hash, basename);
896 }
898 static GstPlugin *
899 gst_registry_lookup_bn (GstRegistry * registry, const char *basename)
900 {
901 GstPlugin *plugin;
903 GST_OBJECT_LOCK (registry);
904 plugin = gst_registry_lookup_bn_locked (registry, basename);
905 if (plugin)
906 gst_object_ref (plugin);
907 GST_OBJECT_UNLOCK (registry);
909 return plugin;
910 }
912 /**
913 * gst_registry_lookup:
914 * @registry: the registry to look up in
915 * @filename: the name of the file to look up
916 *
917 * Look up a plugin in the given registry with the given filename.
918 * If found, plugin is reffed.
919 *
920 * Returns: the #GstPlugin if found, or NULL if not. gst_object_unref()
921 * after usage.
922 */
923 GstPlugin *
924 gst_registry_lookup (GstRegistry * registry, const char *filename)
925 {
926 GstPlugin *plugin;
927 gchar *basename;
929 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
930 g_return_val_if_fail (filename != NULL, NULL);
932 basename = g_path_get_basename (filename);
933 if (G_UNLIKELY (basename == NULL))
934 return NULL;
936 plugin = gst_registry_lookup_bn (registry, basename);
938 g_free (basename);
940 return plugin;
941 }
943 typedef enum
944 {
945 REGISTRY_SCAN_HELPER_NOT_STARTED = 0,
946 REGISTRY_SCAN_HELPER_DISABLED,
947 REGISTRY_SCAN_HELPER_RUNNING
948 } GstRegistryScanHelperState;
950 typedef struct
951 {
952 GstRegistry *registry;
953 GstRegistryScanHelperState helper_state;
954 GstPluginLoader *helper;
955 gboolean changed;
956 } GstRegistryScanContext;
958 static void
959 init_scan_context (GstRegistryScanContext * context, GstRegistry * registry)
960 {
961 gboolean do_fork;
963 context->registry = registry;
965 /* see if forking is enabled and set up the scan helper state accordingly */
966 do_fork = _gst_enable_registry_fork;
967 if (do_fork) {
968 const gchar *fork_env;
970 /* forking enabled, see if it is disabled with an env var */
971 if ((fork_env = g_getenv ("GST_REGISTRY_FORK"))) {
972 /* fork enabled for any value different from "no" */
973 do_fork = strcmp (fork_env, "no") != 0;
974 }
975 }
977 if (do_fork)
978 context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED;
979 else
980 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED;
982 context->helper = NULL;
983 context->changed = FALSE;
984 }
986 static void
987 clear_scan_context (GstRegistryScanContext * context)
988 {
989 if (context->helper) {
990 context->changed |= _priv_gst_plugin_loader_funcs.destroy (context->helper);
991 context->helper = NULL;
992 }
993 }
995 static gboolean
996 gst_registry_scan_plugin_file (GstRegistryScanContext * context,
997 const gchar * filename, off_t file_size, time_t file_mtime)
998 {
999 gboolean changed = FALSE;
1000 GstPlugin *newplugin = NULL;
1002 /* Have a plugin to load - see if the scan-helper needs starting */
1003 if (context->helper_state == REGISTRY_SCAN_HELPER_NOT_STARTED) {
1004 GST_DEBUG ("Starting plugin scanner for file %s", filename);
1005 context->helper = _priv_gst_plugin_loader_funcs.create (context->registry);
1006 if (context->helper != NULL)
1007 context->helper_state = REGISTRY_SCAN_HELPER_RUNNING;
1008 else {
1009 GST_WARNING ("Failed starting plugin scanner. Scanning in-process");
1010 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED;
1011 }
1012 }
1014 if (context->helper_state == REGISTRY_SCAN_HELPER_RUNNING) {
1015 GST_DEBUG ("Using scan-helper to load plugin %s", filename);
1016 if (!_priv_gst_plugin_loader_funcs.load (context->helper,
1017 filename, file_size, file_mtime)) {
1018 g_warning ("External plugin loader failed. This most likely means that "
1019 "the plugin loader helper binary was not found or could not be run. "
1020 "%s", (g_getenv ("GST_PLUGIN_PATH") != NULL) ?
1021 "If you are running an uninstalled GStreamer setup, you might need "
1022 "to update your gst-uninstalled script so that the "
1023 "GST_PLUGIN_SCANNER environment variable gets set." : "");
1024 context->helper_state = REGISTRY_SCAN_HELPER_DISABLED;
1025 }
1026 }
1028 /* Check if the helper is disabled (or just got disabled above) */
1029 if (context->helper_state == REGISTRY_SCAN_HELPER_DISABLED) {
1030 /* Load plugin the old fashioned way... */
1032 /* We don't use a GError here because a failure to load some shared
1033 * objects as plugins is normal (particularly in the uninstalled case)
1034 */
1035 newplugin = gst_plugin_load_file (filename, NULL);
1036 }
1038 if (newplugin) {
1039 GST_DEBUG_OBJECT (context->registry, "marking new plugin %p as registered",
1040 newplugin);
1041 newplugin->registered = TRUE;
1042 gst_object_unref (newplugin);
1043 changed = TRUE;
1044 }
1046 return changed;
1047 }
1049 static gboolean
1050 gst_registry_scan_path_level (GstRegistryScanContext * context,
1051 const gchar * path, int level)
1052 {
1053 GDir *dir;
1054 const gchar *dirent;
1055 gchar *filename;
1056 GstPlugin *plugin;
1057 gboolean changed = FALSE;
1059 dir = g_dir_open (path, 0, NULL);
1060 if (!dir)
1061 return FALSE;
1063 while ((dirent = g_dir_read_name (dir))) {
1064 struct stat file_status;
1066 filename = g_build_filename (path, dirent, NULL);
1067 if (g_stat (filename, &file_status) < 0) {
1068 /* Plugin will be removed from cache after the scan completes if it
1069 * is still marked 'cached' */
1070 g_free (filename);
1071 continue;
1072 }
1074 if (file_status.st_mode & S_IFDIR) {
1075 /* skip the .debug directory, these contain elf files that are not
1076 * useful or worse, can crash dlopen (). do a quick check for the . first
1077 * and then call the compare functions. */
1078 if (G_UNLIKELY (dirent[0] == '.' && (g_str_equal (dirent, ".debug")
1079 || g_str_equal (dirent, ".git")))) {
1080 GST_LOG_OBJECT (context->registry, "ignoring .debug or .git directory");
1081 g_free (filename);
1082 continue;
1083 }
1084 /* FIXME 0.11: Don't recurse into directories, this behaviour
1085 * is inconsistent with other PATH environment variables
1086 */
1087 if (level > 0) {
1088 GST_LOG_OBJECT (context->registry, "recursing into directory %s",
1089 filename);
1090 changed |= gst_registry_scan_path_level (context, filename, level - 1);
1091 } else {
1092 GST_LOG_OBJECT (context->registry, "not recursing into directory %s, "
1093 "recursion level too deep", filename);
1094 }
1095 g_free (filename);
1096 continue;
1097 }
1098 if (!(file_status.st_mode & S_IFREG)) {
1099 GST_LOG_OBJECT (context->registry, "%s is not a regular file, ignoring",
1100 filename);
1101 g_free (filename);
1102 continue;
1103 }
1104 if (!g_str_has_suffix (dirent, G_MODULE_SUFFIX)
1105 #ifdef GST_EXTRA_MODULE_SUFFIX
1106 && !g_str_has_suffix (dirent, GST_EXTRA_MODULE_SUFFIX)
1107 #endif
1108 ) {
1109 GST_LOG_OBJECT (context->registry,
1110 "extension is not recognized as module file, ignoring file %s",
1111 filename);
1112 g_free (filename);
1113 continue;
1114 }
1116 GST_LOG_OBJECT (context->registry, "file %s looks like a possible module",
1117 filename);
1119 /* plug-ins are considered unique by basename; if the given name
1120 * was already seen by the registry, we ignore it */
1121 plugin = gst_registry_lookup_bn (context->registry, dirent);
1122 if (plugin) {
1123 gboolean env_vars_changed, deps_changed = FALSE;
1125 if (plugin->registered) {
1126 GST_DEBUG_OBJECT (context->registry,
1127 "plugin already registered from path \"%s\"",
1128 GST_STR_NULL (plugin->filename));
1129 g_free (filename);
1130 gst_object_unref (plugin);
1131 continue;
1132 }
1134 env_vars_changed = _priv_plugin_deps_env_vars_changed (plugin);
1136 /* If a file with a certain basename is seen on a different path,
1137 * update the plugin to ensure the registry cache will reflect up
1138 * to date information */
1140 if (plugin->file_mtime == file_status.st_mtime &&
1141 plugin->file_size == file_status.st_size && !env_vars_changed &&
1142 !(deps_changed = _priv_plugin_deps_files_changed (plugin)) &&
1143 !strcmp (plugin->filename, filename)) {
1144 GST_LOG_OBJECT (context->registry, "file %s cached", filename);
1145 plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
1146 GST_LOG_OBJECT (context->registry,
1147 "marking plugin %p as registered as %s", plugin, filename);
1148 plugin->registered = TRUE;
1149 } else {
1150 GST_INFO_OBJECT (context->registry, "cached info for %s is stale",
1151 filename);
1152 GST_DEBUG_OBJECT (context->registry, "mtime %ld != %ld or size %"
1153 G_GINT64_FORMAT " != %" G_GINT64_FORMAT " or external dependency "
1154 "env_vars changed: %d or external dependencies changed: %d"
1155 " or old path %s != new path %s",
1156 plugin->file_mtime, file_status.st_mtime,
1157 (gint64) plugin->file_size, (gint64) file_status.st_size,
1158 env_vars_changed, deps_changed, plugin->filename, filename);
1159 gst_registry_remove_plugin (context->registry, plugin);
1160 changed |= gst_registry_scan_plugin_file (context, filename,
1161 file_status.st_size, file_status.st_mtime);
1162 }
1163 gst_object_unref (plugin);
1165 } else {
1166 GST_DEBUG_OBJECT (context->registry, "file %s not yet in registry",
1167 filename);
1168 changed |= gst_registry_scan_plugin_file (context, filename,
1169 file_status.st_size, file_status.st_mtime);
1170 }
1172 g_free (filename);
1173 }
1175 g_dir_close (dir);
1177 return changed;
1178 }
1180 static gboolean
1181 gst_registry_scan_path_internal (GstRegistryScanContext * context,
1182 const gchar * path)
1183 {
1184 gboolean changed;
1186 GST_DEBUG_OBJECT (context->registry, "scanning path %s", path);
1187 changed = gst_registry_scan_path_level (context, path, 10);
1189 GST_DEBUG_OBJECT (context->registry, "registry changed in path %s: %d", path,
1190 changed);
1191 return changed;
1192 }
1194 /**
1195 * gst_registry_scan_path:
1196 * @registry: the registry to add found plugins to
1197 * @path: the path to scan
1198 *
1199 * Scan the given path for plugins to add to the registry. The syntax of the
1200 * path is specific to the registry.
1201 *
1202 * Returns: %TRUE if registry changed
1203 */
1204 gboolean
1205 gst_registry_scan_path (GstRegistry * registry, const gchar * path)
1206 {
1207 GstRegistryScanContext context;
1208 gboolean result;
1210 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
1211 g_return_val_if_fail (path != NULL, FALSE);
1213 init_scan_context (&context, registry);
1215 result = gst_registry_scan_path_internal (&context, path);
1217 clear_scan_context (&context);
1218 result |= context.changed;
1220 return result;
1221 }
1223 static gboolean
1224 _gst_plugin_feature_filter_plugin_name (GstPluginFeature * feature,
1225 gpointer user_data)
1226 {
1227 return (strcmp (feature->plugin_name, (gchar *) user_data) == 0);
1228 }
1230 /**
1231 * gst_registry_get_feature_list_by_plugin:
1232 * @registry: a #GstRegistry.
1233 * @name: a plugin name.
1234 *
1235 * Retrieves a #GList of features of the plugin with name @name.
1236 *
1237 * Returns: a #GList of #GstPluginFeature. Use gst_plugin_feature_list_free()
1238 * after usage.
1239 */
1240 GList *
1241 gst_registry_get_feature_list_by_plugin (GstRegistry * registry,
1242 const gchar * name)
1243 {
1244 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
1245 g_return_val_if_fail (name != NULL, NULL);
1247 return gst_registry_feature_filter (registry,
1248 _gst_plugin_feature_filter_plugin_name, FALSE, (gpointer) name);
1249 }
1251 /* Unref and delete the default registry */
1252 void
1253 _priv_gst_registry_cleanup ()
1254 {
1255 GstRegistry *registry;
1257 g_static_mutex_lock (&_gst_registry_mutex);
1258 if ((registry = _gst_registry_default) != NULL) {
1259 _gst_registry_default = NULL;
1260 }
1261 g_static_mutex_unlock (&_gst_registry_mutex);
1263 /* unref outside of the lock because we can. */
1264 if (registry)
1265 gst_object_unref (registry);
1266 }
1268 /**
1269 * gst_default_registry_check_feature_version:
1270 * @feature_name: the name of the feature (e.g. "oggdemux")
1271 * @min_major: the minimum major version number
1272 * @min_minor: the minimum minor version number
1273 * @min_micro: the minimum micro version number
1274 *
1275 * Checks whether a plugin feature by the given name exists in the
1276 * default registry and whether its version is at least the
1277 * version required.
1278 *
1279 * Returns: #TRUE if the feature could be found and the version is
1280 * the same as the required version or newer, and #FALSE otherwise.
1281 */
1282 gboolean
1283 gst_default_registry_check_feature_version (const gchar * feature_name,
1284 guint min_major, guint min_minor, guint min_micro)
1285 {
1286 GstPluginFeature *feature;
1287 GstRegistry *registry;
1288 gboolean ret = FALSE;
1290 g_return_val_if_fail (feature_name != NULL, FALSE);
1292 GST_DEBUG ("Looking up plugin feature '%s'", feature_name);
1294 registry = gst_registry_get_default ();
1295 feature = gst_registry_lookup_feature (registry, feature_name);
1296 if (feature) {
1297 ret = gst_plugin_feature_check_version (feature, min_major, min_minor,
1298 min_micro);
1299 gst_object_unref (feature);
1300 } else {
1301 GST_DEBUG ("Could not find plugin feature '%s'", feature_name);
1302 }
1304 return ret;
1305 }
1307 static void
1308 load_plugin_func (gpointer data, gpointer user_data)
1309 {
1310 GstPlugin *plugin;
1311 const gchar *filename;
1312 GError *err = NULL;
1314 filename = (const gchar *) data;
1315 GST_DEBUG ("Pre-loading plugin %s", filename);
1317 plugin = gst_plugin_load_file (filename, &err);
1319 if (plugin) {
1320 GST_INFO ("Loaded plugin: \"%s\"", filename);
1322 gst_default_registry_add_plugin (plugin);
1323 } else {
1324 if (err) {
1325 /* Report error to user, and free error */
1326 GST_ERROR ("Failed to load plugin: %s", err->message);
1327 g_error_free (err);
1328 } else {
1329 GST_WARNING ("Failed to load plugin: \"%s\"", filename);
1330 }
1331 }
1332 }
1334 #ifndef GST_DISABLE_REGISTRY
1335 /* Unref all plugins marked 'cached', to clear old plugins that no
1336 * longer exist. Returns TRUE if any plugins were removed */
1337 static gboolean
1338 gst_registry_remove_cache_plugins (GstRegistry * registry)
1339 {
1340 GList *g;
1341 GList *g_next;
1342 GstPlugin *plugin;
1343 gboolean changed = FALSE;
1345 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
1347 GST_OBJECT_LOCK (registry);
1349 GST_DEBUG_OBJECT (registry, "removing cached plugins");
1350 g = registry->plugins;
1351 while (g) {
1352 g_next = g->next;
1353 plugin = g->data;
1354 if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
1355 GST_DEBUG_OBJECT (registry, "removing cached plugin \"%s\"",
1356 GST_STR_NULL (plugin->filename));
1357 registry->plugins = g_list_delete_link (registry->plugins, g);
1358 if (G_LIKELY (plugin->basename))
1359 g_hash_table_remove (registry->basename_hash, plugin->basename);
1360 gst_registry_remove_features_for_plugin_unlocked (registry, plugin);
1361 gst_object_unref (plugin);
1362 changed = TRUE;
1363 }
1364 g = g_next;
1365 }
1367 GST_OBJECT_UNLOCK (registry);
1369 return changed;
1370 }
1372 typedef enum
1373 {
1374 REGISTRY_SCAN_AND_UPDATE_FAILURE = 0,
1375 REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED,
1376 REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED
1377 } GstRegistryScanAndUpdateResult;
1379 /*
1380 * scan_and_update_registry:
1381 * @default_registry: the #GstRegistry
1382 * @registry_file: registry filename
1383 * @write_changes: write registry if it has changed?
1384 *
1385 * Scans for registry changes and eventually updates the registry cache.
1386 *
1387 * Return: %REGISTRY_SCAN_AND_UPDATE_FAILURE if the registry could not scanned
1388 * or updated, %REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED if the
1389 * registry is clean and %REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED if
1390 * it has been updated and the cache needs to be re-read.
1391 */
1392 static GstRegistryScanAndUpdateResult
1393 scan_and_update_registry (GstRegistry * default_registry,
1394 const gchar * registry_file, gboolean write_changes, GError ** error)
1395 {
1396 const gchar *plugin_path;
1397 gboolean changed = FALSE;
1398 GList *l;
1399 GstRegistryScanContext context;
1401 GST_INFO ("Validating plugins from registry cache: %s", registry_file);
1403 init_scan_context (&context, default_registry);
1405 /* It sounds tempting to just compare the mtime of directories with the mtime
1406 * of the registry cache, but it does not work. It would not catch updated
1407 * plugins, which might bring more or less features.
1408 */
1410 /* scan paths specified via --gst-plugin-path */
1411 GST_DEBUG ("scanning paths added via --gst-plugin-path");
1412 for (l = _priv_gst_plugin_paths; l != NULL; l = l->next) {
1413 GST_INFO ("Scanning plugin path: \"%s\"", (gchar *) l->data);
1414 changed |= gst_registry_scan_path_internal (&context, (gchar *) l->data);
1415 }
1416 /* keep plugin_paths around in case a re-scan is forced later on */
1418 /* GST_PLUGIN_PATH specifies a list of directories to scan for
1419 * additional plugins. These take precedence over the system plugins */
1420 plugin_path = g_getenv ("GST_PLUGIN_PATH");
1421 if (plugin_path) {
1422 char **list;
1423 int i;
1425 GST_DEBUG ("GST_PLUGIN_PATH set to %s", plugin_path);
1426 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
1427 for (i = 0; list[i]; i++) {
1428 changed |= gst_registry_scan_path_internal (&context, list[i]);
1429 }
1430 g_strfreev (list);
1431 } else {
1432 GST_DEBUG ("GST_PLUGIN_PATH not set");
1433 }
1435 /* GST_PLUGIN_SYSTEM_PATH specifies a list of plugins that are always
1436 * loaded by default. If not set, this defaults to the system-installed
1437 * path, and the plugins installed in the user's home directory */
1438 plugin_path = g_getenv ("GST_PLUGIN_SYSTEM_PATH");
1439 if (plugin_path == NULL) {
1440 char *home_plugins;
1442 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH not set");
1444 /* plugins in the user's home directory take precedence over
1445 * system-installed ones */
1446 home_plugins = g_build_filename (g_get_home_dir (),
1447 ".gstreamer-" GST_MAJORMINOR, "plugins", NULL);
1448 GST_DEBUG ("scanning home plugins %s", home_plugins);
1449 changed |= gst_registry_scan_path_internal (&context, home_plugins);
1450 g_free (home_plugins);
1452 /* add the main (installed) library path */
1453 GST_DEBUG ("scanning main plugins %s", PLUGINDIR);
1454 changed |= gst_registry_scan_path_internal (&context, PLUGINDIR);
1456 #ifdef G_OS_WIN32
1457 {
1458 char *base_dir;
1459 char *dir;
1461 base_dir =
1462 g_win32_get_package_installation_directory_of_module
1463 (_priv_gst_dll_handle);
1465 dir = g_build_filename (base_dir, "lib", "gstreamer-0.10", NULL);
1466 GST_DEBUG ("scanning DLL dir %s", dir);
1468 changed |= gst_registry_scan_path_internal (&context, dir);
1470 g_free (dir);
1471 g_free (base_dir);
1472 }
1473 #endif
1474 } else {
1475 gchar **list;
1476 gint i;
1478 GST_DEBUG ("GST_PLUGIN_SYSTEM_PATH set to %s", plugin_path);
1479 list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
1480 for (i = 0; list[i]; i++) {
1481 changed |= gst_registry_scan_path_internal (&context, list[i]);
1482 }
1483 g_strfreev (list);
1484 }
1486 clear_scan_context (&context);
1487 changed |= context.changed;
1489 /* Remove cached plugins so stale info is cleared. */
1490 changed |= gst_registry_remove_cache_plugins (default_registry);
1492 if (!changed) {
1493 GST_INFO ("Registry cache has not changed");
1494 return REGISTRY_SCAN_AND_UPDATE_SUCCESS_NOT_CHANGED;
1495 }
1497 if (!write_changes) {
1498 GST_INFO ("Registry cache changed, but writing is disabled. Not writing.");
1499 return REGISTRY_SCAN_AND_UPDATE_FAILURE;
1500 }
1502 GST_INFO ("Registry cache changed. Writing new registry cache");
1503 if (!gst_registry_binary_write_cache (default_registry, registry_file)) {
1504 g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
1505 _("Error writing registry cache to %s: %s"),
1506 registry_file, g_strerror (errno));
1507 return REGISTRY_SCAN_AND_UPDATE_FAILURE;
1508 }
1510 GST_INFO ("Registry cache written successfully");
1511 return REGISTRY_SCAN_AND_UPDATE_SUCCESS_UPDATED;
1512 }
1514 static gboolean
1515 ensure_current_registry (GError ** error)
1516 {
1517 gchar *registry_file;
1518 GstRegistry *default_registry;
1519 gboolean ret = TRUE;
1520 gboolean do_update = TRUE;
1521 gboolean have_cache = TRUE;
1523 default_registry = gst_registry_get_default ();
1524 registry_file = g_strdup (g_getenv ("GST_REGISTRY"));
1525 if (registry_file == NULL) {
1526 registry_file = g_build_filename (g_get_home_dir (),
1527 ".gstreamer-" GST_MAJORMINOR, "registry." HOST_CPU ".bin", NULL);
1528 }
1530 if (!_gst_disable_registry_cache) {
1531 GST_INFO ("reading registry cache: %s", registry_file);
1532 have_cache = gst_registry_binary_read_cache (default_registry,
1533 registry_file);
1534 /* Only ever read the registry cache once, then disable it for
1535 * subsequent updates during the program lifetime */
1536 _gst_disable_registry_cache = TRUE;
1537 }
1539 if (have_cache) {
1540 do_update = !_priv_gst_disable_registry_update;
1541 if (do_update) {
1542 const gchar *update_env;
1544 if ((update_env = g_getenv ("GST_REGISTRY_UPDATE"))) {
1545 /* do update for any value different from "no" */
1546 do_update = (strcmp (update_env, "no") != 0);
1547 }
1548 }
1549 }
1551 if (do_update) {
1552 /* now check registry */
1553 GST_DEBUG ("Updating registry cache");
1554 scan_and_update_registry (default_registry, registry_file, TRUE, error);
1555 } else {
1556 GST_DEBUG ("Not updating registry cache (disabled)");
1557 }
1559 g_free (registry_file);
1560 GST_INFO ("registry reading and updating done, result = %d", ret);
1562 return ret;
1563 }
1564 #endif /* GST_DISABLE_REGISTRY */
1566 /**
1567 * gst_registry_fork_is_enabled:
1568 *
1569 * By default GStreamer will perform scanning and rebuilding of the
1570 * registry file using a helper child process.
1571 *
1572 * Applications might want to disable this behaviour with the
1573 * gst_registry_fork_set_enabled() function, in which case new plugins
1574 * are scanned (and loaded) into the application process.
1575 *
1576 * Returns: %TRUE if GStreamer will use the child helper process when
1577 * rebuilding the registry.
1578 *
1579 * Since: 0.10.10
1580 */
1581 gboolean
1582 gst_registry_fork_is_enabled (void)
1583 {
1584 return _gst_enable_registry_fork;
1585 }
1587 /**
1588 * gst_registry_fork_set_enabled:
1589 * @enabled: whether rebuilding the registry can use a temporary child helper process.
1590 *
1591 * Applications might want to disable/enable spawning of a child helper process
1592 * when rebuilding the registry. See gst_registry_fork_is_enabled() for more
1593 * information.
1594 *
1595 * Since: 0.10.10
1596 */
1597 void
1598 gst_registry_fork_set_enabled (gboolean enabled)
1599 {
1600 _gst_enable_registry_fork = enabled;
1601 }
1603 /**
1604 * gst_update_registry:
1605 *
1606 * Forces GStreamer to re-scan its plugin paths and update the default
1607 * plugin registry.
1608 *
1609 * Applications will almost never need to call this function, it is only
1610 * useful if the application knows new plugins have been installed (or old
1611 * ones removed) since the start of the application (or, to be precise, the
1612 * first call to gst_init()) and the application wants to make use of any
1613 * newly-installed plugins without restarting the application.
1614 *
1615 * Applications should assume that the registry update is neither atomic nor
1616 * thread-safe and should therefore not have any dynamic pipelines running
1617 * (including the playbin and decodebin elements) and should also not create
1618 * any elements or access the GStreamer registry while the update is in
1619 * progress.
1620 *
1621 * Note that this function may block for a significant amount of time.
1622 *
1623 * Returns: %TRUE if the registry has been updated successfully (does not
1624 * imply that there were changes), otherwise %FALSE.
1625 *
1626 * Since: 0.10.12
1627 */
1628 gboolean
1629 gst_update_registry (void)
1630 {
1631 gboolean res;
1633 #ifndef GST_DISABLE_REGISTRY
1634 GError *err = NULL;
1636 res = ensure_current_registry (&err);
1637 if (err) {
1638 GST_WARNING ("registry update failed: %s", err->message);
1639 g_error_free (err);
1640 } else {
1641 GST_LOG ("registry update succeeded");
1642 }
1644 #else
1645 GST_WARNING ("registry update failed: %s", "registry disabled");
1646 res = TRUE;
1647 #endif /* GST_DISABLE_REGISTRY */
1649 if (_priv_gst_preload_plugins) {
1650 GST_DEBUG ("Preloading indicated plugins...");
1651 g_slist_foreach (_priv_gst_preload_plugins, load_plugin_func, NULL);
1652 }
1654 return res;
1655 }
1657 /**
1658 * gst_registry_get_feature_list_cookie:
1659 *
1660 * Returns the registrys feature list cookie. This changes
1661 * every time a feature is added or removed from the registry.
1662 *
1663 * Returns: the feature list cookie.
1664 *
1665 * Since: 0.10.26
1666 */
1667 guint32
1668 gst_registry_get_feature_list_cookie (GstRegistry * registry)
1669 {
1670 g_return_val_if_fail (GST_IS_REGISTRY (registry), 0);
1672 return registry->priv->cookie;
1673 }