X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=gtk%2Fsrc%2Fpresets.c;h=2e231bfd13815f1c1e9ad0453e913a877a1cd165;hb=75a84adcf721b5965c63f78984b8a624dddf6c0c;hp=4a06c1c84b3296c1f5cc2f9988272d25217aa30b;hpb=8ca999c895530bb0555dd29838de4bf8725a2fa5;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 4a06c1c8..2e231bfd 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * presets.c - * Copyright (C) John Stebbins 2008 + * Copyright (C) John Stebbins 2008-2011 * * presets.c is free software. * @@ -11,14 +11,20 @@ * any later version. * */ +#include +#include +#include +#include #include #include #include #include #include +#include "hb.h" #include "settings.h" #include "callbacks.h" #include "audiohandler.h" +#include "subtitlehandler.h" #include "hb-backend.h" #include "plist.h" #include "resources.h" @@ -37,10 +43,24 @@ enum static GValue *presetsPlist = NULL; static GValue *internalPlist = NULL; static GValue *prefsPlist = NULL; +static gboolean prefs_modified = FALSE; static const GValue* preset_dict_get_value(GValue *dict, const gchar *key); static void store_plist(GValue *plist, const gchar *name); static void store_presets(void); +static void store_prefs(void); + +gint +preset_path_cmp(gint *indices1, gint len1, gint *indices2, gint len2) +{ + gint ii; + for (ii = 0; ii < len1 && ii < len2; ii++) + { + if (indices1[ii] != indices2[ii]) + return indices1[ii] - indices2[ii]; + } + return len1 - len2; +} // This only handle limited depth GtkTreePath* @@ -139,37 +159,6 @@ ghb_preset_path_string(const GValue *path) return str; } -static void -debug_show_type(GType tp) -{ - const gchar *str = "unknown"; - if (tp == G_TYPE_STRING) - { - str ="string"; - } - else if (tp == G_TYPE_INT) - { - str ="int"; - } - else if (tp == G_TYPE_INT64) - { - str ="int64"; - } - else if (tp == G_TYPE_BOOLEAN) - { - str ="bool"; - } - else if (tp == ghb_array_get_type()) - { - str ="array"; - } - else if (tp == ghb_dict_get_type()) - { - str ="dict"; - } - g_message("Type: %s", str); -} - void dump_preset_path(const gchar *msg, const GValue *path) { @@ -284,6 +273,17 @@ preset_get_name(GValue *dict) return g_value_get_string(preset_dict_get_value(dict, "PresetName")); } +static gboolean +preset_folder_is_open(GValue *dict) +{ + const GValue *gval; + + gval = preset_dict_get_value(dict, "FolderOpen"); + if (gval != NULL) + return g_value_get_boolean(gval); + return FALSE; +} + gboolean ghb_preset_folder(GValue *dict) { @@ -521,6 +521,37 @@ presets_clear_default(GValue *presets) } } +static void +presets_customize(GValue *presets) +{ + gint count, ii; + + count = ghb_array_len(presets); + for (ii = 0; ii < count; ii++) + { + GValue *dict; + gboolean folder; + gint ptype; + + dict = ghb_array_get_nth(presets, ii); + + ptype = ghb_value_int(preset_dict_get_value(dict, "Type")); + if (ptype != PRESETS_CUSTOM) + { + ghb_dict_insert(dict, g_strdup("Type"), + ghb_int64_value_new(PRESETS_CUSTOM)); + } + folder = ghb_value_boolean(preset_dict_get_value(dict, "Folder")); + if (folder) + { + GValue *nested; + + nested = ghb_dict_lookup(dict, "ChildrenArray"); + presets_customize(nested); + } + } +} + static gint* presets_find_default2(GValue *presets, gint *len) { @@ -555,7 +586,7 @@ presets_find_default2(GValue *presets, gint *len) { if (preset_is_default(dict)) { - indices = malloc(MAX_NESTED_PRESET * sizeof(gint)); + indices = g_malloc(MAX_NESTED_PRESET * sizeof(gint)); indices[*len] = ii; (*len)++; return indices; @@ -675,6 +706,20 @@ presets_set_default(gint *indices, gint len) store_presets(); } +static void +presets_set_folder_open(gboolean open, gint *indices, gint len) +{ + GValue *dict; + + g_debug("presets_set_folder_open ()"); + dict = presets_get_dict(presetsPlist, indices, len); + if (dict) + { + ghb_dict_insert(dict, g_strdup("FolderOpen"), + ghb_boolean_value_new(open)); + } +} + // Used for sorting dictionaries. gint key_cmp(gconstpointer a, gconstpointer b) @@ -862,18 +907,26 @@ preset_to_ui(signal_user_data_t *ud, GValue *dict) init_ui_from_dict(ud, internal, dict); init_ui_from_dict(ud, hidden, dict); - if (ghb_settings_get_boolean(ud->settings, "allow_tweaks")) + if (dict != NULL) { - const GValue *gval; - gval = preset_dict_get_value(dict, "PictureDeinterlace"); - if (gval) + GValue *val; + gboolean dd; + + val = ghb_dict_lookup(dict, "PictureDecombDeinterlace"); + if (val != NULL) { - ghb_ui_update(ud, "tweak_PictureDeinterlace", gval); + dd = ghb_value_boolean(val); + ghb_ui_update(ud, "PictureDeinterlaceDecomb", ghb_boolean_value(!dd)); } - gval = preset_dict_get_value(dict, "PictureDenoise"); - if (gval) + val = ghb_dict_lookup(dict, "PictureHeight"); + if (val != NULL) + { + ghb_ui_update(ud, "scale_height", val); + } + val = ghb_dict_lookup(dict, "PictureWidth"); + if (val != NULL) { - ghb_ui_update(ud, "tweak_PictureDenoise", gval); + ghb_ui_update(ud, "scale_width", val); } } } @@ -1039,7 +1092,7 @@ ghb_get_user_config_dir(gchar *subdir) gchar **split; gint ii; - split = g_strsplit(subdir, "/", -1); + split = g_strsplit(subdir, G_DIR_SEPARATOR_S, -1); for (ii = 0; split[ii] != NULL; ii++) { gchar *tmp; @@ -1086,6 +1139,135 @@ load_plist(const gchar *name) return plist; } +gboolean +ghb_lock_file(const gchar *name) +{ +#if !defined(_WIN32) + gchar *config, *path; + int fd, lock = 0; + + config = ghb_get_user_config_dir(NULL); + path = g_strdup_printf ("%s/%s", config, name); + fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd >= 0) + lock = lockf(fd, F_TLOCK, 0); + if (lock) + close(fd); + g_free(config); + g_free(path); + return !lock; +#else + return 1; +#endif +} + +void +ghb_write_pid_file() +{ +#if !defined(_WIN32) + gchar *config, *path; + pid_t pid; + FILE *fp; + int fd, lock; + + pid = getpid(); + + config = ghb_get_user_config_dir(NULL); + path = g_strdup_printf ("%s/ghb.pid.%d", config, pid); + + fp = g_fopen(path, "w"); + fprintf(fp, "%d\n", pid); + fclose(fp); + + fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + lock = lockf(fd, F_TLOCK, 0); + + g_free(config); + g_free(path); +#endif +} + +void +ghb_unlink_pid_file(int pid) +{ + gchar *config, *path; + + config = ghb_get_user_config_dir(NULL); + path = g_strdup_printf ("%s/ghb.pid.%d", config, pid); + + if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) + { + g_unlink(path); + } + + g_free(config); + g_free(path); +} + +int +ghb_find_pid_file() +{ + const gchar *file; + gchar *config; + + config = ghb_get_user_config_dir(NULL); + + if (g_file_test(config, G_FILE_TEST_IS_DIR)) + { + GDir *gdir = g_dir_open(config, 0, NULL); + file = g_dir_read_name(gdir); + while (file) + { + if (strncmp(file, "ghb.pid.", 8) == 0) + { + gchar *path; + pid_t my_pid; + int pid; + + sscanf(file, "ghb.pid.%d", &pid); + my_pid = getpid(); + if (my_pid == pid) + { + file = g_dir_read_name(gdir); + continue; + } + path = g_strdup_printf("%s/%s", config, file); + +#if !defined(_WIN32) + int fd, lock = 1; + + fd = open(path, O_RDWR); + if (fd >= 0) + { + lock = lockf(fd, F_TLOCK, 0); + } + if (lock == 0) + { + close(fd); + g_dir_close(gdir); + g_unlink(path); + g_free(path); + g_free(config); + return pid; + } + g_free(path); + close(fd); +#else + g_dir_close(gdir); + g_unlink(path); + g_free(path); + g_free(config); + return pid; +#endif + } + file = g_dir_read_name(gdir); + } + g_dir_close(gdir); + } + g_free(config); + return -1; +} + static void remove_plist(const gchar *name) { @@ -1138,14 +1320,14 @@ ghb_prefs_to_ui(signal_user_data_t *ud) // pointer will break strict-aliasing rules" while (g_hash_table_iter_next( &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval)) - { + { const GValue *value = NULL; if (dict) value = ghb_dict_lookup(dict, key); if (value == NULL) value = gval; ghb_settings_set_value(ud->settings, key, value); - } + } internal = plist_get_dict(internalPlist, "Preferences"); ghb_dict_iter_init(&iter, internal); // middle (void*) cast prevents gcc warning "defreferencing type-punned @@ -1176,13 +1358,15 @@ ghb_prefs_to_ui(signal_user_data_t *ud) ghb_ui_update(ud, "hbfd", ghb_int64_value(0)); } gval = ghb_settings_get_value(ud->settings, "default_source"); - ghb_settings_set_value (ud->settings, "source", gval); + ghb_settings_set_value (ud->settings, "scan_source", gval); + str = ghb_settings_get_string(ud->settings, "destination_dir"); + ghb_ui_update(ud, "dest_dir", ghb_string_value(str)); - gchar *path = g_strdup_printf ("%s/new_video.mp4", str); - ghb_ui_update(ud, "destination", ghb_string_value(path)); + gchar *file = g_strdup_printf ("new_video.mp4"); + ghb_ui_update(ud, "dest_file", ghb_string_value(file)); g_free(str); - g_free(path); + g_free(file); prefs_initializing = FALSE; } @@ -1206,20 +1390,43 @@ ghb_prefs_save(GValue *settings) // pointer will break strict-aliasing rules" while (g_hash_table_iter_next( &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value)) - { - value = ghb_settings_get_value(settings, key); - if (value != NULL) - { + { + value = ghb_settings_get_value(settings, key); + if (value != NULL) + { ghb_dict_insert(pref_dict, g_strdup(key), ghb_value_dup(value)); - } + } + } + store_prefs(); + prefs_modified = FALSE; +} + +void +ghb_pref_set(GValue *settings, const gchar *key) +{ + const GValue *value, *value2; + + if (prefs_initializing) return; + value = ghb_settings_get_value(settings, key); + if (value != NULL) + { + GValue *dict; + dict = plist_get_dict(prefsPlist, "Preferences"); + if (dict == NULL) return; + value2 = ghb_dict_lookup(dict, key); + if (ghb_value_cmp(value, value2) != 0) + { + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value)); + store_prefs(); + prefs_modified = TRUE; + } } - store_plist(prefsPlist, "preferences"); } void ghb_pref_save(GValue *settings, const gchar *key) { - const GValue *value; + const GValue *value, *value2; if (prefs_initializing) return; value = ghb_settings_get_value(settings, key); @@ -1228,8 +1435,23 @@ ghb_pref_save(GValue *settings, const gchar *key) GValue *dict; dict = plist_get_dict(prefsPlist, "Preferences"); if (dict == NULL) return; - ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value)); - store_plist(prefsPlist, "preferences"); + value2 = ghb_dict_lookup(dict, key); + if (ghb_value_cmp(value, value2) != 0) + { + ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(value)); + store_prefs(); + prefs_modified = FALSE; + } + } +} + +void +ghb_prefs_store(void) +{ + if (prefs_modified) + { + store_prefs(); + prefs_modified = FALSE; } } @@ -1294,6 +1516,34 @@ ghb_settings_close() ghb_value_free(prefsPlist); } +#if defined(_WIN32) +gchar* +FindFirstCDROM(void) +{ + gint ii, drives; + gchar drive[5]; + + strcpy(drive, "A:" G_DIR_SEPARATOR_S); + drives = GetLogicalDrives(); + for (ii = 0; ii < 26; ii++) + { + if (drives & 0x01) + { + guint dtype; + + drive[0] = 'A' + ii; + dtype = GetDriveType(drive); + if (dtype == DRIVE_CDROM) + { + return g_strdup(drive); + } + } + drives >>= 1; + } + return NULL; +} +#endif + void ghb_prefs_load(signal_user_data_t *ud) { @@ -1308,29 +1558,53 @@ ghb_prefs_load(signal_user_data_t *ud) prefsPlist = ghb_dict_value_new(); dict = plist_get_dict(prefsPlist, "Preferences"); internal = plist_get_dict(internalPlist, "Preferences"); - if (dict == NULL && internal) - { + if (dict == NULL && internal) + { dict = ghb_dict_value_new(); ghb_dict_insert(prefsPlist, g_strdup("Preferences"), dict); - // Get defaults from internal defaults + // Get defaults from internal defaults ghb_dict_iter_init(&iter, internal); // middle (void*) cast prevents gcc warning "defreferencing type-punned // pointer will break strict-aliasing rules" while (g_hash_table_iter_next( &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval)) - { + { ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(gval)); - } - const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); + } + + const gchar *dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); + if (dir == NULL) + { + dir = "."; + } + ghb_dict_insert(dict, + g_strdup("ExportDirectory"), ghb_value_dup(ghb_string_value(dir))); + + dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); if (dir == NULL) { dir = "."; } ghb_dict_insert(dict, g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir))); - store_plist(prefsPlist, "preferences"); - } + + ghb_dict_insert(dict, + g_strdup("SrtDir"), ghb_value_dup(ghb_string_value(dir))); +#if defined(_WIN32) + gchar *source; + + source = FindFirstCDROM(); + if (source == NULL) + { + source = g_strdup("C:" G_DIR_SEPARATOR_S); + } + ghb_dict_insert(dict, g_strdup("default_source"), + ghb_value_dup(ghb_string_value(source))); + g_free(source); +#endif + store_prefs(); + } // Read legacy default_preset preference and update accordingly path = ghb_dict_lookup(dict, "default_preset"); if (path) @@ -1355,7 +1629,7 @@ ghb_prefs_load(signal_user_data_t *ud) g_free(indices); } ghb_dict_remove(dict, "default_preset"); - store_plist(prefsPlist, "preferences"); + store_prefs(); } } @@ -1447,6 +1721,7 @@ ghb_presets_list_init( 2, def ? 2 : 0, 3, color, 4, description, + 5, type == PRESETS_BUILTIN ? 0 : 1, -1); if (def && piter) { @@ -1467,6 +1742,20 @@ ghb_presets_list_init( if (folder) { ghb_presets_list_init(ud, more_indices, len+1); + if (preset_folder_is_open(dict)) + { + GtkTreePath *path; + + if (piter != NULL) + { + path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), piter); + gtk_tree_view_expand_row(treeview, path, FALSE); + gtk_tree_path_free(path); + } + path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); + gtk_tree_view_expand_row(treeview, path, FALSE); + gtk_tree_path_free(path); + } } } g_free(more_indices); @@ -1476,7 +1765,8 @@ static void presets_list_update_item( signal_user_data_t *ud, gint *indices, - gint len) + gint len, + gboolean recurse) { GtkTreeView *treeview; GtkTreeStore *store; @@ -1510,8 +1800,9 @@ presets_list_update_item( 2, def ? 2 : 0, 3, color, 4, description, + 5, type == PRESETS_BUILTIN ? 0 : 1, -1); - if (folder) + if (recurse && folder) { ghb_presets_list_init(ud, indices, len); } @@ -1574,6 +1865,7 @@ presets_list_insert( 2, def ? 2 : 0, 3, color, 4, description, + 5, type == PRESETS_BUILTIN ? 0 : 1, -1); if (folder) { @@ -1631,19 +1923,61 @@ remove_std_presets(signal_user_data_t *ud) void ghb_save_queue(GValue *queue) { - store_plist(queue, "queue"); + pid_t pid; + char *path; + + pid = getpid(); + path = g_strdup_printf ("queue.%d", pid); + store_plist(queue, path); + g_free(path); } GValue* ghb_load_queue() { - return load_plist("queue"); + GValue *queue; + pid_t pid; + char *path; + + pid = getpid(); + path = g_strdup_printf ("queue.%d", pid); + queue = load_plist(path); + g_free(path); + return queue; +} + +GValue* +ghb_load_old_queue(int pid) +{ + GValue *queue; + char *path; + + path = g_strdup_printf ("queue.%d", pid); + queue = load_plist(path); + g_free(path); + return queue; +} + +void +ghb_remove_old_queue_file(int pid) +{ + char *path; + + path = g_strdup_printf ("queue.%d", pid); + remove_plist(path); + g_free(path); } void ghb_remove_queue_file() { - remove_plist("queue"); + pid_t pid; + char *path; + + pid = getpid(); + path = g_strdup_printf ("queue.%d", pid); + remove_plist(path); + g_free(path); } typedef struct @@ -1655,7 +1989,7 @@ typedef struct static value_map_t vcodec_xlat[] = { {"MPEG-4 (FFmpeg)", "ffmpeg"}, - {"MPEG-4 (XviD)", "xvid"}, + {"MPEG-4 (XviD)", "ffmpeg"}, {"H.264 (x264)", "x264"}, {"VP3 (Theora)", "theora"}, {NULL,NULL} @@ -1664,7 +1998,9 @@ static value_map_t vcodec_xlat[] = static value_map_t acodec_xlat[] = { {"AAC (faac)", "faac"}, - {"AC3 Passthru", "ac3"}, + {"AAC (CoreAudio)", "faac"}, + {"AC3 Passthru", "ac3pass"}, + {"DTS Passthru", "dtspass"}, {"MP3 (lame)", "lame"}, {"Vorbis (vorbis)", "vorbis"}, {NULL,NULL} @@ -1673,10 +2009,10 @@ static value_map_t acodec_xlat[] = value_map_t container_xlat[] = { {"MP4 file", "mp4"}, - {"M4V file", "m4v"}, + {"M4V file", "mp4"}, {"MKV file", "mkv"}, - {"AVI file", "avi"}, - {"OGM file", "ogm"}, + {"AVI file", "mkv"}, + {"OGM file", "mkv"}, {NULL, NULL} }; @@ -1687,10 +2023,10 @@ value_map_t framerate_xlat[] = {"10", "10"}, {"12", "12"}, {"15", "15"}, - {"23.976", "23.976"}, + {"23.976 (NTSC Film)", "23.976"}, {"24", "24"}, - {"25", "25"}, - {"29.97", "29.97"}, + {"25 (PAL Film/Video)", "25"}, + {"29.97 (NTSC Video)", "29.97"}, {NULL, NULL} }; @@ -1718,19 +2054,37 @@ value_map_t mix_xlat[] = value_map_t deint_xlat[] = { - {"0", "none"}, - {"1", "fast"}, - {"2", "slow"}, - {"3", "slower"}, + {"0", "off"}, + {"1", "custom"}, + {"2", "fast"}, + {"3", "slow"}, + {"4", "slower"}, {NULL, NULL} }; value_map_t denoise_xlat[] = { - {"0", "none"}, - {"1", "weak"}, - {"2", "medium"}, - {"3", "strong"}, + {"0", "off"}, + {"1", "custom"}, + {"2", "weak"}, + {"3", "medium"}, + {"4", "strong"}, + {NULL, NULL} +}; + +value_map_t detel_xlat[] = +{ + {"0", "off"}, + {"1", "custom"}, + {"2", "default"}, + {NULL, NULL} +}; + +value_map_t decomb_xlat[] = +{ + {"0", "off"}, + {"1", "custom"}, + {"2", "default"}, {NULL, NULL} }; @@ -1750,7 +2104,14 @@ export_lang_xlat2(GValue *lin_val) { if (strcmp(str, ghb_language_table[ii].iso639_2) == 0) { - gval = ghb_string_value_new(ghb_language_table[ii].eng_name); + const gchar *lang; + + if (ghb_language_table[ii].native_name[0] != 0) + lang = ghb_language_table[ii].native_name; + else + lang = ghb_language_table[ii].eng_name; + + gval = ghb_string_value_new(lang); g_free(str); return gval; } @@ -1796,7 +2157,8 @@ import_lang_xlat2(GValue *mac_val) str = ghb_value_string(mac_val); for (ii = 0; ghb_language_table[ii].eng_name; ii++) { - if (strcmp(str, ghb_language_table[ii].eng_name) == 0) + if ((strcmp(str, ghb_language_table[ii].eng_name) == 0) || + (strcmp(str, ghb_language_table[ii].native_name) == 0)) { gval = ghb_string_value_new(ghb_language_table[ii].iso639_2); g_free(str); @@ -1931,37 +2293,53 @@ export_value_xlat(GValue *dict) gval = export_value_xlat2(framerate_xlat, lin_val, G_TYPE_STRING); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); + key = "PictureDetelecine"; + lin_val = ghb_dict_lookup(dict, key); + gval = export_value_xlat2(detel_xlat, lin_val, G_TYPE_INT); + if (gval) + ghb_dict_insert(dict, g_strdup(key), gval); + key = "PictureDecomb"; + lin_val = ghb_dict_lookup(dict, key); + gval = export_value_xlat2(decomb_xlat, lin_val, G_TYPE_INT); + if (gval) + ghb_dict_insert(dict, g_strdup(key), gval); key = "PictureDeinterlace"; lin_val = ghb_dict_lookup(dict, key); gval = export_value_xlat2(deint_xlat, lin_val, G_TYPE_INT); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); - else - ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(lin_val)); key = "PictureDenoise"; lin_val = ghb_dict_lookup(dict, key); gval = export_value_xlat2(denoise_xlat, lin_val, G_TYPE_INT); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); - else - ghb_dict_insert(dict, g_strdup(key), ghb_value_dup(lin_val)); - key = "Subtitles"; - lin_val = ghb_dict_lookup(dict, key); - gval = export_subtitle_xlat2(lin_val); - if (gval) - ghb_dict_insert(dict, g_strdup(key), gval); - GValue *alist; - GValue *adict; + GValue *slist; + GValue *sdict; gint count, ii; - alist = ghb_dict_lookup(dict, "AudioList"); - count = ghb_array_len(alist); + slist = ghb_dict_lookup(dict, "SubtitleList"); + count = ghb_array_len(slist); for (ii = 0; ii < count; ii++) { - adict = ghb_array_get_nth(alist, ii); - key = "AudioTrack"; - lin_val = ghb_dict_lookup(adict, key); + sdict = ghb_array_get_nth(slist, ii); + key = "SubtitleLanguage"; + lin_val = ghb_dict_lookup(sdict, key); + gval = export_subtitle_xlat2(lin_val); + if (gval) + ghb_dict_insert(sdict, g_strdup(key), gval); + } + + GValue *alist; + GValue *adict; + + alist = ghb_dict_lookup(dict, "AudioList"); + count = ghb_array_len(alist); + for (ii = 0; ii < count; ii++) + { + adict = ghb_array_get_nth(alist, ii); + key = "AudioTrack"; + lin_val = ghb_dict_lookup(adict, key); gval = export_audio_track_xlat2(lin_val); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); @@ -2020,13 +2398,34 @@ import_value_xlat2( return gval; } } - //g_warning("Can't map value: (%s)", str); g_free(str); } else { - g_warning("Bad key: (%s)", key); - return NULL; + gint ii; + gchar *str; + GValue *sval; + + str = ghb_value_string(mac_val); + for (ii = 0; value_map[ii].mac_val; ii++) + { + if (strcmp(str, value_map[ii].mac_val) == 0) + { + sval = ghb_string_value_new(value_map[ii].lin_val); + g_free(str); + gval = ghb_value_new(G_VALUE_TYPE(mac_val)); + if (!g_value_transform(sval, gval)) + { + g_warning("can't transform"); + ghb_value_free(gval); + ghb_value_free(sval); + return NULL; + } + ghb_value_free(sval); + return gval; + } + } + g_free(str); } return NULL; } @@ -2053,6 +2452,16 @@ import_value_xlat(GValue *dict) gval = import_value_xlat2(defaults, framerate_xlat, key, mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); + key = "PictureDetelecine"; + mac_val = ghb_dict_lookup(dict, key); + gval = import_value_xlat2(defaults, detel_xlat, key, mac_val); + if (gval) + ghb_dict_insert(dict, g_strdup(key), gval); + key = "PictureDecomb"; + mac_val = ghb_dict_lookup(dict, key); + gval = import_value_xlat2(defaults, decomb_xlat, key, mac_val); + if (gval) + ghb_dict_insert(dict, g_strdup(key), gval); key = "PictureDeinterlace"; mac_val = ghb_dict_lookup(dict, key); gval = import_value_xlat2(defaults, deint_xlat, key, mac_val); @@ -2063,19 +2472,85 @@ import_value_xlat(GValue *dict) gval = import_value_xlat2(defaults, denoise_xlat, key, mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); - key = "Subtitles"; - mac_val = ghb_dict_lookup(dict, key); - gval = import_subtitle_xlat2(mac_val); - if (gval) - ghb_dict_insert(dict, g_strdup(key), gval); + + + GValue *sdeflist; + GValue *sdefaults; + GValue *slist; + GValue *sdict; + gint count, ii; + + sdeflist = ghb_dict_lookup(defaults, "SubtitleList"); + if (sdeflist) + { + slist = ghb_dict_lookup(dict, "SubtitleList"); + if (slist) + { + sdefaults = ghb_array_get_nth(sdeflist, 0); + count = ghb_array_len(slist); + for (ii = 0; ii < count; ii++) + { + sdict = ghb_array_get_nth(slist, ii); + key = "SubtitleLanguage"; + mac_val = ghb_dict_lookup(sdict, key); + gval = import_subtitle_xlat2(mac_val); + if (gval) + ghb_dict_insert(sdict, g_strdup(key), gval); + } + + } + else + { + key = "Subtitles"; + mac_val = ghb_dict_lookup(dict, key); + slist = ghb_array_value_new(8); + ghb_dict_insert(dict, g_strdup("SubtitleList"), slist); + if (mac_val) + { + gchar *lang; + + gval = import_subtitle_xlat2(mac_val); + lang = ghb_value_string(gval); + if (lang && strcasecmp(lang, "none") != 0 && !slist) + { + sdict = ghb_dict_value_new(); + ghb_array_append(slist, sdict); + ghb_dict_insert(sdict, g_strdup("SubtitleLanguage"), gval); + gval = ghb_dict_lookup(dict, "SubtitlesForced"); + if (gval != NULL) + { + ghb_dict_insert(sdict, g_strdup("SubtitleForced"), + ghb_value_dup(gval)); + } + else + { + ghb_dict_insert(sdict, g_strdup("SubtitleForced"), + ghb_boolean_value_new(FALSE)); + } + ghb_dict_insert(sdict, g_strdup("SubtitleBurned"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(sdict, g_strdup("SubtitleDefaultTrack"), + ghb_boolean_value_new(FALSE)); + } + else + { + ghb_value_free(gval); + } + if (lang) + g_free(lang); + } + } + } + ghb_dict_remove(dict, "Subtitles"); + ghb_dict_remove(dict, "SubtitlesForced"); + GValue *alist; GValue *adict; GValue *adefaults; GValue *adeflist; - gint count, ii; - adeflist = ghb_dict_lookup(dict, "AudioList"); + adeflist = ghb_dict_lookup(defaults, "AudioList"); if (adeflist) { adefaults = ghb_array_get_nth(adeflist, 0); @@ -2104,6 +2579,18 @@ import_value_xlat(GValue *dict) gval = import_value_xlat2(adefaults, mix_xlat, key, mac_val); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); + + mac_val = ghb_dict_lookup(adict, "AudioTrackDRCSlider"); + if (mac_val != NULL) + { + gdouble drc; + drc = ghb_value_double(mac_val); + if (drc < 1.0 && drc > 0.0) + { + ghb_dict_insert(adict, g_strdup("AudioTrackDRCSlider"), + ghb_double_value_new(0.0)); + } + } } } } @@ -2133,50 +2620,41 @@ import_xlat_preset(GValue *dict) { case 0: { - ghb_dict_insert(dict, g_strdup("anamorphic"), - ghb_boolean_value_new(FALSE)); - if (ghb_dict_lookup(dict, "ModDimensions") == NULL) - ghb_dict_insert(dict, g_strdup("ModDimensions"), - ghb_boolean_value_new(TRUE)); + if (ghb_dict_lookup(dict, "PictureModulus") == NULL) + ghb_dict_insert(dict, g_strdup("PictureModulus"), + ghb_int_value_new(16)); } break; case 1: { - ghb_dict_insert(dict, g_strdup("anamorphic"), - ghb_boolean_value_new(TRUE)); - ghb_dict_insert(dict, g_strdup("ModDimensions"), - ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("PictureModulus"), + ghb_int_value_new(1)); } break; case 2: { - ghb_dict_insert(dict, g_strdup("anamorphic"), - ghb_boolean_value_new(TRUE)); - ghb_dict_insert(dict, g_strdup("ModDimensions"), - ghb_boolean_value_new(TRUE)); + if (ghb_dict_lookup(dict, "PictureModulus") == NULL) + ghb_dict_insert(dict, g_strdup("PictureModulus"), + ghb_int_value_new(16)); } break; default: { - ghb_dict_insert(dict, g_strdup("anamorphic"), - ghb_boolean_value_new(TRUE)); - ghb_dict_insert(dict, g_strdup("ModDimensions"), - ghb_boolean_value_new(TRUE)); + if (ghb_dict_lookup(dict, "PictureModulus") == NULL) + ghb_dict_insert(dict, g_strdup("PictureModulus"), + ghb_int_value_new(16)); } break; } // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant + // *note: target is no longer used switch (vqtype) { case 0: { - ghb_dict_insert(dict, g_strdup("vquality_type_target"), - ghb_boolean_value_new(TRUE)); ghb_dict_insert(dict, g_strdup("vquality_type_bitrate"), - ghb_boolean_value_new(FALSE)); + ghb_boolean_value_new(TRUE)); ghb_dict_insert(dict, g_strdup("vquality_type_constant"), ghb_boolean_value_new(FALSE)); } break; case 1: { - ghb_dict_insert(dict, g_strdup("vquality_type_target"), - ghb_boolean_value_new(FALSE)); ghb_dict_insert(dict, g_strdup("vquality_type_bitrate"), ghb_boolean_value_new(TRUE)); ghb_dict_insert(dict, g_strdup("vquality_type_constant"), @@ -2184,8 +2662,6 @@ import_xlat_preset(GValue *dict) } break; case 2: { - ghb_dict_insert(dict, g_strdup("vquality_type_target"), - ghb_boolean_value_new(FALSE)); ghb_dict_insert(dict, g_strdup("vquality_type_bitrate"), ghb_boolean_value_new(FALSE)); ghb_dict_insert(dict, g_strdup("vquality_type_constant"), @@ -2193,15 +2669,122 @@ import_xlat_preset(GValue *dict) } break; default: { - ghb_dict_insert(dict, g_strdup("vquality_type_target"), - ghb_boolean_value_new(FALSE)); ghb_dict_insert(dict, g_strdup("vquality_type_bitrate"), ghb_boolean_value_new(FALSE)); ghb_dict_insert(dict, g_strdup("vquality_type_constant"), ghb_boolean_value_new(TRUE)); } break; } + import_value_xlat(dict); + + GValue *mode = ghb_dict_lookup(dict, "VideoFramerateMode"); + if (mode == NULL) + { + GValue *fr = ghb_dict_lookup(dict, "VideoFramerate"); + if (fr) + { + gchar *str; + gboolean pfr = FALSE; + GValue *pfr_val = ghb_dict_lookup(dict, "VideoFrameratePFR"); + if (pfr_val) + { + pfr = ghb_value_boolean(pfr_val); + } + str = ghb_value_string(fr); + if (strcmp(str, "source") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(TRUE)); + } + else if (!pfr) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + g_free(str); + } + } + else + { + gchar *str; + str = ghb_value_string(mode); + if (strcmp(str, "cfr") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else if (strcmp(str, "pfr") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(TRUE)); + } + g_free(str); + } + + gdouble vquality; + const GValue *gval; + + vquality = ghb_value_double(preset_dict_get_value(dict, "VideoQualitySlider")); + if (vquality > 0.0 && vquality < 1.0) + { + gint vcodec; + + gval = preset_dict_get_value(dict, "VideoEncoder"); + vcodec = ghb_lookup_combo_int("VideoEncoder", gval); + switch (vcodec) + { + case HB_VCODEC_X264: + { + vquality = 51. - vquality * 51.; + } break; + + case HB_VCODEC_FFMPEG: + { + vquality = 31. - vquality * 30.; + } break; + + case HB_VCODEC_THEORA: + { + vquality = vquality * 63.; + } break; + + default: + { + vquality = 0.; + } break; + } + ghb_dict_insert(dict, g_strdup("VideoQualitySlider"), + ghb_double_value_new(vquality)); + } } static void @@ -2235,14 +2818,10 @@ import_xlat_presets(GValue *presets) static void export_xlat_preset(GValue *dict) { - gboolean ana, round, autoscale, target, br, constant; + gboolean autoscale, br, constant; g_debug("export_xlat_prest ()"); autoscale = ghb_value_boolean(preset_dict_get_value(dict, "autoscale")); - ana = ghb_value_boolean(preset_dict_get_value(dict, "anamorphic")); - round = ghb_value_boolean(preset_dict_get_value(dict, "ModDimensions")); - target = ghb_value_boolean( - preset_dict_get_value(dict, "vquality_type_target")); br = ghb_value_boolean( preset_dict_get_value(dict, "vquality_type_bitrate")); constant = ghb_value_boolean( @@ -2255,41 +2834,73 @@ export_xlat_preset(GValue *dict) ghb_dict_insert(dict, g_strdup("UsesPictureSettings"), ghb_int_value_new(1)); - if (ana) + // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant + // *note: target is no longer used + if (br) { - if (round) - ghb_dict_insert(dict, g_strdup("PicturePAR"), - ghb_int_value_new(2)); - else - ghb_dict_insert(dict, g_strdup("PicturePAR"), + ghb_dict_insert(dict, g_strdup("VideoQualityType"), ghb_int_value_new(1)); } - else + else if (constant) { - ghb_dict_insert(dict, g_strdup("PicturePAR"), - ghb_int_value_new(0)); + ghb_dict_insert(dict, g_strdup("VideoQualityType"), + ghb_int_value_new(2)); } - // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant - if (target) + + if (ghb_value_boolean(preset_dict_get_value(dict, "VideoFramerateCFR"))) { - ghb_dict_insert(dict, g_strdup("VideoQualityType"), - ghb_int_value_new(0)); + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("cfr")); } - else if (br) + else if (ghb_value_boolean(preset_dict_get_value(dict, "VideoFrameratePFR"))) { - ghb_dict_insert(dict, g_strdup("VideoQualityType"), - ghb_int_value_new(1)); + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("pfr")); } - else if (constant) + else { - ghb_dict_insert(dict, g_strdup("VideoQualityType"), - ghb_int_value_new(2)); + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("vfr")); + } + + GValue *alist, *adict; + gint count, ii; + + alist = ghb_dict_lookup(dict, "AudioList"); + count = ghb_array_len(alist); + for (ii = 0; ii < count; ii++) + { + gdouble drc; + + adict = ghb_array_get_nth(alist, ii); + drc = ghb_value_double( + preset_dict_get_value(adict, "AudioTrackDRCSlider")); + if (drc < 1.0 && drc > 0.0) + { + ghb_dict_insert(adict, g_strdup("AudioTrackDRCSlider"), + ghb_double_value_new(0.0)); + } } - ghb_dict_remove(dict, "autoscale"); - ghb_dict_remove(dict, "anamorphic"); - ghb_dict_remove(dict, "vquality_type_target"); - ghb_dict_remove(dict, "vquality_type_bitrate"); - ghb_dict_remove(dict, "vquality_type_constant"); + + GValue *internal; + GHashTableIter iter; + gchar *key; + GValue *value; + internal = plist_get_dict(internalPlist, "XlatPresets"); + ghb_dict_iter_init(&iter, internal); + // middle (void*) cast prevents gcc warning "defreferencing type-punned + // pointer will break strict-aliasing rules" + while (g_hash_table_iter_next( + &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value)) + { + ghb_dict_remove(dict, key); + } + + // remove obsolete keys + ghb_dict_remove(dict, "UsesMaxPictureSettings"); + ghb_dict_remove(dict, "VFR"); + ghb_dict_remove(dict, "VideoFrameratePFR"); + export_value_xlat(dict); } @@ -2320,6 +2931,16 @@ export_xlat_presets(GValue *presets) } } +static guint prefs_timeout_id = 0; + +static gboolean +delayed_store_prefs(gpointer data) +{ + store_plist(prefsPlist, "preferences"); + prefs_timeout_id = 0; + return FALSE; +} + static void store_presets() { @@ -2331,6 +2952,22 @@ store_presets() ghb_value_free(export); } +static void +store_prefs(void) +{ + if (prefs_timeout_id != 0) + { + GMainContext *mc; + GSource *source; + + mc = g_main_context_default(); + source = g_main_context_find_source_by_id(mc, prefs_timeout_id); + if (source != NULL) + g_source_destroy(source); + } + prefs_timeout_id = g_timeout_add_seconds(1, (GSourceFunc)delayed_store_prefs, NULL); +} + void ghb_presets_reload(signal_user_data_t *ud) { @@ -2343,7 +2980,7 @@ ghb_presets_reload(signal_user_data_t *ud) if (std_presets == NULL) return; remove_std_presets(ud); - indices = presets_find_default(presetsPlist, &len); + indices = presets_find_default(presetsPlist, &len); if (indices) { presets_clear_default(std_presets); @@ -2359,6 +2996,8 @@ ghb_presets_reload(signal_user_data_t *ud) std_dict = ghb_array_get_nth(std_presets, ii); copy_dict = ghb_value_dup(std_dict); + ghb_dict_insert(copy_dict, g_strdup("PresetBuildNumber"), + ghb_int64_value_new(hb_get_build(NULL))); ghb_presets_insert(presetsPlist, copy_dict, &indices, 1); presets_list_insert(ud, &indices, 1); } @@ -2385,8 +3024,102 @@ check_old_presets() return FALSE; } +static void +replace_standard_presets() +{ + GValue *std_presets; + int *indices, len; + gint count, ii; + + count = ghb_array_len(presetsPlist); + for (ii = count-1; ii >= 0; ii--) + { + GValue *dict; + gint ptype; + + dict = ghb_array_get_nth(presetsPlist, ii); + ptype = ghb_value_int(preset_dict_get_value(dict, "Type")); + if (ptype == PRESETS_BUILTIN) + { + gint indices = 0; + ghb_presets_remove(presetsPlist, &indices, 1); + } + } + + std_presets = ghb_resource_get("standard-presets"); + if (std_presets == NULL) return; + + indices = presets_find_default(presetsPlist, &len); + if (indices) + { + presets_clear_default(std_presets); + g_free(indices); + } + // Merge the keyfile contents into our presets + count = ghb_array_len(std_presets); + for (ii = count-1; ii >= 0; ii--) + { + GValue *std_dict; + GValue *copy_dict; + gint indices = 0; + + std_dict = ghb_array_get_nth(std_presets, ii); + copy_dict = ghb_value_dup(std_dict); + ghb_dict_insert(copy_dict, g_strdup("PresetBuildNumber"), + ghb_int64_value_new(hb_get_build(NULL))); + ghb_presets_insert(presetsPlist, copy_dict, &indices, 1); + } + import_xlat_presets(presetsPlist); + store_presets(); +} + +static void +update_standard_presets(signal_user_data_t *ud) +{ + gint count, ii; + + count = ghb_array_len(presetsPlist); + for (ii = count-1; ii >= 0; ii--) + { + GValue *dict; + const GValue *gval; + gint64 build; + gint type; + + dict = ghb_array_get_nth(presetsPlist, ii); + gval = ghb_dict_lookup(dict, "Type"); + if (gval == NULL) + { + // Old preset that doesn't have a Type + replace_standard_presets(); + return; + } + + type = ghb_value_int(gval); + if (type == 0) + { + gval = ghb_dict_lookup(dict, "PresetBuildNumber"); + if (gval == NULL) + { + // Old preset that doesn't have a build number + replace_standard_presets(); + return; + } + + build = ghb_value_int64(gval); + if (build != hb_get_build(NULL)) + { + // Build number does not match + replace_standard_presets(); + return; + } + } + } + return; +} + void -ghb_presets_load() +ghb_presets_load(signal_user_data_t *ud) { presetsPlist = load_plist("presets"); if (presetsPlist == NULL) @@ -2409,6 +3142,7 @@ ghb_presets_load() import_xlat_presets(presetsPlist); store_presets(); } + update_standard_presets(ud); import_xlat_presets(presetsPlist); } @@ -2419,8 +3153,8 @@ settings_save(signal_user_data_t *ud, const GValue *path) GHashTableIter iter; gchar *key; GValue *value; - gboolean autoscale; gint *indices, len, count; + gint *def_indices, def_len; const gchar *name; gboolean replace = FALSE; @@ -2460,25 +3194,9 @@ settings_save(signal_user_data_t *ud, const GValue *path) return; } } - - if (ghb_settings_get_boolean(ud->settings, "allow_tweaks")) - { - gchar *str; - str = ghb_settings_get_string(ud->settings, "tweak_PictureDeinterlace"); - if (str) - { - ghb_settings_set_string(ud->settings, "PictureDeinterlace", str); - g_free(str); - } - str = ghb_settings_get_string(ud->settings, "tweak_PictureDenoise"); - if (str) - { - ghb_settings_set_string(ud->settings, "PictureDenoise", str); - g_free(str); - } - } - autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); + current_preset = dict; ghb_settings_set_int64(ud->settings, "Type", PRESETS_CUSTOM); + ghb_settings_set_int64(ud->settings, "PresetBuildNumber", hb_get_build(NULL)); internal = plist_get_dict(internalPlist, "Presets"); ghb_dict_iter_init(&iter, internal); @@ -2488,21 +3206,8 @@ settings_save(signal_user_data_t *ud, const GValue *path) &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value)) { const GValue *gval; - gchar *key2; - key2 = key; - if (!autoscale) - { - if (strcmp(key, "PictureWidth") == 0) - { - key2 = "scale_width"; - } - else if (strcmp(key, "PictureHeight") == 0) - { - key2 = "scale_height"; - } - } - gval = ghb_settings_get_value(ud->settings, key2); + gval = ghb_settings_get_value(ud->settings, key); if (gval == NULL) { continue; @@ -2527,13 +3232,36 @@ settings_save(signal_user_data_t *ud, const GValue *path) } ghb_dict_insert(dict, g_strdup("PresetName"), ghb_string_value_new(name)); if (replace) - presets_list_update_item(ud, indices, len); + { + def_indices = presets_find_default(presetsPlist, &def_len); + if (def_indices != NULL && + preset_path_cmp(indices, len, def_indices, def_len) != 0) + { + ghb_dict_insert(dict, g_strdup("Default"), + ghb_boolean_value_new(FALSE)); + } + presets_list_update_item(ud, indices, len, FALSE); + } else { ghb_dict_insert(dict, g_strdup("Default"), ghb_boolean_value_new(FALSE)); presets_list_insert(ud, indices, len); } + if (!ghb_settings_get_boolean( ud->settings, "PictureWidthEnable")) + { + ghb_dict_remove(dict, "PictureWidth"); + } + if (!ghb_settings_get_boolean( ud->settings, "PictureHeightEnable")) + { + ghb_dict_remove(dict, "PictureHeight"); + } + ghb_dict_insert(dict, g_strdup("autoscale"), + ghb_boolean_value_new( + !ghb_settings_get_boolean( ud->settings, "PictureWidthEnable") && + !ghb_settings_get_boolean( ud->settings, "PictureHeightEnable") + ) + ); store_presets(); ud->dont_clear_presets = TRUE; // Make the new preset the selected item @@ -2572,7 +3300,9 @@ folder_save(signal_user_data_t *ud, const GValue *path) ghb_dict_insert(dict, g_strdup("PresetDescription"), ghb_value_dup(preset_dict_get_value( ud->settings, "PresetDescription"))); + presets_list_update_item(ud, indices, len, FALSE); g_free(indices); + store_presets(); return; } else @@ -2622,88 +3352,355 @@ ghb_presets_list_default(signal_user_data_t *ud) treepath = ghb_tree_path_new_from_indices(indices, len); if (treepath) { - if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath)) + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath)) + { + gtk_tree_store_set(store, &iter, + 1, 800, + 2, 2 , + -1); + } + gtk_tree_path_free(treepath); + } + g_free(indices); +} + +void +ghb_presets_list_clear_default(signal_user_data_t *ud) +{ + GtkTreeView *treeview; + GtkTreePath *treepath; + GtkTreeIter iter; + GtkTreeStore *store; + gint *indices, len; + + g_debug("ghb_presets_list_clear_default ()"); + treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list")); + store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); + indices = presets_find_default(presetsPlist, &len); + if (indices == NULL) return; + treepath = ghb_tree_path_new_from_indices(indices, len); + if (treepath) + { + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath)) + { + gtk_tree_store_set(store, &iter, + 1, 400, + 2, 0 , + -1); + } + gtk_tree_path_free(treepath); + } + g_free(indices); +} + +static void +update_audio_presets(signal_user_data_t *ud) +{ + g_debug("update_audio_presets"); + const GValue *audio_list; + + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + ghb_settings_set_value(ud->settings, "AudioList", audio_list); +} + +static void +update_subtitle_presets(signal_user_data_t *ud) +{ + g_debug("update_subtitle_presets"); + const GValue *subtitle_list, *subtitle; + GValue *slist, *dict; + gint count, ii, source; + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + slist = ghb_array_value_new(8); + count = ghb_array_len(subtitle_list); + for (ii = 0; ii < count; ii++) + { + subtitle = ghb_array_get_nth(subtitle_list, ii); + source = ghb_settings_get_int(subtitle, "SubtitleSource"); + if (source != SRTSUB) + { + dict = ghb_value_dup(subtitle); + ghb_array_append(slist, dict); + } + } + ghb_settings_take_value(ud->settings, "SubtitleList", slist); +} + +G_MODULE_EXPORT void +presets_menu_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkMenu *menu; + + menu = GTK_MENU(GHB_WIDGET(ud->builder, "presets_menu")); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 1, + gtk_get_current_event_time()); +} + +G_MODULE_EXPORT void +preset_import_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkWidget *dialog; + GtkResponseType response; + gchar *exportDir; + gchar *filename; + GtkFileFilter *filter; + + g_debug("preset_import_clicked_cb ()"); + + dialog = gtk_file_chooser_dialog_new("Import Preset", NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "All (*)"); + gtk_file_filter_add_pattern(filter, "*"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name(filter, "Presets (*.plist)"); + gtk_file_filter_add_pattern(filter, "*.plist"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + if (exportDir == NULL || exportDir[0] == '\0') + { + exportDir = g_strdup("."); + } + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), exportDir); + g_free(exportDir); + + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response == GTK_RESPONSE_ACCEPT) + { + GValue *dict, *array; + gchar *dir; + gint count, ii; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + // import the preset + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + { + gtk_widget_destroy(dialog); + g_free(filename); + return; + } + array = ghb_plist_parse_file(filename); + + import_xlat_presets(array); + presets_clear_default(array); + presets_customize(array); + + count = ghb_array_len(array); + for (ii = 0; ii < count; ii++) + { + GValue *path, *name; + gint *indices, len; + gint index = 1; + + dict = ghb_array_get_nth(array, ii); + path = ghb_array_value_new(1); + name = ghb_value_dup(ghb_dict_lookup(dict, "PresetName")); + ghb_array_append(path, name); + indices = ghb_preset_indices_from_path(presetsPlist, path, &len); + // Modify the preset name till we make it unique + while (indices != NULL) + { + gchar *str = ghb_value_string(name); + + ghb_value_free(path); + g_free(indices); + + str = g_strdup_printf("%s %d", str, index); + path = ghb_array_value_new(1); + name = ghb_string_value_new(str); + ghb_array_append(path, name); + g_free(str); + + index++; + indices = ghb_preset_indices_from_path(presetsPlist, path, &len); + } + ghb_dict_insert(dict, g_strdup("PresetName"), ghb_value_dup(name)); + indices = presets_find_pos(path, PRESETS_CUSTOM, &len); + ghb_presets_insert(presetsPlist, ghb_value_dup(dict), indices, len); + presets_list_insert(ud, indices, len); + ghb_value_free(path); + } + ghb_value_free(array); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + dir = g_path_get_dirname(filename); + if (strcmp(dir, exportDir) != 0) + { + ghb_settings_set_string(ud->settings, "ExportDirectory", dir); + ghb_pref_save(ud->settings, "ExportDirectory"); + } + g_free(filename); + g_free(exportDir); + g_free(dir); + store_presets(); + } + gtk_widget_destroy(dialog); +} + +G_MODULE_EXPORT void +preset_export_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + GtkWidget *dialog; + GtkResponseType response; + GValue *preset; + const gchar *name = ""; + gint count, *indices, len; + gchar *exportDir; + gchar *filename; + + g_debug("preset_export_clicked_cb ()"); + preset = ghb_settings_get_value (ud->settings, "preset_selection"); + if (preset == NULL) + return; + + count = ghb_array_len(preset); + if (count <= 0) + return; + + name = g_value_get_string(ghb_array_get_nth(preset, count-1)); + + dialog = gtk_file_chooser_dialog_new("Export Preset", NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + if (exportDir == NULL || exportDir[0] == '\0') + { + exportDir = g_strdup("."); + } + filename = g_strdup_printf("%s.plist", name); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), exportDir); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); + g_free(filename); + g_free(exportDir); + + indices = ghb_preset_indices_from_path(presetsPlist, preset, &len); + if (indices == NULL) + return; + + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response == GTK_RESPONSE_ACCEPT) + { + GValue *export, *dict, *array; + FILE *file; + gchar *dir; + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + // export the preset + dict = presets_get_dict(presetsPlist, indices, len); + + export = ghb_value_dup(dict); + array = ghb_array_value_new(1); + ghb_array_append(array, export); + presets_clear_default(array); + presets_customize(array); + export_xlat_presets(array); + + file = g_fopen(filename, "w"); + if (file != NULL) { - gtk_tree_store_set(store, &iter, - 1, 800, - 2, 2 , - -1); + ghb_plist_write(file, array); + fclose(file); } - gtk_tree_path_free(treepath); - } - g_free(indices); -} + ghb_value_free(array); -void -ghb_presets_list_clear_default(signal_user_data_t *ud) -{ - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeIter iter; - GtkTreeStore *store; - gint *indices, len; - - g_debug("ghb_presets_list_clear_default ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list")); - store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); - indices = presets_find_default(presetsPlist, &len); - if (indices == NULL) return; - treepath = ghb_tree_path_new_from_indices(indices, len); - if (treepath) - { - if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath)) + exportDir = ghb_settings_get_string(ud->settings, "ExportDirectory"); + dir = g_path_get_dirname(filename); + if (strcmp(dir, exportDir) != 0) { - gtk_tree_store_set(store, &iter, - 1, 400, - 2, 0 , - -1); + ghb_settings_set_string(ud->settings, "ExportDirectory", dir); + ghb_pref_save(ud->settings, "ExportDirectory"); } - gtk_tree_path_free(treepath); + g_free(exportDir); + g_free(dir); + g_free(filename); } + gtk_widget_destroy(dialog); g_free(indices); } -static void -update_audio_presets(signal_user_data_t *ud) +G_MODULE_EXPORT void +presets_new_folder_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { - g_debug("update_audio_presets"); - const GValue *audio_list; + GtkWidget *dialog; + GtkEntry *entry; + GtkTextView *desc; + GtkResponseType response; + GValue *preset, *dict; + const gchar *name = ""; + const gchar *description = ""; + gint count, *indices, len; - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - ghb_settings_set_value(ud->settings, "AudioList", audio_list); -} + g_debug("presets_new_folder_clicked_cb ()"); + preset = ghb_settings_get_value (ud->settings, "preset_selection"); -void -enforce_preset_type(signal_user_data_t *ud, const GValue *path) -{ - gint *indices, len; - GtkWidget *normal, *folder; - gboolean fold; + count = ghb_array_len(preset); + if (count > 0) + name = g_value_get_string(ghb_array_get_nth(preset, count-1)); + else + count = 1; - normal = GHB_WIDGET(ud->builder, "preset_type_normal"); - folder = GHB_WIDGET(ud->builder, "preset_type_folder"); - indices = ghb_preset_indices_from_path(presetsPlist, path, &len); - if (indices) + indices = ghb_preset_indices_from_path(presetsPlist, preset, &len); + dict = presets_get_dict(presetsPlist, indices, len); + if (dict != NULL) { - fold = ghb_presets_get_folder(presetsPlist, indices, len); - if (fold) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(folder), - TRUE); - else - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(normal), - TRUE); - gtk_widget_set_sensitive(folder, fold); - gtk_widget_set_sensitive(normal, !fold); - g_free(indices); + description = g_value_get_string( + ghb_dict_lookup(dict, "PresetDescription")); + ghb_ui_update(ud, "FolderDescription", ghb_string_value(description)); } - else + + desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "FolderDescription")); + dialog = GHB_WIDGET(ud->builder, "preset_new_folder_dialog"); + entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "FolderName")); + gtk_entry_set_text(entry, name); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response == GTK_RESPONSE_OK) { - gtk_widget_set_sensitive(folder, TRUE); - gtk_widget_set_sensitive(normal, TRUE); + // save the preset + const gchar *name = gtk_entry_get_text(entry); + GValue *dest; + + if (count > MAX_NESTED_PRESET-1) + count = MAX_NESTED_PRESET-1; + + dest = ghb_array_value_new(MAX_NESTED_PRESET); + if (indices != NULL) + { + gint ptype; + + ptype = ghb_presets_get_type(presetsPlist, indices, len); + if (ptype == PRESETS_CUSTOM) + { + ghb_array_copy(dest, preset, count-1); + } + } + ghb_array_append(dest, ghb_string_value_new(name)); + GValue *val = ghb_widget_value(GTK_WIDGET(desc)); + ghb_settings_set_value(ud->settings, "PresetDescription", val); + folder_save(ud, dest); + ghb_value_free(dest); } + if (indices != NULL) + g_free(indices); } -void +G_MODULE_EXPORT void presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GtkWidget *dialog; @@ -2722,12 +3719,28 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) name = g_value_get_string(ghb_array_get_nth(preset, count-1)); else count = 1; - // Clear the description + desc = GTK_TEXT_VIEW(GHB_WIDGET(ud->builder, "PresetDescription")); + int width = ghb_settings_get_int(ud->settings, "PictureWidth"); + int height = ghb_settings_get_int(ud->settings, "PictureHeight"); + gboolean autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); + ghb_ui_update(ud, "PictureWidthEnable", + ghb_boolean_value(width!=0&&!autoscale)); + ghb_ui_update(ud, "PictureHeightEnable", + ghb_boolean_value(height!=0&&!autoscale)); + if (!width) + { + width = ghb_settings_get_int(ud->settings, "scale_width"); + ghb_ui_update(ud, "PictureWidth", ghb_int_value(width)); + } + if (!height) + { + height = ghb_settings_get_int(ud->settings, "scale_height"); + ghb_ui_update(ud, "PictureHeight", ghb_int_value(height)); + } dialog = GHB_WIDGET(ud->builder, "preset_save_dialog"); entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "PresetName")); gtk_entry_set_text(entry, name); - enforce_preset_type(ud, preset); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_hide(dialog); if (response == GTK_RESPONSE_OK) @@ -2736,13 +3749,6 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) const gchar *name = gtk_entry_get_text(entry); GValue *dest; - if (ghb_settings_get_boolean(ud->settings, "preset_type_folder")) - { - if (count > MAX_NESTED_PRESET-1) - { - count = MAX_NESTED_PRESET-1; - } - } dest = ghb_array_value_new(MAX_NESTED_PRESET); indices = ghb_preset_indices_from_path(presetsPlist, preset, &len); if (indices) @@ -2754,47 +3760,27 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { ghb_array_copy(dest, preset, count-1); } + g_free(indices); } ghb_array_append(dest, ghb_string_value_new(name)); ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc)); - if (ghb_settings_get_boolean(ud->settings, "preset_type_folder")) - { - folder_save(ud, dest); - } - else - { - // Construct the audio settings presets from the current audio list - update_audio_presets(ud); - settings_save(ud, dest); - } + + // Construct the audio settings presets from the current audio list + update_audio_presets(ud); + update_subtitle_presets(ud); + settings_save(ud, dest); ghb_value_free(dest); } } -void +G_MODULE_EXPORT void preset_type_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { ghb_widget_to_setting(ud->settings, widget); } -void -preset_name_changed_cb(GtkWidget *entry, signal_user_data_t *ud) -{ - gchar *name; - GValue *preset, *dest; - gint count; - - preset = ghb_settings_get_value (ud->settings, "preset_selection"); - name = ghb_widget_string(entry); - dest = ghb_value_dup(preset); - count = ghb_array_len(dest); - ghb_array_replace(dest, count-1, ghb_string_value_new(name)); - enforce_preset_type(ud, dest); - ghb_value_free(dest); -} - -void +G_MODULE_EXPORT void presets_restore_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GValue *preset; @@ -2808,7 +3794,7 @@ presets_restore_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) ghb_select_preset(ud->builder, preset); } -void +G_MODULE_EXPORT void presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GtkTreeView *treeview; @@ -2877,7 +3863,7 @@ presets_remove_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) } // controls where valid drop locations are -gboolean +G_MODULE_EXPORT gboolean presets_drag_motion_cb( GtkTreeView *tv, GdkDragContext *ctx, @@ -2897,6 +3883,11 @@ presets_drag_motion_cb( gboolean src_folder, dst_folder; GValue *preset; gint tree_depth, ii; + GtkWidget *widget; + + widget = gtk_drag_get_source_widget(ctx); + if (widget == NULL || widget != GTK_WIDGET(tv)) + return TRUE; // Get the type of the object being dragged srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx)); @@ -2968,7 +3959,7 @@ presets_drag_motion_cb( return TRUE; } -void +G_MODULE_EXPORT void presets_drag_cb( GtkTreeView *dstwidget, GdkDragContext *dc, @@ -3108,7 +4099,7 @@ presets_drag_cb( dstpath = gtk_tree_model_get_path (dstmodel, &iter); dst_indices = gtk_tree_path_get_indices(dstpath); dst_len = gtk_tree_path_get_depth(dstpath); - presets_list_update_item(ud, dst_indices, dst_len); + presets_list_update_item(ud, dst_indices, dst_len, TRUE); gtk_tree_path_free(dstpath); store_presets(); @@ -3117,6 +4108,62 @@ presets_drag_cb( } } +void +presets_row_expanded_cb( + GtkTreeView *treeview, + GtkTreeIter *iter, + GtkTreePath *path, + signal_user_data_t *ud) +{ + gint *indices, len; + gboolean expanded, folder; + GValue *dict; + + expanded = gtk_tree_view_row_expanded(treeview, path); + indices = gtk_tree_path_get_indices(path); + len = gtk_tree_path_get_depth(path); + dict = presets_get_dict(presetsPlist, indices, len); + if (preset_folder_is_open(dict)) + { + if (expanded) + return; + } + else if (!expanded) + { + return; + } + folder = ghb_presets_get_folder(presetsPlist, indices, len); + if (folder) + { + presets_set_folder_open(expanded, indices, len); + } + + // Collapsing parent folder collapses all children + if (!expanded) + { + GValue *presets = NULL; + gint *more_indices, count, ii; + + more_indices = g_malloc((len+1)*sizeof(gint)); + memcpy(more_indices, indices, len*sizeof(gint)); + + presets = presets_get_folder(presetsPlist, indices, len); + count = ghb_array_len(presets); + for (ii = 0; ii < count; ii++) + { + dict = ghb_array_get_nth(presets, ii); + folder = ghb_preset_folder(dict); + if (folder) + { + more_indices[len] = ii; + presets_set_folder_open(expanded, more_indices, len+1); + } + } + g_free(more_indices); + } + store_presets(); +} + static void preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo) { @@ -3125,10 +4172,11 @@ preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo) ghb_ui_update(ud, "scale_width", ghb_int64_value(tinfo->width - tinfo->crop[2] - tinfo->crop[3])); // If anamorphic or keep_aspect, the hight will be automatically calculated - gboolean keep_aspect, anamorphic; + gboolean keep_aspect; + gint pic_par; keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio"); - anamorphic = ghb_settings_get_boolean(ud->settings, "anamorphic"); - if (!(keep_aspect || anamorphic)) + pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR"); + if (!(keep_aspect || pic_par) || pic_par == 3) { ghb_ui_update(ud, "scale_height", ghb_int64_value(tinfo->height - tinfo->crop[0] - tinfo->crop[1])); @@ -3157,6 +4205,76 @@ preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo) } void +ghb_refresh_preset(signal_user_data_t *ud) +{ + ghb_title_info_t tinfo; + GValue *preset; + gint *indices, len; + + g_debug("ghb_refresh_preset ()"); + preset = ghb_settings_get_value(ud->settings, "preset_selection"); + indices = ghb_preset_indices_from_path(presetsPlist, preset, &len); + if (indices) + { + gboolean folder; + + folder = ghb_presets_get_folder(presetsPlist, indices, len); + if (!folder) + { + ud->dont_clear_presets = TRUE; + ud->scale_busy = TRUE; + // Temporarily set the video_quality range to (0,100) + // This is needed so the video_quality value does not get + // truncated when set. The range will be readjusted below + GtkWidget *qp = GHB_WIDGET(ud->builder, "VideoQualitySlider"); + gtk_range_set_range (GTK_RANGE(qp), 0, 100); + gtk_scale_set_digits(GTK_SCALE(qp), 3); + // Clear the audio list prior to changing the preset. Existing + // audio can cause the container extension to be automatically + // changed when it shouldn't be + ghb_clear_audio_list(ud); + ghb_set_preset_from_indices(ud, indices, len); + gint titleindex; + titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_set_pref_audio(titleindex, ud); + ghb_set_pref_subtitle(titleindex, ud); + ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE); + if (ghb_get_title_info (&tinfo, titleindex)) + { + preset_update_title_deps(ud, &tinfo); + } + ud->scale_busy = FALSE; + ghb_set_scale (ud, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX); + ud->dont_clear_presets = FALSE; + + gdouble vqmin, vqmax, step, page; + gint digits; + gboolean inverted; + + ghb_vquality_range(ud, &vqmin, &vqmax, &step, + &page, &digits, &inverted); + gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax); + gtk_range_set_increments (GTK_RANGE(qp), step, page); + gtk_scale_set_digits(GTK_SCALE(qp), digits); + gtk_range_set_inverted (GTK_RANGE(qp), inverted); + + gchar *text; + gint crop[4]; + GtkWidget *crop_widget; + crop[0] = ghb_settings_get_int(ud->settings, "PictureTopCrop"); + crop[1] = ghb_settings_get_int(ud->settings, "PictureBottomCrop"); + crop[2] = ghb_settings_get_int(ud->settings, "PictureLeftCrop"); + crop[3] = ghb_settings_get_int(ud->settings, "PictureRightCrop"); + crop_widget = GHB_WIDGET (ud->builder, "crop_values"); + text = g_strdup_printf("%d:%d:%d:%d", + crop[0], crop[1], crop[2], crop[3]); + gtk_label_set_text (GTK_LABEL(crop_widget), text); + g_free(text); + } + } +} + +G_MODULE_EXPORT void presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud) { GtkTreeModel *store; @@ -3184,6 +4302,7 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ if (!folder) { ud->dont_clear_presets = TRUE; + ud->scale_busy = TRUE; // Temporarily set the video_quality range to (0,100) // This is needed so the video_quality value does not get // truncated when set. The range will be readjusted below @@ -3195,24 +4314,29 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ // changed when it shouldn't be ghb_clear_audio_list(ud); ghb_set_preset_from_indices(ud, indices, len); - gtk_tree_path_free(treepath); gint titleindex; titleindex = ghb_settings_combo_int(ud->settings, "title"); ghb_set_pref_audio(titleindex, ud); + ghb_set_pref_subtitle(titleindex, ud); ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE); - ud->dont_clear_presets = FALSE; if (ghb_get_title_info (&tinfo, titleindex)) { preset_update_title_deps(ud, &tinfo); } - ghb_set_scale (ud, GHB_SCALE_KEEP_NONE); + ud->scale_busy = FALSE; + ghb_set_scale (ud, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX); + ud->dont_clear_presets = FALSE; gdouble vqmin, vqmax, step, page; gint digits; - ghb_vquality_range(ud, &vqmin, &vqmax, &step, &page, &digits); + gboolean inverted; + + ghb_vquality_range(ud, &vqmin, &vqmax, &step, + &page, &digits, &inverted); gtk_range_set_range (GTK_RANGE(qp), vqmin, vqmax); gtk_range_set_increments (GTK_RANGE(qp), step, page); gtk_scale_set_digits(GTK_SCALE(qp), digits); + gtk_range_set_inverted (GTK_RANGE(qp), inverted); gchar *text; gint crop[4]; @@ -3227,6 +4351,7 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ gtk_label_set_text (GTK_LABEL(crop_widget), text); g_free(text); } + gtk_tree_path_free(treepath); gtk_widget_set_sensitive(widget, TRUE); } else @@ -3234,6 +4359,21 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ g_debug("No selection??? Perhaps unselected."); gtk_widget_set_sensitive(widget, FALSE); } + if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0) + { + gint start, end; + start = ghb_settings_get_int(ud->settings, "start_point"); + end = ghb_settings_get_int(ud->settings, "end_point"); + widget = GHB_WIDGET (ud->builder, "ChapterMarkers"); + gtk_widget_set_sensitive(widget, TRUE); + if (start == end) + { + ud->dont_clear_presets = TRUE; + ghb_ui_update(ud, "ChapterMarkers", ghb_boolean_value(FALSE)); + ud->dont_clear_presets = FALSE; + gtk_widget_set_sensitive(widget, FALSE); + } + } } void @@ -3250,7 +4390,7 @@ ghb_clear_presets_selection(signal_user_data_t *ud) ghb_settings_set_boolean(ud->settings, "preset_modified", TRUE); } -void +G_MODULE_EXPORT void presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, signal_user_data_t *ud) { GtkTreeView *treeview; @@ -3270,7 +4410,7 @@ presets_frame_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation, sig } } -void +G_MODULE_EXPORT void presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GValue *preset; @@ -3291,3 +4431,50 @@ presets_default_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) } } +G_MODULE_EXPORT void +preset_edited_cb( + GtkCellRendererText *cell, + gchar *path, + gchar *text, + signal_user_data_t *ud) +{ + GtkTreePath *treepath; + GtkTreeStore *store; + GtkTreeView *treeview; + GtkTreeIter iter; + gint *indices, len, count; + GValue *dict; + GValue *preset, *dest; + + g_debug("preset_edited_cb ()"); + g_debug("path (%s)", path); + g_debug("text (%s)", text); + + preset = ghb_settings_get_value (ud->settings, "preset_selection"); + dest = ghb_array_value_new(MAX_NESTED_PRESET); + count = ghb_array_len(preset); + ghb_array_copy(dest, preset, count-1); + ghb_array_append(dest, ghb_string_value_new(text)); + indices = ghb_preset_indices_from_path(presetsPlist, dest, &len); + ghb_value_free(dest); + if (indices != NULL) + { + // Already exists + g_free(indices); + return; + } + + treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "presets_list")); + store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview)); + treepath = gtk_tree_path_new_from_string (path); + indices = gtk_tree_path_get_indices(treepath); + len = gtk_tree_path_get_depth(treepath); + gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath); + gtk_tree_store_set(store, &iter, 0, text, -1); + + dict = presets_get_dict(presetsPlist, indices, len); + ghb_dict_insert(dict, g_strdup("PresetName"), ghb_string_value_new(text)); + store_presets(); + gtk_tree_path_free (treepath); +} +