Commit 2ae03ba7 authored by Tim-Philipp Müller's avatar Tim-Philipp Müller 🐠

Add API for making a GStreamer plugin 'dependent' on external files,...

Add API for making a GStreamer plugin 'dependent' on external files, directories or environment variables, so that GS...

Original commit message from CVS:
* docs/gst/gstreamer-sections.txt::
* gst/gst_private.h: (GstPluginDep), (_GstPluginPrivate):
* gst/gstplugin.c: (gst_plugin_init), (gst_plugin_finalize),
(gst_plugin_class_init), (gst_plugin_list_free),
(gst_plugin_ext_dep_get_env_vars_hash),
(_priv_plugin_deps_env_vars_changed),
(gst_plugin_ext_dep_extract_env_vars_paths),
(gst_plugin_ext_dep_get_hash_from_stat_entry),
(gst_plugin_ext_dep_direntry_matches),
(gst_plugin_ext_dep_scan_dir_and_match_names),
(gst_plugin_ext_dep_scan_path_with_filenames),
(gst_plugin_ext_dep_get_stat_hash),
(_priv_plugin_deps_files_changed), (gst_plugin_ext_dep_free),
(gst_plugin_ext_dep_strv_equal), (gst_plugin_ext_dep_equals),
(gst_plugin_add_dependency), (gst_plugin_add_dependency_simple):
* gst/gstplugin.h: (GstPluginPrivate), (GstPluginFlags),
(GST_PLUGIN_DEPENDENCY_FLAG_NONE),
(GST_PLUGIN_DEPENDENCY_FLAG_RECURSE),
(GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY),
(GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX),
(GstPluginDependencyFlags), (GstPluginFilter):
* gst/gstregistry.c: (gst_registry_scan_path_level):
* gst/gstregistrybinary.c: (gst_registry_binary_save_feature),
(gst_registry_binary_save_plugin_dep),
(gst_registry_binary_save_plugin),
(gst_registry_binary_load_feature),
(gst_registry_binary_load_plugin_dep_strv),
(gst_registry_binary_load_plugin_dep),
(gst_registry_binary_load_plugin):
* gst/gstregistrybinary.h: (GST_MAGIC_BINARY_VERSION_STR),
(GstBinaryPluginElement), (_GstBinaryDep), (GstBinaryDep):
* gst/gstregistryxml.c: (gst_registry_xml_save_plugin):
Add API for making a GStreamer plugin 'dependent' on external files,
directories or environment variables, so that GStreamer knows when
it needs to re-load GStreamer plugins that wrap other plugin systems.
Fixes bug #350477.
API: add gst_plugin_add_dependency()
API: add gst_plugin_add_dependency_simple()
parent 15e2bf52
2009-01-06 Tim-Philipp Müller <tim.muller at collabora co uk>
* docs/gst/gstreamer-sections.txt::
* gst/gst_private.h: (GstPluginDep), (_GstPluginPrivate):
* gst/gstplugin.c: (gst_plugin_init), (gst_plugin_finalize),
(gst_plugin_class_init), (gst_plugin_list_free),
(gst_plugin_ext_dep_get_env_vars_hash),
(_priv_plugin_deps_env_vars_changed),
(gst_plugin_ext_dep_extract_env_vars_paths),
(gst_plugin_ext_dep_get_hash_from_stat_entry),
(gst_plugin_ext_dep_direntry_matches),
(gst_plugin_ext_dep_scan_dir_and_match_names),
(gst_plugin_ext_dep_scan_path_with_filenames),
(gst_plugin_ext_dep_get_stat_hash),
(_priv_plugin_deps_files_changed), (gst_plugin_ext_dep_free),
(gst_plugin_ext_dep_strv_equal), (gst_plugin_ext_dep_equals),
(gst_plugin_add_dependency), (gst_plugin_add_dependency_simple):
* gst/gstplugin.h: (GstPluginPrivate), (GstPluginFlags),
(GST_PLUGIN_DEPENDENCY_FLAG_NONE),
(GST_PLUGIN_DEPENDENCY_FLAG_RECURSE),
(GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY),
(GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX),
(GstPluginDependencyFlags), (GstPluginFilter):
* gst/gstregistry.c: (gst_registry_scan_path_level):
* gst/gstregistrybinary.c: (gst_registry_binary_save_feature),
(gst_registry_binary_save_plugin_dep),
(gst_registry_binary_save_plugin),
(gst_registry_binary_load_feature),
(gst_registry_binary_load_plugin_dep_strv),
(gst_registry_binary_load_plugin_dep),
(gst_registry_binary_load_plugin):
* gst/gstregistrybinary.h: (GST_MAGIC_BINARY_VERSION_STR),
(GstBinaryPluginElement), (_GstBinaryDep), (GstBinaryDep):
* gst/gstregistryxml.c: (gst_registry_xml_save_plugin):
Add API for making a GStreamer plugin 'dependent' on external files,
directories or environment variables, so that GStreamer knows when
it needs to re-load GStreamer plugins that wrap other plugin systems.
Fixes bug #350477.
API: add gst_plugin_add_dependency()
API: add gst_plugin_add_dependency_simple()
2009-01-06 Tim-Philipp Müller <tim.muller at collabora co uk>
* docs/faq/gst-uninstalled:
......@@ -1641,6 +1641,10 @@ gst_plugin_load
gst_plugin_load_by_name
gst_plugin_list_free
gst_plugin_register_static
<SUBSECTION>
GstPluginDependencyFlags
gst_plugin_add_dependency
gst_plugin_add_dependency_simple
<SUBSECTION Standard>
GstPluginClass
GST_PLUGIN
......@@ -1653,6 +1657,9 @@ GST_IS_PLUGIN
GST_IS_PLUGIN_CLASS
GstPluginFlags
GST_TYPE_PLUGIN_FLAGS
GST_TYPE_PLUGIN_DEPENDENCY_FLAGS
GstPluginPrivate
gst_plugin_dependency_flags_get_type
<SUBSECTION Private>
gst_plugin_get_type
<SUBSECTION Private>
......
......@@ -44,6 +44,9 @@ extern const char g_log_domain_gstreamer[];
/* we need this in pretty much all files */
#include "gstinfo.h"
/* for the flags in the GstPluginDep structure below */
#include "gstplugin.h"
G_BEGIN_DECLS
/* used by gstparse.c and grammar.y */
......@@ -51,6 +54,26 @@ struct _GstParseContext {
GList * missing_elements;
};
/* used by gstplugin.c and gstregistrybinary.c */
typedef struct {
/* details registered via gst_plugin_add_dependency() */
GstPluginDependencyFlags flags;
gchar **env_vars;
gchar **paths;
gchar **names;
/* information saved from the last time the plugin was loaded (-1 = unset) */
guint env_hash; /* hash of content of environment variables in env_vars */
guint stat_hash; /* hash of stat() on all relevant files and directories */
} GstPluginDep;
struct _GstPluginPrivate {
GList *deps; /* list of GstPluginDep structures */
};
gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin);
gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin);
gboolean _priv_gst_in_valgrind (void);
/* Initialize GStreamer private quark storage */
......
This diff is collapsed.
......@@ -37,6 +37,7 @@ G_BEGIN_DECLS
typedef struct _GstPlugin GstPlugin;
typedef struct _GstPluginClass GstPluginClass;
typedef struct _GstPluginPrivate GstPluginPrivate;
typedef struct _GstPluginDesc GstPluginDesc;
/**
......@@ -75,6 +76,27 @@ typedef enum
GST_PLUGIN_FLAG_CACHED = (1<<0)
} GstPluginFlags;
/**
* GstPluginDependencyFlags:
* @GST_PLUGIN_DEPENDENCY_FLAG_NONE : no special flags
* @GST_PLUGIN_DEPENDENCY_FLAG_RECURSE : recurse into subdirectories
* @GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY : use paths
* argument only if none of the environment variables is set
* @GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX : interpret
* filename argument as filter suffix and check all matching files in
* the directory
*
* Flags used in connection with gst_plugin_add_dependency().
*
* Since: 0.10.22
*/
typedef enum {
GST_PLUGIN_DEPENDENCY_FLAG_NONE = 0,
GST_PLUGIN_DEPENDENCY_FLAG_RECURSE = (1 << 0),
GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY = (1 << 1),
GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX = (1 << 2)
} GstPluginDependencyFlags;
/**
* GstPluginInitFunc:
* @plugin: The plugin object that can be used to register #GstPluginFeatures for this plugin.
......@@ -156,7 +178,8 @@ struct _GstPlugin {
gboolean registered; /* TRUE when the registry has seen a filename
* that matches the plugin's basename */
gpointer _gst_reserved[GST_PADDING];
GstPluginPrivate *priv;
gpointer _gst_reserved[GST_PADDING - 1];
};
struct _GstPluginClass {
......@@ -298,6 +321,18 @@ GstPlugin * gst_plugin_load_file (const gchar *filename, GError** error);
GstPlugin * gst_plugin_load (GstPlugin *plugin);
GstPlugin * gst_plugin_load_by_name (const gchar *name);
void gst_plugin_add_dependency (GstPlugin * plugin,
const gchar ** env_vars,
const gchar ** paths,
const gchar ** names,
GstPluginDependencyFlags flags);
void gst_plugin_add_dependency_simple (GstPlugin * plugin,
const gchar * env_vars,
const gchar * paths,
const gchar * names,
GstPluginDependencyFlags flags);
void gst_plugin_list_free (GList *list);
G_END_DECLS
......
......@@ -863,6 +863,8 @@ gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
* was already seen by the registry, we ignore it */
plugin = gst_registry_lookup (registry, filename);
if (plugin) {
gboolean env_vars_changed, deps_changed = FALSE;
if (plugin->registered) {
GST_DEBUG_OBJECT (registry,
"plugin already registered from path \"%s\"",
......@@ -871,8 +873,12 @@ gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
gst_object_unref (plugin);
continue;
}
env_vars_changed = _priv_plugin_deps_env_vars_changed (plugin);
if (plugin->file_mtime == file_status.st_mtime &&
plugin->file_size == file_status.st_size) {
plugin->file_size == file_status.st_size && !env_vars_changed &&
!(deps_changed = _priv_plugin_deps_files_changed (plugin))) {
GST_LOG_OBJECT (registry, "file %s cached", filename);
plugin->flags &= ~GST_PLUGIN_FLAG_CACHED;
GST_LOG_OBJECT (registry, "marking plugin %p as registered as %s",
......@@ -888,9 +894,11 @@ gst_registry_scan_path_level (GstRegistry * registry, const gchar * path,
} else {
GST_INFO_OBJECT (registry, "cached info for %s is stale", filename);
GST_DEBUG_OBJECT (registry, "mtime %ld != %ld or size %"
G_GINT64_FORMAT " != %"
G_GINT64_FORMAT, plugin->file_mtime, file_status.st_mtime,
(gint64) plugin->file_size, (gint64) file_status.st_size);
G_GINT64_FORMAT " != %" G_GINT64_FORMAT " or external dependency "
"env_vars changed: %d or external dependencies changed: %d",
plugin->file_mtime, file_status.st_mtime,
(gint64) plugin->file_size, (gint64) file_status.st_size,
env_vars_changed, deps_changed);
gst_registry_remove_plugin (gst_registry_get_default (), plugin);
/* We don't use a GError here because a failure to load some shared
* objects as plugins is normal (particularly in the uninstalled case)
......
......@@ -554,6 +554,38 @@ fail:
return FALSE;
}
static gboolean
gst_registry_binary_save_plugin_dep (GList ** list, GstPluginDep * dep)
{
GstBinaryDep *ed;
GstBinaryChunk *chk;
gchar **s;
ed = g_new0 (GstBinaryDep, 1);
chk = gst_registry_binary_make_data (ed, sizeof (GstBinaryDep));
ed->flags = dep->flags;
ed->n_env_vars = 0;
ed->n_paths = 0;
ed->n_names = 0;
ed->env_hash = dep->env_hash;
ed->stat_hash = dep->stat_hash;
for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars)
gst_registry_binary_save_string (list, *s);
for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths)
gst_registry_binary_save_string (list, *s);
for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names)
gst_registry_binary_save_string (list, *s);
*list = g_list_prepend (*list, chk);
GST_LOG ("Saved external plugin dependency");
return TRUE;
}
/*
* gst_registry_binary_save_plugin:
......@@ -575,8 +607,18 @@ gst_registry_binary_save_plugin (GList ** list, GstRegistry * registry,
pe->file_size = plugin->file_size;
pe->file_mtime = plugin->file_mtime;
pe->n_deps = 0;
pe->nfeatures = 0;
/* pack external deps */
for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) {
if (!gst_registry_binary_save_plugin_dep (list, walk->data)) {
GST_ERROR ("Could not save external plugin dependency, aborting.");
goto fail;
}
++pe->n_deps;
}
/* pack plugin features */
plugin_features =
gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
......@@ -954,6 +996,57 @@ fail:
return FALSE;
}
static gchar **
gst_registry_binary_load_plugin_dep_strv (gchar ** in, guint n)
{
gchar **arr;
if (n == 0)
return NULL;
arr = g_new0 (gchar *, n + 1);
while (n > 0) {
unpack_string (*in, arr[n - 1]);
--n;
}
return arr;
}
static gboolean
gst_registry_binary_load_plugin_dep (GstPlugin * plugin, gchar ** in)
{
GstPluginDep *dep;
GstBinaryDep *d;
gchar **s;
align (*in);
GST_LOG_OBJECT (plugin, "Unpacking GstBinaryDep from %p", *in);
unpack_element (*in, d, GstBinaryDep);
dep = g_new0 (GstPluginDep, 1);
dep->env_hash = d->env_hash;
dep->stat_hash = d->stat_hash;
dep->flags = d->flags;
dep->names = gst_registry_binary_load_plugin_dep_strv (in, d->n_names);
dep->paths = gst_registry_binary_load_plugin_dep_strv (in, d->n_paths);
dep->env_vars = gst_registry_binary_load_plugin_dep_strv (in, d->n_env_vars);
plugin->priv->deps = g_list_append (plugin->priv->deps, dep);
GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: "
"env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash);
for (s = dep->env_vars; s != NULL && *s != NULL; ++s)
GST_LOG_OBJECT (plugin, " evar: %s", *s);
for (s = dep->paths; s != NULL && *s != NULL; ++s)
GST_LOG_OBJECT (plugin, " path: %s", *s);
for (s = dep->names; s != NULL && *s != NULL; ++s)
GST_LOG_OBJECT (plugin, " name: %s", *s);
return TRUE;
}
/*
* gst_registry_binary_load_plugin:
......@@ -1004,6 +1097,8 @@ gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in)
gst_registry_add_plugin (registry, plugin);
GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry",
plugin->desc.name, pe->nfeatures);
/* Load plugin features */
for (i = 0; i < pe->nfeatures; i++) {
if (!gst_registry_binary_load_feature (registry, in, plugin->desc.name)) {
GST_ERROR ("Error while loading binary feature");
......@@ -1011,6 +1106,14 @@ gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in)
}
}
/* Load external plugin dependencies */
for (i = 0; i < pe->n_deps; ++i) {
if (!gst_registry_binary_load_plugin_dep (plugin, in)) {
GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency");
goto fail;
}
}
return TRUE;
/* Errors */
......
......@@ -57,7 +57,7 @@
* This _must_ be updated whenever the registry format changes,
* we currently use the core version where this change happened.
*/
#define GST_MAGIC_BINARY_VERSION_STR ("0.10.21.1")
#define GST_MAGIC_BINARY_VERSION_STR ("0.10.21.2")
/*
* GST_MAGIC_BINARY_VERSION_LEN:
......@@ -108,9 +108,23 @@ typedef struct _GstBinaryPluginElement
gulong file_size;
gulong file_mtime;
guint n_deps;
guint nfeatures;
} GstBinaryPluginElement;
/* GstBinaryDep:
*/
typedef struct _GstBinaryDep
{
guint flags;
guint n_env_vars;
guint n_paths;
guint n_names;
guint env_hash;
guint stat_hash;
} GstBinaryDep;
/*
* GstBinaryPluginFeature:
......
......@@ -785,6 +785,10 @@ gst_registry_xml_save_plugin (GstRegistry * registry, GstPlugin * plugin)
GList *walk;
char s[100];
if (plugin->priv->deps != NULL) {
GST_WARNING ("XML registry does not support external plugin dependencies");
}
if (!gst_registry_save_escaped (registry, " ", "name", plugin->desc.name))
return FALSE;
if (!gst_registry_save_escaped (registry, " ", "description",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment