Merge pull request #3643 from FernetMenta/osd
[vuplus_xbmc] / xbmc / settings / MediaSettings.cpp
1 /*
2  *      Copyright (C) 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 <limits.h>
22
23 #include "MediaSettings.h"
24 #include "Application.h"
25 #include "Util.h"
26 #include "dialogs/GUIDialogContextMenu.h"
27 #include "dialogs/GUIDialogFileBrowser.h"
28 #include "dialogs/GUIDialogYesNo.h"
29 #include "guilib/WindowIDs.h"
30 #include "interfaces/Builtins.h"
31 #include "music/MusicDatabase.h"
32 #include "profiles/ProfilesManager.h"
33 #include "settings/lib/Setting.h"
34 #include "storage/MediaManager.h"
35 #include "threads/SingleLock.h"
36 #include "utils/log.h"
37 #include "utils/URIUtils.h"
38 #include "utils/XBMCTinyXML.h"
39 #include "utils/XMLUtils.h"
40 #include "video/VideoDatabase.h"
41
42 using namespace std;
43
44 CMediaSettings::CMediaSettings()
45 {
46   m_watchedModes["movies"] = WatchedModeAll;
47   m_watchedModes["tvshows"] = WatchedModeAll;
48   m_watchedModes["musicvideos"] = WatchedModeAll;
49
50   m_musicPlaylistRepeat = false;
51   m_musicPlaylistShuffle = false;
52   m_videoPlaylistRepeat = false;
53   m_videoPlaylistShuffle = false;
54
55   m_videoStartWindowed = false;
56   m_additionalSubtitleDirectoryChecked = 0;
57
58   m_musicNeedsUpdate = 0;
59   m_videoNeedsUpdate = 0;
60 }
61
62 CMediaSettings::~CMediaSettings()
63 { }
64
65 CMediaSettings& CMediaSettings::Get()
66 {
67   static CMediaSettings sMediaSettings;
68   return sMediaSettings;
69 }
70
71 bool CMediaSettings::Load(const TiXmlNode *settings)
72 {
73   if (settings == NULL)
74     return false;
75
76   CSingleLock lock(m_critical);
77   const TiXmlElement *pElement = settings->FirstChildElement("defaultvideosettings");
78   if (pElement != NULL)
79   {
80     int deinterlaceMode;
81     bool deinterlaceModePresent = XMLUtils::GetInt(pElement, "deinterlacemode", deinterlaceMode, VS_DEINTERLACEMODE_OFF, VS_DEINTERLACEMODE_FORCE);
82     int interlaceMethod;
83     bool interlaceMethodPresent = XMLUtils::GetInt(pElement, "interlacemethod", interlaceMethod, VS_INTERLACEMETHOD_AUTO, VS_INTERLACEMETHOD_MAX);
84     // For smooth conversion of settings stored before the deinterlaceMode existed
85     if (!deinterlaceModePresent && interlaceMethodPresent)
86     {
87       if (interlaceMethod == VS_INTERLACEMETHOD_NONE)
88       {
89         deinterlaceMode = VS_DEINTERLACEMODE_OFF;
90         interlaceMethod = VS_INTERLACEMETHOD_AUTO;
91       }
92       else if (interlaceMethod == VS_INTERLACEMETHOD_AUTO)
93         deinterlaceMode = VS_DEINTERLACEMODE_AUTO;
94       else
95         deinterlaceMode = VS_DEINTERLACEMODE_FORCE;
96     }
97     m_defaultVideoSettings.m_DeinterlaceMode = (EDEINTERLACEMODE)deinterlaceMode;
98     m_defaultVideoSettings.m_InterlaceMethod = (EINTERLACEMETHOD)interlaceMethod;
99     int scalingMethod;
100     if (!XMLUtils::GetInt(pElement, "scalingmethod", scalingMethod, VS_SCALINGMETHOD_NEAREST, VS_SCALINGMETHOD_MAX))
101       scalingMethod = (int)VS_SCALINGMETHOD_LINEAR;
102     m_defaultVideoSettings.m_ScalingMethod = (ESCALINGMETHOD)scalingMethod;
103
104     XMLUtils::GetInt(pElement, "viewmode", m_defaultVideoSettings.m_ViewMode, ViewModeNormal, ViewModeCustom);
105     if (!XMLUtils::GetFloat(pElement, "zoomamount", m_defaultVideoSettings.m_CustomZoomAmount, 0.5f, 2.0f))
106       m_defaultVideoSettings.m_CustomZoomAmount = 1.0f;
107     if (!XMLUtils::GetFloat(pElement, "pixelratio", m_defaultVideoSettings.m_CustomPixelRatio, 0.5f, 2.0f))
108       m_defaultVideoSettings.m_CustomPixelRatio = 1.0f;
109     if (!XMLUtils::GetFloat(pElement, "verticalshift", m_defaultVideoSettings.m_CustomVerticalShift, -2.0f, 2.0f))
110       m_defaultVideoSettings.m_CustomVerticalShift = 0.0f;
111     if (!XMLUtils::GetFloat(pElement, "volumeamplification", m_defaultVideoSettings.m_VolumeAmplification, VOLUME_DRC_MINIMUM * 0.01f, VOLUME_DRC_MAXIMUM * 0.01f))
112       m_defaultVideoSettings.m_VolumeAmplification = VOLUME_DRC_MINIMUM * 0.01f;
113     if (!XMLUtils::GetFloat(pElement, "noisereduction", m_defaultVideoSettings.m_NoiseReduction, 0.0f, 1.0f))
114       m_defaultVideoSettings.m_NoiseReduction = 0.0f;
115     XMLUtils::GetBoolean(pElement, "postprocess", m_defaultVideoSettings.m_PostProcess);
116     if (!XMLUtils::GetFloat(pElement, "sharpness", m_defaultVideoSettings.m_Sharpness, -1.0f, 1.0f))
117       m_defaultVideoSettings.m_Sharpness = 0.0f;
118     XMLUtils::GetBoolean(pElement, "outputtoallspeakers", m_defaultVideoSettings.m_OutputToAllSpeakers);
119     XMLUtils::GetBoolean(pElement, "showsubtitles", m_defaultVideoSettings.m_SubtitleOn);
120     if (!XMLUtils::GetFloat(pElement, "brightness", m_defaultVideoSettings.m_Brightness, 0, 100))
121       m_defaultVideoSettings.m_Brightness = 50;
122     if (!XMLUtils::GetFloat(pElement, "contrast", m_defaultVideoSettings.m_Contrast, 0, 100))
123       m_defaultVideoSettings.m_Contrast = 50;
124     if (!XMLUtils::GetFloat(pElement, "gamma", m_defaultVideoSettings.m_Gamma, 0, 100))
125       m_defaultVideoSettings.m_Gamma = 20;
126     if (!XMLUtils::GetFloat(pElement, "audiodelay", m_defaultVideoSettings.m_AudioDelay, -10.0f, 10.0f))
127       m_defaultVideoSettings.m_AudioDelay = 0.0f;
128     if (!XMLUtils::GetFloat(pElement, "subtitledelay", m_defaultVideoSettings.m_SubtitleDelay, -10.0f, 10.0f))
129       m_defaultVideoSettings.m_SubtitleDelay = 0.0f;
130     XMLUtils::GetBoolean(pElement, "autocrop", m_defaultVideoSettings.m_Crop);
131     XMLUtils::GetBoolean(pElement, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch);
132     if (!XMLUtils::GetInt(pElement, "stereomode", m_defaultVideoSettings.m_StereoMode))
133       m_defaultVideoSettings.m_StereoMode = 0;
134
135     m_defaultVideoSettings.m_SubtitleCached = false;
136   }
137
138   // mymusic settings
139   pElement = settings->FirstChildElement("mymusic");
140   if (pElement != NULL)
141   {
142     const TiXmlElement *pChild = pElement->FirstChildElement("playlist");
143     if (pChild != NULL)
144     {
145       XMLUtils::GetBoolean(pChild, "repeat", m_musicPlaylistRepeat);
146       XMLUtils::GetBoolean(pChild, "shuffle", m_musicPlaylistShuffle);
147     }
148     if (!XMLUtils::GetInt(pElement, "needsupdate", m_musicNeedsUpdate, 0, INT_MAX))
149       m_musicNeedsUpdate = 0;
150   }
151   
152   // Read the watchmode settings for the various media views
153   pElement = settings->FirstChildElement("myvideos");
154   if (pElement != NULL)
155   {
156     int tmp;
157     if (XMLUtils::GetInt(pElement, "watchmodemovies", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
158       m_watchedModes["movies"] = (WatchedMode)tmp;
159     if (XMLUtils::GetInt(pElement, "watchmodetvshows", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
160       m_watchedModes["tvshows"] = (WatchedMode)tmp;
161     if (XMLUtils::GetInt(pElement, "watchmodemusicvideos", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
162       m_watchedModes["musicvideos"] = (WatchedMode)tmp;
163
164     const TiXmlElement *pChild = pElement->FirstChildElement("playlist");
165     if (pChild != NULL)
166     {
167       XMLUtils::GetBoolean(pChild, "repeat", m_videoPlaylistRepeat);
168       XMLUtils::GetBoolean(pChild, "shuffle", m_videoPlaylistShuffle);
169     }
170     if (!XMLUtils::GetInt(pElement, "needsupdate", m_videoNeedsUpdate, 0, INT_MAX))
171       m_videoNeedsUpdate = 0;
172   }
173
174   return true;
175 }
176
177 bool CMediaSettings::Save(TiXmlNode *settings) const
178 {
179   if (settings == NULL)
180     return false;
181
182   CSingleLock lock(m_critical);
183   // default video settings
184   TiXmlElement videoSettingsNode("defaultvideosettings");
185   TiXmlNode *pNode = settings->InsertEndChild(videoSettingsNode);
186   if (pNode == NULL)
187     return false;
188
189   XMLUtils::SetInt(pNode, "deinterlacemode", m_defaultVideoSettings.m_DeinterlaceMode);
190   XMLUtils::SetInt(pNode, "interlacemethod", m_defaultVideoSettings.m_InterlaceMethod);
191   XMLUtils::SetInt(pNode, "scalingmethod", m_defaultVideoSettings.m_ScalingMethod);
192   XMLUtils::SetFloat(pNode, "noisereduction", m_defaultVideoSettings.m_NoiseReduction);
193   XMLUtils::SetBoolean(pNode, "postprocess", m_defaultVideoSettings.m_PostProcess);
194   XMLUtils::SetFloat(pNode, "sharpness", m_defaultVideoSettings.m_Sharpness);
195   XMLUtils::SetInt(pNode, "viewmode", m_defaultVideoSettings.m_ViewMode);
196   XMLUtils::SetFloat(pNode, "zoomamount", m_defaultVideoSettings.m_CustomZoomAmount);
197   XMLUtils::SetFloat(pNode, "pixelratio", m_defaultVideoSettings.m_CustomPixelRatio);
198   XMLUtils::SetFloat(pNode, "verticalshift", m_defaultVideoSettings.m_CustomVerticalShift);
199   XMLUtils::SetFloat(pNode, "volumeamplification", m_defaultVideoSettings.m_VolumeAmplification);
200   XMLUtils::SetBoolean(pNode, "outputtoallspeakers", m_defaultVideoSettings.m_OutputToAllSpeakers);
201   XMLUtils::SetBoolean(pNode, "showsubtitles", m_defaultVideoSettings.m_SubtitleOn);
202   XMLUtils::SetFloat(pNode, "brightness", m_defaultVideoSettings.m_Brightness);
203   XMLUtils::SetFloat(pNode, "contrast", m_defaultVideoSettings.m_Contrast);
204   XMLUtils::SetFloat(pNode, "gamma", m_defaultVideoSettings.m_Gamma);
205   XMLUtils::SetFloat(pNode, "audiodelay", m_defaultVideoSettings.m_AudioDelay);
206   XMLUtils::SetFloat(pNode, "subtitledelay", m_defaultVideoSettings.m_SubtitleDelay);
207   XMLUtils::SetBoolean(pNode, "autocrop", m_defaultVideoSettings.m_Crop); 
208   XMLUtils::SetBoolean(pNode, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch);
209   XMLUtils::SetInt(pNode, "stereomode", m_defaultVideoSettings.m_StereoMode);
210
211   // mymusic
212   pNode = settings->FirstChild("mymusic");
213   if (pNode == NULL)
214   {
215     TiXmlElement videosNode("mymusic");
216     pNode = settings->InsertEndChild(videosNode);
217     if (pNode == NULL)
218       return false;
219   }
220
221   TiXmlElement musicPlaylistNode("playlist");
222   TiXmlNode *playlistNode = pNode->InsertEndChild(musicPlaylistNode);
223   if (playlistNode == NULL)
224     return false;
225   XMLUtils::SetBoolean(playlistNode, "repeat", m_musicPlaylistRepeat);
226   XMLUtils::SetBoolean(playlistNode, "shuffle", m_musicPlaylistShuffle);
227
228   XMLUtils::SetInt(pNode, "needsupdate", m_musicNeedsUpdate);
229
230   // myvideos
231   pNode = settings->FirstChild("myvideos");
232   if (pNode == NULL)
233   {
234     TiXmlElement videosNode("myvideos");
235     pNode = settings->InsertEndChild(videosNode);
236     if (pNode == NULL)
237       return false;
238   }
239
240   XMLUtils::SetInt(pNode, "watchmodemovies", m_watchedModes.find("movies")->second);
241   XMLUtils::SetInt(pNode, "watchmodetvshows", m_watchedModes.find("tvshows")->second);
242   XMLUtils::SetInt(pNode, "watchmodemusicvideos", m_watchedModes.find("musicvideos")->second);
243
244   TiXmlElement videoPlaylistNode("playlist");
245   playlistNode = pNode->InsertEndChild(videoPlaylistNode);
246   if (playlistNode == NULL)
247     return false;
248   XMLUtils::SetBoolean(playlistNode, "repeat", m_videoPlaylistRepeat);
249   XMLUtils::SetBoolean(playlistNode, "shuffle", m_videoPlaylistShuffle);
250
251   XMLUtils::SetInt(pNode, "needsupdate", m_videoNeedsUpdate);
252
253   return true;
254 }
255
256 void CMediaSettings::OnSettingAction(const CSetting *setting)
257 {
258   if (setting == NULL)
259     return;
260
261   const std::string &settingId = setting->GetId();
262   if (settingId == "karaoke.export")
263   {
264     CContextButtons choices;
265     choices.Add(1, g_localizeStrings.Get(22034));
266     choices.Add(2, g_localizeStrings.Get(22035));
267
268     int retVal = CGUIDialogContextMenu::ShowAndGetChoice(choices);
269     if ( retVal > 0 )
270     {
271       CStdString path(CProfilesManager::Get().GetDatabaseFolder());
272       VECSOURCES shares;
273       g_mediaManager.GetLocalDrives(shares);
274       if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(661), path, true))
275       {
276         CMusicDatabase musicdatabase;
277         musicdatabase.Open();
278
279         if ( retVal == 1 )
280         {
281           path = URIUtils::AddFileToFolder(path, "karaoke.html");
282           musicdatabase.ExportKaraokeInfo( path, true );
283         }
284         else
285         {
286           path = URIUtils::AddFileToFolder(path, "karaoke.csv");
287           musicdatabase.ExportKaraokeInfo( path, false );
288         }
289         musicdatabase.Close();
290       }
291     }
292   }
293   else if (settingId == "karaoke.importcsv")
294   {
295     CStdString path(CProfilesManager::Get().GetDatabaseFolder());
296     VECSOURCES shares;
297     g_mediaManager.GetLocalDrives(shares);
298     if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "karaoke.csv", g_localizeStrings.Get(651) , path))
299     {
300       CMusicDatabase musicdatabase;
301       musicdatabase.Open();
302       musicdatabase.ImportKaraokeInfo(path);
303       musicdatabase.Close();
304     }
305   }
306   else if (settingId == "musiclibrary.cleanup")
307   {
308     CMusicDatabase musicdatabase;
309     musicdatabase.Clean();
310     CUtil::DeleteMusicDatabaseDirectoryCache();
311   }
312   else if (settingId == "musiclibrary.export")
313     CBuiltins::Execute("exportlibrary(music)");
314   else if (settingId == "musiclibrary.import")
315   {
316     CStdString path;
317     VECSOURCES shares;
318     g_mediaManager.GetLocalDrives(shares);
319     if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "musicdb.xml", g_localizeStrings.Get(651) , path))
320     {
321       CMusicDatabase musicdatabase;
322       musicdatabase.Open();
323       musicdatabase.ImportFromXML(path);
324       musicdatabase.Close();
325     }
326   }
327   else if (settingId == "videolibrary.cleanup")
328   {
329     if (CGUIDialogYesNo::ShowAndGetInput(313, 333, 0, 0))
330       g_application.StartVideoCleanup();
331   }
332   else if (settingId == "videolibrary.export")
333     CBuiltins::Execute("exportlibrary(video)");
334   else if (settingId == "videolibrary.import")
335   {
336     CStdString path;
337     VECSOURCES shares;
338     g_mediaManager.GetLocalDrives(shares);
339     if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(651) , path))
340     {
341       CVideoDatabase videodatabase;
342       videodatabase.Open();
343       videodatabase.ImportFromXML(path);
344       videodatabase.Close();
345     }
346   }
347 }
348
349 int CMediaSettings::GetWatchedMode(const std::string &content) const
350 {
351   CSingleLock lock(m_critical);
352   WatchedModes::const_iterator it = m_watchedModes.find(GetWatchedContent(content));
353   if (it != m_watchedModes.end())
354     return it->second;
355
356   return WatchedModeAll;
357 }
358
359 void CMediaSettings::SetWatchedMode(const std::string &content, WatchedMode mode)
360 {
361   CSingleLock lock(m_critical);
362   WatchedModes::iterator it = m_watchedModes.find(GetWatchedContent(content));
363   if (it != m_watchedModes.end())
364     it->second = mode;
365 }
366
367 void CMediaSettings::CycleWatchedMode(const std::string &content)
368 {
369   CSingleLock lock(m_critical);
370   WatchedModes::iterator it = m_watchedModes.find(GetWatchedContent(content));
371   if (it != m_watchedModes.end())
372   {
373     it->second = (WatchedMode)((int)it->second + 1);
374     if (it->second > WatchedModeWatched)
375       it->second = WatchedModeAll;
376   }
377 }
378
379 std::string CMediaSettings::GetWatchedContent(const std::string &content)
380 {
381   if (content == "seasons" || content == "episodes")
382     return "tvshows";
383
384   return content;
385 }