diff options
author | jstebbins <[email protected]> | 2008-09-02 22:56:19 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2008-09-02 22:56:19 +0000 |
commit | 45cabbfe4ab8b95b5f25a236f8c93b64d3ccf8df (patch) | |
tree | 40326771d4a7f4721363e3b76ebfca5329595deb /gtk/src/presets.c | |
parent | fd744170cb1da2675e1168402866f5c20f08a726 (diff) |
LinGui: Presets and preferences are now stored as plists
This will also make saving/restoring the queue much easier.
It's a scary big change. 1400 new lines of code. Due to efficiencies
of a better desing, 2400 lines of old code also gets refactored
down to 1600. Giving a final net +600 lines.
Along the way, I stumbled across a couple bugs and fixed them.
Chapter list entry would get wedged under certain circumstances.
Pausing encoding didn't display pause message in status bar.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1662 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src/presets.c')
-rw-r--r-- | gtk/src/presets.c | 722 |
1 files changed, 722 insertions, 0 deletions
diff --git a/gtk/src/presets.c b/gtk/src/presets.c new file mode 100644 index 000000000..75ef74538 --- /dev/null +++ b/gtk/src/presets.c @@ -0,0 +1,722 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * presets.c + * Copyright (C) John Stebbins 2008 <stebbins@stebbins> + * + * presets.c is free software. + * + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License, as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include <glib.h> +#include <glib-object.h> +#include <glib/gstdio.h> +#include <string.h> +#include <gtk/gtk.h> +#include "settings.h" +#include "plist.h" +#include "presets.h" +#include "values.h" + +// +// Internal defaults stored in character arrays and parsed +// the same as external settings files. +const gchar defaultSettings[] = +#include "internal_defaults.h" +; +const gchar standardPresets[] = +#include "standard_presets.h" +; + +static GValue *presetsPlist = NULL; +static GValue *internalPlist = NULL; +static GValue *prefsPlist = NULL; + +static GValue* +plist_get_dict(GValue *presets, const gchar *name) +{ + if (presets == NULL || name == NULL) return NULL; + return ghb_dict_lookup(presets, name); +} + +void +ghb_set_preset_default(GValue *settings) +{ + gchar *preset; + + preset = ghb_settings_get_string (settings, "preset"); + ghb_settings_set_string(settings, "default_preset", preset); + ghb_prefs_save(settings); + g_free(preset); +} + +// Used for sorting dictionaries. +gint +key_cmp(gconstpointer a, gconstpointer b) +{ + gchar *stra = (gchar*)a; + gchar *strb = (gchar*)b; + + return strcmp(stra, strb); +} + +gchar* +ghb_presets_get_description(const gchar *name) +{ + GValue *pdict; + pdict = plist_get_dict(presetsPlist, name); + if (pdict == NULL) return g_strdup(""); + return ghb_value_string(ghb_dict_lookup(pdict, "preset_description")); +} + +static const GValue* +preset_dict_get_value( + GValue *dict, + const gchar *key) +{ + const GValue *gval = NULL; + + if (dict) + { + gval = ghb_dict_lookup(dict, key); + } + if (internalPlist == NULL) return NULL; + if (gval == NULL) + { + dict = plist_get_dict(internalPlist, "Presets"); + if (dict == NULL) return NULL; + gval = ghb_dict_lookup(dict, key); + } + return gval; +} + +static const GValue* +preset_get_value( + const gchar *name, + const gchar *key) +{ + GValue *dict; + + dict = plist_get_dict(presetsPlist, name); + return preset_dict_get_value(dict, key); +} + +GList* +ghb_presets_get_names() +{ + GHashTable *dict; + GList *names, *link; + GList *standard = NULL; + GList *custom = NULL; + + if (presetsPlist == NULL) return NULL; + dict = g_value_get_boxed(presetsPlist); + link = names = g_hash_table_get_keys(dict); + while (link) + { + gchar *name; + gint ptype; + + name = (gchar*)link->data; + ptype = ghb_value_int(preset_get_value(name, "preset_type")); + if (ptype) + custom = g_list_append(custom, name); + else + standard = g_list_append(standard, name); + link = link->next; + } + custom = g_list_sort(custom, key_cmp); + standard = g_list_sort(standard, key_cmp); + g_list_free(names); + names = g_list_concat(standard, custom); + return names; +} + +gint +ghb_preset_flags(const gchar *name) +{ + GValue *dict; + const GValue *gval; + gint ptype; + gint ret = 0; + + dict = plist_get_dict(presetsPlist, name); + gval = preset_dict_get_value(dict, "preset_type"); + if (gval) + { + ptype = ghb_value_int(gval); + ret = (ptype != 0 ? PRESET_CUSTOM : 0); + } + return ret; +} + +static void init_settings_from_dict( + GValue *dest, GValue *internal, GValue *dict); + +static void +init_settings_from_array( + GValue *dest, + GValue *internal, + GValue *array) +{ + GValue *gval, *val; + gint count, ii; + + count = ghb_array_len(array); + // The first element of the internal version is always the + // template for the allowed values + gval = ghb_array_get_nth(internal, 0); + for (ii = 0; ii < count; ii++) + { + val = NULL; + val = ghb_array_get_nth(array, ii); + if (val == NULL) + val = gval; + if (G_VALUE_TYPE(gval) == ghb_dict_get_type()) + { + GValue *new_dict; + new_dict = ghb_dict_value_new(); + ghb_array_append(dest, new_dict); + if (G_VALUE_TYPE(val) == ghb_dict_get_type()) + init_settings_from_dict(new_dict, gval, val); + else + init_settings_from_dict(new_dict, gval, gval); + } + else if (G_VALUE_TYPE(gval) == ghb_array_get_type()) + { + GValue *new_array; + new_array = ghb_array_value_new(8); + ghb_array_append(dest, new_array); + if (G_VALUE_TYPE(val) == ghb_array_get_type()) + init_settings_from_array(new_array, gval, val); + else + init_settings_from_array(new_array, gval, gval); + } + else + { + ghb_array_append(dest, val); + } + } +} + +static void +init_settings_from_dict( + GValue *dest, + GValue *internal, + GValue *dict) +{ + GHashTableIter iter; + gchar *key; + GValue *gval, *val; + + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + val = NULL; + if (dict) + val = ghb_dict_lookup(dict, key); + if (val == NULL) + val = gval; + if (G_VALUE_TYPE(gval) == ghb_dict_get_type()) + { + GValue *new_dict; + new_dict = ghb_dict_value_new(); + ghb_settings_take_value(dest, key, new_dict); + if (G_VALUE_TYPE(val) == ghb_dict_get_type()) + init_settings_from_dict(new_dict, gval, val); + else + init_settings_from_dict(new_dict, gval, gval); + } + else if (G_VALUE_TYPE(gval) == ghb_array_get_type()) + { + GValue *new_array; + new_array = ghb_array_value_new(8); + ghb_settings_take_value(dest, key, new_array); + if (G_VALUE_TYPE(val) == ghb_array_get_type()) + init_settings_from_array(new_array, gval, val); + else + init_settings_from_array(new_array, gval, gval); + + } + else + { + ghb_settings_set_value(dest, key, val); + } + } +} + +void +init_ui_from_dict( + signal_user_data_t *ud, + GValue *internal, + GValue *dict) +{ + GHashTableIter iter; + gchar *key; + GValue *gval, *val; + + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + val = NULL; + if (dict) + val = ghb_dict_lookup(dict, key); + if (val == NULL) + val = gval; + ghb_ui_update(ud, key, val); + } +} + +static void +preset_to_ui(signal_user_data_t *ud, GValue *dict) +{ + g_debug("preset_to_ui()\n"); + // Initialize the ui from presets file. + GValue *internal; + + // Get key list from internal default presets. This way we do not + // load any unknown keys. + if (internalPlist == NULL) return; + internal = plist_get_dict(internalPlist, "Presets"); + // Setting a ui widget will cause the corresponding setting + // to be set, but it also triggers a callback that can + // have the side effect of using other settings values + // that have not yet been set. So set *all* settings first + // then update the ui. + init_settings_from_dict(ud->settings, internal, dict); + init_ui_from_dict(ud, internal, dict); + + if (ghb_settings_get_boolean(ud->settings, "allow_tweaks")) + { + const GValue *gval; + gval = preset_dict_get_value(dict, "deinterlace"); + if (gval) + { + ghb_ui_update(ud, "tweak_deinterlace", gval); + } + gval = preset_dict_get_value(dict, "denoise"); + if (gval) + { + ghb_ui_update(ud, "tweak_denoise", gval); + } + } +} + +void +ghb_set_preset(signal_user_data_t *ud, const gchar *name) +{ + GValue *dict; + + g_debug("ghb_set_preset() %s\n", name); + if (name == NULL) + { + GList *presets; + // Try to get the first preset + presets = ghb_presets_get_names(); + if (presets) + { + name = (const gchar*)presets->data; + g_list_free(presets); + } + } + dict = plist_get_dict(presetsPlist, name); + if (dict == NULL || name == NULL) + { + preset_to_ui(ud, NULL); + } + else + { + preset_to_ui(ud, dict); + ghb_settings_set_string(ud->settings, "preset", name); + } +} + +void +ghb_update_from_preset( + signal_user_data_t *ud, + const gchar *name, + const gchar *key) +{ + const GValue *gval; + + g_debug("ghb_update_from_preset() %s %s", name, key); + if (name == NULL) return; + gval = preset_get_value(name, key); + if (gval != NULL) + { + ghb_ui_update(ud, key, gval); + } +} + +static void +store_plist(GValue *plist, const gchar *name) +{ + const gchar *dir; + gchar *config; + FILE *file; + + dir = g_get_user_config_dir(); + config = g_strdup_printf ("%s/ghb", dir); + if (!g_file_test(config, G_FILE_TEST_IS_DIR)) + { + g_mkdir (config, 0755); + } + g_free(config); + config = g_strdup_printf ("%s/ghb/%s", dir, name); + file = g_fopen(config, "w"); + g_free(config); + ghb_plist_write(file, plist); + fclose(file); +} + +static gboolean prefs_initializing = FALSE; + +void +ghb_prefs_to_ui(signal_user_data_t *ud) +{ + const GValue *gval; + gchar *key; + gchar *str; + GValue *internal, *dict; + GHashTableIter iter; + + + prefs_initializing = TRUE; + + // Setting a ui widget will cause the corresponding setting + // to be set, but it also triggers a callback that can + // have the side effect of using other settings values + // that have not yet been set. So set *all* settings first + // then update the ui. + internal = plist_get_dict(internalPlist, "Initialization"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + ghb_ui_update(ud, key, gval); + } + + dict = plist_get_dict(prefsPlist, "Preferences"); + internal = plist_get_dict(internalPlist, "Preferences"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + const GValue *value = NULL; + if (dict) + value = ghb_dict_lookup(dict, key); + if (value == NULL) + value = gval; + ghb_settings_set_value(ud->settings, key, value); + } + internal = plist_get_dict(internalPlist, "Preferences"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + const GValue *value = NULL; + if (dict) + value = ghb_dict_lookup(dict, key); + if (value == NULL) + value = gval; + ghb_ui_update(ud, key, value); + } + const GValue *val; + val = ghb_settings_get_value(ud->settings, "show_presets"); + ghb_ui_update(ud, "show_presets", val); + if (ghb_settings_get_boolean(ud->settings, "hbfd_feature")) + { + GtkAction *action; + val = ghb_settings_get_value(ud->settings, "hbfd"); + ghb_ui_update(ud, "hbfd", val); + action = GHB_ACTION (ud->builder, "hbfd"); + gtk_action_set_visible(action, TRUE); + } + else + { + ghb_ui_update(ud, "hbfd", ghb_int64_value(0)); + } + gval = ghb_settings_get_value(ud->settings, "default_source"); + ghb_settings_set_value (ud->settings, "source", gval); + str = ghb_settings_get_string(ud->settings, "destination_dir"); + + gchar *path = g_strdup_printf ("%s/new_video.mp4", str); + ghb_ui_update(ud, "destination", ghb_string_value(path)); + g_free(str); + g_free(path); + + prefs_initializing = FALSE; +} + +void +ghb_prefs_save(GValue *settings) +{ + GValue *dict; + GValue *pref_dict; + GHashTableIter iter; + gchar *key; + const GValue *value; + + if (prefs_initializing) return; + dict = plist_get_dict(internalPlist, "Preferences"); + if (dict == NULL) return; + pref_dict = plist_get_dict(prefsPlist, "Preferences"); + if (pref_dict == NULL) return; + ghb_dict_iter_init(&iter, dict); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) + { + value = ghb_settings_get_value(settings, key); + if (value != NULL) + { + ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value)); + } + } + store_plist(prefsPlist, "preferences"); +} + +void +ghb_pref_save(GValue *settings, const gchar *key) +{ + const GValue *value; + + if (prefs_initializing) return; + value = ghb_settings_get_value(settings, key); + if (value != NULL) + { + GValue *dict; + dict = plist_get_dict(prefsPlist, "Preferences"); + if (dict == NULL) return; + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value)); + store_plist(prefsPlist, "preferences"); + } +} + +void +ghb_settings_init(signal_user_data_t *ud) +{ + GValue *internal; + GHashTableIter iter; + gchar *key; + GValue *gval; + + + g_debug("ghb_settings_init"); + prefs_initializing = TRUE; + + internalPlist = ghb_plist_parse(defaultSettings, sizeof(defaultSettings)-1); + // Setting a ui widget will cause the corresponding setting + // to be set, but it also triggers a callback that can + // have the side effect of using other settings values + // that have not yet been set. So set *all* settings first + // then update the ui. + internal = plist_get_dict(internalPlist, "Initialization"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + ghb_settings_set_value(ud->settings, key, gval); + } + + internal = plist_get_dict(internalPlist, "Presets"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + ghb_settings_set_value(ud->settings, key, gval); + } + + internal = plist_get_dict(internalPlist, "Preferences"); + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + ghb_settings_set_value(ud->settings, key, gval); + } + prefs_initializing = FALSE; +} + +void +ghb_prefs_load(signal_user_data_t *ud) +{ + const gchar *dir; + gchar *config; + GValue *dict, *internal; + GHashTableIter iter; + gchar *key; + GValue *gval; + + g_debug("ghb_prefs_load"); + dir = g_get_user_config_dir(); + config = g_strdup_printf ("%s/ghb/preferences", dir); + if (g_file_test(config, G_FILE_TEST_IS_REGULAR)) + { + prefsPlist = ghb_plist_parse_file(config); + if (prefsPlist == NULL) + prefsPlist = ghb_dict_value_new(); + } + else + { + // Make an empty plist + prefsPlist = ghb_dict_value_new(); + } + g_free(config); + dict = plist_get_dict(prefsPlist, "Preferences"); + internal = plist_get_dict(internalPlist, "Preferences"); + if (dict == NULL && internal) + { + dict = ghb_dict_value_new(); + ghb_dict_insert(prefsPlist, g_strdup("Preferences"), dict); + + // Get defaults from internal defaults + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&gval)) + { + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval)); + } + const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); + ghb_dict_insert(dict, + g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir))); + store_plist(prefsPlist, "preferences"); + } + +} + +void +ghb_presets_reload(signal_user_data_t *ud) +{ + GValue *std_dict, *dict; + GHashTableIter std_iter; + + g_debug("ghb_presets_reload()\n"); + std_dict = ghb_plist_parse(standardPresets, sizeof(standardPresets)-1); + if (std_dict == NULL) return; + + // Merge the keyfile contents into our presets + gchar *name; + GValue *orig_dict; + + ghb_dict_iter_init(&std_iter, std_dict); + while (g_hash_table_iter_next(&std_iter, (gpointer*)&name, (gpointer*)&orig_dict)) + { + GHashTableIter iter; + gchar *key; + GValue *value; + + dict = ghb_dict_value_new(); + ghb_dict_insert(presetsPlist, g_strdup(name), dict); + ghb_dict_iter_init(&iter, orig_dict); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) + { + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value)); + } + } + ghb_value_free(std_dict); + store_plist(presetsPlist, "presets"); +} + +static void +presets_store() +{ + g_debug("presets_store ()\n"); + store_plist(presetsPlist, "presets"); +} + +void +ghb_presets_load() +{ + const gchar *dir; + gchar *config; + + dir = g_get_user_config_dir(); + config = g_strdup_printf ("%s/ghb/presets", dir); + if (g_file_test(config, G_FILE_TEST_IS_REGULAR)) + { + presetsPlist = ghb_plist_parse_file(config); + if (presetsPlist == NULL) + { + presetsPlist = ghb_plist_parse( + standardPresets, sizeof(standardPresets)-1); + presets_store(); + } + } + else + { + presetsPlist = ghb_plist_parse( + standardPresets, sizeof(standardPresets)-1); + } + g_free(config); +} + +void +ghb_settings_save(signal_user_data_t *ud, const gchar *name) +{ + GValue *dict, *internal; + GHashTableIter iter; + gchar *key; + GValue *value; + gboolean autoscale; + + if (internalPlist == NULL) return; + if (ghb_settings_get_boolean(ud->settings, "allow_tweaks")) + { + gchar *str; + str = ghb_settings_get_string(ud->settings, "tweak_deinterlace"); + if (str) + { + ghb_settings_set_string(ud->settings, "deinterlace", str); + g_free(str); + } + str = ghb_settings_get_string(ud->settings, "tweak_denoise"); + if (str) + { + ghb_settings_set_string(ud->settings, "denoise", str); + g_free(str); + } + } + autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); + ghb_settings_set_int64(ud->settings, "preset_type", 1); + + dict = ghb_dict_value_new(); + ghb_dict_insert(presetsPlist, g_strdup(name), dict); + internal = plist_get_dict(internalPlist, "Presets"); + + ghb_dict_iter_init(&iter, internal); + while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&value)) + { + if (!autoscale) + { + if (strcmp(key, "scale_width")) + { + key = "max_width"; + } + if (strcmp(key, "scale_height")) + { + key = "max_height"; + } + } + const GValue *gval; + gval = ghb_settings_get_value(ud->settings, key); + if (gval == NULL) + { + g_debug("Setting (%s) is not in defaults\n", (gchar*)key); + continue; + } + if (ghb_value_cmp(gval, value) != 0) + { + // Differs from default value. Store it. + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval)); + } + } + presets_store(); + ud->dont_clear_presets = TRUE; + ghb_set_preset (ud, name); + ud->dont_clear_presets = FALSE; +} + +void +ghb_presets_remove(const gchar *name) +{ + if (ghb_dict_lookup(presetsPlist, name)) + { + ghb_dict_remove(presetsPlist, name); + presets_store(); + } +} + |