summaryrefslogtreecommitdiffstats
path: root/xbmc/video/dialogs/GUIDialogAudioSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/video/dialogs/GUIDialogAudioSettings.cpp')
-rw-r--r--xbmc/video/dialogs/GUIDialogAudioSettings.cpp437
1 files changed, 437 insertions, 0 deletions
diff --git a/xbmc/video/dialogs/GUIDialogAudioSettings.cpp b/xbmc/video/dialogs/GUIDialogAudioSettings.cpp
new file mode 100644
index 0000000..83b888b
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogAudioSettings.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUIDialogAudioSettings.h"
+
+#include "GUIPassword.h"
+#include "ServiceBroker.h"
+#include "addons/Skin.h"
+#include "application/ApplicationComponents.h"
+#include "application/ApplicationPlayer.h"
+#include "application/ApplicationVolumeHandling.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
+#include "cores/IPlayer.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "guilib/GUIMessage.h"
+#include "guilib/LocalizeStrings.h"
+#include "profiles/ProfileManager.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/MediaSettings.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/Setting.h"
+#include "settings/lib/SettingDefinitions.h"
+#include "settings/lib/SettingsManager.h"
+#include "utils/LangCodeExpander.h"
+#include "utils/StringUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+#include "video/VideoDatabase.h"
+
+#include <string>
+#include <vector>
+
+#define SETTING_AUDIO_VOLUME "audio.volume"
+#define SETTING_AUDIO_VOLUME_AMPLIFICATION "audio.volumeamplification"
+#define SETTING_AUDIO_CENTERMIXLEVEL "audio.centermixlevel"
+#define SETTING_AUDIO_DELAY "audio.delay"
+#define SETTING_AUDIO_STREAM "audio.stream"
+#define SETTING_AUDIO_PASSTHROUGH "audio.digitalanalog"
+#define SETTING_AUDIO_MAKE_DEFAULT "audio.makedefault"
+
+CGUIDialogAudioSettings::CGUIDialogAudioSettings()
+ : CGUIDialogSettingsManualBase(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "DialogSettings.xml")
+{ }
+
+CGUIDialogAudioSettings::~CGUIDialogAudioSettings() = default;
+
+void CGUIDialogAudioSettings::FrameMove()
+{
+ // update the volume setting if necessary
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
+ float newVolume = appVolume->GetVolumeRatio();
+ if (newVolume != m_volume)
+ GetSettingsManager()->SetNumber(SETTING_AUDIO_VOLUME, static_cast<double>(newVolume));
+
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ if (appPlayer->HasPlayer())
+ {
+ const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
+
+ // these settings can change on the fly
+ //! @todo (needs special handling): m_settingsManager->SetInt(SETTING_AUDIO_STREAM, g_application.GetAppPlayer().GetAudioStream());
+ GetSettingsManager()->SetNumber(SETTING_AUDIO_DELAY,
+ static_cast<double>(videoSettings.m_AudioDelay));
+ GetSettingsManager()->SetBool(SETTING_AUDIO_PASSTHROUGH, CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH));
+ }
+
+ CGUIDialogSettingsManualBase::FrameMove();
+}
+
+std::string CGUIDialogAudioSettings::FormatDelay(float value, float interval)
+{
+ if (fabs(value) < 0.5f * interval)
+ return StringUtils::Format(g_localizeStrings.Get(22003), 0.0);
+ if (value < 0)
+ return StringUtils::Format(g_localizeStrings.Get(22004), fabs(value));
+
+ return StringUtils::Format(g_localizeStrings.Get(22005), value);
+}
+
+std::string CGUIDialogAudioSettings::FormatDecibel(float value)
+{
+ return StringUtils::Format(g_localizeStrings.Get(14054), value);
+}
+
+std::string CGUIDialogAudioSettings::FormatPercentAsDecibel(float value)
+{
+ return StringUtils::Format(g_localizeStrings.Get(14054), CAEUtil::PercentToGain(value));
+}
+
+void CGUIDialogAudioSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
+{
+ if (setting == NULL)
+ return;
+
+ CGUIDialogSettingsManualBase::OnSettingChanged(setting);
+
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == SETTING_AUDIO_VOLUME)
+ {
+ m_volume = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
+ const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
+ appVolume->SetVolume(m_volume, false); // false - value is not in percent
+ }
+ else if (settingId == SETTING_AUDIO_VOLUME_AMPLIFICATION)
+ {
+ float value = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
+ appPlayer->SetDynamicRangeCompression((long)(value * 100));
+ }
+ else if (settingId == SETTING_AUDIO_CENTERMIXLEVEL)
+ {
+ CVideoSettings vs = appPlayer->GetVideoSettings();
+ vs.m_CenterMixLevel = std::static_pointer_cast<const CSettingInt>(setting)->GetValue();
+ appPlayer->SetVideoSettings(vs);
+ }
+ else if (settingId == SETTING_AUDIO_DELAY)
+ {
+ float value = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
+ appPlayer->SetAVDelay(value);
+ }
+ else if (settingId == SETTING_AUDIO_STREAM)
+ {
+ m_audioStream = std::static_pointer_cast<const CSettingInt>(setting)->GetValue();
+ // only change the audio stream if a different one has been asked for
+ if (appPlayer->GetAudioStream() != m_audioStream)
+ {
+ appPlayer->SetAudioStream(m_audioStream); // Set the audio stream to the one selected
+ }
+ }
+ else if (settingId == SETTING_AUDIO_PASSTHROUGH)
+ {
+ m_passthrough = std::static_pointer_cast<const CSettingBool>(setting)->GetValue();
+ CServiceBroker::GetSettingsComponent()->GetSettings()->SetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH, m_passthrough);
+ }
+}
+
+void CGUIDialogAudioSettings::OnSettingAction(const std::shared_ptr<const CSetting>& setting)
+{
+ if (setting == NULL)
+ return;
+
+ CGUIDialogSettingsManualBase::OnSettingAction(setting);
+
+ const std::string &settingId = setting->GetId();
+ if (settingId == SETTING_AUDIO_MAKE_DEFAULT)
+ Save();
+}
+
+bool CGUIDialogAudioSettings::Save()
+{
+ const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
+
+ if (!g_passwordManager.CheckSettingLevelLock(SettingLevel::Expert) &&
+ profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE)
+ return true;
+
+ // prompt user if they are sure
+ if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{12376}, CVariant{12377}))
+ return true;
+
+ // reset the settings
+ CVideoDatabase db;
+ if (!db.Open())
+ return true;
+
+ db.EraseAllVideoSettings();
+ db.Close();
+
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ CMediaSettings::GetInstance().GetDefaultVideoSettings() = appPlayer->GetVideoSettings();
+ CMediaSettings::GetInstance().GetDefaultVideoSettings().m_AudioStream = -1;
+ CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
+
+ return true;
+}
+
+void CGUIDialogAudioSettings::SetupView()
+{
+ CGUIDialogSettingsManualBase::SetupView();
+
+ SetHeading(13396);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_OKAY_BUTTON);
+ SET_CONTROL_HIDDEN(CONTROL_SETTINGS_CUSTOM_BUTTON);
+ SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 15067);
+}
+
+void CGUIDialogAudioSettings::InitializeSettings()
+{
+ CGUIDialogSettingsManualBase::InitializeSettings();
+
+ const std::shared_ptr<CSettingCategory> category = AddCategory("audiosubtitlesettings", -1);
+ if (category == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
+ return;
+ }
+
+ // get all necessary setting groups
+ const std::shared_ptr<CSettingGroup> groupAudio = AddGroup(category);
+ if (groupAudio == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
+ return;
+ }
+ const std::shared_ptr<CSettingGroup> groupSubtitles = AddGroup(category);
+ if (groupSubtitles == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
+ return;
+ }
+ const std::shared_ptr<CSettingGroup> groupSaveAsDefault = AddGroup(category);
+ if (groupSaveAsDefault == NULL)
+ {
+ CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
+ return;
+ }
+
+ bool usePopup = g_SkinInfo->HasSkinFile("DialogSlider.xml");
+
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+
+ const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
+ if (appPlayer->HasPlayer())
+ {
+ appPlayer->GetAudioCapabilities(m_audioCaps);
+ }
+
+ // register IsPlayingPassthrough condition
+ GetSettingsManager()->AddDynamicCondition("IsPlayingPassthrough", IsPlayingPassthrough);
+
+ CSettingDependency dependencyAudioOutputPassthroughDisabled(SettingDependencyType::Enable, GetSettingsManager());
+ dependencyAudioOutputPassthroughDisabled.Or()
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_AUDIO_PASSTHROUGH, "false", SettingDependencyOperator::Equals, false, GetSettingsManager())))
+ ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition("IsPlayingPassthrough", "", "", true, GetSettingsManager())));
+ SettingDependencies depsAudioOutputPassthroughDisabled;
+ depsAudioOutputPassthroughDisabled.push_back(dependencyAudioOutputPassthroughDisabled);
+
+ // audio settings
+ // audio volume setting
+ const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
+ m_volume = appVolume->GetVolumeRatio();
+ std::shared_ptr<CSettingNumber> settingAudioVolume =
+ AddSlider(groupAudio, SETTING_AUDIO_VOLUME, 13376, SettingLevel::Basic, m_volume, 14054,
+ CApplicationVolumeHandling::VOLUME_MINIMUM,
+ CApplicationVolumeHandling::VOLUME_MAXIMUM / 100.0f,
+ CApplicationVolumeHandling::VOLUME_MAXIMUM);
+ settingAudioVolume->SetDependencies(depsAudioOutputPassthroughDisabled);
+ std::static_pointer_cast<CSettingControlSlider>(settingAudioVolume->GetControl())->SetFormatter(SettingFormatterPercentAsDecibel);
+
+ // audio volume amplification setting
+ if (SupportsAudioFeature(IPC_AUD_AMP))
+ {
+ std::shared_ptr<CSettingNumber> settingAudioVolumeAmplification = AddSlider(groupAudio, SETTING_AUDIO_VOLUME_AMPLIFICATION, 660, SettingLevel::Basic, videoSettings.m_VolumeAmplification, 14054, VOLUME_DRC_MINIMUM * 0.01f, (VOLUME_DRC_MAXIMUM - VOLUME_DRC_MINIMUM) / 6000.0f, VOLUME_DRC_MAXIMUM * 0.01f);
+ settingAudioVolumeAmplification->SetDependencies(depsAudioOutputPassthroughDisabled);
+ }
+
+ // downmix: center mix level
+ {
+ AddSlider(groupAudio, SETTING_AUDIO_CENTERMIXLEVEL, 39112, SettingLevel::Basic,
+ videoSettings.m_CenterMixLevel, 14050, -10, 1, 30,
+ -1, false, false, true, 39113);
+ }
+
+ // audio delay setting
+ if (SupportsAudioFeature(IPC_AUD_OFFSET))
+ {
+ std::shared_ptr<CSettingNumber> settingAudioDelay = AddSlider(
+ groupAudio, SETTING_AUDIO_DELAY, 297, SettingLevel::Basic, videoSettings.m_AudioDelay, 0,
+ -CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange,
+ AUDIO_DELAY_STEP,
+ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, 297,
+ usePopup);
+ std::static_pointer_cast<CSettingControlSlider>(settingAudioDelay->GetControl())->SetFormatter(SettingFormatterDelay);
+ }
+
+ // audio stream setting
+ if (SupportsAudioFeature(IPC_AUD_SELECT_STREAM))
+ AddAudioStreams(groupAudio, SETTING_AUDIO_STREAM);
+
+ // audio digital/analog setting
+ if (SupportsAudioFeature(IPC_AUD_SELECT_OUTPUT))
+ {
+ m_passthrough = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH);
+ AddToggle(groupAudio, SETTING_AUDIO_PASSTHROUGH, 348, SettingLevel::Basic, m_passthrough);
+ }
+
+ // subtitle stream setting
+ AddButton(groupSaveAsDefault, SETTING_AUDIO_MAKE_DEFAULT, 12376, SettingLevel::Basic);
+}
+
+bool CGUIDialogAudioSettings::SupportsAudioFeature(int feature)
+{
+ for (Features::iterator itr = m_audioCaps.begin(); itr != m_audioCaps.end(); ++itr)
+ {
+ if (*itr == feature || *itr == IPC_AUD_ALL)
+ return true;
+ }
+
+ return false;
+}
+
+void CGUIDialogAudioSettings::AddAudioStreams(const std::shared_ptr<CSettingGroup>& group,
+ const std::string& settingId)
+{
+ if (group == NULL || settingId.empty())
+ return;
+
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ m_audioStream = appPlayer->GetAudioStream();
+ if (m_audioStream < 0)
+ m_audioStream = 0;
+
+ AddList(group, settingId, 460, SettingLevel::Basic, m_audioStream, AudioStreamsOptionFiller, 460);
+}
+
+bool CGUIDialogAudioSettings::IsPlayingPassthrough(const std::string& condition,
+ const std::string& value,
+ const SettingConstPtr& setting,
+ void* data)
+{
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ return appPlayer->IsPassthrough();
+}
+
+void CGUIDialogAudioSettings::AudioStreamsOptionFiller(const SettingConstPtr& setting,
+ std::vector<IntegerSettingOption>& list,
+ int& current,
+ void* data)
+{
+ const auto& components = CServiceBroker::GetAppComponents();
+ const auto appPlayer = components.GetComponent<CApplicationPlayer>();
+ int audioStreamCount = appPlayer->GetAudioStreamCount();
+
+ std::string strFormat = "{:s} - {:s} - {:d} " + g_localizeStrings.Get(10127);
+ std::string strUnknown = "[" + g_localizeStrings.Get(13205) + "]";
+
+ // cycle through each audio stream and add it to our list control
+ for (int i = 0; i < audioStreamCount; ++i)
+ {
+ std::string strItem;
+ std::string strLanguage;
+
+ AudioStreamInfo info;
+ appPlayer->GetAudioStreamInfo(i, info);
+
+ if (!g_LangCodeExpander.Lookup(info.language, strLanguage))
+ strLanguage = strUnknown;
+
+ if (info.name.length() == 0)
+ info.name = strUnknown;
+
+ strItem = StringUtils::Format(strFormat, strLanguage, info.name, info.channels);
+
+ strItem += FormatFlags(info.flags);
+ strItem += StringUtils::Format(" ({}/{})", i + 1, audioStreamCount);
+ list.emplace_back(strItem, i);
+ }
+
+ if (list.empty())
+ {
+ list.emplace_back(g_localizeStrings.Get(231), -1);
+ current = -1;
+ }
+}
+
+std::string CGUIDialogAudioSettings::SettingFormatterDelay(
+ const std::shared_ptr<const CSettingControlSlider>& control,
+ const CVariant& value,
+ const CVariant& minimum,
+ const CVariant& step,
+ const CVariant& maximum)
+{
+ if (!value.isDouble())
+ return "";
+
+ float fValue = value.asFloat();
+ float fStep = step.asFloat();
+
+ if (fabs(fValue) < 0.5f * fStep)
+ return StringUtils::Format(g_localizeStrings.Get(22003), 0.0);
+ if (fValue < 0)
+ return StringUtils::Format(g_localizeStrings.Get(22004), fabs(fValue));
+
+ return StringUtils::Format(g_localizeStrings.Get(22005), fValue);
+}
+
+std::string CGUIDialogAudioSettings::SettingFormatterPercentAsDecibel(
+ const std::shared_ptr<const CSettingControlSlider>& control,
+ const CVariant& value,
+ const CVariant& minimum,
+ const CVariant& step,
+ const CVariant& maximum)
+{
+ if (control == NULL || !value.isDouble())
+ return "";
+
+ std::string formatString = control->GetFormatString();
+ if (control->GetFormatLabel() > -1)
+ formatString = g_localizeStrings.Get(control->GetFormatLabel());
+
+ return StringUtils::Format(formatString, CAEUtil::PercentToGain(value.asFloat()));
+}
+
+std::string CGUIDialogAudioSettings::FormatFlags(StreamFlags flags)
+{
+ std::vector<std::string> localizedFlags;
+ if (flags & StreamFlags::FLAG_DEFAULT)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39105));
+ if (flags & StreamFlags::FLAG_FORCED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39106));
+ if (flags & StreamFlags::FLAG_HEARING_IMPAIRED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39107));
+ if (flags & StreamFlags::FLAG_VISUAL_IMPAIRED)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39108));
+ if (flags & StreamFlags::FLAG_ORIGINAL)
+ localizedFlags.emplace_back(g_localizeStrings.Get(39111));
+
+ std::string formated = StringUtils::Join(localizedFlags, ", ");
+
+ if (!formated.empty())
+ formated = StringUtils::Format(" [{}]", formated);
+
+ return formated;
+}