diff options
-rw-r--r-- | gtk/src/audiohandler.c | 2212 | ||||
-rw-r--r-- | gtk/src/audiohandler.h | 11 | ||||
-rw-r--r-- | gtk/src/callbacks.c | 16 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 2636 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 1008 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 25 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 41 | ||||
-rw-r--r-- | gtk/src/main.c | 197 | ||||
-rw-r--r-- | gtk/src/makedeps.py | 27 | ||||
-rw-r--r-- | gtk/src/presets.c | 304 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 8 | ||||
-rw-r--r-- | gtk/src/settings.c | 47 | ||||
-rw-r--r-- | gtk/src/settings.h | 1 | ||||
-rw-r--r-- | gtk/src/subtitlehandler.c | 2128 | ||||
-rw-r--r-- | gtk/src/subtitlehandler.h | 12 | ||||
-rw-r--r-- | gtk/src/values.c | 1 | ||||
-rw-r--r-- | gtk/src/widgetdeps.c | 10 |
17 files changed, 5125 insertions, 3559 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c index 67e979d14..f30b5ee87 100644 --- a/gtk/src/audiohandler.c +++ b/gtk/src/audiohandler.c @@ -2,9 +2,9 @@ /* * audiohandler.c * Copyright (C) John Stebbins 2008-2013 <stebbins@stebbins> - * + * * audiohandler.c is free software. - * + * * You may redistribute it and/or modify it under the terms of the * GNU General Public License, as published by the Free Software * Foundation; either version 2 of the License, or (at your option) @@ -20,67 +20,86 @@ #include "callbacks.h" #include "preview.h" #include "audiohandler.h" +#include "presets.h" -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 audio_add_to_settings(GValue *settings, GValue *asettings); +static void ghb_add_audio_to_ui(signal_user_data_t *ud, const GValue *settings); +static GValue* audio_get_selected_settings(signal_user_data_t *ud, int *index); static void ghb_clear_audio_list_settings(GValue *settings); static void ghb_clear_audio_list_ui(GtkBuilder *builder); static gboolean block_updates = FALSE; -static void audio_deps(signal_user_data_t *ud) +static void enable_quality_widget(signal_user_data_t *ud, int acodec) +{ + GtkWidget *widget1, *widget2; + + widget1 = GHB_WIDGET(ud->builder, "AudioTrackQualityEnable"); + widget2 = GHB_WIDGET(ud->builder, "AudioTrackBitrateEnable"); + if (hb_audio_quality_get_default(acodec) == HB_INVALID_AUDIO_QUALITY) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget2), TRUE); + gtk_widget_set_sensitive(widget1, FALSE); + } + else + { + gtk_widget_set_sensitive(widget1, TRUE); + } +} + +static void audio_deps(signal_user_data_t *ud, GValue *asettings, GtkWidget *widget) { + ghb_adjust_audio_rate_combos(ud); + ghb_grey_combo_options (ud); + if (widget != NULL) + ghb_check_dependency(ud, widget, NULL); + gint track = -1, encoder = 0; hb_audio_config_t *aconfig = NULL; gint titleindex = ghb_settings_combo_int(ud->settings, "title"); - GValue *asettings = get_selected_asettings(ud); if (asettings != NULL) { track = ghb_settings_combo_int(asettings, "AudioTrack"); - encoder = ghb_settings_combo_int(asettings, "AudioEncoderActual"); + encoder = ghb_settings_combo_int(asettings, "AudioEncoder"); aconfig = ghb_get_scan_audio_info(titleindex, track); } + gboolean is_passthru = (encoder & HB_ACODEC_PASS_FLAG); gboolean enable_drc = TRUE; if (aconfig != NULL) { enable_drc = hb_audio_can_apply_drc(aconfig->in.codec, - aconfig->in.codec_param, encoder); + aconfig->in.codec_param, encoder) && + !is_passthru; } - GtkWidget * widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSlider"); + widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSlider"); gtk_widget_set_sensitive(widget, enable_drc); widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSliderLabel"); gtk_widget_set_sensitive(widget, enable_drc); widget = GHB_WIDGET(ud->builder, "AudioTrackDRCValue"); gtk_widget_set_sensitive(widget, enable_drc); -} -void -ghb_show_hide_advanced_audio( signal_user_data_t *ud ) -{ - GtkWidget *widget; - - g_debug("audio_advanced_clicked_cb ()"); - widget = GHB_WIDGET(ud->builder, "AdvancedAudioPassTable"); - if (!ghb_settings_get_boolean(ud->settings, "AdvancedAutoPassthru")) - gtk_widget_hide(widget); - else - gtk_widget_show(widget); -} + enable_quality_widget(ud, encoder); -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); + widget = GHB_WIDGET(ud->builder, "AudioBitrate"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioTrackQualityEnableBox"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioTrackQualityBox"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioMixdown"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioSamplerate"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioTrackGain"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioTrackGain"); + gtk_widget_set_sensitive(widget, !is_passthru); + widget = GHB_WIDGET(ud->builder, "AudioTrackGainValue"); + gtk_widget_set_sensitive(widget, !is_passthru); } gint @@ -152,7 +171,7 @@ int ghb_get_copy_mask(GValue *settings) return mask; } -int ghb_select_fallback( GValue *settings, int mux, int acodec ) +int ghb_select_fallback(GValue *settings, int acodec) { gint fallback = 0; @@ -169,6 +188,7 @@ int ghb_select_fallback( GValue *settings, int mux, int acodec ) default: { + int mux = ghb_settings_combo_int(settings, "FileFormat"); fallback = ghb_settings_combo_int(settings, "AudioEncoderFallback"); return hb_autopassthru_get_encoder(acodec, 0, fallback, mux); } @@ -176,14 +196,14 @@ int ghb_select_fallback( GValue *settings, int mux, int acodec ) } void -ghb_sanitize_audio(GValue *settings, GValue *asettings) +audio_sanitize_settings(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"); @@ -198,9 +218,10 @@ ghb_sanitize_audio(GValue *settings, GValue *asettings) { sr = aconfig ? aconfig->in.samplerate : 48000; } - gint fallback = ghb_select_fallback(settings, mux, acodec); + gint fallback = ghb_select_fallback(settings, acodec); gint copy_mask = ghb_get_copy_mask(settings); - select_acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask); + select_acodec = ghb_select_audio_codec(mux, aconfig, acodec, + fallback, copy_mask); if (ghb_audio_is_passthru (select_acodec)) { if (aconfig) @@ -237,7 +258,7 @@ ghb_sanitize_audio(GValue *settings, GValue *asettings) ghb_settings_set_string(asettings, "AudioBitrate", ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); - ghb_settings_take_value(asettings, "AudioEncoderActual", + ghb_settings_take_value(asettings, "AudioEncoder", ghb_lookup_audio_encoder_value(select_acodec)); } @@ -251,7 +272,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud) gint mux; gint bitrate; gint sr = 48000; - + g_debug("ghb_adjust_audio_rate_combos ()"); mux = ghb_settings_combo_int(ud->settings, "FileFormat"); titleindex = ghb_settings_combo_int(ud->settings, "title"); @@ -284,7 +305,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud) { sr = aconfig ? aconfig->in.samplerate : 48000; } - gint fallback = ghb_select_fallback( ud->settings, mux, acodec ); + gint fallback = ghb_select_fallback(ud->settings, acodec); gint copy_mask = ghb_get_copy_mask(ud->settings); select_acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask); gboolean codec_defined_bitrate = FALSE; @@ -327,16 +348,46 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud) } ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(bitrate)); - ghb_settings_take_value(ud->settings, "AudioEncoderActual", + ghb_settings_take_value(ud->settings, "AudioEncoder", ghb_lookup_audio_encoder_value(select_acodec)); - GValue *asettings = get_selected_asettings(ud); + GValue *asettings = audio_get_selected_settings(ud, NULL); if (asettings) { - ghb_settings_take_value(asettings, "AudioEncoderActual", + ghb_settings_take_value(asettings, "AudioEncoder", ghb_lookup_audio_encoder_value(select_acodec)); } ghb_audio_list_refresh_selected(ud); - ghb_check_dependency(ud, NULL, "AudioEncoderActual"); +} + +static void +audio_update_dialog_widgets(signal_user_data_t *ud, GValue *asettings) +{ + if (asettings != NULL) + { + block_updates = TRUE; + ghb_ui_update(ud, "AudioTrack", + ghb_settings_get_value(asettings, "AudioTrack")); + ghb_ui_update(ud, "AudioEncoder", + ghb_settings_get_value(asettings, "AudioEncoder")); + ghb_ui_update(ud, "AudioBitrate", + ghb_settings_get_value(asettings, "AudioBitrate")); + ghb_ui_update(ud, "AudioTrackName", + ghb_settings_get_value(asettings, "AudioTrackName")); + ghb_ui_update(ud, "AudioSamplerate", + ghb_settings_get_value(asettings, "AudioSamplerate")); + ghb_ui_update(ud, "AudioMixdown", + ghb_settings_get_value(asettings, "AudioMixdown")); + ghb_ui_update(ud, "AudioTrackDRCSlider", + ghb_settings_get_value(asettings, "AudioTrackDRCSlider")); + ghb_ui_update(ud, "AudioTrackGain", + ghb_settings_get_value(asettings, "AudioTrackGain")); + ghb_ui_update(ud, "AudioTrackQuality", + ghb_settings_get_value(asettings, "AudioTrackQuality")); + ghb_ui_update(ud, "AudioTrackQualityEnable", + ghb_settings_get_value(asettings, "AudioTrackQualityEnable")); + block_updates = FALSE; + } + audio_deps(ud, asettings, NULL); } static void @@ -346,7 +397,7 @@ free_audio_hash_key_value(gpointer data) } const gchar* -ghb_get_user_audio_lang(GValue *settings, gint titleindex, gint track) +ghb_get_user_audio_lang(GValue *settings, hb_title_t *title, gint track) { GValue *audio_list, *asettings; const gchar *lang; @@ -356,125 +407,277 @@ ghb_get_user_audio_lang(GValue *settings, gint titleindex, gint track) return "und"; asettings = ghb_array_get_nth(audio_list, track); track = ghb_settings_get_int(asettings, "AudioTrack"); - lang = ghb_get_source_audio_lang(titleindex, track); + lang = ghb_get_source_audio_lang(title, track); return lang; } -void -ghb_set_pref_audio_settings(gint titleindex, GValue *settings) +static gboolean* +get_track_used(gint settings, GHashTable *track_indices, gint count) { - gint track; - gchar *source_lang; - hb_audio_config_t *aconfig; - GHashTable *track_indices; - gint mux; + gboolean *used; - const GValue *pref_audio; - const GValue *audio, *drc, *gain, *enable_qual; - gint acodec, bitrate, mix; - gdouble rate, quality; - gint count, ii, list_count; - - g_debug("set_pref_audio"); - 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_settings(settings); + used = g_hash_table_lookup(track_indices, &settings); + if (used == NULL) + { + gint *key; - // Find "best" audio based on audio preferences - if (!ghb_settings_get_boolean(settings, "AudioDUB")) + used = g_malloc0(count * sizeof(gboolean)); + key = g_malloc(sizeof(gint)); + *key = settings; + g_hash_table_insert(track_indices, key, used); + } + return used; +} + +static GValue* +audio_add_track( + GValue *settings, + hb_title_t *title, + int track, + int encoder, + gboolean enable_quality, + gdouble quality, + int bitrate, + int samplerate, + int mix, + gdouble drc, + gdouble gain) +{ + GValue *asettings; + hb_audio_config_t *aconfig = NULL; + + if (title != NULL) { - source_lang = g_strdup(ghb_get_source_audio_lang(titleindex, 0)); + aconfig = hb_list_audio_config_item(title->list_audio, track); } - else + + 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(encoder))); + + ghb_settings_set_boolean(asettings, + "AudioTrackQualityEnable", enable_quality); + ghb_settings_set_double(asettings, "AudioTrackQuality", quality); + + ghb_settings_set_string(asettings, "AudioBitrate", + ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); + + ghb_settings_set_string(asettings, "AudioSamplerate", + ghb_lookup_combo_string("AudioSamplerate", ghb_int_value(samplerate))); + + if (aconfig != NULL) { - source_lang = ghb_settings_get_string(settings, "PreferredLanguage"); + mix = ghb_get_best_mix(aconfig, encoder, mix); } + ghb_settings_set_string(asettings, "AudioMixdown", + ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); - pref_audio = ghb_settings_get_value(settings, "AudioList"); + ghb_settings_set_double(asettings, "AudioTrackDRCSlider", drc); - list_count = 0; - count = ghb_array_len(pref_audio); - for (ii = 0; ii < count; ii++) + ghb_settings_set_double(asettings, "AudioTrackGain", gain); + + audio_sanitize_settings(settings, asettings); + audio_add_to_settings(settings, asettings); + + return asettings; +} + +static GValue* +audio_select_and_add_track( + hb_title_t *title, + GValue *settings, + GValue *pref_audio, + const char *lang, + int pref_index, + int start_track) +{ + GValue *audio, *asettings = NULL; + gdouble drc, gain, quality; + gboolean enable_quality; + gint track, mux, acodec, bitrate, samplerate, mix; + + gint select_acodec; + gint fallback; + + mux = ghb_settings_combo_int(settings, "FileFormat"); + gint copy_mask = ghb_get_copy_mask(settings); + + audio = ghb_array_get_nth(pref_audio, pref_index); + + acodec = ghb_settings_combo_int(audio, "AudioEncoder"); + fallback = ghb_select_fallback(settings, acodec); + + bitrate = ghb_settings_combo_int(audio, "AudioBitrate"); + samplerate = ghb_settings_combo_int(audio, "AudioSamplerate"); + mix = ghb_settings_combo_int(audio, "AudioMixdown"); + drc = ghb_settings_get_double(audio, "AudioTrackDRCSlider"); + gain = ghb_settings_get_double(audio, "AudioTrackGain"); + enable_quality = ghb_settings_get_boolean(audio, "AudioTrackQualityEnable"); + quality = ghb_settings_get_double(audio, "AudioTrackQuality"); + + track = ghb_find_audio_track(title, lang, start_track); + if (track >= 0) { - gint select_acodec; - gint fallback; - - audio = ghb_array_get_nth(pref_audio, ii); - acodec = ghb_settings_combo_int(audio, "AudioEncoder"); - 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"); - mix = ghb_settings_combo_int(audio, "AudioMixdown"); - drc = ghb_settings_get_value(audio, "AudioTrackDRCSlider"); - gain = ghb_settings_get_value(audio, "AudioTrackGain"); - enable_qual = ghb_settings_get_value(audio, "AudioTrackQualityEnable"); - quality = ghb_settings_get_double(audio, "AudioTrackQuality"); - // If there are multiple audios using the same codec, then - // select sequential tracks for each. The hash keeps track - // of the tracks used for each codec. - track = ghb_find_audio_track(titleindex, source_lang, - select_acodec, fallback, track_indices); // Check to see if: // 1. pref codec is passthru // 2. source codec is not passthru // 3. next pref is enabled - aconfig = ghb_get_scan_audio_info(titleindex, track); - if (aconfig && ghb_audio_is_passthru (acodec)) + hb_audio_config_t *aconfig; + aconfig = hb_list_audio_config_item(title->list_audio, track); + select_acodec = ghb_select_audio_codec( + mux, aconfig, acodec, fallback, copy_mask); + + asettings = audio_add_track(settings, title, track, select_acodec, + enable_quality, quality, bitrate, + samplerate, mix, drc, gain); + } + return asettings; +} + +static void set_pref_audio_with_lang( + hb_title_t *title, + GValue *settings, + const char *lang, + int behavior, + gboolean secondary_audio_track_mode, + GHashTable *track_used) +{ + const GValue *pref_audio, *audio_list; + int count, ii, track, track_count, audio_count; + gint mux; + + audio_list = ghb_settings_get_value(settings, "audio_list"); + + mux = ghb_settings_combo_int(settings, "FileFormat"); + pref_audio = ghb_settings_get_value(settings, "AudioList"); + audio_count = hb_list_count(title->list_audio); + count = ghb_array_len(pref_audio); + int next_track = 0; + track = ghb_find_audio_track(title, lang, next_track); + while (track >= 0) + { + track_count = ghb_array_len(audio_list); + count = (track_count && secondary_audio_track_mode) ? 1 : count; + for (ii = 0; ii < count; ii++) { - // 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) - acodec = fallback; - // If we can't substitute the passthru with a suitable - // encoder and - // If there's more audio to process, or we've already - // placed one in the list, then we can skip this one - if (!(select_acodec & fallback) && - ((ii + 1 < count) || (list_count != 0))) - { - // Skip this audio - acodec = 0; - } - } - else + const GValue *audio; + gint acodec, fallback, copy_mask, bitrate, samplerate, mix; + gint select_acodec; + gdouble drc, gain, quality; + gboolean enable_quality; + + audio = ghb_array_get_nth(pref_audio, ii); + acodec = ghb_settings_combo_int(audio, "AudioEncoder"); + fallback = ghb_select_fallback(settings, acodec); + copy_mask = ghb_get_copy_mask(settings); + bitrate = ghb_settings_combo_int(audio, "AudioBitrate"); + samplerate = ghb_settings_combo_int(audio, "AudioSamplerate"); + mix = ghb_settings_combo_int(audio, "AudioMixdown"); + drc = ghb_settings_get_double(audio, "AudioTrackDRCSlider"); + gain = ghb_settings_get_double(audio, "AudioTrackGain"); + enable_quality = ghb_settings_get_boolean(audio, + "AudioTrackQualityEnable"); + quality = ghb_settings_get_double(audio, "AudioTrackQuality"); + + // Check to see if: + // 1. pref codec is passthru + // 2. source codec is not passthru + // 3. next pref is enabled + hb_audio_config_t *aconfig; + aconfig = hb_list_audio_config_item(title->list_audio, track); + select_acodec = ghb_select_audio_codec( + mux, aconfig, acodec, fallback, copy_mask); + + // Was the source track already encoded + // with the selected encode settings. + gboolean *used = get_track_used(ii, track_used, audio_count); + if (!used[track]) { - select_acodec &= aconfig->in.codec | HB_ACODEC_PASS_FLAG; + used[track] = TRUE; + audio_add_track(settings, title, track, select_acodec, + enable_quality, quality, bitrate, + samplerate, mix, drc, gain); } } - if (titleindex >= 0 && track < 0) - acodec = 0; - if (acodec != 0) - { - 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(asettings, "AudioEncoderActual", - ghb_lookup_audio_encoder_value(select_acodec)); - 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(asettings, "AudioBitrate", - ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate))); - 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(asettings, "AudioMixdown", - ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix))); - 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); + next_track = track + 1; + if (behavior == 2) + { + track = ghb_find_audio_track(title, lang, next_track); + } + else + { + break; } } - g_free(source_lang); - g_hash_table_destroy(track_indices); +} + +void ghb_audio_title_change(signal_user_data_t *ud, gboolean title_valid) +{ + GtkWidget *w = GHB_WIDGET(ud->builder, "audio_add"); + gtk_widget_set_sensitive(w, title_valid); + w = GHB_WIDGET(ud->builder, "audio_add_all"); + gtk_widget_set_sensitive(w, title_valid); + w = GHB_WIDGET(ud->builder, "audio_reset"); + gtk_widget_set_sensitive(w, title_valid); +} + +void +ghb_set_pref_audio_settings(gint titleindex, GValue *settings) +{ + GHashTable *track_used; + hb_title_t *title; + + const GValue *lang_list; + gint behavior; + gint ii, audio_count, lang_count; + + g_debug("set_pref_audio"); + behavior = ghb_settings_combo_int(settings, "AudioTrackSelectionBehavior"); + + // Clear the audio list + ghb_clear_audio_list_settings(settings); + + title = ghb_get_title_info(titleindex); + if (behavior == 0 || title == NULL) + { + // None or no source title + return; + } + audio_count = hb_list_count(title->list_audio); + if (audio_count == 0) + { + // No source audio + return; + } + + track_used = g_hash_table_new_full(g_int_hash, g_int_equal, + free_audio_hash_key_value, free_audio_hash_key_value); + + // Find "best" audio based on audio preset defaults + lang_list = ghb_settings_get_value(settings, "AudioLanguageList"); + + lang_count = ghb_array_len(lang_list); + for (ii = 0; ii < lang_count; ii++) + { + const gchar *lang; + gboolean mode; + GValue *glang = ghb_array_get_nth(lang_list, ii); + lang = g_value_get_string(glang); + mode = ghb_settings_get_boolean(settings, "AudioSecondaryEncoderMode"); + set_pref_audio_with_lang(title, settings, lang, behavior, mode, track_used); + } + GValue *audio_list = ghb_settings_get_value(settings, "audio_list"); + if (audio_list == NULL || ghb_array_len(audio_list) == 0) + { + // No matching audio tracks found. Add first track matching + // any language. + set_pref_audio_with_lang(title, settings, "und", 1, FALSE, track_used); + } + g_hash_table_destroy(track_used); } void @@ -491,234 +694,284 @@ ghb_set_pref_audio_from_settings(signal_user_data_t *ud, GValue *settings) for (ii = 0; ii < count; ii++) { audio = ghb_array_get_nth(audio_list, ii); - ghb_add_audio_to_ui(ud->builder, audio); + ghb_add_audio_to_ui(ud, audio); ghb_adjust_audio_rate_combos(ud); } - check_list_full(ud); } static GValue* -get_selected_asettings(signal_user_data_t *ud) +audio_get_selected_settings(signal_user_data_t *ud, int *index) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; - GtkTreeIter iter; + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeSelection *ts; + GtkTreeModel *tm; + GtkTreeIter ti; gint *indices; gint row; GValue *asettings = NULL; const GValue *audio_list; - - g_debug("get_selected_asettings ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + ts = gtk_tree_view_get_selection (tv); + if (gtk_tree_selection_get_selected(ts, &tm, &ti)) { // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); + tp = gtk_tree_model_get_path (tm, &ti); + indices = gtk_tree_path_get_indices (tp); row = indices[0]; - gtk_tree_path_free(treepath); + gtk_tree_path_free(tp); // find audio settings if (row < 0) return NULL; + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); if (row >= ghb_array_len(audio_list)) return NULL; + asettings = ghb_array_get_nth(audio_list, row); + if (index != NULL) + *index = row; } return asettings; } -void -ghb_audio_list_refresh_selected(signal_user_data_t *ud) +static void +audio_refresh_list_row_ui( + GtkTreeModel *tm, + GtkTreeIter *ti, + signal_user_data_t *ud, + const GValue *settings) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; - GtkTreeIter iter; - gint *indices; - gint row; - GValue *asettings = NULL; - const GValue *audio_list; - - g_debug("ghb_audio_list_refresh_selected ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + GtkTreeIter cti; + char *info_src, *info_src_2; + char *info_dst, *info_dst_2; + + + info_src_2 = NULL; + info_dst_2 = NULL; + + const gchar *s_track, *s_codec, *s_mix; + gchar *s_drc, *s_gain, *s_br_quality, *s_sr, *s_track_name; + gdouble drc, gain; + hb_audio_config_t *aconfig; + int titleindex, track, sr, codec; + + titleindex = ghb_settings_combo_int(ud->settings, "title"); + track = ghb_settings_combo_int(settings, "AudioTrack"); + aconfig = ghb_get_scan_audio_info(titleindex, track); + if (aconfig == NULL) { - const gchar *track, *codec, *br = NULL, *sr, *mix; - gchar *s_drc, *s_gain, *s_quality = NULL; - gdouble drc, gain; - // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); - row = indices[0]; - gtk_tree_path_free(treepath); - // find audio settings - if (row < 0) return; - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - if (row >= ghb_array_len(audio_list)) - return; - asettings = ghb_array_get_nth(audio_list, row); + return; + } - track = ghb_settings_combo_option(asettings, "AudioTrack"); - codec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); - double quality = ghb_settings_get_double(asettings, "AudioTrackQuality"); - if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && - quality != HB_INVALID_AUDIO_QUALITY) + + s_track = ghb_settings_combo_option(settings, "AudioTrack"); + codec = ghb_settings_combo_int(settings, "AudioEncoder"); + s_codec = ghb_settings_combo_option(settings, "AudioEncoder"); + + double quality = ghb_settings_get_double(settings, "AudioTrackQuality"); + if (ghb_settings_get_boolean(settings, "AudioTrackQualityEnable") && + quality != HB_INVALID_AUDIO_QUALITY) + { + s_br_quality = ghb_format_quality("Quality: ", codec, quality); + } + else + { + s_br_quality = g_strdup_printf("Bitrate: %skbps", + ghb_settings_combo_option(settings, "AudioBitrate")); + } + + sr = ghb_settings_combo_int(settings, "AudioSamplerate"); + if (sr == 0) + { + sr = aconfig->in.samplerate; + } + s_sr = g_strdup_printf("%.4gkHz", (double)sr/1000); + + s_mix = ghb_settings_combo_option(settings, "AudioMixdown"); + gain = ghb_settings_get_double(settings, "AudioTrackGain"); + s_gain = g_strdup_printf("%ddB", (int)gain); + + drc = ghb_settings_get_double(settings, "AudioTrackDRCSlider"); + if (drc < 1.0) + s_drc = g_strdup(_("Off")); + else + s_drc = g_strdup_printf("%.1f", drc); + + s_track_name = ghb_settings_get_string(settings, "AudioTrackName"); + + info_src = g_strdup_printf("%s (%.4gkHz)", + s_track, + (double)aconfig->in.samplerate / 1000); + if (aconfig->in.bitrate > 0) + { + info_src_2 = g_strdup_printf( + "Bitrate: %.4gkbps", + (double)aconfig->in.bitrate / 1000); + } + + if (ghb_audio_is_passthru(codec)) + { + info_dst = g_strdup_printf("Passthrough"); + } + else + { + info_dst = g_strdup_printf("%s (%s) (%s)", s_codec, s_mix, s_sr); + if (s_track_name && s_track_name[0]) { - int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); - s_quality = ghb_format_quality("Q/", codec, quality); + info_dst_2 = g_strdup_printf( + "%s\nGain: %s\nDRC: %s\nTrack Name: %s", + s_br_quality, s_gain, s_drc, s_track_name); } else { - br = ghb_settings_combo_option(asettings, "AudioBitrate"); + info_dst_2 = g_strdup_printf("%s\nGain: %s\nDRC: %s", + s_br_quality, s_gain, s_drc); } - sr = ghb_settings_combo_option(asettings, "AudioSamplerate"); - mix = ghb_settings_combo_option(asettings, "AudioMixdown"); - gain = ghb_settings_get_double(asettings, "AudioTrackGain"); - s_gain = g_strdup_printf("%ddB", (int)gain); + } + gtk_tree_store_set(GTK_TREE_STORE(tm), ti, + // These are displayed in list + 0, info_src, + 1, "-->", + 2, info_dst, + 3, "hb-edit", + 4, "hb-queue-delete", + 5, 0.5, + -1); - drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider"); - if (drc < 1.0) - s_drc = g_strdup(_("Off")); - else - s_drc = g_strdup_printf("%.1f", drc); + if (info_src_2 != NULL || info_dst_2 != NULL) + { + if (info_src_2 == NULL) + info_src_2 = g_strdup(""); + if (info_dst_2 == NULL) + info_dst_2 = g_strdup(""); - gtk_list_store_set(GTK_LIST_STORE(store), &iter, + // Get the child of the selection + if (!gtk_tree_model_iter_children(tm, &cti, ti)) + { + gtk_tree_store_append(GTK_TREE_STORE(tm), &cti, ti); + } + gtk_tree_store_set(GTK_TREE_STORE(tm), &cti, // These are displayed in list - 0, track, - 1, codec, - 2, s_quality ? s_quality : br, - 3, sr, - 4, mix, - 5, s_gain, - 6, s_drc, + 0, info_src_2, + 2, info_dst_2, + 5, 0.0, -1); - g_free(s_drc); - g_free(s_gain); - g_free(s_quality); } + else + { + if(gtk_tree_model_iter_children(tm, &cti, ti)) + { + gtk_tree_store_remove(GTK_TREE_STORE(tm), &cti); + } + } + + g_free(info_src); + g_free(info_src_2); + g_free(info_dst); + g_free(info_dst_2); + + g_free(s_sr); + g_free(s_drc); + g_free(s_gain); + g_free(s_br_quality); + g_free(s_track_name); } void -ghb_audio_list_refresh(signal_user_data_t *ud) +ghb_audio_list_refresh_selected(signal_user_data_t *ud) { - GtkTreeView *treeview; - GtkTreeIter iter; - GtkListStore *store; - gboolean done; - gint row = 0; + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeSelection *ts; + GtkTreeModel *tm; + GtkTreeIter ti; + gint *indices; + gint row; + GValue *asettings = NULL; const GValue *audio_list; - g_debug("ghb_audio_list_refresh ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); - store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); - if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) + g_debug("ghb_audio_list_refresh_selected ()"); + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + ts = gtk_tree_view_get_selection (tv); + if (gtk_tree_selection_get_selected(ts, &tm, &ti)) { - do - { - const gchar *track, *codec, *br = NULL, *sr, *mix; - gchar *s_drc, *s_gain, *s_quality = NULL; - gdouble drc, gain; - GValue *asettings; - - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - if (row >= ghb_array_len(audio_list)) - return; - asettings = ghb_array_get_nth(audio_list, row); + // Get the row number + tp = gtk_tree_model_get_path (tm, &ti); + indices = gtk_tree_path_get_indices (tp); + row = indices[0]; + gtk_tree_path_free(tp); + if (row < 0) return; - track = ghb_settings_combo_option(asettings, "AudioTrack"); - codec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); - double quality = ghb_settings_get_double(asettings, "AudioTrackQuality"); - if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && - quality != HB_INVALID_AUDIO_QUALITY) - { - int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); - s_quality = ghb_format_quality("Q/", codec, quality); - } - else - { - br = ghb_settings_get_string(asettings, "AudioBitrate"); - } - sr = ghb_settings_combo_option(asettings, "AudioSamplerate"); - mix = ghb_settings_combo_option(asettings, "AudioMixdown"); - gain = ghb_settings_get_double(asettings, "AudioTrackGain"); - s_gain = g_strdup_printf("%.fdB", gain); - - drc = ghb_settings_get_double(asettings, "AudioTrackDRCSlider"); - if (drc < 1.0) - s_drc = g_strdup(_("Off")); - else - s_drc = g_strdup_printf("%.1f", drc); - - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - // These are displayed in list - 0, track, - 1, codec, - 2, s_quality ? s_quality : br, - 3, sr, - 4, mix, - 5, s_gain, - 6, s_drc, - -1); - g_free(s_drc); - g_free(s_gain); - done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); - row++; - } while (!done); + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + if (row >= ghb_array_len(audio_list)) + return; + + asettings = ghb_array_get_nth(audio_list, row); + audio_refresh_list_row_ui(tm, &ti, ud, asettings); } } -static void enable_quality_widget(signal_user_data_t *ud, int acodec) +static void +audio_refresh_list_ui(signal_user_data_t *ud) { - GtkWidget *widget1, *widget2, *widget3; + GValue *audio_list; + GValue *asettings; + gint ii, count, tm_count; + GtkTreeView *tv; + GtkTreeModel *tm; + GtkTreeIter ti; - widget1 = GHB_WIDGET(ud->builder, "AudioTrackQualityEnable"); - widget2 = GHB_WIDGET(ud->builder, "AudioTrackQualityValue"); - widget3 = GHB_WIDGET(ud->builder, "AudioTrackQuality"); - if (hb_audio_quality_get_default(acodec) == HB_INVALID_AUDIO_QUALITY) + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + tm = gtk_tree_view_get_model(tv); + + tm_count = gtk_tree_model_iter_n_children(tm, NULL); + + audio_list = ghb_settings_get_value(ud->settings, "audio_list"); + count = ghb_array_len(audio_list); + if (count != tm_count) { - gtk_widget_hide(widget1); - gtk_widget_hide(widget2); - gtk_widget_hide(widget3); + ghb_clear_audio_list_ui(ud->builder); + for (ii = 0; ii < count; ii++) + { + gtk_tree_store_append(GTK_TREE_STORE(tm), &ti, NULL); + } } - else + for (ii = 0; ii < count; ii++) { - gtk_widget_show(widget1); - gtk_widget_show(widget2); - gtk_widget_show(widget3); + gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii); + asettings = ghb_array_get_nth(audio_list, ii); + audio_refresh_list_row_ui(tm, &ti, ud, asettings); } } +void +ghb_audio_list_refresh_all(signal_user_data_t *ud) +{ + audio_refresh_list_ui(ud); +} + G_MODULE_EXPORT void audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { static gint prev_acodec = 0; gint acodec_code; - GValue *asettings, *gval; - - g_debug("audio_codec_changed_cb ()"); - gval = ghb_widget_value(widget); - acodec_code = ghb_lookup_combo_int("AudioEncoder", gval); - ghb_value_free(gval); + GValue *asettings; + + ghb_widget_to_setting(ud->settings, widget); + acodec_code = ghb_settings_combo_int(ud->settings, "AudioEncoder"); - enable_quality_widget(ud, acodec_code); if (block_updates) { prev_acodec = acodec_code; - ghb_grey_combo_options (ud); - ghb_check_dependency(ud, widget, NULL); return; } - asettings = get_selected_asettings(ud); - if (ghb_audio_is_passthru (prev_acodec) && + asettings = audio_get_selected_settings(ud, NULL); + if (ghb_audio_is_passthru (prev_acodec) && !ghb_audio_is_passthru (acodec_code)) { - // Transition from passthru to not, put some audio settings back to + // Transition from passthru to not, put some audio settings back to // pref settings gint titleindex; gint track; @@ -757,18 +1010,14 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix_code)); } - ghb_adjust_audio_rate_combos(ud); - ghb_grey_combo_options (ud); - ghb_check_dependency(ud, widget, NULL); - audio_deps(ud); prev_acodec = acodec_code; if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); - ghb_settings_set_value(asettings, "AudioEncoderActual", ghb_settings_get_value(ud->settings, "AudioEncoderActual")); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); + ghb_live_reset(ud); } - ghb_live_reset(ud); float low, high, gran, defval; int dir; @@ -792,28 +1041,24 @@ audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud) GValue *asettings; g_debug("audio_track_changed_cb ()"); + ghb_widget_to_setting(ud->settings, widget); if (block_updates) { - ghb_check_dependency(ud, widget, NULL); - ghb_grey_combo_options (ud); return; } - ghb_adjust_audio_rate_combos(ud); - ghb_check_dependency(ud, widget, NULL); - audio_deps(ud); - ghb_grey_combo_options(ud); - asettings = get_selected_asettings(ud); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { const gchar *track; ghb_widget_to_setting(asettings, widget); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); track = ghb_settings_combo_option(asettings, "AudioTrack"); ghb_settings_set_string(asettings, "AudioTrackDescription", track); + ghb_live_reset(ud); } - ghb_live_reset(ud); } G_MODULE_EXPORT void @@ -821,22 +1066,20 @@ audio_mix_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { GValue *asettings; - g_debug("audio_mix_changed_cb ()"); + ghb_widget_to_setting(ud->settings, widget); if (block_updates) { - ghb_check_dependency(ud, widget, NULL); return; } - ghb_adjust_audio_rate_combos(ud); - ghb_check_dependency(ud, widget, NULL); - asettings = get_selected_asettings(ud); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); + ghb_live_reset(ud); } - ghb_live_reset(ud); } G_MODULE_EXPORT void @@ -844,39 +1087,34 @@ audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { GValue *asettings; - g_debug("audio_widget_changed_cb ()"); + ghb_widget_to_setting(ud->settings, widget); if (block_updates) { - ghb_check_dependency(ud, widget, NULL); return; } - ghb_adjust_audio_rate_combos(ud); - asettings = get_selected_asettings(ud); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); + ghb_live_reset(ud); } - ghb_live_reset(ud); } G_MODULE_EXPORT void -global_audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +audio_quality_radio_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { - g_debug("global_audio_widget_changed_cb ()"); - if (block_updates) - { - ghb_check_dependency(ud, widget, NULL); - return; - } - ghb_check_dependency(ud, widget, NULL); + audio_widget_changed_cb(widget, ud); +} + +G_MODULE_EXPORT void +audio_passthru_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ ghb_widget_to_setting(ud->settings, widget); - ghb_adjust_audio_rate_combos(ud); - ghb_grey_combo_options (ud); - ghb_audio_list_refresh_selected(ud); - ghb_live_reset(ud); + ghb_clear_presets_selection(ud); } G_MODULE_EXPORT gchar* @@ -923,7 +1161,7 @@ quality_widget_changed_cb(GtkWidget *widget, gdouble quality, signal_user_data_t ghb_check_dependency(ud, widget, NULL); float low, high, gran; int dir; - int codec = ghb_settings_combo_int(ud->settings, "AudioEncoderActual"); + int codec = ghb_settings_combo_int(ud->settings, "AudioEncoder"); hb_audio_quality_get_limits(codec, &low, &high, &gran, &dir); if (dir) { @@ -936,7 +1174,7 @@ quality_widget_changed_cb(GtkWidget *widget, gdouble quality, signal_user_data_t if (block_updates) return; - asettings = get_selected_asettings(ud); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { ghb_settings_set_double(asettings, "AudioTrackQuality", quality); @@ -952,8 +1190,11 @@ drc_widget_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud) g_debug("drc_widget_changed_cb ()"); - ghb_check_dependency(ud, widget, NULL); - if (block_updates) return; + ghb_widget_to_setting(ud->settings, widget); + if (block_updates) + { + return; + } char *s_drc; if (drc < 0.99) @@ -963,13 +1204,14 @@ drc_widget_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud) ghb_ui_update( ud, "AudioTrackDRCValue", ghb_string_value(s_drc)); g_free(s_drc); - asettings = get_selected_asettings(ud); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); + ghb_live_reset(ud); } - ghb_live_reset(ud); } G_MODULE_EXPORT gchar* @@ -987,9 +1229,11 @@ gain_widget_changed_cb(GtkWidget *widget, gdouble gain, signal_user_data_t *ud) g_debug("gain_widget_changed_cb ()"); - ghb_check_dependency(ud, widget, NULL); - if (block_updates) return; - asettings = get_selected_asettings(ud); + ghb_widget_to_setting(ud->settings, widget); + if (block_updates) + { + return; + } char *s_gain; if ( gain >= 21.0 ) @@ -999,19 +1243,21 @@ gain_widget_changed_cb(GtkWidget *widget, gdouble gain, signal_user_data_t *ud) ghb_ui_update( ud, "AudioTrackGainValue", ghb_string_value(s_gain)); g_free(s_gain); + asettings = audio_get_selected_settings(ud, NULL); if (asettings != NULL) { ghb_widget_to_setting(asettings, widget); + audio_deps(ud, asettings, widget); ghb_audio_list_refresh_selected(ud); + ghb_live_reset(ud); } - ghb_live_reset(ud); } void ghb_clear_audio_list_settings(GValue *settings) { GValue *audio_list; - + g_debug("clear_audio_list_settings ()"); audio_list = ghb_settings_get_value(settings, "audio_list"); if (audio_list == NULL) @@ -1026,137 +1272,86 @@ ghb_clear_audio_list_settings(GValue *settings) void ghb_clear_audio_list_ui(GtkBuilder *builder) { - GtkTreeView *treeview; - GtkListStore *store; - + GtkTreeView *tv; + GtkTreeStore *ts; + 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); + tv = GTK_TREE_VIEW(GHB_WIDGET(builder, "audio_list")); + ts = GTK_TREE_STORE(gtk_tree_view_get_model(tv)); + gtk_tree_store_clear(ts); } static void -ghb_add_audio_to_ui(GtkBuilder *builder, const GValue *settings) -{ - GtkTreeView *treeview; - GtkTreeIter iter; - GtkListStore *store; - GtkTreeSelection *selection; - const gchar *track, *codec, *br = NULL, *sr, *mix; - gchar *s_drc, *s_gain, *s_quality = NULL; - gdouble drc; - gdouble gain; - - 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)); - - track = ghb_settings_combo_option(settings, "AudioTrack"); - codec = ghb_settings_combo_option(settings, "AudioEncoderActual"); - double quality = ghb_settings_get_double(settings, "AudioTrackQuality"); - if (ghb_settings_get_boolean(settings, "AudioTrackQualityEnable") && - quality != HB_INVALID_AUDIO_QUALITY) - { - int codec = ghb_settings_combo_int(settings, "AudioEncoderActual"); - s_quality = ghb_format_quality("Q/", codec, quality); - } - else - { - br = ghb_settings_combo_option(settings, "AudioBitrate"); - } - sr = ghb_settings_combo_option(settings, "AudioSamplerate"); - mix = ghb_settings_combo_option(settings, "AudioMixdown"); - gain = ghb_settings_get_double(settings, "AudioTrackGain"); - s_gain = g_strdup_printf("%ddB", (int)gain); +ghb_add_audio_to_ui(signal_user_data_t *ud, const GValue *asettings) +{ + GtkTreeView *tv; + GtkTreeIter ti; + GtkTreeModel *tm; + GtkTreeSelection *ts; - drc = ghb_settings_get_double(settings, "AudioTrackDRCSlider"); - if (drc < 1.0) - s_drc = g_strdup(_("Off")); - else - s_drc = g_strdup_printf("%.1f", drc); + if (asettings == NULL) + return; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - // These are displayed in list - 0, track, - 1, codec, - 2, s_quality ? s_quality : br, - 3, sr, - 4, mix, - 5, s_gain, - 6, s_drc, - -1); - gtk_tree_selection_select_iter(selection, &iter); - g_free(s_drc); - g_free(s_gain); - g_free(s_quality); + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + ts = gtk_tree_view_get_selection (tv); + tm = gtk_tree_view_get_model(tv); + + gtk_tree_store_append(GTK_TREE_STORE(tm), &ti, NULL); + gtk_tree_selection_select_iter(ts, &ti); + + audio_refresh_list_row_ui(tm, &ti, ud, asettings); } G_MODULE_EXPORT void -audio_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud) +audio_list_selection_changed_cb(GtkTreeSelection *ts, signal_user_data_t *ud) { - GtkTreeModel *store; - GtkTreeIter iter; - GtkWidget *widget; - - GtkTreePath *treepath; - gint *indices; - gint row; + GtkTreeModel *tm; + GtkTreeIter ti; GValue *asettings = NULL; + gint row; - const GValue *audio_list; g_debug("audio_list_selection_changed_cb ()"); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + if (gtk_tree_selection_get_selected(ts, &tm, &ti)) { - //const gchar *actual_codec, *track, *codec, *bitrate, *sample_rate, *mix; - //gdouble drc; + GtkTreeIter pti; + + if (gtk_tree_model_iter_parent(tm, &pti, &ti)) + { + GtkTreePath *path; + GtkTreeView *tv; + + gtk_tree_selection_select_iter(ts, &pti); + path = gtk_tree_model_get_path(tm, &pti); + tv = gtk_tree_selection_get_tree_view(ts); + // Make the parent visible in scroll window if it is not. + gtk_tree_view_scroll_to_cell(tv, path, NULL, FALSE, 0, 0); + gtk_tree_path_free(path); + return; + } + + GtkTreePath *tp; + gint *indices; + GValue *audio_list; // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); + tp = gtk_tree_model_get_path (tm, &ti); + indices = gtk_tree_path_get_indices (tp); row = indices[0]; - gtk_tree_path_free(treepath); - // find audio settings + gtk_tree_path_free(tp); + if (row < 0) return; audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - if (row >= ghb_array_len(audio_list)) - return; - asettings = ghb_array_get_nth(audio_list, row); - - block_updates = TRUE; - ghb_ui_update(ud, "AudioTrack", ghb_settings_get_value(asettings, "AudioTrack")); - ghb_ui_update(ud, "AudioEncoder", ghb_settings_get_value(asettings, "AudioEncoder")); - ghb_settings_set_value(ud->settings, "AudioEncoderActual", ghb_settings_get_value(asettings, "AudioEncoderActual")); - ghb_check_dependency(ud, NULL, "AudioEncoderActual"); - ghb_ui_update(ud, "AudioBitrate", ghb_settings_get_value(asettings, "AudioBitrate")); - ghb_ui_update(ud, "AudioTrackName", ghb_settings_get_value(asettings, "AudioTrackName")); - ghb_ui_update(ud, "AudioSamplerate", ghb_settings_get_value(asettings, "AudioSamplerate")); - ghb_ui_update(ud, "AudioMixdown", ghb_settings_get_value(asettings, "AudioMixdown")); - ghb_ui_update(ud, "AudioTrackDRCSlider", ghb_settings_get_value(asettings, "AudioTrackDRCSlider")); - ghb_ui_update(ud, "AudioTrackGain", ghb_settings_get_value(asettings, "AudioTrackGain")); - ghb_ui_update(ud, "AudioTrackQuality", ghb_settings_get_value(asettings, "AudioTrackQuality")); - ghb_ui_update(ud, "AudioTrackQualityEnable", ghb_settings_get_value(asettings, "AudioTrackQualityEnable")); - block_updates = FALSE; - widget = GHB_WIDGET (ud->builder, "audio_remove"); - gtk_widget_set_sensitive(widget, TRUE); - - ghb_adjust_audio_rate_combos(ud); - } - else - { - widget = GHB_WIDGET (ud->builder, "audio_remove"); - gtk_widget_set_sensitive(widget, FALSE); + if (row >= 0 && row < ghb_array_len(audio_list)) + asettings = ghb_array_get_nth(audio_list, row); } - audio_deps(ud); + audio_update_dialog_widgets(ud, asettings); } -static gboolean -ghb_add_audio_to_settings(GValue *settings, GValue *asettings) +static void +audio_add_to_settings(GValue *settings, GValue *asettings) { GValue *audio_list; const gchar * track; - int count; audio_list = ghb_settings_get_value(settings, "audio_list"); if (audio_list == NULL) @@ -1164,14 +1359,6 @@ ghb_add_audio_to_settings(GValue *settings, GValue *asettings) audio_list = ghb_array_value_new(8); ghb_settings_set_value(settings, "audio_list", audio_list); } - 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) - { - 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"); @@ -1184,92 +1371,175 @@ ghb_add_audio_to_settings(GValue *settings, GValue *asettings) { ghb_settings_set_string(asettings, "AudioTrackName", ""); } - 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 audio_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { // Add the current audio settings to the list. - GValue *asettings; - GtkWidget *widget; - - g_debug("audio_add_clicked_cb ()"); - asettings = ghb_dict_value_new(); - widget = GHB_WIDGET(ud->builder, "AudioTrack"); - ghb_settings_take_value(asettings, "AudioTrack", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioEncoder"); - ghb_settings_take_value(asettings, "AudioEncoder", ghb_widget_value(widget)); - ghb_settings_set_value(asettings, "AudioEncoderActual", - ghb_settings_get_value(ud->settings, "AudioEncoderActual")); - widget = GHB_WIDGET(ud->builder, "AudioTrackQualityEnable"); - ghb_settings_take_value(asettings, "AudioTrackQualityEnable", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioTrackQuality"); - ghb_settings_take_value(asettings, "AudioTrackQuality", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioBitrate"); - ghb_settings_take_value(asettings, "AudioBitrate", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioSamplerate"); - ghb_settings_take_value(asettings, "AudioSamplerate", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioMixdown"); - ghb_settings_take_value(asettings, "AudioMixdown", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioTrackGain"); - ghb_settings_take_value(asettings, "AudioTrackGain", ghb_widget_value(widget)); - widget = GHB_WIDGET(ud->builder, "AudioTrackDRCSlider"); - ghb_settings_take_value(asettings, "AudioTrackDRCSlider", ghb_widget_value(widget)); + GValue *asettings, *backup; - if (!ghb_add_audio_to_settings(ud->settings, asettings)) - return; + // Back up settings in case we need to revert. + backup = ghb_value_dup( + ghb_settings_get_value(ud->settings, "audio_list")); + + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + hb_title_t *title = ghb_get_title_info(titleindex); + GValue *pref_audio = ghb_settings_get_value(ud->settings, "AudioList"); - ghb_add_audio_to_ui(ud->builder, asettings); - check_list_full(ud); + asettings = audio_select_and_add_track(title, ud->settings, pref_audio, + "und", 0, 0); + ghb_add_audio_to_ui(ud, asettings); + + if (asettings != NULL) + { + // Pop up the edit dialog + GtkResponseType response; + GtkWidget *dialog = GHB_WIDGET(ud->builder, "audio_dialog"); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response != GTK_RESPONSE_OK) + { + ghb_settings_take_value(ud->settings, "audio_list", backup); + asettings = audio_get_selected_settings(ud, NULL); + if (asettings != NULL) + { + audio_update_dialog_widgets(ud, asettings); + } + audio_refresh_list_ui(ud); + } + else + { + ghb_value_free(backup); + } + } } G_MODULE_EXPORT void -audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +audio_add_all_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; - GtkTreeIter iter, nextIter; - gint *indices; + // Add the current audio settings to the list. + + ghb_clear_audio_list_settings(ud->settings); + ghb_clear_audio_list_ui(ud->builder); + + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + hb_title_t *title = ghb_get_title_info(titleindex); + GValue *pref_audio = ghb_settings_get_value(ud->settings, "AudioList"); + + int pref_count = ghb_array_len(pref_audio); + + int ii; + for (ii = 0; ii < pref_count; ii++) + { + GValue *asettings; + int track = 0; + + do + { + + asettings = audio_select_and_add_track(title, ud->settings, + pref_audio, "und", ii, + track); + ghb_add_audio_to_ui(ud, asettings); + if (asettings != NULL) + { + track = ghb_settings_combo_int(asettings, "AudioTrack") + 1; + } + } while (asettings != NULL); + } +} + +G_MODULE_EXPORT void +audio_edit_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) +{ + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeModel *tm; + GtkTreeSelection *ts; + GtkTreeIter ti; + + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + ts = gtk_tree_view_get_selection(tv); + tm = gtk_tree_view_get_model(tv); + tp = gtk_tree_path_new_from_string (path); + if (gtk_tree_path_get_depth(tp) > 1) return; + if (gtk_tree_model_get_iter(tm, &ti, tp)) + { + GValue *asettings, *backup; + + gtk_tree_selection_select_iter(ts, &ti); + + // Back up settings in case we need to revert. + backup = ghb_value_dup( + ghb_settings_get_value(ud->settings, "audio_list")); + + // Pop up the edit dialog + GtkResponseType response; + GtkWidget *dialog = GHB_WIDGET(ud->builder, "audio_dialog"); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response != GTK_RESPONSE_OK) + { + ghb_settings_take_value(ud->settings, "audio_list", backup); + asettings = audio_get_selected_settings(ud, NULL); + if (asettings != NULL) + { + audio_update_dialog_widgets(ud, asettings); + } + audio_refresh_list_ui(ud); + } + else + { + ghb_value_free(backup); + } + } +} + +G_MODULE_EXPORT void +audio_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) +{ + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeModel *tm; + GtkTreeSelection *ts; + GtkTreeIter ti, nextIter; gint row; + gint *indices; GValue *audio_list; - g_debug("audio_remove_clicked_cb ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); + ts = gtk_tree_view_get_selection(tv); + tm = gtk_tree_view_get_model(tv); + tp = gtk_tree_path_new_from_string (path); + if (gtk_tree_path_get_depth(tp) > 1) return; + if (gtk_tree_model_get_iter(tm, &ti, tp)) { - nextIter = iter; - if (!gtk_tree_model_iter_next(store, &nextIter)) + nextIter = ti; + if (!gtk_tree_model_iter_next(tm, &nextIter)) { - nextIter = iter; - if (gtk_tree_model_get_iter_first(store, &nextIter)) + nextIter = ti; + if (gtk_tree_model_get_iter_first(tm, &nextIter)) { - gtk_tree_selection_select_iter (selection, &nextIter); + gtk_tree_selection_select_iter(ts, &nextIter); } } else { - gtk_tree_selection_select_iter (selection, &nextIter); + gtk_tree_selection_select_iter(ts, &nextIter); } - // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); - row = indices[0]; - gtk_tree_path_free(treepath); - if (row < 0) return; audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - if (row >= ghb_array_len(audio_list)) + + // Get the row number + indices = gtk_tree_path_get_indices (tp); + row = indices[0]; + if (row < 0 || row >= ghb_array_len(audio_list)) + { + gtk_tree_path_free(tp); return; + } // Update our settings list before removing the row from the // treeview. Removing from the treeview sometimes provokes an @@ -1280,11 +1550,19 @@ audio_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_array_remove(audio_list, row); // Remove the selected item - gtk_list_store_remove (GTK_LIST_STORE(store), &iter); - // remove from audio settings list - widget = GHB_WIDGET (ud->builder, "audio_add"); - gtk_widget_set_sensitive(widget, TRUE); + gtk_tree_store_remove(GTK_TREE_STORE(tm), &ti); + + ghb_live_reset(ud); } + gtk_tree_path_free(tp); +} + +G_MODULE_EXPORT void +audio_reset_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_set_pref_audio_settings(titleindex, ud->settings); + ghb_set_pref_audio_from_settings(ud, ud->settings); } void @@ -1293,10 +1571,10 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) gint acodec_code; GValue *alist; - GValue *track, *audio, *acodec, *acodec_actual, *bitrate, *rate, + GValue *track, *audio, *acodec, *bitrate, *rate, *mix, *drc, *gain, *quality, *enable_quality; gint count, ii; - + g_debug("set_audio"); // Clear the audio list ghb_clear_audio_list_settings(ud->settings); @@ -1309,7 +1587,6 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) audio = ghb_array_get_nth(alist, ii); track = ghb_settings_get_value(audio, "AudioTrack"); acodec = ghb_settings_get_value(audio, "AudioEncoder"); - acodec_actual = ghb_settings_get_value(audio, "AudioEncoderActual"); enable_quality = ghb_settings_get_value(audio, "AudioTrackQualityEnable"); quality = ghb_settings_get_value(audio, "AudioTrackQuality"); bitrate = ghb_settings_get_value(audio, "AudioBitrate"); @@ -1324,7 +1601,6 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) 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); @@ -1335,12 +1611,884 @@ ghb_set_audio(signal_user_data_t *ud, GValue *settings) 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); + audio_add_to_settings(ud->settings, asettings); + ghb_add_audio_to_ui(ud, asettings); ghb_adjust_audio_rate_combos(ud); } } - check_list_full(ud); } +static GtkWidget *find_widget(GtkWidget *widget, gchar *name) +{ + const char *wname; + GtkWidget *result = NULL; + + if (widget == NULL || name == NULL) + return NULL; + + wname = gtk_widget_get_name(widget); + if (wname != NULL && !strncmp(wname, name, 80)) + { + return widget; + } + if (GTK_IS_CONTAINER(widget)) + { + GList *list, *link; + link = list = gtk_container_get_children(GTK_CONTAINER(widget)); + while (link) + { + result = find_widget(GTK_WIDGET(link->data), name); + if (result != NULL) + break; + link = link->next; + } + g_list_free(list); + } + return result; +} + +static void audio_def_update_widgets(GtkWidget *row, GValue *adict) +{ + GHashTableIter ti; + gchar *key; + GValue *gval; + GtkWidget *widget; + + ghb_dict_iter_init(&ti, adict); + + block_updates = TRUE; + while (g_hash_table_iter_next(&ti, (gpointer*)&key, (gpointer*)&gval)) + { + widget = find_widget(row, key); + if (widget != NULL) + { + ghb_update_widget(widget, gval); + } + } + block_updates = FALSE; +} + +GtkListBoxRow * ghb_audio_settings_get_row(GtkWidget *widget) +{ + while (widget != NULL && G_OBJECT_TYPE(widget) != GTK_TYPE_LIST_BOX_ROW) + { + widget = gtk_widget_get_parent(widget); + } + return GTK_LIST_BOX_ROW(widget); +} + +static void audio_def_settings_bitrate_show(GtkWidget *widget, gboolean show) +{ + GtkWidget *bitrate_widget; + GtkWidget *quality_widget; + + bitrate_widget = find_widget(widget, "AudioBitrate"); + quality_widget = find_widget(widget, "AudioTrackQualityBox"); + + if (show) + { + gtk_widget_hide(quality_widget); + gtk_widget_show(bitrate_widget); + } + else + { + gtk_widget_hide(bitrate_widget); + gtk_widget_show(quality_widget); + } +} + +static void audio_def_settings_quality_set_sensitive(GtkWidget *w, gboolean s) +{ + GtkWidget *bitrate_widget; + GtkWidget *quality_widget; + + bitrate_widget = find_widget(w, "AudioTrackBitrateEnable"); + quality_widget = find_widget(w, "AudioTrackQualityEnable"); + if (!s) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bitrate_widget), TRUE); + } + gtk_widget_set_sensitive(GTK_WIDGET(quality_widget), s); +} + +static void audio_def_settings_show(GtkWidget *widget, gboolean show) +{ + GtkWidget *settings_box; + GtkWidget *add_button; + + settings_box = find_widget(widget, "settings_box"); + add_button = find_widget(widget, "add_button"); + + if (show) + { + gtk_widget_hide(add_button); + gtk_widget_show(settings_box); + } + else + { + gtk_widget_hide(settings_box); + gtk_widget_show(add_button); + } +} + +static void +audio_def_settings_init_row(GValue *adict, GtkWidget *row) +{ + GtkWidget *widget; + + widget = find_widget(row, "AudioEncoder"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioBitrate"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioMixdown"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioSamplerate"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioTrackGain"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioTrackDRCSlider"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioTrackQuality"); + ghb_widget_to_setting(adict, widget); + widget = find_widget(row, "AudioTrackQualityEnable"); + ghb_widget_to_setting(adict, widget); +} + +G_MODULE_EXPORT void +audio_def_setting_add_cb(GtkWidget *w, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_setting_remove_cb(GtkWidget *w, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_encode_setting_changed_cb(GtkWidget *w, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_drc_changed_cb(GtkWidget *w, gdouble drc, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_gain_changed_cb(GtkWidget *w, gdouble gain, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_quality_changed_cb(GtkWidget *w, gdouble quality, signal_user_data_t *ud); +G_MODULE_EXPORT void +audio_def_quality_enable_changed_cb(GtkWidget *w, signal_user_data_t *ud); + +GtkWidget * ghb_create_audio_settings_row(signal_user_data_t *ud) +{ + GtkBox *box, *box2, *box3; + GtkComboBox *combo; + GtkScaleButton *scale; + GtkLabel *label; + GtkRadioButton *radio; + GtkButton *button; + GtkImage *image; + + box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + + // Add Button + button = GTK_BUTTON(gtk_button_new_with_label("Add")); + gtk_widget_set_tooltip_markup(GTK_WIDGET(button), + "Add an audio encoder.\n" + "Each selected source track will be encoded with all selected encoders."); + gtk_widget_set_valign(GTK_WIDGET(button), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(button), "add_button"); + gtk_widget_hide(GTK_WIDGET(button)); + g_signal_connect(button, "clicked", (GCallback)audio_def_setting_add_cb, ud); + gtk_box_pack_start(box, GTK_WIDGET(button), FALSE, FALSE, 0); + + // Hidden widgets box + box2 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_widget_set_name(GTK_WIDGET(box2), "settings_box"); + + // Audio Encoder ComboBox + combo = GTK_COMBO_BOX(gtk_combo_box_new()); + ghb_init_combo_box(combo); + ghb_audio_encoder_opts_set(combo); + // Init to first audio encoder + const hb_encoder_t *aud_enc = hb_audio_encoder_get_next(NULL); + ghb_update_widget(GTK_WIDGET(combo), ghb_int64_value(aud_enc->codec)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(combo), + "Set the audio codec to encode this track with."); + gtk_widget_set_valign(GTK_WIDGET(combo), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(combo), "AudioEncoder"); + gtk_widget_show(GTK_WIDGET(combo)); + g_signal_connect(combo, "changed", (GCallback)audio_def_encode_setting_changed_cb, ud); + gtk_box_pack_start(box2, GTK_WIDGET(combo), FALSE, FALSE, 0); + + box3 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_widget_set_name(GTK_WIDGET(box3), "br_q_box"); + gtk_widget_show(GTK_WIDGET(box3)); + + // Bitrate vs Quality RadioButton + GtkBox *vbox; + vbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0)); + radio = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "Bitrate")); + gtk_widget_set_name(GTK_WIDGET(radio), "AudioTrackBitrateEnable"); + gtk_widget_show(GTK_WIDGET(radio)); + gtk_box_pack_start(vbox, GTK_WIDGET(radio), FALSE, FALSE, 0); + radio = GTK_RADIO_BUTTON( + gtk_radio_button_new_with_label_from_widget(radio, "Quality")); + gtk_widget_set_name(GTK_WIDGET(radio), "AudioTrackQualityEnable"); + g_signal_connect(radio, "toggled", (GCallback)audio_def_quality_enable_changed_cb, ud); + gtk_widget_show(GTK_WIDGET(radio)); + gtk_box_pack_start(vbox, GTK_WIDGET(radio), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(vbox)); + gtk_box_pack_start(box3, GTK_WIDGET(vbox), FALSE, FALSE, 0); + + // Audio Bitrate ComboBox + combo = GTK_COMBO_BOX(gtk_combo_box_new()); + ghb_init_combo_box(combo); + ghb_audio_bitrate_opts_set(combo, FALSE); + ghb_update_widget(GTK_WIDGET(combo), ghb_int64_value(192)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(combo), + "Set the bitrate to encode this track with."); + gtk_widget_set_valign(GTK_WIDGET(combo), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(combo), "AudioBitrate"); + gtk_widget_show(GTK_WIDGET(combo)); + g_signal_connect(combo, "changed", (GCallback)audio_def_encode_setting_changed_cb, ud); + gtk_box_pack_start(box3, GTK_WIDGET(combo), FALSE, FALSE, 0); + + GtkBox *qbox; + qbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_widget_set_name(GTK_WIDGET(qbox), "AudioTrackQualityBox"); + + // Audio Quality ScaleButton + const gchar *quality_icons[] = { + "weather-storm", + "weather-clear", + "weather-storm", + "weather-showers-scattered", + "weather-showers", + "weather-overcast", + "weather-few-clouds", + "weather-clear", + NULL + }; + scale = GTK_SCALE_BUTTON(gtk_scale_button_new(GTK_ICON_SIZE_BUTTON, + 0, 10, 0.1, quality_icons)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(scale), + "<b>Audio Quality:</b>\n" + "For encoders that support it, adjust the quality of the output."); + + gtk_widget_set_valign(GTK_WIDGET(scale), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(scale), "AudioTrackQuality"); + gtk_widget_show(GTK_WIDGET(scale)); + g_signal_connect(scale, "value-changed", (GCallback)audio_def_quality_changed_cb, ud); + gtk_box_pack_start(qbox, GTK_WIDGET(scale), FALSE, FALSE, 0); + + // Audio Quality Label + label = GTK_LABEL(gtk_label_new("0.00")); + gtk_label_set_width_chars(label, 4); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_widget_set_name(GTK_WIDGET(label), "AudioTrackQualityValue"); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(qbox, GTK_WIDGET(label), FALSE, FALSE, 0); + gtk_widget_hide(GTK_WIDGET(qbox)); + gtk_box_pack_start(box3, GTK_WIDGET(qbox), FALSE, FALSE, 0); + gtk_box_pack_start(box2, GTK_WIDGET(box3), FALSE, FALSE, 0); + + // Audio Mix ComboBox + combo = GTK_COMBO_BOX(gtk_combo_box_new()); + ghb_init_combo_box(combo); + ghb_mix_opts_set(combo); + ghb_update_widget(GTK_WIDGET(combo), ghb_int64_value(HB_AMIXDOWN_5POINT1)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(combo), + "Set the mixdown of the output audio track."); + gtk_widget_set_valign(GTK_WIDGET(combo), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(combo), "AudioMixdown"); + gtk_widget_show(GTK_WIDGET(combo)); + g_signal_connect(combo, "changed", (GCallback)audio_def_encode_setting_changed_cb, ud); + gtk_box_pack_start(box2, GTK_WIDGET(combo), FALSE, FALSE, 0); + + // Audio Sample Rate ComboBox + combo = GTK_COMBO_BOX(gtk_combo_box_new()); + ghb_init_combo_box(combo); + ghb_audio_samplerate_opts_set(combo); + ghb_update_widget(GTK_WIDGET(combo), ghb_int64_value(0)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(combo), + "Set the sample rate of the output audio track."); + gtk_widget_set_valign(GTK_WIDGET(combo), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(combo), "AudioSamplerate"); + gtk_widget_show(GTK_WIDGET(combo)); + g_signal_connect(combo, "changed", (GCallback)audio_def_encode_setting_changed_cb, ud); + gtk_box_pack_start(box2, GTK_WIDGET(combo), FALSE, FALSE, 0); + + box3 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_widget_set_name(GTK_WIDGET(box3), "gain_box"); + gtk_widget_show(GTK_WIDGET(box3)); + + // Audio Gain ScaleButton + const gchar *gain_icons[] = { + "audio-volume-muted", + "audio-volume-high", + "audio-volume-low", + "audio-volume-medium", + NULL + }; + scale = GTK_SCALE_BUTTON(gtk_scale_button_new(GTK_ICON_SIZE_BUTTON, + -20, 21, 1, gain_icons)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(scale), + "<b>Audio Gain:</b>\n" + "Adjust the amplification or attenuation of the output audio track."); + + gtk_widget_set_valign(GTK_WIDGET(scale), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(scale), "AudioTrackGain"); + gtk_widget_show(GTK_WIDGET(scale)); + g_signal_connect(scale, "value-changed", (GCallback)audio_def_gain_changed_cb, ud); + gtk_box_pack_start(box3, GTK_WIDGET(scale), FALSE, FALSE, 0); + + // Audio Gain Label + label = GTK_LABEL(gtk_label_new("0dB")); + gtk_label_set_width_chars(label, 6); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_widget_set_name(GTK_WIDGET(label), "AudioTrackGainValue"); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(box3, GTK_WIDGET(label), FALSE, FALSE, 0); + gtk_box_pack_start(box2, GTK_WIDGET(box3), FALSE, FALSE, 0); + + box3 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_widget_set_name(GTK_WIDGET(box3), "drc_box"); + gtk_widget_show(GTK_WIDGET(box3)); + + // Audio DRC ComboBox + const gchar *drc_icons[] = { + "audio-input-microphone", + NULL + }; + scale = GTK_SCALE_BUTTON(gtk_scale_button_new(GTK_ICON_SIZE_BUTTON, + 0.9, 4, 0.1, drc_icons)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(scale), + "<b>Dynamic Range Compression:</b>\n" + "Adjust the dynamic range of the output audio track.\n" + "For source audio that has a wide dynamic range,\n" + "very loud and very soft sequences, DRC allows you\n" + "to 'compress' the range by making loud sounds\n" + "softer and soft sounds louder.\n"); + + gtk_widget_set_valign(GTK_WIDGET(scale), GTK_ALIGN_CENTER); + gtk_widget_set_name(GTK_WIDGET(scale), "AudioTrackDRCSlider"); + gtk_widget_show(GTK_WIDGET(scale)); + g_signal_connect(scale, "value-changed", (GCallback)audio_def_drc_changed_cb, ud); + gtk_box_pack_start(box3, GTK_WIDGET(scale), FALSE, FALSE, 0); + + // Audio DRC Label + label = GTK_LABEL(gtk_label_new("Off")); + gtk_label_set_width_chars(label, 4); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + gtk_widget_set_name(GTK_WIDGET(label), "AudioTrackDRCValue"); + gtk_widget_show(GTK_WIDGET(label)); + gtk_box_pack_start(box3, GTK_WIDGET(label), FALSE, FALSE, 0); + gtk_box_pack_start(box2, GTK_WIDGET(box3), FALSE, FALSE, 0); + + // Remove button + image = GTK_IMAGE(gtk_image_new_from_icon_name("hb-remove", + GTK_ICON_SIZE_BUTTON)); + button = GTK_BUTTON(gtk_button_new()); + gtk_button_set_image(button, GTK_WIDGET(image)); + gtk_widget_set_tooltip_markup(GTK_WIDGET(button), + "Remove this audio encoder"); + gtk_button_set_relief(button, GTK_RELIEF_NONE); + gtk_widget_set_valign(GTK_WIDGET(button), GTK_ALIGN_CENTER); + gtk_widget_set_halign(GTK_WIDGET(button), GTK_ALIGN_END); + gtk_widget_set_name(GTK_WIDGET(button), "remove_button"); + gtk_widget_show(GTK_WIDGET(button)); + g_signal_connect(button, "clicked", (GCallback)audio_def_setting_remove_cb, ud); + gtk_box_pack_start(box2, GTK_WIDGET(button), TRUE, TRUE, 0); + + gtk_widget_show(GTK_WIDGET(box2)); + gtk_box_pack_start(box, GTK_WIDGET(box2), TRUE, TRUE, 0); + + gtk_widget_show(GTK_WIDGET(box)); + + GtkWidget *widget; + + int width; + widget = find_widget(GTK_WIDGET(box), "AudioEncoder"); + gtk_widget_get_preferred_width(widget, NULL, &width); + + widget = GHB_WIDGET(ud->builder, "audio_defaults_encoder_label"); + gtk_widget_set_size_request(widget, width, -1); + widget = find_widget(GTK_WIDGET(box), "br_q_box"); + gtk_widget_get_preferred_width(widget, NULL, &width); + widget = GHB_WIDGET(ud->builder, "audio_defaults_bitrate_label"); + gtk_widget_set_size_request(widget, width, -1); + widget = find_widget(GTK_WIDGET(box), "AudioMixdown"); + gtk_widget_get_preferred_width(widget, NULL, &width); + widget = GHB_WIDGET(ud->builder, "audio_defaults_mixdown_label"); + gtk_widget_set_size_request(widget, width, -1); + widget = find_widget(GTK_WIDGET(box), "AudioSamplerate"); + gtk_widget_get_preferred_width(widget, NULL, &width); + widget = GHB_WIDGET(ud->builder, "audio_defaults_samplerate_label"); + gtk_widget_set_size_request(widget, width, -1); + widget = find_widget(GTK_WIDGET(box), "gain_box"); + gtk_widget_get_preferred_width(widget, NULL, &width); + widget = GHB_WIDGET(ud->builder, "audio_defaults_gain_label"); + gtk_widget_set_size_request(widget, width, -1); + widget = find_widget(GTK_WIDGET(box), "drc_box"); + gtk_widget_get_preferred_width(widget, NULL, &width); + widget = GHB_WIDGET(ud->builder, "audio_defaults_drc_label"); + gtk_widget_set_size_request(widget, width, -1); + + return GTK_WIDGET(box); +} + +static void +audio_def_setting_update(signal_user_data_t *ud, GtkWidget *widget) +{ + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + gint index = gtk_list_box_row_get_index(row); + + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + int count = ghb_array_len(alist); + if (!block_updates && index >= 0 && index < count) + { + GValue *adict = ghb_array_get_nth(alist, index); + ghb_widget_to_setting(adict, widget); + } +} + +G_MODULE_EXPORT void +audio_add_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GtkListBox *avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_avail_lang")); + GtkListBox *selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_selected_lang")); + GtkListBoxRow *row; + GtkWidget *label; + + row = gtk_list_box_get_selected_row(avail); + if (row != NULL) + { + int idx; + const iso639_lang_t *lang; + GValue *glang, *alang_list; + + // Remove from UI available language list box + label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + // Add to UI selected language list box + gtk_list_box_insert(selected, label, -1); + + // Add to preset language list + idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + lang = ghb_iso639_lookup_by_int(idx); + glang = ghb_string_value_new(lang->iso639_2); + alang_list = ghb_settings_get_value(ud->settings, "AudioLanguageList"); + ghb_array_append(alang_list, glang); + ghb_clear_presets_selection(ud); + } +} + +G_MODULE_EXPORT void +audio_remove_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + + GtkListBox *avail, *selected; + GtkListBoxRow *row; + GtkWidget *label; + + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_selected_lang")); + row = gtk_list_box_get_selected_row(selected); + if (row != NULL) + { + gint index; + GValue *alang_list; + + index = gtk_list_box_row_get_index(row); + + // Remove from UI selected language list box + label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + // Add to UI available language list box + gtk_list_box_insert(avail, label, idx); + + // Remove from preset language list + alang_list = ghb_settings_get_value(ud->settings, "AudioLanguageList"); + ghb_array_remove(alang_list, index); + ghb_clear_presets_selection(ud); + } +} + +static void audio_quality_update_limits(GtkWidget *widget, int encoder) +{ + float low, high, gran, defval; + int dir; + + hb_audio_quality_get_limits(encoder, &low, &high, &gran, &dir); + defval = hb_audio_quality_get_default(encoder); + GtkScaleButton *sb; + GtkAdjustment *adj; + sb = GTK_SCALE_BUTTON(widget); + adj = gtk_scale_button_get_adjustment(sb); + if (dir) + { + // Quality values are inverted + defval = high - defval + low; + } + gtk_adjustment_configure (adj, defval, low, high, gran, gran * 10, 0); +} + +void audio_def_set_limits(signal_user_data_t *ud, GtkWidget *widget) +{ + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + gint index = gtk_list_box_row_get_index(row); + + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + int count = ghb_array_len(alist); + if (index < 0 || index >= count) + return; + + GValue *adict = ghb_array_get_nth(alist, index); + + int encoder = ghb_settings_combo_int(adict, "AudioEncoder"); + int fallback = ghb_settings_combo_int(ud->settings, "AudioEncoderFallback"); + // Allow quality settings if the current encoder supports quality + // or if the encoder is auto-passthru and the fallback encoder + // supports quality. + gboolean sensitive = + hb_audio_quality_get_default(encoder) != HB_INVALID_AUDIO_QUALITY || + (encoder == HB_ACODEC_AUTO_PASS && + hb_audio_quality_get_default(fallback) != HB_INVALID_AUDIO_QUALITY); + audio_def_settings_quality_set_sensitive(GTK_WIDGET(row), sensitive); + + int enc; + if (sensitive) + { + enc = encoder; + if (hb_audio_quality_get_default(encoder) == HB_INVALID_AUDIO_QUALITY) + { + enc = fallback; + } + audio_quality_update_limits(find_widget(GTK_WIDGET(row), + "AudioTrackQuality"), enc); + } + + enc = encoder; + if (enc & HB_ACODEC_PASS_FLAG) + { + enc = ghb_select_fallback(ud->settings, enc); + } + int sr = ghb_settings_combo_int(adict, "AudioSamplerate"); + if (sr == 0) + { + sr = 48000; + } + int mix = ghb_settings_combo_int(adict, "AudioMixdown"); + int low, high; + hb_audio_bitrate_get_limits(enc, sr, mix, &low, &high); + GtkWidget *w = find_widget(GTK_WIDGET(row), "AudioBitrate"); + ghb_audio_bitrate_opts_filter(GTK_COMBO_BOX(w), low, high); + w = find_widget(GTK_WIDGET(row), "AudioMixdown"); + ghb_mix_opts_filter(GTK_COMBO_BOX(w), enc); +} + +void audio_def_set_all_limits_cb(GtkWidget *widget, gpointer data) +{ + signal_user_data_t *ud = (signal_user_data_t*)data; + audio_def_set_limits(ud, widget); +} + +void audio_def_set_all_limits(signal_user_data_t *ud) +{ + GtkListBox *list_box; + + list_box = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_list_default")); + gtk_container_foreach(GTK_CONTAINER(list_box), + audio_def_set_all_limits_cb, (gpointer)ud); +} + +G_MODULE_EXPORT void +audio_def_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_fallback_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + audio_def_set_all_limits(ud); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_quality_enable_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + audio_def_setting_update(ud, widget); + + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + gint index = gtk_list_box_row_get_index(row); + + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + GValue *adict = ghb_array_get_nth(alist, index); + + audio_def_settings_bitrate_show(GTK_WIDGET(row), + !ghb_settings_get_boolean(adict, "AudioTrackQualityEnable")); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_quality_changed_cb(GtkWidget *widget, gdouble quality, signal_user_data_t *ud) +{ + audio_def_setting_update(ud, widget); + + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkWidget *quality_label = find_widget(GTK_WIDGET(row), + "AudioTrackQualityValue"); + gint index = gtk_list_box_row_get_index(row); + + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + GValue *adict = ghb_array_get_nth(alist, index); + int codec = ghb_settings_combo_int(adict, "AudioEncoder"); + + float low, high, gran; + int dir; + hb_audio_quality_get_limits(codec, &low, &high, &gran, &dir); + if (dir) + { + // Quality values are inverted + quality = high - quality + low; + } + char *s_quality = ghb_format_quality("", codec, quality); + ghb_update_widget(quality_label, ghb_string_value(s_quality)); + g_free(s_quality); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_gain_changed_cb(GtkWidget *widget, gdouble gain, signal_user_data_t *ud) +{ + audio_def_setting_update(ud, widget); + + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkWidget *gain_label = find_widget(GTK_WIDGET(row), "AudioTrackGainValue"); + char *s_gain; + if ( gain >= 21.0 ) + s_gain = g_strdup_printf("*11*"); + else + s_gain = g_strdup_printf("%ddB", (int)gain); + ghb_update_widget(gain_label, ghb_string_value(s_gain)); + g_free(s_gain); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_drc_changed_cb(GtkWidget *widget, gdouble drc, signal_user_data_t *ud) +{ + audio_def_setting_update(ud, widget); + + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + GtkWidget *drc_label = find_widget(GTK_WIDGET(row), "AudioTrackDRCValue"); + + char *s_drc; + if (drc < 0.99) + s_drc = g_strdup(_("Off")); + else + s_drc = g_strdup_printf("%.1f", drc); + ghb_update_widget(drc_label, ghb_string_value(s_drc)); + g_free(s_drc); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_setting_add_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + + GValue *adict; + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + int count = ghb_array_len(alist); + if (count > 0) + { + // Use first item in list as defaults for new entries. + adict = ghb_value_dup(ghb_array_get_nth(alist, 0)); + audio_def_update_widgets(GTK_WIDGET(row), adict); + } + else + { + // Use hard coded defaults + adict = ghb_dict_value_new(); + audio_def_settings_init_row(adict, GTK_WIDGET(row)); + } + ghb_array_append(alist, adict); + audio_def_settings_show(GTK_WIDGET(row), TRUE); + + // Add new "Add" button + widget = ghb_create_audio_settings_row(ud); + audio_def_settings_show(widget, FALSE); + GtkListBox *list_box; + list_box = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_list_default")); + gtk_list_box_insert(list_box, widget, -1); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_setting_remove_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GtkListBoxRow *row = ghb_audio_settings_get_row(widget); + gint index = gtk_list_box_row_get_index(row); + + GValue *alist = ghb_settings_get_value(ud->settings, "AudioList"); + int count = ghb_array_len(alist); + if (index < 0 || index >= count) + { + return; + } + gtk_widget_destroy(GTK_WIDGET(row)); + ghb_array_remove(alist, index); + ghb_clear_presets_selection(ud); +} + +G_MODULE_EXPORT void +audio_def_encode_setting_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + audio_def_setting_update(ud, widget); + audio_def_set_limits(ud, widget); + ghb_clear_presets_selection(ud); +} + +static void container_empty_cb(GtkWidget *widget, gpointer data) +{ + gtk_widget_destroy(widget); +} + +void ghb_container_empty(GtkContainer *c) +{ + gtk_container_foreach(c, container_empty_cb, NULL); +} + +GtkListBoxRow* ghb_find_lang_row(GtkListBox *list_box, int lang_idx) +{ + GList *list, *link; + GtkListBoxRow *result = NULL; + + list = link = gtk_container_get_children(GTK_CONTAINER(list_box)); + while (link != NULL) + { + GtkListBoxRow *row = (GtkListBoxRow*)link->data; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + if (idx == lang_idx) + { + result = row; + break; + } + link = link->next; + } + g_list_free(list); + + return result; +} + +static void audio_def_lang_list_clear_cb(GtkWidget *row, gpointer data) +{ + GtkListBox *avail = (GtkListBox*)data; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + gtk_list_box_insert(avail, label, idx); +} + +static void audio_def_selected_lang_list_clear(signal_user_data_t *ud) +{ + GtkListBox *avail, *selected; + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_selected_lang")); + gtk_container_foreach(GTK_CONTAINER(selected), + audio_def_lang_list_clear_cb, (gpointer)avail); +} + +static void audio_def_lang_list_init(signal_user_data_t *ud) +{ + GValue *lang_list; + + // Clear selected languages. + audio_def_selected_lang_list_clear(ud); + + lang_list = ghb_settings_get_value(ud->settings, "AudioLanguageList"); + if (lang_list == NULL) + { + lang_list = ghb_array_value_new(8); + ghb_settings_set_value(ud->settings, "AudioLanguageList", lang_list); + } + + int ii, count; + count = ghb_array_len(lang_list); + for (ii = 0; ii < count; ) + { + GValue *lang_val = ghb_array_get_nth(lang_list, ii); + int idx = ghb_lookup_audio_lang(lang_val); + + GtkListBox *avail, *selected; + GtkListBoxRow *row; + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_selected_lang")); + row = ghb_find_lang_row(avail, idx); + if (row) + { + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + gtk_list_box_insert(selected, label, -1); + ii++; + } + else + { + // Error in list. Probably duplicate languages. Remove + // this item from the list. + ghb_array_remove(lang_list, ii); + count--; + } + } +} + +void ghb_audio_def_settings_init(signal_user_data_t *ud) +{ + GtkListBox *list_box; + GValue *alist; + int count, ii; + + audio_def_lang_list_init(ud); + + // Init the AudioList settings if necessary + alist = ghb_settings_get_value(ud->settings, "AudioList"); + if (alist == NULL) + { + alist = ghb_array_value_new(8); + ghb_settings_set_value(ud->settings, "AudioList", alist); + } + + // Empty the current list + list_box = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_list_default")); + ghb_container_empty(GTK_CONTAINER(list_box)); + + GtkWidget *widget; + // Populate with new values + count = ghb_array_len(alist); + for (ii = 0; ii < count; ii++) + { + GValue *adict; + + adict = ghb_array_get_nth(alist, ii); + widget = ghb_create_audio_settings_row(ud); + gtk_list_box_insert(list_box, widget, -1); + audio_def_update_widgets(widget, adict); + } + // Add row with "Add" button + widget = ghb_create_audio_settings_row(ud); + audio_def_settings_show(widget, FALSE); + gtk_list_box_insert(list_box, widget, -1); +} + +void ghb_init_audio_defaults_ui(signal_user_data_t *ud) +{ + GtkListBox *list_box; + + list_box = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "audio_avail_lang")); + ghb_init_lang_list_box(list_box); +} diff --git a/gtk/src/audiohandler.h b/gtk/src/audiohandler.h index aaaddc89d..f1c7e8072 100644 --- a/gtk/src/audiohandler.h +++ b/gtk/src/audiohandler.h @@ -31,13 +31,16 @@ void ghb_adjust_audio_rate_combos(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); -const gchar* ghb_get_user_audio_lang(GValue *settings, gint titleindex, gint track); +const gchar* ghb_get_user_audio_lang(GValue *settings, hb_title_t *title, 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_select_fallback( GValue *settings, int mux, int acodec ); +int ghb_select_fallback( GValue *settings, int acodec ); int ghb_get_copy_mask(GValue *settings); -void ghb_audio_list_refresh(signal_user_data_t *ud); +void ghb_audio_list_refresh_all(signal_user_data_t *ud); char * ghb_format_quality( const char *prefix, int codec, double quality ); -void ghb_show_hide_advanced_audio( signal_user_data_t *ud ); +void ghb_init_audio_defaults_ui(signal_user_data_t *ud); +void ghb_audio_def_settings_init(signal_user_data_t *ud); +GtkListBoxRow* ghb_find_lang_row(GtkListBox *list_box, int lang_idx); +void ghb_audio_title_change(signal_user_data_t *ud, gboolean title_valid); #endif // _AUDIOHANDLER_H_ diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index bfb67bf6f..9d2253431 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -56,7 +56,6 @@ #define NOTIFY_CHECK_VERSION(x,y,z) 0 #endif #else -#define WINVER 0x0500 #include <winsock2.h> #include <dbt.h> #endif @@ -889,7 +888,6 @@ start_scan( gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(widget), "hb-stop"); gtk_tool_button_set_label(GTK_TOOL_BUTTON(widget), _("Stop Scan")); gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), _("Stop Scan")); - //gtk_widget_set_sensitive(widget, FALSE); widget = GHB_WIDGET(ud->builder, "source_open"); gtk_widget_set_sensitive(widget, FALSE); @@ -1258,7 +1256,7 @@ window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *u } static void -update_acodec_combo(signal_user_data_t *ud) +update_acodec(signal_user_data_t *ud) { ghb_adjust_audio_rate_combos(ud); ghb_grey_combo_options (ud); @@ -1299,12 +1297,12 @@ container_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_widget_to_setting(ud->settings, widget); ghb_check_dependency(ud, widget, NULL); show_container_options(ud); - update_acodec_combo(ud); + update_acodec(ud); ghb_update_destination_extension(ud); ghb_clear_presets_selection(ud); ghb_live_reset(ud); ghb_subtitle_prune(ud); - ghb_subtitle_list_refresh_selected(ud); + ghb_subtitle_list_refresh_all(ud); ghb_audio_list_refresh_selected(ud); } @@ -1641,10 +1639,10 @@ set_title_settings(GValue *settings, gint titleindex) ghb_settings_set_string(settings, "MetaLongDescription", title->metadata->long_description); } + ghb_set_pref_subtitle_settings(title, settings); } 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; @@ -1705,8 +1703,10 @@ title_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_check_dependency(ud, widget, NULL); update_chapter_list_settings(ud->settings); update_chapter_list_from_settings(ud->builder, ud->settings); + ghb_audio_title_change(ud, title != NULL); ghb_set_pref_audio_settings(titleindex, ud->settings); ghb_set_pref_audio_from_settings(ud, ud->settings); + ghb_subtitle_title_change(ud, title != NULL); ghb_set_pref_subtitle(titleindex, ud); ghb_grey_combo_options (ud); @@ -3424,8 +3424,7 @@ static void browse_url(const gchar *url) { #if defined(_WIN32) - HINSTANCE r; - r = ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); #else gboolean result; char *argv[] = @@ -3895,7 +3894,6 @@ advanced_audio_changed_cb(GtkWidget *widget, signal_user_data_t *ud) ghb_check_dependency(ud, widget, NULL); const gchar *name = ghb_get_setting_key(widget); ghb_pref_save(ud->settings, name); - ghb_show_hide_advanced_audio( ud ); } G_MODULE_EXPORT void diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index acbea7cf9..6fda5cea4 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -2802,795 +2802,608 @@ Colon separated list of x264 options.</property> </packing> </child> <child> - <object class="GtkBox" id="audio_tab"> - <property name="orientation">vertical</property> + <object class="GtkBox" id="audio_defaults"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="orientation">vertical</property> + <property name="margin_left">12</property> + <property name="margin_right">12</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</property> + <property name="hexpand">True</property> <child> - <object class="GtkAlignment" id="alignment18"> + <object class="GtkBox" id="audio_defaults_box1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="top_padding">6</property> - <property name="bottom_padding">2</property> - <property name="left_padding">12</property> - <property name="right_padding">2</property> + <property name="orientation">horizontal</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="vbox17"> - <property name="orientation">vertical</property> + <object class="GtkBox" id="audio_defaults_box2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">2</property> + <property name="orientation">vertical</property> <child> - <object class="GtkGrid" id="table16"> + <object class="GtkGrid" id="grid2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="column_spacing">5</property> <property name="row_spacing">2</property> <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <object class="GtkAlignment" id="alignment47"> + <object class="GtkLabel" id="label4"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="yalign">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkButton" id="audio_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Add new audio settings to the list</property> - <property name="relief">none</property> - <signal name="clicked" handler="audio_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - </child> + <property name="xalign">1</property> + <property name="label" translatable="yes">Selection Behavior:</property> + <property name="justify">right</property> </object> <packing> - <property name="top_attach">0</property> <property name="left_attach">0</property> + <property name="top_attach">0</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkAlignment" id="alignment37"> + <object class="GtkComboBox" id="AudioTrackSelectionBehavior"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="yalign">0</property> - <property name="yscale">0</property> - <child> - <object class="GtkButton" id="audio_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Remove the selected audio settings</property> - <property name="relief">none</property> - <signal name="clicked" handler="audio_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - </child> + <signal name="changed" handler="audio_def_widget_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">0</property> <property name="left_attach">1</property> + <property name="top_attach">0</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> </object> <packing> - <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkExpander" id="AdvancedAudioExpander"> + <object class="GtkGrid" id="grid3"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="column_spacing">5</property> + <property name="row_spacing">2</property> + <property name="halign">GTK_ALIGN_END</property> + <property name="margin_top">6</property> + <property name="margin_bottom">6</property> <child> - <object class="GtkBox" id="vbox44"> - <property name="orientation">vertical</property> + <object class="GtkScrolledWindow" id="scrolledwindow10"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">5</property> + <property name="min_content_height">108</property> <child> - <object class="GtkGrid" id="AdvancedAudioPassTable"> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="column_spacing">5</property> - <property name="row_spacing">2</property> - <child> - <object class="GtkBox" id="hbox40"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">5</property> - <child> - <object class="GtkLabel" id="labela3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">1</property> - <property name="label" translatable="yes">Auto Passthru:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioAllowMP3Pass"> - <property name="label" translatable="yes">MP3</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Enable this if your playback device supports MP3. -This permits MP3 passthru to be selected when automatic passthru selection is enabled.</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioAllowAACPass"> - <property name="label" translatable="yes">AAC</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Enable this if your playback device supports AAC. -This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioAllowAC3Pass"> - <property name="label" translatable="yes">AC-3</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Enable this if your playback device supports AC-3. -This permits AC-3 passthru to be selected when automatic passthru selection is enabled.</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioAllowDTSPass"> - <property name="label" translatable="yes">DTS</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Enable this if your playback device supports DTS. -This permits DTS passthru to be selected when automatic passthru selection is enabled.</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioAllowDTSHDPass"> - <property name="label" translatable="yes">DTS-HD</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Enable this if your playback device supports DTS-HD. -This permits DTS-HD passthru to be selected when automatic passthru selection is enabled.</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">0</property> - <property name="width">4</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="labela4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">1</property> - <property name="hexpand">True</property> - <property name="label" translatable="yes">Passthru Fallback:</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">4</property> - <property name="width">3</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="AudioEncoderFallback"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the audio codec to encode with when a suitable track can not be found for audio passthru.</property> - <signal name="changed" handler="global_audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">7</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkSeparator" id="separator1"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">0</property> - <property name="width">8</property> - <property name="height">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkGrid" id="table14"> + <object class="GtkListBox" id="audio_avail_lang"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="column_spacing">5</property> - <property name="row_spacing">2</property> - <child> - <object class="GtkLabel" id="audio_name_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Track Name:</property> - <property name="use_markup">True</property> - <property name="halign">center</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioSamplerateLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Sample Rate:</property> - <property name="use_markup">True</property> - <property name="halign">center</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioTrackGainLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Gain:</property> - <property name="use_markup">True</property> - <property name="halign">center</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">2</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioTrackDRCSliderLabel"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_markup"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. - -For source audio that has a wide dynamic range (very loud and very soft sequences), -DRC allows you to 'compress' the range by making loud sounds softer and soft sounds louder.</property> - <property name="label" translatable="yes">DRC:</property> - <property name="use_markup">True</property> - <property name="halign">center</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">3</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="AudioTrackQualityEnable"> - <property name="label" translatable="yes">Quality:</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_markup"><b>Quality:</b> For output codec's that support it, adjust the quality of the output.</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">4</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="AudioTrackName"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the audio track name. - -Players may use this in the audio selection list.</property> - <property name="max_length">40</property> - <property name="activates_default">True</property> - <property name="width_chars">20</property> - <property name="truncate_multiline">True</property> - <property name="primary_icon_activatable">False</property> - <property name="secondary_icon_activatable">False</property> - <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="AudioSamplerate"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the sample rate of the output audio track.</property> - <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox34"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkScaleButton" id="AudioTrackGain"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_markup"><b>Audio Gain:</b> Adjust the amplification or attenuation of the output audio track.</property> - <property name="orientation">vertical</property> - <property name="adjustment">adjustment35</property> - <property name="icons">audio-volume-muted -audio-volume-high -audio-volume-low -audio-volume-medium</property> - <signal name="value-changed" handler="gain_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioTrackGainValue"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">0dB</property> - <property name="use_markup">True</property> - <property name="width_chars">6</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">2</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox33"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkScaleButton" id="AudioTrackDRCSlider"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_markup"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. - -For source audio that has a wide dynamic range (very loud and very soft sequences), -DRC allows you to 'compress' the range by making loud sounds softer and soft sounds louder.</property> - <property name="orientation">vertical</property> - <property name="adjustment">adjustment28</property> - <property name="icons">audio-input-microphone</property> - <signal name="value-changed" handler="drc_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioTrackDRCValue"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Off</property> - <property name="use_markup">True</property> - <property name="width_chars">4</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">3</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox32"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkScaleButton" id="AudioTrackQuality"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="receives_default">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_markup"><b>Quality:</b> For output codec's that support it, adjust the quality of the output.</property> - <property name="orientation">vertical</property> - <property name="adjustment">audio_quality_adj</property> - <property name="icons">weather-storm -weather-clear -weather-storm -weather-showers-scattered -weather-showers -weather-overcast -weather-few-clouds -weather-clear</property> - <signal name="value-changed" handler="quality_widget_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="AudioTrackQualityValue"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">00.0</property> - <property name="use_markup">True</property> - <property name="width_chars">4</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">4</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="filler_label0"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="top_attach">1</property> - <property name="left_attach">5</property> - <property name="width">3</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="filler_label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="top_attach">0</property> - <property name="left_attach">5</property> - <property name="width">3</property> - <property name="height">1</property> - </packing> - </child> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> </child> </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">4</property> + </packing> </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkGrid" id="table1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkLabel" id="label35"> + <object class="GtkScrolledWindow" id="scrolledwindow11"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Track</property> + <child> + <object class="GtkListBox" id="audio_selected_lang"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> </object> <packing> - <property name="top_attach">0</property> - <property name="left_attach">0</property> + <property name="left_attach">2</property> + <property name="top_attach">1</property> <property name="width">1</property> - <property name="height">1</property> + <property name="height">4</property> </packing> </child> <child> - <object class="GtkLabel" id="label68"> + <object class="GtkButton" id="audio_lang_add"> + <property name="label" translatable="yes">Add</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Encoder</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <signal name="clicked" handler="audio_add_lang_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">0</property> <property name="left_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkLabel" id="AudioBitrateLabel"> + <object class="GtkButton" id="audio_lang_remove"> + <property name="label" translatable="yes">Remove</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Bitrate</property> - <property name="justify">center</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <signal name="clicked" handler="audio_remove_lang_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">0</property> - <property name="left_attach">2</property> + <property name="left_attach">1</property> + <property name="top_attach">3</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkLabel" id="AudioMixdownLabel"> + <object class="GtkLabel" id="label8"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Mix</property> + <property name="label" translatable="yes">Available Languages</property> </object> <packing> + <property name="left_attach">0</property> <property name="top_attach">0</property> - <property name="left_attach">3</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkComboBox" id="AudioTrack"> - <property name="width_request">180</property> + <object class="GtkLabel" id="label24"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">List of audio tracks available from your source.</property> - <signal name="changed" handler="audio_track_changed_cb" swapped="no"/> + <property name="label" translatable="yes">Selected Languages</property> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">0</property> + <property name="left_attach">2</property> + <property name="top_attach">0</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="grid4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="column_spacing">5</property> + <property name="row_spacing">2</property> + <child> + <object class="GtkLabel" id="labela3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Auto Passthru Options:</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowMP3Pass"> + <property name="label" translatable="yes">MP3</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable this if your playback device supports MP3. +This permits MP3 passthru to be selected when automatic passthru selection is enabled.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_passthru_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowAACPass"> + <property name="label" translatable="yes">AAC</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable this if your playback device supports AAC. +This permits AAC passthru to be selected when automatic passthru selection is enabled.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_passthru_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowAC3Pass"> + <property name="label" translatable="yes">AC-3</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable this if your playback device supports AC-3. +This permits AC-3 passthru to be selected when automatic passthru selection is enabled.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_passthru_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowDTSPass"> + <property name="label" translatable="yes">DTS</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable this if your playback device supports DTS. +This permits DTS passthru to be selected when automatic passthru selection is enabled.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_passthru_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioAllowDTSHDPass"> + <property name="label" translatable="yes">DTS-HD</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable this if your playback device supports DTS-HD. +This permits DTS-HD passthru to be selected when automatic passthru selection is enabled.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_passthru_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="labela4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">1</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes">Passthru Fallback:</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">5</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioEncoderFallback"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the audio codec to encode with when a suitable track can not be found for audio passthru.</property> + <signal name="changed" handler="audio_fallback_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">5</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="AudioSecondaryEncoderMode"> + <property name="label" translatable="yes">Use only first encoder for secondary audio</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Only the primary audio track will be encoded with the full encoder list. +All other secondary audio output tracks will be encoded with first encoder only.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_def_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_def_settings_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">12</property> + <property name="xalign">0</property> + <property name="use_markup">True</property> + <property name="label" translatable="yes"><b>Audio Encoder Settings:</b></property> + <property name="tooltip_markup">Each selected source track will be encoded with all selected encoders</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator" id="sep1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="audio_list_default_header"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkLabel" id="audio_defaults_encoder_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Encoder</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_defaults_bitrate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Bitrate/Quality</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_defaults_mixdown_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Mixdown</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_defaults_samplerate_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Samplerate</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_defaults_gain_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Gain</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_defaults_drc_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">DRC</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow12"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="hexpand">True</property> + <child> + <object class="GtkListBox" id="audio_list_default"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="vexpand">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="audio_defaults_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Audio Defaults</property> + </object> + <packing> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="audio_tab"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkAlignment" id="alignment18"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">6</property> + <property name="right_padding">6</property> + <child> + <object class="GtkBox" id="vbox17"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">2</property> + <child> + <object class="GtkToolbar" id="audio_toolbar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkComboBox" id="AudioEncoder"> + <object class="GtkToolButton" id="audio_add"> <property name="visible">True</property> + <property name="sensitive">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the audio codec to encode this track with.</property> - <signal name="changed" handler="audio_codec_changed_cb" swapped="no"/> + <property name="is_important">True</property> + <property name="label" translatable="yes">Add</property> + <property name="icon_name">list-add</property> + <property name="tooltip_text" translatable="yes">Add new audio settings to the list</property> + <signal name="clicked" handler="audio_add_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> <child> - <object class="GtkComboBox" id="AudioBitrate"> + <object class="GtkToolButton" id="audio_add_all"> <property name="visible">True</property> + <property name="sensitive">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the bitrate to encode this track with.</property> - <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> + <property name="is_important">True</property> + <property name="label" translatable="yes">Add All</property> + <property name="icon_name">list-add</property> + <property name="tooltip_text" translatable="yes">Add all audio tracks to the list</property> + <signal name="clicked" handler="audio_add_all_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">2</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> <child> - <object class="GtkComboBox" id="AudioMixdown"> + <object class="GtkToolButton" id="audio_reset"> <property name="visible">True</property> + <property name="sensitive">True</property> <property name="can_focus">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the mixdown of the output audio track.</property> - <signal name="changed" handler="audio_mix_changed_cb" swapped="no"/> + <property name="is_important">True</property> + <property name="label" translatable="yes">Reload Defaults</property> + <property name="icon_name">emblem-default</property> + <property name="tooltip_text" translatable="yes">Reload all audio settings from defaults</property> + <signal name="clicked" handler="audio_reset_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">3</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="position">0</property> </packing> </child> <child> <object class="GtkScrolledWindow" id="scrolledwindow5"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> <object class="GtkTreeView" id="audio_list"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="headers_visible">False</property> + <property name="headers_clickable">False</property> <child internal-child="selection"> <object class="GtkTreeSelection" id="treeview-selection1"/> </child> @@ -3600,7 +3413,7 @@ weather-clear</property> <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">3</property> + <property name="position">2</property> </packing> </child> </object> @@ -3614,301 +3427,380 @@ weather-clear</property> </child> </object> <packing> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> <child type="tab"> <object class="GtkLabel" id="label48"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">Audio</property> + <property name="label" translatable="yes">Audio List</property> </object> <packing> - <property name="position">2</property> + <property name="position">3</property> <property name="tab_fill">False</property> </packing> </child> <child> - <object class="GtkBox" id="subtitle_tab"> - <property name="orientation">vertical</property> + <object class="GtkBox" id="subtitle_defaults"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="orientation">vertical</property> + <property name="margin_left">12</property> + <property name="margin_right">12</property> + <property name="margin_top">12</property> + <property name="margin_bottom">12</property> + <property name="hexpand">True</property> <child> - <object class="GtkAlignment" id="alignment23"> + <object class="GtkBox" id="subtitle_defaults_box1"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="top_padding">12</property> - <property name="bottom_padding">2</property> - <property name="left_padding">12</property> - <property name="right_padding">2</property> + <property name="orientation">horizontal</property> + <property name="spacing">6</property> <child> - <object class="GtkBox" id="vbox12"> - <property name="orientation">vertical</property> + <object class="GtkBox" id="subtitle_defaults_box2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">2</property> + <property name="orientation">vertical</property> <child> - <object class="GtkBox" id="hbox45"> - <property name="orientation">horizontal</property> + <object class="GtkGrid" id="sub_grid2"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">5</property> - <child> - <object class="GtkButton" id="subtitle_add"> - <property name="label" translatable="yes">Subtitle</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Add new subtitle to the list</property> - <property name="image">subtitle_add_image</property> - <property name="relief">none</property> - <signal name="clicked" handler="subtitle_add_clicked_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> + <property name="column_spacing">5</property> + <property name="row_spacing">2</property> <child> - <object class="GtkButton" id="srt_add"> - <property name="label" translatable="yes">Import SRT</property> + <object class="GtkLabel" id="sub_label4"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Add new SRT subtitle to the list</property> - <property name="image">srt_add_image</property> - <property name="relief">none</property> - <signal name="clicked" handler="srt_add_clicked_cb" swapped="no"/> + <property name="can_focus">False</property> + <property name="xalign">1</property> + <property name="label" translatable="yes">Selection Behavior:</property> + <property name="justify">right</property> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> </packing> </child> <child> - <object class="GtkButton" id="subtitle_remove"> + <object class="GtkComboBox" id="SubtitleTrackSelectionBehavior"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Remove the selected subtitle settings</property> - <property name="relief">none</property> - <signal name="clicked" handler="subtitle_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-remove</property> - </object> - </child> + <property name="can_focus">False</property> + <signal name="changed" handler="subtitle_def_widget_changed_cb" swapped="no"/> </object> <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> </packing> </child> </object> <packing> - <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkGrid" id="subtitle_table"> + <object class="GtkGrid" id="sub_grid3"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="column_spacing">4</property> + <property name="column_spacing">5</property> + <property name="row_spacing">2</property> + <property name="halign">GTK_ALIGN_END</property> + <property name="margin_top">6</property> + <property name="margin_bottom">6</property> <child> - <object class="GtkLabel" id="subtitle_track_label"> + <object class="GtkScrolledWindow" id="sub_scrolledwindow10"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Track</property> + <property name="min_content_height">108</property> + <child> + <object class="GtkListBox" id="subtitle_avail_lang"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> </object> <packing> - <property name="top_attach">0</property> <property name="left_attach">0</property> + <property name="top_attach">1</property> <property name="width">1</property> - <property name="height">1</property> + <property name="height">4</property> </packing> </child> <child> - <object class="GtkLabel" id="srt_lang_label"> + <object class="GtkScrolledWindow" id="sub_scrolledwindow11"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Language</property> + <child> + <object class="GtkListBox" id="subtitle_selected_lang"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> </object> <packing> - <property name="top_attach">0</property> - <property name="left_attach">1</property> + <property name="left_attach">2</property> + <property name="top_attach">1</property> <property name="width">1</property> - <property name="height">1</property> + <property name="height">4</property> </packing> </child> <child> - <object class="GtkLabel" id="srt_code_label"> + <object class="GtkButton" id="subtitle_lang_add"> + <property name="label" translatable="yes">Add</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Character Code</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <signal name="clicked" handler="subtitle_add_lang_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">0</property> - <property name="left_attach">2</property> + <property name="left_attach">1</property> + <property name="top_attach">2</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkLabel" id="srt_file_label"> + <object class="GtkButton" id="subtitle_lang_remove"> + <property name="label" translatable="yes">Remove</property> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">File</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <signal name="clicked" handler="subtitle_remove_lang_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">0</property> - <property name="left_attach">3</property> + <property name="left_attach">1</property> + <property name="top_attach">3</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkLabel" id="srt_offset_label"> + <object class="GtkLabel" id="sub_label8"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Offset (ms)</property> + <property name="label" translatable="yes">Available Languages</property> </object> <packing> + <property name="left_attach">0</property> <property name="top_attach">0</property> - <property name="left_attach">4</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkComboBox" id="SubtitleTrack"> + <object class="GtkLabel" id="sub_label24"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">List of subtitle tracks available from your source.</property> - <signal name="changed" handler="subtitle_track_changed_cb" swapped="no"/> + <property name="label" translatable="yes">Selected Languages</property> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">0</property> + <property name="left_attach">2</property> + <property name="top_attach">0</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> <child> - <object class="GtkComboBox" id="SrtLanguage"> + <object class="GtkLabel" id="subtitle_preferred_language"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the language of this subtitle. -This value will be used by players in subtitle menus.</property> - <signal name="changed" handler="srt_lang_changed_cb" swapped="no"/> + <property name="xalign">0</property> + <property name="label" translatable="yes">Preferred Language: None</property> + <property name="justify">right</property> </object> <packing> + <property name="left_attach">3</property> <property name="top_attach">1</property> - <property name="left_attach">1</property> <property name="width">1</property> <property name="height">1</property> </packing> </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="SubtitleAddForeignAudioSearch"> + <property name="label" translatable="yes">Add Foreign Audio Search Pass</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Add "Foreign Audio Search" when the default audio track is your preferred language. +This search pass finds short sequences of foreign audio and provides subtitles for them.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_def_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="SubtitleAddForeignAudioSubtitle"> + <property name="label" translatable="yes">Add subtitle track if default audio is foreign</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">When the default audio track is not your preferred language, add a subtitle track.</property> + <property name="xalign">0</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_def_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="SubtitleAddCC"> + <property name="label" translatable="yes">Add Closed Captions when available</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Closed captions are text subtitles that can be added to any container as a soft subtitle track (not burned)</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_def_widget_changed_cb" swapped="no"/> + </object> + </child> + </object> + <packing> + <property name="position">4</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="subtitle_defaults_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Subtitle Defaults</property> + </object> + <packing> + <property name="position">4</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <object class="GtkBox" id="subtitle_tab"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkAlignment" id="alignment23"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="top_padding">6</property> + <property name="bottom_padding">6</property> + <property name="left_padding">6</property> + <property name="right_padding">6</property> + <child> + <object class="GtkBox" id="vbox12"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="spacing">2</property> + <child> + <object class="GtkToolbar" id="subtitle_toolbar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkComboBox" id="SrtCodeset"> - <property name="width_request">150</property> + <object class="GtkToolButton" id="subtitle_add"> <property name="visible">True</property> + <property name="sensitive">True</property> <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Set the character code used by the SRT file you are importing. - -SRTs come in all flavours of character sets. -We translate the character set to UTF-8. -The source's character code is needed in order to perform this translation.</property> - <property name="has_entry">True</property> - <signal name="changed" handler="srt_changed_cb" swapped="no"/> - <child internal-child="entry"> - <object class="GtkEntry" id="combobox-entry1"> - <property name="can_focus">True</property> - </object> - </child> + <property name="is_important">True</property> + <property name="label" translatable="yes">Add</property> + <property name="icon_name">list-add</property> + <property name="tooltip_text" translatable="yes">Add new subtitle settings to the list</property> + <signal name="clicked" handler="subtitle_add_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">2</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> <child> - <object class="GtkFileChooserButton" id="SrtFile"> + <object class="GtkToolButton" id="subtitle_add_all"> <property name="visible">True</property> + <property name="sensitive">True</property> <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Select the SRT file to import.</property> - <property name="local_only">False</property> - <property name="hexpand">True</property> - <property name="title" translatable="yes">Srt File</property> - <signal name="selection-changed" handler="srt_file_changed_cb" swapped="no"/> + <property name="is_important">True</property> + <property name="label" translatable="yes">Add All</property> + <property name="icon_name">list-add</property> + <property name="tooltip_text" translatable="yes">Add all subtitle tracks to the list</property> + <signal name="clicked" handler="subtitle_add_all_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">3</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> <child> - <object class="GtkSpinButton" id="SrtOffset"> + <object class="GtkToolButton" id="subtitle_reset"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="sensitive">True</property> + <property name="can_focus">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip_text" translatable="yes">Adjust the offset in milliseconds between video and SRT timestamps</property> - <property name="primary_icon_activatable">False</property> - <property name="secondary_icon_activatable">False</property> - <property name="adjustment">adjustment31</property> - <signal name="value-changed" handler="srt_changed_cb" swapped="no"/> + <property name="is_important">True</property> + <property name="label" translatable="yes">Reload Defaults</property> + <property name="icon_name">emblem-default</property> + <property name="tooltip_text" translatable="yes">Reload all subtitle settings from defaults</property> + <signal name="clicked" handler="subtitle_reset_clicked_cb" swapped="no"/> </object> <packing> - <property name="top_attach">1</property> - <property name="left_attach">4</property> - <property name="width">1</property> - <property name="height">1</property> + <property name="expand">False</property> </packing> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">0</property> </packing> </child> <child> <object class="GtkScrolledWindow" id="scrolledwindow4"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> <object class="GtkTreeView" id="subtitle_list"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="headers_visible">False</property> + <property name="headers_clickable">False</property> <child internal-child="selection"> <object class="GtkTreeSelection" id="treeview-selection2"/> </child> @@ -3918,7 +3810,7 @@ The source's character code is needed in order to perform this translation.</pro <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">2</property> + <property name="position">1</property> </packing> </child> </object> @@ -3932,17 +3824,17 @@ The source's character code is needed in order to perform this translation.</pro </child> </object> <packing> - <property name="position">3</property> + <property name="position">5</property> </packing> </child> <child type="tab"> <object class="GtkLabel" id="label9"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">Subtitles</property> + <property name="label" translatable="yes">Subtitle List</property> </object> <packing> - <property name="position">3</property> + <property name="position">5</property> <property name="tab_fill">False</property> </packing> </child> @@ -5015,7 +4907,7 @@ You can edit these and add additional options.</property> </child> </object> <packing> - <property name="position">4</property> + <property name="position">6</property> </packing> </child> <child type="tab"> @@ -5025,7 +4917,7 @@ You can edit these and add additional options.</property> <property name="label" translatable="yes">Advanced</property> </object> <packing> - <property name="position">4</property> + <property name="position">6</property> <property name="tab_fill">False</property> </packing> </child> @@ -5096,7 +4988,7 @@ You can edit these and add additional options.</property> </child> </object> <packing> - <property name="position">5</property> + <property name="position">7</property> </packing> </child> <child type="tab"> @@ -5107,7 +4999,7 @@ You can edit these and add additional options.</property> <property name="label" translatable="yes">Chapters</property> </object> <packing> - <property name="position">5</property> + <property name="position">7</property> <property name="tab_fill">False</property> </packing> </child> @@ -5430,7 +5322,7 @@ You can edit these and add additional options.</property> </child> </object> <packing> - <property name="position">6</property> + <property name="position">8</property> </packing> </child> <child type="tab"> @@ -5441,7 +5333,7 @@ You can edit these and add additional options.</property> <property name="label" translatable="yes">Tags</property> </object> <packing> - <property name="position">6</property> + <property name="position">8</property> <property name="tab_fill">False</property> </packing> </child> @@ -6149,173 +6041,6 @@ You can edit these and add additional options.</property> </packing> </child> <child> - <object class="GtkBox" id="vbox18"> - <property name="orientation">vertical</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkAlignment" id="alignment61"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="yscale">0</property> - <property name="top_padding">6</property> - <property name="bottom_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox7"> - <property name="orientation">vertical</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkBox" id="hbox81"> - <property name="orientation">horizontal</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="spacing">4</property> - <child> - <object class="GtkLabel" id="label87"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Preferred Language:</property> - <property name="use_markup">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkComboBox" id="PreferredLanguage"> - <property name="width_request">150</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <signal name="changed" handler="pref_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">17</property> - <child> - <object class="GtkBox" id="vbox49"> - <property name="orientation">vertical</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkRadioButton" id="AudioDUB"> - <property name="label" translatable="yes">DUB Foreign language audio</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="pref_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="NotAudioDUB"> - <property name="label" translatable="yes">Use foreign language audio and add subtitles</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <property name="group">AudioDUB</property> - <signal name="toggled" handler="pref_changed_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment70"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="yscale">0</property> - <property name="top_padding">6</property> - <property name="bottom_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkCheckButton" id="AddCC"> - <property name="label" translatable="yes">Add Closed Captions when available</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="pref_changed_cb" swapped="no"/> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Audio/Subtitles</property> - </object> - <packing> - <property name="position">1</property> - <property name="tab_fill">False</property> - </packing> - </child> - <child> <object class="GtkAlignment" id="alignment3"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -6579,26 +6304,6 @@ You can edit these and add additional options.</property> </packing> </child> <child> - <object class="GtkCheckButton" id="AdvancedAutoPassthru"> - <property name="label" translatable="yes">Enable Advanced Auto-Passthru options</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">Enabling this adds extra widgets to the audio panel that allow -you to specify which particular codecs shall be passed -and which codec to use when passthru is not possible</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="advanced_audio_changed_cb" swapped="no"/> - </object> - <packing> - <property name="top_attach">5</property> - <property name="left_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> <object class="GtkCheckButton" id="HideAdvancedVideoSettings"> <property name="label" translatable="yes">Hide Advanced Video Options Tab</property> <property name="visible">True</property> @@ -6612,7 +6317,7 @@ on the Video tab instead.</property> <signal name="toggled" handler="advanced_video_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">6</property> + <property name="top_attach">5</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> @@ -6838,7 +6543,7 @@ on the Video tab instead.</property> </child> </object> <packing> - <property name="position">2</property> + <property name="position">1</property> </packing> </child> <child type="tab"> @@ -6848,7 +6553,7 @@ on the Video tab instead.</property> <property name="label" translatable="yes">Advanced</property> </object> <packing> - <property name="position">2</property> + <property name="position">1</property> <property name="tab_fill">False</property> </packing> </child> @@ -7470,7 +7175,7 @@ Setting this to 0 means there is no maximum height.</property> <object class="GtkImage" id="live_preview_play_image"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="stock">gtk-media-play</property> + <property name="icon_name">gtk-media-play</property> </object> </child> </object> @@ -9434,13 +9139,13 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-add</property> + <property name="icon_name">gtk-add</property> </object> <object class="GtkImage" id="subtitle_add_image"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="stock">gtk-add</property> + <property name="icon_name">gtk-add</property> </object> <object class="GtkDialog" id="tweak_dialog"> <property name="can_focus">False</property> @@ -9553,6 +9258,915 @@ YadifMode:YadifParity:McdintMode:McdeintQp</property> <action-widget response="-5">tweak_ok</action-widget> </action-widgets> </object> + <object class="GtkDialog" id="subtitle_dialog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="modal">True</property> + <property name="window_position">center-on-parent</property> + <property name="type_hint">dialog</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-subtitle-vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-subtitle-action_area"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="subtitle_cancel"> + <property name="label" translatable="yes">Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="subtitle_ok"> + <property name="label" translatable="yes">Ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="subtitle_srt_switch_box"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_bottom">24</property> + <child> + <object class="GtkRadioButton" id="SubtitleSrtEnable"> + <property name="label" translatable="yes">Import SRT</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable settings to import an SRT subtitle file</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_srt_radio_toggled_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="SubtitleSrtDisable"> + <property name="label" translatable="yes">Embedded Subtitle List</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable settings to select embedded subtitles</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <property name="group">SubtitleSrtEnable</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="subtitle_settings_box"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkGrid" id="subtitle_srt_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="column_spacing">4</property> + <child> + <object class="GtkLabel" id="srt_lang_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Language</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="srt_code_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Character Code</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="srt_file_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">File:</property> + <property name="halign">end</property> + </object> + <packing> + <property name="top_attach">2</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="srt_offset_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Offset (ms)</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">4</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="SrtLanguage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the language of this subtitle. + This value will be used by players in subtitle menus.</property> + <signal name="changed" handler="srt_lang_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="SrtCodeset"> + <property name="width_request">150</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the character code used by the SRT file you are importing. + + SRTs come in all flavours of character sets. + We translate the character set to UTF-8. + The source's character code is needed in order to perform this translation.</property> + <property name="has_entry">True</property> + <signal name="changed" handler="srt_changed_cb" swapped="no"/> + <child internal-child="entry"> + <object class="GtkEntry" id="combobox-entry1"> + <property name="can_focus">True</property> + </object> + </child> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkFileChooserButton" id="SrtFile"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="tooltip_text" translatable="yes">Select the SRT file to import.</property> + <property name="local_only">False</property> + <property name="hexpand">True</property> + <property name="title" translatable="yes">Srt File</property> + <signal name="selection-changed" handler="srt_file_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">2</property> + <property name="left_attach">1</property> + <property name="width">2</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="SrtOffset"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Adjust the offset in milliseconds between video and SRT timestamps</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="adjustment">adjustment31</property> + <signal name="value-changed" handler="srt_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">4</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="subtitle_track_box"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="subtitle_track_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Track</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="SubtitleTrack"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">List of subtitle tracks available from your source.</property> + <signal name="changed" handler="subtitle_track_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="subtitle_options_box"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkCheckButton" id="SubtitleForced"> + <property name="label" translatable="yes">Forced Subtitles Only</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Use only subtitles that have been flagged +as forced in the source subtitle track + +"Forced" subtitles are usually used to show +subtitles during scenes where someone is speaking +a foreign language.</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_forced_toggled_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="SubtitleBurned"> + <property name="label" translatable="yes">Burn into video</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Render the subtitle over the video. +The subtitle will be part of the video and can not be disabled.</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_burned_toggled_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="SubtitleDefaultTrack"> + <property name="label" translatable="yes">Set Default Track</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the default output subtitle track. + +Most players will automatically display this +subtitle track whenever the video is played. + +This is usefule for creating a "forced" track +in your output.</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="subtitle_default_toggled_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">subtitle_cancel</action-widget> + <action-widget response="-5">subtitle_ok</action-widget> + </action-widgets> + </object> + <object class="GtkDialog" id="audio_dialog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="modal">True</property> + <property name="window_position">center-on-parent</property> + <property name="type_hint">dialog</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-audio-vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-audio-action_area"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="audio_cancel"> + <property name="label" translatable="yes">Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="audio_ok"> + <property name="label" translatable="yes">Ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="audio_dialog_grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="column_spacing">5</property> + <child> + <object class="GtkLabel" id="label35"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Source Track</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioTrack"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">List of audio tracks available from your source.</property> + <signal name="changed" handler="audio_track_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="audio_name_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Track Name:</property> + <property name="use_markup">True</property> + <property name="halign">center</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="AudioTrackName"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the audio track name. + +Players may use this in the audio selection list.</property> + <property name="max_length">40</property> + <property name="hexpand">True</property> + <property name="activates_default">True</property> + <property name="truncate_multiline">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="audio_dialog_grid2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_top">24</property> + <child> + <object class="GtkLabel" id="AudioEncoderLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Encoder</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioBitrateLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Bitrate/Quality</property> + <property name="use_markup">True</property> + <property name="halign">center</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioMixdownLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Mix</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioSamplerateLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Sample Rate</property> + <property name="use_markup">True</property> + <property name="halign">center</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">3</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackGainLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Gain</property> + <property name="use_markup">True</property> + <property name="halign">center</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">4</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackDRCSliderLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="tooltip_markup"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. + +For source audio that has a wide dynamic range (very loud and very soft sequences), +DRC allows you to 'compress' the range by making loud sounds softer and soft sounds louder.</property> + <property name="label" translatable="yes">DRC</property> + <property name="use_markup">True</property> + <property name="halign">center</property> + </object> + <packing> + <property name="top_attach">0</property> + <property name="left_attach">5</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioEncoder"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the audio codec to encode this track with.</property> + <signal name="changed" handler="audio_codec_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="audio_dialog_hbox24"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkBox" id="AudioTrackQualityEnableBox"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkRadioButton" id="AudioTrackBitrateEnable"> + <property name="label" translatable="yes">Bitrate</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable bitrate setting</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="audio_quality_radio_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="AudioTrackQualityEnable"> + <property name="label" translatable="yes">Quality</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Enable quality setting</property> + <property name="xalign">0</property> + <property name="draw_indicator">True</property> + <property name="group">AudioTrackBitrateEnable</property> + <signal name="toggled" handler="audio_quality_radio_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioBitrate"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the bitrate to encode this track with.</property> + <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="AudioTrackQualityBox"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkScaleButton" id="AudioTrackQuality"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_markup"><b>Quality:</b> For output codec's that support it, adjust the quality of the output.</property> + <property name="orientation">vertical</property> + <property name="adjustment">audio_quality_adj</property> + <property name="icons">weather-storm +weather-clear +weather-storm +weather-showers-scattered +weather-showers +weather-overcast +weather-few-clouds +weather-clear</property> + <signal name="value-changed" handler="quality_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackQualityValue"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">00.0</property> + <property name="use_markup">True</property> + <property name="width_chars">4</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioMixdown"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the mixdown of the output audio track.</property> + <signal name="changed" handler="audio_mix_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="AudioSamplerate"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Set the sample rate of the output audio track.</property> + <signal name="changed" handler="audio_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">3</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="hbox34"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkScaleButton" id="AudioTrackGain"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_markup"><b>Audio Gain:</b> Adjust the amplification or attenuation of the output audio track.</property> + <property name="orientation">vertical</property> + <property name="adjustment">adjustment35</property> + <property name="icons">audio-volume-muted +audio-volume-high +audio-volume-low +audio-volume-medium</property> + <signal name="value-changed" handler="gain_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackGainValue"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">0dB</property> + <property name="use_markup">True</property> + <property name="width_chars">6</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">4</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="hbox33"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <object class="GtkScaleButton" id="AudioTrackDRCSlider"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_markup"><b>Dynamic Range Compression:</b> Adjust the dynamic range of the output audio track. + +For source audio that has a wide dynamic range (very loud and very soft sequences), +DRC allows you to 'compress' the range by making loud sounds softer and soft sounds louder.</property> + <property name="orientation">vertical</property> + <property name="adjustment">adjustment28</property> + <property name="icons">audio-input-microphone</property> + <signal name="value-changed" handler="drc_widget_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="AudioTrackDRCValue"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Off</property> + <property name="use_markup">True</property> + <property name="width_chars">4</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="top_attach">1</property> + <property name="left_attach">5</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">audio_cancel</action-widget> + <action-widget response="-5">audio_ok</action-widget> + </action-widgets> + </object> <object class="GtkDialog" id="update_dialog"> <property name="can_focus">False</property> <property name="border_width">5</property> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 393aad0e5..c857884e4 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -71,6 +71,30 @@ index_str_init(gint max_index) } } +static options_map_t d_subtitle_track_sel_opts[] = +{ + {N_("None"), "none", 0, "0"}, + {N_("First Track Matching Selected Languages"), "first", 1, "1"}, + {N_("All Tracks Matching Selected Languages"), "all", 2, "2"}, +}; +combo_opts_t subtitle_track_sel_opts = +{ + sizeof(d_subtitle_track_sel_opts)/sizeof(options_map_t), + d_subtitle_track_sel_opts +}; + +static options_map_t d_audio_track_sel_opts[] = +{ + {N_("None"), "none", 0, "0"}, + {N_("First Track Matching Selected Languages"), "first", 1, "1"}, + {N_("All Tracks Matching Selected Languages"), "all", 2, "2"}, +}; +combo_opts_t audio_track_sel_opts = +{ + sizeof(d_audio_track_sel_opts)/sizeof(options_map_t), + d_audio_track_sel_opts +}; + static options_map_t d_point_to_point_opts[] = { {N_("Chapters:"), "chapter", 0, "0"}, @@ -365,6 +389,8 @@ typedef struct combo_name_map_t combo_name_map[] = { + {"SubtitleTrackSelectionBehavior", &subtitle_track_sel_opts}, + {"AudioTrackSelectionBehavior", &audio_track_sel_opts}, {"PtoPType", &point_to_point_opts}, {"WhenComplete", &when_complete_opts}, {"PicturePAR", &par_opts}, @@ -1028,62 +1054,33 @@ ghb_find_closest_audio_samplerate(gint irate) return result; } -hb_rate_t *ghb_audio_bitrates = NULL; -int ghb_audio_bitrates_count = 0; -int ghb_abr_count = 0; - -static const hb_rate_t * -lookup_audio_bitrate(const GValue *grate) -{ - gint ii; - const hb_rate_t *result = NULL; - - if (G_VALUE_TYPE(grate) == G_TYPE_STRING) - { - // Coincidentally, the string "source" will return 0 - // which is our flag to use "same as source" - gchar *str = ghb_value_string(grate); - for (ii = 0; ii < ghb_audio_bitrates_count; ii++) - { - if (strcmp(ghb_audio_bitrates[ii].name, str) == 0) - { - g_free(str); - return &ghb_audio_bitrates[ii]; - } - } - g_free(str); - } - else if (G_VALUE_TYPE(grate) == G_TYPE_INT || - G_VALUE_TYPE(grate) == G_TYPE_INT64 || - G_VALUE_TYPE(grate) == G_TYPE_DOUBLE) - { - gint val = ghb_value_int(grate); - for (ii = 0; ii < ghb_audio_bitrates_count; ii++) - { - if (ghb_audio_bitrates[ii].rate == val) - { - return &ghb_audio_bitrates[ii]; - } - } - } - return result; -} +int ghb_custom_bitrate = 0; +gchar *ghb_custom_bitrate_str = NULL; static gint lookup_audio_bitrate_int(const GValue *grate) { - const hb_rate_t *rate = lookup_audio_bitrate(grate); - if (rate != NULL) - return rate->rate; - return 160; + return ghb_value_int(grate); } static const gchar* lookup_audio_bitrate_option(const GValue *grate) { - const hb_rate_t *rate = lookup_audio_bitrate(grate); - if (rate != NULL) - return rate->name; + int rate = ghb_value_int(grate); + + if (rate == ghb_custom_bitrate && ghb_custom_bitrate_str != NULL) + return ghb_custom_bitrate_str; + + const hb_rate_t *hbrate; + for (hbrate = hb_audio_bitrate_get_next(NULL); hbrate != NULL; + hbrate = hb_audio_bitrate_get_next(hbrate)) + { + if (rate == hbrate->rate) + { + return hbrate->name; + } + } + return "160"; } @@ -1199,7 +1196,7 @@ lookup_audio_encoder_option(const GValue *genc) const hb_encoder_t *enc = lookup_audio_encoder(genc); if (enc != NULL) return enc->name; - return NULL; + return "None"; } static const gchar* @@ -1217,7 +1214,7 @@ lookup_audio_encoder_string(const GValue *genc) const hb_encoder_t *enc = lookup_audio_encoder(genc); if (enc != NULL) return enc->short_name; - return NULL; + return "none"; } static const gchar* @@ -1229,8 +1226,13 @@ lookup_video_encoder_string(const GValue *genc) return NULL; } -static int -lookup_audio_lang(const GValue *glang) +const iso639_lang_t* ghb_iso639_lookup_by_int(int idx) +{ + return &ghb_language_table[idx]; +} + +int +ghb_lookup_audio_lang(const GValue *glang) { gint ii; gchar *str; @@ -1238,7 +1240,32 @@ lookup_audio_lang(const GValue *glang) str = ghb_value_string(glang); for (ii = 0; ii < LANG_TABLE_SIZE; ii++) { - if (strcmp(ghb_language_table[ii].iso639_2, str) == 0) + if (ghb_language_table[ii].iso639_2 && + strcmp(ghb_language_table[ii].iso639_2, str) == 0) + { + g_free(str); + return ii; + } + if (ghb_language_table[ii].iso639_2b && + strcmp(ghb_language_table[ii].iso639_2b, str) == 0) + { + g_free(str); + return ii; + } + if (ghb_language_table[ii].iso639_1 && + strcmp(ghb_language_table[ii].iso639_1, str) == 0) + { + g_free(str); + return ii; + } + if (ghb_language_table[ii].native_name && + strcmp(ghb_language_table[ii].native_name, str) == 0) + { + g_free(str); + return ii; + } + if (ghb_language_table[ii].eng_name && + strcmp(ghb_language_table[ii].eng_name, str) == 0) { g_free(str); return ii; @@ -1251,7 +1278,7 @@ lookup_audio_lang(const GValue *glang) static int lookup_audio_lang_int(const GValue *glang) { - gint ii = lookup_audio_lang(glang); + gint ii = ghb_lookup_audio_lang(glang); if (ii >= 0) return ii; return 0; @@ -1260,7 +1287,7 @@ lookup_audio_lang_int(const GValue *glang) static const gchar* lookup_audio_lang_option(const GValue *glang) { - gint ii = lookup_audio_lang(glang); + gint ii = ghb_lookup_audio_lang(glang); if (ii >= 0) { if (ghb_language_table[ii].native_name[0] != 0) @@ -1268,7 +1295,7 @@ lookup_audio_lang_option(const GValue *glang) else return ghb_language_table[ii].eng_name; } - return "Same as source"; + return "Any"; } GValue* @@ -1277,7 +1304,7 @@ ghb_lookup_audio_encoder_value(gint ienc) const hb_encoder_t *enc = lookup_audio_encoder_by_int(ienc); if (enc != NULL) return ghb_string_value_new(enc->short_name); - return ghb_string_value_new("copy"); + return ghb_string_value_new("none"); } static GValue* @@ -1413,21 +1440,20 @@ const gchar* ghb_subtitle_track_lang(GValue *settings, gint track) { gint titleindex; + hb_title_t * title; titleindex = ghb_settings_combo_int(settings, "title"); if (titleindex < 0) goto fail; + title = ghb_get_title_info(titleindex); + if (title == NULL) // Bad titleindex + goto fail; if (track == -1) - return ghb_get_user_audio_lang(settings, titleindex, 0); + return ghb_get_user_audio_lang(settings, title, 0); if (track < 0) goto fail; - hb_title_t * title; hb_subtitle_t * sub; - - title = ghb_get_title_info( titleindex ); - if (title == NULL) // Bad titleindex - goto fail; sub = hb_list_item( title->list_subtitle, track); if (sub != NULL) return sub->iso639_2; @@ -1471,39 +1497,27 @@ get_hb_audio(hb_handle_t *h, gint titleindex, gint track) } static gint -search_rates(hb_rate_t *rates, gint rate, gint count) +search_audio_bitrates(gint rate) { - gint ii; - for (ii = 0; ii < count; ii++) + const hb_rate_t *hbrate; + for (hbrate = hb_audio_bitrate_get_next(NULL); hbrate != NULL; + hbrate = hb_audio_bitrate_get_next(hbrate)) { - if (rates[ii].rate == rate) - return ii; + if (hbrate->rate == rate) + return 1; } - return -1; + return 0; } static gboolean find_combo_item_by_int(GtkTreeModel *store, gint value, GtkTreeIter *iter); -static GtkListStore* -get_combo_box_store(GtkBuilder *builder, const gchar *name) -{ - GtkComboBox *combo; - GtkListStore *store; - - g_debug("get_combo_box_store() %s\n", name); - // First modify the combobox model to allow greying out of options - combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); - store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); - return store; -} - static void -grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey) +grey_combo_box_item(GtkComboBox *combo, gint value, gboolean grey) { GtkListStore *store; GtkTreeIter iter; - store = get_combo_box_store(builder, name); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); if (find_combo_item_by_int(GTK_TREE_MODEL(store), value, &iter)) { gtk_list_store_set(store, &iter, @@ -1513,6 +1527,27 @@ grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean } static void +grey_builder_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean grey) +{ + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + grey_combo_box_item(combo, value, grey); +} + +void +ghb_mix_opts_filter(GtkComboBox *combo, gint acodec) +{ + g_debug("ghb_mix_opts_filter()\n"); + + const hb_mixdown_t *mix; + for (mix = hb_mixdown_get_next(NULL); mix != NULL; + mix = hb_mixdown_get_next(mix)) + { + grey_combo_box_item(combo, mix->amixdown, + !hb_mixdown_has_codec_support(mix->amixdown, acodec)); + } +} + +static void grey_mix_opts(signal_user_data_t *ud, gint acodec, gint64 layout) { g_debug("grey_mix_opts()\n"); @@ -1521,7 +1556,7 @@ grey_mix_opts(signal_user_data_t *ud, gint acodec, gint64 layout) for (mix = hb_mixdown_get_next(NULL); mix != NULL; mix = hb_mixdown_get_next(mix)) { - grey_combo_box_item(ud->builder, "AudioMixdown", mix->amixdown, + grey_builder_combo_box_item(ud->builder, "AudioMixdown", mix->amixdown, !hb_mixdown_is_supported(mix->amixdown, acodec, layout)); } } @@ -1548,7 +1583,7 @@ ghb_grey_combo_options(signal_user_data_t *ud) mux = ghb_lookup_combo_int("FileFormat", gval); ghb_value_free(gval); - grey_combo_box_item(ud->builder, "x264_analyse", 4, TRUE); + grey_builder_combo_box_item(ud->builder, "x264_analyse", 4, TRUE); const hb_encoder_t *enc; for (enc = hb_audio_encoder_get_next(NULL); enc != NULL; @@ -1556,16 +1591,16 @@ ghb_grey_combo_options(signal_user_data_t *ud) { if (!(mux & enc->muxers)) { - grey_combo_box_item(ud->builder, "AudioEncoder", + grey_builder_combo_box_item(ud->builder, "AudioEncoder", enc->codec, TRUE); - grey_combo_box_item(ud->builder, "AudioEncoderFallback", + grey_builder_combo_box_item(ud->builder, "AudioEncoderFallback", enc->codec, TRUE); } else { - grey_combo_box_item(ud->builder, "AudioEncoder", + grey_builder_combo_box_item(ud->builder, "AudioEncoder", enc->codec, FALSE); - grey_combo_box_item(ud->builder, "AudioEncoderFallback", + grey_builder_combo_box_item(ud->builder, "AudioEncoderFallback", enc->codec, FALSE); } } @@ -1574,35 +1609,35 @@ ghb_grey_combo_options(signal_user_data_t *ud) { if (!(mux & enc->muxers)) { - grey_combo_box_item(ud->builder, "VideoEncoder", + grey_builder_combo_box_item(ud->builder, "VideoEncoder", enc->codec, TRUE); } else { - grey_combo_box_item(ud->builder, "VideoEncoder", + grey_builder_combo_box_item(ud->builder, "VideoEncoder", enc->codec, FALSE); } } if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_MP3) { - grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_MP3_PASS, TRUE); + grey_builder_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_MP3_PASS, TRUE); } if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_FFAAC) { - grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AAC_PASS, TRUE); + grey_builder_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AAC_PASS, TRUE); } if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_AC3) { - grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AC3_PASS, TRUE); + grey_builder_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AC3_PASS, TRUE); } if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_DCA) { - grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE); + grey_builder_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE); } if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_DCA_HD) { - grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, TRUE); + grey_builder_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, TRUE); } widget = GHB_WIDGET (ud->builder, "AudioEncoder"); @@ -1611,7 +1646,7 @@ ghb_grey_combo_options(signal_user_data_t *ud) ghb_value_free(gval); gint64 layout = aconfig != NULL ? aconfig->in.channel_layout : ~0; - fallback = ghb_select_fallback(ud->settings, mux, acodec); + fallback = ghb_select_fallback(ud->settings, acodec); gint copy_mask = ghb_get_copy_mask(ud->settings); acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask); grey_mix_opts(ud, acodec, layout); @@ -1630,16 +1665,14 @@ ghb_get_best_mix(hb_audio_config_t *aconfig, gint acodec, gint mix) } // Set up the model for the combo box -static void -init_combo_box(GtkBuilder *builder, const gchar *name) +void +ghb_init_combo_box(GtkComboBox *combo) { - GtkComboBox *combo; GtkListStore *store; GtkCellRenderer *cell; - g_debug("init_combo_box() %s\n", name); + g_debug("ghb_init_combo_box()\n"); // First modify the combobox model to allow greying out of options - combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); if (combo == NULL) return; // Store contains: @@ -1666,15 +1699,27 @@ init_combo_box(GtkBuilder *builder, const gchar *name) } } +// Set up the model for the combo box static void -audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name) +init_combo_box(GtkBuilder *builder, const gchar *name) +{ + GtkComboBox *combo; + + g_debug("init_combo_box() %s\n", name); + // First modify the combobox model to allow greying out of options + combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_init_combo_box(combo); +} + +void +ghb_audio_samplerate_opts_set(GtkComboBox *combo) { GtkTreeIter iter; GtkListStore *store; gchar *str; g_debug("audio_samplerate_opts_set ()\n"); - store = get_combo_box_store(builder, name); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); // Add an item for "Same As Source" gtk_list_store_append(store, &iter); @@ -1706,13 +1751,22 @@ audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name) } static void +audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name) +{ + g_debug("audio_samplerate_opts_set ()\n"); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_audio_samplerate_opts_set(combo); +} + +static void video_framerate_opts_set(GtkBuilder *builder, const gchar *name) { GtkTreeIter iter; GtkListStore *store; g_debug("video_framerate_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); // Add an item for "Same As Source" gtk_list_store_append(store, &iter); @@ -1765,7 +1819,8 @@ video_encoder_opts_set( gchar *str; g_debug("video_encoder_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); const hb_encoder_t *enc; @@ -1785,10 +1840,9 @@ video_encoder_opts_set( } } -static void -audio_encoder_opts_set_with_mask( - GtkBuilder *builder, - const gchar *name, +void +ghb_audio_encoder_opts_set_with_mask( + GtkComboBox *combo, int mask, int neg_mask) { @@ -1796,8 +1850,8 @@ audio_encoder_opts_set_with_mask( GtkListStore *store; gchar *str; - g_debug("audio_encoder_opts_set ()\n"); - store = get_combo_box_store(builder, name); + g_debug("ghb_audio_encoder_opts_set_with_mask()\n"); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); const hb_encoder_t *enc; @@ -1821,11 +1875,54 @@ audio_encoder_opts_set_with_mask( } static void +audio_encoder_opts_set_with_mask( + GtkBuilder *builder, + const gchar *name, + int mask, + int neg_mask) +{ + g_debug("audio_encoder_opts_set_with_mask()\n"); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_audio_encoder_opts_set_with_mask(combo, mask, neg_mask); +} + +void +ghb_audio_encoder_opts_set(GtkComboBox *combo) +{ + ghb_audio_encoder_opts_set_with_mask(combo, ~0, 0); +} + +static void audio_encoder_opts_set( GtkBuilder *builder, const gchar *name) { - audio_encoder_opts_set_with_mask(builder, name, ~0, 0); + GtkTreeIter iter; + GtkListStore *store; + gchar *str; + + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); + gtk_list_store_clear(store); + + const hb_encoder_t *enc; + for (enc = hb_audio_encoder_get_next(NULL); enc != NULL; + enc = hb_audio_encoder_get_next(enc)) + { + if (enc->codec != HB_ACODEC_AUTO_PASS) + { + gtk_list_store_append(store, &iter); + str = g_strdup_printf("<small>%s</small>", enc->name); + gtk_list_store_set(store, &iter, + 0, str, + 1, TRUE, + 2, enc->short_name, + 3, (gdouble)enc->codec, + 4, enc->short_name, + -1); + g_free(str); + } + } } static void @@ -1834,15 +1931,15 @@ acodec_fallback_opts_set(GtkBuilder *builder, const gchar *name) audio_encoder_opts_set_with_mask(builder, name, ~0, HB_ACODEC_PASS_FLAG); } -static void -mix_opts_set(GtkBuilder *builder, const gchar *name) +void +ghb_mix_opts_set(GtkComboBox *combo) { GtkTreeIter iter; GtkListStore *store; gchar *str; g_debug("mix_opts_set ()\n"); - store = get_combo_box_store(builder, name); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); const hb_mixdown_t *mix; @@ -1863,6 +1960,14 @@ mix_opts_set(GtkBuilder *builder, const gchar *name) } static void +mix_opts_set(GtkBuilder *builder, const gchar *name) +{ + g_debug("mix_opts_set ()\n"); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_mix_opts_set(combo); +} + +static void container_opts_set( GtkBuilder *builder, const gchar *name) @@ -1872,7 +1977,8 @@ container_opts_set( gchar *str; g_debug("hb_container_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); const hb_container_t *mux; @@ -1900,7 +2006,8 @@ srt_codeset_opts_set(GtkBuilder *builder, const gchar *name) gint ii; g_debug("srt_codeset_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < SRT_TABLE_SIZE; ii++) { @@ -1923,7 +2030,8 @@ language_opts_set(GtkBuilder *builder, const gchar *name) gint ii; g_debug("language_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < LANG_TABLE_SIZE; ii++) { @@ -1958,7 +2066,8 @@ title_opts_set(GtkBuilder *builder, const gchar *name) gint count = 0; g_debug("title_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); if (h_scan != NULL) { @@ -2074,7 +2183,8 @@ x264_tune_opts_set(GtkBuilder *builder, const gchar *name) while (tunes && tunes[count]) count++; g_debug("x264_tune_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); gtk_list_store_append(store, &iter); @@ -2114,7 +2224,8 @@ h264_profile_opts_set(GtkBuilder *builder, const gchar *name) while (profiles && profiles[count]) count++; g_debug("h264_profile_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < count; ii++) @@ -2142,7 +2253,8 @@ h264_level_opts_set(GtkBuilder *builder, const gchar *name) while (levels && levels[count]) count++; g_debug("h264_level_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < count; ii++) @@ -2197,7 +2309,8 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) gchar *str; g_debug("audio_track_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); title = ghb_get_title_info(titleindex); if (title != NULL) @@ -2264,7 +2377,6 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) audio_track_opts.map[ii].ivalue = ii; audio_track_opts.map[ii].svalue = index_str[ii]; } - GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); gtk_combo_box_set_active (combo, 0); } @@ -2297,39 +2409,34 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) static char ** options = NULL; g_debug("subtitle_track_opts_set ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); title = ghb_get_title_info(titleindex); if (title != NULL) { count = hb_list_count( title->list_subtitle ); } - if (count > 100) count = 100; if (subtitle_opts.map) g_free(subtitle_opts.map); + + subtitle_opts.count = count+1; + subtitle_opts.map = g_malloc((subtitle_opts.count)*sizeof(options_map_t)); + if (count > 0) { - subtitle_opts.count = count+1; - subtitle_opts.map = g_malloc((count+1)*sizeof(options_map_t)); - } - else - { - subtitle_opts.count = LANG_TABLE_SIZE+1; - subtitle_opts.map = g_malloc((LANG_TABLE_SIZE+1)*sizeof(options_map_t)); - } - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - 0, _("Foreign Audio Search"), - 1, TRUE, - 2, "-1", - 3, -1.0, - 4, "auto", - -1); - subtitle_opts.map[0].option = "Foreign Audio Search"; - subtitle_opts.map[0].shortOpt = "-1"; - subtitle_opts.map[0].ivalue = -1; - subtitle_opts.map[0].svalue = "auto"; - if (count > 0) - { + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + 0, _("Foreign Audio Search"), + 1, TRUE, + 2, "-1", + 3, -1.0, + 4, "auto", + -1); + subtitle_opts.map[0].option = "Foreign Audio Search"; + subtitle_opts.map[0].shortOpt = "-1"; + subtitle_opts.map[0].ivalue = -1; + subtitle_opts.map[0].svalue = "auto"; + if (options != NULL) g_strfreev(options); options = g_malloc((count+1)*sizeof(gchar*)); @@ -2357,31 +2464,19 @@ subtitle_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex) } else { - index_str_init(LANG_TABLE_SIZE-1); - for (ii = 0; ii < LANG_TABLE_SIZE; ii++) - { - const gchar *lang; - - if (ghb_language_table[ii].native_name[0] != 0) - lang = ghb_language_table[ii].native_name; - else - lang = ghb_language_table[ii].eng_name; - - subtitle_opts.map[ii+1].option = (gchar*)lang; - subtitle_opts.map[ii+1].shortOpt = index_str[ii]; - subtitle_opts.map[ii+1].ivalue = ii; - subtitle_opts.map[ii+1].svalue = ghb_language_table[ii].iso639_2; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - 0, lang, - 1, TRUE, - 2, index_str[ii], - 3, (gdouble)ii, - 4, ghb_language_table[ii].iso639_2, - -1); - } + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + 0, _("None"), + 1, TRUE, + 2, "0", + 3, 0.0, + 4, "none", + -1); + subtitle_opts.map[0].option = "None"; + subtitle_opts.map[0].shortOpt = "0"; + subtitle_opts.map[0].ivalue = 0; + subtitle_opts.map[0].svalue = "none"; } - GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); gtk_combo_box_set_active (combo, 0); } @@ -2413,14 +2508,12 @@ ghb_longest_title() } const gchar* -ghb_get_source_audio_lang(gint titleindex, gint track) +ghb_get_source_audio_lang(hb_title_t *title, gint track) { - hb_title_t * title; hb_audio_config_t * audio; const gchar *lang = "und"; g_debug("ghb_lookup_1st_audio_lang ()\n"); - title = ghb_get_title_info( titleindex ); if (title == NULL) return lang; if (hb_list_count( title->list_audio ) <= track) @@ -2434,236 +2527,26 @@ ghb_get_source_audio_lang(gint titleindex, gint track) return lang; } -static gboolean* -get_track_used(gint acodec, GHashTable *track_indices, gint count) -{ - gboolean *used; - - used = g_hash_table_lookup(track_indices, &acodec); - if (used == NULL) - { - gint *key; - - used = g_malloc0(count * sizeof(gboolean)); - key = g_malloc(sizeof(gint)); - *key = acodec; - g_hash_table_insert(track_indices, key, used); - } - return used; -} - gint -ghb_find_audio_track( - gint titleindex, - const gchar *lang, - gint acodec, - gint fallback_acodec, - GHashTable *track_indices) +ghb_find_audio_track(hb_title_t *title, const gchar *lang, int start) { - hb_title_t * title; hb_audio_config_t * audio; - gint ii; - gint count = 0; - gint track = -1; - gint max_chan; - gboolean *used = NULL; - gboolean *passthru_used; - gint try_acodec; - gint passthru_acodec; - gboolean passthru; - gint channels; - - g_debug("find_audio_track ()\n"); - title = ghb_get_title_info( titleindex ); + gint ii, count = 0; + if (title != NULL) { - count = hb_list_count( title->list_audio ); + count = hb_list_count(title->list_audio); } - if (count > 10) count = 10; - // Try to find an item that matches the preferred language and - // the passthru codec type - max_chan = 0; - passthru = (acodec & HB_ACODEC_PASS_FLAG) != 0; - if (passthru) - { - for (ii = 0; ii < count; ii++) - { - audio = (hb_audio_config_t*)hb_list_audio_config_item( - title->list_audio, ii ); - passthru_acodec = HB_ACODEC_PASS_MASK & acodec & audio->in.codec; - // Is the source track use a passthru capable codec? - if (passthru_acodec == 0) - continue; - used = get_track_used(passthru_acodec, track_indices, count); - // Has the track already been used with this codec? - if (used[ii]) - continue; - channels = av_get_channel_layout_nb_channels( - audio->in.channel_layout); - // Find a track that is not visually impaired or dirctor's - // commentary, and has the highest channel count. - if ((audio->lang.type < 2) && - ((strcmp(lang, audio->lang.iso639_2) == 0) || - (strcmp(lang, "und") == 0))) - { - if (channels > max_chan) - { - track = ii; - max_chan = channels; - } - } - } - try_acodec = fallback_acodec; - } - else - { - try_acodec = acodec; - } - if (track > -1) - { - used[track] = TRUE; - return track; - } - // Try to find an item that matches the preferred language - max_chan = 0; - used = get_track_used(try_acodec, track_indices, count); - for (ii = 0; ii < count; ii++) - { - // Has the track already been used with this codec? - if (used[ii]) - continue; - audio = (hb_audio_config_t*)hb_list_audio_config_item( - title->list_audio, ii ); - passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec; - if (passthru_acodec && passthru) - { - passthru_used = get_track_used(passthru_acodec, track_indices, count); - // Has the track already been used with this codec for passthru? - if (passthru_used[ii]) - continue; - } - channels = av_get_channel_layout_nb_channels( - audio->in.channel_layout); - // Find a track that is not visually impaired or dirctor's commentary - if ((audio->lang.type < 2) && - ((strcmp(lang, audio->lang.iso639_2) == 0) || - (strcmp(lang, "und") == 0))) - { - if (channels > max_chan) - { - track = ii; - max_chan = channels; - } - } - } - if (track > -1) + for (ii = start; ii < count; ii++) { - used[track] = TRUE; - return track; - } - // Try to fine an item that does not match the preferred language and - // matches the passthru codec type - max_chan = 0; - if (passthru) - { - for (ii = 0; ii < count; ii++) + audio = hb_list_audio_config_item(title->list_audio, ii); + if (!strcmp(lang, audio->lang.iso639_2) || !strcmp(lang, "und")) { - audio = (hb_audio_config_t*)hb_list_audio_config_item( - title->list_audio, ii ); - passthru_acodec = HB_ACODEC_PASS_MASK & acodec & audio->in.codec; - // Is the source track use a passthru capable codec? - if (passthru_acodec == 0) - continue; - used = get_track_used(passthru_acodec, track_indices, count); - // Has the track already been used with this codec? - if (used[ii]) - continue; - - channels = av_get_channel_layout_nb_channels( - audio->in.channel_layout); - // Find a track that is not visually impaired or dirctor's - // commentary, and has the highest channel count. - if (audio->lang.type < 2) - { - if (channels > max_chan) - { - track = ii; - max_chan = channels; - } - } - } - try_acodec = fallback_acodec; - } - else - { - try_acodec = acodec; - } - if (track > -1) - { - used[track] = TRUE; - return track; - } - // Try to fine an item that does not match the preferred language - max_chan = 0; - used = get_track_used(try_acodec, track_indices, count); - for (ii = 0; ii < count; ii++) - { - // Has the track already been used with this codec? - if (used[ii]) - continue; - audio = (hb_audio_config_t*)hb_list_audio_config_item( - title->list_audio, ii ); - passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec; - channels = av_get_channel_layout_nb_channels( - audio->in.channel_layout); - if (passthru_acodec && passthru) - { - passthru_used = get_track_used(passthru_acodec, track_indices, count); - // Has the track already been used with this codec for passthru? - if (passthru_used[ii]) - continue; - } - // Find a track that is not visually impaired or dirctor's commentary - if (audio->lang.type < 2) - { - if (channels > max_chan) - { - track = ii; - max_chan = channels; - } - } - } - if (track > -1) - { - used[track] = TRUE; - return track; - } - // Last ditch, anything goes - for (ii = 0; ii < count; ii++) - { - audio = (hb_audio_config_t*)hb_list_audio_config_item( - title->list_audio, ii ); - passthru_acodec = HB_ACODEC_PASS_MASK & audio->in.codec; - if (passthru_acodec && passthru) - { - passthru_used = get_track_used(passthru_acodec, track_indices, count); - // Has the track already been used with this codec for passthru? - if (passthru_used[ii]) - continue; - } - // Has the track already been used with this codec? - if (!used[ii]) - { - track = ii; - break; + return ii; } } - if (track > -1) - { - used[track] = TRUE; - } - return track; + return -1; } gint @@ -2682,89 +2565,24 @@ ghb_find_pref_subtitle_track(const gchar *lang) } gint -ghb_find_cc_track(gint titleindex) +ghb_find_subtitle_track(hb_title_t * title, const gchar * lang, int start) { - hb_title_t * title; hb_subtitle_t * subtitle; gint count, ii; - - g_debug("ghb_find_cc_track ()\n"); - title = ghb_get_title_info( titleindex ); - if (title != NULL) - { - count = hb_list_count( title->list_subtitle ); - // Try to find an item that matches the preferred language - for (ii = 0; ii < count; ii++) - { - subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii ); - if (subtitle->source == CC608SUB || subtitle->source == CC708SUB) - return ii; - } - } - return -2; -} - -gint -ghb_find_subtitle_track( - gint titleindex, - const gchar * lang, - gboolean burn, - gboolean force, - gint source, - GHashTable * track_indices) -{ - hb_title_t * title; - hb_subtitle_t * subtitle; - gint count, ii; - gboolean *used; - - g_debug("find_subtitle_track ()\n"); - if (strcmp(lang, "auto") == 0) - return -1; - title = ghb_get_title_info( titleindex ); - if (title == NULL) - return -2; - - count = hb_list_count( title->list_subtitle ); - used = g_hash_table_lookup(track_indices, lang); - if (used == NULL) - { - used = g_malloc0(count * sizeof(gboolean)); - g_hash_table_insert(track_indices, g_strdup(lang), used); - } - // Try to find an item that matches the preferred language and source - for (ii = 0; ii < count; ii++) - { - if (used[ii]) - continue; + count = hb_list_count(title->list_subtitle); - subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii ); - if (source == subtitle->source && - ((strcmp(lang, subtitle->iso639_2) == 0) || - (strcmp(lang, "und") == 0))) - { - used[ii] = TRUE; - return ii; - } - } // Try to find an item that matches the preferred language - for (ii = 0; ii < count; ii++) + for (ii = start; ii < count; ii++) { - if (used[ii]) - continue; - subtitle = (hb_subtitle_t*)hb_list_item( title->list_subtitle, ii ); - if (((!force || (force && ghb_canForceSub(subtitle->source))) && - (!burn || (burn && ghb_canBurnSub(subtitle->source)))) && - ((strcmp(lang, subtitle->iso639_2) == 0) || - (strcmp(lang, "und") == 0))) + if (strcmp(lang, subtitle->iso639_2) == 0 || + strcmp(lang, "und") == 0) { - used[ii] = TRUE; return ii; } } - return -2; + return -1; } static void @@ -2776,13 +2594,14 @@ generic_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts) g_debug("generic_opts_set ()\n"); if (name == NULL || opts == NULL) return; - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < opts->count; ii++) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - 0, _(opts->map[ii].option), + 0, gettext(opts->map[ii].option), 1, TRUE, 2, opts->map[ii].shortOpt, 3, opts->map[ii].ivalue, @@ -2801,12 +2620,14 @@ small_opts_set(GtkBuilder *builder, const gchar *name, combo_opts_t *opts) g_debug("small_opts_set ()\n"); if (name == NULL || opts == NULL) return; - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); for (ii = 0; ii < opts->count; ii++) { gtk_list_store_append(store, &iter); - str = g_strdup_printf("<small>%s</small>", _(opts->map[ii].option)); + str = g_strdup_printf("<small>%s</small>", + gettext(opts->map[ii].option)); gtk_list_store_set(store, &iter, 0, str, 1, TRUE, @@ -2848,16 +2669,12 @@ ghb_lookup_combo_int(const gchar *name, const GValue *gval) return lookup_mixdown_int(gval); else if (strcmp(name, "SrtLanguage") == 0) return lookup_audio_lang_int(gval); - else if (strcmp(name, "PreferredLanguage") == 0) - return lookup_audio_lang_int(gval); else if (strcmp(name, "VideoEncoder") == 0) return lookup_video_encoder_int(gval); else if (strcmp(name, "AudioEncoder") == 0) return lookup_audio_encoder_int(gval); else if (strcmp(name, "AudioEncoderFallback") == 0) return lookup_audio_encoder_int(gval); - else if (strcmp(name, "AudioEncoderActual") == 0) - return lookup_audio_encoder_int(gval); else if (strcmp(name, "FileFormat") == 0) return lookup_container_int(gval); else @@ -2883,16 +2700,12 @@ ghb_lookup_combo_double(const gchar *name, const GValue *gval) return lookup_mixdown_int(gval); else if (strcmp(name, "SrtLanguage") == 0) return lookup_audio_lang_int(gval); - else if (strcmp(name, "PreferredLanguage") == 0) - return lookup_audio_lang_int(gval); else if (strcmp(name, "VideoEncoder") == 0) return lookup_video_encoder_int(gval); else if (strcmp(name, "AudioEncoder") == 0) return lookup_audio_encoder_int(gval); else if (strcmp(name, "AudioEncoderFallback") == 0) return lookup_audio_encoder_int(gval); - else if (strcmp(name, "AudioEncoderActual") == 0) - return lookup_audio_encoder_int(gval); else if (strcmp(name, "FileFormat") == 0) return lookup_container_int(gval); else @@ -2918,16 +2731,12 @@ ghb_lookup_combo_option(const gchar *name, const GValue *gval) return lookup_mixdown_option(gval); else if (strcmp(name, "SrtLanguage") == 0) return lookup_audio_lang_option(gval); - else if (strcmp(name, "PreferredLanguage") == 0) - return lookup_audio_lang_option(gval); else if (strcmp(name, "VideoEncoder") == 0) return lookup_video_encoder_option(gval); else if (strcmp(name, "AudioEncoder") == 0) return lookup_audio_encoder_option(gval); else if (strcmp(name, "AudioEncoderFallback") == 0) return lookup_audio_encoder_option(gval); - else if (strcmp(name, "AudioEncoderActual") == 0) - return lookup_audio_encoder_option(gval); else if (strcmp(name, "FileFormat") == 0) return lookup_container_option(gval); else @@ -2953,16 +2762,12 @@ ghb_lookup_combo_string(const gchar *name, const GValue *gval) return lookup_mixdown_string(gval); else if (strcmp(name, "SrtLanguage") == 0) return lookup_audio_lang_option(gval); - else if (strcmp(name, "PreferredLanguage") == 0) - return lookup_audio_lang_option(gval); else if (strcmp(name, "VideoEncoder") == 0) return lookup_video_encoder_string(gval); else if (strcmp(name, "AudioEncoder") == 0) return lookup_audio_encoder_string(gval); else if (strcmp(name, "AudioEncoderFallback") == 0) return lookup_audio_encoder_string(gval); - else if (strcmp(name, "AudioEncoderActual") == 0) - return lookup_audio_encoder_string(gval); else if (strcmp(name, "FileFormat") == 0) return lookup_container_string(gval); else @@ -2973,6 +2778,77 @@ ghb_lookup_combo_string(const gchar *name, const GValue *gval) return NULL; } +#if 0 +static gboolean acodec_list_box_filter(GtkListBoxRow *row, gpointer data) +{ + GValue *settings = (GValue*)data; + + int mux = ghb_settings_combo_int(settings, "FileFormat"); + + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + int codec = (intptr_t)g_object_get_data(G_OBJECT(label), "codec"); + + const hb_encoder_t *enc; + for (enc = hb_audio_encoder_get_next(NULL); enc != NULL; + enc = hb_audio_encoder_get_next(enc)) + { + if (enc->codec == codec && (mux & enc->muxers)) + { + return TRUE; + } + } + return FALSE; +} + +void ghb_update_acodec_list_box(GtkListBox *list_box) +{ + gtk_list_box_invalidate_filter(list_box); +} + +void ghb_init_acodec_list_box(GtkListBox *list_box, GValue *settings) +{ + int mux = ghb_settings_combo_int(settings, "FileFormat"); + + const hb_encoder_t *enc; + for (enc = hb_audio_encoder_get_next(NULL); enc != NULL; + enc = hb_audio_encoder_get_next(enc)) + { + if (mux & enc->muxers) + { + GtkWidget *label = gtk_label_new(enc->name); + g_object_set_data(G_OBJECT(label), "codec", (gpointer)(intptr_t)enc->codec); + gtk_widget_show(label); + gtk_list_box_insert(list_box, label, -1); + } + } + gtk_list_box_set_filter_func(list_box, acodec_list_box_filter, + settings, NULL); +} +#endif + +void ghb_init_lang_list_box(GtkListBox *list_box) +{ + int ii; + + for (ii = 0; ii < LANG_TABLE_SIZE; ii++) + { + const char *lang; + if (ghb_language_table[ii].native_name != NULL && + ghb_language_table[ii].native_name[0] != 0) + { + lang = ghb_language_table[ii].native_name; + } + else + { + lang = ghb_language_table[ii].eng_name; + } + GtkWidget *label = gtk_label_new(lang); + g_object_set_data(G_OBJECT(label), "lang_idx", (gpointer)(intptr_t)ii); + gtk_widget_show(label); + gtk_list_box_insert(list_box, label, -1); + } +} + void ghb_update_ui_combo_box( signal_user_data_t *ud, @@ -3014,12 +2890,13 @@ ghb_update_ui_combo_box( audio_encoder_opts_set(ud->builder, "AudioEncoder"); acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback"); language_opts_set(ud->builder, "SrtLanguage"); - language_opts_set(ud->builder, "PreferredLanguage"); srt_codeset_opts_set(ud->builder, "SrtCodeset"); title_opts_set(ud->builder, "title"); audio_track_opts_set(ud->builder, "AudioTrack", user_data); subtitle_track_opts_set(ud->builder, "SubtitleTrack", user_data); generic_opts_set(ud->builder, "VideoQualityGranularity", &vqual_granularity_opts); + generic_opts_set(ud->builder, "SubtitleTrackSelectionBehavior", &subtitle_track_sel_opts); + generic_opts_set(ud->builder, "AudioTrackSelectionBehavior", &audio_track_sel_opts); generic_opts_set(ud->builder, "PtoPType", &point_to_point_opts); generic_opts_set(ud->builder, "WhenComplete", &when_complete_opts); generic_opts_set(ud->builder, "PicturePAR", &par_opts); @@ -3062,8 +2939,6 @@ ghb_update_ui_combo_box( acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback"); else if (strcmp(name, "SrtLanguage") == 0) language_opts_set(ud->builder, "SrtLanguage"); - else if (strcmp(name, "PreferredLanguage") == 0) - language_opts_set(ud->builder, "PreferredLanguage"); else if (strcmp(name, "SrtCodeset") == 0) srt_codeset_opts_set(ud->builder, "SrtCodeset"); else if (strcmp(name, "title") == 0) @@ -3099,7 +2974,6 @@ init_ui_combo_boxes(GtkBuilder *builder) init_combo_box(builder, "VideoFramerate"); init_combo_box(builder, "AudioMixdown"); init_combo_box(builder, "SrtLanguage"); - init_combo_box(builder, "PreferredLanguage"); init_combo_box(builder, "SrtCodeset"); init_combo_box(builder, "title"); init_combo_box(builder, "AudioTrack"); @@ -3354,38 +3228,68 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate) if (rate >= 0 && rate < 8) return; - if (ghb_audio_bitrates[ghb_abr_count].name) + if (ghb_custom_bitrate_str != NULL) { - g_free((char*)ghb_audio_bitrates[ghb_abr_count].name); + g_free(ghb_custom_bitrate_str); } - ghb_audio_bitrates[ghb_abr_count].rate = rate; + ghb_custom_bitrate = rate; if (rate < 0) { - ghb_audio_bitrates[ghb_abr_count].name = g_strdup_printf("N/A"); + ghb_custom_bitrate_str = g_strdup_printf("N/A"); } else { - ghb_audio_bitrates[ghb_abr_count].name = g_strdup_printf("%d", rate); + ghb_custom_bitrate_str = g_strdup_printf("%d", rate); } - ghb_audio_bitrates_count = ghb_abr_count + 1; - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter)) { - str = g_strdup_printf ("<small>%s</small>", - ghb_audio_bitrates[ghb_abr_count].name); + str = g_strdup_printf ("<small>%s</small>", ghb_custom_bitrate_str); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, str, 1, TRUE, - 2, ghb_audio_bitrates[ghb_abr_count].name, + 2, ghb_custom_bitrate_str, 3, (gdouble)rate, - 4, ghb_audio_bitrates[ghb_abr_count].name, + 4, ghb_custom_bitrate_str, -1); g_free(str); } } +void +ghb_audio_bitrate_opts_filter( + GtkComboBox *combo, + gint first_rate, + gint last_rate) +{ + GtkTreeIter iter; + GtkListStore *store; + gdouble ivalue; + gboolean done = FALSE; + + g_debug("audio_bitrate_opts_filter ()\n"); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter)) + { + do + { + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1); + if ((int)ivalue < first_rate || (int)ivalue > last_rate) + { + gtk_list_store_set(store, &iter, 1, FALSE, -1); + } + else + { + gtk_list_store_set(store, &iter, 1, TRUE, -1); + } + done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter); + } while (!done); + } +} + static void audio_bitrate_opts_update( GtkBuilder *builder, @@ -3398,91 +3302,85 @@ audio_bitrate_opts_update( GtkListStore *store; gdouble ivalue; gboolean done = FALSE; - gint ii = 0; - guint last = (guint)last_rate; - guint first = (guint)first_rate; - ghb_audio_bitrates_count = ghb_abr_count; - g_debug("audio_bitrate_opts_clean ()\n"); - store = get_combo_box_store(builder, name); + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_audio_bitrate_opts_filter(combo, first_rate, last_rate); + + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter)) { do { gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 3, &ivalue, -1); - if (ivalue != first_rate && ivalue != last_rate && - !(ivalue == extra_rate && extra_rate >= first_rate) && - search_rates( - ghb_audio_bitrates, ivalue, ghb_audio_bitrates_count) < 0) + if (!search_audio_bitrates(ivalue) && (ivalue != extra_rate)) { done = !gtk_list_store_remove(store, &iter); } - else if ((int)ivalue < first || (int)ivalue > last) - { - ii++; - gtk_list_store_set(store, &iter, 1, FALSE, -1); - done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter); - } else { - ii++; - gtk_list_store_set(store, &iter, 1, TRUE, -1); - done = !gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter); + done = !gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); } } while (!done); } - if (extra_rate >= first_rate) + if (extra_rate > 0 && !search_audio_bitrates(extra_rate)) + { audio_bitrate_opts_add(builder, name, extra_rate); + } + else + { + g_free(ghb_custom_bitrate_str); + ghb_custom_bitrate_str = NULL; + ghb_custom_bitrate = 0; + } } -static void -audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name) +void +ghb_audio_bitrate_opts_set(GtkComboBox *combo, gboolean extra) { GtkTreeIter iter; GtkListStore *store; - gint count = 0; gchar *str; - int ii; - const hb_rate_t *rate; - - if (ghb_audio_bitrates == NULL) - { - // Count rates - for (rate = hb_audio_bitrate_get_next(NULL); rate != NULL; - rate = hb_audio_bitrate_get_next(rate)) - { - count++; - } - - ghb_audio_bitrates_count = ghb_abr_count = count; - ghb_audio_bitrates = calloc(count+1, sizeof(hb_rate_t)); - - for (ii = 0, rate = hb_audio_bitrate_get_next(NULL); rate != NULL; - ii++, rate = hb_audio_bitrate_get_next(rate)) - { - ghb_audio_bitrates[ii] = *rate; - } - } - g_debug("audio_bitrate_opts_set ()\n"); - store = get_combo_box_store(builder, name); + store = GTK_LIST_STORE(gtk_combo_box_get_model (combo)); gtk_list_store_clear(store); - for (ii = 0; ii < ghb_audio_bitrates_count; ii++) + + const hb_rate_t *rate; + for (rate = hb_audio_bitrate_get_next(NULL); rate != NULL; + rate = hb_audio_bitrate_get_next(rate)) { gtk_list_store_append(store, &iter); - str = g_strdup_printf ("<small>%s</small>", - ghb_audio_bitrates[ii].name); + str = g_strdup_printf ("<small>%s</small>", rate->name); gtk_list_store_set(store, &iter, 0, str, 1, TRUE, - 2, ghb_audio_bitrates[ii].name, - 3, (gdouble)ghb_audio_bitrates[ii].rate, - 4, ghb_audio_bitrates[ii].name, + 2, rate->name, + 3, (gdouble)rate->rate, + 4, rate->name, -1); g_free(str); } + if (extra && ghb_custom_bitrate_str != NULL) + { + gtk_list_store_append(store, &iter); + str = g_strdup_printf ("<small>%s</small>", ghb_custom_bitrate_str); + gtk_list_store_set(store, &iter, + 0, str, + 1, TRUE, + 2, ghb_custom_bitrate_str, + 3, (gdouble)ghb_custom_bitrate, + 4, ghb_custom_bitrate_str, + -1); + g_free(str); + } +} + +static void +audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name) +{ + GtkComboBox *combo = GTK_COMBO_BOX(GHB_WIDGET(builder, name)); + ghb_audio_bitrate_opts_set(combo, TRUE); } void @@ -4361,7 +4259,7 @@ ghb_validate_filters(GValue *settings) if (!ghb_validate_filter_string(str, -1)) { message = g_strdup_printf( - N_("Invalid Decomb Settings:\n\n%s\n"), + _("Invalid Decomb Settings:\n\n%s\n"), str); ghb_message_dialog(GTK_MESSAGE_ERROR, message, _("Cancel"), NULL); g_free(message); @@ -5147,7 +5045,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) { sub_config.dest = PASSTHRUSUB; } - else if ( burned && ghb_canBurnSub(subt->source) ) + else if (burned && hb_subtitle_can_burn(subt->source)) { // Only allow one subtitle to be burned into the video if (one_burned) diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 7b514cf8d..9aaf94fcc 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -19,6 +19,7 @@ #include "settings.h" #include "hb.h" +#include "lang.h" enum { @@ -120,18 +121,13 @@ void ghb_set_bitrate_opts( void ghb_grey_combo_options(signal_user_data_t *ud); void ghb_update_ui_combo_box( signal_user_data_t *ud, const gchar *name, gint user_data, gboolean all); -const 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_get_source_audio_lang(hb_title_t *title, gint track); +gint ghb_find_audio_track(hb_title_t *title, const gchar *lang, int start); 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( - gint titleindex, const gchar *lang, gboolean burn, - gboolean force, gint source, GHashTable *track_indices); +gint ghb_find_subtitle_track(hb_title_t * title, const gchar * lang, int start); gint ghb_pick_subtitle_track(signal_user_data_t *ud); -gint ghb_find_cc_track(gint titleindex); gint ghb_longest_title(void); gchar* ghb_build_advanced_opts_string(GValue *settings); GdkPixbuf* ghb_get_preview_image( @@ -158,4 +154,17 @@ gchar* ghb_get_tmp_dir(); gint ghb_find_closest_audio_samplerate(gint rate); GValue* ghb_lookup_audio_encoder_value(gint val); +void ghb_init_lang_list_box(GtkListBox *list_box); + +void ghb_init_combo_box(GtkComboBox *combo); +void ghb_audio_encoder_opts_set(GtkComboBox *combo); +void ghb_audio_bitrate_opts_set(GtkComboBox *combo, gboolean extra); +void ghb_audio_bitrate_opts_filter(GtkComboBox *combo, gint first_rate, gint last_rate); +void ghb_mix_opts_set(GtkComboBox *combo); +void ghb_mix_opts_filter(GtkComboBox *combo, gint acodec); +void ghb_audio_samplerate_opts_set(GtkComboBox *combo); + +int ghb_lookup_audio_lang(const GValue *glang); +const iso639_lang_t* ghb_iso639_lookup_by_int(int idx); + #endif // _HBBACKEND_H_ diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 7ac06d3e8..467880c9e 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -6,8 +6,6 @@ <dict> <key>AudioTrackName</key> <string></string> - <key>AudioEncoderActual</key> - <string></string> <key>angle_count</key> <integer>1</integer> <key>angle</key> @@ -215,10 +213,6 @@ <string>0.1</string> <key>PreferredLanguage</key> <string>und</string> - <key>AudioDUB</key> - <false /> - <key>NotAudioDUB</key> - <true /> <key>constant_rate_factor</key> <true /> <key>WhenComplete</key> @@ -335,6 +329,10 @@ <true /> <key>AudioEncoderFallback</key> <string>ffac3</string> + <key>AudioLanguageList</key> + <array> + <string>und</string> + </array> <key>AudioList</key> <array> <dict> @@ -342,10 +340,6 @@ <string>192</string> <key>AudioEncoder</key> <string>copy:ac3</string> - <key>AudioTrack</key> - <integer>1</integer> - <key>AudioTrackDescription</key> - <string></string> <key>AudioTrackQualityEnable</key> <false /> <key>AudioTrackQuality</key> @@ -360,27 +354,28 @@ <string>source</string> </dict> </array> + <key>AudioSecondaryEncoderMode</key> + <true /> + <key>AudioTrackSelectionBehavior</key> + <string>first</string> <key>PresetDescription</key> <string></string> <key>PresetName</key> <string>Name Missing</string> <key>Type</key> <integer>1</integer> - <key>SubtitleList</key> + <key>SubtitleLanguageList</key> <array> - <dict> - <key>SubtitleLanguage</key> - <string>und</string> - <key>SubtitleForced</key> - <true /> - <key>SubtitleSource</key> - <integer>0</integer> - <key>SubtitleBurned</key> - <true /> - <key>SubtitleDefaultTrack</key> - <false /> - </dict> + <string>und</string> </array> + <key>SubtitleTrackSelectionBehavior</key> + <string>none</string> + <key>SubtitleAddCC</key> + <false /> + <key>SubtitleAddForeignAudioSearch</key> + <false /> + <key>SubtitleAddForeignAudioSubtitle</key> + <false /> <key>VideoTurboTwoPass</key> <false /> <key>UsesPictureFilters</key> diff --git a/gtk/src/main.c b/gtk/src/main.c index 04c43df6a..437540380 100644 --- a/gtk/src/main.c +++ b/gtk/src/main.c @@ -63,6 +63,8 @@ #include "icons.h" #include "callbacks.h" #include "queuehandler.h" +#include "audiohandler.h" +#include "subtitlehandler.h" #include "x264handler.h" #include "settings.h" #include "resources.h" @@ -112,7 +114,7 @@ create_builder_or_die(const gchar * name) GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - _(markup), + gettext(markup), name, error->message); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); @@ -274,7 +276,6 @@ bind_queue_tree_model(signal_user_data_t *ud) column = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(column, _("Job Information")); cell = gtk_cell_renderer_pixbuf_new(); - g_object_set(cell, "yalign", 0.0, NULL); gtk_tree_view_column_pack_start(column, cell, FALSE); gtk_tree_view_column_add_attribute(column, cell, "icon-name", 0); textcell = gtk_cell_renderer_text_new(); @@ -287,7 +288,6 @@ bind_queue_tree_model(signal_user_data_t *ud) gtk_tree_view_column_set_max_width(column, 550); cell = custom_cell_renderer_button_new(); - g_object_set(cell, "yalign", 0.0, NULL); column = gtk_tree_view_column_new_with_attributes( _(""), cell, "icon-name", 2, NULL); gtk_tree_view_column_set_min_width(column, 24); @@ -307,161 +307,128 @@ bind_queue_tree_model(signal_user_data_t *ud) } extern G_MODULE_EXPORT void audio_list_selection_changed_cb(void); +extern G_MODULE_EXPORT void audio_edit_clicked_cb(void); +extern G_MODULE_EXPORT void audio_remove_clicked_cb(void); // Create and bind the tree model to the tree view for the audio track list // Also, connect up the signal that lets us know the selection has changed static void bind_audio_tree_model(signal_user_data_t *ud) { - GtkCellRenderer *cell; + GtkCellRenderer *source_cell; + GtkCellRenderer *arrow_cell; + GtkCellRenderer *output_cell; + GtkCellRenderer *edit_cell; + GtkCellRenderer *delete_cell; GtkTreeViewColumn *column; - GtkListStore *treestore; + GtkTreeStore *treestore; GtkTreeView *treeview; GtkTreeSelection *selection; - GtkWidget *widget; g_debug("bind_audio_tree_model()\n"); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "audio_list")); selection = gtk_tree_view_get_selection(treeview); - // 12 columns in model. 6 are visible, the other 6 are for storing - // values that I need - treestore = gtk_list_store_new(7, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + treestore = gtk_tree_store_new(6, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_FLOAT); gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(treestore)); - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Track"), cell, "text", 0, NULL); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 200); - gtk_tree_view_column_set_max_width(column, 200); + source_cell = gtk_cell_renderer_text_new(); + arrow_cell = gtk_cell_renderer_text_new(); + output_cell = gtk_cell_renderer_text_new(); + edit_cell = custom_cell_renderer_button_new(); + delete_cell = custom_cell_renderer_button_new(); - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Codec"), cell, "text", 1, NULL); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 110); - - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Bitrate"), cell, "text", 2, NULL); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 50); - - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Sample Rate"), cell, "text", 3, NULL); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 100); - - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Mix"), cell, "text", 4, NULL); + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_spacing(column, 12); + gtk_tree_view_column_set_title(column, _("Track Information")); + gtk_tree_view_column_pack_start(column, source_cell, FALSE); + gtk_tree_view_column_add_attribute(column, source_cell, "text", 0); + gtk_tree_view_column_add_attribute(column, source_cell, "yalign", 5); + gtk_tree_view_column_pack_start(column, arrow_cell, FALSE); + gtk_tree_view_column_add_attribute(column, arrow_cell, "text", 1); + gtk_tree_view_column_pack_start(column, output_cell, TRUE); + gtk_tree_view_column_add_attribute(column, output_cell, "markup", 2); + gtk_tree_view_column_add_attribute(column, output_cell, "yalign", 5); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 115); + gtk_tree_view_column_set_expand(column, TRUE); - cell = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( - _("Gain"), cell, "text", 5, NULL); + _(""), edit_cell, "icon-name", 3, NULL); + //gtk_tree_view_column_set_min_width(column, 24); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - cell = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( - _("DRC"), cell, "text", 6, NULL); + _(""), delete_cell, "icon-name", 4, NULL); + //gtk_tree_view_column_set_min_width(column, 24); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); g_signal_connect(selection, "changed", audio_list_selection_changed_cb, ud); - // Need to disable remove and update buttons since there are initially - // no selections - widget = GHB_WIDGET(ud->builder, "audio_remove"); - gtk_widget_set_sensitive(widget, FALSE); + g_signal_connect(edit_cell, "clicked", audio_edit_clicked_cb, ud); + g_signal_connect(delete_cell, "clicked", audio_remove_clicked_cb, ud); + g_debug("Done\n"); } extern G_MODULE_EXPORT void subtitle_list_selection_changed_cb(void); -extern G_MODULE_EXPORT void subtitle_forced_toggled_cb(void); -extern G_MODULE_EXPORT void subtitle_burned_toggled_cb(void); -extern G_MODULE_EXPORT void subtitle_default_toggled_cb(void); +extern G_MODULE_EXPORT void subtitle_edit_clicked_cb(void); +extern G_MODULE_EXPORT void subtitle_remove_clicked_cb(void); // Create and bind the tree model to the tree view for the subtitle track list // Also, connect up the signal that lets us know the selection has changed static void bind_subtitle_tree_model(signal_user_data_t *ud) { - GtkCellRenderer *cell; + GtkCellRenderer *source_cell; + GtkCellRenderer *arrow_cell; + GtkCellRenderer *output_cell; + GtkCellRenderer *edit_cell; + GtkCellRenderer *delete_cell; GtkTreeViewColumn *column; - GtkListStore *treestore; + GtkTreeStore *treestore; GtkTreeView *treeview; GtkTreeSelection *selection; - GtkWidget *widget; g_debug("bind_subtitle_tree_model()\n"); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); selection = gtk_tree_view_get_selection(treeview); - // 6 columns in model. 5 are visible, the other 1 is for storing - // values that I need - // Track, force, burn, default, type, srt offset, track short, source - // force visible, burn visible, offset visible - treestore = gtk_list_store_new(10, - G_TYPE_STRING, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, - G_TYPE_INT, G_TYPE_STRING, - G_TYPE_INT, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN); + treestore = gtk_tree_store_new(6, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_FLOAT); gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(treestore)); - cell = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Track"), cell, "text", 0, NULL); - widget = GHB_WIDGET(ud->builder, "SubTrackLabel"); - gtk_tree_view_column_set_widget(column, widget); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - gtk_tree_view_column_set_min_width(column, 350); - gtk_tree_view_column_set_max_width(column, 350); - - cell = gtk_cell_renderer_toggle_new(); - column = gtk_tree_view_column_new_with_attributes( - _("Forced Only"), cell, "active", 1, "visible", 7, NULL); - widget = GHB_WIDGET(ud->builder, "SubForcedLabel"); - gtk_tree_view_column_set_widget(column, widget); - gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - g_signal_connect(cell, "toggled", subtitle_forced_toggled_cb, ud); + source_cell = gtk_cell_renderer_text_new(); + arrow_cell = gtk_cell_renderer_text_new(); + output_cell = gtk_cell_renderer_text_new(); + edit_cell = custom_cell_renderer_button_new(); + delete_cell = custom_cell_renderer_button_new(); - cell = gtk_cell_renderer_toggle_new(); - gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(cell), TRUE); - column = gtk_tree_view_column_new_with_attributes( - _("Burned In"), cell, "active", 2, "visible", 8, NULL); - widget = GHB_WIDGET(ud->builder, "SubBurnedLabel"); - gtk_tree_view_column_set_widget(column, widget); + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_spacing(column, 12); + gtk_tree_view_column_set_title(column, _("Track Information")); + gtk_tree_view_column_pack_start(column, source_cell, FALSE); + gtk_tree_view_column_add_attribute(column, source_cell, "text", 0); + gtk_tree_view_column_add_attribute(column, source_cell, "yalign", 5); + gtk_tree_view_column_pack_start(column, arrow_cell, FALSE); + gtk_tree_view_column_add_attribute(column, arrow_cell, "text", 1); + gtk_tree_view_column_pack_start(column, output_cell, TRUE); + gtk_tree_view_column_add_attribute(column, output_cell, "markup", 2); + gtk_tree_view_column_add_attribute(column, output_cell, "yalign", 5); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - g_signal_connect(cell, "toggled", subtitle_burned_toggled_cb, ud); + gtk_tree_view_column_set_expand(column, TRUE); + gtk_tree_view_column_set_max_width(column, 400); - cell = gtk_cell_renderer_toggle_new(); - gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(cell), TRUE); column = gtk_tree_view_column_new_with_attributes( - _("Default"), cell, "active", 3, NULL); - widget = GHB_WIDGET(ud->builder, "SubDefaultLabel"); - gtk_tree_view_column_set_widget(column, widget); + _(""), edit_cell, "icon-name", 3, NULL); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - g_signal_connect(cell, "toggled", subtitle_default_toggled_cb, ud); - cell = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes( - _("Srt Offset"), cell, "text", 4, "visible", 9, NULL); - widget = GHB_WIDGET(ud->builder, "SubSRTOffsetLabel"); - gtk_tree_view_column_set_widget(column, widget); + _(""), delete_cell, "icon-name", 4, NULL); gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column)); - g_signal_connect(selection, "changed", subtitle_list_selection_changed_cb, ud); - // Need to disable remove and update buttons since there are initially - // no selections - widget = GHB_WIDGET(ud->builder, "subtitle_remove"); - gtk_widget_set_sensitive(widget, FALSE); - g_debug("Done\n"); + g_signal_connect(edit_cell, "clicked", subtitle_edit_clicked_cb, ud); + g_signal_connect(delete_cell, "clicked", subtitle_remove_clicked_cb, ud); } extern G_MODULE_EXPORT void presets_list_selection_changed_cb(void); @@ -734,11 +701,18 @@ G_MODULE_EXPORT void preview_hud_size_alloc_cb(GtkWidget *widget, signal_user_da #if GTK_CHECK_VERSION(3, 0, 0) const gchar *MyCSS = " \n\ +GtkRadioButton .button { \n\ + border-width: 0px; \n\ + padding: 0px; \n\ +} \n\ GtkComboBox { \n\ - padding: 1px; \n\ + padding: 0px; \n\ +} \n\ +GtkComboBox .button { \n\ + padding: 2px; \n\ } \n\ GtkEntry { \n\ - padding: 4px; \n\ + padding: 0px 4px; \n\ } \n\ \n\ @define-color black #000000; \n\ @@ -1028,11 +1002,16 @@ main(int argc, char *argv[]) while (x264_presets && x264_presets[count]) count++; gtk_range_set_range(GTK_RANGE(presetSlider), 0, count-1); + ghb_init_audio_defaults_ui(ud); + ghb_init_subtitle_defaults_ui(ud); + // Load all internal settings ghb_settings_init(ud); + // Load prefs before presets. Some preset defaults may depend + // on preference settings. + ghb_prefs_load(ud); // Load the presets files ghb_presets_load(ud); - ghb_prefs_load(ud); ghb_prefs_to_ui(ud); @@ -1132,8 +1111,6 @@ main(int argc, char *argv[]) widget = GHB_WIDGET(ud->builder, "srt_code_label"); gtk_widget_get_preferred_size( widget, &min_size, &size ); height += MAX(min_size.height, size.height); - widget = GHB_WIDGET(ud->builder, "subtitle_table"); - gtk_widget_set_size_request(widget, -1, height); #else GtkRequisition size; @@ -1143,8 +1120,6 @@ main(int argc, char *argv[]) widget = GHB_WIDGET(ud->builder, "srt_code_label"); gtk_widget_size_request( widget, &size ); height += size.height; - widget = GHB_WIDGET(ud->builder, "subtitle_table"); - gtk_widget_set_size_request(widget, -1, height); #endif widget = GHB_WIDGET(ud->builder, "hb_window"); diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py index c0f791d1c..40ea364d4 100644 --- a/gtk/src/makedeps.py +++ b/gtk/src/makedeps.py @@ -48,22 +48,17 @@ dep_map = ( DepEntry("VideoEncoder", "x264_tab", "x264", False, True), DepEntry("VideoEncoder", "x264VideoSettings", "x264", False, True), DepEntry("VideoEncoder", "lavc_mpeg4_tab", "mpeg4|mpeg2", False, True), - DepEntry("AudioTrackQualityEnable", "AudioBitrateLabel", "TRUE", True, False), - DepEntry("AudioTrackQualityEnable", "AudioBitrate", "TRUE", True, False), - DepEntry("AudioEncoderActual", "AudioBitrateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioBitrate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioSamplerateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioSamplerate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioMixdownLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioMixdown", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioTrackGainLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioTrackGain", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoderActual", "AudioTrackGainValue", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), - DepEntry("AudioEncoder", "AudioAllowMP3Pass", "copy", False, False), - DepEntry("AudioEncoder", "AudioAllowAACPass", "copy", False, False), - DepEntry("AudioEncoder", "AudioAllowAC3Pass", "copy", False, False), - DepEntry("AudioEncoder", "AudioAllowDTSPass", "copy", False, False), - DepEntry("AudioEncoder", "AudioAllowDTSHDPass", "copy", False, False), + DepEntry("AudioTrackQualityEnable", "AudioBitrate", "TRUE", True, True), + DepEntry("AudioTrackQualityEnable", "AudioTrackQualityBox", "FALSE", True, True), + DepEntry("AudioEncoder", "AudioBitrateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioBitrate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioSamplerateLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioSamplerate", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioMixdownLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioMixdown", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioTrackGainLabel", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioTrackGain", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), + DepEntry("AudioEncoder", "AudioTrackGainValue", "copy:mp3|copy:aac|copy:ac3|copy:dts|copy:dtshd", True, False), DepEntry("x264_bframes", "x264_bpyramid", "<2", True, False), DepEntry("x264_bframes", "x264_direct", "0", True, False), DepEntry("x264_bframes", "x264_b_adapt", "0", True, False), diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 3b374375b..81d610cba 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -807,9 +807,9 @@ init_settings_from_array( else init_settings_from_array(new_array, gval, gval); } - else + else if (val != NULL) { - ghb_array_append(dest, val); + ghb_array_append(dest, ghb_value_dup(val)); } } } @@ -1581,7 +1581,7 @@ ghb_prefs_load(signal_user_data_t *ud) GValue *dict, *internal; GHashTableIter iter; gchar *key; - GValue *gval, *path; + GValue *gval; g_debug("ghb_prefs_load"); prefsPlist = load_plist("preferences"); @@ -1636,32 +1636,6 @@ ghb_prefs_load(signal_user_data_t *ud) #endif store_prefs(); } - // Read legacy default_preset preference and update accordingly - path = ghb_dict_lookup(dict, "default_preset"); - if (path) - { - gint *indices, len; - - if (G_VALUE_TYPE(path) == G_TYPE_STRING) - { - GValue *str = path; - - path = ghb_array_value_new(1); - ghb_array_append(path, ghb_value_dup(str)); - indices = ghb_preset_indices_from_path(presetsPlist, path, &len); - ghb_value_free(path); - } - else - indices = ghb_preset_indices_from_path(presetsPlist, path, &len); - - if (indices) - { - presets_set_default(indices, len); - g_free(indices); - } - ghb_dict_remove(dict, "default_preset"); - store_prefs(); - } } static const gchar* @@ -2057,6 +2031,7 @@ value_map_t decomb_xlat[] = {NULL, NULL} }; +#if 0 extern iso639_lang_t ghb_language_table[]; static GValue* @@ -2091,30 +2066,6 @@ export_lang_xlat2(GValue *lin_val) } static GValue* -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) - { - gval = ghb_string_value_new("None"); - } - else if (strcmp(str, "auto") == 0) - { - gval = ghb_string_value_new("Autoselect"); - } - else - { - gval = export_lang_xlat2(lin_val); - } - g_free(str); - return gval; -} - -static GValue* import_lang_xlat2(GValue *mac_val) { GValue *gval; @@ -2138,74 +2089,7 @@ import_lang_xlat2(GValue *mac_val) g_free(str); return NULL; } - -static GValue* -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) - { - gval = ghb_string_value_new("none"); - } - else if (strcmp(str, "Autoselect") == 0) - { - gval = ghb_string_value_new("auto"); - } - else - { - gval = import_lang_xlat2(mac_val); - } - g_free(str); - return gval; -} - -static GValue* -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) - { - gval = ghb_int_value_new(1); - } - else - { - gint val = ghb_value_int(lin_val) + 1; - gval = ghb_int_value_new(val); - } - g_free(str); - return gval; -} - -static GValue* -import_audio_track_xlat2(GValue *mac_val) -{ - gint val; - gchar *str; - GValue *gval; - - if (mac_val == NULL) return NULL; - val = ghb_value_int(mac_val); - if (val <= 0) - { - val = 0; - } - else - { - val--; - } - str = g_strdup_printf("%d", val); - gval = ghb_string_value_new(str); - g_free(str); - return gval; -} +#endif static GValue* export_value_xlat2(value_map_t *value_map, GValue *lin_val, GType mac_type) @@ -2379,22 +2263,7 @@ export_value_xlat(GValue *dict) 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; @@ -2409,11 +2278,6 @@ export_value_xlat(GValue *dict) for (ii = 0; ii < count; ii++) { adict = ghb_array_get_nth(alist, ii); - key = "AudioTrack"; - lin_val = ghb_dict_lookup(adict, key); - gval = export_audio_track_xlat2(lin_val); - if (gval) - ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioEncoder"; lin_val = ghb_dict_lookup(adict, key); gval = export_value_audio_encoder(lin_val); @@ -2649,75 +2513,10 @@ import_value_xlat(GValue *dict) if (gval) ghb_dict_insert(dict, g_strdup(key), gval); - GValue *sdeflist; - GValue *slist; - GValue *sdict; - gint count, ii; - - sdeflist = ghb_dict_lookup(defaults, "SubtitleList"); - if (sdeflist) - { - slist = ghb_dict_lookup(dict, "SubtitleList"); - if (slist) - { - 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"); - + gint count, ii; GValue *alist; GValue *adict; GValue *adefaults; @@ -2738,11 +2537,6 @@ import_value_xlat(GValue *dict) for (ii = 0; ii < count; ii++) { adict = ghb_array_get_nth(alist, ii); - key = "AudioTrack"; - mac_val = ghb_dict_lookup(adict, key); - gval = import_audio_track_xlat2(mac_val); - if (gval) - ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioEncoder"; mac_val = ghb_dict_lookup(adict, key); gval = import_value_audio_encoder(mac_val); @@ -2789,7 +2583,6 @@ import_xlat_preset(GValue *dict) gint vqtype; g_debug("import_xlat_preset ()"); - uses_max = ghb_value_boolean( preset_dict_get_value(dict, "UsesMaxPictureSettings")); uses_pic = ghb_value_int( @@ -2862,6 +2655,75 @@ import_xlat_preset(GValue *dict) } break; } + // Initialize the AudioLanguageList from preferences PreferredLanguage + // and translate old AudioDUB preference option if found + GValue *list = ghb_dict_lookup(dict, "AudioLanguageList"); + if (list == NULL) + { + list = ghb_array_value_new(8); + ghb_dict_insert(dict, g_strdup("AudioLanguageList"), list); + } + if (ghb_array_len(list) == 0) + { + GValue *prefs = plist_get_dict(prefsPlist, "Preferences"); + GValue *gdub = ghb_dict_lookup(prefs, "AudioDUB"); + GValue *glang = ghb_dict_lookup(prefs, "PreferredLanguage"); + const char *lang = NULL; + if (glang != NULL) + { + lang = g_value_get_string(glang); + } + if (gdub != NULL && !ghb_value_boolean(gdub)) + { + if (lang == NULL || strncmp(lang, "und", 4)) + { + ghb_array_append(list, ghb_string_value_new("und")); + } + } + if (glang != NULL) + { + ghb_array_append(list, ghb_value_dup(glang)); + } + } + + // Initialize the SubtitleLanguageList from preferences PreferredLanguage + // and translate old AudioDUB preference option if found + list = ghb_dict_lookup(dict, "SubtitleLanguageList"); + if (list == NULL) + { + list = ghb_array_value_new(8); + ghb_dict_insert(dict, g_strdup("SubtitleLanguageList"), list); + } + if (ghb_array_len(list) == 0) + { + GValue *prefs = plist_get_dict(prefsPlist, "Preferences"); + GValue *val = ghb_dict_lookup(prefs, "PreferredLanguage"); + if (val != NULL) + { + ghb_array_append(list, ghb_value_dup(val)); + + val = ghb_dict_lookup(prefs, "AudioDUB"); + if (val != NULL && !ghb_value_boolean(val)) + { + ghb_dict_insert(dict, + g_strdup("SubtitleAddForeignAudioSubtitle"), + ghb_boolean_value_new(TRUE)); + } + } + } + + GValue *addCC = ghb_dict_lookup(dict, "SubtitleAddCC"); + if (addCC == NULL) + { + GValue *prefs = plist_get_dict(prefsPlist, "Preferences"); + GValue *val = ghb_dict_lookup(prefs, "AddCC"); + if (val != NULL) + { + ghb_dict_insert(dict, g_strdup("SubtitleAddCC"), + ghb_value_dup(val)); + } + } + import_value_xlat(dict); GValue *mode = ghb_dict_lookup(dict, "VideoFramerateMode"); @@ -3665,16 +3527,6 @@ ghb_presets_list_clear_default(signal_user_data_t *ud) } static void -update_audio_presets(signal_user_data_t *ud) -{ - g_debug("update_audio_presets"); - const GValue *audio_list; - - audio_list = ghb_settings_get_value(ud->settings, "audio_list"); - ghb_settings_set_value(ud->settings, "AudioList", audio_list); -} - -static void update_subtitle_presets(signal_user_data_t *ud) { g_debug("update_subtitle_presets"); @@ -4037,8 +3889,6 @@ presets_save_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) ghb_widget_to_setting(ud->settings, GTK_WIDGET(desc)); - // 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); @@ -4502,6 +4352,8 @@ ghb_refresh_preset(signal_user_data_t *ud) ghb_set_preset_from_indices(ud, indices, len); gint titleindex; titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_audio_def_settings_init(ud); + ghb_subtitle_def_settings_init(ud); ghb_set_pref_audio_settings(titleindex, ud->settings); ghb_set_pref_audio_from_settings(ud, ud->settings); ghb_set_pref_subtitle(titleindex, ud); @@ -4579,6 +4431,8 @@ presets_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_ ghb_set_preset_from_indices(ud, indices, len); gint titleindex; titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_audio_def_settings_init(ud); + ghb_subtitle_def_settings_init(ud); ghb_set_pref_audio_settings(titleindex, ud->settings); ghb_set_pref_audio_from_settings(ud, ud->settings); ghb_set_pref_subtitle(titleindex, ud); diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index f02195673..5c45eebb8 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -417,12 +417,12 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) asettings = ghb_array_get_nth(audio_list, ii); - acodec = ghb_settings_combo_option(asettings, "AudioEncoderActual"); + acodec = ghb_settings_combo_option(asettings, "AudioEncoder"); double q = ghb_settings_get_double(asettings, "AudioTrackQuality"); if (ghb_settings_get_boolean(asettings, "AudioTrackQualityEnable") && q != HB_INVALID_AUDIO_QUALITY) { - int codec = ghb_settings_combo_int(asettings, "AudioEncoderActual"); + int codec = ghb_settings_combo_int(asettings, "AudioEncoder"); quality = ghb_format_quality("Quality: ", codec, q); } else @@ -715,7 +715,7 @@ queue_add_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) if (!ghb_queue_add(ud, settings, 0)) ghb_value_free(settings); // Validation of settings may have changed audio list - ghb_audio_list_refresh(ud); + ghb_audio_list_refresh_all(ud); } G_MODULE_EXPORT void @@ -1196,7 +1196,7 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) return; } // Validation of settings may have changed audio list - ghb_audio_list_refresh(ud); + ghb_audio_list_refresh_all(ud); } if (state == GHB_STATE_IDLE) { diff --git a/gtk/src/settings.c b/gtk/src/settings.c index ee68f74f6..5acee1ece 100644 --- a/gtk/src/settings.c +++ b/gtk/src/settings.c @@ -190,6 +190,10 @@ ghb_get_setting_key(GtkWidget *widget) if (name == NULL) { + name = gtk_widget_get_name(widget); + } + if (name == NULL) + { // Bad widget pointer? Should never happen. g_debug("Bad widget\n"); return NULL; @@ -415,26 +419,6 @@ ghb_widget_boolean(GtkWidget *widget) return bval; } -static void check_radio_consistency(GValue *settings, GtkWidget *widget) -{ - const gchar *key = NULL; - GValue *value; - - if (widget == NULL) return; - if (G_OBJECT_TYPE(widget) == GTK_TYPE_RADIO_BUTTON) - { - // Find corresponding setting - key = ghb_get_setting_key(widget); - if (key == NULL) return; - value = ghb_widget_value(widget); - if (value == NULL) return; - if (ghb_value_boolean(value) == ghb_settings_get_boolean(settings, key)) - { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE); - } - } -} - void ghb_widget_to_setting(GValue *settings, GtkWidget *widget) { @@ -449,7 +433,6 @@ ghb_widget_to_setting(GValue *settings, GtkWidget *widget) value = ghb_widget_value(widget); if (value != NULL) { - check_radio_consistency(settings, widget); ghb_settings_take_value(settings, key, value); } else @@ -458,15 +441,15 @@ ghb_widget_to_setting(GValue *settings, GtkWidget *widget) } } -static void -update_widget(GtkWidget *widget, const GValue *value) +void +ghb_update_widget(GtkWidget *widget, const GValue *value) { GType type; gchar *str; gint ival; gdouble dval; - g_debug("update_widget"); + g_debug("ghb_update_widget"); type = G_VALUE_TYPE(value); if (type == ghb_array_get_type() || type == ghb_dict_get_type()) return; @@ -475,6 +458,7 @@ update_widget(GtkWidget *widget, const GValue *value) ival = ghb_value_int(value); dval = ghb_value_double(value); type = G_OBJECT_TYPE(widget); + if (type == GTK_TYPE_ENTRY) { g_debug("entry"); @@ -483,16 +467,7 @@ update_widget(GtkWidget *widget, const GValue *value) else if (type == GTK_TYPE_RADIO_BUTTON) { g_debug("radio button"); - int cur_val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - if (cur_val && !ival) - { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), TRUE); - } - else - { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival); - } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), !!ival); } else if (type == GTK_TYPE_CHECK_BUTTON) { @@ -666,7 +641,7 @@ ghb_ui_update_from_settings(GtkBuilder *builder, const gchar *name, const GValue g_debug("Failed to find widget for key: %s\n", name); return -1; } - update_widget((GtkWidget*)object, value); + ghb_update_widget((GtkWidget*)object, value); return 0; } @@ -684,7 +659,7 @@ ghb_ui_update(signal_user_data_t *ud, const gchar *name, const GValue *value) g_debug("Failed to find widget for key: %s\n", name); return -1; } - update_widget((GtkWidget*)object, value); + ghb_update_widget((GtkWidget*)object, value); // Its possible the value hasn't changed. Since settings are only // updated when the value changes, I'm initializing settings here as well. ghb_widget_to_setting(ud->settings, (GtkWidget*)object); diff --git a/gtk/src/settings.h b/gtk/src/settings.h index 76f2d97be..6e3ee55ff 100644 --- a/gtk/src/settings.h +++ b/gtk/src/settings.h @@ -118,5 +118,6 @@ int ghb_ui_update( int ghb_ui_update_from_settings( GtkBuilder *builder, const gchar *name, const GValue *settings); const gchar* ghb_get_setting_key(GtkWidget *widget); +void ghb_update_widget(GtkWidget *widget, const GValue *value); #endif // _SETTINGS_H_ diff --git a/gtk/src/subtitlehandler.c b/gtk/src/subtitlehandler.c index 121654ac5..abaee4b2e 100644 --- a/gtk/src/subtitlehandler.c +++ b/gtk/src/subtitlehandler.c @@ -2,15 +2,16 @@ /* * subtitlehandler.c * Copyright (C) John Stebbins 2008-2013 <stebbins@stebbins> - * + * * subtitlehandler.c is free software. - * + * * You may redistribute it and/or modify it under the terms of the * GNU General Public License, as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. */ +#include <glib/gi18n.h> #include "ghbcompat.h" #include "hb.h" #include "settings.h" @@ -22,118 +23,164 @@ #include "audiohandler.h" #include "subtitlehandler.h" -static gboolean ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings); +static void subtitle_add_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 add_to_subtitle_list_ui(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 ghb_clear_subtitle_list_ui(GtkBuilder *builder); static void -free_subtitle_index_list(gpointer data) +subtitle_refresh_list_row_ui( + GtkTreeModel *tm, + GtkTreeIter *ti, + GValue *subsettings) { - g_free(data); -} + GtkTreeIter cti; + gboolean forced, burned, def; + char *info_src, *info_src_2; + char *info_dst, *info_dst_2; -static void -free_subtitle_key(gpointer data) -{ - if (data != NULL) - g_free(data); -} -gboolean -ghb_canPassSub(int source, int mux) -{ - return hb_subtitle_can_pass(source, mux); -} + info_src_2 = NULL; + info_dst_2 = NULL; -gboolean -ghb_canBurnSub(int source) -{ - return hb_subtitle_can_burn(source); -} + forced = ghb_settings_get_boolean(subsettings, "SubtitleForced"); + burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned"); + def = ghb_settings_get_boolean(subsettings, "SubtitleDefaultTrack"); + info_src = ghb_settings_get_string(subsettings, "SubtitleTrackDescription"); + if (ghb_settings_get_int(subsettings, "SubtitleSource") == SRTSUB) + { + gint offset; + offset = ghb_settings_get_int(subsettings, "SrtOffset"); + if (offset != 0) + { + info_dst_2 = g_strdup_printf("Offset: %dms", offset); + } + } -gboolean -ghb_canForceSub(int source) -{ - return hb_subtitle_can_force(source); -} + GString *str = g_string_new(""); + g_string_append_printf(str, "%s ", burned ? "Burned Into Video" : + "Passthrough"); + if (forced) + { + g_string_append_printf(str, "(Forced Subtitles Only)"); + } + if (def) + { + g_string_append_printf(str, "(Default)"); + } -gboolean -ghb_soft_in_subtitle_list(GValue *subtitle_list) -{ - gint count, ii; - GValue *settings; + info_dst = g_string_free(str, FALSE); - count = ghb_array_len(subtitle_list); - for (ii = 0; ii < count; ii++) + gtk_tree_store_set(GTK_TREE_STORE(tm), ti, + // These are displayed in list + 0, info_src, + 1, "-->", + 2, info_dst, + 3, "hb-edit", + 4, "hb-queue-delete", + 5, 0.5, + -1); + + if (info_src_2 != NULL || info_dst_2 != NULL) { - settings = ghb_array_get_nth(subtitle_list, ii); - if (!ghb_settings_get_boolean(settings, "SubtitleBurned")) + if (info_src_2 == NULL) + info_src_2 = g_strdup(""); + if (info_dst_2 == NULL) + info_dst_2 = g_strdup(""); + + if(!gtk_tree_model_iter_children(tm, &cti, ti)) { - return TRUE; + gtk_tree_store_append(GTK_TREE_STORE(tm), &cti, ti); } + gtk_tree_store_set(GTK_TREE_STORE(tm), &cti, + // These are displayed in list + 0, info_src_2, + 2, info_dst_2, + 5, 0.0, + -1); } - return FALSE; + else + { + if(gtk_tree_model_iter_children(tm, &cti, ti)) + { + gtk_tree_store_remove(GTK_TREE_STORE(tm), &cti); + } + } + + g_free(info_src); + g_free(info_src_2); + g_free(info_dst); + g_free(info_dst_2); } -void -ghb_subtitle_exclusive_burn_settings(GValue *settings, gint index) +static void +subtitle_refresh_list_ui(signal_user_data_t *ud) { GValue *subtitle_list; GValue *subsettings; - gint ii, count; + gint ii, count, tm_count; + GtkTreeView *tv; + GtkTreeModel *tm; + GtkTreeIter ti; - g_debug("ghb_subtitle_exclusive_burn_settings"); - subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + tm = gtk_tree_view_get_model(tv); + + tm_count = gtk_tree_model_iter_n_children(tm, NULL); + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); count = ghb_array_len(subtitle_list); - for (ii = 0; ii < count; ii++) + if (count != tm_count) { - if (ii != index) + ghb_clear_subtitle_list_ui(ud->builder); + for (ii = 0; ii < count; ii++) { - subsettings = ghb_array_get_nth(subtitle_list, ii); - ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE); + gtk_tree_store_append(GTK_TREE_STORE(tm), &ti, NULL); } } + for (ii = 0; ii < count; ii++) + { + g_return_if_fail(tv != NULL); + gtk_tree_model_iter_nth_child(tm, &ti, NULL, ii); + subsettings = ghb_array_get_nth(subtitle_list, ii); + subtitle_refresh_list_row_ui(tm, &ti, subsettings); + } } void -ghb_subtitle_exclusive_burn(signal_user_data_t *ud, gint index) +ghb_subtitle_exclusive_burn_settings(GValue *settings, gint index) { GValue *subtitle_list; GValue *subsettings; gint ii, count; - GtkTreeView *tv; - GtkTreeModel *tm; - GtkTreeIter ti; - g_debug("ghb_subtitle_exclusive_burn"); - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); count = ghb_array_len(subtitle_list); for (ii = 0; ii < count; ii++) { - 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 (ii != index) { 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_burn(signal_user_data_t *ud, gint index) +{ + ghb_subtitle_exclusive_burn_settings(ud->settings, index); + subtitle_refresh_list_ui(ud); +} + +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++) @@ -149,93 +196,29 @@ ghb_subtitle_exclusive_default_settings(GValue *settings, gint index) void ghb_subtitle_exclusive_default(signal_user_data_t *ud, gint index) { - GValue *subtitle_list; - GValue *settings; - gint ii, count; - GtkTreeView *tv; - GtkTreeModel *tm; - GtkTreeIter ti; - gboolean def; - - g_debug("ghb_subtitle_exclusive_default"); - 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); - def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack"); - - 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 (def && ii != index) - { - - ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, FALSE, -1); - } - } + ghb_subtitle_exclusive_default_settings(ud->settings, index); + subtitle_refresh_list_ui(ud); } -void -ghb_add_srt(signal_user_data_t *ud, GValue *settings) +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; - const gchar *lang; - - g_debug("ghb_add_srt ()"); - - ghb_settings_set_boolean(settings, "SubtitleBurned", FALSE); - // Add the long track description so the queue can access it - // when a different title is selected. - lang = ghb_settings_combo_option(settings, "SrtLanguage"); - ghb_settings_set_string(settings, "SubtitleTrackDescription", lang); - - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - if (subtitle_list == NULL) - { - subtitle_list = ghb_array_value_new(8); - ghb_settings_set_value(ud->settings, "subtitle_list", 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() - if (count >= 99) - { - ghb_value_free(settings); + if (subsettings == NULL) return; - } - - ghb_array_append(subtitle_list, settings); - add_to_srt_list(ud, settings); - if (count == 98) - { - GtkWidget *widget; - widget = GHB_WIDGET (ud->builder, "subtitle_add"); - gtk_widget_set_sensitive(widget, FALSE); - widget = GHB_WIDGET (ud->builder, "srt_add"); - gtk_widget_set_sensitive(widget, FALSE); - } + // Add the current subtitle settings to the list. + add_to_subtitle_list_ui(ud, subsettings); ghb_live_reset(ud); } -static gboolean -ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings) +static void +subtitle_add_to_settings(GValue *settings, GValue *subsettings) { // Add the current subtitle settings to the list. GValue *subtitle_list; gint count; - gboolean burned, forced; + gboolean burned, forced, def; gint source, mux; - const gchar *track; - const gchar *lang; - - g_debug("ghb_add_subtitle_to_settings ()"); subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) @@ -244,39 +227,24 @@ ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings) ghb_settings_set_value(settings, "subtitle_list", subtitle_list); } - count = ghb_array_len(subtitle_list); - // Don't allow more than 99 - // This is a hard limit imposed by libhb/reader.c:GetFifoForId() - if (count >= 99) - { - ghb_value_free(subsettings); - return FALSE; - } - - // 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); - - lang = ghb_settings_combo_string(subsettings, "SubtitleTrack"); - ghb_settings_set_string(subsettings, "SubtitleLanguage", lang); - + // Validate some settings mux = ghb_settings_combo_int(settings, "FileFormat"); source = ghb_settings_get_int(subsettings, "SubtitleSource"); burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned"); - if (burned && !ghb_canBurnSub(source)) + if (burned && !hb_subtitle_can_burn(source)) { burned = FALSE; ghb_settings_set_boolean(subsettings, "SubtitleBurned", burned); } - if (!burned && !ghb_canPassSub(source, mux)) + if (!burned && !hb_subtitle_can_pass(source, mux)) { burned = TRUE; ghb_settings_set_boolean(subsettings, "SubtitleBurned", burned); ghb_settings_set_boolean(subsettings, "SubtitleDefaultTrack", FALSE); } + def = ghb_settings_get_boolean(subsettings, "SubtitleDefaultTrack"); forced = ghb_settings_get_boolean(subsettings, "SubtitleForced"); - if (forced && !ghb_canForceSub(source)) + if (forced && !hb_subtitle_can_force(source)) { forced = FALSE; ghb_settings_set_boolean(subsettings, "SubtitleForced", forced); @@ -284,85 +252,177 @@ ghb_add_subtitle_to_settings(GValue *settings, GValue *subsettings) ghb_array_append(subtitle_list, subsettings); + // Check consistancy of exclusive flags + count = ghb_array_len(subtitle_list); if (burned) - ghb_subtitle_exclusive_burn_settings(settings, count); - return TRUE; + ghb_subtitle_exclusive_burn_settings(settings, count-1); + if (def) + ghb_subtitle_exclusive_default_settings(settings, count-1); } static void -ghb_add_subtitle_to_ui(signal_user_data_t *ud, GValue *subsettings) +subtitle_set_track_description(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); + char *track; - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - count = ghb_array_len(subtitle_list); - if (count == 99) + if (ghb_settings_get_int(subsettings, "SubtitleSource") == SRTSUB) { - GtkWidget *widget; - widget = GHB_WIDGET (ud->builder, "subtitle_add"); - gtk_widget_set_sensitive(widget, FALSE); - widget = GHB_WIDGET (ud->builder, "srt_add"); - gtk_widget_set_sensitive(widget, FALSE); + gchar *filename, *code; + const gchar *lang; + + lang = ghb_settings_combo_option(subsettings, "SrtLanguage"); + code = ghb_settings_get_string(subsettings, "SrtCodeset"); + + filename = ghb_settings_get_string(subsettings, "SrtFile"); + if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + { + gchar *basename; + + basename = g_path_get_basename(filename); + track = g_strdup_printf("%s (%s)(SRT)(%s)", lang, code, basename); + g_free(basename); + } + else + { + track = g_strdup_printf("%s (%s)(SRT)", lang, code); + } + g_free(code); } - ghb_live_reset(ud); + else + { + track = g_strdup( + ghb_settings_combo_option(subsettings, "SubtitleTrack")); + } + + ghb_settings_set_string( + subsettings, "SubtitleTrackDescription", track); + + g_free(track); } -static void -add_all_pref_subtitles(signal_user_data_t *ud) +static GValue* subtitle_add_track( + GValue *settings, + hb_title_t *title, + int track, + int mux, + gboolean default_track, + gboolean srt, + gboolean *burned) { - const GValue *pref_subtitle; - GValue *subtitle; - gint count, ii, track; - char *lang; + int source = 0; - pref_subtitle = ghb_settings_get_value(ud->settings, "SubtitleList"); - count = ghb_array_len(pref_subtitle); - for (ii = 0; ii < count; ii++) + if (track >= 0 && !srt) { - subtitle = ghb_value_dup(ghb_array_get_nth(pref_subtitle, ii)); - lang = ghb_settings_get_string(subtitle, "SubtitleLanguage"); - // If there are multiple subtitles using the same language, then - // select sequential tracks for each. The hash keeps track - // of the tracks used for each language. - track = ghb_find_pref_subtitle_track(lang); - g_free(lang); - if (track >= -1) - { - int source; + hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, track); + source = subtitle->source; + } + else if (srt) + { + source = SRTSUB; + } - // Add to subtitle list - ghb_settings_set_int(subtitle, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud->settings, track); - ghb_settings_set_int(subtitle, "SubtitleSource", source); + if (*burned && !hb_subtitle_can_pass(source, mux)) + { + // Can only burn one. Skip others that must be burned. + return NULL; + } - if (!ghb_add_subtitle_to_settings(ud->settings, subtitle)) - return; + GValue *subsettings = ghb_dict_value_new(); + ghb_settings_set_int(subsettings, "SubtitleTrack", track); + ghb_settings_set_int(subsettings, "SubtitleSource", source); - ghb_add_subtitle_to_ui(ud, subtitle); - } + // Set default SRT settings + gchar *pref_lang, *dir, *filename; + + pref_lang = ghb_settings_get_string(settings, "PreferredLanguage"); + ghb_settings_set_string(subsettings, "SrtLanguage", pref_lang); + g_free(pref_lang); + + ghb_settings_set_string(subsettings, "SrtCodeset", "UTF-8"); + + dir = ghb_settings_get_string(settings, "SrtDir"); + filename = g_strdup_printf("%s/none", dir); + ghb_settings_set_string(subsettings, "SrtFile", filename); + g_free(dir); + g_free(filename); + + ghb_settings_set_int(subsettings, "SrtOffset", 0); + + subtitle_set_track_description(subsettings); + + if (!hb_subtitle_can_pass(source, mux)) + { + ghb_settings_set_boolean(subsettings, "SubtitleBurned", TRUE); + *burned = TRUE; + } + else + { + ghb_settings_set_boolean(subsettings, "SubtitleBurned", FALSE); } + if (track == -1) + { + // Foreign audio search "track" + ghb_settings_set_boolean(subsettings, "SubtitleForced", TRUE); + } + else + { + ghb_settings_set_boolean(subsettings, "SubtitleForced", FALSE); + } + if (default_track) + { + ghb_settings_set_boolean(subsettings, "SubtitleDefaultTrack", TRUE); + } + else + { + ghb_settings_set_boolean(subsettings, "SubtitleDefaultTrack", FALSE); + } + subtitle_add_to_settings(settings, subsettings); + + return subsettings; } void -ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings) +ghb_subtitle_title_change(signal_user_data_t *ud, gboolean show) +{ + GtkWidget *w = GHB_WIDGET(ud->builder, "subtitle_add"); + gtk_widget_set_sensitive(w, show); + w = GHB_WIDGET(ud->builder, "subtitle_add_all"); + gtk_widget_set_sensitive(w, show); + w = GHB_WIDGET(ud->builder, "subtitle_reset"); + gtk_widget_set_sensitive(w, show); +} + +void +ghb_set_pref_subtitle_settings(hb_title_t *title, GValue *settings) { gint track; - GHashTable *track_indices; - gchar *lang, *pref_lang = NULL; - const gchar *audio_lang; - gint foreign_lang_index = -1; - gboolean found_cc = FALSE; + gboolean *used; + const gchar *audio_lang, *pref_lang = NULL; + gboolean foreign_audio_search, foreign_audio_subs; + gboolean one_burned = FALSE; - const GValue *pref_subtitle; - GValue *subtitle; - gint count, ii, jj; - - g_debug("ghb_set_pref_subtitle %d", titleindex); + const GValue *lang_list; + gint lang_count, sub_count, ii; + int behavior, mux; + + behavior = ghb_settings_combo_int(settings, + "SubtitleTrackSelectionBehavior"); + // Clear the subtitle list + ghb_clear_subtitle_list_settings(settings); + + if (title == NULL) + { + // no source title + return; + } + sub_count = hb_list_count(title->list_subtitle); + if (sub_count == 0) + { + // No source subtitles + return; + } + + mux = ghb_settings_combo_int(settings, "FileFormat"); // Check to see if we need to add a subtitle track for foreign audio // language films. A subtitle track will be added if: @@ -370,560 +430,466 @@ ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings) // 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(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)) + audio_lang = ghb_get_user_audio_lang(settings, title, 0); + foreign_audio_search = ghb_settings_get_boolean( + settings, "SubtitleAddForeignAudioSearch"); + foreign_audio_subs = ghb_settings_get_boolean( + settings, "SubtitleAddForeignAudioSubtitle"); + lang_list = ghb_settings_get_value(settings, "SubtitleLanguageList"); + lang_count = ghb_array_len(lang_list); + if (lang_count > 0) { - g_free(pref_lang); - pref_lang = NULL; + GValue *glang = ghb_array_get_nth(lang_list, 0); + pref_lang = g_value_get_string(glang); } - track_indices = g_hash_table_new_full(g_str_hash, g_str_equal, - free_subtitle_key, free_subtitle_index_list); - - ghb_settings_set_int(settings, "SubtitleTrack", 0); - - // Clear the subtitle list - ghb_clear_subtitle_list_settings(settings); - if (titleindex < 0) + if (pref_lang == NULL || !strncmp(pref_lang, "und", 4)) { - return; + foreign_audio_search = foreign_audio_subs = FALSE; + pref_lang = NULL; } - // Find "best" subtitle based on subtitle preferences - pref_subtitle = ghb_settings_get_value(settings, "SubtitleList"); + used = g_malloc0(sub_count * sizeof(gboolean)); - count = ghb_array_len(pref_subtitle); - jj = 0; - for (ii = 0; ii < count; ii++) + if (foreign_audio_subs && + (audio_lang == NULL || strncmp(audio_lang, pref_lang, 4))) { - gint source; - gboolean force, burn; - - subtitle = ghb_array_get_nth(pref_subtitle, ii); - lang = ghb_settings_get_string(subtitle, "SubtitleLanguage"); - source = ghb_settings_get_int(subtitle, "SubtitleSource"); - burn = ghb_settings_get_boolean(subtitle, "SubtitleBurned"); - force = ghb_settings_get_boolean(subtitle, "SubtitleForced"); - // If there are multiple subtitles using the same language, then - // select sequential tracks for each. The hash keeps track - // of the tracks used for each language. - track = ghb_find_subtitle_track(titleindex, lang, burn, - force, source, track_indices); - g_free(lang); - if (track >= -1) + // Add preferred language subtitle since first audio track + // is foreign language. + foreign_audio_search = FALSE; + track = ghb_find_subtitle_track(title, pref_lang, 0); + if (track > 0) { - const gchar *track_lang; - GValue *dup = ghb_value_dup(subtitle); - track_lang = ghb_subtitle_track_lang(settings, track); - ghb_settings_set_int(dup, "SubtitleTrack", track); - if (foreign_lang_index < 0 && pref_lang != NULL && - strcmp(track_lang, pref_lang) == 0 && - !ghb_settings_get_boolean(dup, "SubtitleBurned")) - { - foreign_lang_index = jj; - ghb_settings_take_value(dup, "SubtitleForced", - ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(dup, "SubtitleDefaultTrack", - ghb_boolean_value_new(TRUE)); - } - 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_to_settings(settings, dup); - jj++; + used[track] = TRUE; + subtitle_add_track(settings, title, track, mux, + TRUE, FALSE, &one_burned); } } - if (foreign_lang_index < 0 && pref_lang != NULL) + + if (foreign_audio_search && + (audio_lang != NULL && !strncmp(audio_lang, pref_lang, 4))) { - // Subtitle for foreign language audio not added yet - GValue *subsettings; - gboolean burn; + // Add search for foreign audio segments + subtitle_add_track(settings, title, -1, mux, TRUE, FALSE, &one_burned); + } - track = ghb_find_subtitle_track(titleindex, pref_lang, FALSE, FALSE, PGSSUB, track_indices); - if (track >= -1) + if (behavior != 0) + { + // Find "best" subtitle based on subtitle preferences + for (ii = 0; ii < lang_count; ii++) { - int source; + GValue *glang = ghb_array_get_nth(lang_list, ii); + const gchar *lang = g_value_get_string(glang); - 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(subsettings, "SubtitleBurned", - ghb_boolean_value_new(burn)); - ghb_settings_take_value(subsettings, "SubtitleDefaultTrack", - ghb_boolean_value_new(TRUE)); - - ghb_add_subtitle_to_settings(settings, subsettings); - foreign_lang_index = jj; + int next_track = 0; + track = ghb_find_subtitle_track(title, lang, next_track); + while (track >= 0) + { + if (!used[track]) + { + used[track] = TRUE; + subtitle_add_track(settings, title, track, mux, + FALSE, FALSE, &one_burned); + } + next_track = track + 1; + if (behavior == 2) + { + track = ghb_find_subtitle_track(title, lang, next_track); + } + else + { + break; + } + } } } - if (foreign_lang_index >= 0) - { - GValue *subtitle_list; - gboolean burn, def; - - 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_settings(settings, foreign_lang_index); - if (def) - 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(settings, "AddCC") && !found_cc) + if (ghb_settings_get_boolean(settings, "SubtitleAddCC")) { - // Subtitle for foreign language audio not added yet - GValue *subsettings; + for (track = 0; track < sub_count; track++) + { + hb_subtitle_t *subtitle = hb_list_item(title->list_subtitle, track); + if (subtitle->source == CC608SUB || subtitle->source == CC708SUB) + break; + } - track = ghb_find_cc_track(titleindex); - if (track >= 0) + if (track < sub_count && !used[track]) { - int source; - 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(subsettings, "SubtitleBurned", - ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(subsettings, "SubtitleDefaultTrack", - ghb_boolean_value_new(FALSE)); - - ghb_add_subtitle_to_settings(settings, subsettings); - ghb_log("adding Closed Captions: %s", audio_lang); + used[track] = TRUE; + subtitle_add_track(settings, title, track, mux, + FALSE, FALSE, &one_burned); } } - if (pref_lang != NULL) - g_free(pref_lang); - g_hash_table_destroy(track_indices); + g_free(used); } 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) + hb_title_t *title; + int sub_count; + GtkWidget *widget; + + ghb_clear_subtitle_list_ui(ud->builder); + title = ghb_get_title_info(titleindex); + if (title == NULL) { - 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++) + sub_count = hb_list_count(title->list_subtitle); + if (sub_count == 0) + { + // No source subtitles + widget = GHB_WIDGET(ud->builder, "SubtitleSrtDisable"); + gtk_widget_set_sensitive(widget, FALSE); + } + else { - GValue *subtitle; - subtitle = ghb_array_get_nth(subtitle_list, ii); - ghb_add_subtitle_to_ui(ud, subtitle); + widget = GHB_WIDGET(ud->builder, "SubtitleSrtDisable"); + gtk_widget_set_sensitive(widget, TRUE); } + ghb_set_pref_subtitle_settings(title, ud->settings); + subtitle_refresh_list_ui(ud); } gint ghb_selected_subtitle_row(signal_user_data_t *ud) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeSelection *ts; + GtkTreeModel *tm; GtkTreeIter iter; gint *indices; gint row = -1; - + g_debug("ghb_selected_subtitle_row ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + if (gtk_tree_selection_get_selected(ts, &tm, &iter)) { // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); + tp = gtk_tree_model_get_path(tm, &iter); + indices = gtk_tree_path_get_indices(tp); row = indices[0]; - gtk_tree_path_free(treepath); + gtk_tree_path_free(tp); } return row; } -GValue* -ghb_selected_subtitle_settings(signal_user_data_t *ud) +static GValue* +subtitle_get_selected_settings(signal_user_data_t *ud, int *index) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeSelection *ts; + GtkTreeModel *tm; GtkTreeIter iter; gint *indices; gint row; - GValue *settings = NULL; + GValue *subsettings = NULL; const GValue *subtitle_list; - + g_debug("get_selected_settings ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + if (gtk_tree_selection_get_selected(ts, &tm, &iter)) { // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); + tp = gtk_tree_model_get_path(tm, &iter); + indices = gtk_tree_path_get_indices(tp); row = indices[0]; - gtk_tree_path_free(treepath); - // find subtitle settings + gtk_tree_path_free(tp); if (row < 0) return NULL; + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); if (row >= ghb_array_len(subtitle_list)) return NULL; - settings = ghb_array_get_nth(subtitle_list, row); + + subsettings = ghb_array_get_nth(subtitle_list, row); + if (index != NULL) + *index = row; } - return settings; + return subsettings; } -G_MODULE_EXPORT void -subtitle_forced_toggled_cb( - GtkCellRendererToggle *cell, - gchar *path, - signal_user_data_t *ud) +static void +subtitle_update_dialog_widgets(signal_user_data_t *ud, GValue *subsettings) { - GtkTreeView *tv; - GtkTreeModel *tm; - GtkTreeIter ti; - gboolean active; - gint row; - GtkTreePath *tp; - gint *indices; - GValue *subtitle_list, *settings; - gint source; + GtkWidget *widget; - g_debug("forced toggled"); - tp = gtk_tree_path_new_from_string (path); - tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - g_return_if_fail(tv != NULL); - tm = gtk_tree_view_get_model(tv); - g_return_if_fail(tm != NULL); - gtk_tree_model_get_iter(tm, &ti, tp); - gtk_tree_model_get(tm, &ti, 1, &active, -1); - active ^= 1; - - // Get the row number - indices = gtk_tree_path_get_indices (tp); - row = indices[0]; - gtk_tree_path_free(tp); + if (subsettings != NULL) + { + // Update widgets with subsettings + gchar *str, *track; + gint offset; + gboolean burn, force, def; - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + int mux = ghb_settings_combo_int(ud->settings, "FileFormat"); + int source = ghb_settings_get_int(subsettings, "SubtitleSource"); - if (row < 0 || row >= ghb_array_len(subtitle_list)) - return; + track = ghb_settings_get_string(subsettings, "SubtitleTrack"); + ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track)); + g_free(track); - settings = ghb_array_get_nth(subtitle_list, row); + str = ghb_settings_get_string(subsettings, "SrtLanguage"); + ghb_ui_update(ud, "SrtLanguage", ghb_string_value(str)); + g_free(str); - source = ghb_settings_get_int(settings, "SubtitleSource"); - if (!ghb_canForceSub(source)) - { - return; - } + str = ghb_settings_get_string(subsettings, "SrtCodeset"); + ghb_ui_update(ud, "SrtCodeset", ghb_string_value(str)); + g_free(str); - ghb_settings_set_boolean(settings, "SubtitleForced", active); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 1, active, -1); - ghb_live_reset(ud); -} + str = ghb_settings_get_string(subsettings, "SrtFile"); + ghb_ui_update(ud, "SrtFile", ghb_string_value(str)); + g_free(str); -G_MODULE_EXPORT void -subtitle_burned_toggled_cb( - GtkCellRendererToggle *cell, - gchar *path, - signal_user_data_t *ud) -{ - GtkTreeView *tv; - GtkTreeModel *tm; - GtkTreeIter ti; - GtkTreePath *tp; - gboolean active; - gint row; - gint *indices; - GValue *subtitle_list; - gint count; - GValue *settings; - gint source, mux; + offset = ghb_settings_get_int(subsettings, "SrtOffset"); + ghb_ui_update(ud, "SrtOffset", ghb_int_value(offset)); - g_debug("burned toggled"); - tp = gtk_tree_path_new_from_string (path); - tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - g_return_if_fail(tv != NULL); - tm = gtk_tree_view_get_model(tv); - g_return_if_fail(tm != NULL); - gtk_tree_model_get_iter(tm, &ti, tp); - gtk_tree_model_get(tm, &ti, 2, &active, -1); - active ^= 1; - - // Get the row number - indices = gtk_tree_path_get_indices (tp); - row = indices[0]; - gtk_tree_path_free(tp); + if (source == SRTSUB) + { + ghb_ui_update(ud, "SubtitleSrtEnable", ghb_boolean_value(TRUE)); + } + else + { + ghb_ui_update(ud, "SubtitleSrtDisable", ghb_boolean_value(TRUE)); + } - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - count = ghb_array_len(subtitle_list); - if (row < 0 || row >= count) - return; + widget = GHB_WIDGET(ud->builder, "SubtitleBurned"); + gtk_widget_set_sensitive(widget, + hb_subtitle_can_burn(source) && hb_subtitle_can_pass(source, mux)); + widget = GHB_WIDGET(ud->builder, "SubtitleForced"); + gtk_widget_set_sensitive(widget, hb_subtitle_can_force(source)); + widget = GHB_WIDGET(ud->builder, "SubtitleDefaultTrack"); + gtk_widget_set_sensitive(widget, hb_subtitle_can_pass(source, mux)); - settings = ghb_array_get_nth(subtitle_list, row); - source = ghb_settings_get_int(settings, "SubtitleSource"); - if (!ghb_canBurnSub(source)) - return; - mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - if (!active && !hb_subtitle_can_pass(source, mux)) - return; + burn = ghb_settings_get_int(subsettings, "SubtitleBurned"); + force = ghb_settings_get_int(subsettings, "SubtitleForced"); + def = ghb_settings_get_int(subsettings, "SubtitleDefaultTrack"); + + if (!hb_subtitle_can_burn(source)) + { + burn = FALSE; + } + if (!hb_subtitle_can_force(source)) + { + force = FALSE; + } + if (!hb_subtitle_can_pass(source, mux)) + { + def = FALSE; + burn = TRUE; + } + ghb_settings_set_boolean(subsettings, "SubtitleBurned", burn); + ghb_ui_update(ud, "SubtitleBurned", ghb_boolean_value(burn)); + ghb_settings_set_boolean(subsettings, "SubtitleForced", force); + ghb_ui_update(ud, "SubtitleForced", ghb_boolean_value(force)); + ghb_settings_set_boolean(subsettings, "SubtitleDefaultTrack", def); + ghb_ui_update(ud, "SubtitleDefaultTrack", ghb_boolean_value(def)); - ghb_settings_set_boolean(settings, "SubtitleBurned", active); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, active, -1); + if (source == SRTSUB) + { + // Hide regular subtitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_track_box"); + gtk_widget_hide(widget); - if (active) - { - ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", !active); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, !active, -1); + // Show SRT subitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_srt_grid"); + gtk_widget_show(widget); + } + else + { + // Hide SRT subitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_srt_grid"); + gtk_widget_hide(widget); + + // Show regular subtitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_track_box"); + gtk_widget_show(widget); + } } + else + { + // Hide SRT subitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_srt_grid"); + gtk_widget_hide(widget); - // Unburn the rest - if (active) - ghb_subtitle_exclusive_burn(ud, row); - ghb_live_reset(ud); + // Show regular subtitle widgets + widget = GHB_WIDGET(ud->builder, "subtitle_track_box"); + gtk_widget_show(widget); + } } -G_MODULE_EXPORT void -subtitle_default_toggled_cb( - GtkCellRendererToggle *cell, - gchar *path, - signal_user_data_t *ud) +static GValue* +subtitle_update_setting(GtkWidget *widget, signal_user_data_t *ud) { - GtkTreeView *tv; - GtkTreeModel *tm; - GtkTreeIter ti; - GtkTreePath *tp; - gboolean active; - gint row; - gint *indices; - GValue *subtitle_list; - gint count; - GValue *settings; - - g_debug("default toggled"); - tp = gtk_tree_path_new_from_string (path); - tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - g_return_if_fail(tv != NULL); - tm = gtk_tree_view_get_model(tv); - g_return_if_fail(tm != NULL); - gtk_tree_model_get_iter(tm, &ti, tp); - gtk_tree_model_get(tm, &ti, 3, &active, -1); - active ^= 1; - - // Get the row number - indices = gtk_tree_path_get_indices (tp); - row = indices[0]; - gtk_tree_path_free(tp); - - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - count = ghb_array_len(subtitle_list); - if (row < 0 || row >= count) - return; - - settings = ghb_array_get_nth(subtitle_list, row); + GValue *subsettings; - int source, mux; - source = ghb_settings_get_int(settings, "SubtitleSource"); - mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - if (active && !hb_subtitle_can_pass(source, mux)) - return; + ghb_widget_to_setting(ud->settings, widget); + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) + { + ghb_widget_to_setting(subsettings, widget); + ghb_subtitle_list_refresh_selected(ud); + ghb_live_reset(ud); + } + return subsettings; +} - ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", active); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 3, active, -1); +G_MODULE_EXPORT void +subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GValue *subsettings; - if (active) + g_debug("subtitle_track_changed_cb()"); + ghb_widget_to_setting(ud->settings, widget); + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { - ghb_settings_set_boolean(settings, "SubtitleBurned", !active); - gtk_list_store_set(GTK_LIST_STORE(tm), &ti, 2, !active, -1); + gint track, source; + + ghb_widget_to_setting(subsettings, widget); + track = ghb_settings_get_int(subsettings, "SubtitleTrack"); + source = ghb_subtitle_track_source(ud->settings, track); + ghb_settings_set_int(subsettings, "SubtitleSource", source); + subtitle_set_track_description(subsettings); + subtitle_update_dialog_widgets(ud, subsettings); + ghb_subtitle_list_refresh_selected(ud); + ghb_live_reset(ud); } - // allow only one default - ghb_subtitle_exclusive_default(ud, row); - ghb_live_reset(ud); } -void -ghb_subtitle_list_refresh_selected(signal_user_data_t *ud) +G_MODULE_EXPORT void +subtitle_forced_toggled_cb(GtkWidget *widget, signal_user_data_t *ud) { - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; - GtkTreeIter iter; - gint *indices; - gint row; - GValue *settings = NULL; - const GValue *subtitle_list; - gboolean allow_force = FALSE; - gboolean allow_burn = FALSE; - - g_debug("subtitle_list_refresh_selected ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) - { - gchar *track, *source; - gboolean forced, burned, def; - gchar *s_track; - gint offset = 0; - - // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); - row = indices[0]; - gtk_tree_path_free(treepath); - if (row < 0) return; - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - if (row >= ghb_array_len(subtitle_list)) - return; - settings = ghb_array_get_nth(subtitle_list, row); + subtitle_update_setting(widget, ud); +} - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); +G_MODULE_EXPORT void +subtitle_burned_toggled_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GValue *subsettings; + int index; - gint i_source; - i_source = ghb_settings_get_int(settings, "SubtitleSource"); - if (!ghb_canBurnSub(i_source)) + ghb_widget_to_setting(ud->settings, widget); + subsettings = subtitle_get_selected_settings(ud, &index); + if (subsettings != NULL) + { + ghb_widget_to_setting(subsettings, widget); + if (ghb_settings_get_boolean(subsettings, "SubtitleBurned")) { - burned = FALSE; - ghb_settings_set_boolean(settings, "SubtitleBurned", burned); + ghb_ui_update(ud, "SubtitleDefaultTrack", ghb_boolean_value(FALSE)); + ghb_subtitle_exclusive_burn(ud, index); } + ghb_subtitle_list_refresh_selected(ud); + ghb_live_reset(ud); + } +} - gint i_mux; - i_mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - if (!burned && !ghb_canPassSub(i_source, i_mux)) - { - burned = TRUE; - ghb_settings_set_boolean(settings, "SubtitleBurned", burned); - ghb_settings_set_boolean(settings, "SubtitleDefaultTrack", FALSE); - } +G_MODULE_EXPORT void +subtitle_default_toggled_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GValue *subsettings; + int index; - forced = ghb_settings_get_boolean(settings, "SubtitleForced"); - if (!ghb_canForceSub(i_source)) + ghb_widget_to_setting(ud->settings, widget); + subsettings = subtitle_get_selected_settings(ud, &index); + if (subsettings != NULL) + { + ghb_widget_to_setting(subsettings, widget); + if (ghb_settings_get_boolean(subsettings, "SubtitleDefaultTrack")) { - forced = FALSE; - ghb_settings_set_boolean(settings, "SubtitleForced", forced); + ghb_ui_update(ud, "SubtitleBurned", ghb_boolean_value(FALSE)); + ghb_subtitle_exclusive_default(ud, index); } + ghb_subtitle_list_refresh_selected(ud); + ghb_live_reset(ud); + } +} - def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack"); +G_MODULE_EXPORT void +subtitle_srt_radio_toggled_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GValue *subsettings; - if (i_source == SRTSUB) + ghb_widget_to_setting(ud->settings, widget); + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) + { + if (ghb_settings_get_boolean(ud->settings, "SubtitleSrtEnable")) { - const gchar *lang; - gchar *code; - - lang = ghb_settings_combo_option(settings, "SrtLanguage"); - code = ghb_settings_get_string(settings, "SrtCodeset"); - - s_track = ghb_settings_get_string(settings, "SrtFile"); - if (g_file_test(s_track, G_FILE_TEST_IS_REGULAR)) - { - gchar *basename; - - basename = g_path_get_basename(s_track); - track = g_strdup_printf("%s (%s)(SRT)(%s)", lang, code, basename); - source = g_strdup_printf("SRT (%s)", basename); - g_free(basename); - } - else - { - track = g_strdup_printf("%s (%s)(SRT)", lang, code); - source = g_strdup_printf("SRT (none)"); - } - g_free(code); - offset = ghb_settings_get_int(settings, "SrtOffset"); + ghb_settings_set_int(subsettings, "SubtitleSource", SRTSUB); } else { - track = g_strdup( - ghb_settings_combo_option(settings, "SubtitleTrack")); - source = g_strdup(hb_subsource_name(i_source)); - s_track = ghb_settings_get_string(settings, "SubtitleTrack"); - } - - if (ghb_canBurnSub(i_source)) - allow_burn = TRUE; - if (ghb_canForceSub(i_source)) - allow_force = TRUE; + int track, source; - gtk_list_store_set(GTK_LIST_STORE(store), &iter, - // These are displayed in list - 0, track, - 1, forced, - 2, burned, - 3, def, - 4, offset, - // These are used to set combo box values when a list item is selected - 5, s_track, - 6, i_source, - 7, allow_force, - 8, allow_burn, - -1); - g_free(track); - g_free(source); - g_free(s_track); - if (burned) - ghb_subtitle_exclusive_burn(ud, row); + track = ghb_settings_get_int(subsettings, "SubtitleTrack"); + source = ghb_subtitle_track_source(ud->settings, track); + ghb_settings_set_int(subsettings, "SubtitleSource", source); + } + subtitle_set_track_description(subsettings); + subtitle_update_dialog_widgets(ud, subsettings); + ghb_subtitle_list_refresh_selected(ud); + ghb_live_reset(ud); } } -G_MODULE_EXPORT void -subtitle_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +void +ghb_subtitle_list_refresh_selected(signal_user_data_t *ud) { - GValue *settings; + GtkTreeView *tv; + GtkTreeModel *tm; + GtkTreePath *tp; + GtkTreeSelection *ts; + GtkTreeIter ti; + gint *indices; + gint row; + GValue *subsettings = NULL; + const GValue *subtitle_list; - g_debug("subtitle_track_changed_cb ()"); - ghb_check_dependency(ud, widget, NULL); - ghb_widget_to_setting(ud->settings, widget); - settings = ghb_selected_subtitle_settings(ud); - if (settings != NULL) - { - const gchar *track, *lang; - gint tt, source; - - ghb_widget_to_setting(settings, widget); - 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->settings, tt); - ghb_settings_set_int(settings, "SubtitleSource", source); - lang = ghb_settings_combo_string(settings, "SubtitleTrack"); - ghb_settings_set_string(settings, "SubtitleLanguage", lang); - ghb_subtitle_list_refresh_selected(ud); - ghb_live_reset(ud); + g_debug("subtitle_list_refresh_selected()"); + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + if (gtk_tree_selection_get_selected(ts, &tm, &ti)) + { + // Get the row number + tp = gtk_tree_model_get_path(tm, &ti); + indices = gtk_tree_path_get_indices(tp); + row = indices[0]; + gtk_tree_path_free(tp); + if (row < 0) return; + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + if (row >= ghb_array_len(subtitle_list)) + return; + + subsettings = ghb_array_get_nth(subtitle_list, row); + subtitle_refresh_list_row_ui(tm, &ti, subsettings); } - ghb_live_reset(ud); +} + +void +ghb_subtitle_list_refresh_all(signal_user_data_t *ud) +{ + subtitle_refresh_list_ui(ud); } G_MODULE_EXPORT void srt_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { - GValue *settings; + GValue *subsettings; - g_debug("srt_changed_cb ()"); + g_debug("srt_changed_cb()"); ghb_check_dependency(ud, widget, NULL); ghb_widget_to_setting(ud->settings, widget); - settings = ghb_selected_subtitle_settings(ud); - if (settings != NULL) + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { - ghb_widget_to_setting(settings, widget); + ghb_widget_to_setting(subsettings, widget); + subtitle_set_track_description(subsettings); ghb_subtitle_list_refresh_selected(ud); - ghb_live_reset(ud); } } @@ -931,22 +897,23 @@ srt_changed_cb(GtkWidget *widget, signal_user_data_t *ud) G_MODULE_EXPORT void srt_file_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { - GValue *settings; + GValue *subsettings; - g_debug("srt_file_changed_cb ()"); + g_debug("srt_file_changed_cb()"); ghb_check_dependency(ud, widget, NULL); ghb_widget_to_setting(ud->settings, widget); - settings = ghb_selected_subtitle_settings(ud); - if (settings != NULL) + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { gchar *filename, *dirname; - ghb_widget_to_setting(settings, widget); + ghb_widget_to_setting(subsettings, widget); + subtitle_set_track_description(subsettings); ghb_subtitle_list_refresh_selected(ud); - ghb_live_reset(ud); - filename = ghb_settings_get_string(settings, "SrtFile"); + // Update SrtDir preference + filename = ghb_settings_get_string(subsettings, "SrtFile"); if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { ghb_settings_set_string(ud->settings, "SrtDir", filename); @@ -965,23 +932,18 @@ srt_file_changed_cb(GtkWidget *widget, signal_user_data_t *ud) G_MODULE_EXPORT void srt_lang_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { - GValue *settings; + GValue *subsettings; - g_debug("srt_lang_changed_cb ()"); + g_debug("srt_lang_changed_cb()"); ghb_check_dependency(ud, widget, NULL); ghb_widget_to_setting(ud->settings, widget); - settings = ghb_selected_subtitle_settings(ud); - if (settings != NULL) + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { - const gchar *lang; - - ghb_widget_to_setting(settings, widget); + ghb_widget_to_setting(subsettings, widget); + subtitle_set_track_description(subsettings); ghb_subtitle_list_refresh_selected(ud); - ghb_live_reset(ud); - - lang = ghb_settings_combo_option(settings, "SrtLanguage"); - ghb_settings_set_string(settings, "SubtitleTrackDescription", lang); } } @@ -990,7 +952,6 @@ ghb_clear_subtitle_list_settings(GValue *settings) { GValue *subtitle_list; - g_debug("clear_subtitle_list ()"); subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); if (subtitle_list == NULL) { @@ -1002,415 +963,239 @@ ghb_clear_subtitle_list_settings(GValue *settings) } static void -ghb_clear_subtitle_list(signal_user_data_t *ud) +ghb_clear_subtitle_list_ui(GtkBuilder *builder) { - 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); -} + GtkTreeView *tv; + GtkTreeStore *ts; -static void -add_to_subtitle_list( - signal_user_data_t *ud, - GValue *settings) -{ - GtkTreeView *treeview; - GtkTreeIter iter; - GtkListStore *store; - GtkTreeSelection *selection; - const gchar *track; - gboolean forced, burned, def; - gchar *s_track; - gint i_source; - gboolean allow_force = FALSE; - gboolean allow_burn = FALSE; - - g_debug("add_to_subtitle_list ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); - - track = ghb_settings_combo_option(settings, "SubtitleTrack"); - forced = ghb_settings_get_boolean(settings, "SubtitleForced"); - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); - def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack"); - - s_track = ghb_settings_get_string(settings, "SubtitleTrack"); - i_source = ghb_settings_get_int(settings, "SubtitleSource"); - - if (ghb_canBurnSub(i_source)) - allow_burn = TRUE; - if (ghb_canForceSub(i_source)) - allow_force = TRUE; - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - // These are displayed in list - 0, track, - 1, forced, - 2, burned, - 3, def, - // These are used to set combo box values when a list item is selected - 5, s_track, - 6, i_source, - 7, allow_force, - 8, allow_burn, - 9, FALSE, - -1); - gtk_tree_selection_select_iter(selection, &iter); - g_free(s_track); + tv = GTK_TREE_VIEW(GHB_WIDGET(builder, "subtitle_list")); + ts = GTK_TREE_STORE(gtk_tree_view_get_model(tv)); + gtk_tree_store_clear(ts); } static void -add_to_srt_list( - signal_user_data_t *ud, - GValue *settings) +add_to_subtitle_list_ui(signal_user_data_t *ud, GValue *subsettings) { - GtkTreeView *treeview; - GtkTreeIter iter; - GtkListStore *store; - GtkTreeSelection *selection; - const gchar *lang; - gboolean forced, burned, def; - gchar *filename, *code, *track, *source; - gint i_source, offset; - - g_debug("add_to_srt_list ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); - - lang = ghb_settings_combo_option(settings, "SrtLanguage"); - code = ghb_settings_get_string(settings, "SrtCodeset"); - forced = FALSE; - burned = FALSE; - def = ghb_settings_get_boolean(settings, "SubtitleDefaultTrack"); - - filename = ghb_settings_get_string(settings, "SrtFile"); - if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) - { - gchar *basename; - - basename = g_path_get_basename(filename); - track = g_strdup_printf("%s (%s)(SRT)(%s)", lang, code, basename); - source = g_strdup_printf("SRT (%s)", basename); - g_free(basename); - } - else - { - track = g_strdup_printf("%s (%s)(SRT)", lang, code); - source = g_strdup_printf("SRT (none)"); - } - i_source = SRTSUB; - offset = ghb_settings_get_int(settings, "SrtOffset"); + GtkTreeView *tv; + GtkTreeIter ti; + GtkTreeModel *tm; + GtkTreeSelection *ts; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - // These are displayed in list - 0, track, - 1, forced, - 2, burned, - 3, def, - 4, offset, - // These are used to set combo box values when a list item is selected - 5, filename, - 6, i_source, - 7, FALSE, - 8, FALSE, - 9, TRUE, - -1); - gtk_tree_selection_select_iter(selection, &iter); - g_free(code); - g_free(track); - g_free(filename); - g_free(source); + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + tm = gtk_tree_view_get_model(tv); + + gtk_tree_store_append(GTK_TREE_STORE(tm), &ti, NULL); + subtitle_refresh_list_row_ui(tm, &ti, subsettings); + + gtk_tree_selection_select_iter(ts, &ti); } G_MODULE_EXPORT void -subtitle_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud) +subtitle_list_selection_changed_cb(GtkTreeSelection *ts, signal_user_data_t *ud) { - GtkTreeModel *store; + GtkTreeModel *tm; GtkTreeIter iter; - GtkWidget *widget; - - g_debug("subtitle_list_selection_changed_cb ()"); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) - { - gint source; - GtkTreePath *treepath; - gint *indices, row; - GValue *subtitle_list, *settings; + GValue *subsettings = NULL; + int row; - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); - row = indices[0]; - gtk_tree_path_free(treepath); - - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - if (row >= ghb_array_len(subtitle_list)) - return; - - settings = ghb_array_get_nth(subtitle_list, row); + g_debug("subtitle_list_selection_changed_cb()"); + if (gtk_tree_selection_get_selected(ts, &tm, &iter)) + { + GtkTreeIter piter; - source = ghb_settings_get_int(settings, "SubtitleSource"); - if (source == SRTSUB) + if (gtk_tree_model_iter_parent(tm, &piter, &iter)) { - gchar *str; - gint offset; - - str = ghb_settings_get_string(settings, "SrtLanguage"); - ghb_ui_update(ud, "SrtLanguage", ghb_string_value(str)); - g_free(str); - - str = ghb_settings_get_string(settings, "SrtCodeset"); - ghb_ui_update(ud, "SrtCodeset", ghb_string_value(str)); - g_free(str); - - str = ghb_settings_get_string(settings, "SrtFile"); - ghb_ui_update(ud, "SrtFile", ghb_string_value(str)); - g_free(str); - - offset = ghb_settings_get_int(settings, "SrtOffset"); - ghb_ui_update(ud, "SrtOffset", ghb_int_value(offset)); - - widget = GHB_WIDGET(ud->builder, "subtitle_track_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SubtitleTrack"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_lang_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "srt_code_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "srt_file_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "srt_offset_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SrtLanguage"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SrtCodeset"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SrtFile"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SrtOffset"); - gtk_widget_show(widget); + GtkTreePath *path; + GtkTreeView *tv; + + gtk_tree_selection_select_iter(ts, &piter); + path = gtk_tree_model_get_path(tm, &piter); + tv = gtk_tree_selection_get_tree_view(ts); + // Make the parent visible in scroll window if it is not. + gtk_tree_view_scroll_to_cell(tv, path, NULL, FALSE, 0, 0); + gtk_tree_path_free(path); + return; } - else - { - gchar *track; - track = ghb_settings_get_string(settings, "SubtitleTrack"); - ghb_ui_update(ud, "SubtitleTrack", ghb_string_value(track)); - g_free(track); + GtkTreePath *tp; + gint *indices; + GValue *subtitle_list; - widget = GHB_WIDGET(ud->builder, "srt_lang_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_code_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_file_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_offset_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtLanguage"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtCodeset"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtFile"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtOffset"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "subtitle_track_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SubtitleTrack"); - gtk_widget_show(widget); - } - widget = GHB_WIDGET (ud->builder, "subtitle_remove"); - gtk_widget_set_sensitive(widget, TRUE); + tp = gtk_tree_model_get_path(tm, &iter); + indices = gtk_tree_path_get_indices(tp); + row = indices[0]; + gtk_tree_path_free(tp); + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + if (row >= 0 && row < ghb_array_len(subtitle_list)) + subsettings = ghb_array_get_nth(subtitle_list, row); } - else + subtitle_update_dialog_widgets(ud, subsettings); + if (subsettings) { - widget = GHB_WIDGET(ud->builder, "srt_lang_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_code_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_file_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "srt_offset_label"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtLanguage"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtCodeset"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtFile"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "SrtOffset"); - gtk_widget_hide(widget); - widget = GHB_WIDGET(ud->builder, "subtitle_track_label"); - gtk_widget_show(widget); - widget = GHB_WIDGET(ud->builder, "SubtitleTrack"); - gtk_widget_show(widget); + if (ghb_settings_get_boolean(subsettings, "SubtitleBurned")) + { + ghb_subtitle_exclusive_burn(ud, row); + } } } -G_MODULE_EXPORT void -srt_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +static gboolean subtitle_is_one_burned(GValue *settings) { - // Add the current subtitle settings to the list. - GValue *settings; - gchar *dir, *filename, *lang; - - g_debug("subtitle_add_clicked_cb ()"); - - settings = ghb_dict_value_new(); - ghb_settings_set_int(settings, "SubtitleSource", SRTSUB); - lang = ghb_settings_get_string(ud->settings, "PreferredLanguage"); - ghb_settings_set_string(settings, "SrtLanguage", lang); - g_free(lang); - ghb_settings_set_string(settings, "SrtCodeset", "UTF-8"); - - dir = ghb_settings_get_string(ud->settings, "SrtDir"); - filename = g_strdup_printf("%s/none", dir); - ghb_settings_set_string(settings, "SrtFile", filename); - g_free(dir); - g_free(filename); + GValue *subtitle_list, *subsettings; + int count, ii; - ghb_settings_set_int(settings, "SrtOffset", 0); - ghb_settings_take_value(settings, "SubtitleDefaultTrack", - ghb_boolean_value_new(FALSE)); + subtitle_list = ghb_settings_get_value(settings, "subtitle_list"); + if (subtitle_list == NULL) + return FALSE; - ghb_add_srt(ud, settings); + count = ghb_array_len(subtitle_list); + for (ii = 0; ii < count; ii++) + { + subsettings = ghb_array_get_nth(subtitle_list, ii); + if (ghb_settings_get_boolean(subsettings, "SubtitleBurned")) + { + return TRUE; + } + } + return FALSE; } G_MODULE_EXPORT void subtitle_add_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { // Add the current subtitle settings to the list. - GValue *settings; - gboolean burned = FALSE; - gint track, source, mux; - - g_debug("subtitle_add_clicked_cb ()"); - - track = ghb_settings_get_int(ud->settings, "SubtitleTrack"); + GValue *subsettings, *backup; + gboolean one_burned; + gint track, mux; + + hb_title_t *title; + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + title = ghb_get_title_info(titleindex); + if (title == NULL) + { + return; + } - settings = ghb_dict_value_new(); - ghb_settings_set_int(settings, "SubtitleTrack", track); - source = ghb_subtitle_track_source(ud->settings, track); + // Back up settings in case we need to revert. + backup = ghb_value_dup( + ghb_settings_get_value(ud->settings, "subtitle_list")); - // Initialize to passthru if possible, else burn + one_burned = subtitle_is_one_burned(ud->settings); mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - burned = !hb_subtitle_can_pass(source, mux); - - ghb_settings_set_int(settings, "SubtitleSource", source); - ghb_settings_take_value(settings, "SubtitleForced", - ghb_boolean_value_new(FALSE)); - ghb_settings_take_value(settings, "SubtitleBurned", - ghb_boolean_value_new(burned)); - ghb_settings_take_value(settings, "SubtitleDefaultTrack", - ghb_boolean_value_new(FALSE)); - if (!ghb_add_subtitle_to_settings(ud->settings, settings)) - return; - - ghb_add_subtitle_to_ui(ud, settings); -} - -G_MODULE_EXPORT void -subtitle_remove_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) -{ - GtkTreeView *treeview; - GtkTreePath *treepath; - GtkTreeSelection *selection; - GtkTreeModel *store; - GtkTreeIter iter, nextIter; - gint *indices; - gint row; - GValue *subtitle_list; + int count = hb_list_count(title->list_subtitle); + for (subsettings = NULL, track = 0; + subsettings == NULL && track < count; track++) + { + subsettings = subtitle_add_track(ud->settings, title, track, mux, + FALSE, FALSE, &one_burned); + } + if (subsettings == NULL) + { + subsettings = subtitle_add_track(ud->settings, title, 0, mux, + FALSE, TRUE, &one_burned); + } + ghb_add_subtitle_to_ui(ud, subsettings); - g_debug("subtitle_remove_clicked_cb ()"); - treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected(selection, &store, &iter)) + if (subsettings != NULL) { - nextIter = iter; - if (!gtk_tree_model_iter_next(store, &nextIter)) + // Pop up the edit dialog + GtkResponseType response; + GtkWidget *dialog = GHB_WIDGET(ud->builder, "subtitle_dialog"); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response != GTK_RESPONSE_OK) { - nextIter = iter; - if (gtk_tree_model_get_iter_first(store, &nextIter)) + ghb_settings_take_value(ud->settings, "subtitle_list", backup); + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { - gtk_tree_selection_select_iter (selection, &nextIter); + subtitle_update_dialog_widgets(ud, subsettings); } + subtitle_refresh_list_ui(ud); } else { - gtk_tree_selection_select_iter (selection, &nextIter); + ghb_value_free(backup); } + } +} - // Get the row number - treepath = gtk_tree_model_get_path (store, &iter); - indices = gtk_tree_path_get_indices (treepath); - row = indices[0]; - gtk_tree_path_free(treepath); - if (row < 0) return; +G_MODULE_EXPORT void +subtitle_add_all_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + // Add the current subtitle settings to the list. + gboolean one_burned = FALSE; + gint track, mux; - subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); - if (row >= ghb_array_len(subtitle_list)) - return; + hb_title_t *title; + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + title = ghb_get_title_info(titleindex); + if (title == NULL) + { + return; + } - // Update our settings list before removing the row from the - // treeview. Removing from the treeview sometimes provokes an - // immediate selection change, so the list needs to be up to date - // when this happens. - GValue *old = ghb_array_get_nth(subtitle_list, row); - ghb_value_free(old); - ghb_array_remove(subtitle_list, row); + ghb_clear_subtitle_list_settings(ud->settings); + ghb_clear_subtitle_list_ui(ud->builder); - // Remove the selected item - gtk_list_store_remove (GTK_LIST_STORE(store), &iter); - // remove from subtitle settings list - widget = GHB_WIDGET (ud->builder, "subtitle_add"); - gtk_widget_set_sensitive(widget, TRUE); - widget = GHB_WIDGET (ud->builder, "srt_add"); - gtk_widget_set_sensitive(widget, TRUE); + mux = ghb_settings_combo_int(ud->settings, "FileFormat"); - ghb_live_reset(ud); + int count = hb_list_count(title->list_subtitle); + for (track = 0; track < count; track++) + { + subtitle_add_track(ud->settings, title, track, mux, + FALSE, FALSE, &one_burned); } + subtitle_refresh_list_ui(ud); + ghb_live_reset(ud); +} + +G_MODULE_EXPORT void +subtitle_reset_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) +{ + int titleindex = ghb_settings_combo_int(ud->settings, "title"); + ghb_set_pref_subtitle(titleindex, ud); } void ghb_subtitle_prune(signal_user_data_t *ud) { - GtkTreeView *tv; GValue *subtitle_list; - gint count, ii; - gint first_track = 0, one_burned = 0; + GValue *subsettings; + gint ii; + gboolean one_burned = FALSE; subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); if (subtitle_list == NULL) return; - count = ghb_array_len(subtitle_list); - tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); - g_return_if_fail(tv != NULL); - for (ii = count-1; ii >= 0; ii--) + int mux = ghb_settings_combo_int(ud->settings, "FileFormat"); + + for (ii = 0; ii < ghb_array_len(subtitle_list); ) { gboolean burned; - GValue *settings; + int source; - settings = ghb_array_get_nth(subtitle_list, ii); - burned = ghb_settings_get_boolean(settings, "SubtitleBurned"); - if (burned) + subsettings = ghb_array_get_nth(subtitle_list, ii); + burned = ghb_settings_get_boolean(subsettings, "SubtitleBurned"); + source = ghb_settings_get_boolean(subsettings, "SubtitleSource"); + burned = burned || !hb_subtitle_can_pass(source, mux); + if (burned && one_burned) { - first_track = ii; - one_burned++; + ghb_array_remove(subtitle_list, ii); + continue; } + one_burned = one_burned || burned; + ghb_settings_set_boolean(subsettings, "SubtitleBurned", burned); + ii++; } - if (one_burned) + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) { - ghb_subtitle_exclusive_burn(ud, first_track); + subtitle_update_dialog_widgets(ud, subsettings); } } @@ -1421,10 +1206,10 @@ ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings) GValue *subtitle; gint count, ii; gint titleindex; - + g_debug("ghb_reset_subtitles"); ghb_clear_subtitle_list_settings(ud->settings); - ghb_clear_subtitle_list(ud); + ghb_clear_subtitle_list_ui(ud->builder); titleindex = ghb_settings_combo_int(ud->settings, "title"); if (titleindex < 0) return; @@ -1433,18 +1218,335 @@ ghb_reset_subtitles(signal_user_data_t *ud, GValue *settings) count = ghb_array_len(slist); for (ii = 0; ii < count; ii++) { - int source; - subtitle = ghb_value_dup(ghb_array_get_nth(slist, ii)); - source = ghb_settings_get_int(subtitle, "SubtitleSource"); - if (source == SRTSUB) - ghb_add_srt(ud, subtitle); + subtitle_add_to_settings(ud->settings, subtitle); + } + subtitle_refresh_list_ui(ud); +} + +G_MODULE_EXPORT void +subtitle_def_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + ghb_clear_presets_selection(ud); +} + +static void +subtitle_update_pref_lang(signal_user_data_t *ud, const iso639_lang_t *lang) +{ + GtkLabel *label; + GtkButton *button; + gchar *str; + const char * name = _("None"); + const char * code = "und"; + + label = GTK_LABEL(GHB_WIDGET(ud->builder, "subtitle_preferred_language")); + if (lang != NULL) + { + code = lang->iso639_2; + if (strncmp(code, "und", 4)) + { + name = lang->native_name && lang->native_name[0] ? + lang->native_name : lang->eng_name; + } + } + + str = g_strdup_printf(_("Preferred Language: %s"), name); + gtk_label_set_text(label, str); + g_free(str); + + ghb_settings_set_string(ud->settings, "PreferredLanguage", code); + + button = GTK_BUTTON(GHB_WIDGET(ud->builder, + "SubtitleAddForeignAudioSubtitle")); + str = g_strdup_printf(_("Add %s subtitle track if default audio is not %s"), + name, name); + gtk_button_set_label(button, str); + g_free(str); + + // If there is no preferred language, hide options that require + // a preferred language to be set. + gboolean visible = !(lang == NULL || !strncmp(code, "und", 4)); + gtk_widget_set_visible(GTK_WIDGET(button), visible); + button = GTK_BUTTON(GHB_WIDGET(ud->builder, + "SubtitleAddForeignAudioSearch")); + gtk_widget_set_visible(GTK_WIDGET(button), visible); +} + +G_MODULE_EXPORT void +subtitle_add_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + GtkListBox *avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); + GtkListBox *selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); + GtkListBoxRow *row; + GtkWidget *label; + + row = gtk_list_box_get_selected_row(avail); + if (row != NULL) + { + int idx; + const iso639_lang_t *lang; + GValue *glang, *lang_list; + + // Remove from UI available language list box + label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + // Add to UI selected language list box + gtk_list_box_insert(selected, label, -1); + + // Add to preset language list + idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + lang = ghb_iso639_lookup_by_int(idx); + glang = ghb_string_value_new(lang->iso639_2); + lang_list = ghb_settings_get_value(ud->settings, "SubtitleLanguageList"); + if (ghb_array_len(lang_list) == 0) + { + subtitle_update_pref_lang(ud, lang); + } + ghb_array_append(lang_list, glang); + ghb_clear_presets_selection(ud); + } +} + +G_MODULE_EXPORT void +subtitle_remove_lang_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + + GtkListBox *avail, *selected; + GtkListBoxRow *row; + GtkWidget *label; + + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); + row = gtk_list_box_get_selected_row(selected); + if (row != NULL) + { + gint index; + GValue *lang_list; + + index = gtk_list_box_row_get_index(row); + + // Remove from UI selected language list box + label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + // Add to UI available language list box + gtk_list_box_insert(avail, label, idx); + + // Remove from preset language list + lang_list = ghb_settings_get_value(ud->settings, "SubtitleLanguageList"); + ghb_array_remove(lang_list, index); + ghb_clear_presets_selection(ud); + + if (ghb_array_len(lang_list) > 0) + { + const iso639_lang_t *lang; + GValue *entry = ghb_array_get_nth(lang_list, 0); + lang = ghb_iso639_lookup_by_int(ghb_lookup_audio_lang(entry)); + subtitle_update_pref_lang(ud, lang); + } + else + { + subtitle_update_pref_lang(ud, NULL); + } + } +} + +static void subtitle_def_lang_list_clear_cb(GtkWidget *row, gpointer data) +{ + GtkListBox *avail = (GtkListBox*)data; + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + int idx = (intptr_t)g_object_get_data(G_OBJECT(label), "lang_idx"); + gtk_list_box_insert(avail, label, idx); +} + +static void subtitle_def_selected_lang_list_clear(signal_user_data_t *ud) +{ + GtkListBox *avail, *selected; + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); + gtk_container_foreach(GTK_CONTAINER(selected), + subtitle_def_lang_list_clear_cb, (gpointer)avail); +} + +static void subtitle_def_lang_list_init(signal_user_data_t *ud) +{ + GValue *lang_list; + + // Clear selected languages. + subtitle_def_selected_lang_list_clear(ud); + + lang_list = ghb_settings_get_value(ud->settings, "SubtitleLanguageList"); + if (lang_list == NULL) + { + lang_list = ghb_array_value_new(8); + ghb_settings_set_value(ud->settings, "SubtitleLanguageList", lang_list); + } + + int ii, count; + count = ghb_array_len(lang_list); + for (ii = 0; ii < count; ) + { + GValue *lang_val = ghb_array_get_nth(lang_list, ii); + int idx = ghb_lookup_audio_lang(lang_val); + if (ii == 0) + { + const iso639_lang_t *lang; + lang = ghb_iso639_lookup_by_int(idx); + subtitle_update_pref_lang(ud, lang); + } + + GtkListBox *avail, *selected; + GtkListBoxRow *row; + avail = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); + selected = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_selected_lang")); + row = ghb_find_lang_row(avail, idx); + if (row) + { + GtkWidget *label = gtk_bin_get_child(GTK_BIN(row)); + g_object_ref(G_OBJECT(label)); + gtk_widget_destroy(GTK_WIDGET(row)); + gtk_widget_show(label); + gtk_list_box_insert(selected, label, -1); + ii++; + } + else + { + // Error in list. Probably duplicate languages. Remove + // this item from the list. + ghb_array_remove(lang_list, ii); + count--; + } + } + if (count == 0) + { + subtitle_update_pref_lang(ud, NULL); + } +} + +void ghb_subtitle_def_settings_init(signal_user_data_t *ud) +{ + subtitle_def_lang_list_init(ud); +} + +void ghb_init_subtitle_defaults_ui(signal_user_data_t *ud) +{ + GtkListBox *list_box; + + list_box = GTK_LIST_BOX(GHB_WIDGET(ud->builder, "subtitle_avail_lang")); + ghb_init_lang_list_box(list_box); +} + +G_MODULE_EXPORT void +subtitle_edit_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) +{ + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeModel *tm; + GtkTreeSelection *ts; + GtkTreeIter ti; + + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + tm = gtk_tree_view_get_model(tv); + tp = gtk_tree_path_new_from_string (path); + if (gtk_tree_path_get_depth(tp) > 1) return; + if (gtk_tree_model_get_iter(tm, &ti, tp)) + { + GValue *subsettings, *backup; + + gtk_tree_selection_select_iter(ts, &ti); + + // Back up settings in case we need to revert. + backup = ghb_value_dup( + ghb_settings_get_value(ud->settings, "subtitle_list")); + + // Pop up the edit dialog + GtkResponseType response; + GtkWidget *dialog = GHB_WIDGET(ud->builder, "subtitle_dialog"); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + if (response != GTK_RESPONSE_OK) + { + ghb_settings_take_value(ud->settings, "subtitle_list", backup); + subsettings = subtitle_get_selected_settings(ud, NULL); + if (subsettings != NULL) + { + subtitle_update_dialog_widgets(ud, subsettings); + } + subtitle_refresh_list_ui(ud); + } + else + { + ghb_value_free(backup); + } + } +} + +G_MODULE_EXPORT void +subtitle_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud) +{ + GtkTreeView *tv; + GtkTreePath *tp; + GtkTreeModel *tm; + GtkTreeSelection *ts; + GtkTreeIter ti, nextIter; + gint row; + gint *indices; + GValue *subtitle_list; + + tv = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "subtitle_list")); + ts = gtk_tree_view_get_selection(tv); + tm = gtk_tree_view_get_model(tv); + tp = gtk_tree_path_new_from_string (path); + if (gtk_tree_path_get_depth(tp) > 1) return; + if (gtk_tree_model_get_iter(tm, &ti, tp)) + { + nextIter = ti; + if (!gtk_tree_model_iter_next(tm, &nextIter)) + { + nextIter = ti; + if (gtk_tree_model_get_iter_first(tm, &nextIter)) + { + gtk_tree_selection_select_iter(ts, &nextIter); + } + } else { - if (!ghb_add_subtitle_to_settings(ud->settings, subtitle)) - return; - ghb_add_subtitle_to_ui(ud, subtitle); + gtk_tree_selection_select_iter(ts, &nextIter); + } + + subtitle_list = ghb_settings_get_value(ud->settings, "subtitle_list"); + + // Get the row number + indices = gtk_tree_path_get_indices (tp); + row = indices[0]; + if (row < 0 || row >= ghb_array_len(subtitle_list)) + { + gtk_tree_path_free(tp); + return; } + + // Update our settings list before removing the row from the + // treeview. Removing from the treeview sometimes provokes an + // immediate selection change, so the list needs to be up to date + // when this happens. + GValue *old = ghb_array_get_nth(subtitle_list, row); + ghb_value_free(old); + ghb_array_remove(subtitle_list, row); + + // Remove the selected item + gtk_tree_store_remove(GTK_TREE_STORE(tm), &ti); + + ghb_live_reset(ud); } + gtk_tree_path_free(tp); } diff --git a/gtk/src/subtitlehandler.h b/gtk/src/subtitlehandler.h index b63b169c6..e1f261d3c 100644 --- a/gtk/src/subtitlehandler.h +++ b/gtk/src/subtitlehandler.h @@ -28,16 +28,14 @@ #include "settings.h" void ghb_set_pref_subtitle(gint titleindex, signal_user_data_t *ud); -void ghb_set_pref_subtitle_settings(gint titleindex, GValue *settings); +void ghb_set_pref_subtitle_settings(hb_title_t *title, 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_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); -gboolean ghb_canBurnSub(int source); -gboolean ghb_canForceSub(int source); -gboolean ghb_canPassSub(int source, int mux); void ghb_subtitle_list_refresh_selected(signal_user_data_t *ud); +void ghb_subtitle_list_refresh_all(signal_user_data_t *ud); +void ghb_init_subtitle_defaults_ui(signal_user_data_t *ud); +void ghb_subtitle_def_settings_init(signal_user_data_t *ud); +void ghb_subtitle_title_change(signal_user_data_t *ud, gboolean show); #endif // _SUBTITLEHANDLER_H_ diff --git a/gtk/src/values.c b/gtk/src/values.c index 149d371a8..2b253c0e6 100644 --- a/gtk/src/values.c +++ b/gtk/src/values.c @@ -14,6 +14,7 @@ #include <glib.h> #include <glib-object.h> +#include <stdio.h> #include <string.h> #include <inttypes.h> #include "values.h" diff --git a/gtk/src/widgetdeps.c b/gtk/src/widgetdeps.c index f2c7c82ae..059390d7b 100644 --- a/gtk/src/widgetdeps.c +++ b/gtk/src/widgetdeps.c @@ -57,11 +57,11 @@ static dependency_t dep_map[] = {"VideoEncoder", "x264_tab", "x264", FALSE, FALSE}, {"VideoEncoder", "x264_tab_label", "x264", FALSE, FALSE}, {"VideoEncoder", "Mp4iPodCompatible", "x264", FALSE, FALSE}, - {"AudioEncoderActual", "AudioBitrate", "ac3|dts", TRUE, FALSE}, - {"AudioEncoderActual", "AudioSamplerate", "ac3|dts", TRUE, FALSE}, - {"AudioEncoderActual", "AudioMixdown", "ac3|dts", TRUE, FALSE}, - {"AudioEncoderActual", "AudioTrackDRCSlider", "ac3|dts", TRUE, FALSE}, - {"AudioEncoderActual", "drc_label", "ac3|dts", TRUE, FALSE}, + {"AudioEncoder", "AudioBitrate", "ac3|dts", TRUE, FALSE}, + {"AudioEncoder", "AudioSamplerate", "ac3|dts", TRUE, FALSE}, + {"AudioEncoder", "AudioMixdown", "ac3|dts", TRUE, FALSE}, + {"AudioEncoder", "AudioTrackDRCSlider", "ac3|dts", TRUE, FALSE}, + {"AudioEncoder", "drc_label", "ac3|dts", TRUE, FALSE}, {"x264_bframes", "x264_bpyramid", "<2", TRUE, FALSE}, {"x264_bframes", "x264_direct", "0", TRUE, FALSE}, {"x264_bframes", "x264_b_adapt", "0", TRUE, FALSE}, |