* means of doing so is to load every plugin and look at the resulting
* information that is gathered in the default registry. Clearly, this is a time
* consuming process, so we cache information in the registry file. The format
- * and location of the cache file is internal to gstreamer.
+ * and location of the cache file is internal to gstreamer.
*
* On startup, plugins are searched for in the plugin search path. The following
* locations are checked in this order:
* different sets of plugins. For various reasons, at init time, the cache is
* stored in the default registry, and plugins not relevant to the current
* process are marked with the %GST_PLUGIN_FLAG_CACHED bit. These plugins are
- * removed at the end of intitialization.
+ * removed at the end of initialization.
*/
#ifdef HAVE_CONFIG_H
#include "gsterror.h"
#include "gstregistry.h"
#include "gstmarshal.h"
-#include "gstfilter.h"
#include "gstpluginloader.h"
/* Set to TRUE when the registry cache should be disabled */
gboolean _gst_disable_registry_cache = FALSE;
+
+static gboolean __registry_reuse_plugin_scanner = TRUE;
#endif
/* Element signals and args */
static GstPlugin *gst_registry_lookup_bn_locked (GstRegistry * registry,
const char *basename);
+#define gst_registry_parent_class parent_class
G_DEFINE_TYPE (GstRegistry, gst_registry, GST_TYPE_OBJECT);
-static GstObjectClass *parent_class = NULL;
static void
gst_registry_class_init (GstRegistryClass * klass)
gobject_class = (GObjectClass *) klass;
- parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (GstRegistryPrivate));
/**
GstPluginFeature *feature = f->data;
if (feature) {
- GST_LOG_OBJECT (registry, "removing feature %p (%s)",
- feature, gst_plugin_feature_get_name (feature));
- gst_object_unref (feature);
+ GST_LOG_OBJECT (registry, "removing feature %p (%s)", feature,
+ GST_OBJECT_NAME (feature));
+ gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = g_list_next (f);
}
plugin->desc.name);
registry->features = g_list_delete_link (registry->features, f);
- g_hash_table_remove (registry->feature_hash, feature->name);
- gst_object_unref (feature);
+ g_hash_table_remove (registry->feature_hash, GST_OBJECT_NAME (feature));
+ gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = next;
}
g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
g_return_val_if_fail (GST_IS_PLUGIN_FEATURE (feature), FALSE);
- g_return_val_if_fail (feature->name != NULL, FALSE);
+ g_return_val_if_fail (GST_OBJECT_NAME (feature) != NULL, FALSE);
g_return_val_if_fail (feature->plugin_name != NULL, FALSE);
GST_OBJECT_LOCK (registry);
existing_feature = gst_registry_lookup_feature_locked (registry,
- feature->name);
+ GST_OBJECT_NAME (feature));
if (G_UNLIKELY (existing_feature)) {
GST_DEBUG_OBJECT (registry, "replacing existing feature %p (%s)",
- existing_feature, feature->name);
+ existing_feature, GST_OBJECT_NAME (feature));
/* Remove the existing feature from the list now, before we insert the new
* one, but don't unref yet because the hash is still storing a reference to
* it. */
registry->features = g_list_remove (registry->features, existing_feature);
}
- GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature, feature->name);
+ GST_DEBUG_OBJECT (registry, "adding feature %p (%s)", feature,
+ GST_OBJECT_NAME (feature));
registry->features = g_list_prepend (registry->features, feature);
- g_hash_table_replace (registry->feature_hash, feature->name, feature);
+ g_hash_table_replace (registry->feature_hash, GST_OBJECT_NAME (feature),
+ feature);
if (G_UNLIKELY (existing_feature)) {
/* We unref now. No need to remove the feature name from the hash table, it
* got replaced by the new feature */
- gst_object_unref (existing_feature);
+ gst_object_unparent (GST_OBJECT_CAST (existing_feature));
}
- gst_object_ref_sink (feature);
+ gst_object_set_parent (GST_OBJECT_CAST (feature), GST_OBJECT_CAST (registry));
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
- GST_LOG_OBJECT (registry, "emitting feature-added for %s", feature->name);
+ GST_LOG_OBJECT (registry, "emitting feature-added for %s",
+ GST_OBJECT_NAME (feature));
g_signal_emit (registry, gst_registry_signals[FEATURE_ADDED], 0, feature);
return TRUE;
GST_OBJECT_LOCK (registry);
registry->features = g_list_remove (registry->features, feature);
- g_hash_table_remove (registry->feature_hash, feature->name);
+ g_hash_table_remove (registry->feature_hash, GST_OBJECT_NAME (feature));
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
- gst_object_unref (feature);
+
+ gst_object_unparent ((GstObject *) feature);
}
/**
gst_registry_plugin_filter (GstRegistry * registry,
GstPluginFilter filter, gboolean first, gpointer user_data)
{
- GList *list;
- GList *g;
+ GList *list = NULL;
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
GST_OBJECT_LOCK (registry);
- list = gst_filter_run (registry->plugins, (GstFilterFunc) filter, first,
- user_data);
- for (g = list; g; g = g->next) {
- gst_object_ref (GST_PLUGIN_CAST (g->data));
+ {
+ const GList *walk;
+
+ for (walk = registry->plugins; walk != NULL; walk = walk->next) {
+ GstPlugin *plugin = walk->data;
+
+ if (filter == NULL || filter (plugin, user_data)) {
+ list = g_list_prepend (list, gst_object_ref (plugin));
+
+ if (first)
+ break;
+ }
+ }
}
GST_OBJECT_UNLOCK (registry);
return list;
}
+typedef struct
+{
+ const gchar *name;
+ GType type;
+} GstTypeNameData;
+
+static gboolean
+gst_plugin_feature_type_name_filter (GstPluginFeature * feature,
+ GstTypeNameData * data)
+{
+ g_assert (GST_IS_PLUGIN_FEATURE (feature));
+
+ return ((data->type == 0 || data->type == G_OBJECT_TYPE (feature)) &&
+ (data->name == NULL || !strcmp (data->name, GST_OBJECT_NAME (feature))));
+}
+
/* returns TRUE if the list was changed
*
* Must be called with the object lock taken */
if (G_UNLIKELY (!*previous || priv->cookie != *cookie)) {
GstTypeNameData data;
+ const GList *walk;
- if (*previous)
+ if (*previous) {
gst_plugin_feature_list_free (*previous);
+ *previous = NULL;
+ }
data.type = type;
data.name = NULL;
- *previous =
- gst_filter_run (registry->features,
- (GstFilterFunc) gst_plugin_feature_type_name_filter, FALSE, &data);
- g_list_foreach (*previous, (GFunc) gst_object_ref, NULL);
+
+ for (walk = registry->features; walk != NULL; walk = walk->next) {
+ GstPluginFeature *feature = walk->data;
+
+ if (gst_plugin_feature_type_name_filter (feature, &data)) {
+ *previous = g_list_prepend (*previous, gst_object_ref (feature));
+ }
+ }
+
*cookie = priv->cookie;
res = TRUE;
}
/* to make the order in which things happen more deterministic,
* sort by name when the ranks are the same. */
- return strcmp (fac1->name, fac2->name);
+ return strcmp (GST_OBJECT_NAME (fac1), GST_OBJECT_NAME (fac2));
}
static GList *
gst_registry_feature_filter (GstRegistry * registry,
GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
{
- GList *list;
- GList *g;
+ GList *list = NULL;
g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
GST_OBJECT_LOCK (registry);
- list = gst_filter_run (registry->features, (GstFilterFunc) filter, first,
- user_data);
- for (g = list; g; g = g->next) {
- gst_object_ref (GST_PLUGIN_FEATURE_CAST (g->data));
+ {
+ const GList *walk;
+
+ for (walk = registry->features; walk != NULL; walk = walk->next) {
+ GstPluginFeature *feature = walk->data;
+
+ if (filter == NULL || filter (feature, user_data)) {
+ list = g_list_prepend (list, gst_object_ref (feature));
+
+ if (first)
+ break;
+ }
+ }
}
GST_OBJECT_UNLOCK (registry);
changed = TRUE;
}
+ if (!__registry_reuse_plugin_scanner) {
+ clear_scan_context (context);
+ context->helper_state = REGISTRY_SCAN_HELPER_NOT_STARTED;
+ }
+
return changed;
}
} else {
GST_INFO_OBJECT (context->registry, "cached info for %s is stale",
filename);
- GST_DEBUG_OBJECT (context->registry, "mtime %ld != %ld or size %"
- G_GINT64_FORMAT " != %" G_GINT64_FORMAT " or external dependency "
- "env_vars changed: %d or external dependencies changed: %d"
- " or old path %s != new path %s",
- plugin->file_mtime, file_status.st_mtime,
+ GST_DEBUG_OBJECT (context->registry, "mtime %" G_GINT64_FORMAT " != %"
+ G_GINT64_FORMAT " or size %" G_GINT64_FORMAT " != %"
+ G_GINT64_FORMAT " or external dependency env_vars changed: %d or"
+ " external dependencies changed: %d or old path %s != new path %s",
+ (gint64) plugin->file_mtime, (gint64) file_status.st_mtime,
(gint64) plugin->file_size, (gint64) file_status.st_size,
env_vars_changed, deps_changed, plugin->filename, filename);
gst_registry_remove_plugin (context->registry, plugin);
}
GST_INFO ("Registry cache changed. Writing new registry cache");
- if (!gst_registry_binary_write_cache (default_registry, registry_file)) {
+ if (!priv_gst_registry_binary_write_cache (default_registry, registry_file)) {
g_set_error (error, GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
_("Error writing registry cache to %s: %s"),
registry_file, g_strerror (errno));
if (!_gst_disable_registry_cache) {
GST_INFO ("reading registry cache: %s", registry_file);
- have_cache = gst_registry_binary_read_cache (default_registry,
+ have_cache = priv_gst_registry_binary_read_cache (default_registry,
registry_file);
/* Only ever read the registry cache once, then disable it for
* subsequent updates during the program lifetime */
}
if (do_update) {
+ const gchar *reuse_env;
+
+ if ((reuse_env = g_getenv ("GST_REGISTRY_REUSE_PLUGIN_SCANNER"))) {
+ /* do reuse for any value different from "no" */
+ __registry_reuse_plugin_scanner = (strcmp (reuse_env, "no") != 0);
+ }
/* now check registry */
GST_DEBUG ("Updating registry cache");
scan_and_update_registry (default_registry, registry_file, TRUE, error);