2 * Copyright (C) 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/>.
23 #include "MediaSettings.h"
24 #include "Application.h"
25 #include "PlayListPlayer.h"
27 #include "dialogs/GUIDialogContextMenu.h"
28 #include "dialogs/GUIDialogFileBrowser.h"
29 #include "dialogs/GUIDialogYesNo.h"
30 #include "guilib/WindowIDs.h"
31 #include "interfaces/Builtins.h"
32 #include "music/MusicDatabase.h"
33 #include "profiles/ProfilesManager.h"
34 #include "settings/lib/Setting.h"
35 #include "storage/MediaManager.h"
36 #include "threads/SingleLock.h"
37 #include "utils/log.h"
38 #include "utils/URIUtils.h"
39 #include "utils/XBMCTinyXML.h"
40 #include "utils/XMLUtils.h"
41 #include "video/VideoDatabase.h"
45 CMediaSettings::CMediaSettings()
47 m_watchedModes["movies"] = WatchedModeAll;
48 m_watchedModes["tvshows"] = WatchedModeAll;
49 m_watchedModes["musicvideos"] = WatchedModeAll;
51 m_musicPlaylistRepeat = false;
52 m_musicPlaylistShuffle = false;
53 m_videoPlaylistRepeat = false;
54 m_videoPlaylistShuffle = false;
56 m_videoStartWindowed = false;
57 m_additionalSubtitleDirectoryChecked = 0;
59 m_musicNeedsUpdate = 0;
60 m_videoNeedsUpdate = 0;
63 CMediaSettings::~CMediaSettings()
66 CMediaSettings& CMediaSettings::Get()
68 static CMediaSettings sMediaSettings;
69 return sMediaSettings;
72 bool CMediaSettings::Load(const TiXmlNode *settings)
77 CSingleLock lock(m_critical);
78 const TiXmlElement *pElement = settings->FirstChildElement("defaultvideosettings");
82 bool deinterlaceModePresent = XMLUtils::GetInt(pElement, "deinterlacemode", deinterlaceMode, VS_DEINTERLACEMODE_OFF, VS_DEINTERLACEMODE_FORCE);
84 bool interlaceMethodPresent = XMLUtils::GetInt(pElement, "interlacemethod", interlaceMethod, VS_INTERLACEMETHOD_AUTO, VS_INTERLACEMETHOD_MAX);
85 // For smooth conversion of settings stored before the deinterlaceMode existed
86 if (!deinterlaceModePresent && interlaceMethodPresent)
88 if (interlaceMethod == VS_INTERLACEMETHOD_NONE)
90 deinterlaceMode = VS_DEINTERLACEMODE_OFF;
91 interlaceMethod = VS_INTERLACEMETHOD_AUTO;
93 else if (interlaceMethod == VS_INTERLACEMETHOD_AUTO)
94 deinterlaceMode = VS_DEINTERLACEMODE_AUTO;
96 deinterlaceMode = VS_DEINTERLACEMODE_FORCE;
98 m_defaultVideoSettings.m_DeinterlaceMode = (EDEINTERLACEMODE)deinterlaceMode;
99 m_defaultVideoSettings.m_InterlaceMethod = (EINTERLACEMETHOD)interlaceMethod;
101 if (!XMLUtils::GetInt(pElement, "scalingmethod", scalingMethod, VS_SCALINGMETHOD_NEAREST, VS_SCALINGMETHOD_MAX))
102 scalingMethod = (int)VS_SCALINGMETHOD_LINEAR;
103 m_defaultVideoSettings.m_ScalingMethod = (ESCALINGMETHOD)scalingMethod;
105 XMLUtils::GetInt(pElement, "viewmode", m_defaultVideoSettings.m_ViewMode, ViewModeNormal, ViewModeCustom);
106 if (!XMLUtils::GetFloat(pElement, "zoomamount", m_defaultVideoSettings.m_CustomZoomAmount, 0.5f, 2.0f))
107 m_defaultVideoSettings.m_CustomZoomAmount = 1.0f;
108 if (!XMLUtils::GetFloat(pElement, "pixelratio", m_defaultVideoSettings.m_CustomPixelRatio, 0.5f, 2.0f))
109 m_defaultVideoSettings.m_CustomPixelRatio = 1.0f;
110 if (!XMLUtils::GetFloat(pElement, "verticalshift", m_defaultVideoSettings.m_CustomVerticalShift, -2.0f, 2.0f))
111 m_defaultVideoSettings.m_CustomVerticalShift = 0.0f;
112 if (!XMLUtils::GetFloat(pElement, "volumeamplification", m_defaultVideoSettings.m_VolumeAmplification, VOLUME_DRC_MINIMUM * 0.01f, VOLUME_DRC_MAXIMUM * 0.01f))
113 m_defaultVideoSettings.m_VolumeAmplification = VOLUME_DRC_MINIMUM * 0.01f;
114 if (!XMLUtils::GetFloat(pElement, "noisereduction", m_defaultVideoSettings.m_NoiseReduction, 0.0f, 1.0f))
115 m_defaultVideoSettings.m_NoiseReduction = 0.0f;
116 XMLUtils::GetBoolean(pElement, "postprocess", m_defaultVideoSettings.m_PostProcess);
117 if (!XMLUtils::GetFloat(pElement, "sharpness", m_defaultVideoSettings.m_Sharpness, -1.0f, 1.0f))
118 m_defaultVideoSettings.m_Sharpness = 0.0f;
119 XMLUtils::GetBoolean(pElement, "outputtoallspeakers", m_defaultVideoSettings.m_OutputToAllSpeakers);
120 XMLUtils::GetBoolean(pElement, "showsubtitles", m_defaultVideoSettings.m_SubtitleOn);
121 if (!XMLUtils::GetFloat(pElement, "brightness", m_defaultVideoSettings.m_Brightness, 0, 100))
122 m_defaultVideoSettings.m_Brightness = 50;
123 if (!XMLUtils::GetFloat(pElement, "contrast", m_defaultVideoSettings.m_Contrast, 0, 100))
124 m_defaultVideoSettings.m_Contrast = 50;
125 if (!XMLUtils::GetFloat(pElement, "gamma", m_defaultVideoSettings.m_Gamma, 0, 100))
126 m_defaultVideoSettings.m_Gamma = 20;
127 if (!XMLUtils::GetFloat(pElement, "audiodelay", m_defaultVideoSettings.m_AudioDelay, -10.0f, 10.0f))
128 m_defaultVideoSettings.m_AudioDelay = 0.0f;
129 if (!XMLUtils::GetFloat(pElement, "subtitledelay", m_defaultVideoSettings.m_SubtitleDelay, -10.0f, 10.0f))
130 m_defaultVideoSettings.m_SubtitleDelay = 0.0f;
131 XMLUtils::GetBoolean(pElement, "autocrop", m_defaultVideoSettings.m_Crop);
132 XMLUtils::GetBoolean(pElement, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch);
133 if (!XMLUtils::GetInt(pElement, "stereomode", m_defaultVideoSettings.m_StereoMode))
134 m_defaultVideoSettings.m_StereoMode = 0;
136 m_defaultVideoSettings.m_SubtitleCached = false;
140 pElement = settings->FirstChildElement("mymusic");
141 if (pElement != NULL)
143 const TiXmlElement *pChild = pElement->FirstChildElement("playlist");
146 XMLUtils::GetBoolean(pChild, "repeat", m_musicPlaylistRepeat);
147 XMLUtils::GetBoolean(pChild, "shuffle", m_musicPlaylistShuffle);
149 if (!XMLUtils::GetInt(pElement, "needsupdate", m_musicNeedsUpdate, 0, INT_MAX))
150 m_musicNeedsUpdate = 0;
153 // Read the watchmode settings for the various media views
154 pElement = settings->FirstChildElement("myvideos");
155 if (pElement != NULL)
158 if (XMLUtils::GetInt(pElement, "watchmodemovies", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
159 m_watchedModes["movies"] = (WatchedMode)tmp;
160 if (XMLUtils::GetInt(pElement, "watchmodetvshows", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
161 m_watchedModes["tvshows"] = (WatchedMode)tmp;
162 if (XMLUtils::GetInt(pElement, "watchmodemusicvideos", tmp, (int)WatchedModeAll, (int)WatchedModeWatched))
163 m_watchedModes["musicvideos"] = (WatchedMode)tmp;
165 const TiXmlElement *pChild = pElement->FirstChildElement("playlist");
168 XMLUtils::GetBoolean(pChild, "repeat", m_videoPlaylistRepeat);
169 XMLUtils::GetBoolean(pChild, "shuffle", m_videoPlaylistShuffle);
171 if (!XMLUtils::GetInt(pElement, "needsupdate", m_videoNeedsUpdate, 0, INT_MAX))
172 m_videoNeedsUpdate = 0;
178 void CMediaSettings::OnSettingsLoaded()
180 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, m_musicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
181 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, m_musicPlaylistShuffle);
182 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, m_videoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
183 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, m_videoPlaylistShuffle);
186 bool CMediaSettings::Save(TiXmlNode *settings) const
188 if (settings == NULL)
191 CSingleLock lock(m_critical);
192 // default video settings
193 TiXmlElement videoSettingsNode("defaultvideosettings");
194 TiXmlNode *pNode = settings->InsertEndChild(videoSettingsNode);
198 XMLUtils::SetInt(pNode, "deinterlacemode", m_defaultVideoSettings.m_DeinterlaceMode);
199 XMLUtils::SetInt(pNode, "interlacemethod", m_defaultVideoSettings.m_InterlaceMethod);
200 XMLUtils::SetInt(pNode, "scalingmethod", m_defaultVideoSettings.m_ScalingMethod);
201 XMLUtils::SetFloat(pNode, "noisereduction", m_defaultVideoSettings.m_NoiseReduction);
202 XMLUtils::SetBoolean(pNode, "postprocess", m_defaultVideoSettings.m_PostProcess);
203 XMLUtils::SetFloat(pNode, "sharpness", m_defaultVideoSettings.m_Sharpness);
204 XMLUtils::SetInt(pNode, "viewmode", m_defaultVideoSettings.m_ViewMode);
205 XMLUtils::SetFloat(pNode, "zoomamount", m_defaultVideoSettings.m_CustomZoomAmount);
206 XMLUtils::SetFloat(pNode, "pixelratio", m_defaultVideoSettings.m_CustomPixelRatio);
207 XMLUtils::SetFloat(pNode, "verticalshift", m_defaultVideoSettings.m_CustomVerticalShift);
208 XMLUtils::SetFloat(pNode, "volumeamplification", m_defaultVideoSettings.m_VolumeAmplification);
209 XMLUtils::SetBoolean(pNode, "outputtoallspeakers", m_defaultVideoSettings.m_OutputToAllSpeakers);
210 XMLUtils::SetBoolean(pNode, "showsubtitles", m_defaultVideoSettings.m_SubtitleOn);
211 XMLUtils::SetFloat(pNode, "brightness", m_defaultVideoSettings.m_Brightness);
212 XMLUtils::SetFloat(pNode, "contrast", m_defaultVideoSettings.m_Contrast);
213 XMLUtils::SetFloat(pNode, "gamma", m_defaultVideoSettings.m_Gamma);
214 XMLUtils::SetFloat(pNode, "audiodelay", m_defaultVideoSettings.m_AudioDelay);
215 XMLUtils::SetFloat(pNode, "subtitledelay", m_defaultVideoSettings.m_SubtitleDelay);
216 XMLUtils::SetBoolean(pNode, "autocrop", m_defaultVideoSettings.m_Crop);
217 XMLUtils::SetBoolean(pNode, "nonlinstretch", m_defaultVideoSettings.m_CustomNonLinStretch);
218 XMLUtils::SetInt(pNode, "stereomode", m_defaultVideoSettings.m_StereoMode);
221 pNode = settings->FirstChild("mymusic");
224 TiXmlElement videosNode("mymusic");
225 pNode = settings->InsertEndChild(videosNode);
230 TiXmlElement musicPlaylistNode("playlist");
231 TiXmlNode *playlistNode = pNode->InsertEndChild(musicPlaylistNode);
232 if (playlistNode == NULL)
234 XMLUtils::SetBoolean(playlistNode, "repeat", m_musicPlaylistRepeat);
235 XMLUtils::SetBoolean(playlistNode, "shuffle", m_musicPlaylistShuffle);
237 XMLUtils::SetInt(pNode, "needsupdate", m_musicNeedsUpdate);
240 pNode = settings->FirstChild("myvideos");
243 TiXmlElement videosNode("myvideos");
244 pNode = settings->InsertEndChild(videosNode);
249 XMLUtils::SetInt(pNode, "watchmodemovies", m_watchedModes.find("movies")->second);
250 XMLUtils::SetInt(pNode, "watchmodetvshows", m_watchedModes.find("tvshows")->second);
251 XMLUtils::SetInt(pNode, "watchmodemusicvideos", m_watchedModes.find("musicvideos")->second);
253 TiXmlElement videoPlaylistNode("playlist");
254 playlistNode = pNode->InsertEndChild(videoPlaylistNode);
255 if (playlistNode == NULL)
257 XMLUtils::SetBoolean(playlistNode, "repeat", m_videoPlaylistRepeat);
258 XMLUtils::SetBoolean(playlistNode, "shuffle", m_videoPlaylistShuffle);
260 XMLUtils::SetInt(pNode, "needsupdate", m_videoNeedsUpdate);
265 void CMediaSettings::OnSettingAction(const CSetting *setting)
270 const std::string &settingId = setting->GetId();
271 if (settingId == "karaoke.export")
273 CContextButtons choices;
274 choices.Add(1, g_localizeStrings.Get(22034));
275 choices.Add(2, g_localizeStrings.Get(22035));
277 int retVal = CGUIDialogContextMenu::ShowAndGetChoice(choices);
280 CStdString path(CProfilesManager::Get().GetDatabaseFolder());
282 g_mediaManager.GetLocalDrives(shares);
283 if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(661), path, true))
285 CMusicDatabase musicdatabase;
286 musicdatabase.Open();
290 path = URIUtils::AddFileToFolder(path, "karaoke.html");
291 musicdatabase.ExportKaraokeInfo( path, true );
295 path = URIUtils::AddFileToFolder(path, "karaoke.csv");
296 musicdatabase.ExportKaraokeInfo( path, false );
298 musicdatabase.Close();
302 else if (settingId == "karaoke.importcsv")
304 CStdString path(CProfilesManager::Get().GetDatabaseFolder());
306 g_mediaManager.GetLocalDrives(shares);
307 if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "karaoke.csv", g_localizeStrings.Get(651) , path))
309 CMusicDatabase musicdatabase;
310 musicdatabase.Open();
311 musicdatabase.ImportKaraokeInfo(path);
312 musicdatabase.Close();
315 else if (settingId == "musiclibrary.cleanup")
317 CMusicDatabase musicdatabase;
318 musicdatabase.Clean();
319 CUtil::DeleteMusicDatabaseDirectoryCache();
321 else if (settingId == "musiclibrary.export")
322 CBuiltins::Execute("exportlibrary(music)");
323 else if (settingId == "musiclibrary.import")
327 g_mediaManager.GetLocalDrives(shares);
328 if (CGUIDialogFileBrowser::ShowAndGetFile(shares, "musicdb.xml", g_localizeStrings.Get(651) , path))
330 CMusicDatabase musicdatabase;
331 musicdatabase.Open();
332 musicdatabase.ImportFromXML(path);
333 musicdatabase.Close();
336 else if (settingId == "videolibrary.cleanup")
338 if (CGUIDialogYesNo::ShowAndGetInput(313, 333, 0, 0))
339 g_application.StartVideoCleanup();
341 else if (settingId == "videolibrary.export")
342 CBuiltins::Execute("exportlibrary(video)");
343 else if (settingId == "videolibrary.import")
347 g_mediaManager.GetLocalDrives(shares);
348 if (CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(651) , path))
350 CVideoDatabase videodatabase;
351 videodatabase.Open();
352 videodatabase.ImportFromXML(path);
353 videodatabase.Close();
358 int CMediaSettings::GetWatchedMode(const std::string &content) const
360 CSingleLock lock(m_critical);
361 WatchedModes::const_iterator it = m_watchedModes.find(GetWatchedContent(content));
362 if (it != m_watchedModes.end())
365 return WatchedModeAll;
368 void CMediaSettings::SetWatchedMode(const std::string &content, WatchedMode mode)
370 CSingleLock lock(m_critical);
371 WatchedModes::iterator it = m_watchedModes.find(GetWatchedContent(content));
372 if (it != m_watchedModes.end())
376 void CMediaSettings::CycleWatchedMode(const std::string &content)
378 CSingleLock lock(m_critical);
379 WatchedModes::iterator it = m_watchedModes.find(GetWatchedContent(content));
380 if (it != m_watchedModes.end())
382 it->second = (WatchedMode)((int)it->second + 1);
383 if (it->second > WatchedModeWatched)
384 it->second = WatchedModeAll;
388 std::string CMediaSettings::GetWatchedContent(const std::string &content)
390 if (content == "seasons" || content == "episodes")