[cstdstring] demise Format, replacing with StringUtils::Format
[vuplus_xbmc] / xbmc / video / dialogs / GUIDialogAudioSubtitleSettings.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://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/MediaSettings.h"
37 #include "settings/MediaSourceSettings.h"
38 #include "settings/Settings.h"
39 #include "guilib/LocalizeStrings.h"
40 #include "pvr/PVRManager.h"
41 #include "cores/AudioEngine/Utils/AEUtil.h"
42 #include "cores/IPlayer.h"
43 #include "utils/LangCodeExpander.h"
44 #include "utils/StringUtils.h"
45
46 using namespace std;
47 using namespace XFILE;
48 using namespace PVR;
49
50 CGUIDialogAudioSubtitleSettings::CGUIDialogAudioSubtitleSettings(void)
51     : CGUIDialogSettings(WINDOW_DIALOG_AUDIO_OSD_SETTINGS, "VideoOSDSettings.xml")
52 {
53 }
54
55 CGUIDialogAudioSubtitleSettings::~CGUIDialogAudioSubtitleSettings(void)
56 {
57 }
58
59 #define AUDIO_SETTINGS_VOLUME             1
60 #define AUDIO_SETTINGS_VOLUME_AMPLIFICATION 2
61 #define AUDIO_SETTINGS_DELAY              3
62 #define AUDIO_SETTINGS_STREAM             4
63 #define AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS 5
64 #define AUDIO_SETTINGS_DIGITAL_ANALOG     6
65
66 // separator 7
67 #define SUBTITLE_SETTINGS_ENABLE          8
68 #define SUBTITLE_SETTINGS_DELAY           9
69 #define SUBTITLE_SETTINGS_STREAM          10
70 #define SUBTITLE_SETTINGS_BROWSER         11
71 #define AUDIO_SETTINGS_MAKE_DEFAULT       12
72
73 void CGUIDialogAudioSubtitleSettings::CreateSettings()
74 {
75   m_usePopupSliders = g_SkinInfo->HasSkinFile("DialogSlider.xml");
76
77   if (g_application.m_pPlayer->HasPlayer())
78   {
79     g_application.m_pPlayer->GetAudioCapabilities(m_audioCaps);
80     g_application.m_pPlayer->GetSubtitleCapabilities(m_subCaps);
81   }
82
83   // clear out any old settings
84   m_settings.clear();
85   // create our settings
86   m_volume = g_application.GetVolume(false);
87   AddSlider(AUDIO_SETTINGS_VOLUME, 13376, &m_volume, VOLUME_MINIMUM, VOLUME_MAXIMUM / 100.0f, VOLUME_MAXIMUM, PercentAsDecibel, false);
88   if (SupportsAudioFeature(IPC_AUD_AMP))
89     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);
90   if (g_application.m_pPlayer->IsPassthrough())
91   {
92     EnableSettings(AUDIO_SETTINGS_VOLUME,false);
93     EnableSettings(AUDIO_SETTINGS_VOLUME_AMPLIFICATION,false);
94   }
95   if (SupportsAudioFeature(IPC_AUD_OFFSET))
96     AddSlider(AUDIO_SETTINGS_DELAY, 297, &CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay, -g_advancedSettings.m_videoAudioDelayRange, .025f, g_advancedSettings.m_videoAudioDelayRange, FormatDelay);
97   if (SupportsAudioFeature(IPC_AUD_SELECT_STREAM))
98     AddAudioStreams(AUDIO_SETTINGS_STREAM);
99
100   // TODO: remove this setting
101   if (SupportsAudioFeature(IPC_AUD_OUTPUT_STEREO))
102     AddBool(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, 252, &CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers, true);
103
104   m_outputmode = CSettings::Get().GetBool("audiooutput.passthrough");
105   if (SupportsAudioFeature(IPC_AUD_SELECT_OUTPUT))
106     AddBool(AUDIO_SETTINGS_DIGITAL_ANALOG, 348, &m_outputmode);
107
108   AddSeparator(7);
109   m_subtitleVisible = g_application.m_pPlayer->GetSubtitleVisible();
110   AddBool(SUBTITLE_SETTINGS_ENABLE, 13397, &m_subtitleVisible);
111   if (SupportsSubtitleFeature(IPC_SUBS_OFFSET))
112     AddSlider(SUBTITLE_SETTINGS_DELAY, 22006, &CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay, -g_advancedSettings.m_videoSubsDelayRange, 0.1f, g_advancedSettings.m_videoSubsDelayRange, FormatDelay);
113   if (SupportsSubtitleFeature(IPC_SUBS_SELECT))
114     AddSubtitleStreams(SUBTITLE_SETTINGS_STREAM);
115   if (SupportsSubtitleFeature(IPC_SUBS_EXTERNAL))
116     AddButton(SUBTITLE_SETTINGS_BROWSER,13250);
117   AddButton(AUDIO_SETTINGS_MAKE_DEFAULT, 12376);
118 }
119
120 void CGUIDialogAudioSubtitleSettings::AddAudioStreams(unsigned int id)
121 {
122   SettingInfo setting;
123   setting.id = id;
124   setting.name = g_localizeStrings.Get(460);
125   setting.type = SettingInfo::SPIN;
126   setting.min = 0;
127   setting.data = &m_audioStream;
128
129   // get the number of audio strams for the current movie
130   setting.max = (float)g_application.m_pPlayer->GetAudioStreamCount() - 1;
131   m_audioStream = g_application.m_pPlayer->GetAudioStream();
132
133   if( m_audioStream < 0 ) m_audioStream = 0;
134
135   // check if we have a single, stereo stream, and if so, allow us to split into
136   // left, right or both
137   if (!setting.max)
138   {
139     CStdString strAudioInfo;
140     g_application.m_pPlayer->GetAudioInfo(strAudioInfo);
141     int iNumChannels = atoi(strAudioInfo.Right(strAudioInfo.size() - strAudioInfo.Find("chns:") - 5).c_str());
142     CStdString strAudioCodec = strAudioInfo.Mid(7, strAudioInfo.Find(") VBR") - 5);
143     bool bDTS = strstr(strAudioCodec.c_str(), "DTS") != 0;
144     bool bAC3 = strstr(strAudioCodec.c_str(), "AC3") != 0;
145     if (iNumChannels == 2 && !(bDTS || bAC3))
146     { // ok, enable these options
147 /*      if (CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream == -1)
148       { // default to stereo stream
149         CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = 0;
150       }*/
151       setting.max = 2;
152       for (int i = 0; i <= setting.max; i++)
153         setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(13320 + i)));
154       m_audioStream = -CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream - 1;
155       m_settings.push_back(setting);
156       return;
157     }
158   }
159
160   // cycle through each audio stream and add it to our list control
161   for (int i = 0; i <= setting.max; ++i)
162   {
163     CStdString strItem;
164     CStdString strLanguage;
165
166     SPlayerAudioStreamInfo info;
167     g_application.m_pPlayer->GetAudioStreamInfo(i, info);
168
169     if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
170       strLanguage = g_localizeStrings.Get(13205); // Unknown
171
172     if (info.name.length() == 0)
173       strItem = strLanguage;
174     else
175       strItem = StringUtils::Format("%s - %s", strLanguage.c_str(), info.name.c_str());
176
177     strItem.AppendFormat(" (%i/%i)", i + 1, (int)setting.max + 1);
178     setting.entry.push_back(make_pair(setting.entry.size(), strItem));
179   }
180
181   if( setting.max < 0 )
182   {
183     setting.max = 0;
184     setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
185   }
186
187   m_settings.push_back(setting);
188 }
189
190 void CGUIDialogAudioSubtitleSettings::AddSubtitleStreams(unsigned int id)
191 {
192   SettingInfo setting;
193
194   setting.id = id;
195   setting.name = g_localizeStrings.Get(462);
196   setting.type = SettingInfo::SPIN;
197   setting.min = 0;
198   setting.data = &m_subtitleStream;
199   m_subtitleStream = CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream;
200
201   if(m_subtitleStream < 0) m_subtitleStream = 0;
202
203   // get the number of audio strams for the current movie
204   setting.max = (float)g_application.m_pPlayer->GetSubtitleCount() - 1;
205
206   // cycle through each subtitle and add it to our entry list
207   for (int i = 0; i <= setting.max; ++i)
208   {
209     SPlayerSubtitleStreamInfo info;
210     g_application.m_pPlayer->GetSubtitleStreamInfo(i, info);
211
212     CStdString strItem;
213     CStdString strLanguage;
214
215     if (!g_LangCodeExpander.Lookup(strLanguage, info.language))
216       strLanguage = g_localizeStrings.Get(13205); // Unknown
217
218     if (info.name.length() == 0)
219       strItem = strLanguage;
220     else
221       strItem = StringUtils::Format("%s - %s", strLanguage.c_str(), info.name.c_str());
222
223     strItem.AppendFormat(" (%i/%i)", i + 1, (int)setting.max + 1);
224
225     setting.entry.push_back(make_pair(setting.entry.size(), strItem));
226   }
227
228   if (setting.max < 0)
229   { // no subtitle streams - just add a "None" entry
230     m_subtitleStream = 0;
231     setting.max = 0;
232     setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
233   }
234   m_settings.push_back(setting);
235 }
236
237 void CGUIDialogAudioSubtitleSettings::OnSettingChanged(SettingInfo &setting)
238 {
239   // check and update anything that needs it
240   if (setting.id == AUDIO_SETTINGS_VOLUME)
241     g_application.SetVolume(m_volume, false); //false - value is not in percent
242   else if (setting.id == AUDIO_SETTINGS_VOLUME_AMPLIFICATION)
243   {
244     g_application.m_pPlayer->SetDynamicRangeCompression((long)(CMediaSettings::Get().GetCurrentVideoSettings().m_VolumeAmplification * 100));
245   }
246   else if (setting.id == AUDIO_SETTINGS_DELAY)
247   {
248     g_application.m_pPlayer->SetAVDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay);
249   }
250   else if (setting.id == AUDIO_SETTINGS_STREAM)
251   {
252     // first check if it's a stereo track that we can change between stereo, left and right
253     if (g_application.m_pPlayer->GetAudioStreamCount() == 1)
254     {
255       if (setting.max == 2)
256       { // we're in the case we want - call the code to switch channels etc.
257         // update the screen setting...
258         CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = -1 - m_audioStream;
259         // call monkeyh1's code here...
260         //bool bAudioOnAllSpeakers = (CSettings::Get().GetInt("audiooutput.mode") == AUDIO_IEC958) && CMediaSettings::Get().GetCurrentVideoSettings().m_OutputToAllSpeakers;
261         return;
262       }
263     }
264     // only change the audio stream if a different one has been asked for
265     if (g_application.m_pPlayer->GetAudioStream() != m_audioStream)
266     {
267       CMediaSettings::Get().GetCurrentVideoSettings().m_AudioStream = m_audioStream;
268       g_application.m_pPlayer->SetAudioStream(m_audioStream);    // Set the audio stream to the one selected
269       EnableSettings(AUDIO_SETTINGS_VOLUME, !g_application.m_pPlayer->IsPassthrough());
270     }
271   }
272   else if (setting.id == AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS)
273   {
274     g_application.Restart();
275   }
276   else if (setting.id == AUDIO_SETTINGS_DIGITAL_ANALOG)
277   {
278     CSettings::Get().SetBool("audiooutput.passthrough", m_outputmode);
279
280     EnableSettings(AUDIO_SETTINGS_OUTPUT_TO_ALL_SPEAKERS, true);
281     EnableSettings(AUDIO_SETTINGS_VOLUME, !g_application.m_pPlayer->IsPassthrough());
282   }
283   else if (setting.id == SUBTITLE_SETTINGS_ENABLE)
284   {
285     CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn = m_subtitleVisible;
286     g_application.m_pPlayer->SetSubtitleVisible(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn);
287   }
288   else if (setting.id == SUBTITLE_SETTINGS_DELAY)
289   {
290     g_application.m_pPlayer->SetSubTitleDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay);
291   }
292   else if (setting.id == SUBTITLE_SETTINGS_STREAM && setting.max > 0)
293   {
294     CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleStream = m_subtitleStream;
295     g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
296   }
297   else if (setting.id == SUBTITLE_SETTINGS_BROWSER)
298   {
299     CStdString strPath;
300     if (URIUtils::IsInRAR(g_application.CurrentFileItem().GetPath()) || URIUtils::IsInZIP(g_application.CurrentFileItem().GetPath()))
301     {
302       CURL url(g_application.CurrentFileItem().GetPath());
303       strPath = url.GetHostName();
304     }
305     else
306       strPath = g_application.CurrentFileItem().GetPath();
307
308     CStdString strMask = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.aqt|.jss|.ass|.idx|.rar|.zip";
309     if (g_application.GetCurrentPlayer() == EPC_DVDPLAYER)
310       strMask = ".srt|.rar|.zip|.ifo|.smi|.sub|.idx|.ass|.ssa|.txt";
311     VECSOURCES shares(*CMediaSourceSettings::Get().GetSources("video"));
312     if (CMediaSettings::Get().GetAdditionalSubtitleDirectoryChecked() != -1 && !CSettings::Get().GetString("subtitles.custompath").empty())
313     {
314       CMediaSource share;
315       std::vector<CStdString> paths;
316       paths.push_back(URIUtils::GetDirectory(strPath));
317       paths.push_back(CSettings::Get().GetString("subtitles.custompath"));
318       share.FromNameAndPaths("video",g_localizeStrings.Get(21367),paths);
319       shares.push_back(share);
320       strPath = share.strPath;
321       URIUtils::AddSlashAtEnd(strPath);
322     }
323     if (CGUIDialogFileBrowser::ShowAndGetFile(shares,strMask,g_localizeStrings.Get(293),strPath,false,true)) // "subtitles"
324     {
325       if (URIUtils::HasExtension(strPath, ".sub"))
326         if (CFile::Exists(URIUtils::ReplaceExtension(strPath, ".idx")))
327           strPath = URIUtils::ReplaceExtension(strPath, ".idx");
328       
329       int id = g_application.m_pPlayer->AddSubtitle(strPath);
330       if(id >= 0)
331       {
332         m_subtitleStream = id;
333         g_application.m_pPlayer->SetSubtitle(m_subtitleStream);
334         g_application.m_pPlayer->SetSubtitleVisible(true);
335       }
336       CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleCached = true;
337       Close();
338     }
339   }
340   else if (setting.id == AUDIO_SETTINGS_MAKE_DEFAULT)
341   {
342     if (!g_passwordManager.CheckSettingLevelLock(SettingLevelExpert) &&
343         CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE)
344       return;
345
346     // prompt user if they are sure
347     if (CGUIDialogYesNo::ShowAndGetInput(12376, 750, 0, 12377))
348     { // reset the settings
349       CVideoDatabase db;
350       db.Open();
351       db.EraseVideoSettings();
352       db.Close();
353       CMediaSettings::Get().GetDefaultVideoSettings() = CMediaSettings::Get().GetCurrentVideoSettings();
354       CMediaSettings::Get().GetDefaultVideoSettings().m_SubtitleStream = -1;
355       CMediaSettings::Get().GetDefaultVideoSettings().m_AudioStream = -1;
356       CSettings::Get().Save();
357     }
358   }
359
360   if (g_PVRManager.IsPlayingRadio() || g_PVRManager.IsPlayingTV())
361     g_PVRManager.TriggerSaveChannelSettings();
362 }
363
364 void CGUIDialogAudioSubtitleSettings::FrameMove()
365 {
366   m_volume = g_application.GetVolume(false);
367   UpdateSetting(AUDIO_SETTINGS_VOLUME);
368   if (g_application.m_pPlayer->HasPlayer())
369   {
370     // these settings can change on the fly
371     UpdateSetting(AUDIO_SETTINGS_DELAY);
372     UpdateSetting(SUBTITLE_SETTINGS_ENABLE);
373     UpdateSetting(SUBTITLE_SETTINGS_DELAY);
374   }
375   CGUIDialogSettings::FrameMove();
376 }
377
378 CStdString CGUIDialogAudioSubtitleSettings::PercentAsDecibel(float value, float interval)
379 {
380   return StringUtils::Format("%2.1f dB", CAEUtil::PercentToGain(value));;
381 }
382
383 CStdString CGUIDialogAudioSubtitleSettings::FormatDecibel(float value, float interval)
384 {
385   return StringUtils::Format("%2.1f dB", value);;
386 }
387
388 CStdString CGUIDialogAudioSubtitleSettings::FormatDelay(float value, float interval)
389 {
390   CStdString text;
391   if (fabs(value) < 0.5f*interval)
392     text = StringUtils::Format(g_localizeStrings.Get(22003).c_str(), 0.0);
393   else if (value < 0)
394     text = StringUtils::Format(g_localizeStrings.Get(22004).c_str(), fabs(value));
395   else
396     text = StringUtils::Format(g_localizeStrings.Get(22005).c_str(), value);
397   return text;
398 }
399
400 bool CGUIDialogAudioSubtitleSettings::SupportsAudioFeature(int feature)
401 {
402   for (Features::iterator itr = m_audioCaps.begin(); itr != m_audioCaps.end(); itr++)
403   {
404     if(*itr == feature || *itr == IPC_AUD_ALL)
405       return true;
406   }
407   return false;
408 }
409
410 bool CGUIDialogAudioSubtitleSettings::SupportsSubtitleFeature(int feature)
411 {
412   for (Features::iterator itr = m_subCaps.begin(); itr != m_subCaps.end(); itr++)
413   {
414     if(*itr == feature || *itr == IPC_SUBS_ALL)
415       return true;
416   }
417   return false;
418 }