1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
6 * presets.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
15 #include <glib-object.h>
16 #include <glib/gstdio.h>
21 #include "resources.h"
25 static GValue *presetsPlist = NULL;
26 static GValue *internalPlist = NULL;
27 static GValue *prefsPlist = NULL;
30 plist_get_dict(GValue *presets, const gchar *name)
32 if (presets == NULL || name == NULL) return NULL;
33 return ghb_dict_lookup(presets, name);
37 ghb_set_preset_default(GValue *settings)
41 preset = ghb_settings_get_string (settings, "preset");
42 ghb_settings_set_string(settings, "default_preset", preset);
43 ghb_prefs_save(settings);
47 // Used for sorting dictionaries.
49 key_cmp(gconstpointer a, gconstpointer b)
51 gchar *stra = (gchar*)a;
52 gchar *strb = (gchar*)b;
54 return strcmp(stra, strb);
58 ghb_presets_get_description(const gchar *name)
61 pdict = plist_get_dict(presetsPlist, name);
62 if (pdict == NULL) return g_strdup("");
63 return ghb_value_string(ghb_dict_lookup(pdict, "preset_description"));
67 preset_dict_get_value(
71 const GValue *gval = NULL;
75 gval = ghb_dict_lookup(dict, key);
77 if (internalPlist == NULL) return NULL;
80 dict = plist_get_dict(internalPlist, "Presets");
81 if (dict == NULL) return NULL;
82 gval = ghb_dict_lookup(dict, key);
94 dict = plist_get_dict(presetsPlist, name);
95 return preset_dict_get_value(dict, key);
99 ghb_presets_get_names()
103 GList *standard = NULL;
104 GList *custom = NULL;
106 if (presetsPlist == NULL) return NULL;
107 dict = g_value_get_boxed(presetsPlist);
108 link = names = g_hash_table_get_keys(dict);
114 name = (gchar*)link->data;
115 ptype = ghb_value_int(preset_get_value(name, "preset_type"));
117 custom = g_list_append(custom, name);
119 standard = g_list_append(standard, name);
122 custom = g_list_sort(custom, key_cmp);
123 standard = g_list_sort(standard, key_cmp);
125 names = g_list_concat(standard, custom);
130 ghb_preset_flags(const gchar *name)
137 dict = plist_get_dict(presetsPlist, name);
138 gval = preset_dict_get_value(dict, "preset_type");
141 ptype = ghb_value_int(gval);
142 ret = (ptype != 0 ? PRESET_CUSTOM : 0);
147 static void init_settings_from_dict(
148 GValue *dest, GValue *internal, GValue *dict);
151 init_settings_from_array(
159 count = ghb_array_len(array);
160 // The first element of the internal version is always the
161 // template for the allowed values
162 gval = ghb_array_get_nth(internal, 0);
163 for (ii = 0; ii < count; ii++)
166 val = ghb_array_get_nth(array, ii);
169 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
172 new_dict = ghb_dict_value_new();
173 ghb_array_append(dest, new_dict);
174 if (G_VALUE_TYPE(val) == ghb_dict_get_type())
175 init_settings_from_dict(new_dict, gval, val);
177 init_settings_from_dict(new_dict, gval, gval);
179 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
182 new_array = ghb_array_value_new(8);
183 ghb_array_append(dest, new_array);
184 if (G_VALUE_TYPE(val) == ghb_array_get_type())
185 init_settings_from_array(new_array, gval, val);
187 init_settings_from_array(new_array, gval, gval);
191 ghb_array_append(dest, val);
197 init_settings_from_dict(
206 ghb_dict_iter_init(&iter, internal);
207 // middle (void*) cast prevents gcc warning "defreferencing type-punned
208 // pointer will break strict-aliasing rules"
209 while (g_hash_table_iter_next(
210 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
214 val = ghb_dict_lookup(dict, key);
217 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
220 new_dict = ghb_dict_value_new();
221 ghb_settings_take_value(dest, key, new_dict);
222 if (G_VALUE_TYPE(val) == ghb_dict_get_type())
223 init_settings_from_dict(new_dict, gval, val);
225 init_settings_from_dict(new_dict, gval, gval);
227 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
230 new_array = ghb_array_value_new(8);
231 ghb_settings_take_value(dest, key, new_array);
232 if (G_VALUE_TYPE(val) == ghb_array_get_type())
233 init_settings_from_array(new_array, gval, val);
235 init_settings_from_array(new_array, gval, gval);
240 ghb_settings_set_value(dest, key, val);
247 signal_user_data_t *ud,
255 ghb_dict_iter_init(&iter, internal);
256 // middle (void*) cast prevents gcc warning "defreferencing type-punned
257 // pointer will break strict-aliasing rules"
258 while (g_hash_table_iter_next(
259 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
263 val = ghb_dict_lookup(dict, key);
266 ghb_ui_update(ud, key, val);
271 preset_to_ui(signal_user_data_t *ud, GValue *dict)
273 g_debug("preset_to_ui()\n");
274 // Initialize the ui from presets file.
277 // Get key list from internal default presets. This way we do not
278 // load any unknown keys.
279 if (internalPlist == NULL) return;
280 internal = plist_get_dict(internalPlist, "Presets");
281 // Setting a ui widget will cause the corresponding setting
282 // to be set, but it also triggers a callback that can
283 // have the side effect of using other settings values
284 // that have not yet been set. So set *all* settings first
285 // then update the ui.
286 init_settings_from_dict(ud->settings, internal, dict);
287 init_ui_from_dict(ud, internal, dict);
289 if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
292 gval = preset_dict_get_value(dict, "deinterlace");
295 ghb_ui_update(ud, "tweak_deinterlace", gval);
297 gval = preset_dict_get_value(dict, "denoise");
300 ghb_ui_update(ud, "tweak_denoise", gval);
306 ghb_set_preset(signal_user_data_t *ud, const gchar *name)
310 g_debug("ghb_set_preset() %s\n", name);
314 // Try to get the first preset
315 presets = ghb_presets_get_names();
318 name = (const gchar*)presets->data;
319 g_list_free(presets);
322 dict = plist_get_dict(presetsPlist, name);
323 if (dict == NULL || name == NULL)
325 preset_to_ui(ud, NULL);
329 preset_to_ui(ud, dict);
330 ghb_settings_set_string(ud->settings, "preset", name);
335 ghb_update_from_preset(
336 signal_user_data_t *ud,
342 g_debug("ghb_update_from_preset() %s %s", name, key);
343 if (name == NULL) return;
344 gval = preset_get_value(name, key);
347 ghb_ui_update(ud, key, gval);
352 ghb_get_user_config_dir()
357 dir = g_get_user_config_dir();
358 if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
360 dir = g_get_home_dir();
361 config = g_strdup_printf ("%s/.ghb", dir);
362 if (!g_file_test(config, G_FILE_TEST_IS_DIR))
363 g_mkdir (config, 0755);
367 config = g_strdup_printf ("%s/ghb", dir);
368 if (!g_file_test(config, G_FILE_TEST_IS_DIR))
369 g_mkdir (config, 0755);
375 store_plist(GValue *plist, const gchar *name)
377 gchar *config, *path;
380 config = ghb_get_user_config_dir();
381 path = g_strdup_printf ("%s/%s", config, name);
382 file = g_fopen(path, "w");
385 ghb_plist_write(file, plist);
390 load_plist(const gchar *name)
392 gchar *config, *path;
393 GValue *plist = NULL;
395 config = ghb_get_user_config_dir();
396 path = g_strdup_printf ("%s/%s", config, name);
397 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
399 plist = ghb_plist_parse_file(path);
407 remove_plist(const gchar *name)
409 gchar *config, *path;
411 config = ghb_get_user_config_dir();
412 path = g_strdup_printf ("%s/%s", config, name);
413 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
421 static gboolean prefs_initializing = FALSE;
424 ghb_prefs_to_ui(signal_user_data_t *ud)
429 GValue *internal, *dict;
433 prefs_initializing = TRUE;
435 // Setting a ui widget will cause the corresponding setting
436 // to be set, but it also triggers a callback that can
437 // have the side effect of using other settings values
438 // that have not yet been set. So set *all* settings first
439 // then update the ui.
440 internal = plist_get_dict(internalPlist, "Initialization");
441 ghb_dict_iter_init(&iter, internal);
442 // middle (void*) cast prevents gcc warning "defreferencing type-punned
443 // pointer will break strict-aliasing rules"
444 while (g_hash_table_iter_next(
445 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
447 ghb_ui_update(ud, key, gval);
450 dict = plist_get_dict(prefsPlist, "Preferences");
451 internal = plist_get_dict(internalPlist, "Preferences");
452 ghb_dict_iter_init(&iter, internal);
453 // middle (void*) cast prevents gcc warning "defreferencing type-punned
454 // pointer will break strict-aliasing rules"
455 while (g_hash_table_iter_next(
456 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
458 const GValue *value = NULL;
460 value = ghb_dict_lookup(dict, key);
463 ghb_settings_set_value(ud->settings, key, value);
465 internal = plist_get_dict(internalPlist, "Preferences");
466 ghb_dict_iter_init(&iter, internal);
467 // middle (void*) cast prevents gcc warning "defreferencing type-punned
468 // pointer will break strict-aliasing rules"
469 while (g_hash_table_iter_next(
470 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
472 const GValue *value = NULL;
474 value = ghb_dict_lookup(dict, key);
477 ghb_ui_update(ud, key, value);
480 val = ghb_settings_get_value(ud->settings, "show_presets");
481 ghb_ui_update(ud, "show_presets", val);
482 if (ghb_settings_get_boolean(ud->settings, "hbfd_feature"))
485 val = ghb_settings_get_value(ud->settings, "hbfd");
486 ghb_ui_update(ud, "hbfd", val);
487 action = GHB_ACTION (ud->builder, "hbfd");
488 gtk_action_set_visible(action, TRUE);
492 ghb_ui_update(ud, "hbfd", ghb_int64_value(0));
494 gval = ghb_settings_get_value(ud->settings, "default_source");
495 ghb_settings_set_value (ud->settings, "source", gval);
496 str = ghb_settings_get_string(ud->settings, "destination_dir");
498 gchar *path = g_strdup_printf ("%s/new_video.mp4", str);
499 ghb_ui_update(ud, "destination", ghb_string_value(path));
503 prefs_initializing = FALSE;
507 ghb_prefs_save(GValue *settings)
515 if (prefs_initializing) return;
516 dict = plist_get_dict(internalPlist, "Preferences");
517 if (dict == NULL) return;
518 pref_dict = plist_get_dict(prefsPlist, "Preferences");
519 if (pref_dict == NULL) return;
520 ghb_dict_iter_init(&iter, dict);
521 // middle (void*) cast prevents gcc warning "defreferencing type-punned
522 // pointer will break strict-aliasing rules"
523 while (g_hash_table_iter_next(
524 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
526 value = ghb_settings_get_value(settings, key);
529 ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value));
532 store_plist(prefsPlist, "preferences");
536 ghb_pref_save(GValue *settings, const gchar *key)
540 if (prefs_initializing) return;
541 value = ghb_settings_get_value(settings, key);
545 dict = plist_get_dict(prefsPlist, "Preferences");
546 if (dict == NULL) return;
547 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
548 store_plist(prefsPlist, "preferences");
553 ghb_settings_init(signal_user_data_t *ud)
561 g_debug("ghb_settings_init");
562 prefs_initializing = TRUE;
564 internalPlist = ghb_resource_get("internal-defaults");
565 // Setting a ui widget will cause the corresponding setting
566 // to be set, but it also triggers a callback that can
567 // have the side effect of using other settings values
568 // that have not yet been set. So set *all* settings first
569 // then update the ui.
570 internal = plist_get_dict(internalPlist, "Initialization");
571 ghb_dict_iter_init(&iter, internal);
572 // middle (void*) cast prevents gcc warning "defreferencing type-punned
573 // pointer will break strict-aliasing rules"
574 while (g_hash_table_iter_next(
575 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
577 ghb_settings_set_value(ud->settings, key, gval);
580 internal = plist_get_dict(internalPlist, "Presets");
581 ghb_dict_iter_init(&iter, internal);
582 // middle (void*) cast prevents gcc warning "defreferencing type-punned
583 // pointer will break strict-aliasing rules"
584 while (g_hash_table_iter_next(
585 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
587 ghb_settings_set_value(ud->settings, key, gval);
590 internal = plist_get_dict(internalPlist, "Preferences");
591 ghb_dict_iter_init(&iter, internal);
592 // middle (void*) cast prevents gcc warning "defreferencing type-punned
593 // pointer will break strict-aliasing rules"
594 while (g_hash_table_iter_next(
595 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
597 ghb_settings_set_value(ud->settings, key, gval);
599 prefs_initializing = FALSE;
606 //ghb_value_free(internalPlist);
608 ghb_value_free(presetsPlist);
610 ghb_value_free(prefsPlist);
614 ghb_prefs_load(signal_user_data_t *ud)
616 GValue *dict, *internal;
621 g_debug("ghb_prefs_load");
622 prefsPlist = load_plist("preferences");
623 if (prefsPlist == NULL)
624 prefsPlist = ghb_dict_value_new();
625 dict = plist_get_dict(prefsPlist, "Preferences");
626 internal = plist_get_dict(internalPlist, "Preferences");
627 if (dict == NULL && internal)
629 dict = ghb_dict_value_new();
630 ghb_dict_insert(prefsPlist, g_strdup("Preferences"), dict);
632 // Get defaults from internal defaults
633 ghb_dict_iter_init(&iter, internal);
634 // middle (void*) cast prevents gcc warning "defreferencing type-punned
635 // pointer will break strict-aliasing rules"
636 while (g_hash_table_iter_next(
637 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
639 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
641 const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
646 ghb_dict_insert(dict,
647 g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir)));
648 store_plist(prefsPlist, "preferences");
653 ghb_presets_reload(signal_user_data_t *ud)
655 GValue *std_dict, *dict;
656 GHashTableIter std_iter;
658 g_debug("ghb_presets_reload()\n");
659 std_dict = ghb_resource_get("standard-presets");
660 if (std_dict == NULL) return;
662 // Merge the keyfile contents into our presets
666 ghb_dict_iter_init(&std_iter, std_dict);
667 // middle (void*) cast prevents gcc warning "defreferencing type-punned
668 // pointer will break strict-aliasing rules"
669 while (g_hash_table_iter_next(
670 &std_iter, (gpointer*)(void*)&name, (gpointer*)(void*)&orig_dict))
676 dict = ghb_dict_value_new();
677 ghb_dict_insert(presetsPlist, g_strdup(name), dict);
678 ghb_dict_iter_init(&iter, orig_dict);
679 // middle (void*) cast prevents gcc warning "defreferencing type-punned
680 // pointer will break strict-aliasing rules"
681 while (g_hash_table_iter_next(
682 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
684 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
687 store_plist(presetsPlist, "presets");
693 g_debug("presets_store ()\n");
694 store_plist(presetsPlist, "presets");
698 ghb_save_queue(GValue *queue)
700 store_plist(queue, "queue");
706 return load_plist("queue");
710 ghb_remove_queue_file()
712 remove_plist("queue");
718 presetsPlist = load_plist("presets");
719 if (presetsPlist == NULL)
721 presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets"));
727 ghb_settings_save(signal_user_data_t *ud, const gchar *name)
729 GValue *dict, *internal;
735 if (internalPlist == NULL) return;
736 if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
739 str = ghb_settings_get_string(ud->settings, "tweak_deinterlace");
742 ghb_settings_set_string(ud->settings, "deinterlace", str);
745 str = ghb_settings_get_string(ud->settings, "tweak_denoise");
748 ghb_settings_set_string(ud->settings, "denoise", str);
752 autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
753 ghb_settings_set_int64(ud->settings, "preset_type", 1);
755 dict = ghb_dict_value_new();
756 ghb_dict_insert(presetsPlist, g_strdup(name), dict);
757 internal = plist_get_dict(internalPlist, "Presets");
759 ghb_dict_iter_init(&iter, internal);
760 // middle (void*) cast prevents gcc warning "defreferencing type-punned
761 // pointer will break strict-aliasing rules"
762 while (g_hash_table_iter_next(
763 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
771 if (strcmp(key, "max_width") == 0)
773 key2 = "scale_width";
775 else if (strcmp(key, "max_height") == 0)
777 key2 = "scale_height";
780 gval = ghb_settings_get_value(ud->settings, key2);
783 g_debug("Setting (%s) is not in defaults\n", (gchar*)key);
786 if (ghb_value_cmp(gval, value) != 0)
788 // Differs from default value. Store it.
789 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
793 ud->dont_clear_presets = TRUE;
794 ghb_set_preset (ud, name);
795 ud->dont_clear_presets = FALSE;
799 ghb_presets_remove(const gchar *name)
801 if (ghb_dict_lookup(presetsPlist, name))
803 ghb_dict_remove(presetsPlist, name);