*/
/**
* SECTION:gstpreset
+ * @title: GstPreset
* @short_description: helper interface for element presets
*
* This interface offers methods to query and manipulate parameter preset sets.
* for gst_preset_save_preset() and gst_preset_delete_preset() to %NULL.
* Applications can use gst_preset_is_editable() to check for that.
*
- * The default implementation supports presets located in a system directory,
+ * The default implementation supports presets located in a system directory,
* application specific directory and in the users home directory. When getting
- * a list of presets individual presets are read and overlaid in 1) system,
+ * a list of presets individual presets are read and overlaid in 1) system,
* 2) application and 3) user order. Whenever an earlier entry is newer, the
- * later entries will be updated.
- *
+ * later entries will be updated. Since 1.8 you can also provide extra paths
+ * where to find presets through the GST_PRESET_PATH environment variable.
+ * Presets found in those paths will be considered as "app presets".
*/
/* FIXME:
* - non racyness
/* ERRORS */
load_error:
{
- GST_WARNING_OBJECT (preset, "Unable to read preset file %s: %s",
+ GST_INFO_OBJECT (preset, "Unable to read preset file %s: %s",
preset_path, error->message);
g_error_free (error);
g_key_file_free (in);
g_strfreev (groups);
}
+typedef struct
+{
+ GKeyFile *preset;
+ guint64 version;
+} PresetAndVersion;
+
+static gint
+compare_preset_and_version (gconstpointer a, gconstpointer b,
+ gpointer user_data)
+{
+ const PresetAndVersion *pa = a, *pb = b;
+
+ if (pa->version > pb->version)
+ return -1;
+ if (pa->version < pb->version)
+ return 1;
+ else
+ return 0;
+}
+
/* reads the user and system presets files and merges them together. This
* function caches the GKeyFile on the element type. If there is no existing
* preset file, a new in-memory GKeyFile will be created. */
guint64 version = G_GUINT64_CONSTANT (0);
gboolean merged = FALSE;
GKeyFile *in_user, *in_app = NULL, *in_system;
-
- preset_get_paths (preset, &preset_user_path, &preset_app_path,
- &preset_system_path);
+ GQueue in_env = G_QUEUE_INIT;
+ gboolean have_env = FALSE;
+ const gchar *envvar;
/* try to load the user, app and system presets, we do this to get the
* versions of all files. */
+ preset_get_paths (preset, &preset_user_path, &preset_app_path,
+ &preset_system_path);
in_user = preset_open_and_parse_header (preset, preset_user_path,
&version_user);
+
if (preset_app_path) {
in_app = preset_open_and_parse_header (preset, preset_app_path,
&version_app);
}
+
+ envvar = g_getenv ("GST_PRESET_PATH");
+ if (envvar) {
+ gint i;
+ gchar **preset_dirs = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, -1);
+
+ for (i = 0; preset_dirs[i]; i++) {
+ gchar *preset_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.prs",
+ preset_dirs[i], G_OBJECT_TYPE_NAME (preset));
+ GKeyFile *env_file;
+ guint64 env_version;
+
+ env_file = preset_open_and_parse_header (preset, preset_path,
+ &env_version);
+ g_free (preset_path);
+ if (env_file) {
+ PresetAndVersion *pv = g_new (PresetAndVersion, 1);
+ pv->preset = env_file;
+ pv->version = env_version;
+ g_queue_push_tail (&in_env, pv);
+ have_env = TRUE;
+ }
+ }
+ g_strfreev (preset_dirs);
+ }
+
in_system = preset_open_and_parse_header (preset, preset_system_path,
&version_system);
presets = in_system;
version = version_system;
}
+
+ if (have_env) {
+ GList *l;
+
+ /* merge the ones from the environment paths. If any of them has a
+ * higher version, take that as the "master" version. Lower versions are
+ * then just merged in. */
+ g_queue_sort (&in_env, compare_preset_and_version, NULL);
+ /* highest version to lowest */
+ for (l = in_env.head; l; l = l->next) {
+ PresetAndVersion *pv = l->data;
+
+ if (version > pv->version) {
+ preset_merge (presets, pv->preset);
+ g_key_file_free (pv->preset);
+ } else {
+ if (presets)
+ g_key_file_free (presets);
+ presets = pv->preset;
+ version = pv->version;
+ }
+ g_free (pv);
+ }
+ g_queue_clear (&in_env);
+ }
+
if (in_app) {
- /* if system version is higher, merge */
+ /* if system/env version is higher, merge */
if (version > version_app) {
preset_merge (presets, in_app);
g_key_file_free (in_app);
if (presets)
g_key_file_free (presets);
presets = in_app;
- version = version_system;
+ version = version_app;
}
}
if (in_user) {
- /* if system or app version is higher, merge */
+ /* if system/env or app version is higher, merge */
if (version > version_user) {
preset_merge (presets, in_user);
g_key_file_free (in_user);
/* check if we have a settings for this element property */
if (!(str = g_key_file_get_value (presets, name, props[i], NULL))) {
/* the element has a property but the parameter is not in the keyfile */
- GST_WARNING_OBJECT (preset, "parameter '%s' not in preset", props[i]);
+ GST_INFO_OBJECT (preset, "parameter '%s' not in preset", props[i]);
continue;
}
continue;
}
+ if (property->flags & G_PARAM_DEPRECATED) {
+ GST_INFO_OBJECT (preset, "Not saving property %s as it is deprecated",
+ property->name);
+ continue;
+ }
+
g_value_init (&gvalue, property->value_type);
if (is_child_proxy) {
gst_child_proxy_get_property ((GstChildProxy *) preset, props[i],
/**
* gst_preset_set_app_dir:
- * @app_dir: the application specific preset dir
+ * @app_dir: (type filename): the application specific preset dir
*
* Sets an extra directory as an absolute path that should be considered when
- * looking for presets. Any presets in the application dir will shadow the
+ * looking for presets. Any presets in the application dir will shadow the
* system presets.
*
* Returns: %TRUE for success, %FALSE if the dir already has been set
* Gets the directory for application specific presets if set by the
* application.
*
- * Returns: (nullable): the directory or %NULL, don't free or modify
+ * Returns: (nullable) (type filename): the directory or %NULL, don't free or modify
* the string
*/
const gchar *