2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "GUIDialogAudioSubtitleSettings.h"
23 #include "dialogs/GUIDialogFileBrowser.h"
24 #include "GUIPassword.h"
25 #include "utils/URIUtils.h"
26 #include "Application.h"
27 #include "video/VideoDatabase.h"
28 #include "dialogs/GUIDialogYesNo.h"
29 #include "filesystem/Directory.h"
30 #include "filesystem/File.h"
33 #include "addons/Skin.h"
34 #include "profiles/ProfilesManager.h"
35 #include "settings/AdvancedSettings.h"
36 #include "settings/Settings.h"
37 #include "settings/GUISettings.h"
38 #include "settings/MediaSettings.h"
39 #include "settings/MediaSourceSettings.h"
40 #include "guilib/LocalizeStrings.h"
41 #include "pvr/PVRManager.h"
42 #include "cores/AudioEngine/Utils/AEUtil.h"
43 #include "cores/IPlayer.h"
44 #include "utils/LangCodeExpander.h"
47 using namespace XFILE;
50 #ifdef HAS_VIDEO_PLAYBACK
51 extern void xbox_audio_switch_channel(int iAudioStream, bool bAudioOnAllSpeakers); //lowlevel audio
54 CGUIDialogAudioSubtitleSettings::CGUIDialogAudioSubtitleSettings(void)
55 : CGUIDialogSettings(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "VideoOSDSettings.xml")
59 CGUIDialogAudioSubtitleSettings::~CGUIDialogAudioSubtitleSettings(void)
63 #define AUDIO_SETTINGS_VOLUME 1
64 #define AUDIO_SETTINGS_VOLUME_AMPLIFICATION 2
65 #define AUDIO_SETTINGS_DELAY 3
66 #define AUDIO_SETTINGS_STREAM 4
67 #define AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS 5
68 #define AUDIO_SETTINGS_DIGITAL_ANALOG 6
71 #define SUBTITLE_SETTINGS_ENABLE 8
72 #define SUBTITLE_SETTINGS_DELAY 9
73 #define SUBTITLE_SETTINGS_STREAM 10
74 #define SUBTITLE_SETTINGS_BROWSER 11
75 #define AUDIO_SETTINGS_MAKE_DEFAULT 12
77 void CGUIDialogAudioSubtitleSettings::CreateSettings()
79 m_usePopupSliders = g_SkinInfo->HasSkinFile("DialogSlider.xml");
81 if (g_application.m_pPlayer)
83 g_application.m_pPlayer->GetAudioCapabilities(m_audioCaps);
84 g_application.m_pPlayer->GetSubtitleCapabilities(m_subCaps);
87 // clear out any old settings
89 // create our settings
90 m_volume = g_settings.m_fVolumeLevel;
91 AddSlider(AUDIO_SETTINGS_VOLUME, 13376, &m_volume, VOLUME_MINIMUM, VOLUME_MAXIMUM / 100.0f, VOLUME_MAXIMUM, PercentAsDecibel, false);
92 if (SupportsAudioFeature(IPC_AUD_AMP))
93 AddSlider(AUDIO_SETTINGS_VOLUME_AMPLIFICATION, 660, &CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification, VOLUME_DRC_MINIMUM * 0.01f, (VOLUME_DRC_MAXIMUM - VOLUME_DRC_MINIMUM) / 6000.0f, VOLUME_DRC_MAXIMUM * 0.01f, FormatDecibel, false);
94 if (g_application.m_pPlayer && g_application.m_pPlayer->IsPassthrough())
96 EnableSettings(AUDIO_SETTINGS_VOLUME,false);
97 EnableSettings(AUDIO_SETTINGS_VOLUME_AMPLIFICATION,false);
99 if (SupportsAudioFeature(IPC_AUD_OFFSET))
100 AddSlider(AUDIO_SETTINGS_DELAY, 297, &CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay, -g_advancedSettings.m_videoAudioDelayRange, .025f, g_advancedSettings.m_videoAudioDelayRange, FormatDelay);
101 if (SupportsAudioFeature(IPC_AUD_SELECT_STREAM))
102 AddAudioStreams(AUDIO_SETTINGS_STREAM);
104 // only show stuff available in digital mode if we have digital output
105 if (SupportsAudioFeature(IPC_AUD_OUTPUT_STEREO))
106 AddBool(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, 252, &CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers, AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")));
108 int settings[3] = { 338, 339, 420 }; //ANALOG, IEC958, HDMI
109 m_outputmode = g_guiSettings.GetInt("audiooutput.mode");
110 if (SupportsAudioFeature(IPC_AUD_SELECT_OUTPUT))
111 AddSpin(AUDIO_SETTINGS_DIGITAL_ANALOG, 337, &m_outputmode, 3, settings);
114 m_subtitleVisible = g_application.m_pPlayer->GetSubtitleVisible();
115 AddBool(SUBTITLE_SETTINGS_ENABLE, 13397, &m_subtitleVisible);
116 if (SupportsSubtitleFeature(IPC_SUBS_OFFSET))
117 AddSlider(SUBTITLE_SETTINGS_DELAY, 22006, &CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay, -g_advancedSettings.m_videoSubsDelayRange, 0.1f, g_advancedSettings.m_videoSubsDelayRange, FormatDelay);
118 if (SupportsSubtitleFeature(IPC_SUBS_SELECT))
119 AddSubtitleStreams(SUBTITLE_SETTINGS_STREAM);
120 if (SupportsSubtitleFeature(IPC_SUBS_EXTERNAL))
121 AddButton(SUBTITLE_SETTINGS_BROWSER,13250);
122 AddButton(AUDIO_SETTINGS_MAKE_DEFAULT, 12376);
125 void CGUIDialogAudioSubtitleSettings::AddAudioStreams(unsigned int id)
129 setting.name = g_localizeStrings.Get(460);
130 setting.type = SettingInfo::SPIN;
132 setting.data = &m_audioStream;
134 // get the number of audio strams for the current movie
135 setting.max = (float)g_application.m_pPlayer->GetAudioStreamCount() - 1;
136 m_audioStream = g_application.m_pPlayer->GetAudioStream();
138 if( m_audioStream < 0 ) m_audioStream = 0;
140 // check if we have a single, stereo stream, and if so, allow us to split into
141 // left, right or both
144 CStdString strAudioInfo;
145 g_application.m_pPlayer->GetAudioInfo(strAudioInfo);
146 int iNumChannels = atoi(strAudioInfo.Right(strAudioInfo.size() - strAudioInfo.Find("chns:") - 5).c_str());
147 CStdString strAudioCodec = strAudioInfo.Mid(7, strAudioInfo.Find(") VBR") - 5);
148 bool bDTS = strstr(strAudioCodec.c_str(), "DTS") != 0;
149 bool bAC3 = strstr(strAudioCodec.c_str(), "AC3") != 0;
150 if (iNumChannels == 2 && !(bDTS || bAC3))
151 { // ok, enable these options
152 /* if (CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream == -1)
153 { // default to stereo stream
154 CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = 0;
157 for (int i = 0; i <= setting.max; i++)
158 setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(13320 + i)));
159 m_audioStream = -CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream - 1;
160 m_settings.push_back(setting);
165 // cycle through each audio stream and add it to our list control
166 for (int i = 0; i <= setting.max; ++i)
169 CStdString strLanguage;
171 SPlayerAudioStreamInfo info;
172 g_application.m_pPlayer->GetAudioStreamInfo(i, info);
174 if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
175 strLanguage = g_localizeStrings.Get(13205); // Unknown
177 if (info.name.length() == 0)
178 strItem = strLanguage;
180 strItem.Format("%s - %s", strLanguage.c_str(), info.name.c_str());
182 strItem.Format("%s (%i/%i)", strItem.c_str(), i + 1, (int)setting.max + 1);
183 setting.entry.push_back(make_pair(setting.entry.size(), strItem));
186 if( setting.max < 0 )
189 setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
192 m_settings.push_back(setting);
195 void CGUIDialogAudioSubtitleSettings::AddSubtitleStreams(unsigned int id)
200 setting.name = g_localizeStrings.Get(462);
201 setting.type = SettingInfo::SPIN;
203 setting.data = &m_subtitleStream;
204 m_subtitleStream = g_application.m_pPlayer->GetSubtitle();
206 if(m_subtitleStream < 0) m_subtitleStream = 0;
208 // get the number of audio strams for the current movie
209 setting.max = (float)g_application.m_pPlayer->GetSubtitleCount() - 1;
211 // cycle through each subtitle and add it to our entry list
212 for (int i = 0; i <= setting.max; ++i)
214 SPlayerSubtitleStreamInfo info;
215 g_application.m_pPlayer->GetSubtitleStreamInfo(i, info);
218 CStdString strLanguage;
220 if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
221 strLanguage = g_localizeStrings.Get(13205); // Unknown
223 if (info.name.length() == 0)
224 strItem = strLanguage;
226 strItem.Format("%s - %s", strLanguage.c_str(), info.name.c_str());
228 strItem.Format("%s (%i/%i)", strItem.c_str(), i + 1, (int)setting.max + 1);
230 setting.entry.push_back(make_pair(setting.entry.size(), strItem));
234 { // no subtitle streams - just add a "None" entry
235 m_subtitleStream = 0;
237 setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
239 m_settings.push_back(setting);
242 void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting)
244 // check and update anything that needs it
245 if (setting.id == AUDIO_SETTINGS_VOLUME)
247 g_settings.m_fVolumeLevel = m_volume;
248 g_application.SetVolume(m_volume, false);//false - value is not in percent
250 else if (setting.id == AUDIO_SETTINGS_VOLUME_AMPLIFICATION)
252 if (g_application.m_pPlayer)
253 g_application.m_pPlayer->SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
255 else if (setting.id == AUDIO_SETTINGS_DELAY)
257 if (g_application.m_pPlayer)
258 g_application.m_pPlayer->SetAVDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay);
260 else if (setting.id == AUDIO_SETTINGS_STREAM)
262 // first check if it's a stereo track that we can change between stereo, left and right
263 if (g_application.m_pPlayer->GetAudioStreamCount() == 1)
265 if (setting.max == 2)
266 { // we're in the case we want - call the code to switch channels etc.
267 // update the screen setting...
268 CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = -1 - m_audioStream;
269 // call monkeyh1's code here...
270 //bool bAudioOnAllSpeakers = (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_IEC958) && CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers;
274 // only change the audio stream if a different one has been asked for
275 if (g_application.m_pPlayer->GetAudioStream() != m_audioStream)
277 CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = m_audioStream;
278 g_application.m_pPlayer->SetAudioStream(m_audioStream); // Set the audio stream to the one selected
279 EnableSettings(AUDIO_SETTINGS_VOLUME, !g_application.m_pPlayer->IsPassthrough());
282 else if (setting.id == AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS)
284 g_application.Restart();
286 else if (setting.id == AUDIO_SETTINGS_DIGITAL_ANALOG)
288 bool bitstream = false;
292 case 0: g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG ); break;
293 case 1: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958 ); bitstream = true; break;
294 case 2: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); bitstream = true; break;
297 EnableSettings(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, bitstream);
298 g_application.Restart();
299 EnableSettings(AUDIO_SETTINGS_VOLUME, !g_application.m_pPlayer->IsPassthrough());
301 else if (setting.id == SUBTITLE_SETTINGS_ENABLE)
303 CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn = m_subtitleVisible;
304 g_application.m_pPlayer->SetSubtitleVisible(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn);
306 else if (setting.id == SUBTITLE_SETTINGS_DELAY)
308 g_application.m_pPlayer->SetSubTitleDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay);
310 else if (setting.id == SUBTITLE_SETTINGS_STREAM && setting.max > 0)
312 CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream = m_subtitleStream;
313 g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
315 else if (setting.id == SUBTITLE_SETTINGS_BROWSER)
318 if (URIUtils::IsInRAR(g_application.CurrentFileItem().GetPath()) || URIUtils::IsInZIP(g_application.CurrentFileItem().GetPath()))
320 CURL url(g_application.CurrentFileItem().GetPath());
321 strPath = url.GetHostName();
324 strPath = g_application.CurrentFileItem().GetPath();
326 CStdString strMask = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.aqt|.jss|.ass|.idx|.rar|.zip";
327 if (g_application.GetCurrentPlayer() == EPC_DVDPLAYER)
328 strMask = ".srt|.rar|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.txt";
329 VECSOURCES shares(*CMediaSourceSettings::Get().GetSources("video"));
330 if (g_settings.iAdditionalSubtitleDirectoryChecked != -1 && !g_guiSettings.GetString("subtitles.custompath").IsEmpty())
333 std::vector<CStdString> paths;
335 URIUtils::GetDirectory(strPath,strPath1);
336 paths.push_back(strPath1);
337 strPath1 = g_guiSettings.GetString("subtitles.custompath");
338 paths.push_back(g_guiSettings.GetString("subtitles.custompath"));
339 share.FromNameAndPaths("video",g_localizeStrings.Get(21367),paths);
340 shares.push_back(share);
341 strPath = share.strPath;
342 URIUtils::AddSlashAtEnd(strPath);
344 if (CGUIDialogFileBrowser::ShowAndGetFile(shares,strMask,g_localizeStrings.Get(293),strPath,false,true)) // "subtitles"
346 if (URIUtils::GetExtension(strPath) == ".sub")
347 if (CFile::Exists(URIUtils::ReplaceExtension(strPath, ".idx")))
348 strPath = URIUtils::ReplaceExtension(strPath, ".idx");
350 int id = g_application.m_pPlayer->AddSubtitle(strPath);
353 m_subtitleStream = id;
354 g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
355 g_application.m_pPlayer->SetSubtitleVisible(true);
357 CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleCached = true;
361 else if (setting.id == AUDIO_SETTINGS_MAKE_DEFAULT)
363 if (CProfilesManager::Get().GetCurrentProfile().settingsLocked() &&
364 CProfilesManager::Get().GetMasterProfile().getLockMode() != ::LOCK_MODE_EVERYONE)
365 if (!g_passwordManager.IsMasterLockUnlocked(true))
368 // prompt user if they are sure
369 if (CGUIDialogYesNo::ShowAndGetInput(12376, 750, 0, 12377))
370 { // reset the settings
373 db.EraseVideoSettings();
375 CMediaSettings::Get().GetDefaultVideoSettings() = CMediaSettings::Get().GetCurrentVideoSettings();
376 CMediaSettings::Get().GetDefaultVideoSettings().m_SubtitleStream = -1;
377 CMediaSettings::Get().GetDefaultVideoSettings().m_AudioStream = -1;
382 if (g_PVRManager.IsPlayingRadio() || g_PVRManager.IsPlayingTV())
383 g_PVRManager.TriggerSaveChannelSettings();
386 void CGUIDialogAudioSubtitleSettings::FrameMove()
388 m_volume = g_settings.m_fVolumeLevel;
389 UpdateSetting(AUDIO_SETTINGS_VOLUME);
390 if (g_application.m_pPlayer)
392 // these settings can change on the fly
393 UpdateSetting(AUDIO_SETTINGS_DELAY);
394 UpdateSetting(SUBTITLE_SETTINGS_ENABLE);
395 UpdateSetting(SUBTITLE_SETTINGS_DELAY);
397 CGUIDialogSettings::FrameMove();
400 CStdString CGUIDialogAudioSubtitleSettings::PercentAsDecibel(float value, float interval)
403 text.Format("%2.1f dB", CAEUtil::PercentToGain(value));
407 CStdString CGUIDialogAudioSubtitleSettings::FormatDecibel(float value, float interval)
410 text.Format("%2.1f dB", value);
414 CStdString CGUIDialogAudioSubtitleSettings::FormatDelay(float value, float interval)
417 if (fabs(value) < 0.5f*interval)
418 text.Format(g_localizeStrings.Get(22003).c_str(), 0.0);
420 text.Format(g_localizeStrings.Get(22004).c_str(), fabs(value));
422 text.Format(g_localizeStrings.Get(22005).c_str(), value);
426 bool CGUIDialogAudioSubtitleSettings::SupportsAudioFeature(int feature)
428 for (Features::iterator itr = m_audioCaps.begin(); itr != m_audioCaps.end(); itr++)
430 if(*itr == feature || *itr == IPC_AUD_ALL)
436 bool CGUIDialogAudioSubtitleSettings::SupportsSubtitleFeature(int feature)
438 for (Features::iterator itr = m_subCaps.begin(); itr != m_subCaps.end(); itr++)
440 if(*itr == feature || *itr == IPC_SUBS_ALL)