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>
20 #include "callbacks.h"
21 #include "audiohandler.h"
22 #include "hb-backend.h"
24 #include "resources.h"
28 #define MAX_NESTED_PRESET 3
30 // These are flags. One bit for each feature
34 PRESETS_FOLDER = 0x02,
37 static GValue *presetsPlist = NULL;
38 static GValue *internalPlist = NULL;
39 static GValue *prefsPlist = NULL;
41 static const GValue* preset_dict_get_value(GValue *dict, const gchar *key);
42 static void store_plist(GValue *plist, const gchar *name);
44 // This only handle limited depth
46 ghb_tree_path_new_from_indices(gint *indices, gint len)
51 return gtk_tree_path_new_from_indices(
54 return gtk_tree_path_new_from_indices(
55 indices[0], indices[1], -1);
57 return gtk_tree_path_new_from_indices(
58 indices[0], indices[1], indices[2], -1);
60 return gtk_tree_path_new_from_indices(
61 indices[0], indices[1], indices[2], indices[3], -1);
63 return gtk_tree_path_new_from_indices(
64 indices[0], indices[1], indices[2], indices[3], indices[4], -1);
71 ghb_parse_preset_path(const gchar *path)
77 preset = ghb_array_value_new(MAX_NESTED_PRESET);
78 split = g_strsplit(path, "#", MAX_NESTED_PRESET);
79 for (ii = 0; split[ii] != NULL; ii++)
81 ghb_array_append(preset, ghb_string_value_new(split[ii]));
88 preset_path_from_indices(GValue *presets, gint *indices, gint len)
93 g_debug("preset_path_from_indices");
94 path = ghb_array_value_new(MAX_NESTED_PRESET);
95 for (ii = 0; ii < len; ii++)
101 count = ghb_array_len(presets);
102 if (indices[ii] >= count) break;
103 dict = ghb_array_get_nth(presets, indices[ii]);
104 name = ghb_dict_lookup(dict, "preset_name");
105 ghb_array_append(path, ghb_value_dup(name));
106 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
107 if (!(ptype & PRESETS_FOLDER))
109 presets = ghb_dict_lookup(dict, "preset_folder");
115 ghb_preset_path_string(const GValue *path)
122 gstr = g_string_new("");
125 count = ghb_array_len(path);
126 for (ii = 0; ii < count; ii++)
128 val = ghb_array_get_nth(path, ii);
129 str = ghb_value_string(val);
130 g_string_append(gstr, str);
132 g_string_append(gstr, "->");
136 str = g_string_free(gstr, FALSE);
141 debug_show_type(GType tp)
143 const gchar *str = "unknown";
144 if (tp == G_TYPE_STRING)
148 else if (tp == G_TYPE_INT)
152 else if (tp == G_TYPE_INT64)
156 else if (tp == G_TYPE_BOOLEAN)
160 else if (tp == ghb_array_get_type())
164 else if (tp == ghb_dict_get_type())
168 g_message("Type: %s", str);
172 dump_preset_path(const gchar *msg, const GValue *path)
177 debug_show_type (G_VALUE_TYPE(path));
178 str = ghb_preset_path_string(path);
179 g_message("%s path: (%s)", msg, str);
184 dump_preset_indices(const gchar *msg, gint *indices, gint len)
188 g_message("%s indices: len %d", msg, len);
189 for (ii = 0; ii < len; ii++)
191 printf("%d ", indices[ii]);
198 preset_path_cmp(const GValue *path1, const GValue *path2)
205 count = ghb_array_len(path1);
206 ii = ghb_array_len(path2);
209 for (ii = 0; ii < count; ii++)
211 val = ghb_array_get_nth(path1, ii);
212 str1 = ghb_value_string(val);
213 val = ghb_array_get_nth(path2, ii);
214 str2 = ghb_value_string(val);
215 result = strcmp(str1, str2);
226 presets_get_dict(GValue *presets, gint *indices, gint len)
228 gint ii, count, ptype;
231 g_debug("presets_get_dict ()");
232 for (ii = 0; ii < len; ii++)
234 count = ghb_array_len(presets);
235 if (indices[ii] >= count) return NULL;
236 dict = ghb_array_get_nth(presets, indices[ii]);
239 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
240 if (!(ptype & PRESETS_FOLDER))
242 presets = ghb_dict_lookup(dict, "preset_folder");
251 presets_get_folder(GValue *presets, gint *indices, gint len)
253 gint ii, count, ptype;
256 g_debug("presets_get_folder ()");
257 for (ii = 0; ii < len; ii++)
259 count = ghb_array_len(presets);
260 if (indices[ii] >= count) return NULL;
261 dict = ghb_array_get_nth(presets, indices[ii]);
262 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
263 if (!(ptype & PRESETS_FOLDER))
265 presets = ghb_dict_lookup(dict, "preset_folder");
273 plist_get_dict(GValue *presets, const gchar *name)
275 if (presets == NULL || name == NULL) return NULL;
276 return ghb_dict_lookup(presets, name);
280 preset_get_name(GValue *dict)
282 return g_value_get_string(ghb_dict_lookup(dict, "preset_name"));
286 ghb_preset_flags(GValue *dict)
291 gval = preset_dict_get_value(dict, "preset_type");
294 ptype = ghb_value_int(gval);
300 presets_remove_nth(GValue *presets, gint pos)
305 if (presets == NULL || pos < 0) return;
306 count = ghb_array_len(presets);
307 if (pos >= count) return;
308 dict = ghb_array_get_nth(presets, pos);
309 ghb_array_remove(presets, pos);
310 ghb_value_free(dict);
319 GValue *folder = NULL;
321 folder = presets_get_folder(presets, indices, len-1);
323 presets_remove_nth(folder, indices[len-1]);
326 g_warning("ghb_presets_remove ()");
327 g_warning("internal preset lookup error");
340 GValue *folder = NULL;
342 folder = presets_get_folder(presets, indices, len-1);
344 ghb_array_replace(folder, indices[len-1], dict);
347 g_warning("ghb_presets_replace ()");
348 g_warning("internal preset lookup error");
359 GValue *folder = NULL;
361 folder = presets_get_folder(presets, indices, len-1);
363 ghb_array_insert(folder, indices[len-1], dict);
366 g_warning("ghb_presets_insert ()");
367 g_warning("internal preset lookup error");
372 presets_find_element(GValue *presets, const gchar *name)
377 g_debug("presets_find_element () (%s)", name);
378 if (presets == NULL || name == NULL) return -1;
379 count = ghb_array_len(presets);
380 for (ii = 0; ii < count; ii++)
383 dict = ghb_array_get_nth(presets, ii);
384 str = preset_get_name(dict);
385 if (strcmp(name, str) == 0)
394 single_find_pos(GValue *presets, const gchar *name, gint type)
397 gint count, ii, ptype, last;
399 if (presets == NULL || name == NULL) return -1;
400 last = count = ghb_array_len(presets);
401 for (ii = 0; ii < count; ii++)
404 dict = ghb_array_get_nth(presets, ii);
405 str = preset_get_name(dict);
406 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
407 if (strcasecmp(name, str) <= 0 && ptype == type)
418 presets_find_pos(const GValue *path, gint type, gint *len)
422 gint count, ii, ptype;
423 gint *indices = NULL;
427 g_debug("presets_find_pos () ");
428 nested = presetsPlist;
429 count = ghb_array_len(path);
430 indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
431 for (ii = 0; ii < count-1; ii++)
433 val = ghb_array_get_nth(path, ii);
434 name = g_value_get_string(val);
435 indices[ii] = presets_find_element(nested, name);
436 if (indices[ii] == -1) return NULL;
437 dict = ghb_array_get_nth(nested, indices[ii]);
438 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
440 if (!(ptype & PRESETS_FOLDER))
442 nested = ghb_dict_lookup(dict, "preset_folder");
448 name = g_value_get_string(ghb_array_get_nth(path, count-1));
449 indices[ii] = single_find_pos(nested, name, type);
457 preset_tree_depth(GValue *dict)
461 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
462 if (ptype & PRESETS_FOLDER)
468 presets = ghb_dict_lookup(dict, "preset_folder");
469 count = ghb_array_len(presets);
470 for (ii = 0; ii < count; ii++)
474 dict = ghb_array_get_nth(presets, ii);
475 tmp = preset_tree_depth(dict);
476 depth = MAX(depth, tmp);
487 preset_is_default(GValue *dict)
491 val = preset_dict_get_value(dict, "Default");
492 return g_value_get_boolean(val);
496 presets_find_default2(GValue *presets, gint *len)
501 count = ghb_array_len(presets);
502 for (ii = 0; ii < count; ii++)
507 dict = ghb_array_get_nth(presets, ii);
508 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
509 if (ptype & PRESETS_FOLDER)
514 nested = ghb_dict_lookup(dict, "preset_folder");
516 indices = presets_find_default2(nested, len);
527 if (preset_is_default(dict))
529 indices = malloc(MAX_NESTED_PRESET * sizeof(gint));
540 presets_find_default(gint *len)
543 return presets_find_default2(presetsPlist, len);
547 ghb_preset_indices_from_path(
554 gint count, ii, ptype;
555 gint *indices = NULL;
559 g_debug("ghb_preset_indices_from_path () ");
561 count = ghb_array_len(path);
563 indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint));
565 for (ii = 0; ii < count; ii++)
567 val = ghb_array_get_nth(path, ii);
568 name = g_value_get_string(val);
569 indices[ii] = presets_find_element(nested, name);
570 if (indices[ii] == -1)
577 dict = ghb_array_get_nth(nested, indices[ii]);
578 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
579 if (!(ptype & PRESETS_FOLDER))
584 nested = ghb_dict_lookup(dict, "preset_folder");
592 ghb_presets_get_type(
600 dict = presets_get_dict(presets, indices, len);
603 flags = ghb_preset_flags(dict);
607 g_warning("ghb_presets_get_type ()");
608 g_warning("internal preset lookup error");
614 presets_set_default(gint *indices, gint len)
617 gint *curr_indices, curr_len;
619 g_debug("presets_set_default ()");
620 curr_indices = presets_find_default(&curr_len);
623 dict = presets_get_dict(presetsPlist, curr_indices, curr_len);
626 ghb_dict_insert(dict, g_strdup("Default"),
627 ghb_boolean_value_new(FALSE));
630 dict = presets_get_dict(presetsPlist, indices, len);
633 ghb_dict_insert(dict, g_strdup("Default"), ghb_boolean_value_new(TRUE));
635 store_plist(presetsPlist, "presets");
638 // Used for sorting dictionaries.
640 key_cmp(gconstpointer a, gconstpointer b)
642 gchar *stra = (gchar*)a;
643 gchar *strb = (gchar*)b;
645 return strcmp(stra, strb);
649 preset_dict_get_value(GValue *dict, const gchar *key)
651 const GValue *gval = NULL;
655 gval = ghb_dict_lookup(dict, key);
657 if (internalPlist == NULL) return NULL;
660 dict = plist_get_dict(internalPlist, "Presets");
661 if (dict == NULL) return NULL;
662 gval = ghb_dict_lookup(dict, key);
668 ghb_presets_get_description(GValue *pdict)
672 if (pdict == NULL) return NULL;
673 desc = g_value_get_string(
674 preset_dict_get_value(pdict, "preset_description"));
675 if (desc[0] == 0) return NULL;
681 preset_get_value(const GValue *preset, const gchar *key)
687 indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
690 dict = presets_get_dict(presetsPlist, indices, len);
693 return preset_dict_get_value(dict, key);
696 static void init_settings_from_dict(
697 GValue *dest, GValue *internal, GValue *dict);
700 init_settings_from_array(
708 count = ghb_array_len(array);
709 // The first element of the internal version is always the
710 // template for the allowed values
711 gval = ghb_array_get_nth(internal, 0);
712 for (ii = 0; ii < count; ii++)
715 val = ghb_array_get_nth(array, ii);
718 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
721 new_dict = ghb_dict_value_new();
722 ghb_array_append(dest, new_dict);
723 if (G_VALUE_TYPE(val) == ghb_dict_get_type())
724 init_settings_from_dict(new_dict, gval, val);
726 init_settings_from_dict(new_dict, gval, gval);
728 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
731 new_array = ghb_array_value_new(8);
732 ghb_array_append(dest, new_array);
733 if (G_VALUE_TYPE(val) == ghb_array_get_type())
734 init_settings_from_array(new_array, gval, val);
736 init_settings_from_array(new_array, gval, gval);
740 ghb_array_append(dest, val);
746 init_settings_from_dict(
755 ghb_dict_iter_init(&iter, internal);
756 // middle (void*) cast prevents gcc warning "defreferencing type-punned
757 // pointer will break strict-aliasing rules"
758 while (g_hash_table_iter_next(
759 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
763 val = ghb_dict_lookup(dict, key);
766 if (G_VALUE_TYPE(gval) == ghb_dict_get_type())
769 new_dict = ghb_dict_value_new();
770 ghb_settings_take_value(dest, key, new_dict);
771 if (G_VALUE_TYPE(val) == ghb_dict_get_type())
772 init_settings_from_dict(new_dict, gval, val);
774 init_settings_from_dict(new_dict, gval, gval);
776 else if (G_VALUE_TYPE(gval) == ghb_array_get_type())
779 new_array = ghb_array_value_new(8);
780 ghb_settings_take_value(dest, key, new_array);
781 if (G_VALUE_TYPE(val) == ghb_array_get_type())
782 init_settings_from_array(new_array, gval, val);
784 init_settings_from_array(new_array, gval, gval);
789 ghb_settings_set_value(dest, key, val);
796 signal_user_data_t *ud,
804 ghb_dict_iter_init(&iter, internal);
805 // middle (void*) cast prevents gcc warning "defreferencing type-punned
806 // pointer will break strict-aliasing rules"
807 while (g_hash_table_iter_next(
808 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
812 val = ghb_dict_lookup(dict, key);
815 ghb_ui_update(ud, key, val);
820 preset_to_ui(signal_user_data_t *ud, GValue *dict)
822 g_debug("preset_to_ui()\n");
823 // Initialize the ui from presets file.
826 // Get key list from internal default presets. This way we do not
827 // load any unknown keys.
828 if (internalPlist == NULL) return;
829 internal = plist_get_dict(internalPlist, "Presets");
830 // Setting a ui widget will cause the corresponding setting
831 // to be set, but it also triggers a callback that can
832 // have the side effect of using other settings values
833 // that have not yet been set. So set *all* settings first
834 // then update the ui.
835 init_settings_from_dict(ud->settings, internal, dict);
836 init_ui_from_dict(ud, internal, dict);
838 if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
841 gval = preset_dict_get_value(dict, "deinterlace");
844 ghb_ui_update(ud, "tweak_deinterlace", gval);
846 gval = preset_dict_get_value(dict, "denoise");
849 ghb_ui_update(ud, "tweak_denoise", gval);
855 ghb_settings_to_ui(signal_user_data_t *ud, GValue *dict)
857 init_ui_from_dict(ud, dict, dict);
861 ghb_set_preset_from_indices(signal_user_data_t *ud, gint *indices, gint len)
864 gint fallback[2] = {0, -1};
867 dict = presets_get_dict(presetsPlist, indices, len);
872 dict = presets_get_dict(presetsPlist, indices, len);
876 preset_to_ui(ud, NULL);
883 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
884 if (ptype & PRESETS_FOLDER)
885 preset_to_ui(ud, NULL);
887 preset_to_ui(ud, dict);
888 path = preset_path_from_indices(presetsPlist, indices, len);
889 ghb_settings_set_value(ud->settings, "preset", path);
890 ghb_value_free(path);
895 ghb_set_preset(signal_user_data_t *ud, const GValue *path)
899 g_debug("ghb_set_preset()");
900 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
901 ghb_set_preset_from_indices(ud, indices, len);
902 if (indices) g_free(indices);
906 ghb_update_from_preset(
907 signal_user_data_t *ud,
908 const GValue *preset,
913 g_debug("ghb_update_from_preset() %s", key);
914 if (preset == NULL) return;
915 gval = preset_get_value(preset, key);
918 ghb_ui_update(ud, key, gval);
923 ghb_get_user_config_dir()
928 dir = g_get_user_config_dir();
929 if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
931 dir = g_get_home_dir();
932 config = g_strdup_printf ("%s/.ghb", dir);
933 if (!g_file_test(config, G_FILE_TEST_IS_DIR))
934 g_mkdir (config, 0755);
938 config = g_strdup_printf ("%s/ghb", dir);
939 if (!g_file_test(config, G_FILE_TEST_IS_DIR))
940 g_mkdir (config, 0755);
946 store_plist(GValue *plist, const gchar *name)
948 gchar *config, *path;
951 config = ghb_get_user_config_dir();
952 path = g_strdup_printf ("%s/%s", config, name);
953 file = g_fopen(path, "w");
956 ghb_plist_write(file, plist);
961 load_plist(const gchar *name)
963 gchar *config, *path;
964 GValue *plist = NULL;
966 config = ghb_get_user_config_dir();
967 path = g_strdup_printf ("%s/%s", config, name);
968 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
970 plist = ghb_plist_parse_file(path);
978 remove_plist(const gchar *name)
980 gchar *config, *path;
982 config = ghb_get_user_config_dir();
983 path = g_strdup_printf ("%s/%s", config, name);
984 if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
992 static gboolean prefs_initializing = FALSE;
995 ghb_prefs_to_ui(signal_user_data_t *ud)
1000 GValue *internal, *dict;
1001 GHashTableIter iter;
1004 g_debug("ghb_prefs_to_ui");
1005 prefs_initializing = TRUE;
1007 // Setting a ui widget will cause the corresponding setting
1008 // to be set, but it also triggers a callback that can
1009 // have the side effect of using other settings values
1010 // that have not yet been set. So set *all* settings first
1011 // then update the ui.
1012 internal = plist_get_dict(internalPlist, "Initialization");
1013 ghb_dict_iter_init(&iter, internal);
1014 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1015 // pointer will break strict-aliasing rules"
1016 while (g_hash_table_iter_next(
1017 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1019 ghb_ui_update(ud, key, gval);
1022 dict = plist_get_dict(prefsPlist, "Preferences");
1023 internal = plist_get_dict(internalPlist, "Preferences");
1024 ghb_dict_iter_init(&iter, internal);
1025 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1026 // pointer will break strict-aliasing rules"
1027 while (g_hash_table_iter_next(
1028 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1030 const GValue *value = NULL;
1032 value = ghb_dict_lookup(dict, key);
1035 ghb_settings_set_value(ud->settings, key, value);
1037 internal = plist_get_dict(internalPlist, "Preferences");
1038 ghb_dict_iter_init(&iter, internal);
1039 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1040 // pointer will break strict-aliasing rules"
1041 while (g_hash_table_iter_next(
1042 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1044 const GValue *value = NULL;
1046 value = ghb_dict_lookup(dict, key);
1049 ghb_ui_update(ud, key, value);
1052 val = ghb_settings_get_value(ud->settings, "show_presets");
1053 ghb_ui_update(ud, "show_presets", val);
1054 if (ghb_settings_get_boolean(ud->settings, "hbfd_feature"))
1057 val = ghb_settings_get_value(ud->settings, "hbfd");
1058 ghb_ui_update(ud, "hbfd", val);
1059 action = GHB_ACTION (ud->builder, "hbfd");
1060 gtk_action_set_visible(action, TRUE);
1064 ghb_ui_update(ud, "hbfd", ghb_int64_value(0));
1066 gval = ghb_settings_get_value(ud->settings, "default_source");
1067 ghb_settings_set_value (ud->settings, "source", gval);
1068 str = ghb_settings_get_string(ud->settings, "destination_dir");
1070 gchar *path = g_strdup_printf ("%s/new_video.mp4", str);
1071 ghb_ui_update(ud, "destination", ghb_string_value(path));
1075 prefs_initializing = FALSE;
1079 ghb_prefs_save(GValue *settings)
1083 GHashTableIter iter;
1085 const GValue *value;
1087 if (prefs_initializing) return;
1088 dict = plist_get_dict(internalPlist, "Preferences");
1089 if (dict == NULL) return;
1090 pref_dict = plist_get_dict(prefsPlist, "Preferences");
1091 if (pref_dict == NULL) return;
1092 ghb_dict_iter_init(&iter, dict);
1093 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1094 // pointer will break strict-aliasing rules"
1095 while (g_hash_table_iter_next(
1096 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
1098 value = ghb_settings_get_value(settings, key);
1101 ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value));
1104 store_plist(prefsPlist, "preferences");
1108 ghb_pref_save(GValue *settings, const gchar *key)
1110 const GValue *value;
1112 if (prefs_initializing) return;
1113 value = ghb_settings_get_value(settings, key);
1117 dict = plist_get_dict(prefsPlist, "Preferences");
1118 if (dict == NULL) return;
1119 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
1120 store_plist(prefsPlist, "preferences");
1125 ghb_settings_init(signal_user_data_t *ud)
1128 GHashTableIter iter;
1133 g_debug("ghb_settings_init");
1134 prefs_initializing = TRUE;
1136 internalPlist = ghb_resource_get("internal-defaults");
1137 // Setting a ui widget will cause the corresponding setting
1138 // to be set, but it also triggers a callback that can
1139 // have the side effect of using other settings values
1140 // that have not yet been set. So set *all* settings first
1141 // then update the ui.
1142 internal = plist_get_dict(internalPlist, "Initialization");
1143 ghb_dict_iter_init(&iter, internal);
1144 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1145 // pointer will break strict-aliasing rules"
1146 while (g_hash_table_iter_next(
1147 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1149 ghb_settings_set_value(ud->settings, key, gval);
1152 internal = plist_get_dict(internalPlist, "Presets");
1153 ghb_dict_iter_init(&iter, internal);
1154 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1155 // pointer will break strict-aliasing rules"
1156 while (g_hash_table_iter_next(
1157 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1159 ghb_settings_set_value(ud->settings, key, gval);
1162 internal = plist_get_dict(internalPlist, "Preferences");
1163 ghb_dict_iter_init(&iter, internal);
1164 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1165 // pointer will break strict-aliasing rules"
1166 while (g_hash_table_iter_next(
1167 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1169 ghb_settings_set_value(ud->settings, key, gval);
1171 prefs_initializing = FALSE;
1175 ghb_settings_close()
1178 ghb_value_free(internalPlist);
1180 ghb_value_free(presetsPlist);
1182 ghb_value_free(prefsPlist);
1186 ghb_prefs_load(signal_user_data_t *ud)
1188 GValue *dict, *internal;
1189 GHashTableIter iter;
1191 GValue *gval, *path;
1193 g_debug("ghb_prefs_load");
1194 prefsPlist = load_plist("preferences");
1195 if (prefsPlist == NULL)
1196 prefsPlist = ghb_dict_value_new();
1197 dict = plist_get_dict(prefsPlist, "Preferences");
1198 internal = plist_get_dict(internalPlist, "Preferences");
1199 if (dict == NULL && internal)
1201 dict = ghb_dict_value_new();
1202 ghb_dict_insert(prefsPlist, g_strdup("Preferences"), dict);
1204 // Get defaults from internal defaults
1205 ghb_dict_iter_init(&iter, internal);
1206 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1207 // pointer will break strict-aliasing rules"
1208 while (g_hash_table_iter_next(
1209 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
1211 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
1213 const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
1218 ghb_dict_insert(dict,
1219 g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir)));
1220 store_plist(prefsPlist, "preferences");
1222 // Read legacy default_preset preference and update accordingly
1223 path = ghb_dict_lookup(dict, "default_preset");
1228 if (G_VALUE_TYPE(path) == G_TYPE_STRING)
1232 path = ghb_array_value_new(1);
1233 ghb_array_append(path, ghb_value_dup(str));
1234 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1235 ghb_value_free(path);
1238 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1242 presets_set_default(indices, len);
1245 ghb_dict_remove(dict, "default_preset");
1246 store_plist(prefsPlist, "preferences");
1251 get_preset_color(gint flags)
1255 if (flags & PRESETS_CUST)
1258 if (flags & PRESETS_FOLDER)
1266 if (flags & PRESETS_FOLDER)
1275 ghb_presets_list_init(
1276 signal_user_data_t *ud,
1280 GtkTreeView *treeview;
1281 GtkTreeIter iter, titer, *piter;
1283 GtkTreeStore *store;
1284 const gchar *preset;
1285 GtkTreePath *parent_path;
1286 const gchar *description;
1292 GValue *presets = NULL;
1294 g_debug("ghb_presets_list_init ()");
1295 more_indices = g_malloc((len+1)*sizeof(gint));
1296 memcpy(more_indices, indices, len*sizeof(gint));
1297 presets = presets_get_folder(presetsPlist, indices, len);
1298 if (presets == NULL)
1300 g_warning("Failed to find parent folder when adding child.");
1303 count = ghb_array_len(presets);
1304 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1305 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1306 parent_path = ghb_tree_path_new_from_indices(indices, len);
1309 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &titer, parent_path);
1311 gtk_tree_path_free(parent_path);
1317 for (ii = 0; ii < count; ii++)
1321 // Additional settings, add row
1322 dict = ghb_array_get_nth(presets, ii);
1323 preset = preset_get_name(dict);
1324 more_indices[len] = ii;
1325 def = preset_is_default(dict);
1327 description = ghb_presets_get_description(dict);
1328 gtk_tree_store_append(store, &iter, piter);
1329 flags = ghb_preset_flags(dict);
1330 color = get_preset_color(flags);
1331 gtk_tree_store_set(store, &iter, 0, preset,
1342 if (gtk_tree_model_iter_parent(
1343 GTK_TREE_MODEL(store), &ppiter, piter))
1345 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &ppiter);
1346 gtk_tree_view_expand_row(treeview, path, FALSE);
1347 gtk_tree_path_free(path);
1349 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter);
1350 gtk_tree_view_expand_row(treeview, path, FALSE);
1351 gtk_tree_path_free(path);
1353 if (flags & PRESETS_FOLDER)
1355 ghb_presets_list_init(ud, more_indices, len+1);
1358 g_free(more_indices);
1362 presets_list_update_item(
1363 signal_user_data_t *ud,
1367 GtkTreeView *treeview;
1368 GtkTreeStore *store;
1370 GtkTreePath *treepath;
1372 const gchar *description;
1378 g_debug("presets_list_update_item ()");
1379 dict = presets_get_dict(presetsPlist, indices, len);
1382 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1383 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1384 treepath = ghb_tree_path_new_from_indices(indices, len);
1385 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
1386 // Additional settings, add row
1387 name = preset_get_name(dict);
1388 def = preset_is_default(dict);
1390 description = ghb_presets_get_description(dict);
1391 flags = ghb_preset_flags(dict);
1392 color = get_preset_color(flags);
1393 gtk_tree_store_set(store, &iter, 0, name,
1399 if (flags & PRESETS_FOLDER)
1401 ghb_presets_list_init(ud, indices, len);
1406 presets_list_insert(
1407 signal_user_data_t *ud,
1411 GtkTreeView *treeview;
1412 GtkTreeIter iter, titer, *piter;
1413 GtkTreeStore *store;
1414 const gchar *preset;
1415 const gchar *description;
1420 GtkTreePath *parent_path;
1424 g_debug("presets_list_insert ()");
1425 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1426 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1427 presets = presets_get_folder(presetsPlist, indices, len-1);
1428 if (presets == NULL)
1430 g_warning("Failed to find parent folder while adding child.");
1433 parent_path = ghb_tree_path_new_from_indices(indices, len-1);
1436 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &titer, parent_path);
1438 gtk_tree_path_free(parent_path);
1444 count = ghb_array_len(presets);
1445 if (indices[len-1] >= count)
1447 // Additional settings, add row
1448 dict = ghb_array_get_nth(presets, indices[len-1]);
1449 preset = preset_get_name(dict);
1450 def = preset_is_default(dict);
1452 description = ghb_presets_get_description(dict);
1453 gtk_tree_store_insert(store, &iter, piter, indices[len-1]);
1454 flags = ghb_preset_flags(dict);
1455 color = get_preset_color(flags);
1456 gtk_tree_store_set(store, &iter, 0, preset,
1462 if (flags & PRESETS_FOLDER)
1464 ghb_presets_list_init(ud, indices, len);
1469 presets_list_remove(
1470 signal_user_data_t *ud,
1474 GtkTreeView *treeview;
1475 GtkTreePath *treepath;
1477 GtkTreeStore *store;
1479 g_debug("presets_list_remove ()");
1480 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1481 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1482 treepath = ghb_tree_path_new_from_indices(indices, len);
1485 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
1486 gtk_tree_store_remove(store, &iter);
1487 gtk_tree_path_free(treepath);
1492 remove_std_presets(signal_user_data_t *ud)
1497 count = ghb_array_len(presetsPlist);
1498 for (ii = count-1; ii >= 0; ii--)
1503 dict = ghb_array_get_nth(presetsPlist, ii);
1504 ptype = ghb_value_int(preset_dict_get_value(dict, "preset_type"));
1505 if (!(ptype & PRESETS_CUST))
1507 if (ghb_presets_remove(presetsPlist, &indices, 1))
1509 presets_list_remove(ud, &indices, 1);
1516 ghb_presets_reload(signal_user_data_t *ud)
1518 GValue *std_presets;
1521 g_debug("ghb_presets_reload()\n");
1522 std_presets = ghb_resource_get("standard-presets");
1523 if (std_presets == NULL) return;
1525 remove_std_presets(ud);
1526 // Merge the keyfile contents into our presets
1527 count = ghb_array_len(std_presets);
1528 for (ii = count-1; ii >= 0; ii--)
1532 GHashTableIter iter;
1537 std_dict = ghb_array_get_nth(std_presets, ii);
1538 copy_dict = ghb_dict_value_new();
1539 ghb_presets_insert(presetsPlist, copy_dict, &indices, 1);
1540 ghb_dict_iter_init(&iter, std_dict);
1541 // middle (void*) cast prevents gcc warning "defreferencing
1542 // type-punned pointer will break strict-aliasing rules"
1543 while (g_hash_table_iter_next(
1544 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
1546 ghb_dict_insert(copy_dict, g_strdup(key), ghb_value_dup(value));
1548 presets_list_insert(ud, &indices, 1);
1550 store_plist(presetsPlist, "presets");
1554 ghb_save_queue(GValue *queue)
1556 store_plist(queue, "queue");
1562 return load_plist("queue");
1566 ghb_remove_queue_file()
1568 remove_plist("queue");
1574 presetsPlist = load_plist("presets");
1575 if (presetsPlist == NULL)
1577 presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets"));
1578 store_plist(presetsPlist, "presets");
1580 if (G_VALUE_TYPE(presetsPlist) == ghb_dict_get_type())
1581 { // Presets is older dictionary format. Convert to array
1582 GHashTableIter old_iter;
1587 presets = ghb_array_value_new(32);
1588 ghb_dict_iter_init(&old_iter, presetsPlist);
1589 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1590 // pointer will break strict-aliasing rules"
1591 while (g_hash_table_iter_next(
1592 &old_iter, (gpointer*)(void*)&name, (gpointer*)(void*)&orig_dict))
1594 GHashTableIter iter;
1596 GValue *value, *dict;
1598 dict = ghb_dict_value_new();
1599 ghb_dict_insert(dict, g_strdup("preset_name"),
1600 ghb_string_value_new(name));
1601 ghb_array_append(presets, dict);
1602 ghb_dict_iter_init(&iter, orig_dict);
1603 // middle (void*) cast prevents gcc warning "defreferencing
1604 // type-punned pointer will break strict-aliasing rules"
1605 while (g_hash_table_iter_next(
1606 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
1608 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value));
1611 ghb_value_free(presetsPlist);
1612 presetsPlist = presets;
1613 store_plist(presetsPlist, "presets");
1618 settings_save(signal_user_data_t *ud, const GValue *path)
1620 GValue *dict, *internal;
1621 GHashTableIter iter;
1625 gint *indices, len, count;
1627 gboolean replace = FALSE;
1629 g_debug("settings_save");
1630 if (internalPlist == NULL) return;
1631 count = ghb_array_len(path);
1632 name = g_value_get_string(ghb_array_get_nth(path, count-1));
1633 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1636 if (ghb_presets_get_type(presetsPlist, indices, len) &
1640 message = g_strdup_printf(
1641 "%s: Folder already exists.\n"
1642 "You can not replace it with a preset.",
1644 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
1648 dict = ghb_dict_value_new();
1649 ghb_presets_replace(presetsPlist, dict, indices, len);
1654 indices = presets_find_pos(path, PRESETS_CUST, &len);
1657 dict = ghb_dict_value_new();
1658 ghb_presets_insert(presetsPlist, dict, indices, len);
1662 g_warning("failed to find insert path");
1666 ghb_dict_insert(dict, g_strdup("preset_name"), ghb_string_value_new(name));
1668 if (ghb_settings_get_boolean(ud->settings, "allow_tweaks"))
1671 str = ghb_settings_get_string(ud->settings, "tweak_deinterlace");
1674 ghb_settings_set_string(ud->settings, "deinterlace", str);
1677 str = ghb_settings_get_string(ud->settings, "tweak_denoise");
1680 ghb_settings_set_string(ud->settings, "denoise", str);
1684 autoscale = ghb_settings_get_boolean(ud->settings, "autoscale");
1685 ghb_settings_set_int64(ud->settings, "preset_type", PRESETS_CUST);
1687 internal = plist_get_dict(internalPlist, "Presets");
1688 ghb_dict_iter_init(&iter, internal);
1689 // middle (void*) cast prevents gcc warning "defreferencing type-punned
1690 // pointer will break strict-aliasing rules"
1691 while (g_hash_table_iter_next(
1692 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value))
1700 if (strcmp(key, "max_width") == 0)
1702 key2 = "scale_width";
1704 else if (strcmp(key, "max_height") == 0)
1706 key2 = "scale_height";
1709 gval = ghb_settings_get_value(ud->settings, key2);
1712 g_debug("Setting (%s) is not in defaults\n", (gchar*)key);
1715 if (ghb_value_cmp(gval, value) != 0)
1717 // Differs from default value. Store it.
1718 ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval));
1722 presets_list_update_item(ud, indices, len);
1725 ghb_dict_insert(dict, g_strdup("Default"),
1726 ghb_boolean_value_new(FALSE));
1727 presets_list_insert(ud, indices, len);
1730 store_plist(presetsPlist, "presets");
1731 ud->dont_clear_presets = TRUE;
1732 ghb_set_preset(ud, path);
1733 ud->dont_clear_presets = FALSE;
1738 folder_save(signal_user_data_t *ud, const GValue *path)
1740 GValue *dict, *folder;
1741 gint *indices, len, count;
1744 count = ghb_array_len(path);
1745 name = g_value_get_string(ghb_array_get_nth(path, count-1));
1746 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1749 if (!(ghb_presets_get_type(presetsPlist, indices, len) &
1753 message = g_strdup_printf(
1754 "%s: Preset already exists.\n"
1755 "You can not replace it with a folder.",
1757 ghb_message_dialog(GTK_MESSAGE_ERROR, message, "Cancel", NULL);
1762 // Already exists, update its description
1763 dict = presets_get_dict(presetsPlist, indices, len);
1764 ghb_dict_insert(dict, g_strdup("preset_description"),
1765 ghb_value_dup(preset_dict_get_value(
1766 ud->settings, "preset_description")));
1772 indices = presets_find_pos(path, PRESETS_CUST, &len);
1775 dict = ghb_dict_value_new();
1776 ghb_presets_insert(presetsPlist, dict, indices, len);
1780 g_warning("failed to find insert path");
1784 ghb_dict_insert(dict, g_strdup("preset_description"),
1785 ghb_value_dup(preset_dict_get_value(
1786 ud->settings, "preset_description")));
1787 ghb_dict_insert(dict, g_strdup("preset_name"), ghb_string_value_new(name));
1788 folder = ghb_array_value_new(8);
1789 ghb_dict_insert(dict, g_strdup("preset_folder"), folder);
1790 ghb_dict_insert(dict, g_strdup("preset_type"),
1791 ghb_int64_value_new(PRESETS_FOLDER|PRESETS_CUST));
1793 presets_list_insert(ud, indices, len);
1795 store_plist(presetsPlist, "presets");
1796 ud->dont_clear_presets = TRUE;
1797 ghb_set_preset(ud, path);
1798 ud->dont_clear_presets = FALSE;
1803 ghb_presets_list_default(signal_user_data_t *ud)
1805 GtkTreeView *treeview;
1806 GtkTreePath *treepath;
1808 GtkTreeStore *store;
1811 g_debug("ghb_presets_list_default ()");
1812 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1813 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1814 indices = presets_find_default(&len);
1815 if (indices == NULL) return;
1816 treepath = ghb_tree_path_new_from_indices(indices, len);
1819 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
1821 gtk_tree_store_set(store, &iter,
1826 gtk_tree_path_free(treepath);
1832 ghb_presets_list_clear_default(signal_user_data_t *ud)
1834 GtkTreeView *treeview;
1835 GtkTreePath *treepath;
1837 GtkTreeStore *store;
1840 g_debug("ghb_presets_list_clear_default ()");
1841 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
1842 store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
1843 indices = presets_find_default(&len);
1844 if (indices == NULL) return;
1845 treepath = ghb_tree_path_new_from_indices(indices, len);
1848 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath))
1850 gtk_tree_store_set(store, &iter,
1855 gtk_tree_path_free(treepath);
1862 GtkBuilder *builder,
1866 GtkTreeView *treeview;
1867 GtkTreeSelection *selection;
1868 GtkTreeModel *store;
1872 g_debug("ghb_select_preset2()");
1873 treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "presets_list"));
1874 selection = gtk_tree_view_get_selection (treeview);
1875 store = gtk_tree_view_get_model (treeview);
1876 path = ghb_tree_path_new_from_indices(indices, len);
1879 if (gtk_tree_model_get_iter(store, &iter, path))
1881 gtk_tree_selection_select_iter (selection, &iter);
1885 if (gtk_tree_model_get_iter_first(store, &iter))
1886 gtk_tree_selection_select_iter (selection, &iter);
1888 gtk_tree_path_free(path);
1893 ghb_select_preset(GtkBuilder *builder, const GValue *path)
1897 g_debug("ghb_select_preset()");
1898 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1901 ghb_select_preset2(builder, indices, len);
1907 ghb_select_default_preset(GtkBuilder *builder)
1911 g_debug("ghb_select_default_preset()");
1912 indices = presets_find_default(&len);
1915 ghb_select_preset2(builder, indices, len);
1921 update_audio_presets(signal_user_data_t *ud)
1923 g_debug("update_audio_presets");
1924 const GValue *audio_list;
1926 audio_list = ghb_settings_get_value(ud->settings, "audio_list");
1927 ghb_settings_set_value(ud->settings, "pref_audio_list", audio_list);
1931 enforce_preset_type(signal_user_data_t *ud, const GValue *path)
1934 GtkWidget *normal, *folder;
1937 normal = GHB_WIDGET(ud->builder, "preset_type_normal");
1938 folder = GHB_WIDGET(ud->builder, "preset_type_folder");
1939 indices = ghb_preset_indices_from_path(presetsPlist, path, &len);
1942 ptype = ghb_presets_get_type(presetsPlist, indices, len);
1943 if (ptype & PRESETS_FOLDER)
1944 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(folder),
1947 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(normal),
1949 gtk_widget_set_sensitive(folder, ptype & PRESETS_FOLDER);
1950 gtk_widget_set_sensitive(normal, !(ptype & PRESETS_FOLDER));
1955 gtk_widget_set_sensitive(folder, TRUE);
1956 gtk_widget_set_sensitive(normal, TRUE);
1961 presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
1966 GtkResponseType response;
1968 const gchar *name = "";
1969 gint count, *indices, len;
1971 g_debug("presets_save_clicked_cb ()");
1972 preset = ghb_settings_get_value (ud->settings, "preset_selection");
1974 count = ghb_array_len(preset);
1976 name = g_value_get_string(ghb_array_get_nth(preset, count-1));
1979 // Clear the description
1980 desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "preset_description"));
1981 dialog = GHB_WIDGET(ud->builder, "preset_save_dialog");
1982 entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "preset_name"));
1983 gtk_entry_set_text(entry, name);
1984 enforce_preset_type(ud, preset);
1985 response = gtk_dialog_run(GTK_DIALOG(dialog));
1986 gtk_widget_hide(dialog);
1987 if (response == GTK_RESPONSE_OK)
1990 const gchar *name = gtk_entry_get_text(entry);
1993 if (ghb_settings_get_boolean(ud->settings, "preset_type_folder"))
1995 if (count > MAX_NESTED_PRESET-1)
1997 count = MAX_NESTED_PRESET-1;
2000 dest = ghb_array_value_new(MAX_NESTED_PRESET);
2001 indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
2006 ptype = ghb_presets_get_type(presetsPlist, indices, len);
2007 if (ptype & PRESETS_CUST)
2009 ghb_array_copy(dest, preset, count-1);
2012 ghb_array_append(dest, ghb_string_value_new(name));
2014 ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc));
2015 if (ghb_settings_get_boolean(ud->settings, "preset_type_folder"))
2017 folder_save(ud, dest);
2021 // Construct the audio settings presets from the current audio list
2022 update_audio_presets(ud);
2023 settings_save(ud, dest);
2025 // Make the new preset the selected item
2026 ghb_select_preset(ud->builder, dest);
2027 ghb_value_free(dest);
2032 preset_type_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
2034 ghb_widget_to_setting(ud->settings, widget);
2038 preset_name_changed_cb(GtkWidget *entry, signal_user_data_t *ud)
2041 GValue *preset, *dest;
2044 preset = ghb_settings_get_value (ud->settings, "preset_selection");
2045 name = ghb_widget_string(entry);
2046 dest = ghb_value_dup(preset);
2047 count = ghb_array_len(dest);
2048 ghb_array_replace(dest, count-1, ghb_string_value_new(name));
2049 enforce_preset_type(ud, dest);
2050 ghb_value_free(dest);
2054 presets_restore_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2058 g_debug("presets_restore_clicked_cb ()");
2059 // Reload only the standard presets
2060 ghb_presets_reload(ud);
2061 // Updating the presets list shuffles things around
2062 // need to make sure the proper preset is selected
2063 preset = ghb_settings_get_value (ud->settings, "preset");
2064 ghb_select_preset(ud->builder, preset);
2068 presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2070 GtkTreeView *treeview;
2071 GtkTreeSelection *selection;
2072 GtkTreeModel *store;
2075 GtkResponseType response;
2077 g_debug("presets_remove_clicked_cb ()");
2078 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
2079 selection = gtk_tree_view_get_selection (treeview);
2080 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2087 gtk_tree_model_get(store, &iter, 0, &preset, -1);
2088 path = gtk_tree_model_get_path(store, &iter);
2089 indices = gtk_tree_path_get_indices(path);
2090 len = gtk_tree_path_get_depth(path);
2092 ptype = ghb_presets_get_type(presetsPlist, indices, len);
2093 dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
2094 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
2095 "Confirm deletion of %s:\n\n%s",
2096 (ptype & PRESETS_FOLDER) ? "folder" : "preset",
2098 response = gtk_dialog_run(GTK_DIALOG(dialog));
2099 gtk_widget_destroy (dialog);
2100 if (response == GTK_RESPONSE_YES)
2102 GtkTreeIter nextIter = iter;
2103 gboolean valid = TRUE;
2104 if (!gtk_tree_model_iter_next(store, &nextIter))
2106 if (!gtk_tree_model_iter_parent(store, &nextIter, &iter))
2111 // Remove the selected item
2112 // First unselect it so that selecting the new item works properly
2113 gtk_tree_selection_unselect_iter (selection, &iter);
2114 if (ghb_presets_remove(presetsPlist, indices, len))
2116 store_plist(presetsPlist, "presets");
2117 presets_list_remove(ud, indices, len);
2120 valid = gtk_tree_model_get_iter_first(store, &nextIter);
2123 gtk_tree_path_free(path);
2124 path = gtk_tree_model_get_path(store, &nextIter);
2125 indices = gtk_tree_path_get_indices(path);
2126 len = gtk_tree_path_get_depth(path);
2127 ghb_select_preset2(ud->builder, indices, len);
2131 gtk_tree_path_free(path);
2135 // controls where valid drop locations are
2137 presets_drag_motion_cb(
2139 GdkDragContext *ctx,
2143 signal_user_data_t *ud)
2145 GtkTreePath *path = NULL;
2146 GtkTreeViewDropPosition drop_pos;
2150 GtkTreeModel *model;
2151 GtkTreeSelection *select;
2152 gint src_ptype, dst_ptype;
2154 gint tree_depth, ii;
2156 // Get the type of the object being dragged
2157 srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
2158 select = gtk_tree_view_get_selection (srctv);
2159 gtk_tree_selection_get_selected (select, &model, &iter);
2160 path = gtk_tree_model_get_path (model, &iter);
2161 indices = gtk_tree_path_get_indices(path);
2162 len = gtk_tree_path_get_depth(path);
2164 preset = presets_get_dict(presetsPlist, indices, len);
2165 tree_depth = preset_tree_depth(preset);
2167 src_ptype = ghb_presets_get_type(presetsPlist, indices, len);
2168 gtk_tree_path_free(path);
2170 if ((src_ptype & PRESETS_FOLDER) && tree_depth == 1)
2173 // The rest checks that the destination is a valid position
2175 gtk_tree_view_get_dest_row_at_pos (tv, x, y, &path, &drop_pos);
2178 gdk_drag_status(ctx, 0, time);
2181 // Don't allow repositioning of builtin presets
2182 if (!(src_ptype & PRESETS_CUST))
2184 gdk_drag_status(ctx, 0, time);
2188 len = gtk_tree_path_get_depth(path);
2189 if (len+tree_depth-1 >= MAX_NESTED_PRESET)
2191 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
2192 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
2193 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
2194 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
2196 for (ii = len+tree_depth-1; ii > MAX_NESTED_PRESET; ii--)
2197 gtk_tree_path_up(path);
2198 indices = gtk_tree_path_get_indices(path);
2199 len = gtk_tree_path_get_depth(path);
2200 dst_ptype = ghb_presets_get_type(presetsPlist, indices, len);
2201 // Don't allow mixing custom presets in the builtins
2202 if (!(dst_ptype & PRESETS_CUST))
2204 gdk_drag_status(ctx, 0, time);
2208 // Only allow *drop into* for folders
2209 if (!(dst_ptype & PRESETS_FOLDER))
2211 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
2212 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
2213 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
2214 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
2217 len = gtk_tree_path_get_depth(path);
2218 gtk_tree_view_set_drag_dest_row(tv, path, drop_pos);
2219 gtk_tree_path_free(path);
2220 gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
2226 GtkTreeView *dstwidget,
2229 GtkSelectionData *selection_data,
2230 guint info, guint t,
2231 signal_user_data_t *ud)
2233 GtkTreePath *path = NULL;
2234 GtkTreeViewDropPosition drop_pos;
2235 GtkTreeIter dstiter, srciter;
2236 gint *dst_indices, dst_len, *src_indices, src_len;
2237 gint src_ptype, dst_ptype;
2239 GtkTreeModel *dstmodel = gtk_tree_view_get_model(dstwidget);
2241 g_debug("preset_drag_cb ()");
2242 // This doesn't work here for some reason...
2243 // gtk_tree_view_get_drag_dest_row(dstwidget, &path, &drop_pos);
2244 gtk_tree_view_get_dest_row_at_pos (dstwidget, x, y, &path, &drop_pos);
2245 // This little hack is needed because attempting to drop after
2246 // the last item gives us no path or drop_pos.
2251 n_children = gtk_tree_model_iter_n_children(dstmodel, NULL);
2254 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
2255 path = gtk_tree_path_new_from_indices(n_children-1, -1);
2259 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
2260 path = gtk_tree_path_new_from_indices(0, -1);
2265 GtkTreeView *srcwidget;
2266 GtkTreeModel *srcmodel;
2267 GtkTreeSelection *select;
2268 GtkTreePath *srcpath = NULL;
2270 gint tree_depth, ii;
2272 srcwidget = GTK_TREE_VIEW(gtk_drag_get_source_widget(dc));
2273 select = gtk_tree_view_get_selection (srcwidget);
2274 gtk_tree_selection_get_selected (select, &srcmodel, &srciter);
2276 srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
2277 src_indices = gtk_tree_path_get_indices(srcpath);
2278 src_len = gtk_tree_path_get_depth(srcpath);
2279 src_ptype = ghb_presets_get_type(presetsPlist, src_indices, src_len);
2280 preset = ghb_value_dup(
2281 presets_get_dict(presetsPlist, src_indices, src_len));
2282 gtk_tree_path_free(srcpath);
2284 // Don't allow repositioning of builtin presets
2285 if (!(src_ptype & PRESETS_CUST))
2288 tree_depth = preset_tree_depth(preset);
2289 if ((src_ptype & PRESETS_FOLDER) && tree_depth == 1)
2292 dst_len = gtk_tree_path_get_depth(path);
2293 if (dst_len+tree_depth-1 >= MAX_NESTED_PRESET)
2295 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
2296 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
2297 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
2298 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
2301 for (ii = dst_len+tree_depth-1; ii > MAX_NESTED_PRESET; ii--)
2302 gtk_tree_path_up(path);
2303 dst_indices = gtk_tree_path_get_indices(path);
2304 dst_len = gtk_tree_path_get_depth(path);
2305 dst_ptype = ghb_presets_get_type(presetsPlist, dst_indices, dst_len);
2306 // Only allow *drop into* for folders
2307 if (!(dst_ptype & PRESETS_FOLDER))
2309 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
2310 drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
2311 if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
2312 drop_pos = GTK_TREE_VIEW_DROP_AFTER;
2314 if (gtk_tree_model_get_iter (dstmodel, &dstiter, path))
2317 GtkTreePath *dstpath = NULL;
2321 case GTK_TREE_VIEW_DROP_BEFORE:
2322 gtk_tree_store_insert_before(GTK_TREE_STORE (dstmodel),
2323 &iter, NULL, &dstiter);
2326 case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
2327 gtk_tree_store_insert(GTK_TREE_STORE (dstmodel),
2328 &iter, &dstiter, 0);
2331 case GTK_TREE_VIEW_DROP_AFTER:
2332 gtk_tree_store_insert_after(GTK_TREE_STORE (dstmodel),
2333 &iter, NULL, &dstiter);
2336 case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
2337 gtk_tree_store_insert_after(GTK_TREE_STORE (dstmodel),
2338 &iter, &dstiter, 0);
2345 dstpath = gtk_tree_model_get_path (dstmodel, &iter);
2346 dst_indices = gtk_tree_path_get_indices(dstpath);
2347 dst_len = gtk_tree_path_get_depth(dstpath);
2348 ghb_presets_insert(presetsPlist, preset, dst_indices, dst_len);
2349 gtk_tree_path_free(dstpath);
2351 srcpath = gtk_tree_model_get_path (srcmodel, &srciter);
2352 src_indices = gtk_tree_path_get_indices(srcpath);
2353 src_len = gtk_tree_path_get_depth(srcpath);
2354 ghb_presets_remove(presetsPlist, src_indices, src_len);
2355 gtk_tree_path_free(srcpath);
2357 gtk_tree_store_remove (GTK_TREE_STORE (srcmodel), &srciter);
2359 dstpath = gtk_tree_model_get_path (dstmodel, &iter);
2360 dst_indices = gtk_tree_path_get_indices(dstpath);
2361 dst_len = gtk_tree_path_get_depth(dstpath);
2362 presets_list_update_item(ud, dst_indices, dst_len);
2363 gtk_tree_path_free(dstpath);
2365 store_plist(presetsPlist, "presets");
2367 gtk_tree_path_free(path);
2372 preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo)
2376 ghb_ui_update(ud, "scale_width",
2377 ghb_int64_value(tinfo->width - tinfo->crop[2] - tinfo->crop[3]));
2378 // If anamorphic or keep_aspect, the hight will be automatically calculated
2379 gboolean keep_aspect, anamorphic;
2380 keep_aspect = ghb_settings_get_boolean(ud->settings, "keep_aspect");
2381 anamorphic = ghb_settings_get_boolean(ud->settings, "anamorphic");
2382 if (!(keep_aspect || anamorphic))
2384 ghb_ui_update(ud, "scale_height",
2385 ghb_int64_value(tinfo->height - tinfo->crop[0] - tinfo->crop[1]));
2388 // Set the limits of cropping. hb_set_anamorphic_size crashes if
2389 // you pass it a cropped width or height == 0.
2391 bound = tinfo->height / 2 - 2;
2392 widget = GHB_WIDGET (ud->builder, "crop_top");
2393 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
2394 widget = GHB_WIDGET (ud->builder, "crop_bottom");
2395 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
2396 bound = tinfo->width / 2 - 2;
2397 widget = GHB_WIDGET (ud->builder, "crop_left");
2398 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
2399 widget = GHB_WIDGET (ud->builder, "crop_right");
2400 gtk_spin_button_set_range (GTK_SPIN_BUTTON(widget), 0, bound);
2401 if (ghb_settings_get_boolean(ud->settings, "autocrop"))
2403 ghb_ui_update(ud, "crop_top", ghb_int64_value(tinfo->crop[0]));
2404 ghb_ui_update(ud, "crop_bottom", ghb_int64_value(tinfo->crop[1]));
2405 ghb_ui_update(ud, "crop_left", ghb_int64_value(tinfo->crop[2]));
2406 ghb_ui_update(ud, "crop_right", ghb_int64_value(tinfo->crop[3]));
2410 ghb_ui_update(ud, "crop_top", ghb_int64_value(0));
2411 ghb_ui_update(ud, "crop_bottom", ghb_int64_value(0));
2412 ghb_ui_update(ud, "crop_left", ghb_int64_value(0));
2413 ghb_ui_update(ud, "crop_right", ghb_int64_value(0));
2418 presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
2420 GtkTreeModel *store;
2422 ghb_title_info_t tinfo;
2425 g_debug("presets_list_selection_changed_cb ()");
2426 widget = GHB_WIDGET (ud->builder, "presets_remove");
2427 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2429 GtkTreePath *treepath;
2430 gint *indices, len, ptype;
2433 treepath = gtk_tree_model_get_path(store, &iter);
2434 indices = gtk_tree_path_get_indices(treepath);
2435 len = gtk_tree_path_get_depth(treepath);
2437 path = preset_path_from_indices(presetsPlist, indices, len);
2438 ghb_settings_take_value(ud->settings, "preset_selection", path);
2440 ptype = ghb_presets_get_type(presetsPlist, indices, len);
2441 if (!(ptype & PRESETS_FOLDER))
2443 ud->dont_clear_presets = TRUE;
2444 // Temporarily set the video_quality range to (0,100)
2445 // This is needed so the video_quality value does not get
2446 // truncated when set. The range will be readjusted below
2447 GtkWidget *qp = GHB_WIDGET(ud->builder, "video_quality");
2448 gtk_range_set_range (GTK_RANGE(qp), 0, 100);
2449 // Clear the audio list prior to changing the preset. Existing
2450 // audio can cause the container extension to be automatically
2451 // changed when it shouldn't be
2452 ghb_clear_audio_list(ud);
2453 ghb_set_preset_from_indices(ud, indices, len);
2454 gtk_tree_path_free(treepath);
2456 titleindex = ghb_settings_combo_int(ud->settings, "title");
2457 ghb_set_pref_audio(titleindex, ud);
2458 ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE);
2459 ud->dont_clear_presets = FALSE;
2460 if (ghb_get_title_info (&tinfo, titleindex))
2462 preset_update_title_deps(ud, &tinfo);
2464 ghb_set_scale (ud, GHB_SCALE_KEEP_NONE);
2467 ghb_vquality_range(ud, &vqmin, &vqmax);
2468 gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax);
2469 gtk_widget_set_sensitive(widget, TRUE);
2474 g_debug("No selection??? Perhaps unselected.");
2475 gtk_widget_set_sensitive(widget, FALSE);
2480 ghb_clear_presets_selection(signal_user_data_t *ud)
2482 GtkTreeView *treeview;
2483 GtkTreeSelection *selection;
2485 if (ud->dont_clear_presets) return;
2486 g_debug("ghb_clear_presets_selection()");
2487 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
2488 selection = gtk_tree_view_get_selection (treeview);
2489 gtk_tree_selection_unselect_all (selection);
2490 ghb_settings_set_boolean(ud->settings, "preset_modified", TRUE);
2494 presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud)
2496 GtkTreeView *treeview;
2497 GtkTreeSelection *selection;
2498 GtkTreeModel *store;
2501 treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list"));
2502 selection = gtk_tree_view_get_selection(treeview);
2503 if (gtk_tree_selection_get_selected(selection, &store, &iter))
2506 path = gtk_tree_model_get_path (store, &iter);
2507 // Make the parent visible in scroll window if it is not.
2508 gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0, 0);
2509 gtk_tree_path_free(path);
2514 presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
2519 g_debug("presets_default_clicked_cb ()");
2520 preset = ghb_settings_get_value(ud->settings, "preset_selection");
2521 indices = ghb_preset_indices_from_path(presetsPlist, preset, &len);
2524 if (!(ghb_presets_get_type(presetsPlist, indices, len) &
2527 ghb_presets_list_clear_default(ud);
2528 presets_set_default(indices, len);
2529 ghb_presets_list_default(ud);