summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/audiohandler.c8
-rw-r--r--gtk/src/create_resources.c51
-rw-r--r--gtk/src/plist.c7
-rw-r--r--gtk/src/presets.c115
-rw-r--r--gtk/src/presets.h2
-rw-r--r--gtk/src/queuehandler.c55
-rw-r--r--gtk/src/quotestring.py7
-rw-r--r--gtk/src/resources.c3
-rw-r--r--gtk/src/subtitlehandler.c8
-rw-r--r--gtk/src/values.c46
-rw-r--r--gtk/src/values.h7
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 <inc path>] <in resource list> <out resource plist>\n"
+"Usage: %s [-I <inc path>] <in resource list> <out resource dict>\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"
" <in resource list> Input resources file\n"
-" <out resource plist> Output resources plist file\n"
+" <out resource dict> 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 <string.h>
#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 <glib.h>
+#include <glib/gstdio.h>
#include <glib-object.h>
#include <stdio.h>
#include <string.h>
@@ -62,6 +63,20 @@ ghb_value_new(GhbType type)
}
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)
{
if (gval == NULL) return;
@@ -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_