X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=gtk%2Fsrc%2Fpresets.c;h=c17a902d4e22fd96e92e645a324d03da6ccff72e;hb=47f681558afcfa3032c64a73f605b1d73812bfc7;hp=bb5e2e70f190d0fc2620eee38b9df8be3a125e68;hpb=7d4f3c93ea6ce9de22cf4187b03bb9432e51726c;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/gtk/src/presets.c b/gtk/src/presets.c index bb5e2e70..c17a902d 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -16,9 +16,11 @@ #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 +39,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 +155,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 +269,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) { @@ -323,8 +319,7 @@ ghb_presets_remove( presets_remove_nth(folder, indices[len-1]); else { - g_warning("ghb_presets_remove ()"); - g_warning("internal preset lookup error"); + g_warning("ghb_presets_remove (): internal preset lookup error"); return FALSE; } return TRUE; @@ -344,8 +339,7 @@ ghb_presets_replace( ghb_array_replace(folder, indices[len-1], dict); else { - g_warning("ghb_presets_replace ()"); - g_warning("internal preset lookup error"); + g_warning("ghb_presets_replace (): internal preset lookup error"); } } @@ -363,8 +357,7 @@ ghb_presets_insert( ghb_array_insert(folder, indices[len-1], dict); else { - g_warning("ghb_presets_insert ()"); - g_warning("internal preset lookup error"); + g_warning("ghb_presets_insert (): internal preset lookup error"); } } @@ -493,6 +486,37 @@ preset_is_default(GValue *dict) return ghb_value_boolean(val); } +static void +presets_clear_default(GValue *presets) +{ + gint count, ii; + + count = ghb_array_len(presets); + for (ii = 0; ii < count; ii++) + { + GValue *dict; + gboolean folder; + + dict = ghb_array_get_nth(presets, ii); + folder = ghb_value_boolean(preset_dict_get_value(dict, "Folder")); + if (folder) + { + GValue *nested; + + nested = ghb_dict_lookup(dict, "ChildrenArray"); + presets_clear_default(nested); + } + else + { + if (preset_is_default(dict)) + { + ghb_dict_insert(dict, g_strdup("Default"), + ghb_boolean_value_new(FALSE)); + } + } + } +} + static gint* presets_find_default2(GValue *presets, gint *len) { @@ -527,7 +551,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; @@ -538,10 +562,10 @@ presets_find_default2(GValue *presets, gint *len) } static gint* -presets_find_default(gint *len) +presets_find_default(GValue *presets, gint *len) { *len = 0; - return presets_find_default2(presetsPlist, len); + return presets_find_default2(presets, len); } gint* @@ -606,8 +630,7 @@ ghb_presets_get_type( } else { - g_warning("ghb_presets_get_type ()"); - g_warning("internal preset lookup error"); + g_warning("ghb_presets_get_type (): internal preset lookup error"); } return type; } @@ -628,8 +651,7 @@ ghb_presets_get_folder( } else { - g_warning("ghb_presets_get_folder ()"); - g_warning("internal preset lookup error"); + g_warning("ghb_presets_get_folder (): internal preset lookup error"); } return folder; } @@ -638,19 +660,9 @@ void presets_set_default(gint *indices, gint len) { GValue *dict; - gint *curr_indices, curr_len; g_debug("presets_set_default ()"); - curr_indices = presets_find_default(&curr_len); - if (curr_indices) - { - dict = presets_get_dict(presetsPlist, curr_indices, curr_len); - if (dict) - { - ghb_dict_insert(dict, g_strdup("Default"), - ghb_boolean_value_new(FALSE)); - } - } + presets_clear_default(presetsPlist); dict = presets_get_dict(presetsPlist, indices, len); if (dict) { @@ -659,6 +671,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) @@ -845,21 +871,6 @@ preset_to_ui(signal_user_data_t *ud, GValue *dict) init_settings_from_dict(ud->settings, hidden, dict); init_ui_from_dict(ud, internal, dict); init_ui_from_dict(ud, hidden, dict); - - if (ghb_settings_get_boolean(ud->settings, "allow_tweaks")) - { - const GValue *gval; - gval = preset_dict_get_value(dict, "PictureDeinterlace"); - if (gval) - { - ghb_ui_update(ud, "tweak_PictureDeinterlace", gval); - } - gval = preset_dict_get_value(dict, "PictureDenoise"); - if (gval) - { - ghb_ui_update(ud, "tweak_PictureDenoise", gval); - } - } } void @@ -870,6 +881,16 @@ ghb_settings_to_ui(signal_user_data_t *ud, GValue *dict) static GValue *current_preset = NULL; +gboolean +ghb_preset_is_custom() +{ + const GValue *val; + + if (current_preset == NULL) return FALSE; + val = preset_dict_get_value(current_preset, "Type"); + return (ghb_value_int(val) == 1); +} + void ghb_set_preset_from_indices(signal_user_data_t *ud, gint *indices, gint len) { @@ -980,7 +1001,7 @@ ghb_select_default_preset(GtkBuilder *builder) gint *indices, len; g_debug("ghb_select_default_preset()"); - indices = presets_find_default(&len); + indices = presets_find_default(presetsPlist, &len); if (indices) { ghb_select_preset2(builder, indices, len); @@ -989,7 +1010,7 @@ ghb_select_default_preset(GtkBuilder *builder) } gchar* -ghb_get_user_config_dir() +ghb_get_user_config_dir(gchar *subdir) { const gchar *dir; gchar *config; @@ -1008,6 +1029,23 @@ ghb_get_user_config_dir() if (!g_file_test(config, G_FILE_TEST_IS_DIR)) g_mkdir (config, 0755); } + if (subdir) + { + gchar **split; + gint ii; + + split = g_strsplit(subdir, G_DIR_SEPARATOR_S, -1); + for (ii = 0; split[ii] != NULL; ii++) + { + gchar *tmp; + + tmp = g_strdup_printf ("%s/%s", config, split[ii]); + g_free(config); + config = tmp; + if (!g_file_test(config, G_FILE_TEST_IS_DIR)) + g_mkdir (config, 0755); + } + } return config; } @@ -1017,7 +1055,7 @@ store_plist(GValue *plist, const gchar *name) gchar *config, *path; FILE *file; - config = ghb_get_user_config_dir(); + config = ghb_get_user_config_dir(NULL); path = g_strdup_printf ("%s/%s", config, name); file = g_fopen(path, "w"); g_free(config); @@ -1032,7 +1070,7 @@ load_plist(const gchar *name) gchar *config, *path; GValue *plist = NULL; - config = ghb_get_user_config_dir(); + config = ghb_get_user_config_dir(NULL); path = g_strdup_printf ("%s/%s", config, name); if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { @@ -1048,7 +1086,7 @@ remove_plist(const gchar *name) { gchar *config, *path; - config = ghb_get_user_config_dir(); + config = ghb_get_user_config_dir(NULL); path = g_strdup_printf ("%s/%s", config, name); if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { @@ -1095,14 +1133,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 @@ -1134,12 +1172,14 @@ ghb_prefs_to_ui(signal_user_data_t *ud) } gval = ghb_settings_get_value(ud->settings, "default_source"); ghb_settings_set_value (ud->settings, "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; } @@ -1163,20 +1203,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); @@ -1185,8 +1248,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; } } @@ -1251,6 +1329,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) { @@ -1265,20 +1371,20 @@ 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); if (dir == NULL) { @@ -1286,8 +1392,22 @@ ghb_prefs_load(signal_user_data_t *ud) } 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) @@ -1312,7 +1432,7 @@ ghb_prefs_load(signal_user_data_t *ud) g_free(indices); } ghb_dict_remove(dict, "default_preset"); - store_plist(prefsPlist, "preferences"); + store_prefs(); } } @@ -1424,6 +1544,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); @@ -1612,7 +1746,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} @@ -1621,6 +1755,7 @@ static value_map_t vcodec_xlat[] = static value_map_t acodec_xlat[] = { {"AAC (faac)", "faac"}, + {"AAC (CoreAudio)", "faac"}, {"AC3 Passthru", "ac3"}, {"MP3 (lame)", "lame"}, {"Vorbis (vorbis)", "vorbis"}, @@ -1630,10 +1765,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} }; @@ -1676,18 +1811,36 @@ value_map_t mix_xlat[] = value_map_t deint_xlat[] = { {"0", "none"}, - {"1", "fast"}, - {"2", "slow"}, - {"3", "slower"}, + {"1", "custom"}, + {"2", "fast"}, + {"3", "slow"}, + {"4", "slower"}, {NULL, NULL} }; value_map_t denoise_xlat[] = { {"0", "none"}, - {"1", "weak"}, - {"2", "medium"}, - {"3", "strong"}, + {"1", "custom"}, + {"2", "weak"}, + {"3", "medium"}, + {"4", "strong"}, + {NULL, NULL} +}; + +value_map_t detel_xlat[] = +{ + {"0", "none"}, + {"1", "custom"}, + {"2", "default"}, + {NULL, NULL} +}; + +value_map_t decomb_xlat[] = +{ + {"0", "none"}, + {"1", "custom"}, + {"2", "default"}, {NULL, NULL} }; @@ -1723,6 +1876,7 @@ export_subtitle_xlat2(GValue *lin_val) gchar *str; GValue *gval; + if (lin_val == NULL) return NULL; str = ghb_value_string(lin_val); if (strcmp(str, "none") == 0) { @@ -1770,6 +1924,7 @@ import_subtitle_xlat2(GValue *mac_val) gchar *str; GValue *gval; + if (mac_val == NULL) return NULL; str = ghb_value_string(mac_val); if (strcmp(str, "None") == 0) { @@ -1793,6 +1948,7 @@ export_audio_track_xlat2(GValue *lin_val) gchar *str; GValue *gval = NULL; + if (lin_val == NULL) return NULL; str = ghb_value_string(lin_val); if (strcmp(str, "none") == 0) { @@ -1814,6 +1970,7 @@ import_audio_track_xlat2(GValue *mac_val) gchar *str; GValue *gval; + if (mac_val == NULL) return NULL; val = ghb_value_int(mac_val); if (val <= 0) { @@ -1884,29 +2041,45 @@ 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 *slist; + GValue *sdict; + gint count, ii; + + slist = ghb_dict_lookup(dict, "SubtitleList"); + count = ghb_array_len(slist); + for (ii = 0; ii < count; ii++) + { + 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; - gint count, ii; alist = ghb_dict_lookup(dict, "AudioList"); count = ghb_array_len(alist); @@ -1973,13 +2146,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; } @@ -2006,6 +2200,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); @@ -2016,19 +2220,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); @@ -2057,6 +2327,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)); + } + } } } } @@ -2086,32 +2368,26 @@ 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 @@ -2155,6 +2431,42 @@ import_xlat_preset(GValue *dict) } break; } import_value_xlat(dict); + + gdouble vquality; + const GValue *gval; + + vquality = ghb_value_double(preset_dict_get_value(dict, "VideoQualitySlider")); + if (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 @@ -2188,12 +2500,10 @@ import_xlat_presets(GValue *presets) static void export_xlat_preset(GValue *dict) { - gboolean ana, round, autoscale, target, br, constant; + gboolean autoscale, target, 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( @@ -2208,20 +2518,6 @@ export_xlat_preset(GValue *dict) ghb_dict_insert(dict, g_strdup("UsesPictureSettings"), ghb_int_value_new(1)); - if (ana) - { - if (round) - ghb_dict_insert(dict, g_strdup("PicturePAR"), - ghb_int_value_new(2)); - else - ghb_dict_insert(dict, g_strdup("PicturePAR"), - ghb_int_value_new(1)); - } - else - { - ghb_dict_insert(dict, g_strdup("PicturePAR"), - ghb_int_value_new(0)); - } // VideoQualityType/0/1/2 - vquality_type_/target/bitrate/constant if (target) { @@ -2238,8 +2534,28 @@ export_xlat_preset(GValue *dict) ghb_dict_insert(dict, g_strdup("VideoQualityType"), ghb_int_value_new(2)); } + + 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, "UsesMaxPictureSettings"); 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"); @@ -2273,6 +2589,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() { @@ -2284,60 +2610,197 @@ 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) { GValue *std_presets; gint count, ii; + int *indices, len; g_debug("ghb_presets_reload()\n"); std_presets = ghb_resource_get("standard-presets"); if (std_presets == NULL) return; remove_std_presets(ud); + 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; - GHashTableIter iter; - gchar *key; - GValue *value; gint indices = 0; std_dict = ghb_array_get_nth(std_presets, ii); - copy_dict = ghb_dict_value_new(); + 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); - ghb_dict_iter_init(&iter, std_dict); - // 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)) + presets_list_insert(ud, &indices, 1); + } + import_xlat_presets(presetsPlist); + store_presets(); +} + +static gboolean +check_old_presets() +{ + gint count, ii; + + count = ghb_array_len(presetsPlist); + for (ii = count-1; ii >= 0; ii--) + { + GValue *dict; + GValue *type; + + dict = ghb_array_get_nth(presetsPlist, ii); + type = ghb_dict_lookup(dict, "Type"); + if (type == NULL) + return TRUE; + } + 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) { - ghb_dict_insert(copy_dict, g_strdup(key), ghb_value_dup(value)); + gint indices = 0; + ghb_presets_remove(presetsPlist, &indices, 1); } - presets_list_insert(ud, &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) { presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets")); + import_xlat_presets(presetsPlist); store_presets(); } else if (G_VALUE_TYPE(presetsPlist) == ghb_dict_get_type()) { // Presets is older dictionary format. Convert to array ghb_value_free(presetsPlist); presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets")); + import_xlat_presets(presetsPlist); store_presets(); } + else if (check_old_presets()) + { + ghb_value_free(presetsPlist); + presetsPlist = ghb_value_dup(ghb_resource_get("standard-presets")); + import_xlat_presets(presetsPlist); + store_presets(); + } + update_standard_presets(ud); import_xlat_presets(presetsPlist); } @@ -2350,6 +2813,7 @@ settings_save(signal_user_data_t *ud, const GValue *path) GValue *value; gboolean autoscale; gint *indices, len, count; + gint *def_indices, def_len; const gchar *name; gboolean replace = FALSE; @@ -2389,25 +2853,10 @@ 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); - } - } + current_preset = dict; autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); 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); @@ -2456,7 +2905,16 @@ settings_save(signal_user_data_t *ud, const GValue *path) } ghb_dict_insert(dict, g_strdup("PresetName"), ghb_string_value_new(name)); if (replace) + { + 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); + } else { ghb_dict_insert(dict, g_strdup("Default"), @@ -2546,7 +3004,7 @@ ghb_presets_list_default(signal_user_data_t *ud) g_debug("ghb_presets_list_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(&len); + indices = presets_find_default(presetsPlist, &len); if (indices == NULL) return; treepath = ghb_tree_path_new_from_indices(indices, len); if (treepath) @@ -2575,7 +3033,7 @@ ghb_presets_list_clear_default(signal_user_data_t *ud) 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(&len); + indices = presets_find_default(presetsPlist, &len); if (indices == NULL) return; treepath = ghb_tree_path_new_from_indices(indices, len); if (treepath) @@ -2602,6 +3060,30 @@ update_audio_presets(signal_user_data_t *ud) 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); +} + void enforce_preset_type(signal_user_data_t *ud, const GValue *path) { @@ -2632,7 +3114,7 @@ enforce_preset_type(signal_user_data_t *ud, const GValue *path) } } -void +G_MODULE_EXPORT void presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GtkWidget *dialog; @@ -2695,19 +3177,20 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { // 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 +G_MODULE_EXPORT void preset_name_changed_cb(GtkWidget *entry, signal_user_data_t *ud) { gchar *name; @@ -2723,7 +3206,7 @@ preset_name_changed_cb(GtkWidget *entry, signal_user_data_t *ud) ghb_value_free(dest); } -void +G_MODULE_EXPORT void presets_restore_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { GValue *preset; @@ -2737,7 +3220,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; @@ -2806,7 +3289,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, @@ -2826,6 +3309,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)); @@ -2897,7 +3385,7 @@ presets_drag_motion_cb( return TRUE; } -void +G_MODULE_EXPORT void presets_drag_cb( GtkTreeView *dstwidget, GdkDragContext *dc, @@ -3046,6 +3534,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) { @@ -3054,10 +3598,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])); @@ -3085,7 +3630,7 @@ preset_update_title_deps(signal_user_data_t *ud, ghb_title_info_t *tinfo) } } -void +G_MODULE_EXPORT void presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud) { GtkTreeModel *store; @@ -3128,20 +3673,25 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ 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); + ghb_set_scale (ud, GHB_PIC_KEEP_PAR); + 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]; @@ -3179,7 +3729,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; @@ -3199,7 +3749,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;