diff options
author | jstebbins <[email protected]> | 2014-02-18 16:02:14 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2014-02-18 16:02:14 +0000 |
commit | b3e905dde9dacd4129c05440cedbe5a1366d0243 (patch) | |
tree | 420015a42c464390a90c3f9c94c268a3d0ea5bd3 /gtk/src | |
parent | 52036382899171921343e10053fa3adaedcb19d2 (diff) |
LinGui: Audio and subtitle UI rework.
Adds new tabs for audio and subtitle defaults (presets).
"Audio" and "Subtitle" tabs renamed to "Audio List" and "Subtitle List"
New Preset Keys:
AudioLanguageList - array of strings
List of languages that will be used to generate the output
audio tracks for a job.
Values: preset - UI display
iso639_2 codes - native_name if not NULL, else eng_name
SubtitleLanguageList - array of strings
List of languages that will be used to generate the output
subtitle tracks for a job.
Values: preset - UI display
iso639_2 codes - native_name if not NULL, else eng_name
AudioTrackSelectionBehavior - string
Defines how source tracks will be selected when generating
the audio list for a job.
Values: preset - UI display
none - None
first - First Matching Selected Languages
all - All Matching Selected Languages
SubtitleTrackSelectionBehavior - string
Defines how source tracks will be selected when generating
the subtitle list for a job.
Values: preset - UI display
none - None
first - First Matching Selected Languages
all - All Matching Selected Languages
SubtitleAddCC - boolean
Add Closed Caption track to subtitle list if available
SubtitleAddForeignAudioSearch - boolean
Add Foreign audio search pass to job if a default subtitle
language is set (i.e. SubtitleLanguageList is not empty and
first entry is not "Any") and default audio track language
matches subtitle preferred language.
SubtitleAddForeignAudioSubtitle - boolean
Add preferred language subtitle track if the default subtitle
language is set (i.e. SubtitleLanguageList is not empty and
first entry is not "Any") and default audio track language
does not match the preferred subtitle language.
Removed Preset Keys:
AudioTrack
SubtitleList - I think only the LinGui had this key.
Note that the remaining keys in the pre-existing AudioList are reused
and map to the "Audio Encoder Settings" on the "Audio Defaults" tab.
They used to map to the entries in the list on the old "Audio" tab.
The old "Audio" tab is now the "Audio List" tab. Nothing in the "Audio
List"
tab map to preset values in the new design. The contents of this tab is
strictly for use in the encode job. Ditto for "Subtitle Defaults" and
"Subtitle List".
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6040 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src')
-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}, |