From 01eabb2d314372bb301c3468d53840994105c652 Mon Sep 17 00:00:00 2001 From: jstebbins Date: Fri, 6 Mar 2015 22:17:34 +0000 Subject: LinGui: add methods for reading and writing json config files queue, preferences and app resources are now stored in json. presets are not yet stored as json, pending sync with other platforms git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6970 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- gtk/src/audiohandler.c | 8 ---- gtk/src/create_resources.c | 51 ++++++++++++++++---- gtk/src/plist.c | 7 ++- gtk/src/presets.c | 115 +++++++++++++++++++++++++++------------------ gtk/src/presets.h | 2 + gtk/src/queuehandler.c | 55 +++++++++------------- gtk/src/quotestring.py | 7 ++- gtk/src/resources.c | 3 +- gtk/src/subtitlehandler.c | 8 ---- gtk/src/values.c | 46 ++++++++++++++++++ gtk/src/values.h | 7 +++ 11 files changed, 192 insertions(+), 117 deletions(-) diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index 8f59f6d7c..50ec98eeb 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -1598,8 +1598,6 @@ audio_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) // treeview. Removing from the treeview sometimes provokes an // immediate selection change, so the list needs to be up to date // when this happens. - GhbValue *old = ghb_array_get_nth(audio_list, row); - ghb_value_free(old); ghb_array_remove(audio_list, row); // Remove the selected item @@ -2110,9 +2108,7 @@ audio_remove_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) // Remove from preset language list alang_list = ghb_settings_get_value(ud->settings, "AudioLanguageList"); - GhbValue *glang = ghb_array_get_nth(alang_list, index); ghb_array_remove(alang_list, index); - ghb_value_free(glang); ghb_clear_presets_selection(ud); } } @@ -2337,9 +2333,7 @@ audio_def_setting_remove_cb(GtkWidget *widget, signal_user_data_t *ud) return; } gtk_widget_destroy(GTK_WIDGET(row)); - GhbValue *asettings = ghb_array_get_nth(alist, index); ghb_array_remove(alist, index); - ghb_value_free(asettings); ghb_clear_presets_selection(ud); } @@ -2443,9 +2437,7 @@ audio_def_lang_list_init(signal_user_data_t *ud) { // Error in list. Probably duplicate languages. Remove // this item from the list. - GhbValue *glang = ghb_array_get_nth(lang_list, ii); ghb_array_remove(lang_list, ii); - ghb_value_free(glang); count--; } } diff --git a/gtk/src/create_resources.c b/gtk/src/create_resources.c index d9a5e7668..c21fb5626 100644 --- a/gtk/src/create_resources.c +++ b/gtk/src/create_resources.c @@ -17,6 +17,7 @@ enum R_SECTION, R_ICON, R_PLIST, + R_JSON, R_STRING, }; @@ -32,6 +33,7 @@ static tag_map_t tag_map[] = {"section", R_SECTION}, {"icon", R_ICON}, {"plist", R_PLIST}, + {"json", R_JSON}, {"string", R_STRING}, }; #define TAG_MAP_SZ (sizeof(tag_map)/sizeof(tag_map_t)) @@ -40,7 +42,7 @@ typedef struct { gchar *key; gchar *value; - GhbValue *plist; + GhbValue *dict; GQueue *stack; GQueue *tag_stack; gboolean closed_top; @@ -297,6 +299,35 @@ start_element( pd->key = g_strdup(key); g_free(fname); } break; + case R_JSON: + { + gchar *fname; + const gchar *name, *key; + + name = lookup_attr_value("file", attr_names, attr_values); + if (name == NULL) + { + g_warning("json: missing a requried *file* attribute"); + exit(EXIT_FAILURE); + } + fname = find_file(inc_list, name); + if (fname == NULL) + { + g_warning("json: no such file %s", name); + exit(EXIT_FAILURE); + } + key = lookup_attr_value("name", attr_names, attr_values); + if (key == NULL) + { + g_warning("json: missing a requried *name* attribute"); + g_free(fname); + exit(EXIT_FAILURE); + } + gval = ghb_json_parse_file(fname); + if (pd->key) g_free(pd->key); + pd->key = g_strdup(key); + g_free(fname); + } break; case R_STRING: { gchar *fname; @@ -357,7 +388,7 @@ start_element( { // There's an element to add if (current == NULL) { - pd->plist = gval; + pd->dict = gval; return; } insert_value(current, pd->key, gval); @@ -417,7 +448,7 @@ end_element( // or dict, add the current element if (current == NULL) { - pd->plist = gval; + pd->dict = gval; pd->closed_top = TRUE; return; } @@ -478,8 +509,8 @@ ghb_resource_parse(const gchar *buf, gssize len) pd.tag_stack = g_queue_new(); pd.key = NULL; pd.value = NULL; - pd.plist = ghb_dict_value_new(); - g_queue_push_head(pd.stack, pd.plist); + pd.dict = ghb_dict_value_new(); + g_queue_push_head(pd.stack, pd.dict); pd.closed_top = FALSE; parser.start_element = start_element; @@ -494,7 +525,7 @@ ghb_resource_parse(const gchar *buf, gssize len) g_markup_parse_context_free(ctx); g_queue_free(pd.stack); g_queue_free(pd.tag_stack); - return pd.plist; + return pd.dict; } GhbValue* @@ -521,13 +552,13 @@ static void usage(char *cmd) { fprintf(stderr, -"Usage: %s [-I ] \n" +"Usage: %s [-I ] \n" "Summary:\n" -" Creates a resource plist from a resource list\n" +" Creates a resource dict from a resource list\n" "Options:\n" " I - Include path to search for files\n" " Input resources file\n" -" Output resources plist file\n" +" Output resources dict file\n" , cmd); exit(EXIT_FAILURE); @@ -576,7 +607,7 @@ main(gint argc, gchar *argv[]) } gval = ghb_resource_parse_file(file); - ghb_plist_write_file(dst, gval); + ghb_json_write_file(dst, gval); fclose(file); return 0; } diff --git a/gtk/src/plist.c b/gtk/src/plist.c index a2429864f..51430cc5b 100644 --- a/gtk/src/plist.c +++ b/gtk/src/plist.c @@ -506,13 +506,12 @@ ghb_plist_write_file(const gchar *filename, GhbValue *gval) { FILE *file; - file = fopen(filename, "w"); + file = g_fopen(filename, "w"); if (file == NULL) return; - fprintf(file, "%s", preamble); - gval_write(file, gval); - fprintf(file, "%s", postfix); + ghb_plist_write(file, gval); + fclose(file); } diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 82199c0ec..acaf31dbb 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -48,7 +48,6 @@ static GhbValue *prefsPlist = NULL; static gboolean prefs_modified = FALSE; static const GhbValue* preset_dict_get_value(GhbValue *dict, const gchar *key); -static void store_plist(GhbValue *plist, const gchar *name); static void store_presets(void); static void store_prefs(void); @@ -322,15 +321,12 @@ ghb_preset_type(GhbValue *dict) static void presets_remove_nth(GhbValue *presets, gint pos) { - GhbValue *dict; gint count; if (presets == NULL || pos < 0) return; count = ghb_array_len(presets); if (pos >= count) return; - dict = ghb_array_get_nth(presets, pos); ghb_array_remove(presets, pos); - ghb_value_free(dict); } gboolean @@ -1170,35 +1166,66 @@ ghb_get_user_config_dir(gchar *subdir) } static void -store_plist(GhbValue *plist, const gchar *name) +write_config_file(const gchar *name, GhbValue *dict) { gchar *config, *path; - FILE *file; config = ghb_get_user_config_dir(NULL); path = g_strdup_printf ("%s/%s", config, name); - file = g_fopen(path, "w"); g_free(config); + ghb_json_write_file(path, dict); + g_free(path); +} + +void +ghb_write_settings_file(const gchar *path, GhbValue *dict) +{ + ghb_json_write_file(path, dict); +} + +static void +store_plist(const gchar *name, GhbValue *plist) +{ + gchar *config, *path; + + config = ghb_get_user_config_dir(NULL); + path = g_strdup_printf ("%s/%s", config, name); + g_free(config); + ghb_plist_write_file(path, plist); g_free(path); - ghb_plist_write(file, plist); - fclose(file); } static GhbValue* -load_plist(const gchar *name) +read_config_file(const gchar *name) { gchar *config, *path; - GhbValue *plist = NULL; + GhbValue *gval = NULL; config = ghb_get_user_config_dir(NULL); path = g_strdup_printf ("%s/%s", config, name); + g_free(config); if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { - plist = ghb_plist_parse_file(path); + gval = ghb_json_parse_file(path); + if (gval == NULL) + gval = ghb_plist_parse_file(path); } - g_free(config); g_free(path); - return plist; + return gval; +} + +GhbValue* +ghb_read_settings_file(const gchar *path) +{ + GhbValue *gval = NULL; + + if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) + { + gval = ghb_json_parse_file(path); + if (gval == NULL) + gval = ghb_plist_parse_file(path); + } + return gval; } gboolean @@ -1331,7 +1358,7 @@ ghb_find_pid_file() } static void -remove_plist(const gchar *name) +remove_config_file(const gchar *name) { gchar *config, *path; @@ -1495,7 +1522,7 @@ ghb_prefs_load(signal_user_data_t *ud) g_debug("ghb_prefs_load"); GhbValue *internalPlist = ghb_resource_get("internal-defaults"); - prefsPlist = load_plist("preferences"); + prefsPlist = read_config_file("preferences"); if (prefsPlist == NULL) prefsPlist = ghb_dict_value_new(); dict = plist_get_dict(prefsPlist, "Preferences"); @@ -1859,12 +1886,12 @@ void ghb_save_queue(GhbValue *queue) { pid_t pid; - char *path; + char *name; pid = getpid(); - path = g_strdup_printf ("queue.%d", pid); - store_plist(queue, path); - g_free(path); + name = g_strdup_printf ("queue.%d", pid); + write_config_file(name, queue); + g_free(name); } GhbValue* @@ -1872,12 +1899,12 @@ ghb_load_queue() { GhbValue *queue; pid_t pid; - char *path; + char *name; pid = getpid(); - path = g_strdup_printf ("queue.%d", pid); - queue = load_plist(path); - g_free(path); + name = g_strdup_printf ("queue.%d", pid); + queue = read_config_file(name); + g_free(name); return queue; } @@ -1885,34 +1912,34 @@ GhbValue* ghb_load_old_queue(int pid) { GhbValue *queue; - char *path; + char *name; - path = g_strdup_printf ("queue.%d", pid); - queue = load_plist(path); - g_free(path); + name = g_strdup_printf ("queue.%d", pid); + queue = read_config_file(name); + g_free(name); return queue; } void ghb_remove_old_queue_file(int pid) { - char *path; + char *name; - path = g_strdup_printf ("queue.%d", pid); - remove_plist(path); - g_free(path); + name = g_strdup_printf ("queue.%d", pid); + remove_config_file(name); + g_free(name); } void ghb_remove_queue_file() { pid_t pid; - char *path; + char *name; pid = getpid(); - path = g_strdup_printf ("queue.%d", pid); - remove_plist(path); - g_free(path); + name = g_strdup_printf ("queue.%d", pid); + remove_config_file(name); + g_free(name); } typedef struct @@ -2933,7 +2960,7 @@ static guint prefs_timeout_id = 0; static gboolean delayed_store_prefs(gpointer data) { - store_plist(prefsPlist, "preferences"); + write_config_file("preferences", prefsPlist); prefs_timeout_id = 0; return FALSE; } @@ -2945,7 +2972,7 @@ store_presets() export = ghb_value_dup(presetsPlist); export_xlat_presets(export); - store_plist(export, "presets"); + store_plist("presets", export); ghb_value_free(export); } @@ -3125,7 +3152,7 @@ void ghb_presets_load(signal_user_data_t *ud) { gboolean store = FALSE; - presetsPlistFile = load_plist("presets"); + presetsPlistFile = read_config_file("presets"); if ((presetsPlistFile == NULL) || (ghb_value_type(presetsPlistFile) == GHB_DICT) || (check_old_presets(presetsPlistFile))) @@ -3439,7 +3466,7 @@ preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) g_free(filename); return; } - array = ghb_plist_parse_file(filename); + array = ghb_read_settings_file(filename); import_xlat_presets(array); presets_clear_default(array); @@ -3576,7 +3603,6 @@ preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) if (response == GTK_RESPONSE_ACCEPT) { GhbValue *export, *dict, *array; - FILE *file; gchar *dir; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); @@ -3591,12 +3617,7 @@ preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) presets_customize(array); export_xlat_presets(array); - file = g_fopen(filename, "w"); - if (file != NULL) - { - ghb_plist_write(file, array); - fclose(file); - } + store_plist(filename, array); ghb_value_free(array); exportDir = ghb_settings_get_const_string(ud->prefs, "ExportDirectory"); diff --git a/gtk/src/presets.h b/gtk/src/presets.h index f3bbaf0cb..d9fe4e92f 100644 --- a/gtk/src/presets.h +++ b/gtk/src/presets.h @@ -53,5 +53,7 @@ GhbValue* ghb_get_current_preset_path(signal_user_data_t *ud); void ghb_preset_to_settings(GhbValue *settings, GhbValue *preset); void ghb_prefs_to_settings(GhbValue *settings); void dump_preset_path(const gchar *msg, const GhbValue *path); +GhbValue* ghb_read_settings_file(const gchar *path); +void ghb_write_settings_file(const gchar *path, GhbValue *dict); #endif // _GHB_PRESETS_H_ diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index c3457989e..20d973372 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -772,12 +772,7 @@ save_queue_file(signal_user_data_t *ud) char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog)); gtk_widget_destroy(dialog); - FILE *file = g_fopen(filename, "w"); - if (file != NULL) - { - ghb_plist_write(file, queue); - fclose(file); - } + ghb_write_settings_file(filename, queue); g_free (filename); ghb_value_free(queue); } @@ -821,29 +816,27 @@ open_queue_file(signal_user_data_t *ud) char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog)); gtk_widget_destroy(dialog); - if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + queue = ghb_read_settings_file(filename); + if (queue != NULL) { - queue = ghb_plist_parse_file(filename); - if (queue != NULL) + int ii, count; + count = ghb_array_len(queue); + for (ii = 0; ii < count; ii++) { - int ii, count; - count = ghb_array_len(queue); - for (ii = 0; ii < count; ii++) - { - GhbValue *settings = ghb_array_get_nth(queue, ii); - ghb_array_remove(queue, ii); - ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING); - ghb_settings_set_int(settings, "job_unique_id", 0); - - if (ud->queue == NULL) - ud->queue = ghb_array_value_new(32); - ghb_array_append(ud->queue, settings); - add_to_queue_list(ud, settings, NULL); - } - ghb_queue_buttons_grey(ud); - ghb_save_queue(ud->queue); - ghb_value_free(queue); + GhbValue *settings = ghb_array_get_nth(queue, ii); + ghb_value_incref(settings); + ghb_array_remove(queue, ii); + ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING); + ghb_settings_set_int(settings, "job_unique_id", 0); + + if (ud->queue == NULL) + ud->queue = ghb_array_value_new(32); + ghb_array_append(ud->queue, settings); + add_to_queue_list(ud, settings, NULL); } + ghb_queue_buttons_grey(ud); + ghb_save_queue(ud->queue); + ghb_value_free(queue); } g_free (filename); } @@ -1684,9 +1677,7 @@ queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) // Remove the selected item gtk_tree_store_remove(GTK_TREE_STORE(store), &iter); // Remove the corresponding item from the queue list - GhbValue *old = ghb_array_get_nth(ud->queue, row); ghb_array_remove(ud->queue, row); - ghb_value_free(old); ghb_save_queue(ud->queue); } else @@ -1893,6 +1884,7 @@ queue_drag_cb( indices = gtk_tree_path_get_indices(dstpath); row = indices[0]; gtk_tree_path_free(dstpath); + ghb_value_incref(js); ghb_array_insert(ud->queue, row, js); srcpath = gtk_tree_model_get_path (srcmodel, &srciter); @@ -2128,8 +2120,6 @@ find_pid: status = ghb_settings_get_int(settings, "job_status"); if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED) { - GhbValue *old = ghb_array_get_nth(queue, ii); - ghb_value_free(old); ghb_array_remove(queue, ii); } } @@ -2174,8 +2164,6 @@ ghb_queue_remove_row(signal_user_data_t *ud, int row) } g_free(path); - GhbValue *old = ghb_array_get_nth(ud->queue, row); - ghb_value_free(old); ghb_array_remove(ud->queue, row); ghb_save_queue(ud->queue); } @@ -2232,8 +2220,6 @@ queue_key_press_cb( // Remove the selected item gtk_tree_store_remove(GTK_TREE_STORE(store), &iter); // Remove the corresponding item from the queue list - GhbValue *old = ghb_array_get_nth(ud->queue, row); - ghb_value_free(old); ghb_array_remove(ud->queue, row); ghb_save_queue(ud->queue); return TRUE; @@ -2280,6 +2266,7 @@ queue_edit_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) // Remove the selected item gtk_tree_store_remove(GTK_TREE_STORE(store), &iter); // Remove the corresponding item from the queue list + ghb_value_incref(ghb_queue_edit_settings); ghb_array_remove(ud->queue, row); } else diff --git a/gtk/src/quotestring.py b/gtk/src/quotestring.py index 1c0c5b2d1..1038719e7 100644 --- a/gtk/src/quotestring.py +++ b/gtk/src/quotestring.py @@ -50,11 +50,10 @@ def main(): outfile = sys.stdout ss = infile.read() - ss = re.sub("\"", "\\\"", ss) + ss = re.sub(r'\\', r'\\\\', ss) + ss = re.sub(r'"', r'\\"', ss) pattern = re.compile("$", re.M) - # the replacement string below seems a bit strange, but it seems to be - # the only way to get the litteral chars '\' 'n' inserted into the string - ss = re.sub(pattern, "\\\\n\"", ss) + ss = re.sub(pattern, r'\\n"', ss) pattern = re.compile("^", re.M) ss = re.sub(pattern, "\"", ss) outfile.write(ss) diff --git a/gtk/src/resources.c b/gtk/src/resources.c index 7010202f1..420795dc7 100644 --- a/gtk/src/resources.c +++ b/gtk/src/resources.c @@ -17,7 +17,6 @@ #include #include "ghbcompat.h" #include "settings.h" -#include "plist.h" #include "resources.h" #include "values.h" @@ -30,7 +29,7 @@ static GhbValue *resources; void ghb_resource_init() { - resources = ghb_plist_parse(resource_str, sizeof(resource_str)-1); + resources = ghb_json_parse(resource_str, sizeof(resource_str)-1); } GhbValue* diff --git a/gtk/src/subtitlehandler.c b/gtk/src/subtitlehandler.c index 0b80cfe89..9b07203d6 100644 --- a/gtk/src/subtitlehandler.c +++ b/gtk/src/subtitlehandler.c @@ -1299,9 +1299,7 @@ ghb_subtitle_prune(signal_user_data_t *ud) burned = burned || !hb_subtitle_can_pass(source, mux->format); if (burned && one_burned) { - GhbValue *gsub = ghb_array_get_nth(subtitle_list, ii); ghb_array_remove(subtitle_list, ii); - ghb_value_free(gsub); continue; } one_burned = one_burned || burned; @@ -1479,9 +1477,7 @@ subtitle_remove_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) // Remove from preset language list lang_list = ghb_settings_get_value(ud->settings, "SubtitleLanguageList"); - GhbValue *glang = ghb_array_get_nth(lang_list, index); ghb_array_remove(lang_list, index); - ghb_value_free(glang); ghb_clear_presets_selection(ud); @@ -1564,9 +1560,7 @@ static void subtitle_def_lang_list_init(signal_user_data_t *ud) { // Error in list. Probably duplicate languages. Remove // this item from the list. - GhbValue *glang = ghb_array_get_nth(lang_list, ii); ghb_array_remove(lang_list, ii); - ghb_value_free(glang); count--; } } @@ -1683,9 +1677,7 @@ subtitle_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *u // treeview. Removing from the treeview sometimes provokes an // immediate selection change, so the list needs to be up to date // when this happens. - GhbValue *old = ghb_array_get_nth(subtitle_list, row); ghb_array_remove(subtitle_list, row); - ghb_value_free(old); // Remove the selected item gtk_tree_store_remove(GTK_TREE_STORE(tm), &ti); diff --git a/gtk/src/values.c b/gtk/src/values.c index c0bb1305b..749ce0bca 100644 --- a/gtk/src/values.c +++ b/gtk/src/values.c @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -61,6 +62,20 @@ ghb_value_new(GhbType type) return val; } +void +ghb_value_incref(GhbValue *gval) +{ + if (gval == NULL) return; + json_incref(gval); +} + +void +ghb_value_decref(GhbValue *gval) +{ + if (gval == NULL) return; + json_decref(gval); +} + void ghb_value_free(GhbValue *gval) { @@ -535,3 +550,34 @@ ghb_array_len(const GhbValue *array) { return json_array_size(array); } + +void +ghb_json_write(FILE *file, GhbValue *gval) +{ + char * json = json_dumps(gval, JSON_INDENT(4)|JSON_PRESERVE_ORDER); + fprintf(file, "%s", json); + free(json); +} + +void +ghb_json_write_file(const char *path, GhbValue *gval) +{ + FILE *file = g_fopen(path, "w"); + if (file == NULL) + return; + ghb_json_write(file, gval); + fclose(file); +} + +GhbValue* +ghb_json_parse(const char *json, size_t size) +{ + return json_loadb(json, size, JSON_REJECT_DUPLICATES, NULL); +} + +GhbValue* +ghb_json_parse_file(const char *path) +{ + return json_load_file(path, JSON_REJECT_DUPLICATES, NULL); +} + diff --git a/gtk/src/values.h b/gtk/src/values.h index ceb70687c..dd3a1dc04 100644 --- a/gtk/src/values.h +++ b/gtk/src/values.h @@ -32,6 +32,8 @@ typedef json_t GhbValue; typedef int GhbType; typedef void* GhbDictIter; +void ghb_value_incref(GhbValue *gval); +void ghb_value_decref(GhbValue *gval); GhbType ghb_value_type(const GhbValue *val); GhbType ghb_array_get_type(void); GhbType ghb_dict_get_type(void); @@ -81,4 +83,9 @@ gboolean ghb_dict_remove(GhbValue *gval, const gchar *key); void debug_show_value(GhbValue *gval); void debug_show_type(GhbType tp); +void ghb_json_write(FILE *file, GhbValue *gval); +void ghb_json_write_file(const char *path, GhbValue *gval); +GhbValue* ghb_json_parse(const char *json, size_t size); +GhbValue* ghb_json_parse_file(const char *path); + #endif // _GHB_VALUES_H_ -- cgit v1.2.3