From 84b114026ce65ce0bc0798c07ef8be2e08e4d706 Mon Sep 17 00:00:00 2001 From: Klaas de Waal Date: Sat, 10 Feb 2024 18:18:56 +0100 Subject: [PATCH] Add "Audio Language" selection Add a selection for the preferred audio language. The existing "Language" setting is used for the menu language but was until this fix also used as preferred audio language. When there is no "Audio Language" preference specified then the "Language" setting is used so users do not need to configure anything to keep the current behavior. Note that TVs sold in Europe generally have separate settings for "Menu Language" and "Audio Language". --- mythtv/libs/libmythbase/mythcorecontext.cpp | 35 +++++++++++++++++++ mythtv/libs/libmythbase/mythcorecontext.h | 3 ++ .../libmythtv/decoders/avformatdecoder.cpp | 14 ++++---- mythtv/libs/libmythui/mythmainwindow.cpp | 1 + .../programs/mythfrontend/globalsettings.cpp | 33 ++++++++++++++++- 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/mythtv/libs/libmythbase/mythcorecontext.cpp b/mythtv/libs/libmythbase/mythcorecontext.cpp index 69f42245436..f0709248ba3 100644 --- a/mythtv/libs/libmythbase/mythcorecontext.cpp +++ b/mythtv/libs/libmythbase/mythcorecontext.cpp @@ -94,6 +94,7 @@ class MythCoreContextPrivate : public QObject MythLocale *m_locale { nullptr }; QString m_language; + QString m_audioLanguage; MythScheduler *m_scheduler { nullptr }; @@ -1792,6 +1793,40 @@ void MythCoreContext::ResetLanguage(void) d->m_language.clear(); } +/** + * \brief Returns two character ISO-639 language descriptor for audio language. + * \sa iso639_get_language_list() + */ +QString MythCoreContext::GetAudioLanguage(void) +{ + return GetAudioLanguageAndVariant().left(2); +} + +/** + * \brief Returns the user-set audio language and variant. + * + * The string has the form ll or ll_vv, where ll is the two character + * ISO-639 language code, and vv (which may not exist) is the variant. + * Examples include en_AU, en_CA, en_GB, en_US, fr_CH, fr_DE, pt_BR, pt_PT. + */ +QString MythCoreContext::GetAudioLanguageAndVariant(void) +{ + if (d->m_audioLanguage.isEmpty()) + { + auto menuLanguage = GetLanguageAndVariant(); + d->m_audioLanguage = GetSetting("AudioLanguage", menuLanguage).toLower(); + + LOG(VB_AUDIO, LOG_DEBUG, LOC + QString("audio language:%1 menu language:%2") + .arg(d->m_audioLanguage).arg(menuLanguage)); + } + return d->m_audioLanguage; +} + +void MythCoreContext::ResetAudioLanguage(void) +{ + d->m_audioLanguage.clear(); +} + void MythCoreContext::ResetSockets(void) { QMutexLocker locker(&d->m_sockLock); diff --git a/mythtv/libs/libmythbase/mythcorecontext.h b/mythtv/libs/libmythbase/mythcorecontext.h index 93b8d40807a..7c6dd8a64f5 100644 --- a/mythtv/libs/libmythbase/mythcorecontext.h +++ b/mythtv/libs/libmythbase/mythcorecontext.h @@ -236,6 +236,9 @@ class MBASE_PUBLIC MythCoreContext : public QObject, public MythObservable, publ QString GetLanguage(void); QString GetLanguageAndVariant(void); void ResetLanguage(void); + QString GetAudioLanguage(void); + QString GetAudioLanguageAndVariant(void); + void ResetAudioLanguage(void); void ResetSockets(void); using PlaybackStartCb = void (QObject::*)(void); diff --git a/mythtv/libs/libmythtv/decoders/avformatdecoder.cpp b/mythtv/libs/libmythtv/decoders/avformatdecoder.cpp index c13088e87a9..b0374b68df8 100644 --- a/mythtv/libs/libmythtv/decoders/avformatdecoder.cpp +++ b/mythtv/libs/libmythtv/decoders/avformatdecoder.cpp @@ -4394,8 +4394,8 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) ftype.push_back(i); } - // try to get the language track matching the frontend language. - QString language_key_convert = iso639_str2_to_str3(gCoreContext->GetLanguage()); + // Try to get the language track for the preferred language for audio + QString language_key_convert = iso639_str2_to_str3(gCoreContext->GetAudioLanguage()); uint language_key = iso639_str3_to_key(language_key_convert); uint canonical_key = iso639_key_to_canonical_key(language_key); @@ -4422,8 +4422,8 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) if (selTrack < 0) selTrack = filter_max_ch(m_ic, atracks, flang); - // try to get best track for most preferred language - // Set by the "Guide Data" language prefs in Appearance. + // Try to get best track for most preferred language for audio. + // Set by the "Guide Data" "Audio Language" preference in Appearance. if (selTrack < 0) { auto it = m_languagePreference.begin(); @@ -4457,8 +4457,8 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) } } - // could not select track based on user preferences (language) - // try to select the default track + // Could not select track based on user preferences (audio language) + // Try to select the default track if (selTrack < 0) { LOG(VB_AUDIO, LOG_INFO, LOC + "Trying to select default track"); @@ -4472,7 +4472,7 @@ int AvFormatDecoder::AutoSelectAudioTrack(void) } } - // try to get best track for any language + // Try to get best track for any language if (selTrack < 0) { LOG(VB_AUDIO, LOG_INFO, LOC + diff --git a/mythtv/libs/libmythui/mythmainwindow.cpp b/mythtv/libs/libmythui/mythmainwindow.cpp index 2677628e5cc..de9a74bd0d4 100644 --- a/mythtv/libs/libmythui/mythmainwindow.cpp +++ b/mythtv/libs/libmythui/mythmainwindow.cpp @@ -634,6 +634,7 @@ bool MythMainWindow::event(QEvent *Event) void MythMainWindow::LoadQtConfig() { gCoreContext->ResetLanguage(); + gCoreContext->ResetAudioLanguage(); GetMythUI()->ClearThemeCacheDir(); QApplication::setStyle("Windows"); } diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp index 3254096d93c..b00ad99d348 100644 --- a/mythtv/programs/mythfrontend/globalsettings.cpp +++ b/mythtv/programs/mythfrontend/globalsettings.cpp @@ -3214,7 +3214,7 @@ static GlobalComboBoxSetting *MythLanguage() { auto *gc = new GlobalComboBoxSetting("Language"); - gc->setLabel(AppearanceSettings::tr("Language")); + gc->setLabel(AppearanceSettings::tr("Menu Language")); QMap langMap = MythTranslation::getLanguages(); QStringList langs = langMap.values(); @@ -3237,6 +3237,36 @@ static GlobalComboBoxSetting *MythLanguage() return gc; } +static GlobalComboBoxSetting *AudioLanguage() +{ + auto *gc = new GlobalComboBoxSetting("AudioLanguage"); + + gc->setLabel(AppearanceSettings::tr("Audio Language")); + + QMap langMap = MythTranslation::getLanguages(); + QStringList langs = langMap.values(); + langs.sort(); + QString langCode = gCoreContext->GetSetting("AudioLanguage").toLower(); + + if (langCode.isEmpty()) + { + auto menuLangCode = gCoreContext->GetSetting("Language").toLower(); + langCode = menuLangCode.isEmpty() ? "en_US" : menuLangCode; + } + + gc->clearSelections(); + + for (const auto & label : qAsConst(langs)) + { + QString value = langMap.key(label); + gc->addSelection(label, value, (value.toLower() == langCode)); + } + + gc->setHelpText(AppearanceSettings::tr("Preferred language for the " + "audio track.")); + return gc; +} + static void ISO639_fill_selections(MythUIComboBoxSetting *widget, uint i) { widget->clearSelections(); @@ -4784,6 +4814,7 @@ AppearanceSettings::AppearanceSettings() dates->setLabel(tr("Localization")); dates->addChild(MythLanguage()); + dates->addChild(AudioLanguage()); dates->addChild(ISO639PreferredLanguage(0)); dates->addChild(ISO639PreferredLanguage(1)); dates->addChild(MythDateFormatCB());