[Windows] Remove redundant DirectSound error codes
[xbmc.git] / xbmc / video / dialogs / GUIDialogAudioSettings.cpp
blobe8371ffa3bc3e0c4111aff5633279d2455a218e9
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUIDialogAudioSettings.h"
11 #include "GUIPassword.h"
12 #include "ServiceBroker.h"
13 #include "addons/Skin.h"
14 #include "application/ApplicationComponents.h"
15 #include "application/ApplicationPlayer.h"
16 #include "application/ApplicationVolumeHandling.h"
17 #include "cores/AudioEngine/Utils/AEUtil.h"
18 #include "cores/IPlayer.h"
19 #include "dialogs/GUIDialogYesNo.h"
20 #include "guilib/GUIMessage.h"
21 #include "guilib/LocalizeStrings.h"
22 #include "profiles/ProfileManager.h"
23 #include "settings/AdvancedSettings.h"
24 #include "settings/MediaSettings.h"
25 #include "settings/Settings.h"
26 #include "settings/SettingsComponent.h"
27 #include "settings/lib/Setting.h"
28 #include "settings/lib/SettingDefinitions.h"
29 #include "settings/lib/SettingsManager.h"
30 #include "utils/LangCodeExpander.h"
31 #include "utils/StringUtils.h"
32 #include "utils/Variant.h"
33 #include "utils/log.h"
34 #include "video/VideoDatabase.h"
36 #include <memory>
37 #include <string>
38 #include <vector>
40 #define SETTING_AUDIO_VOLUME "audio.volume"
41 #define SETTING_AUDIO_VOLUME_AMPLIFICATION "audio.volumeamplification"
42 #define SETTING_AUDIO_CENTERMIXLEVEL "audio.centermixlevel"
43 #define SETTING_AUDIO_DELAY "audio.delay"
44 #define SETTING_AUDIO_STREAM "audio.stream"
45 #define SETTING_AUDIO_PASSTHROUGH "audio.digitalanalog"
46 #define SETTING_AUDIO_MAKE_DEFAULT "audio.makedefault"
48 CGUIDialogAudioSettings::CGUIDialogAudioSettings()
49 : CGUIDialogSettingsManualBase(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "DialogSettings.xml")
50 { }
52 CGUIDialogAudioSettings::~CGUIDialogAudioSettings() = default;
54 void CGUIDialogAudioSettings::FrameMove()
56 // update the volume setting if necessary
57 const auto& components = CServiceBroker::GetAppComponents();
58 const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
59 float newVolume = appVolume->GetVolumeRatio();
60 if (newVolume != m_volume)
61 GetSettingsManager()->SetNumber(SETTING_AUDIO_VOLUME, static_cast<double>(newVolume));
63 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
64 if (appPlayer->HasPlayer())
66 const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
68 // these settings can change on the fly
69 //! @todo (needs special handling): m_settingsManager->SetInt(SETTING_AUDIO_STREAM, g_application.GetAppPlayer().GetAudioStream());
70 GetSettingsManager()->SetNumber(SETTING_AUDIO_DELAY,
71 static_cast<double>(videoSettings.m_AudioDelay));
72 GetSettingsManager()->SetBool(SETTING_AUDIO_PASSTHROUGH, CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH));
75 CGUIDialogSettingsManualBase::FrameMove();
78 std::string CGUIDialogAudioSettings::FormatDelay(float value, float interval)
80 if (fabs(value) < 0.5f * interval)
81 return StringUtils::Format(g_localizeStrings.Get(22003), 0.0);
82 if (value < 0)
83 return StringUtils::Format(g_localizeStrings.Get(22004), fabs(value));
85 return StringUtils::Format(g_localizeStrings.Get(22005), value);
88 std::string CGUIDialogAudioSettings::FormatDecibel(float value)
90 return StringUtils::Format(g_localizeStrings.Get(14054), value);
93 std::string CGUIDialogAudioSettings::FormatPercentAsDecibel(float value)
95 return StringUtils::Format(g_localizeStrings.Get(14054), CAEUtil::PercentToGain(value));
98 void CGUIDialogAudioSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
100 if (setting == NULL)
101 return;
103 CGUIDialogSettingsManualBase::OnSettingChanged(setting);
105 auto& components = CServiceBroker::GetAppComponents();
106 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
108 const std::string &settingId = setting->GetId();
109 if (settingId == SETTING_AUDIO_VOLUME)
111 m_volume = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
112 const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
113 appVolume->SetVolume(m_volume, false); // false - value is not in percent
115 else if (settingId == SETTING_AUDIO_VOLUME_AMPLIFICATION)
117 float value = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
118 appPlayer->SetDynamicRangeCompression((long)(value * 100));
120 else if (settingId == SETTING_AUDIO_CENTERMIXLEVEL)
122 CVideoSettings vs = appPlayer->GetVideoSettings();
123 vs.m_CenterMixLevel = std::static_pointer_cast<const CSettingInt>(setting)->GetValue();
124 appPlayer->SetVideoSettings(vs);
126 else if (settingId == SETTING_AUDIO_DELAY)
128 float value = static_cast<float>(std::static_pointer_cast<const CSettingNumber>(setting)->GetValue());
129 appPlayer->SetAVDelay(value);
131 else if (settingId == SETTING_AUDIO_STREAM)
133 m_audioStream = std::static_pointer_cast<const CSettingInt>(setting)->GetValue();
134 // only change the audio stream if a different one has been asked for
135 if (appPlayer->GetAudioStream() != m_audioStream)
137 appPlayer->SetAudioStream(m_audioStream); // Set the audio stream to the one selected
140 else if (settingId == SETTING_AUDIO_PASSTHROUGH)
142 m_passthrough = std::static_pointer_cast<const CSettingBool>(setting)->GetValue();
143 CServiceBroker::GetSettingsComponent()->GetSettings()->SetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH, m_passthrough);
147 void CGUIDialogAudioSettings::OnSettingAction(const std::shared_ptr<const CSetting>& setting)
149 if (setting == NULL)
150 return;
152 CGUIDialogSettingsManualBase::OnSettingAction(setting);
154 const std::string &settingId = setting->GetId();
155 if (settingId == SETTING_AUDIO_MAKE_DEFAULT)
156 Save();
159 bool CGUIDialogAudioSettings::Save()
161 const std::shared_ptr<CProfileManager> profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager();
163 if (!g_passwordManager.CheckSettingLevelLock(SettingLevel::Expert) &&
164 profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE)
165 return true;
167 // prompt user if they are sure
168 if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{12376}, CVariant{12377}))
169 return true;
171 // reset the settings
172 CVideoDatabase db;
173 if (!db.Open())
174 return true;
176 db.EraseAllVideoSettings();
177 db.Close();
179 const auto& components = CServiceBroker::GetAppComponents();
180 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
181 CMediaSettings::GetInstance().GetDefaultVideoSettings() = appPlayer->GetVideoSettings();
182 CMediaSettings::GetInstance().GetDefaultVideoSettings().m_AudioStream = -1;
183 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
185 return true;
188 void CGUIDialogAudioSettings::SetupView()
190 CGUIDialogSettingsManualBase::SetupView();
192 SetHeading(13396);
193 SET_CONTROL_HIDDEN(CONTROL_SETTINGS_OKAY_BUTTON);
194 SET_CONTROL_HIDDEN(CONTROL_SETTINGS_CUSTOM_BUTTON);
195 SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 15067);
198 void CGUIDialogAudioSettings::InitializeSettings()
200 CGUIDialogSettingsManualBase::InitializeSettings();
202 const std::shared_ptr<CSettingCategory> category = AddCategory("audiosubtitlesettings", -1);
203 if (category == NULL)
205 CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
206 return;
209 // get all necessary setting groups
210 const std::shared_ptr<CSettingGroup> groupAudio = AddGroup(category);
211 if (groupAudio == NULL)
213 CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
214 return;
216 const std::shared_ptr<CSettingGroup> groupSubtitles = AddGroup(category);
217 if (groupSubtitles == NULL)
219 CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
220 return;
222 const std::shared_ptr<CSettingGroup> groupSaveAsDefault = AddGroup(category);
223 if (groupSaveAsDefault == NULL)
225 CLog::Log(LOGERROR, "CGUIDialogAudioSettings: unable to setup settings");
226 return;
229 bool usePopup = g_SkinInfo->HasSkinFile("DialogSlider.xml");
231 const auto& components = CServiceBroker::GetAppComponents();
232 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
234 const CVideoSettings videoSettings = appPlayer->GetVideoSettings();
235 if (appPlayer->HasPlayer())
237 appPlayer->GetAudioCapabilities(m_audioCaps);
240 // register IsPlayingPassthrough condition
241 GetSettingsManager()->AddDynamicCondition("IsPlayingPassthrough", IsPlayingPassthrough);
243 CSettingDependency dependencyAudioOutputPassthroughDisabled(SettingDependencyType::Enable, GetSettingsManager());
244 dependencyAudioOutputPassthroughDisabled.Or()
245 ->Add(std::make_shared<CSettingDependencyCondition>(SETTING_AUDIO_PASSTHROUGH, "false",
246 SettingDependencyOperator::Equals, false,
247 GetSettingsManager()))
248 ->Add(std::make_shared<CSettingDependencyCondition>("IsPlayingPassthrough", "", "", true,
249 GetSettingsManager()));
250 SettingDependencies depsAudioOutputPassthroughDisabled;
251 depsAudioOutputPassthroughDisabled.push_back(dependencyAudioOutputPassthroughDisabled);
253 // audio settings
254 // audio volume setting
255 const auto appVolume = components.GetComponent<CApplicationVolumeHandling>();
256 m_volume = appVolume->GetVolumeRatio();
257 std::shared_ptr<CSettingNumber> settingAudioVolume =
258 AddSlider(groupAudio, SETTING_AUDIO_VOLUME, 13376, SettingLevel::Basic, m_volume, 14054,
259 CApplicationVolumeHandling::VOLUME_MINIMUM,
260 CApplicationVolumeHandling::VOLUME_MAXIMUM / 100.0f,
261 CApplicationVolumeHandling::VOLUME_MAXIMUM);
262 settingAudioVolume->SetDependencies(depsAudioOutputPassthroughDisabled);
263 std::static_pointer_cast<CSettingControlSlider>(settingAudioVolume->GetControl())->SetFormatter(SettingFormatterPercentAsDecibel);
265 // audio volume amplification setting
266 if (SupportsAudioFeature(IPlayerAudioCaps::VOLUME_AMP))
268 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);
269 settingAudioVolumeAmplification->SetDependencies(depsAudioOutputPassthroughDisabled);
272 // downmix: center mix level
274 AddSlider(groupAudio, SETTING_AUDIO_CENTERMIXLEVEL, 39112, SettingLevel::Basic,
275 videoSettings.m_CenterMixLevel, 14050, -10, 1, 30,
276 -1, false, false, true, 39113);
279 // audio delay setting
280 if (SupportsAudioFeature(IPlayerAudioCaps::OFFSET))
282 std::shared_ptr<CSettingNumber> settingAudioDelay = AddSlider(
283 groupAudio, SETTING_AUDIO_DELAY, 297, SettingLevel::Basic, videoSettings.m_AudioDelay, 0,
284 -CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange,
285 AUDIO_DELAY_STEP,
286 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_videoAudioDelayRange, 297,
287 usePopup);
288 std::static_pointer_cast<CSettingControlSlider>(settingAudioDelay->GetControl())->SetFormatter(SettingFormatterDelay);
291 // audio stream setting
292 if (SupportsAudioFeature(IPlayerAudioCaps::SELECT_STREAM))
293 AddAudioStreams(groupAudio, SETTING_AUDIO_STREAM);
295 // audio digital/analog setting
296 if (SupportsAudioFeature(IPlayerAudioCaps::SELECT_OUTPUT))
298 m_passthrough = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGH);
299 AddToggle(groupAudio, SETTING_AUDIO_PASSTHROUGH, 348, SettingLevel::Basic, m_passthrough);
302 // subtitle stream setting
303 AddButton(groupSaveAsDefault, SETTING_AUDIO_MAKE_DEFAULT, 12376, SettingLevel::Basic);
306 bool CGUIDialogAudioSettings::SupportsAudioFeature(IPlayerAudioCaps feature)
308 for (IPlayerAudioCaps cap : m_audioCaps)
310 if (cap == feature || cap == IPlayerAudioCaps::ALL)
311 return true;
314 return false;
317 void CGUIDialogAudioSettings::AddAudioStreams(const std::shared_ptr<CSettingGroup>& group,
318 const std::string& settingId)
320 if (group == NULL || settingId.empty())
321 return;
323 auto& components = CServiceBroker::GetAppComponents();
324 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
325 m_audioStream = appPlayer->GetAudioStream();
326 if (m_audioStream < 0)
327 m_audioStream = 0;
329 AddList(group, settingId, 460, SettingLevel::Basic, m_audioStream, AudioStreamsOptionFiller, 460);
332 bool CGUIDialogAudioSettings::IsPlayingPassthrough(const std::string& condition,
333 const std::string& value,
334 const SettingConstPtr& setting,
335 void* data)
337 const auto& components = CServiceBroker::GetAppComponents();
338 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
339 return appPlayer->IsPassthrough();
342 void CGUIDialogAudioSettings::AudioStreamsOptionFiller(const SettingConstPtr& setting,
343 std::vector<IntegerSettingOption>& list,
344 int& current,
345 void* data)
347 const auto& components = CServiceBroker::GetAppComponents();
348 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
349 const int audioStreamCount = appPlayer->GetAudioStreamCount();
351 std::string channelsLabel = g_localizeStrings.Get(10127);
352 std::string strUnknown = "[" + g_localizeStrings.Get(13205) + "]";
354 // cycle through each audio stream and add it to our list control
355 for (int i = 0; i < audioStreamCount; ++i)
357 std::string strLanguage;
359 AudioStreamInfo info;
360 appPlayer->GetAudioStreamInfo(i, info);
362 if (!g_LangCodeExpander.Lookup(info.language, strLanguage))
363 strLanguage = strUnknown;
365 std::string textInfo = strLanguage;
366 if (!info.name.empty())
367 textInfo += " - " + info.name;
369 textInfo += " (";
370 if (!info.codecDesc.empty())
371 textInfo += info.codecDesc + ", ";
373 textInfo += std::to_string(info.channels) + " " + channelsLabel + ")";
375 textInfo += FormatFlags(info.flags);
376 textInfo += StringUtils::Format(" ({}/{})", i + 1, audioStreamCount);
377 list.emplace_back(textInfo, i);
380 if (list.empty())
382 list.emplace_back(g_localizeStrings.Get(231), -1);
383 current = -1;
387 std::string CGUIDialogAudioSettings::SettingFormatterDelay(
388 const std::shared_ptr<const CSettingControlSlider>& control,
389 const CVariant& value,
390 const CVariant& minimum,
391 const CVariant& step,
392 const CVariant& maximum)
394 if (!value.isDouble())
395 return "";
397 float fValue = value.asFloat();
398 float fStep = step.asFloat();
400 if (fabs(fValue) < 0.5f * fStep)
401 return StringUtils::Format(g_localizeStrings.Get(22003), 0.0);
402 if (fValue < 0)
403 return StringUtils::Format(g_localizeStrings.Get(22004), fabs(fValue));
405 return StringUtils::Format(g_localizeStrings.Get(22005), fValue);
408 std::string CGUIDialogAudioSettings::SettingFormatterPercentAsDecibel(
409 const std::shared_ptr<const CSettingControlSlider>& control,
410 const CVariant& value,
411 const CVariant& minimum,
412 const CVariant& step,
413 const CVariant& maximum)
415 if (control == NULL || !value.isDouble())
416 return "";
418 std::string formatString = control->GetFormatString();
419 if (control->GetFormatLabel() > -1)
420 formatString = g_localizeStrings.Get(control->GetFormatLabel());
422 return StringUtils::Format(formatString, CAEUtil::PercentToGain(value.asFloat()));
425 std::string CGUIDialogAudioSettings::FormatFlags(StreamFlags flags)
427 std::vector<std::string> localizedFlags;
428 if (flags & StreamFlags::FLAG_DEFAULT)
429 localizedFlags.emplace_back(g_localizeStrings.Get(39105));
430 if (flags & StreamFlags::FLAG_FORCED)
431 localizedFlags.emplace_back(g_localizeStrings.Get(39106));
432 if (flags & StreamFlags::FLAG_HEARING_IMPAIRED)
433 localizedFlags.emplace_back(g_localizeStrings.Get(39107));
434 if (flags & StreamFlags::FLAG_VISUAL_IMPAIRED)
435 localizedFlags.emplace_back(g_localizeStrings.Get(39108));
436 if (flags & StreamFlags::FLAG_ORIGINAL)
437 localizedFlags.emplace_back(g_localizeStrings.Get(39111));
439 std::string formated = StringUtils::Join(localizedFlags, ", ");
441 if (!formated.empty())
442 formated = StringUtils::Format(" [{}]", formated);
444 return formated;