diff options
author | jstebbins <[email protected]> | 2011-10-16 17:33:20 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-10-16 17:33:20 +0000 |
commit | 49fad04f4365f0c3c01583dabd8d261ec76505f3 (patch) | |
tree | dee0f99ba705f57f21bffa8390380974a521ffba | |
parent | cf10a485d3892f8d2d055c62ba0b853a7286bd57 (diff) |
LinGui: experimental support for batch queuing
This allows all titles in the title popup to be added to the queue in
one go. It uses the current *preset* for the settings. I.e. settings
changes in the UI are ignored. This deficiency will be rectified at a
future time.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4294 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | gtk/src/audiohandler.c | 268 | ||||
-rw-r--r-- | gtk/src/audiohandler.h | 7 | ||||
-rw-r--r-- | gtk/src/callbacks.c | 171 | ||||
-rw-r--r-- | gtk/src/callbacks.h | 1 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 12 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 334 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 17 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 4 | ||||
-rw-r--r-- | gtk/src/presets.c | 14 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 103 | ||||
-rw-r--r-- | gtk/src/queuehandler.h | 1 | ||||
-rw-r--r-- | gtk/src/settings.c | 22 | ||||
-rw-r--r-- | gtk/src/settings.h | 2 | ||||
-rw-r--r-- | gtk/src/subtitlehandler.c | 272 | ||||
-rw-r--r-- | gtk/src/subtitlehandler.h | 4 |
15 files changed, 816 insertions, 416 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index 39c42bd74..2e12c1939 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -20,11 +20,26 @@ #include "preview.h" #include "audiohandler.h" -static void ghb_add_audio(signal_user_data_t *ud, GValue *settings); +static gboolean ghb_add_audio_to_settings(GValue *settings, GValue *asettings); +static void ghb_add_audio_to_ui(GtkBuilder *builder, const GValue *settings); static GValue* get_selected_asettings(signal_user_data_t *ud); +static void ghb_clear_audio_list_settings(GValue *settings); +static void ghb_clear_audio_list_ui(GtkBuilder *builder); static gboolean block_updates = FALSE; +void +check_list_full(signal_user_data_t *ud) +{ + GValue *audio_list; + gint count; + + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + count = ghb_array_len(audio_list); + GtkWidget * widget = GHB_WIDGET(ud->builder, "audio_add"); + gtk_widget_set_sensitive(widget, count != 99); +} + gint ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint fallback, gint copy_mask) { @@ -122,6 +137,74 @@ static int ghb_select_fallback( GValue *settings, int mux, int acodec ) } void +ghb_sanitize_audio(GValue *settings, GValue *asettings) +{ + gint titleindex, track, acodec, select_acodec, mix; + hb_audio_config_t *aconfig; + gint mux; + gint bitrate; + gint sr; + + g_debug("ghb_santiize_audio ()"); + mux = ghb_settings_combo_int(settings, "FileFormat"); + titleindex = ghb_settings_get_int(settings, "title_no"); + track = ghb_settings_combo_int(asettings, "AudioTrack"); + acodec = ghb_settings_combo_int(asettings, "AudioEncoder"); + mix = ghb_settings_combo_int(asettings, "AudioMixdown"); + bitrate = ghb_settings_combo_int(asettings, "AudioBitrate"); + sr = ghb_settings_combo_int(asettings, "AudioSamplerate"); + + aconfig = ghb_get_scan_audio_info(titleindex, track); + if (sr == 0) + { + sr = aconfig ? aconfig->in.samplerate : 48000; + } + gint fallback = ghb_select_fallback(settings, mux, acodec); + gint copy_mask = ghb_get_copy_mask(settings); + select_acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask); + gboolean codec_defined_bitrate = FALSE; + if (ghb_audio_is_passthru (select_acodec)) + { + if (aconfig) + { + bitrate = aconfig->in.bitrate / 1000; + + // Set the values for bitrate and samplerate to the input rates + mix = 0; + ghb_settings_set_string(asettings, "AudioMixdown", + ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); + select_acodec &= aconfig->in.codec | HB_ACODEC_PASS_FLAG; + codec_defined_bitrate = TRUE; + ghb_settings_set_string(asettings, "AudioSamplerate", + ghb_lookup_combo_string("AudioSamplerate", ghb_int_value(0))); + } + else + { + mix = 0; + ghb_settings_set_string(asettings, "AudioMixdown", + ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); + ghb_settings_set_string(asettings, "AudioSamplerate", + ghb_lookup_combo_string("AudioSamplerate", ghb_int_value(0))); + bitrate = 448; + } + ghb_settings_set_double(asettings, "AudioTrackDRCSlider", 0.0); + } + else + { + if (mix == 0) + mix = ghb_get_best_mix( aconfig, select_acodec, 0); + bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate, sr, mix); + ghb_settings_set_string(asettings, "AudioMixdown", + ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); + } + ghb_settings_set_string(asettings, "AudioBitrate", + ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); + + ghb_settings_take_value(asettings, "AudioEncoderActual", + ghb_lookup_acodec_value(select_acodec)); +} + +void ghb_adjust_audio_rate_combos(signal_user_data_t *ud) { gint titleindex, track, acodec, select_acodec, mix; @@ -226,12 +309,12 @@ free_audio_hash_key_value(gpointer data) } gchar* -ghb_get_user_audio_lang(signal_user_data_t *ud, gint titleindex, gint track) +ghb_get_user_audio_lang(GValue *settings, gint titleindex, gint track) { GValue *audio_list, *asettings; gchar *lang = NULL; - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + audio_list = ghb_settings_get_value(settings, "audio_list"); if (ghb_array_len(audio_list) <= track) return NULL; asettings = ghb_array_get_nth(audio_list, track); @@ -241,7 +324,7 @@ ghb_get_user_audio_lang(signal_user_data_t *ud, gint titleindex, gint track) } void -ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) +ghb_set_pref_audio_settings(gint titleindex, GValue *settings) { gint track; gchar *source_lang = NULL; @@ -256,20 +339,21 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) gint count, ii, list_count; g_debug("set_pref_audio"); - mux = ghb_settings_combo_int(ud->settings, "FileFormat"); + mux = ghb_settings_combo_int(settings, "FileFormat"); track_indices = g_hash_table_new_full(g_int_hash, g_int_equal, free_audio_hash_key_value, free_audio_hash_key_value); // Clear the audio list - ghb_clear_audio_list(ud); + ghb_clear_audio_list_settings(settings); + // Find "best" audio based on audio preferences - if (!ghb_settings_get_boolean(ud->settings, "AudioDUB")) + if (!ghb_settings_get_boolean(settings, "AudioDUB")) { source_lang = ghb_get_source_audio_lang(titleindex, 0); } if (source_lang == NULL) - source_lang = ghb_settings_get_string(ud->settings, "PreferredLanguage"); + source_lang = ghb_settings_get_string(settings, "PreferredLanguage"); - pref_audio = ghb_settings_get_value(ud->settings, "AudioList"); + pref_audio = ghb_settings_get_value(settings, "AudioList"); list_count = 0; count = ghb_array_len(pref_audio); @@ -280,8 +364,8 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) audio = ghb_array_get_nth(pref_audio, ii); acodec = ghb_settings_combo_int(audio, "AudioEncoder"); - fallback = ghb_select_fallback( ud->settings, mux, acodec ); - gint copy_mask = ghb_get_copy_mask(ud->settings); + fallback = ghb_select_fallback(settings, mux, acodec); + gint copy_mask = ghb_get_copy_mask(settings); select_acodec = ghb_select_audio_codec(mux, NULL, acodec, fallback, copy_mask); bitrate = ghb_settings_combo_int(audio, "AudioBitrate"); rate = ghb_settings_combo_double(audio, "AudioSamplerate"); @@ -305,7 +389,7 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) // HB_ACODEC_* are bit fields. Treat acodec as mask if (!(aconfig->in.codec & select_acodec & HB_ACODEC_PASS_MASK)) { - if (acodec != HB_ACODEC_AUTO_PASS) + if (acodec != HB_ACODEC_ANY) acodec = fallback; // If we can't substitute the passthru with a suitable // encoder and @@ -326,7 +410,6 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) bitrate = aconfig->in.bitrate / 1000; bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate, aconfig->in.samplerate, mix); - quality = hb_get_default_audio_quality( select_acodec ); rate = 0; } } @@ -339,32 +422,53 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud) acodec = 0; if (acodec != 0) { - GValue *settings = ghb_dict_value_new(); - ghb_settings_set_int(settings, "AudioTrack", track); - ghb_settings_set_string(settings, "AudioEncoder", + GValue *asettings = ghb_dict_value_new(); + ghb_settings_set_int(asettings, "AudioTrack", track); + ghb_settings_set_string(asettings, "AudioEncoder", ghb_lookup_combo_string("AudioEncoder", ghb_int_value(acodec))); - ghb_settings_set_value(settings, "AudioEncoderActual", + ghb_settings_set_value(asettings, "AudioEncoderActual", ghb_lookup_acodec_value(select_acodec)); - ghb_settings_set_value(settings, "AudioTrackQualityEnable", enable_qual); - ghb_settings_set_double(settings, "AudioTrackQuality", quality); + ghb_settings_set_value(asettings, "AudioTrackQualityEnable", enable_qual); + ghb_settings_set_double(asettings, "AudioTrackQuality", quality); + // This gets set autimatically if the codec is passthru - ghb_settings_set_string(settings, "AudioBitrate", + ghb_settings_set_string(asettings, "AudioBitrate", ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); - ghb_settings_set_string(settings, "AudioSamplerate", + ghb_settings_set_string(asettings, "AudioSamplerate", ghb_lookup_combo_string("AudioSamplerate", ghb_int_value(rate))); mix = ghb_get_best_mix( aconfig, select_acodec, mix); - ghb_settings_set_string(settings, "AudioMixdown", + ghb_settings_set_string(asettings, "AudioMixdown", ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); - ghb_settings_set_value(settings, "AudioTrackDRCSlider", drc); - ghb_settings_set_value(settings, "AudioTrackGain", gain); - ghb_add_audio(ud, settings); - ghb_adjust_audio_rate_combos(ud); + ghb_settings_set_value(asettings, "AudioTrackDRCSlider", drc); + ghb_settings_set_value(asettings, "AudioTrackGain", gain); + ghb_sanitize_audio(settings, asettings); + ghb_add_audio_to_settings(settings, asettings); } } g_free(source_lang); g_hash_table_destroy(track_indices); } +void +ghb_set_pref_audio_from_settings(signal_user_data_t *ud, GValue *settings) +{ + const GValue *audio_list, *audio; + gint count, ii; + + // Clear the audio list + ghb_clear_audio_list_ui(ud->builder); + + audio_list = ghb_settings_get_value(settings, "audio_list"); + count = ghb_array_len(audio_list); + for (ii = 0; ii < count; ii++) + { + audio = ghb_array_get_nth(audio_list, ii); + ghb_add_audio_to_ui(ud->builder, audio); + ghb_adjust_audio_rate_combos(ud); + } + check_list_full(ud); +} + static GValue* get_selected_asettings(signal_user_data_t *ud) { @@ -617,7 +721,6 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_settings_set_value(asettings, "AudioEncoderActual", ghb_settings_get_value(ud->settings, "AudioEncoderActual")); ghb_audio_list_refresh_selected(ud); } - ghb_update_destination_extension(ud); ghb_live_reset(ud); float low, high, gran, defval; @@ -859,28 +962,35 @@ gain_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } void -ghb_clear_audio_list(signal_user_data_t *ud) +ghb_clear_audio_list_settings(GValue *settings) { - GtkTreeView *treeview; - GtkListStore *store; GValue *audio_list; - g_debug("clear_audio_list ()"); - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + g_debug("clear_audio_list_settings ()"); + audio_list = ghb_settings_get_value(settings, "audio_list"); if (audio_list == NULL) { audio_list = ghb_array_value_new(8); - ghb_settings_set_value(ud->settings, "audio_list", audio_list); + ghb_settings_set_value(settings, "audio_list", audio_list); } else ghb_array_value_reset(audio_list, 8); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); +} + +void +ghb_clear_audio_list_ui(GtkBuilder *builder) +{ + GtkTreeView *treeview; + GtkListStore *store; + + g_debug("clear_audio_list_ui ()"); + treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "audio_list")); store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); gtk_list_store_clear (store); } static void -add_to_audio_list(signal_user_data_t *ud, GValue *settings) +ghb_add_audio_to_ui(GtkBuilder *builder, const GValue *settings) { GtkTreeView *treeview; GtkTreeIter iter; @@ -892,8 +1002,8 @@ add_to_audio_list(signal_user_data_t *ud, GValue *settings) gdouble drc; gdouble gain; - g_debug("add_to_audio_list ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + g_debug("ghb_add_audio_to_ui ()"); + treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "audio_list")); selection = gtk_tree_view_get_selection (treeview); store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); @@ -994,37 +1104,46 @@ audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t } } -static void -ghb_add_audio(signal_user_data_t *ud, GValue *settings) +static gboolean +ghb_add_audio_to_settings(GValue *settings, GValue *asettings) { GValue *audio_list; - int count; const gchar * track; + int count; - track = ghb_settings_combo_option(settings, "AudioTrack"); - ghb_settings_set_string(settings, "AudioTrackDescription", track); - - GValue *aname; - aname = ghb_dict_lookup(settings, "AudioTrackName"); - if (aname == NULL) - { - ghb_settings_set_string(settings, "AudioTrackName", ""); - } - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + audio_list = ghb_settings_get_value(settings, "audio_list"); if (audio_list == NULL) { audio_list = ghb_array_value_new(8); - ghb_settings_set_value(ud->settings, "audio_list", audio_list); + ghb_settings_set_value(settings, "audio_list", audio_list); } - ghb_array_append(audio_list, settings); - add_to_audio_list(ud, settings); count = ghb_array_len(audio_list); + // Don't allow more than 99 + // This is a hard limit imposed by libhb/reader.c:GetFifoForId() if (count >= 99) { - GtkWidget * widget = GHB_WIDGET(ud->builder, "audio_add"); - gtk_widget_set_sensitive(widget, FALSE); + ghb_value_free(asettings); + return FALSE; + } + + int title_no = ghb_settings_get_int(settings, "title_no"); + int track_no = ghb_settings_get_int(asettings, "AudioTrack"); + track = ghb_audio_track_description(track_no, title_no); + ghb_settings_set_string(asettings, "AudioTrackDescription", track); + + GValue *aname; + aname = ghb_dict_lookup(asettings, "AudioTrackName"); + if (aname == NULL) + { + ghb_settings_set_string(asettings, "AudioTrackName", ""); } - ghb_update_destination_extension(ud); + if (ghb_array_len(audio_list) >= 99) + { + ghb_value_free(asettings); + return FALSE; + } + ghb_array_append(audio_list, asettings); + return TRUE; } G_MODULE_EXPORT void @@ -1057,7 +1176,11 @@ audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSlider"); ghb_settings_take_value(asettings, "AudioTrackDRCSlider", ghb_widget_value(widget)); - ghb_add_audio(ud, asettings); + if (!ghb_add_audio_to_settings(ud->settings, asettings)) + return; + + ghb_add_audio_to_ui(ud->builder, asettings); + check_list_full(ud); } G_MODULE_EXPORT void @@ -1145,7 +1268,8 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) g_debug("set_audio"); // Clear the audio list - ghb_clear_audio_list(ud); + ghb_clear_audio_list_settings(ud->settings); + ghb_clear_audio_list_ui(ud->builder); alist = ghb_settings_get_value(settings, "audio_list"); count = ghb_array_len(alist); @@ -1166,22 +1290,26 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) if (acodec_code != 0) { - GValue *settings = ghb_dict_value_new(); - ghb_settings_set_value(settings, "AudioTrack", track); - ghb_settings_set_value(settings, "AudioEncoder", acodec); - ghb_settings_set_value(settings, "AudioEncoderActual", acodec_actual); - ghb_settings_set_value(settings, "AudioTrackQualityEnable", enable_quality); - ghb_settings_set_value(settings, "AudioTrackQuality", quality); + GValue *asettings = ghb_dict_value_new(); + ghb_settings_set_value(asettings, "AudioTrack", track); + ghb_settings_set_value(asettings, "AudioEncoder", acodec); + ghb_settings_set_value(asettings, "AudioEncoderActual", acodec_actual); + ghb_settings_set_value(asettings, "AudioTrackQualityEnable", enable_quality); + ghb_settings_set_value(asettings, "AudioTrackQuality", quality); // This gets set autimatically if the codec is passthru - ghb_settings_set_value(settings, "AudioBitrate", bitrate); - ghb_settings_set_value(settings, "AudioSamplerate", rate); - ghb_settings_set_value(settings, "AudioMixdown", mix); - ghb_settings_set_value(settings, "AudioTrackGain", gain); - ghb_settings_set_value(settings, "AudioTrackDRCSlider", drc); - ghb_add_audio(ud, settings); + ghb_settings_set_value(asettings, "AudioBitrate", bitrate); + ghb_settings_set_value(asettings, "AudioSamplerate", rate); + ghb_settings_set_value(asettings, "AudioMixdown", mix); + ghb_settings_set_value(asettings, "AudioTrackGain", gain); + ghb_settings_set_value(asettings, "AudioTrackDRCSlider", drc); + + ghb_add_audio_to_settings(ud->settings, asettings); + + ghb_add_audio_to_ui(ud->builder, asettings); ghb_adjust_audio_rate_combos(ud); } } + check_list_full(ud); } diff --git a/gtk/src/audiohandler.h b/gtk/src/audiohandler.h index 6ecca9983..d228a784f 100644 --- a/gtk/src/audiohandler.h +++ b/gtk/src/audiohandler.h @@ -28,11 +28,10 @@ #include "settings.h" void ghb_adjust_audio_rate_combos(signal_user_data_t *ud); -void ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud); -void ghb_clear_audio_list(signal_user_data_t *ud); +void ghb_set_pref_audio_settings(gint titleindex, GValue *settings); +void ghb_set_pref_audio_from_settings(signal_user_data_t *ud, GValue *settings); void ghb_set_audio(signal_user_data_t *ud, GValue *settings); -gchar* ghb_get_user_audio_lang( - signal_user_data_t *ud, gint titleindex, gint track); +gchar* ghb_get_user_audio_lang(GValue *settings, gint titleindex, gint track); void ghb_audio_list_refresh_selected(signal_user_data_t *ud); gint ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint fallback_acodec, gint copy_mask); int ghb_get_copy_mask(GValue *settings); diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index cce28befd..338b53aab 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -76,7 +76,8 @@ #include "ghbcellrenderertext.h" static void reset_chapter_list(signal_user_data_t *ud, GValue *settings); -static void update_chapter_list(signal_user_data_t *ud); +static void update_chapter_list_from_settings(GtkBuilder *builder, GValue *settings); +static void update_chapter_list_settings(GValue *settings); static GList* dvd_device_list(); static void prune_logs(signal_user_data_t *ud); void ghb_notify_done(signal_user_data_t *ud); @@ -545,16 +546,16 @@ ghb_cache_volnames(signal_user_data_t *ud) } static const gchar* -get_extension(signal_user_data_t *ud) +get_extension(GValue *settings) { int container; const gchar *extension = "error"; - container = ghb_settings_combo_int(ud->settings, "FileFormat"); + container = ghb_settings_combo_int(settings, "FileFormat"); if (container == HB_MUX_MP4) { extension = "mp4"; - if (ghb_settings_get_boolean(ud->settings, "UseM4v")) + if (ghb_settings_get_boolean(settings, "UseM4v")) { extension = "m4v"; } @@ -567,44 +568,41 @@ get_extension(signal_user_data_t *ud) } static void -set_destination(signal_user_data_t *ud) +set_destination_settings(GValue *settings) { - g_debug("set_destination"); - if (ghb_settings_get_boolean(ud->settings, "use_source_name")) + g_debug("set_destination_settings"); + if (ghb_settings_get_boolean(settings, "use_source_name")) { GString *str = g_string_new(""); - gchar *vol_name, *filename; + gchar *vol_name; const gchar *extension; gchar *new_name; gint title; - filename = ghb_settings_get_string(ud->settings, "dest_file"); - extension = get_extension(ud); - vol_name = ghb_settings_get_string(ud->settings, "volume_label"); + extension = get_extension(settings); + vol_name = ghb_settings_get_string(settings, "volume_label"); g_string_append_printf(str, "%s", vol_name); - title = ghb_settings_combo_int(ud->settings, "title"); + title = ghb_settings_get_int(settings, "title_no"); if (title >= 0) { - if (ghb_settings_get_boolean( - ud->settings, "title_no_in_destination")) + if (ghb_settings_get_boolean(settings, "title_no_in_destination")) { - title = ghb_settings_combo_int(ud->settings, "title"); g_string_append_printf(str, " - %d", title+1); } - if (ghb_settings_combo_int(ud->settings, "PtoPType") == 0 && + if (ghb_settings_combo_int(settings, "PtoPType") == 0 && ghb_settings_get_boolean( - ud->settings, "chapters_in_destination")) + settings, "chapters_in_destination")) { gint start, end; if (!ghb_settings_get_boolean( - ud->settings, "title_no_in_destination")) + settings, "title_no_in_destination")) { g_string_append_printf(str, " -"); } - start = ghb_settings_get_int(ud->settings, "start_point"); - end = ghb_settings_get_int(ud->settings, "end_point"); + start = ghb_settings_get_int(settings, "start_point"); + end = ghb_settings_get_int(settings, "end_point"); if (start == end) g_string_append_printf(str, " Ch %d", start); else @@ -613,13 +611,20 @@ set_destination(signal_user_data_t *ud) } g_string_append_printf(str, ".%s", extension); new_name = g_string_free(str, FALSE); - ghb_ui_update(ud, "dest_file", ghb_string_value(new_name)); - g_free(filename); + ghb_settings_set_string(settings, "dest_file", new_name); g_free(vol_name); g_free(new_name); } } +static void +set_destination(signal_user_data_t *ud) +{ + set_destination_settings(ud->settings); + ghb_ui_update(ud, "dest_file", + ghb_settings_get_value(ud->settings, "dest_file")); +} + static gchar* get_file_label(const gchar *filename) { @@ -1064,7 +1069,7 @@ ghb_update_destination_extension(signal_user_data_t *ud) if (busy) return; busy = TRUE; - extension = get_extension(ud); + extension = get_extension(ud->settings); entry = GTK_ENTRY(GHB_WIDGET(ud->builder, "dest_file")); filename = g_strdup(gtk_entry_get_text(entry)); for (ii = 0; containers[ii] != NULL; ii++) @@ -1488,6 +1493,90 @@ show_title_info(signal_user_data_t *ud, ghb_title_info_t *tinfo) ud->dont_clear_presets = FALSE; } +void +set_title_settings(GValue *settings, gint titleindex) +{ + ghb_title_info_t tinfo; + + ghb_settings_set_int(settings, "title", titleindex); + ghb_settings_set_int(settings, "title_no", titleindex); + + if (ghb_get_title_info (&tinfo, titleindex)) + { + ghb_settings_set_int(settings, "source_width", tinfo.width); + ghb_settings_set_int(settings, "source_height", tinfo.height); + ghb_settings_set_string(settings, "source", tinfo.path); + if (tinfo.type == HB_STREAM_TYPE || tinfo.type == HB_FF_STREAM_TYPE) + { + if (tinfo.name != NULL && tinfo.name[0] != 0) + { + ghb_settings_set_string(settings, "volume_label", tinfo.name); + } + else + { + gchar *label = "No Title Found"; + ghb_settings_set_string(settings, "volume_label", label); + } + } + ghb_settings_set_int(settings, "scale_width", + tinfo.width - tinfo.crop[2] - tinfo.crop[3]); + + // If anamorphic or keep_aspect, the hight will + // be automatically calculated + gboolean keep_aspect; + gint pic_par; + keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio"); + pic_par = ghb_settings_combo_int(settings, "PicturePAR"); + if (!(keep_aspect || pic_par) || pic_par == 3) + { + ghb_settings_set_int(settings, "scale_height", + tinfo.width - tinfo.crop[0] - tinfo.crop[1]); + } + + ghb_set_scale_settings(settings, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX); + ghb_settings_set_int(settings, "angle_count", tinfo.angle_count); + } + update_chapter_list_settings(settings); + ghb_set_pref_audio_settings(titleindex, settings); + ghb_set_pref_subtitle_settings(titleindex, settings); + set_destination_settings(settings); + + char *dest_file, *dest_dir, *dest; + dest_file = ghb_settings_get_string(settings, "dest_file"); + dest_dir = ghb_settings_get_string(settings, "dest_dir"); + dest = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dest_dir, dest_file); + ghb_settings_set_string(settings, "destination", dest); + g_free(dest_file); + g_free(dest_dir); + g_free(dest); +} + +void +ghb_add_all_titles(signal_user_data_t *ud) +{ + gint ii; + gint count = ghb_get_title_count(); + + for (ii = 0; ii < count; ii++) + { + ghb_title_info_t tinfo; + + GValue *settings = ghb_value_dup(ud->settings); + ghb_settings_set_boolean(settings, "use_source_name", TRUE); + if (ghb_get_title_info (&tinfo, ii)) + { + if (tinfo.type == HB_DVD_TYPE || + tinfo.type == HB_BD_TYPE) + { + ghb_settings_set_boolean(settings, + "title_no_in_destination", TRUE); + } + } + set_title_settings(settings, ii); + ghb_queue_add(ud, settings, ii); + } +} + static gboolean update_preview = FALSE; G_MODULE_EXPORT void @@ -1495,11 +1584,12 @@ title_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { ghb_title_info_t tinfo; gint titleindex; - + g_debug("title_changed_cb ()"); ghb_widget_to_setting(ud->settings, widget); titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_settings_set_int(ud->settings, "title_no", titleindex); ghb_update_ui_combo_box (ud, "AudioTrack", titleindex, FALSE); ghb_update_ui_combo_box (ud, "SubtitleTrack", titleindex, FALSE); @@ -1508,11 +1598,12 @@ title_changed_cb(GtkWidget *widget, signal_user_data_t *ud) show_title_info(ud, &tinfo); } ghb_check_dependency(ud, widget, NULL); - update_chapter_list (ud); - ghb_adjust_audio_rate_combos(ud); - ghb_set_pref_audio(titleindex, ud); - ghb_grey_combo_options (ud); + update_chapter_list_settings(ud->settings); + update_chapter_list_from_settings(ud->builder, ud->settings); + ghb_set_pref_audio_settings(titleindex, ud->settings); + ghb_set_pref_audio_from_settings(ud, ud->settings); ghb_set_pref_subtitle(titleindex, ud); + ghb_grey_combo_options (ud); // Unfortunately, there is no way to query how many frames were // actually generated during the scan. @@ -1631,7 +1722,6 @@ chapter_markers_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_check_dependency(ud, widget, NULL); ghb_clear_presets_selection(ud); ghb_live_reset(ud); - ghb_update_destination_extension(ud); } G_MODULE_EXPORT void @@ -3391,7 +3481,20 @@ reset_chapter_list(signal_user_data_t *ud, GValue *settings) } static void -update_chapter_list(signal_user_data_t *ud) +update_chapter_list_settings(GValue *settings) +{ + GValue *chapters; + gint titleindex; + + g_debug("update_chapter_list_settings ()"); + titleindex = ghb_settings_get_int(settings, "title_no"); + chapters = ghb_get_chapters(titleindex); + if (chapters) + ghb_settings_set_value(settings, "chapter_list", chapters); +} + +static void +update_chapter_list_from_settings(GtkBuilder *builder, GValue *settings) { GtkTreeView *treeview; GtkTreeIter iter; @@ -3402,13 +3505,11 @@ update_chapter_list(signal_user_data_t *ud) gint count; g_debug("update_chapter_list ()"); - titleindex = ghb_settings_combo_int(ud->settings, "title"); - chapters = ghb_get_chapters(titleindex); + titleindex = ghb_settings_get_int(settings, "title_no"); + chapters = ghb_settings_get_value(settings, "chapter_list"); count = ghb_array_len(chapters); - if (chapters) - ghb_settings_set_value(ud->settings, "chapter_list", chapters); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list")); + treeview = GTK_TREE_VIEW(GHB_WIDGET(builder, "chapters_list")); store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); ii = 0; if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) diff --git a/gtk/src/callbacks.h b/gtk/src/callbacks.h index 2ebcf9350..16e4b5b40 100644 --- a/gtk/src/callbacks.h +++ b/gtk/src/callbacks.h @@ -67,6 +67,7 @@ void ghb_volname_cache_init(void); void ghb_update_destination_extension(signal_user_data_t *ud); void ghb_update_pending(signal_user_data_t *ud); gboolean ghb_idle_scan(signal_user_data_t *ud); +void ghb_add_all_titles(signal_user_data_t *ud); #endif // _CALLBACKS_H_ diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index b25120594..c19a4b785 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -395,6 +395,15 @@ </object> </child> <child> + <object class="GtkAction" id="queue_add_all_menu"> + <property name="sensitive">False</property> + <property name="icon-name">hb-add-queue</property> + <property name="name">queue_add_all_menu</property> + <property name="label">Add A_ll Queue</property> + <signal handler="queue_add_all_clicked_cb" name="activate"/> + </object> + </child> + <child> <object class="GtkAction" id="queue_start_menu"> <property name="sensitive">False</property> <property name="icon-name">hb-play</property> @@ -501,6 +510,7 @@ </menu> <menu action="menuitem2"> <menuitem action="queue_add_menu"/> + <menuitem action="queue_add_all_menu"/> <menuitem action="queue_start_menu"/> <menuitem action="queue_pause_menu"/> </menu> @@ -4572,7 +4582,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property> <property name="visible">True</property> <child> <object class="GtkCheckButton" id="use_source_name"> - <property name="label" translatable="yes">Use automatic naming (uses DVD name)</property> + <property name="label" translatable="yes">Use automatic naming (uses modified source name)</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 03fb954a5..baed3892c 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -1389,7 +1389,7 @@ ghb_hb_cleanup(gboolean partial) } gint -ghb_subtitle_track_source(signal_user_data_t *ud, gint track) +ghb_subtitle_track_source(GValue *settings, gint track) { gint titleindex; @@ -1397,7 +1397,7 @@ ghb_subtitle_track_source(signal_user_data_t *ud, gint track) return SRTSUB; if (track < 0) return VOBSUB; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); if (titleindex < 0) return VOBSUB; @@ -1453,7 +1453,7 @@ ghb_subtitle_source_name(gint source) } const char* -ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track) +ghb_subtitle_track_source_name(GValue *settings, gint track) { gint titleindex; const gchar * name = "Unknown"; @@ -1469,7 +1469,7 @@ ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track) goto done; } - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); if (titleindex < 0) goto done; @@ -1498,15 +1498,15 @@ done: } gchar* -ghb_subtitle_track_lang(signal_user_data_t *ud, gint track) +ghb_subtitle_track_lang(GValue *settings, gint track) { gint titleindex; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); if (titleindex < 0) goto fail; if (track == -1) - return ghb_get_user_audio_lang(ud, titleindex, 0); + return ghb_get_user_audio_lang(settings, titleindex, 0); if (track < 0) goto fail; @@ -2111,6 +2111,12 @@ title_opts_set(GtkBuilder *builder, const gchar *name) titles[ii] = NULL; } +int +ghb_get_title_count() +{ + return title_opts.count; +} + static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter) { @@ -2206,6 +2212,27 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) } } +const gchar* +ghb_audio_track_description(gint track, int titleindex) +{ + hb_list_t * list = NULL; + hb_title_t * title = NULL; + hb_audio_config_t * audio; + gchar * desc = "Unknown"; + + g_debug("ghb_audio_track_description ()\n"); + + if (h_scan == NULL) return desc; + list = hb_get_titles( h_scan ); + title = (hb_title_t*)hb_list_item( list, titleindex ); + if (title == NULL) return desc; + if (track >= hb_list_count( title->list_audio )) return desc; + + audio = hb_list_audio_config_item(title->list_audio, track); + if (audio == NULL) return desc; + return audio->lang.description; +} + void subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) { @@ -3166,12 +3193,13 @@ ghb_get_chapters(gint titleindex) GValue *chapters = NULL; g_debug("ghb_get_chapters (title = %d)\n", titleindex); - if (h_scan == NULL) return NULL; + chapters = ghb_array_value_new(0); + + if (h_scan == NULL) return chapters; list = hb_get_titles( h_scan ); title = (hb_title_t*)hb_list_item( list, titleindex ); - if (title == NULL) return NULL; + if (title == NULL) return chapters; count = hb_list_count( title->list_chapter ); - chapters = ghb_array_value_new(count); for (ii = 0; ii < count; ii++) { chapter = hb_list_item(title->list_chapter, ii); @@ -3701,17 +3729,7 @@ picture_settings_deps(signal_user_data_t *ud) GtkWidget *widget; pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR"); - if (pic_par == 1) - { - ghb_ui_update(ud, "autoscale", ghb_boolean_value(TRUE)); - ghb_ui_update(ud, "PictureModulus", ghb_int_value(2)); - ghb_ui_update(ud, "PictureLooseCrop", ghb_boolean_value(TRUE)); - } enable_keep_aspect = (pic_par != 1 && pic_par != 2); - if (!enable_keep_aspect) - { - ghb_ui_update(ud, "PictureKeepRatio", ghb_boolean_value(TRUE)); - } keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio"); autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); @@ -3764,7 +3782,7 @@ ghb_limit_rational( gint *num, gint *den, gint limit ) } void -ghb_set_scale(signal_user_data_t *ud, gint mode) +ghb_set_scale_settings(GValue *settings, gint mode) { hb_list_t * list; hb_title_t * title; @@ -3777,14 +3795,24 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) gint aspect_n, aspect_d; gboolean keep_width = (mode & GHB_PIC_KEEP_WIDTH); gboolean keep_height = (mode & GHB_PIC_KEEP_HEIGHT); - gint step; - GtkWidget *widget; gint mod; gint max_width = 0; gint max_height = 0; g_debug("ghb_set_scale ()\n"); - picture_settings_deps(ud); + + pic_par = ghb_settings_combo_int(settings, "PicturePAR"); + if (pic_par == 1) + { + ghb_settings_set_boolean(settings, "autoscale", TRUE); + ghb_settings_set_int(settings, "PictureModulus", 2); + ghb_settings_set_boolean(settings, "PictureLooseCrop", TRUE); + } + if (pic_par == 1 || pic_par == 2) + { + ghb_settings_set_boolean(settings, "PictureKeepRatio", TRUE); + } + if (h_scan == NULL) return; list = hb_get_titles( h_scan ); if( !hb_list_count( list ) ) @@ -3794,24 +3822,20 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) } gint titleindex; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); title = hb_list_item( list, titleindex ); if (title == NULL) return; job = title->job; if (job == NULL) return; - if (ud->scale_busy) return; - ud->scale_busy = TRUE; - // First configure widgets - mod = ghb_settings_combo_int(ud->settings, "PictureModulus"); - pic_par = ghb_settings_combo_int(ud->settings, "PicturePAR"); - keep_aspect = ghb_settings_get_boolean(ud->settings, "PictureKeepRatio"); - autocrop = ghb_settings_get_boolean(ud->settings, "PictureAutoCrop"); - autoscale = ghb_settings_get_boolean(ud->settings, "autoscale"); + mod = ghb_settings_combo_int(settings, "PictureModulus"); + keep_aspect = ghb_settings_get_boolean(settings, "PictureKeepRatio"); + autocrop = ghb_settings_get_boolean(settings, "PictureAutoCrop"); + autoscale = ghb_settings_get_boolean(settings, "autoscale"); // "Noscale" is a flag that says we prefer to crop extra to satisfy // alignment constraints rather than scaling to satisfy them. - noscale = ghb_settings_get_boolean(ud->settings, "PictureLooseCrop"); + noscale = ghb_settings_get_boolean(settings, "PictureLooseCrop"); // Align dimensions to either 16 or 2 pixels // The scaler crashes if the dimensions are not divisible by 2 // x264 also will not accept dims that are not multiple of 2 @@ -3820,35 +3844,7 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) keep_width = FALSE; keep_height = FALSE; } - // Step needs to be at least 2 because odd widths cause scaler crash - // subsampled chroma requires even crop values. - step = mod; - widget = GHB_WIDGET (ud->builder, "scale_width"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - widget = GHB_WIDGET (ud->builder, "scale_height"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - if (noscale) - { - widget = GHB_WIDGET (ud->builder, "PictureTopCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - widget = GHB_WIDGET (ud->builder, "PictureBottomCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - widget = GHB_WIDGET (ud->builder, "PictureLeftCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - widget = GHB_WIDGET (ud->builder, "PictureRightCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), step, 16); - } - else - { - widget = GHB_WIDGET (ud->builder, "PictureTopCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); - widget = GHB_WIDGET (ud->builder, "PictureBottomCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); - widget = GHB_WIDGET (ud->builder, "PictureLeftCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); - widget = GHB_WIDGET (ud->builder, "PictureRightCrop"); - gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); - } + ghb_title_info_t tinfo; ghb_get_title_info (&tinfo, titleindex); if (autocrop) @@ -3857,25 +3853,22 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) crop[1] = tinfo.crop[1]; crop[2] = tinfo.crop[2]; crop[3] = tinfo.crop[3]; - ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0])); - ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1])); - ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2])); - ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3])); + ghb_settings_set_int(settings, "PictureTopCrop", crop[0]); + ghb_settings_set_int(settings, "PictureBottomCrop", crop[1]); + ghb_settings_set_int(settings, "PictureLeftCrop", crop[2]); + ghb_settings_set_int(settings, "PictureRightCrop", crop[3]); } else { - 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[0] = ghb_settings_get_int(settings, "PictureTopCrop"); + crop[1] = ghb_settings_get_int(settings, "PictureBottomCrop"); + crop[2] = ghb_settings_get_int(settings, "PictureLeftCrop"); + crop[3] = ghb_settings_get_int(settings, "PictureRightCrop"); } if (noscale) { gint need1, need2; - // Note: until we allow color formats other than yuv420 in the - // pipeline, title width and height will always be even - // // Adjust the cropping to accomplish the desired width and height crop_width = tinfo.width - crop[2] - crop[3]; crop_height = tinfo.height - crop[0] - crop[1]; @@ -3883,27 +3876,17 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) height = MOD_DOWN(crop_height, mod); need1 = (crop_height - height) / 2; - // If the top crop would fall on an odd boundary, crop an extra - // line from the top - if ((crop[0] + need1) & 1) - need1++; need2 = crop_height - height - need1; crop[0] += need1; crop[1] += need2; - need1 = (crop_width - width) / 2; - // If the left crop would fall on an odd boundary, crop an extra - // column from the left - if ((crop[2] + need1) & 1) - need1++; need2 = crop_width - width - need1; crop[2] += need1; crop[3] += need2; - - ghb_ui_update(ud, "PictureTopCrop", ghb_int64_value(crop[0])); - ghb_ui_update(ud, "PictureBottomCrop", ghb_int64_value(crop[1])); - ghb_ui_update(ud, "PictureLeftCrop", ghb_int64_value(crop[2])); - ghb_ui_update(ud, "PictureRightCrop", ghb_int64_value(crop[3])); + ghb_settings_set_int(settings, "PictureTopCrop", crop[0]); + ghb_settings_set_int(settings, "PictureBottomCrop", crop[1]); + ghb_settings_set_int(settings, "PictureLeftCrop", crop[2]); + ghb_settings_set_int(settings, "PictureRightCrop", crop[3]); } hb_reduce(&aspect_n, &aspect_d, title->width * title->pixel_aspect_width, @@ -3917,14 +3900,14 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) } else { - width = ghb_settings_get_int(ud->settings, "scale_width"); - height = ghb_settings_get_int(ud->settings, "scale_height"); + width = ghb_settings_get_int(settings, "scale_width"); + height = ghb_settings_get_int(settings, "scale_height"); if (mode & GHB_PIC_USE_MAX) { max_width = MOD_DOWN( - ghb_settings_get_int(ud->settings, "PictureWidth"), mod); + ghb_settings_get_int(settings, "PictureWidth"), mod); max_height = MOD_DOWN( - ghb_settings_get_int(ud->settings, "PictureHeight"), mod); + ghb_settings_get_int(settings, "PictureHeight"), mod); } } g_debug("max_width %d, max_height %d\n", max_width, max_height); @@ -3954,23 +3937,24 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) job->height = height; job->maxWidth = max_width; job->maxHeight = max_height; - job->crop[0] = crop[0]; job->crop[1] = crop[1]; - job->crop[2] = crop[2]; job->crop[3] = crop[3]; + job->crop[0] = crop[0]; + job->crop[1] = crop[1]; + job->crop[2] = crop[2]; + job->crop[3] = crop[3]; if (job->anamorphic.mode == 3 && !keep_aspect) { job->anamorphic.keep_display_aspect = 0; if (mode & GHB_PIC_KEEP_PAR) { job->anamorphic.par_width = - ghb_settings_get_int(ud->settings, "PicturePARWidth"); + ghb_settings_get_int(settings, "PicturePARWidth"); job->anamorphic.par_height = - ghb_settings_get_int(ud->settings, "PicturePARHeight"); + ghb_settings_get_int(settings, "PicturePARHeight"); } else { job->anamorphic.dar_width = - ghb_settings_get_int(ud->settings, - "PictureDisplayWidth"); + ghb_settings_get_int(settings, "PictureDisplayWidth"); job->anamorphic.dar_height = height; } } @@ -3981,27 +3965,22 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) // hb_set_anamorphic_size will adjust par, dar, and width/height // to conform to job parameters that have been set, including // maxWidth and maxHeight - hb_set_anamorphic_size( job, &width, &height, - &par_width, &par_height ); + hb_set_anamorphic_size(job, &width, &height, &par_width, &par_height); if (job->anamorphic.mode == 3 && !keep_aspect && mode & GHB_PIC_KEEP_PAR) { // hb_set_anamorphic_size reduces the par, which we // don't want in this case because the user is // explicitely specifying it. - par_width = ghb_settings_get_int(ud->settings, - "PicturePARWidth"); - par_height = ghb_settings_get_int(ud->settings, - "PicturePARHeight"); + par_width = ghb_settings_get_int(settings, "PicturePARWidth"); + par_height = ghb_settings_get_int(settings, "PicturePARHeight"); } } else { // Adjust dims according to max values - if (max_height) - height = MIN(height, max_height); - if (max_width) - width = MIN(width, max_width); + if (max_height) height = MIN(height, max_height); + if (max_width) width = MIN(width, max_width); if (keep_aspect) { @@ -4049,15 +4028,87 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) width = MIN(width, max_width); par_width = par_height = 1; } - ghb_ui_update(ud, "scale_width", ghb_int64_value(width)); - ghb_ui_update(ud, "scale_height", ghb_int64_value(height)); + ghb_settings_set_int(settings, "scale_width", width); + ghb_settings_set_int(settings, "scale_height", height); - gint disp_width, dar_width, dar_height; - gchar *str; + gint disp_width; disp_width = ((gdouble)par_width / par_height) * width + 0.5; - hb_reduce(&dar_width, &dar_height, disp_width, height); ghb_limit_rational(&par_width, &par_height, 65535); + + ghb_settings_set_int(settings, "PicturePARWidth", par_width); + ghb_settings_set_int(settings, "PicturePARHeight", par_height); + ghb_settings_set_int(settings, "PictureDisplayWidth", disp_width); + ghb_settings_set_int(settings, "PictureDisplayHeight", height); +} + +void +ghb_set_scale(signal_user_data_t *ud, gint mode) +{ + if (ud->scale_busy) return; + ud->scale_busy = TRUE; + + ghb_set_scale_settings(ud->settings, mode); + picture_settings_deps(ud); + + // Step needs to be at least 2 because odd widths cause scaler crash + // subsampled chroma requires even crop values. + GtkWidget *widget; + int mod = ghb_settings_combo_int(ud->settings, "PictureModulus"); + widget = GHB_WIDGET (ud->builder, "scale_width"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + widget = GHB_WIDGET (ud->builder, "scale_height"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + + // "Noscale" is a flag that says we prefer to crop extra to satisfy + // alignment constraints rather than scaling to satisfy them. + gboolean noscale = ghb_settings_get_boolean(ud->settings, "PictureLooseCrop"); + if (noscale) + { + widget = GHB_WIDGET (ud->builder, "PictureTopCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + widget = GHB_WIDGET (ud->builder, "PictureBottomCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + widget = GHB_WIDGET (ud->builder, "PictureLeftCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + widget = GHB_WIDGET (ud->builder, "PictureRightCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), mod, 16); + } + else + { + widget = GHB_WIDGET (ud->builder, "PictureTopCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); + widget = GHB_WIDGET (ud->builder, "PictureBottomCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); + widget = GHB_WIDGET (ud->builder, "PictureLeftCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); + widget = GHB_WIDGET (ud->builder, "PictureRightCrop"); + gtk_spin_button_set_increments (GTK_SPIN_BUTTON(widget), 2, 16); + } + + ghb_ui_update_from_settings(ud->builder, "autoscale", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureModulus", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureLooseCrop", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureKeepRatio", ud->settings); + + ghb_ui_update_from_settings(ud->builder, "PictureTopCrop", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureBottomCrop", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureLeftCrop", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureRightCrop", ud->settings); + + ghb_ui_update_from_settings(ud->builder, "scale_width", ud->settings); + ghb_ui_update_from_settings(ud->builder, "scale_height", ud->settings); + + ghb_ui_update_from_settings(ud->builder, "PicturePARWidth", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PicturePARHeight", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureDisplayWidth", ud->settings); + ghb_ui_update_from_settings(ud->builder, "PictureDisplayHeight", ud->settings); + gint disp_width, disp_height, dar_width, dar_height; + gchar *str; + + disp_width = ghb_settings_get_int(ud->settings, "PictureDisplayWidth"); + disp_height = ghb_settings_get_int(ud->settings, "PictureDisplayHeight"); + hb_reduce(&dar_width, &dar_height, disp_width, disp_height); gint iaspect = dar_width * 9 / dar_height; if (dar_width > 2 * dar_height) { @@ -4077,10 +4128,6 @@ ghb_set_scale(signal_user_data_t *ud, gint mode) } ghb_ui_update(ud, "display_aspect", ghb_string_value(str)); g_free(str); - ghb_ui_update(ud, "PicturePARWidth", ghb_int64_value(par_width)); - ghb_ui_update(ud, "PicturePARHeight", ghb_int64_value(par_height)); - ghb_ui_update(ud, "PictureDisplayWidth", ghb_int64_value(disp_width)); - ghb_ui_update(ud, "PictureDisplayHeight", ghb_int64_value(height)); ud->scale_busy = FALSE; } @@ -4178,18 +4225,18 @@ ghb_validate_filter_string(const gchar *str, gint max_fields) } gboolean -ghb_validate_filters(signal_user_data_t *ud) +ghb_validate_filters(GValue *settings) { gchar *str; gint index; gchar *message; - gboolean decomb_deint = ghb_settings_get_boolean(ud->settings, "PictureDecombDeinterlace"); + gboolean decomb_deint = ghb_settings_get_boolean(settings, "PictureDecombDeinterlace"); // deinte - index = ghb_settings_combo_int(ud->settings, "PictureDeinterlace"); + index = ghb_settings_combo_int(settings, "PictureDeinterlace"); if (!decomb_deint && index == 1) { - str = ghb_settings_get_string(ud->settings, "PictureDeinterlaceCustom"); + str = ghb_settings_get_string(settings, "PictureDeinterlaceCustom"); if (!ghb_validate_filter_string(str, -1)) { message = g_strdup_printf( @@ -4203,10 +4250,10 @@ ghb_validate_filters(signal_user_data_t *ud) g_free(str); } // detel - index = ghb_settings_combo_int(ud->settings, "PictureDetelecine"); + index = ghb_settings_combo_int(settings, "PictureDetelecine"); if (index == 1) { - str = ghb_settings_get_string(ud->settings, "PictureDetelecineCustom"); + str = ghb_settings_get_string(settings, "PictureDetelecineCustom"); if (!ghb_validate_filter_string(str, -1)) { message = g_strdup_printf( @@ -4220,10 +4267,10 @@ ghb_validate_filters(signal_user_data_t *ud) g_free(str); } // decomb - index = ghb_settings_combo_int(ud->settings, "PictureDecomb"); + index = ghb_settings_combo_int(settings, "PictureDecomb"); if (decomb_deint && index == 1) { - str = ghb_settings_get_string(ud->settings, "PictureDecombCustom"); + str = ghb_settings_get_string(settings, "PictureDecombCustom"); if (!ghb_validate_filter_string(str, -1)) { message = g_strdup_printf( @@ -4237,10 +4284,10 @@ ghb_validate_filters(signal_user_data_t *ud) g_free(str); } // denois - index = ghb_settings_combo_int(ud->settings, "PictureDenoise"); + index = ghb_settings_combo_int(settings, "PictureDenoise"); if (index == 1) { - str = ghb_settings_get_string(ud->settings, "PictureDenoiseCustom"); + str = ghb_settings_get_string(settings, "PictureDenoiseCustom"); if (!ghb_validate_filter_string(str, -1)) { message = g_strdup_printf( @@ -4257,13 +4304,13 @@ ghb_validate_filters(signal_user_data_t *ud) } gboolean -ghb_validate_video(signal_user_data_t *ud) +ghb_validate_video(GValue *settings) { gint vcodec, mux; gchar *message; - mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - vcodec = ghb_settings_combo_int(ud->settings, "VideoEncoder"); + mux = ghb_settings_combo_int(settings, "FileFormat"); + vcodec = ghb_settings_combo_int(settings, "VideoEncoder"); if ((mux == HB_MUX_MP4) && (vcodec == HB_VCODEC_THEORA)) { // mp4/theora combination is not supported. @@ -4277,14 +4324,13 @@ ghb_validate_video(signal_user_data_t *ud) return FALSE; } g_free(message); - vcodec = HB_VCODEC_FFMPEG_MPEG4; - ghb_ui_update(ud, "VideoEncoder", ghb_int64_value(vcodec)); + ghb_settings_set_int(settings, "VideoEncoder", HB_VCODEC_FFMPEG_MPEG4); } return TRUE; } gboolean -ghb_validate_subtitles(signal_user_data_t *ud) +ghb_validate_subtitles(GValue *settings) { hb_list_t * list; hb_title_t * title; @@ -4301,21 +4347,21 @@ ghb_validate_subtitles(signal_user_data_t *ud) gint titleindex; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); title = hb_list_item( list, titleindex ); if (title == NULL) return FALSE; - const GValue *slist, *settings; + const GValue *slist, *subtitle; gint count, ii, source; gboolean burned, one_burned = FALSE; - slist = ghb_settings_get_value(ud->settings, "subtitle_list"); + slist = ghb_settings_get_value(settings, "subtitle_list"); count = ghb_array_len(slist); for (ii = 0; ii < count; ii++) { - settings = ghb_array_get_nth(slist, ii); - source = ghb_settings_get_int(settings, "SubtitleSource"); - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); + subtitle = ghb_array_get_nth(slist, ii); + source = ghb_settings_get_int(subtitle, "SubtitleSource"); + burned = ghb_settings_get_boolean(subtitle, "SubtitleBurned"); if (burned && one_burned) { // MP4 can only handle burned vobsubs. make sure there isn't @@ -4340,7 +4386,7 @@ ghb_validate_subtitles(signal_user_data_t *ud) { gchar *filename; - filename = ghb_settings_get_string(settings, "SrtFile"); + filename = ghb_settings_get_string(subtitle, "SrtFile"); if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { message = g_strdup_printf( @@ -4362,7 +4408,7 @@ ghb_validate_subtitles(signal_user_data_t *ud) } gboolean -ghb_validate_audio(signal_user_data_t *ud) +ghb_validate_audio(GValue *settings) { hb_list_t * list; hb_title_t * title; @@ -4380,15 +4426,15 @@ ghb_validate_audio(signal_user_data_t *ud) gint titleindex; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); title = hb_list_item( list, titleindex ); if (title == NULL) return FALSE; - gint mux = ghb_settings_combo_int(ud->settings, "FileFormat"); + gint mux = ghb_settings_combo_int(settings, "FileFormat"); const GValue *audio_list; gint count, ii; - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + audio_list = ghb_settings_get_value(settings, "audio_list"); count = ghb_array_len(audio_list); for (ii = 0; ii < count; ii++) { diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 4d6f1efa3..407dc7315 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -126,6 +126,7 @@ void ghb_backend_queue_scan(const gchar *path, gint titleindex); gboolean ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex); void ghb_par_init(signal_user_data_t *ud); void ghb_set_scale(signal_user_data_t *ud, gint mode); +void ghb_set_scale_settings(GValue *settings, gint mode); GValue* ghb_get_chapters(gint titleindex); void ghb_get_chapter_duration(gint ti, gint ii, gint *hh, gint *mm, gint *ss); void ghb_part_duration(gint tt, gint sc, gint ec, gint *hh, gint *mm, gint *ss); @@ -144,6 +145,7 @@ gchar* ghb_get_source_audio_lang(gint titleindex, gint track); gint ghb_find_audio_track( gint titleindex, const gchar *lang, gint acodec, gint fallback_acodec, GHashTable *track_indices); +const gchar* ghb_audio_track_description(gint track, int titleindex); void ghb_add_all_subtitles(signal_user_data_t *ud, gint titleindex); gint ghb_find_pref_subtitle_track(const gchar *lang); gint ghb_find_subtitle_track( @@ -158,16 +160,17 @@ GdkPixbuf* ghb_get_preview_image( gint *width, gint *height); gchar* ghb_dvd_volname(const gchar *device); gint ghb_get_title_number(gint titleindex); -gint ghb_subtitle_track_source(signal_user_data_t *ud, gint track); -const char* ghb_subtitle_track_source_name(signal_user_data_t *ud, gint track); +int ghb_get_title_count(); +gint ghb_subtitle_track_source(GValue *settings, gint track); +const char* ghb_subtitle_track_source_name(GValue *settings, gint track); const char* ghb_subtitle_source_name(gint source); -gchar* ghb_subtitle_track_lang(signal_user_data_t *ud, gint track); +gchar* ghb_subtitle_track_lang(GValue *settings, gint track); gboolean ghb_validate_vquality(GValue *settings); -gboolean ghb_validate_audio(signal_user_data_t *ud); -gboolean ghb_validate_subtitles(signal_user_data_t *ud); -gboolean ghb_validate_video(signal_user_data_t *ud); -gboolean ghb_validate_filters(signal_user_data_t *ud); +gboolean ghb_validate_audio(GValue *settings); +gboolean ghb_validate_subtitles(GValue *settings); +gboolean ghb_validate_video(GValue *settings); +gboolean ghb_validate_filters(GValue *settings); gboolean ghb_validate_filter_string(const gchar *str, gint max_fields); void ghb_hb_cleanup(gboolean partial); gint ghb_lookup_combo_int(const gchar *name, const GValue *gval); diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 0a6f65aba..d6b856f13 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -54,6 +54,8 @@ <integer>1</integer> <key>start_frame</key> <integer>-1</integer> + <key>title_no</key> + <integer>0</integer> <key>title</key> <string>none</string> <key>volume_label</key> @@ -313,7 +315,7 @@ <key>AudioBitrate</key> <string>192</string> <key>AudioEncoder</key> - <string>ac3pass</string> + <string>copy:ac3</string> <key>AudioTrack</key> <integer>1</integer> <key>AudioTrackDescription</key> diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 8305c4ae3..2f46cda4c 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -4230,14 +4230,11 @@ ghb_refresh_preset(signal_user_data_t *ud) 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_audio_settings(titleindex, ud->settings); + ghb_set_pref_audio_from_settings(ud, ud->settings); ghb_set_pref_subtitle(titleindex, ud); ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE); if (ghb_get_title_info (&tinfo, titleindex)) @@ -4310,14 +4307,11 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ 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_audio_settings(titleindex, ud->settings); + ghb_set_pref_audio_from_settings(ud, ud->settings); ghb_set_pref_subtitle(titleindex, ud); ghb_settings_set_boolean(ud->settings, "preset_modified", FALSE); if (ghb_get_title_info (&tinfo, titleindex)) diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 8769ad5b3..539e4d79e 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -519,7 +519,7 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) } static gboolean -validate_settings(signal_user_data_t *ud) +validate_settings(signal_user_data_t *ud, GValue *settings, gint batch) { // Check to see if the dest file exists or is // already in the queue @@ -527,9 +527,9 @@ validate_settings(signal_user_data_t *ud) gint count, ii; gint titleindex; - titleindex = ghb_settings_combo_int(ud->settings, "title"); + titleindex = ghb_settings_combo_int(settings, "title"); if (titleindex < 0) return FALSE; - dest = ghb_settings_get_string(ud->settings, "destination"); + dest = ghb_settings_get_string(settings, "destination"); count = ghb_array_len(ud->queue); for (ii = 0; ii < count; ii++) { @@ -585,41 +585,44 @@ validate_settings(signal_user_data_t *ud) return FALSE; } #endif - GFile *gfile; - GFileInfo *info; - guint64 size; - gchar *resolved = ghb_resolve_symlink(destdir); - - gfile = g_file_new_for_path(resolved); - info = g_file_query_filesystem_info(gfile, - G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL); - if (info != NULL) + if (!batch) { - if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) + GFile *gfile; + GFileInfo *info; + guint64 size; + gchar *resolved = ghb_resolve_symlink(destdir); + + gfile = g_file_new_for_path(resolved); + info = g_file_query_filesystem_info(gfile, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL); + if (info != NULL) { - size = g_file_info_get_attribute_uint64(info, - G_FILE_ATTRIBUTE_FILESYSTEM_FREE); - - gint64 fsize = (guint64)10 * 1024 * 1024 * 1024; - if (size < fsize) + if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) { - message = g_strdup_printf( - "Destination filesystem is almost full: %uM free\n\n" - "Encode may be incomplete if you proceed.\n", - (guint)(size / (1024L*1024L))); - if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Proceed")) + size = g_file_info_get_attribute_uint64(info, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + + gint64 fsize = (guint64)10 * 1024 * 1024 * 1024; + if (size < fsize) { - g_free(dest); + message = g_strdup_printf( + "Destination filesystem is almost full: %uM free\n\n" + "Encode may be incomplete if you proceed.\n", + (guint)(size / (1024L*1024L))); + if (!ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "Cancel", "Proceed")) + { + g_free(dest); + g_free(message); + return FALSE; + } g_free(message); - return FALSE; } - g_free(message); } + g_object_unref(info); } - g_object_unref(info); + g_object_unref(gfile); + g_free(resolved); } - g_object_unref(gfile); - g_free(resolved); g_free(destdir); if (g_file_test(dest, G_FILE_TEST_EXISTS)) { @@ -639,44 +642,42 @@ validate_settings(signal_user_data_t *ud) } g_free(dest); // Validate video quality is in a reasonable range - if (!ghb_validate_vquality(ud->settings)) + if (!ghb_validate_vquality(settings)) { return FALSE; } // Validate audio settings - if (!ghb_validate_audio(ud)) + if (!ghb_validate_audio(settings)) { return FALSE; } // Validate audio settings - if (!ghb_validate_subtitles(ud)) + if (!ghb_validate_subtitles(settings)) { return FALSE; } // Validate video settings - if (!ghb_validate_video(ud)) + if (!ghb_validate_video(settings)) { return FALSE; } // Validate filter settings - if (!ghb_validate_filters(ud)) + if (!ghb_validate_filters(settings)) { return FALSE; } - ghb_audio_list_refresh(ud); return TRUE; } -static gboolean -queue_add(signal_user_data_t *ud) +gboolean +ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch) { // Add settings to the queue - GValue *settings; gint titleindex; gint titlenum; g_debug("queue_add ()"); - if (!validate_settings(ud)) + if (!validate_settings(ud, settings, batch)) { return FALSE; } @@ -684,7 +685,6 @@ queue_add(signal_user_data_t *ud) if (ud->queue == NULL) ud->queue = ghb_array_value_new(32); // Make a copy of current settings to be used for the new job - settings = ghb_value_dup(ud->settings); ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING); ghb_settings_set_int(settings, "job_unique_id", 0); titleindex = ghb_settings_combo_int(settings, "title"); @@ -702,7 +702,18 @@ G_MODULE_EXPORT void queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) { g_debug("queue_add_clicked_cb ()"); - queue_add(ud); + GValue *settings = ghb_value_dup(ud->settings); + if (!ghb_queue_add(ud, settings, 0)) + ghb_value_free(settings); + // Validation of settings may have changed audio list + ghb_audio_list_refresh(ud); +} + +G_MODULE_EXPORT void +queue_add_all_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + g_debug("queue_add_all_clicked_cb ()"); + ghb_add_all_titles(ud); } G_MODULE_EXPORT void @@ -1001,6 +1012,8 @@ ghb_queue_buttons_grey(signal_user_data_t *ud) gtk_widget_set_sensitive(widget, show_start); action = GHB_ACTION(ud->builder, "queue_add_menu"); gtk_action_set_sensitive(action, show_start); + action = GHB_ACTION(ud->builder, "queue_add_all_menu"); + gtk_action_set_sensitive(action, show_start); widget = GHB_WIDGET (ud->builder, "queue_start1"); if (show_stop) @@ -1180,8 +1193,14 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { // The queue has no running or pending jobs. // Add current settings to the queue, then run. - if (!queue_add(ud)) + GValue *settings = ghb_value_dup(ud->settings); + if (!ghb_queue_add(ud, settings, 0)) + { + ghb_value_free(settings); return; + } + // Validation of settings may have changed audio list + ghb_audio_list_refresh(ud); } if (state == GHB_STATE_IDLE) { diff --git a/gtk/src/queuehandler.h b/gtk/src/queuehandler.h index 36a8e4449..a8c103ac9 100644 --- a/gtk/src/queuehandler.h +++ b/gtk/src/queuehandler.h @@ -30,5 +30,6 @@ void ghb_queue_buttons_grey(signal_user_data_t *ud); gboolean ghb_reload_queue(signal_user_data_t *ud); +gboolean ghb_queue_add(signal_user_data_t *ud, GValue *settings, gint batch); #endif // _QUEUEHANDLER_H_ diff --git a/gtk/src/settings.c b/gtk/src/settings.c index 2fe0b5e6d..389120351 100644 --- a/gtk/src/settings.c +++ b/gtk/src/settings.c @@ -707,6 +707,28 @@ update_widget(GtkWidget *widget, const GValue *value) } int +ghb_ui_update_from_settings(GtkBuilder *builder, const gchar *name, const GValue *settings) +{ + GObject *object; + GValue * value; + + g_debug("ghb_ui_update_from_settings() %s", name); + if (name == NULL) + return 0; + value = ghb_settings_get_value(settings, name); + if (value == NULL) + return 0; + object = GHB_OBJECT(builder, name); + if (object == NULL) + { + g_debug("Failed to find widget for key: %s\n", name); + return -1; + } + update_widget((GtkWidget*)object, value); + return 0; +} + +int ghb_ui_update(signal_user_data_t *ud, const gchar *name, const GValue *value) { GObject *object; diff --git a/gtk/src/settings.h b/gtk/src/settings.h index d9d92beb1..f9f72e123 100644 --- a/gtk/src/settings.h +++ b/gtk/src/settings.h @@ -115,6 +115,8 @@ gint ghb_widget_boolean(GtkWidget *widget); void ghb_widget_to_setting(GValue *settings, GtkWidget *widget); int ghb_ui_update( signal_user_data_t *ud, const gchar *name, const GValue *value); +int ghb_ui_update_from_settings( + GtkBuilder *builder, const gchar *name, const GValue *settings); const gchar* ghb_get_setting_key(GtkWidget *widget); #endif // _SETTINGS_H_ diff --git a/gtk/src/subtitlehandler.c b/gtk/src/subtitlehandler.c index 14d3da0a0..ffe38a0e6 100644 --- a/gtk/src/subtitlehandler.c +++ b/gtk/src/subtitlehandler.c @@ -22,8 +22,12 @@ #include "audiohandler.h" #include "subtitlehandler.h" +static gboolean ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings); +static void ghb_add_subtitle_to_ui(signal_user_data_t *ud, GValue *subsettings); static void add_to_subtitle_list(signal_user_data_t *ud, GValue *settings); static void add_to_srt_list(signal_user_data_t *ud, GValue *settings); +static void ghb_clear_subtitle_list_settings(GValue *settings); +static void ghb_clear_subtitle_list(signal_user_data_t *ud); static void free_subtitle_index_list(gpointer data) @@ -39,12 +43,6 @@ free_subtitle_key(gpointer data) } static gboolean -mustBurn(signal_user_data_t *ud, GValue *settings) -{ - return FALSE; -} - -static gboolean canBurn(int source) { return (source == VOBSUB || source == SSASUB); @@ -75,37 +73,76 @@ ghb_soft_in_subtitle_list(GValue *subtitle_list) } void +ghb_subtitle_exclusive_burn_settings(GValue *settings, gint index) +{ + GValue *subtitle_list; + GValue *subsettings; + gint ii, count; + + g_debug("ghb_subtitle_exclusive_burn_settings"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); + count = ghb_array_len(subtitle_list); + for (ii = 0; ii < count; ii++) + { + if (ii != index) + { +printf("settings burn %d also %d\n", index, ii); + subsettings = ghb_array_get_nth(subtitle_list, ii); + ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE); + } + } +} + +void ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index) { GValue *subtitle_list; - GValue *settings; + GValue *subsettings; gint ii, count; GtkTreeView *tv; GtkTreeModel *tm; GtkTreeIter ti; - gboolean burned; g_debug("ghb_subtitle_exclusive_burn"); subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); count = ghb_array_len(subtitle_list); for (ii = 0; ii < count; ii++) { - settings = ghb_array_get_nth(subtitle_list, ii); - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); - tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); g_return_if_fail(tv != NULL); tm = gtk_tree_view_get_model(tv); gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii); - if (burned && ii != index && !mustBurn(ud, settings)) + if (ii != index) { - ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE); +printf("ui burn %d also %d\n", index, ii); + subsettings = ghb_array_get_nth(subtitle_list, ii); + ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE); gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, FALSE, -1); } } } void +ghb_subtitle_exclusive_default_settings(GValue *settings, gint index) +{ + GValue *subtitle_list; + GValue *subtitle; + gint ii, count; + + g_debug("ghb_subtitle_exclusive_default"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); + count = ghb_array_len(subtitle_list); + for (ii = 0; ii < count; ii++) + { + if (ii != index) + { + subtitle = ghb_array_get_nth(subtitle_list, ii); + ghb_settings_set_boolean(subtitle, "SubtitleDefaultTrack", FALSE); + } + } +} + +void ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index) { GValue *subtitle_list; @@ -180,12 +217,11 @@ ghb_add_srt(signal_user_data_t *ud, GValue *settings) widget = GHB_WIDGET (ud->builder, "srt_add"); gtk_widget_set_sensitive(widget, FALSE); } - ghb_update_destination_extension(ud); ghb_live_reset(ud); } -void -ghb_add_subtitle(signal_user_data_t *ud, GValue *settings) +static gboolean +ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings) { // Add the current subtitle settings to the list. GValue *subtitle_list; @@ -194,39 +230,53 @@ ghb_add_subtitle(signal_user_data_t *ud, GValue *settings) const gchar *track; const gchar *lang; - g_debug("ghb_add_subtitle ()"); + g_debug("ghb_add_subtitle_to_settings ()"); - // Add the long track description so the queue can access it - // when a different title is selected. - track = ghb_settings_combo_option(settings, "SubtitleTrack"); - ghb_settings_set_string(settings, "SubtitleTrackDescription", track); - - lang = ghb_settings_combo_string(settings, "SubtitleTrack"); - ghb_settings_set_string(settings, "SubtitleLanguage", lang); - - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) { subtitle_list = ghb_array_value_new(8); - ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list); + ghb_settings_set_value(settings, "subtitle_list", subtitle_list); } - count = ghb_array_len(subtitle_list); + count = ghb_array_len(subtitle_list); // Don't allow more than 99 - // This is a had limit imposed by libhb/sync.c:GetFifoForId() + // This is a hard limit imposed by libhb/reader.c:GetFifoForId() if (count >= 99) { - ghb_value_free(settings); - return; + ghb_value_free(subsettings); + return FALSE; } - ghb_array_append(subtitle_list, settings); - add_to_subtitle_list(ud, settings); + // Add the long track description so the queue can access it + // when a different title is selected. + track = ghb_settings_combo_option(subsettings, "SubtitleTrack"); + ghb_settings_set_string(subsettings, "SubtitleTrackDescription", track); - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); + lang = ghb_settings_combo_string(subsettings, "SubtitleTrack"); + ghb_settings_set_string(subsettings, "SubtitleLanguage", lang); + + ghb_array_append(subtitle_list, subsettings); + + burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned"); if (burned) - ghb_subtitle_exclusive_burn(ud, count); - if (count == 98) + ghb_subtitle_exclusive_burn_settings(settings, count); + return TRUE; +} + +static void +ghb_add_subtitle_to_ui(signal_user_data_t *ud, GValue *subsettings) +{ + // Add the current subtitle settings to the list. + GValue *subtitle_list; + gint count; + + g_debug("ghb_add_subtitle_to_ui ()"); + add_to_subtitle_list(ud, subsettings); + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + count = ghb_array_len(subtitle_list); + if (count == 99) { GtkWidget *widget; widget = GHB_WIDGET (ud->builder, "subtitle_add"); @@ -234,7 +284,6 @@ ghb_add_subtitle(signal_user_data_t *ud, GValue *settings) widget = GHB_WIDGET (ud->builder, "srt_add"); gtk_widget_set_sensitive(widget, FALSE); } - ghb_update_destination_extension(ud); ghb_live_reset(ud); } @@ -263,15 +312,19 @@ add_all_pref_subtitles(signal_user_data_t *ud) // Add to subtitle list ghb_settings_set_int(subtitle, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud, track); + source = ghb_subtitle_track_source(ud->settings, track); ghb_settings_set_int(subtitle, "SubtitleSource", source); - ghb_add_subtitle(ud, subtitle); + + if (!ghb_add_subtitle_to_settings(ud->settings, subtitle)) + return; + + ghb_add_subtitle_to_ui(ud, subtitle); } } } void -ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) +ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings) { gint track; GHashTable *track_indices; @@ -292,8 +345,8 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) // The first (default) audio track language does NOT match the users // chosen Preferred Language AND the Preferred Language is NOT Any (und). // - audio_lang = ghb_get_user_audio_lang(ud, titleindex, 0); - pref_lang = ghb_settings_get_string(ud->settings, "PreferredLanguage"); + audio_lang = ghb_get_user_audio_lang(settings, titleindex, 0); + pref_lang = ghb_settings_get_string(settings, "PreferredLanguage"); if (audio_lang != NULL && pref_lang != NULL && (strcmp(audio_lang, pref_lang) == 0 || strcmp("und", pref_lang) == 0)) @@ -305,18 +358,17 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) track_indices = g_hash_table_new_full(g_str_hash, g_str_equal, free_subtitle_key, free_subtitle_index_list); - ghb_ui_update(ud, "SubtitleTrack", ghb_int_value(0)); + ghb_settings_set_int(settings, "SubtitleTrack", 0); // Clear the subtitle list - ghb_clear_subtitle_list(ud); + ghb_clear_subtitle_list_settings(settings); if (titleindex < 0) { - add_all_pref_subtitles(ud); return; } // Find "best" subtitle based on subtitle preferences - pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList"); + pref_subtitle = ghb_settings_get_value(settings, "SubtitleList"); count = ghb_array_len(pref_subtitle); jj = 0; @@ -339,7 +391,7 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) if (track >= -1) { GValue *dup = ghb_value_dup(subtitle); - lang = ghb_subtitle_track_lang(ud, track); + lang = ghb_subtitle_track_lang(settings, track); ghb_settings_set_int(dup, "SubtitleTrack", track); if (foreign_lang_index < 0 && pref_lang != NULL && strcmp(lang, pref_lang) == 0) @@ -350,11 +402,11 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) ghb_settings_take_value(dup, "SubtitleDefaultTrack", ghb_boolean_value_new(TRUE)); } - source = ghb_subtitle_track_source(ud, track); + source = ghb_subtitle_track_source(settings, track); ghb_settings_set_int(dup, "SubtitleSource", source); if (source == CC608SUB || source == CC708SUB) found_cc = TRUE; - ghb_add_subtitle(ud, dup); + ghb_add_subtitle_to_settings(settings, dup); jj++; g_free(lang); } @@ -362,7 +414,7 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) if (foreign_lang_index < 0 && pref_lang != NULL) { // Subtitle for foreign language audio not added yet - GValue *settings; + GValue *subsettings; gboolean burn; track = ghb_find_subtitle_track(titleindex, pref_lang, FALSE, FALSE, VOBSUB, track_indices); @@ -370,19 +422,19 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) { int source; - settings = ghb_dict_value_new(); - ghb_settings_set_int(settings, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud, track); - ghb_settings_set_int(settings, "SubtitleSource", source); - burn = mustBurn(ud, settings); - ghb_settings_take_value(settings, "SubtitleForced", + subsettings = ghb_dict_value_new(); + ghb_settings_set_int(subsettings, "SubtitleTrack", track); + source = ghb_subtitle_track_source(settings, track); + ghb_settings_set_int(subsettings, "SubtitleSource", source); + burn = FALSE; + ghb_settings_take_value(subsettings, "SubtitleForced", ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(settings, "SubtitleBurned", + ghb_settings_take_value(subsettings, "SubtitleBurned", ghb_boolean_value_new(burn)); - ghb_settings_take_value(settings, "SubtitleDefaultTrack", + ghb_settings_take_value(subsettings, "SubtitleDefaultTrack", ghb_boolean_value_new(TRUE)); - ghb_add_subtitle(ud, settings); + ghb_add_subtitle_to_settings(settings, subsettings); foreign_lang_index = jj; } } @@ -391,39 +443,39 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) GValue *subtitle_list; gboolean burn, def; - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); subtitle = ghb_array_get_nth(subtitle_list, foreign_lang_index); burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned"); def = ghb_settings_get_boolean(subtitle, "SubtitleDefaultTrack"); if (burn) - ghb_subtitle_exclusive_burn(ud, foreign_lang_index); + ghb_subtitle_exclusive_burn_settings(settings, foreign_lang_index); if (def) - ghb_subtitle_exclusive_default(ud, foreign_lang_index); + ghb_subtitle_exclusive_default_settings(settings, foreign_lang_index); ghb_log("adding subtitle for foreign language audio: %s", audio_lang); } - if (ghb_settings_get_boolean(ud->settings, "AddCC") && !found_cc) + if (ghb_settings_get_boolean(settings, "AddCC") && !found_cc) { // Subtitle for foreign language audio not added yet - GValue *settings; + GValue *subsettings; track = ghb_find_cc_track(titleindex); if (track >= 0) { int source; - settings = ghb_dict_value_new(); - ghb_settings_set_int(settings, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud, track); - ghb_settings_set_int(settings, "SubtitleSource", source); - ghb_settings_take_value(settings, "SubtitleForced", + subsettings = ghb_dict_value_new(); + ghb_settings_set_int(subsettings, "SubtitleTrack", track); + source = ghb_subtitle_track_source(settings, track); + ghb_settings_set_int(subsettings, "SubtitleSource", source); + ghb_settings_take_value(subsettings, "SubtitleForced", ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(settings, "SubtitleBurned", + ghb_settings_take_value(subsettings, "SubtitleBurned", ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(settings, "SubtitleDefaultTrack", + ghb_settings_take_value(subsettings, "SubtitleDefaultTrack", ghb_boolean_value_new(FALSE)); - ghb_add_subtitle(ud, settings); + ghb_add_subtitle_to_settings(settings, subsettings); ghb_log("adding Closed Captions: %s", audio_lang); } } @@ -434,6 +486,29 @@ ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) g_hash_table_destroy(track_indices); } +void +ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud) +{ + ghb_set_pref_subtitle_settings(titleindex, ud->settings); + ghb_clear_subtitle_list(ud); + if (titleindex < 0) + { + add_all_pref_subtitles(ud); + return; + } + + gint count, ii; + GValue *subtitle_list; + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + count = ghb_array_len(subtitle_list); + for (ii = 0; ii < count; ii++) + { + GValue *subtitle; + subtitle = ghb_array_get_nth(subtitle_list, ii); + ghb_add_subtitle_to_ui(ud, subtitle); + } +} + gint ghb_selected_subtitle_row(signal_user_data_t *ud) { @@ -581,8 +656,6 @@ subtitle_burned_toggled_cb( source = ghb_settings_get_int(settings, "SubtitleSource"); if (!canBurn(source)) return; - if (!active && mustBurn(ud, settings)) - return; ghb_settings_set_boolean(settings, "SubtitleBurned", active); gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1); @@ -596,7 +669,6 @@ subtitle_burned_toggled_cb( // Unburn the rest if (active) ghb_subtitle_exclusive_burn(ud, row); - ghb_update_destination_extension(ud); ghb_live_reset(ud); } @@ -638,8 +710,6 @@ subtitle_default_toggled_cb( return; settings = ghb_array_get_nth(subtitle_list, row); - if (active && mustBurn(ud, settings)) - return; ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active); gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1); @@ -790,7 +860,7 @@ subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud) track = ghb_settings_combo_option(settings, "SubtitleTrack"); ghb_settings_set_string(settings, "SubtitleTrackDescription", track); tt = ghb_settings_get_int(settings, "SubtitleTrack"); - source = ghb_subtitle_track_source(ud, tt); + source = ghb_subtitle_track_source(ud->settings, tt); ghb_settings_set_int(settings, "SubtitleSource", source); lang = ghb_settings_combo_string(settings, "SubtitleTrack"); ghb_settings_set_string(settings, "SubtitleLanguage", lang); @@ -875,22 +945,29 @@ srt_lang_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } } -void -ghb_clear_subtitle_list(signal_user_data_t *ud) +static void +ghb_clear_subtitle_list_settings(GValue *settings) { - GtkTreeView *treeview; - GtkListStore *store; GValue *subtitle_list; - + g_debug("clear_subtitle_list ()"); - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) { subtitle_list = ghb_array_value_new(8); - ghb_settings_set_value(ud->settings, "subtitle_list", subtitle_list); + ghb_settings_set_value(settings, "subtitle_list", subtitle_list); } else ghb_array_value_reset(subtitle_list, 8); +} + +static void +ghb_clear_subtitle_list(signal_user_data_t *ud) +{ + GtkTreeView *treeview; + GtkListStore *store; + + g_debug("clear_subtitle_list ()"); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); gtk_list_store_clear (store); @@ -1182,12 +1259,8 @@ subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) settings = ghb_dict_value_new(); ghb_settings_set_int(settings, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud, track); + source = ghb_subtitle_track_source(ud->settings, track); ghb_settings_set_int(settings, "SubtitleSource", source); - if (mustBurn(ud, settings)) - { - burned = TRUE; - } ghb_settings_take_value(settings, "SubtitleForced", ghb_boolean_value_new(FALSE)); ghb_settings_take_value(settings, "SubtitleBurned", @@ -1195,7 +1268,10 @@ subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) ghb_settings_take_value(settings, "SubtitleDefaultTrack", ghb_boolean_value_new(FALSE)); - ghb_add_subtitle(ud, settings); + if (!ghb_add_subtitle_to_settings(ud->settings, settings)) + return; + + ghb_add_subtitle_to_ui(ud, settings); } G_MODULE_EXPORT void @@ -1256,7 +1332,6 @@ ghb_subtitle_prune(signal_user_data_t *ud) { GtkTreeView *tv; GtkTreeModel *tm; - GtkTreeIter ti; GValue *subtitle_list; gint count, ii; gint first_track = 0, one_burned = 0; @@ -1276,12 +1351,6 @@ ghb_subtitle_prune(signal_user_data_t *ud) settings = ghb_array_get_nth(subtitle_list, ii); burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); - if (!burned && mustBurn(ud, settings)) - { - gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii); - gtk_list_store_remove (GTK_LIST_STORE(tm), &ti); - ghb_array_remove(subtitle_list, ii); - } if (burned) { first_track = ii; @@ -1303,6 +1372,7 @@ ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings) gint titleindex; g_debug("ghb_reset_subtitles"); + ghb_clear_subtitle_list_settings(ud->settings); ghb_clear_subtitle_list(ud); titleindex = ghb_settings_combo_int(ud->settings, "title"); if (titleindex < 0) @@ -1319,7 +1389,11 @@ ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings) if (source == SRTSUB) ghb_add_srt(ud, subtitle); else - ghb_add_subtitle(ud, subtitle); + { + if (!ghb_add_subtitle_to_settings(ud->settings, subtitle)) + return; + ghb_add_subtitle_to_ui(ud, subtitle); + } } } diff --git a/gtk/src/subtitlehandler.h b/gtk/src/subtitlehandler.h index 839057826..ac662499f 100644 --- a/gtk/src/subtitlehandler.h +++ b/gtk/src/subtitlehandler.h @@ -28,12 +28,10 @@ #include "settings.h" void ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud); -void ghb_clear_subtitle_list(signal_user_data_t *ud); +void ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings); void ghb_set_subtitle(signal_user_data_t *ud, gint track, GValue *settings); GValue* ghb_selected_subtitle_settings(signal_user_data_t *ud); gint ghb_selected_subtitle_row(signal_user_data_t *ud); -void ghb_add_subtitle( - signal_user_data_t *ud, GValue *settings); void ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings); void ghb_subtitle_prune(signal_user_data_t *ud); gboolean ghb_soft_in_subtitle_list(GValue *subtitle_list); |