Merge pull request #2531 from Montellese/settings_cleanup_4
[vuplus_xbmc] / xbmc / video / dialogs / GUIDialogAudioSubtitleSettings.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include "system.h"
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"
31 #include "URL.h"
32 #include "FileItem.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"
45
46 using namespace std;
47 using namespace XFILE;
48 using namespace PVR;
49
50 #ifdef HAS_VIDEO_PLAYBACK
51 extern void xbox_audio_switch_channel(int iAudioStream, bool bAudioOnAllSpeakers); //lowlevel audio
52 #endif
53
54 CGUIDialogAudioSubtitleSettings::CGUIDialogAudioSubtitleSettings(void)
55     : CGUIDialogSettings(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "VideoOSDSettings.xml")
56 {
57 }
58
59 CGUIDialogAudioSubtitleSettings::~CGUIDialogAudioSubtitleSettings(void)
60 {
61 }
62
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
69
70 // separator 7
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
76
77 void CGUIDialogAudioSubtitleSettings::CreateSettings()
78 {
79   m_usePopupSliders = g_SkinInfo->HasSkinFile("DialogSlider.xml");
80
81   if (g_application.m_pPlayer)
82   {
83     g_application.m_pPlayer->GetAudioCapabilities(m_audioCaps);
84     g_application.m_pPlayer->GetSubtitleCapabilities(m_subCaps);
85   }
86
87   // clear out any old settings
88   m_settings.clear();
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())
95   {
96     EnableSettings(AUDIO_SETTINGS_VOLUME,false);
97     EnableSettings(AUDIO_SETTINGS_VOLUME_AMPLIFICATION,false);
98   }
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);
103
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")));
107
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);
112
113   AddSeparator(7);
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);
123 }
124
125 void CGUIDialogAudioSubtitleSettings::AddAudioStreams(unsigned int id)
126 {
127   SettingInfo setting;
128   setting.id = id;
129   setting.name = g_localizeStrings.Get(460);
130   setting.type = SettingInfo::SPIN;
131   setting.min = 0;
132   setting.data = &m_audioStream;
133
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();
137
138   if( m_audioStream < 0 ) m_audioStream = 0;
139
140   // check if we have a single, stereo stream, and if so, allow us to split into
141   // left, right or both
142   if (!setting.max)
143   {
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;
155       }*/
156       setting.max = 2;
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);
161       return;
162     }
163   }
164
165   // cycle through each audio stream and add it to our list control
166   for (int i = 0; i <= setting.max; ++i)
167   {
168     CStdString strItem;
169     CStdString strLanguage;
170
171     SPlayerAudioStreamInfo info;
172     g_application.m_pPlayer->GetAudioStreamInfo(i, info);
173
174     if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
175       strLanguage = g_localizeStrings.Get(13205); // Unknown
176
177     if (info.name.length() == 0)
178       strItem = strLanguage;
179     else
180       strItem.Format("%s - %s", strLanguage.c_str(), info.name.c_str());
181
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));
184   }
185
186   if( setting.max < 0 )
187   {
188     setting.max = 0;
189     setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
190   }
191
192   m_settings.push_back(setting);
193 }
194
195 void CGUIDialogAudioSubtitleSettings::AddSubtitleStreams(unsigned int id)
196 {
197   SettingInfo setting;
198
199   setting.id = id;
200   setting.name = g_localizeStrings.Get(462);
201   setting.type = SettingInfo::SPIN;
202   setting.min = 0;
203   setting.data = &m_subtitleStream;
204   m_subtitleStream = g_application.m_pPlayer->GetSubtitle();
205
206   if(m_subtitleStream < 0) m_subtitleStream = 0;
207
208   // get the number of audio strams for the current movie
209   setting.max = (float)g_application.m_pPlayer->GetSubtitleCount() - 1;
210
211   // cycle through each subtitle and add it to our entry list
212   for (int i = 0; i <= setting.max; ++i)
213   {
214     SPlayerSubtitleStreamInfo info;
215     g_application.m_pPlayer->GetSubtitleStreamInfo(i, info);
216
217     CStdString strItem;
218     CStdString strLanguage;
219
220     if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
221       strLanguage = g_localizeStrings.Get(13205); // Unknown
222
223     if (info.name.length() == 0)
224       strItem = strLanguage;
225     else
226       strItem.Format("%s - %s", strLanguage.c_str(), info.name.c_str());
227
228     strItem.Format("%s (%i/%i)", strItem.c_str(), i + 1, (int)setting.max + 1);
229
230     setting.entry.push_back(make_pair(setting.entry.size(), strItem));
231   }
232
233   if (setting.max < 0)
234   { // no subtitle streams - just add a "None" entry
235     m_subtitleStream = 0;
236     setting.max = 0;
237     setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
238   }
239   m_settings.push_back(setting);
240 }
241
242 void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting)
243 {
244   // check and update anything that needs it
245   if (setting.id == AUDIO_SETTINGS_VOLUME)
246   {
247     g_settings.m_fVolumeLevel = m_volume;
248     g_application.SetVolume(m_volume, false);//false - value is not in percent
249   }
250   else if (setting.id == AUDIO_SETTINGS_VOLUME_AMPLIFICATION)
251   {
252     if (g_application.m_pPlayer)
253       g_application.m_pPlayer->SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
254   }
255   else if (setting.id == AUDIO_SETTINGS_DELAY)
256   {
257     if (g_application.m_pPlayer)
258       g_application.m_pPlayer->SetAVDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay);
259   }
260   else if (setting.id == AUDIO_SETTINGS_STREAM)
261   {
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)
264     {
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;
271         return;
272       }
273     }
274     // only change the audio stream if a different one has been asked for
275     if (g_application.m_pPlayer->GetAudioStream() != m_audioStream)
276     {
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());
280     }
281   }
282   else if (setting.id == AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS)
283   {
284     g_application.Restart();
285   }
286   else if (setting.id == AUDIO_SETTINGS_DIGITAL_ANALOG)
287   {
288     bool bitstream = false;
289
290     switch(m_outputmode)
291     {
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;
295     }
296
297     EnableSettings(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, bitstream);
298     g_application.Restart();
299     EnableSettings(AUDIO_SETTINGS_VOLUME, !g_application.m_pPlayer->IsPassthrough());
300   }
301   else if (setting.id == SUBTITLE_SETTINGS_ENABLE)
302   {
303     CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn = m_subtitleVisible;
304     g_application.m_pPlayer->SetSubtitleVisible(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn);
305   }
306   else if (setting.id == SUBTITLE_SETTINGS_DELAY)
307   {
308     g_application.m_pPlayer->SetSubTitleDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay);
309   }
310   else if (setting.id == SUBTITLE_SETTINGS_STREAM && setting.max > 0)
311   {
312     CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream = m_subtitleStream;
313     g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
314   }
315   else if (setting.id == SUBTITLE_SETTINGS_BROWSER)
316   {
317     CStdString strPath;
318     if (URIUtils::IsInRAR(g_application.CurrentFileItem().GetPath()) || URIUtils::IsInZIP(g_application.CurrentFileItem().GetPath()))
319     {
320       CURL url(g_application.CurrentFileItem().GetPath());
321       strPath = url.GetHostName();
322     }
323     else
324       strPath = g_application.CurrentFileItem().GetPath();
325
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())
331     {
332       CMediaSource share;
333       std::vector<CStdString> paths;
334       CStdString strPath1;
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);
343     }
344     if (CGUIDialogFileBrowser::ShowAndGetFile(shares,strMask,g_localizeStrings.Get(293),strPath,false,true)) // "subtitles"
345     {
346       if (URIUtils::GetExtension(strPath) == ".sub")
347         if (CFile::Exists(URIUtils::ReplaceExtension(strPath, ".idx")))
348           strPath = URIUtils::ReplaceExtension(strPath, ".idx");
349       
350       int id = g_application.m_pPlayer->AddSubtitle(strPath);
351       if(id >= 0)
352       {
353         m_subtitleStream = id;
354         g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
355         g_application.m_pPlayer->SetSubtitleVisible(true);
356       }
357       CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleCached = true;
358       Close();
359     }
360   }
361   else if (setting.id == AUDIO_SETTINGS_MAKE_DEFAULT)
362   {
363     if (CProfilesManager::Get().GetCurrentProfile().settingsLocked() &&
364         CProfilesManager::Get().GetMasterProfile().getLockMode() != ::LOCK_MODE_EVERYONE)
365       if (!g_passwordManager.IsMasterLockUnlocked(true))
366         return;
367
368     // prompt user if they are sure
369     if (CGUIDialogYesNo::ShowAndGetInput(12376, 750, 0, 12377))
370     { // reset the settings
371       CVideoDatabase db;
372       db.Open();
373       db.EraseVideoSettings();
374       db.Close();
375       CMediaSettings::Get().GetDefaultVideoSettings() = CMediaSettings::Get().GetCurrentVideoSettings();
376       CMediaSettings::Get().GetDefaultVideoSettings().m_SubtitleStream = -1;
377       CMediaSettings::Get().GetDefaultVideoSettings().m_AudioStream = -1;
378       g_settings.Save();
379     }
380   }
381
382   if (g_PVRManager.IsPlayingRadio() || g_PVRManager.IsPlayingTV())
383     g_PVRManager.TriggerSaveChannelSettings();
384 }
385
386 void CGUIDialogAudioSubtitleSettings::FrameMove()
387 {
388   m_volume = g_settings.m_fVolumeLevel;
389   UpdateSetting(AUDIO_SETTINGS_VOLUME);
390   if (g_application.m_pPlayer)
391   {
392     // these settings can change on the fly
393     UpdateSetting(AUDIO_SETTINGS_DELAY);
394     UpdateSetting(SUBTITLE_SETTINGS_ENABLE);
395     UpdateSetting(SUBTITLE_SETTINGS_DELAY);
396   }
397   CGUIDialogSettings::FrameMove();
398 }
399
400 CStdString CGUIDialogAudioSubtitleSettings::PercentAsDecibel(float value, float interval)
401 {
402   CStdString text;
403   text.Format("%2.1f dB", CAEUtil::PercentToGain(value));
404   return text;
405 }
406
407 CStdString CGUIDialogAudioSubtitleSettings::FormatDecibel(float value, float interval)
408 {
409   CStdString text;
410   text.Format("%2.1f dB", value);
411   return text;
412 }
413
414 CStdString CGUIDialogAudioSubtitleSettings::FormatDelay(float value, float interval)
415 {
416   CStdString text;
417   if (fabs(value) < 0.5f*interval)
418     text.Format(g_localizeStrings.Get(22003).c_str(), 0.0);
419   else if (value < 0)
420     text.Format(g_localizeStrings.Get(22004).c_str(), fabs(value));
421   else
422     text.Format(g_localizeStrings.Get(22005).c_str(), value);
423   return text;
424 }
425
426 bool CGUIDialogAudioSubtitleSettings::SupportsAudioFeature(int feature)
427 {
428   for (Features::iterator itr = m_audioCaps.begin(); itr != m_audioCaps.end(); itr++)
429   {
430     if(*itr == feature || *itr == IPC_AUD_ALL)
431       return true;
432   }
433   return false;
434 }
435
436 bool CGUIDialogAudioSubtitleSettings::SupportsSubtitleFeature(int feature)
437 {
438   for (Features::iterator itr = m_subCaps.begin(); itr != m_subCaps.end(); itr++)
439   {
440     if(*itr == feature || *itr == IPC_SUBS_ALL)
441       return true;
442   }
443   return false;
444 }