changed: don't reaload xrandr output and mode id from disk into an arbitrary resoluti...
[xbmc:xbmc-antiquated.git] / XBMC / xbmc / Settings.cpp
1 /*
2  *      Copyright (C) 2005-2008 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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "stdafx.h"
23 #include "Settings.h"
24 #include "Application.h"
25 #include "KeyboardLayoutConfiguration.h"
26 #include "Util.h"
27 #include "URL.h"
28 #include "GUIWindowFileManager.h"
29 #include "GUIDialogButtonMenu.h"
30 #include "GUIFontManager.h"
31 #include "LangCodeExpander.h"
32 #include "ButtonTranslator.h"
33 #include "XMLUtils.h"
34 #include "GUIPassword.h"
35 #include "GUIAudioManager.h"
36 #include "AudioContext.h"
37 #include "utils/GUIInfoManager.h"
38 #include "utils/Network.h"
39 #include "FileSystem/MultiPathDirectory.h"
40 #include "GUIBaseContainer.h" // for VIEW_TYPE enum
41 #include "MediaManager.h"
42 #include "XBVideoConfig.h"
43 #include "DNSNameCache.h"
44 #include "GUIWindowManager.h"
45 #include "GUIDialogYesNo.h"
46 #include "FileSystem/Directory.h"
47 #include "FileItem.h"
48 #ifdef _WIN32PC
49 #include "win32/WIN32Util.h"
50 #endif
51 #include "FileSystem/SMBDirectory.h"
52
53
54 using namespace std;
55 using namespace XFILE;
56 using namespace DIRECTORY;
57 using namespace MEDIA_DETECT;
58
59 struct CSettings::stSettings g_stSettings;
60 struct CSettings::AdvancedSettings g_advancedSettings;
61 class CSettings g_settings;
62
63 extern CStdString g_LoadErrorStr;
64
65 CSettings::CSettings(void)
66 {
67 }
68
69 void CSettings::Initialize()
70 {
71   for (int i = HDTV_1080i; i <= PAL60_16x9; i++)
72   {
73     ZeroMemory(&m_ResInfo[i], sizeof(RESOLUTION));
74     g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
75     g_graphicsContext.ResetOverscan((RESOLUTION)i, m_ResInfo[i].Overscan);
76   }
77
78   for (int i = DESKTOP ; i<=CUSTOM ; i++)
79   {
80     ZeroMemory(&m_ResInfo[i], sizeof(RESOLUTION));
81     g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
82     g_graphicsContext.ResetOverscan(m_ResInfo[i]);
83   }
84
85   g_graphicsContext.ResetScreenParameters(WINDOW);
86   g_graphicsContext.ResetOverscan(m_ResInfo[WINDOW]);
87
88   g_stSettings.m_iMyVideoStack = STACK_NONE;
89
90   strcpy(g_stSettings.m_szMyVideoCleanTokens, "divx|xvid|3ivx|ac3|ac351|dts|mp3|wma|m4a|mp4|aac|ogg|scr|ts|sharereactor|dvd|dvdrip|hd-dvd|remux|dtshd|ddplus|blue-ray");
91   strcpy(g_stSettings.m_szMyVideoCleanSeparators, "- _.[({+");
92
93   StringUtils::SplitString(g_stSettings.m_szMyVideoCleanTokens, "|", g_settings.m_szMyVideoCleanTokensArray);
94   g_settings.m_szMyVideoCleanSeparatorsString = g_stSettings.m_szMyVideoCleanSeparators;
95
96   for (int i = 0; i < (int)g_settings.m_szMyVideoCleanTokensArray.size(); i++)
97     g_settings.m_szMyVideoCleanTokensArray[i].MakeLower();
98
99   strcpy(g_stSettings.szOnlineArenaPassword, "");
100   strcpy(g_stSettings.szOnlineArenaDescription, "It's Good To Play Together!");
101
102   g_stSettings.m_bMyMusicSongInfoInVis = true;    // UNUSED - depreciated.
103   g_stSettings.m_bMyMusicSongThumbInVis = false;  // used for music info in vis screen
104
105   g_stSettings.m_bMyMusicPlaylistRepeat = false;
106   g_stSettings.m_bMyMusicPlaylistShuffle = false;
107
108   g_stSettings.m_bMyVideoPlaylistRepeat = false;
109   g_stSettings.m_bMyVideoPlaylistShuffle = false;
110   g_stSettings.m_bMyVideoNavFlatten = false;
111
112   g_stSettings.m_nVolumeLevel = 0;
113   g_stSettings.m_dynamicRangeCompressionLevel = 0;
114   g_stSettings.m_iPreMuteVolumeLevel = 0;
115   g_stSettings.m_bMute = false;
116   g_stSettings.m_fZoomAmount = 1.0f;
117   g_stSettings.m_fPixelRatio = 1.0f;
118
119   g_stSettings.m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.m3u|.dng|.nef";
120   g_stSettings.m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.mod|.amf|.669|.dmf|.dsm|.far|.gdm|.imf|.it|.m15|.med|.okt|.s3m|.stm|.sfx|.ult|.uni|.xm|.sid|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.nsf|.spc|.gym|.adplug|.adx|.dsp|.adp|.ymf|.ast|.afc|.hps|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.mid|.kar|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga";
121   g_stSettings.m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec";
122   // internal music extensions
123   g_stSettings.m_musicExtensions += "|.sidstream|.oggstream|.nsfstream|.asapstream|.cdda";
124
125   #ifdef __APPLE__
126     CStdString logDir = getenv("HOME");
127     logDir += "/Library/Logs/";
128     g_stSettings.m_logFolder = logDir;
129   #else
130     g_stSettings.m_logFolder = "Q:\\";              // log file location
131   #endif
132
133   g_stSettings.m_defaultMusicScraper = "allmusic.xml";
134
135   m_iLastLoadedProfileIndex = 0;
136
137   // defaults for scanning
138   g_stSettings.m_bMyMusicIsScanning = false;
139
140   g_stSettings.iAdditionalSubtitleDirectoryChecked = 0;
141
142   g_settings.bUseLoginScreen = false;
143
144   // Advanced settings
145   g_advancedSettings.m_useMultipaths = true;
146   g_advancedSettings.m_DisableModChipDetection = true;
147
148   g_advancedSettings.m_audioHeadRoom = 0;
149   g_advancedSettings.m_karaokeSyncDelay = 0.0f;
150   g_advancedSettings.m_analogMultiChannel = false;
151
152   g_advancedSettings.m_videoSubsDelayRange = 10;
153   g_advancedSettings.m_videoAudioDelayRange = 10;
154   g_advancedSettings.m_videoSmallStepBackSeconds = 7;
155   g_advancedSettings.m_videoSmallStepBackTries = 3;
156   g_advancedSettings.m_videoSmallStepBackDelay = 300;
157   g_advancedSettings.m_videoUseTimeSeeking = true;
158   g_advancedSettings.m_videoTimeSeekForward = 30;
159   g_advancedSettings.m_videoTimeSeekBackward = -30;
160   g_advancedSettings.m_videoTimeSeekForwardBig = 600;
161   g_advancedSettings.m_videoTimeSeekBackwardBig = -600;
162   g_advancedSettings.m_videoPercentSeekForward = 2;
163   g_advancedSettings.m_videoPercentSeekBackward = -2;
164   g_advancedSettings.m_videoPercentSeekForwardBig = 10;
165   g_advancedSettings.m_videoPercentSeekBackwardBig = -10;
166   g_advancedSettings.m_videoBlackBarColour = 1;
167
168   g_advancedSettings.m_slideshowPanAmount = 2.5f;
169   g_advancedSettings.m_slideshowZoomAmount = 5.0f;
170   g_advancedSettings.m_slideshowBlackBarCompensation = 20.0f;
171
172   g_advancedSettings.m_lcdRows = 4;
173   g_advancedSettings.m_lcdColumns = 20;
174   g_advancedSettings.m_lcdAddress1 = 0;
175   g_advancedSettings.m_lcdAddress2 = 0x40;
176   g_advancedSettings.m_lcdAddress3 = 0x14;
177   g_advancedSettings.m_lcdAddress4 = 0x54;
178   g_advancedSettings.m_lcdHeartbeat = false;
179
180   g_advancedSettings.m_autoDetectPingTime = 30;
181   g_advancedSettings.m_playCountMinimumPercent = 90.0f;
182
183   g_advancedSettings.m_songInfoDuration = 10;
184   g_advancedSettings.m_busyDialogDelay = 2000;
185 #ifdef _DEBUG
186   g_advancedSettings.m_logLevel = LOG_LEVEL_DEBUG;
187 #else
188   g_advancedSettings.m_logLevel = LOG_LEVEL_NORMAL;
189 #endif
190   g_advancedSettings.m_cddbAddress = "freedb.freedb.org";
191 #ifdef HAS_HAL
192   g_advancedSettings.m_useSystemPowerManagement = g_application.IsStandAlone();
193   g_advancedSettings.m_useHalMount = g_application.IsStandAlone();
194 #endif
195   g_advancedSettings.m_fullScreenOnMovieStart = true;
196   g_advancedSettings.m_noDVDROM = false;
197   g_advancedSettings.m_cachePath = "Z:\\";
198   g_advancedSettings.m_displayRemoteCodes = false;
199
200   g_advancedSettings.m_videoExcludeRegExps.push_back("[-\\._ ](sample|trailer)[-\\._ ]");
201
202   g_advancedSettings.m_videoStackRegExps.push_back("[ _\\.-]+cd[ _\\.-]*([0-9a-d]+)");
203   g_advancedSettings.m_videoStackRegExps.push_back("[ _\\.-]+dvd[ _\\.-]*([0-9a-d]+)");
204   g_advancedSettings.m_videoStackRegExps.push_back("[ _\\.-]+part[ _\\.-]*([0-9a-d]+)");
205   g_advancedSettings.m_videoStackRegExps.push_back("[ _\\.-]+dis[ck][ _\\.-]*([0-9a-d]+)");
206   g_advancedSettings.m_videoStackRegExps.push_back("()[ _\\.-]+([0-9]*[abcd]+)(\\.....?)$"); // can anyone explain this one?  should this be ([0-9a-d]+) ?
207   g_advancedSettings.m_videoStackRegExps.push_back("([a-z])([0-9]+)(\\.....?)$");
208   g_advancedSettings.m_videoStackRegExps.push_back("()([ab])(\\.....?)$");
209
210   // foo_[s01]_[e01]
211   g_advancedSettings.m_tvshowStackRegExps.push_back("\\[[Ss]([0-9]+)\\]_\\[[Ee]([0-9]+)\\]?([^\\\\/]*)$");
212   // foo.1x09* or just /1x09*
213   g_advancedSettings.m_tvshowStackRegExps.push_back("[\\\\/\\._ \\[-]([0-9]+)x([0-9]+)([^\\\\/]*)$");
214   // foo.s01.e01, foo.s01_e01, S01E02 foo
215   g_advancedSettings.m_tvshowStackRegExps.push_back("[Ss]([0-9]+)[\\.-]?[Ee]([0-9]+)([^\\\\/]*)$");
216   // foo.103*
217   g_advancedSettings.m_tvshowStackRegExps.push_back("[\\._ -]([0-9]+)([0-9][0-9])([\\._ -][^\\\\/]*)$");
218
219   g_advancedSettings.m_tvshowMultiPartStackRegExp = "^[-EeXx]+([0-9]+)";
220
221   g_advancedSettings.m_remoteRepeat = 480;
222   g_advancedSettings.m_controllerDeadzone = 0.2f;
223   g_advancedSettings.m_FTPShowCache = false;
224
225   g_advancedSettings.m_playlistAsFolders = true;
226   g_advancedSettings.m_detectAsUdf = false;
227
228   g_advancedSettings.m_thumbSize = 512;
229
230   g_advancedSettings.m_sambaclienttimeout = 10;
231   g_advancedSettings.m_sambadoscodepage = "";
232   g_advancedSettings.m_musicThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG|cover.jpg|Cover.jpg|cover.jpeg";
233   g_advancedSettings.m_dvdThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG";
234
235   g_advancedSettings.m_bMusicLibraryHideAllItems = false;
236   g_advancedSettings.m_bMusicLibraryAllItemsOnBottom = false;
237   g_advancedSettings.m_bMusicLibraryAlbumsSortByArtistThenYear = false;
238   g_advancedSettings.m_strMusicLibraryAlbumFormat = "";
239   g_advancedSettings.m_strMusicLibraryAlbumFormatRight = "";
240   g_advancedSettings.m_prioritiseAPEv2tags = false;
241   g_advancedSettings.m_musicItemSeparator = " / ";
242   g_advancedSettings.m_videoItemSeparator = " / ";
243
244   g_advancedSettings.m_bVideoLibraryHideAllItems = false;
245   g_advancedSettings.m_bVideoLibraryAllItemsOnBottom = false;
246   g_advancedSettings.m_bVideoLibraryHideRecentlyAddedItems = false;
247   g_advancedSettings.m_bVideoLibraryHideEmptySeries = false;
248   g_advancedSettings.m_bVideoLibraryCleanOnUpdate = false;
249
250   g_advancedSettings.m_bUseEvilB = true;
251
252   g_advancedSettings.m_bTuxBoxAudioChannelSelection = false;
253   g_advancedSettings.m_bTuxBoxSubMenuSelection = false;
254   g_advancedSettings.m_bTuxBoxPictureIcon= true;
255   g_advancedSettings.m_bTuxBoxSendAllAPids= false;
256   g_advancedSettings.m_iTuxBoxEpgRequestTime = 10; //seconds
257   g_advancedSettings.m_iTuxBoxDefaultSubMenu = 4;
258   g_advancedSettings.m_iTuxBoxDefaultRootMenu = 0; //default TV Mode
259   g_advancedSettings.m_iTuxBoxZapWaitTime = 0; // Time in sec. Default 0:OFF
260
261   g_advancedSettings.m_curlclienttimeout = 10;
262
263 #ifdef HAS_SDL
264   g_advancedSettings.m_fullScreen = false;
265 #endif
266
267   g_advancedSettings.m_playlistRetries = 100;
268   g_advancedSettings.m_playlistTimeout = 20; // 20 seconds timeout
269   g_advancedSettings.m_GLRectangleHack = false;
270   g_advancedSettings.m_iSkipLoopFilter = 0;
271   g_advancedSettings.m_osx_GLFullScreen = false;
272
273 #ifdef _WIN32
274         g_advancedSettings.m_ForcedSwapTime = 2.0;
275 #else
276         g_advancedSettings.m_ForcedSwapTime = 0.0;
277 #endif
278
279 }
280
281 CSettings::~CSettings(void)
282 {
283 }
284
285
286 void CSettings::Save() const
287 {
288   if (g_application.m_bStop)
289   {
290     //don't save settings when we're busy stopping the application
291     //a lot of screens try to save settings on deinit and deinit is called
292     //for every screen when the application is stopping.
293     return ;
294   }
295   if (!SaveSettings(GetSettingsFile()))
296   {
297     CLog::Log(LOGERROR, "Unable to save settings to %s", GetSettingsFile().c_str());
298   }
299 }
300
301 bool CSettings::Reset()
302 {
303   CLog::Log(LOGINFO, "Resetting settings");
304   CFile::Delete(GetSettingsFile());
305   Save();
306   return LoadSettings(GetSettingsFile());
307 }
308
309 bool CSettings::Load(bool& bXboxMediacenter, bool& bSettings)
310 {
311   // load settings file...
312   bXboxMediacenter = bSettings = false;
313
314   CStdString strMnt = GetProfileUserDataFolder();
315   CIoSupport::RemapDriveLetter('P', (char*) strMnt.c_str());
316   CLog::Log(LOGNOTICE, "loading %s", GetSettingsFile().c_str());
317   CStdString strFile=GetSettingsFile();
318   if (!LoadSettings(strFile))
319   {
320     CLog::Log(LOGERROR, "Unable to load %s, creating new %s with default values", GetSettingsFile().c_str(), GetSettingsFile().c_str());
321     Save();
322     if (!(bSettings = Reset()))
323       return false;
324   }
325
326   // clear sources, then load xml file...
327   m_fileSources.clear();
328   m_musicSources.clear();
329   m_pictureSources.clear();
330   m_programSources.clear();
331   m_videoSources.clear();
332   CStdString strXMLFile = GetSourcesFile();
333   CLog::Log(LOGNOTICE, "%s",strXMLFile.c_str());
334   TiXmlDocument xmlDoc;
335   TiXmlElement *pRootElement = NULL;
336   if ( xmlDoc.LoadFile( strXMLFile.c_str() ) )
337   {
338     pRootElement = xmlDoc.RootElement();
339     CStdString strValue;
340     if (pRootElement)
341       strValue = pRootElement->Value();
342     if ( strValue != "sources")
343       CLog::Log(LOGERROR, "%s sources.xml file does not contain <sources>", __FUNCTION__);
344   }
345   else
346     CLog::Log(LOGERROR, "%s Error loading %s: Line %d, %s", __FUNCTION__, strXMLFile.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
347
348   // look for external sources file
349   CStdString strCached = "Z:\\remotesources.xml";
350   bool bRemoteSourceFile = false;
351   TiXmlNode *pInclude = pRootElement ? pRootElement->FirstChild("remote") : NULL;
352   if (pInclude)
353   {
354     CStdString strRemoteFile = pInclude->FirstChild()->Value();
355     if (!strRemoteFile.IsEmpty())
356     {
357       // local file is not allowed as a remote source
358       if (!CUtil::IsHD(strRemoteFile))
359       {
360         CLog::Log(LOGDEBUG, "Found <remote> tag");
361         CLog::Log(LOGDEBUG, "Attempting to retrieve remote file: %s", strRemoteFile.c_str());
362         // sometimes we have to wait for the network
363         if (g_application.getNetwork().IsAvailable(true))
364         {
365           // cache the external source file
366           if (CFile::Cache(strRemoteFile, strCached))
367           {
368             bRemoteSourceFile = true;
369             CLog::Log(LOGDEBUG, "Success! Remote sources will be used");
370           }
371         }
372         else
373           CLog::Log(LOGERROR, "Could not retrieve remote file, defaulting to local sources");
374       }
375       else
376         CLog::Log(LOGERROR, "Local harddrive path is not allowed as remote");
377     }
378   }
379
380   // open cached external source file
381   if (bRemoteSourceFile)
382   {
383     strXMLFile = strCached;
384     if ( xmlDoc.LoadFile( strXMLFile.c_str() ) )
385     {
386       pRootElement = xmlDoc.RootElement();
387       CStdString strValue;
388       if (pRootElement)
389         strValue = pRootElement->Value();
390       if ( strValue != "sources")
391         CLog::Log(LOGERROR, "%s remote_sources.xml file does not contain <sources>", __FUNCTION__);
392     }
393     else
394       CLog::Log(LOGERROR, "%s unable to load file: %s, Line %d, %s", __FUNCTION__, strXMLFile.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
395   }
396
397   if (pRootElement)
398   { // parse sources...
399     GetSources(pRootElement, "programs", m_programSources, m_defaultProgramSource);
400     if (!m_programSources.size()) // backward compatibility with "my" notation
401       GetSources(pRootElement, "myprograms", m_programSources, m_defaultProgramSource);
402
403     GetSources(pRootElement, "pictures", m_pictureSources, m_defaultPictureSource);
404     GetSources(pRootElement, "files", m_fileSources, m_defaultFileSource);
405     GetSources(pRootElement, "music", m_musicSources, m_defaultMusicSource);
406     GetSources(pRootElement, "video", m_videoSources, m_defaultVideoSource);
407   }
408
409   bXboxMediacenter = true;
410
411   LoadRSSFeeds();
412   LoadUserFolderLayout();
413
414   return true;
415 }
416
417 void CSettings::ConvertHomeVar(CStdString& strText)
418 {
419   // Replaces first occurence of $HOME with the home directory.
420   // "$HOME\foo" becomes for instance "e:\apps\xbmc\foo"
421
422   char szText[1024];
423   char szTemp[1024];
424   char *pReplace, *pReplace2;
425
426   CStdString strHomePath = "Q:";
427   strcpy(szText, strText.c_str());
428
429   pReplace = strstr(szText, "$HOME");
430
431   if (pReplace != NULL)
432   {
433     pReplace2 = pReplace + sizeof("$HOME") - 1;
434     strcpy(szTemp, pReplace2);
435     strcpy(pReplace, strHomePath.c_str() );
436     strcat(szText, szTemp);
437   }
438   strText = szText;
439   // unroll any relative paths used
440   std::vector<CStdString> token;
441   CUtil::Tokenize(_P(strText),token,"\\");
442   if (token.size() > 1)
443   {
444     strText = "";
445     for (unsigned int i=0;i<token.size();++i)
446       if (token[i] == "..")
447       {
448         CStdString strParent;
449         CUtil::GetParentPath(strText,strParent);
450         strText = strParent;
451       }
452       else
453         strText += token[i]+"\\";
454   }
455 }
456
457 VECSOURCES *CSettings::GetSourcesFromType(const CStdString &type)
458 {
459   if (type == "programs" || type == "myprograms")
460     return &g_settings.m_programSources;
461   else if (type == "files")
462   {
463     // this nasty block of code is needed as we have to
464     // call getlocaldrives after localize strings has been loaded
465     bool bAdded=false;
466     for (unsigned int i=0;i<g_settings.m_fileSources.size();++i)
467     {
468       if (g_settings.m_fileSources[i].m_ignore)
469       {
470         bAdded = true;
471         break;
472       }
473     }
474     if (!bAdded)
475     {
476       VECSOURCES shares;
477       g_mediaManager.GetLocalDrives(shares, true);  // true to include Q
478       m_fileSources.insert(m_fileSources.end(),shares.begin(),shares.end());
479       
480       CMediaSource source;
481       source.strName = g_localizeStrings.Get(22013);
482       source.m_ignore = true;
483       source.strPath = _P("P:\\");
484       source.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
485       m_fileSources.push_back(source);
486     }
487
488     return &g_settings.m_fileSources;
489   }
490   else if (type == "music")
491     return &g_settings.m_musicSources;
492   else if (type == "video")
493     return &g_settings.m_videoSources;
494   else if (type == "pictures")
495     return &g_settings.m_pictureSources;
496   else if (type == "upnpmusic")
497     return &g_settings.m_UPnPMusicSources;
498   else if (type == "upnpvideo")
499     return &g_settings.m_UPnPVideoSources;
500   else if (type == "upnppictures")
501     return &g_settings.m_UPnPPictureSources;
502
503   return NULL;
504 }
505
506 CStdString CSettings::GetDefaultSourceFromType(const CStdString &type)
507 {
508   CStdString defaultShare;
509   if (type == "programs" || type == "myprograms")
510     defaultShare = g_settings.m_defaultProgramSource;
511   else if (type == "files")
512     defaultShare = g_settings.m_defaultFileSource;
513   else if (type == "music")
514     defaultShare = g_settings.m_defaultMusicSource;
515   else if (type == "video")
516     defaultShare = g_settings.m_defaultVideoSource;
517   else if (type == "pictures")
518     defaultShare = g_settings.m_defaultPictureSource;
519   return defaultShare;
520 }
521
522 void CSettings::GetSources(const TiXmlElement* pRootElement, const CStdString& strTagName, VECSOURCES& items, CStdString& strDefault)
523 {
524   //CLog::Log(LOGDEBUG, "  Parsing <%s> tag", strTagName.c_str());
525   strDefault = "";
526
527   items.clear();
528   const TiXmlNode *pChild = pRootElement->FirstChild(strTagName.c_str());
529   if (pChild)
530   {
531     pChild = pChild->FirstChild();
532     while (pChild > 0)
533     {
534       CStdString strValue = pChild->Value();
535       if (strValue == "source" || strValue == "bookmark") // "bookmark" left in for backwards compatibility
536       {
537         CMediaSource share;
538         if (GetSource(strTagName, pChild, share))
539         {
540           items.push_back(share);
541         }
542         else
543         {
544           CLog::Log(LOGERROR, "    Missing or invalid <name> and/or <path> in source");
545         }
546       }
547
548       if (strValue == "default")
549       {
550         const TiXmlNode *pValueNode = pChild->FirstChild();
551         if (pValueNode)
552         {
553           const char* pszText = pChild->FirstChild()->Value();
554           if (strlen(pszText) > 0)
555             strDefault = pszText;
556           CLog::Log(LOGDEBUG, "    Setting <default> source to : %s", strDefault.c_str());
557         }
558       }
559       pChild = pChild->NextSibling();
560     }
561   }
562   else
563   {
564     CLog::Log(LOGDEBUG, "  <%s> tag is missing or sources.xml is malformed", strTagName.c_str());
565   }
566 }
567
568 bool CSettings::GetSource(const CStdString &category, const TiXmlNode *source, CMediaSource &share)
569 {
570   //CLog::Log(LOGDEBUG,"    ---- SOURCE START ----");
571   const TiXmlNode *pNodeName = source->FirstChild("name");
572   CStdString strName;
573   if (pNodeName && pNodeName->FirstChild())
574   {
575     strName = pNodeName->FirstChild()->Value();
576     //CLog::Log(LOGDEBUG,"    Found name: %s", strName.c_str());
577   }
578   // get multiple paths
579   vector<CStdString> vecPaths;
580   const TiXmlNode *pPathName = source->FirstChild("path");
581   while (pPathName)
582   {
583     if (pPathName->FirstChild())
584     {
585       CStdString strPath = pPathName->FirstChild()->Value();
586       // make sure there are no virtualpaths or stack paths defined in xboxmediacenter.xml
587       //CLog::Log(LOGDEBUG,"    Found path: %s", strPath.c_str());
588       if (!CUtil::IsVirtualPath(strPath) && !CUtil::IsStack(strPath))
589       {
590         // translate special tags
591         if (strPath.at(0) == '$')
592         {
593           CStdString strPathOld(strPath);
594           strPath = CUtil::TranslateSpecialSource(strPath);
595           if (!strPath.IsEmpty())
596           {
597             //CLog::Log(LOGDEBUG,"    -> Translated to path: %s", strPath.c_str());
598           }
599           else
600           {
601             //CLog::Log(LOGERROR,"    -> Skipping invalid token: %s", strPathOld.c_str());
602             pPathName = pPathName->NextSibling("path");
603             continue;
604           }
605         }
606         CUtil::AddSlashAtEnd(strPath);
607         vecPaths.push_back(strPath);
608       }
609       else
610         CLog::Log(LOGERROR,"    Invalid path type (%s) in source", strPath.c_str());
611     }
612     pPathName = pPathName->NextSibling("path");
613   }
614
615   const TiXmlNode *pLockMode = source->FirstChild("lockmode");
616   const TiXmlNode *pLockCode = source->FirstChild("lockcode");
617   const TiXmlNode *pBadPwdCount = source->FirstChild("badpwdcount");
618   const TiXmlNode *pThumbnailNode = source->FirstChild("thumbnail");
619
620   if (!strName.IsEmpty() && vecPaths.size() > 0)
621   {
622     vector<CStdString> verifiedPaths;
623     // disallowed for files, or theres only a single path in the vector
624     if ((category.Equals("files")) || (vecPaths.size() == 1))
625       verifiedPaths.push_back(vecPaths[0]);
626
627     // multiple paths?
628     else
629     {
630       // validate the paths
631       for (int j = 0; j < (int)vecPaths.size(); ++j)
632       {
633         CURL url(vecPaths[j]);
634         CStdString protocol = url.GetProtocol();
635         bool bIsInvalid = false;
636
637         // for my programs
638         if (category.Equals("programs") || category.Equals("myprograms"))
639         {
640           // only allow HD and plugins
641           if (url.IsLocal() || protocol.Equals("plugin"))
642             verifiedPaths.push_back(vecPaths[j]);
643           else
644             bIsInvalid = true;
645         }
646
647         // for others allow everything (if the user does something silly, we can't stop them)
648         else
649           verifiedPaths.push_back(vecPaths[j]);
650
651         // error message
652         if (bIsInvalid)
653           CLog::Log(LOGERROR,"    Invalid path type (%s) for multipath source", vecPaths[j].c_str());
654       }
655
656       // no valid paths? skip to next source
657       if (verifiedPaths.size() == 0)
658       {
659         CLog::Log(LOGERROR,"    Missing or invalid <name> and/or <path> in source");
660         return false;
661       }
662     }
663
664     share.FromNameAndPaths(category, strName, verifiedPaths);
665
666 /*    CLog::Log(LOGDEBUG,"      Adding source:");
667     CLog::Log(LOGDEBUG,"        Name: %s", share.strName.c_str());
668     if (CUtil::IsVirtualPath(share.strPath) || CUtil::IsMultiPath(share.strPath))
669     {
670       for (int i = 0; i < (int)share.vecPaths.size(); ++i)
671         CLog::Log(LOGDEBUG,"        Path (%02i): %s", i+1, share.vecPaths.at(i).c_str());
672     }
673     else
674       CLog::Log(LOGDEBUG,"        Path: %s", share.strPath.c_str());
675 */
676     share.m_iBadPwdCount = 0;
677     if (pLockMode)
678     {
679       share.m_iLockMode = LockType(atoi(pLockMode->FirstChild()->Value()));
680       share.m_iHasLock = 2;
681     }
682
683     if (pLockCode)
684     {
685       if (pLockCode->FirstChild())
686         share.m_strLockCode = pLockCode->FirstChild()->Value();
687     }
688
689     if (pBadPwdCount)
690     {
691       if (pBadPwdCount->FirstChild())
692         share.m_iBadPwdCount = atoi( pBadPwdCount->FirstChild()->Value() );
693     }
694
695     if (pThumbnailNode)
696     {
697       if (pThumbnailNode->FirstChild())
698         share.m_strThumbnailImage = pThumbnailNode->FirstChild()->Value();
699     }
700
701     return true;
702   }
703   return false;
704 }
705
706 bool CSettings::GetString(const TiXmlElement* pRootElement, const char *tagName, CStdString &strValue)
707 {
708   CStdString defaultValue = strValue;
709   return GetString(pRootElement, tagName, strValue, defaultValue);
710 }
711
712 bool CSettings::GetString(const TiXmlElement* pRootElement, const char *tagName, CStdString &strValue, const CStdString& strDefaultValue)
713 {
714   if (XMLUtils::GetString(pRootElement, tagName, strValue))
715   { // tag exists
716     // check for "-" for backward compatibility
717     if (!strValue.Equals("-"))
718       return true;
719   }
720   // tag doesn't exist - set default
721   strValue = strDefaultValue;
722   return false;
723 }
724
725 bool CSettings::GetString(const TiXmlElement* pRootElement, const char *tagName, char *szValue, const CStdString& strDefaultValue)
726 {
727   CStdString strValue;
728   bool ret = GetString(pRootElement, tagName, strValue, strDefaultValue);
729   if (szValue)
730     strcpy(szValue, strValue.c_str());
731   return ret;
732 }
733
734 bool CSettings::GetInteger(const TiXmlElement* pRootElement, const char *tagName, int& iValue, const int iDefault, const int iMin, const int iMax)
735 {
736   if (GetInteger(pRootElement, tagName, iValue, iMin, iMax))
737     return true;
738   // default
739   iValue = iDefault;
740   return false;
741 }
742
743 bool CSettings::GetInteger(const TiXmlElement* pRootElement, const char *tagName, int& iValue, const int iMin, const int iMax)
744 {
745   if (XMLUtils::GetInt(pRootElement, tagName, iValue))
746   { // check range
747     if (iValue < iMin) iValue = iMin;
748     if (iValue > iMax) iValue = iMax;
749     return true;
750   }
751   return false;
752 }
753
754 bool CSettings::GetFloat(const TiXmlElement* pRootElement, const char *tagName, float& fValue, const float fDefault, const float fMin, const float fMax)
755 {
756   if (GetFloat(pRootElement, tagName, fValue, fMin, fMax))
757     return true;
758   // default
759   fValue = fDefault;
760   return false;
761 }
762
763 bool CSettings::GetFloat(const TiXmlElement* pRootElement, const char *tagName, float& fValue, const float fMin, const float fMax)
764 {
765   if (XMLUtils::GetFloat(pRootElement, tagName, fValue))
766   { // check range
767     if (fValue < fMin) fValue = fMin;
768     if (fValue > fMax) fValue = fMax;
769     return true;
770   }
771   return false;
772 }
773
774 void CSettings::GetViewState(const TiXmlElement *pRootElement, const CStdString &strTagName, CViewState &viewState, SORT_METHOD defaultSort, int defaultView)
775 {
776   const TiXmlElement* pNode = pRootElement->FirstChildElement(strTagName);
777   if (!pNode)
778   {
779     viewState.m_sortMethod = defaultSort;
780     viewState.m_viewMode = defaultView;
781     return;
782   }
783   GetInteger(pNode, "viewmode", viewState.m_viewMode, defaultView, DEFAULT_VIEW_LIST, DEFAULT_VIEW_MAX);
784   GetInteger(pNode, "sortmethod", (int&)viewState.m_sortMethod, defaultSort, SORT_METHOD_NONE, SORT_METHOD_MAX);
785   GetInteger(pNode, "sortorder", (int&)viewState.m_sortOrder, SORT_ORDER_ASC, SORT_ORDER_NONE, SORT_ORDER_DESC);
786 }
787
788 void CSettings::SetString(TiXmlNode* pRootNode, const CStdString& strTagName, const CStdString& strValue) const
789 {
790   CStdString strPersistedValue = strValue;
791   if (strPersistedValue.length() == 0)
792   {
793     strPersistedValue = '-';
794   }
795
796   TiXmlElement newElement(strTagName);
797   TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
798   if (pNewNode)
799   {
800     TiXmlText value(strValue);
801     pNewNode->InsertEndChild(value);
802   }
803 }
804
805 void CSettings::SetInteger(TiXmlNode* pRootNode, const CStdString& strTagName, int iValue) const
806 {
807   CStdString strValue;
808   strValue.Format("%d", iValue);
809   SetString(pRootNode, strTagName, strValue);
810 }
811
812 void CSettings::SetViewState(TiXmlNode *pRootNode, const CStdString &strTagName, const CViewState &viewState) const
813 {
814   TiXmlElement newElement(strTagName);
815   TiXmlNode *pNewNode = pRootNode->InsertEndChild(newElement);
816   if (pNewNode)
817   {
818     SetInteger(pNewNode, "viewmode", viewState.m_viewMode);
819     SetInteger(pNewNode, "sortmethod", (int)viewState.m_sortMethod);
820     SetInteger(pNewNode, "sortorder", (int)viewState.m_sortOrder);
821   }
822 }
823
824 void CSettings::SetFloat(TiXmlNode* pRootNode, const CStdString& strTagName, float fValue) const
825 {
826   CStdString strValue;
827   strValue.Format("%f", fValue);
828   SetString(pRootNode, strTagName, strValue);
829 }
830
831 void CSettings::SetBoolean(TiXmlNode* pRootNode, const CStdString& strTagName, bool bValue) const
832 {
833   if (bValue)
834     SetString(pRootNode, strTagName, "true");
835   else
836     SetString(pRootNode, strTagName, "false");
837 }
838
839 void CSettings::SetHex(TiXmlNode* pRootNode, const CStdString& strTagName, DWORD dwHexValue) const
840 {
841   CStdString strValue;
842   strValue.Format("%x", dwHexValue);
843   SetString(pRootNode, strTagName, strValue);
844 }
845
846 bool CSettings::LoadCalibration(const TiXmlElement* pElement, const CStdString& strSettingsFile)
847 {
848   // reset the calibration to the defaults
849   //g_graphicsContext.SetD3DParameters(NULL, m_ResInfo);
850   //for (int i=0; i<10; i++)
851   //  g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
852
853   const TiXmlElement *pRootElement;
854   CStdString strTagName = pElement->Value();
855   if (!strcmp(strTagName.c_str(), "calibration"))
856   {
857     pRootElement = pElement;
858   }
859   else
860   {
861     pRootElement = pElement->FirstChildElement("calibration");
862   }
863   if (!pRootElement)
864   {
865     g_LoadErrorStr.Format("%s Doesn't contain <calibration>", strSettingsFile.c_str());
866     return false;
867   }
868   const TiXmlElement *pResolution = pRootElement->FirstChildElement("resolution");
869   while (pResolution)
870   {
871     // get the data for this resolution
872     int iRes;
873     CStdString mode;
874     GetInteger(pResolution, "id", iRes, (int)PAL_4x3, HDTV_1080i, MAX_RESOLUTIONS); //PAL4x3 as default data
875     GetString(pResolution, "description", mode, m_ResInfo[iRes].strMode);
876 #ifdef HAS_SDL
877     if(iRes == DESKTOP && !mode.Equals(m_ResInfo[iRes].strMode))
878     {
879       CLog::Log(LOGDEBUG, "%s - Ignoring desktop resolution \"%s\" that differs from current \"%s\"", __FUNCTION__, mode.c_str(), m_ResInfo[iRes].strMode);
880
881       pResolution = pResolution->NextSiblingElement("resolution");
882       continue;
883     }
884 #endif
885
886     // get the appropriate "safe graphics area" = 10% for 4x3, 3.5% for 16x9
887     float fSafe;
888     if (iRes == PAL_4x3 || iRes == NTSC_4x3 || iRes == PAL60_4x3 || iRes == HDTV_480p_4x3)
889       fSafe = 0.1f;
890     else
891       fSafe = 0.035f;
892     GetInteger(pResolution, "subtitles", m_ResInfo[iRes].iSubtitles, (int)((1 - fSafe)*m_ResInfo[iRes].iHeight), m_ResInfo[iRes].iHeight / 2, m_ResInfo[iRes].iHeight*5 / 4);
893     GetFloat(pResolution, "pixelratio", m_ResInfo[iRes].fPixelRatio, 128.0f / 117.0f, 0.5f, 2.0f);
894
895 /* Hmm, these stuff shouldn't be releaded, they should be used instead of our internal
896    id counter to select what resolution is affected by this settings
897 #ifdef HAS_XRANDR
898     const CStdString def("");
899     CStdString val;
900     GetString(pResolution, "xrandrid", val, def);
901     strncpy(m_ResInfo[iRes].strId, val.c_str(), sizeof(m_ResInfo[iRes].strId));
902     GetString(pResolution, "output", val, def);
903     strncpy(m_ResInfo[iRes].strOutput, val.c_str(), sizeof(m_ResInfo[iRes].strOutput));
904     GetFloat(pResolution, "refreshrate", m_ResInfo[iRes].fRefreshRate, 0, 0, 200);
905 #endif
906 */
907
908     // get the overscan info
909     const TiXmlElement *pOverscan = pResolution->FirstChildElement("overscan");
910     if (pOverscan)
911     {
912       GetInteger(pOverscan, "left", m_ResInfo[iRes].Overscan.left, 0, -m_ResInfo[iRes].iWidth / 4, m_ResInfo[iRes].iWidth / 4);
913       GetInteger(pOverscan, "top", m_ResInfo[iRes].Overscan.top, 0, -m_ResInfo[iRes].iHeight / 4, m_ResInfo[iRes].iHeight / 4);
914       GetInteger(pOverscan, "right", m_ResInfo[iRes].Overscan.right, m_ResInfo[iRes].iWidth, m_ResInfo[iRes].iWidth / 2, m_ResInfo[iRes].iWidth*3 / 2);
915       GetInteger(pOverscan, "bottom", m_ResInfo[iRes].Overscan.bottom, m_ResInfo[iRes].iHeight, m_ResInfo[iRes].iHeight / 2, m_ResInfo[iRes].iHeight*3 / 2);
916     }
917
918 /*    CLog::Log(LOGDEBUG, "  calibration for %s %ix%i", m_ResInfo[iRes].strMode, m_ResInfo[iRes].iWidth, m_ResInfo[iRes].iHeight);
919     CLog::Log(LOGDEBUG, "    subtitle yposition:%i pixelratio:%03.3f offsets:(%i,%i)->(%i,%i)",
920               m_ResInfo[iRes].iSubtitles, m_ResInfo[iRes].fPixelRatio,
921               m_ResInfo[iRes].Overscan.left, m_ResInfo[iRes].Overscan.top,
922               m_ResInfo[iRes].Overscan.right, m_ResInfo[iRes].Overscan.bottom);*/
923
924     // iterate around
925     pResolution = pResolution->NextSiblingElement("resolution");
926   }
927   return true;
928 }
929
930 bool CSettings::SaveCalibration(TiXmlNode* pRootNode) const
931 {
932   TiXmlElement xmlRootElement("calibration");
933   TiXmlNode *pRoot = pRootNode->InsertEndChild(xmlRootElement);
934   for (int i = 0; i < 10; i++)
935   {
936     // Write the resolution tag
937     TiXmlElement resElement("resolution");
938     TiXmlNode *pNode = pRoot->InsertEndChild(resElement);
939     // Now write each of the pieces of information we need...
940     SetString(pNode, "description", m_ResInfo[i].strMode);
941     SetInteger(pNode, "id", i);
942     SetInteger(pNode, "subtitles", m_ResInfo[i].iSubtitles);
943     SetFloat(pNode, "pixelratio", m_ResInfo[i].fPixelRatio);
944     // create the overscan child
945     TiXmlElement overscanElement("overscan");
946     TiXmlNode *pOverscanNode = pNode->InsertEndChild(overscanElement);
947     SetInteger(pOverscanNode, "left", m_ResInfo[i].Overscan.left);
948     SetInteger(pOverscanNode, "top", m_ResInfo[i].Overscan.top);
949     SetInteger(pOverscanNode, "right", m_ResInfo[i].Overscan.right);
950     SetInteger(pOverscanNode, "bottom", m_ResInfo[i].Overscan.bottom);
951   }
952
953   // save WINDOW, DESKTOP and CUSTOM resolution
954   for (int i = (int)WINDOW ; i<(CUSTOM+g_videoConfig.GetNumberOfResolutions()) ; i++)
955   {
956     // Write the resolution tag
957     TiXmlElement resElement("resolution");
958     TiXmlNode *pNode = pRoot->InsertEndChild(resElement);
959     // Now write each of the pieces of information we need...
960     SetString(pNode, "description", m_ResInfo[i].strMode);
961     SetInteger(pNode, "id", i);
962     SetInteger(pNode, "subtitles", m_ResInfo[i].iSubtitles);
963     SetFloat(pNode, "pixelratio", m_ResInfo[i].fPixelRatio);
964 #ifdef HAS_XRANDR
965     SetFloat(pNode, "refreshrate", m_ResInfo[i].fRefreshRate);
966     SetString(pNode, "output", m_ResInfo[i].strOutput);
967     SetString(pNode, "xrandrid", m_ResInfo[i].strId);
968 #endif
969     // create the overscan child
970     TiXmlElement overscanElement("overscan");
971     TiXmlNode *pOverscanNode = pNode->InsertEndChild(overscanElement);
972     SetInteger(pOverscanNode, "left", m_ResInfo[i].Overscan.left);
973     SetInteger(pOverscanNode, "top", m_ResInfo[i].Overscan.top);
974     SetInteger(pOverscanNode, "right", m_ResInfo[i].Overscan.right);
975     SetInteger(pOverscanNode, "bottom", m_ResInfo[i].Overscan.bottom);
976   }
977   return true;
978 }
979
980 bool CSettings::LoadSettings(const CStdString& strSettingsFile)
981 {
982   // load the xml file
983   TiXmlDocument xmlDoc;
984
985   if (!xmlDoc.LoadFile(strSettingsFile))
986   {
987     g_LoadErrorStr.Format("%s, Line %d\n%s", strSettingsFile.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
988     return false;
989   }
990
991   TiXmlElement *pRootElement = xmlDoc.RootElement();
992   if (strcmpi(pRootElement->Value(), "settings") != 0)
993   {
994     g_LoadErrorStr.Format("%s\nDoesn't contain <settings>", strSettingsFile.c_str());
995     return false;
996   }
997
998   // mymusic settings
999   TiXmlElement *pElement = pRootElement->FirstChildElement("mymusic");
1000   if (pElement)
1001   {
1002     TiXmlElement *pChild = pElement->FirstChildElement("playlist");
1003     if (pChild)
1004     {
1005       XMLUtils::GetBoolean(pChild, "repeat", g_stSettings.m_bMyMusicPlaylistRepeat);
1006       XMLUtils::GetBoolean(pChild, "shuffle", g_stSettings.m_bMyMusicPlaylistShuffle);
1007     }
1008     // if the user happened to reboot in the middle of the scan we save this state
1009     pChild = pElement->FirstChildElement("scanning");
1010     if (pChild)
1011     {
1012       XMLUtils::GetBoolean(pChild, "isscanning", g_stSettings.m_bMyMusicIsScanning);
1013     }
1014     GetInteger(pElement, "startwindow", g_stSettings.m_iMyMusicStartWindow, WINDOW_MUSIC_FILES, WINDOW_MUSIC_FILES, WINDOW_MUSIC_NAV); //501; view songs
1015     XMLUtils::GetBoolean(pElement, "songinfoinvis", g_stSettings.m_bMyMusicSongInfoInVis);
1016     XMLUtils::GetBoolean(pElement, "songthumbinvis", g_stSettings.m_bMyMusicSongThumbInVis);
1017     GetString(pElement, "defaultlibview", g_settings.m_defaultMusicLibSource, g_settings.m_defaultMusicLibSource);
1018     GetString(pElement, "defaultscraper", g_stSettings.m_defaultMusicScraper, g_stSettings.m_defaultMusicScraper);
1019   }
1020   // myvideos settings
1021   pElement = pRootElement->FirstChildElement("myvideos");
1022   if (pElement)
1023   {
1024     GetInteger(pElement, "startwindow", g_stSettings.m_iVideoStartWindow, WINDOW_VIDEO_FILES, WINDOW_VIDEO_FILES, WINDOW_VIDEO_NAV);
1025     GetInteger(pElement, "stackvideomode", g_stSettings.m_iMyVideoStack, STACK_NONE, STACK_NONE, STACK_SIMPLE);
1026
1027     GetString(pElement, "cleantokens", g_stSettings.m_szMyVideoCleanTokens, g_stSettings.m_szMyVideoCleanTokens);
1028     GetString(pElement, "cleanseparators", g_stSettings.m_szMyVideoCleanSeparators, g_stSettings.m_szMyVideoCleanSeparators);
1029
1030     StringUtils::SplitString(g_stSettings.m_szMyVideoCleanTokens, "|", g_settings.m_szMyVideoCleanTokensArray);
1031     g_settings.m_szMyVideoCleanSeparatorsString = g_stSettings.m_szMyVideoCleanSeparators;
1032
1033     for (int i = 0; i < (int)g_settings.m_szMyVideoCleanTokensArray.size(); i++)
1034       g_settings.m_szMyVideoCleanTokensArray[i].MakeLower();
1035
1036     GetString(pElement, "defaultlibview", g_settings.m_defaultVideoLibSource, g_settings.m_defaultVideoLibSource);
1037     GetInteger(pElement, "watchmode", g_stSettings.m_iMyVideoWatchMode, VIDEO_SHOW_ALL, VIDEO_SHOW_ALL, VIDEO_SHOW_WATCHED);
1038     XMLUtils::GetBoolean(pElement, "flatten", g_stSettings.m_bMyVideoNavFlatten);
1039
1040     TiXmlElement *pChild = pElement->FirstChildElement("playlist");
1041     if (pChild)
1042     { // playlist
1043       XMLUtils::GetBoolean(pChild, "repeat", g_stSettings.m_bMyVideoPlaylistRepeat);
1044       XMLUtils::GetBoolean(pChild, "shuffle", g_stSettings.m_bMyVideoPlaylistShuffle);
1045     }
1046   }
1047
1048   pElement = pRootElement->FirstChildElement("viewstates");
1049   if (pElement)
1050   {
1051     GetViewState(pElement, "musicnavartists", g_stSettings.m_viewStateMusicNavArtists);
1052     GetViewState(pElement, "musicnavalbums", g_stSettings.m_viewStateMusicNavAlbums);
1053     GetViewState(pElement, "musicnavsongs", g_stSettings.m_viewStateMusicNavSongs);
1054     GetViewState(pElement, "musicshoutcast", g_stSettings.m_viewStateMusicShoutcast);
1055     GetViewState(pElement, "musiclastfm", g_stSettings.m_viewStateMusicLastFM);
1056     GetViewState(pElement, "videonavactors", g_stSettings.m_viewStateVideoNavActors);
1057     GetViewState(pElement, "videonavyears", g_stSettings.m_viewStateVideoNavYears);
1058     GetViewState(pElement, "videonavgenres", g_stSettings.m_viewStateVideoNavGenres);
1059     GetViewState(pElement, "videonavtitles", g_stSettings.m_viewStateVideoNavTitles);
1060     GetViewState(pElement, "videonavepisodes", g_stSettings.m_viewStateVideoNavEpisodes, SORT_METHOD_EPISODE);
1061     GetViewState(pElement, "videonavtvshows", g_stSettings.m_viewStateVideoNavTvShows);
1062     GetViewState(pElement, "videonavseasons", g_stSettings.m_viewStateVideoNavSeasons);
1063     GetViewState(pElement, "videonavmusicvideos", g_stSettings.m_viewStateVideoNavMusicVideos);
1064
1065     GetViewState(pElement, "programs", g_stSettings.m_viewStatePrograms, SORT_METHOD_LABEL, DEFAULT_VIEW_AUTO);
1066     GetViewState(pElement, "pictures", g_stSettings.m_viewStatePictures, SORT_METHOD_LABEL, DEFAULT_VIEW_AUTO);
1067     GetViewState(pElement, "videofiles", g_stSettings.m_viewStateVideoFiles, SORT_METHOD_LABEL, DEFAULT_VIEW_AUTO);
1068     GetViewState(pElement, "musicfiles", g_stSettings.m_viewStateMusicFiles, SORT_METHOD_LABEL, DEFAULT_VIEW_AUTO);
1069   }
1070
1071   // general settings
1072   pElement = pRootElement->FirstChildElement("general");
1073   if (pElement)
1074   {
1075     GetInteger(pElement, "systemtotaluptime", g_stSettings.m_iSystemTimeTotalUp, 0, 0, INT_MAX);
1076     GetInteger(pElement, "httpapibroadcastlevel", g_stSettings.m_HttpApiBroadcastLevel, 0, 0,5);
1077     GetInteger(pElement, "httpapibroadcastport", g_stSettings.m_HttpApiBroadcastPort, 8278, 1, 65535);
1078   }
1079
1080   pElement = pRootElement->FirstChildElement("defaultvideosettings");
1081   if (pElement)
1082   {
1083     GetInteger(pElement, "interlacemethod", (int &)g_stSettings.m_defaultVideoSettings.m_InterlaceMethod, VS_INTERLACEMETHOD_NONE, VS_INTERLACEMETHOD_NONE, VS_INTERLACEMETHOD_RENDER_BLEND);
1084     GetInteger(pElement, "filmgrain", g_stSettings.m_defaultVideoSettings.m_FilmGrain, 0, 0, 10);
1085     GetInteger(pElement, "viewmode", g_stSettings.m_defaultVideoSettings.m_ViewMode, VIEW_MODE_NORMAL, VIEW_MODE_NORMAL, VIEW_MODE_CUSTOM);
1086     GetFloat(pElement, "zoomamount", g_stSettings.m_defaultVideoSettings.m_CustomZoomAmount, 1.0f, 0.5f, 2.0f);
1087     GetFloat(pElement, "pixelratio", g_stSettings.m_defaultVideoSettings.m_CustomPixelRatio, 1.0f, 0.5f, 2.0f);
1088     GetFloat(pElement, "volumeamplification", g_stSettings.m_defaultVideoSettings.m_VolumeAmplification, VOLUME_DRC_MINIMUM * 0.01f, VOLUME_DRC_MINIMUM * 0.01f, VOLUME_DRC_MAXIMUM * 0.01f);
1089     XMLUtils::GetBoolean(pElement, "outputtoallspeakers", g_stSettings.m_defaultVideoSettings.m_OutputToAllSpeakers);
1090     XMLUtils::GetBoolean(pElement, "showsubtitles", g_stSettings.m_defaultVideoSettings.m_SubtitleOn);
1091     GetInteger(pElement, "brightness", g_stSettings.m_defaultVideoSettings.m_Brightness, 50, 0, 100);
1092     GetInteger(pElement, "contrast", g_stSettings.m_defaultVideoSettings.m_Contrast, 50, 0, 100);
1093     GetInteger(pElement, "gamma", g_stSettings.m_defaultVideoSettings.m_Gamma, 20, 0, 100);
1094     GetFloat(pElement, "audiodelay", g_stSettings.m_defaultVideoSettings.m_AudioDelay, 0.0f, -10.0f, 10.0f);
1095     GetFloat(pElement, "subtitledelay", g_stSettings.m_defaultVideoSettings.m_SubtitleDelay, 0.0f, -10.0f, 10.0f);
1096
1097     g_stSettings.m_defaultVideoSettings.m_SubtitleCached = false;
1098   }
1099   // audio settings
1100   pElement = pRootElement->FirstChildElement("audio");
1101   if (pElement)
1102   {
1103     GetInteger(pElement, "volumelevel", g_stSettings.m_nVolumeLevel, VOLUME_MAXIMUM, VOLUME_MINIMUM, VOLUME_MAXIMUM);
1104     GetInteger(pElement, "dynamicrangecompression", g_stSettings.m_dynamicRangeCompressionLevel, VOLUME_DRC_MINIMUM, VOLUME_DRC_MINIMUM, VOLUME_DRC_MAXIMUM);
1105     for (int i = 0; i < 4; i++)
1106     {
1107       CStdString setting;
1108       setting.Format("karaoke%i", i);
1109 #define XVOICE_MASK_PARAM_DISABLED (-1.0f)
1110       GetFloat(pElement, setting + "energy", g_stSettings.m_karaokeVoiceMask[i].energy, XVOICE_MASK_PARAM_DISABLED, XVOICE_MASK_PARAM_DISABLED, 1.0f);
1111       GetFloat(pElement, setting + "pitch", g_stSettings.m_karaokeVoiceMask[i].pitch, XVOICE_MASK_PARAM_DISABLED, XVOICE_MASK_PARAM_DISABLED, 1.0f);
1112       GetFloat(pElement, setting + "whisper", g_stSettings.m_karaokeVoiceMask[i].whisper, XVOICE_MASK_PARAM_DISABLED, XVOICE_MASK_PARAM_DISABLED, 1.0f);
1113       GetFloat(pElement, setting + "robotic", g_stSettings.m_karaokeVoiceMask[i].robotic, XVOICE_MASK_PARAM_DISABLED, XVOICE_MASK_PARAM_DISABLED, 1.0f);
1114     }
1115   }
1116
1117   LoadCalibration(pRootElement, strSettingsFile);
1118   g_guiSettings.LoadXML(pRootElement);
1119   LoadSkinSettings(pRootElement);
1120
1121   // Advanced settings
1122   LoadAdvancedSettings();
1123
1124   return true;
1125 }
1126
1127 void CSettings::LoadAdvancedSettings()
1128 {
1129   // NOTE: This routine should NOT set the default of any of these parameters
1130   //       it should instead use the versions of GetString/Integer/Float that
1131   //       don't take defaults in.  Defaults are set in the constructor above
1132   CStdString advancedSettingsXML;
1133   advancedSettingsXML  = g_settings.GetUserDataItem("advancedsettings.xml");
1134   TiXmlDocument advancedXML;
1135   if (!CFile::Exists(advancedSettingsXML))
1136   { // tell the user it doesn't exist
1137     CLog::Log(LOGNOTICE, "No advancedsettings.xml to load (%s)", advancedSettingsXML.c_str());
1138     return;
1139   }
1140
1141   if (!advancedXML.LoadFile(advancedSettingsXML.c_str()))
1142   {
1143     CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", advancedSettingsXML.c_str(), advancedXML.ErrorRow(), advancedXML.ErrorDesc());
1144     return;
1145   }
1146
1147   TiXmlElement *pRootElement = advancedXML.RootElement();
1148   if (!pRootElement || strcmpi(pRootElement->Value(),"advancedsettings") != 0)
1149   {
1150     CLog::Log(LOGERROR, "Error loading %s, no <advancedsettings> node", advancedSettingsXML.c_str());
1151     return;
1152   }
1153
1154   // succeeded - tell the user it worked
1155   CLog::Log(LOGNOTICE, "Loaded advancedsettings.xml from %s", advancedSettingsXML.c_str());
1156
1157   TiXmlElement *pElement = pRootElement->FirstChildElement("audio");
1158   if (pElement)
1159   {
1160     GetInteger(pElement, "headroom", g_advancedSettings.m_audioHeadRoom, 0, 12);
1161     GetFloat(pElement, "karaokesyncdelay", g_advancedSettings.m_karaokeSyncDelay, -3.0f, 3.0f);
1162     XMLUtils::GetBoolean(pElement, "analogmultichannel", g_advancedSettings.m_analogMultiChannel);
1163   }
1164
1165   pElement = pRootElement->FirstChildElement("video");
1166   if (pElement)
1167   {
1168     GetFloat(pElement, "subsdelayrange", g_advancedSettings.m_videoSubsDelayRange, 10, 600);
1169     GetFloat(pElement, "audiodelayrange", g_advancedSettings.m_videoAudioDelayRange, 10, 600);
1170     GetInteger(pElement, "smallstepbackseconds", g_advancedSettings.m_videoSmallStepBackSeconds, 1, INT_MAX);
1171     GetInteger(pElement, "smallstepbacktries", g_advancedSettings.m_videoSmallStepBackTries, 1, 10);
1172     GetInteger(pElement, "smallstepbackdelay", g_advancedSettings.m_videoSmallStepBackDelay, 100, 5000); //MS
1173
1174     XMLUtils::GetBoolean(pElement, "usetimeseeking", g_advancedSettings.m_videoUseTimeSeeking);
1175     GetInteger(pElement, "timeseekforward", g_advancedSettings.m_videoTimeSeekForward, 0, 6000);
1176     GetInteger(pElement, "timeseekbackward", g_advancedSettings.m_videoTimeSeekBackward, -6000, 0);
1177     GetInteger(pElement, "timeseekforwardbig", g_advancedSettings.m_videoTimeSeekForwardBig, 0, 6000);
1178     GetInteger(pElement, "timeseekbackwardbig", g_advancedSettings.m_videoTimeSeekBackwardBig, -6000, 0);
1179
1180     GetInteger(pElement, "percentseekforward", g_advancedSettings.m_videoPercentSeekForward, 0, 100);
1181     GetInteger(pElement, "percentseekbackward", g_advancedSettings.m_videoPercentSeekBackward, -100, 0);
1182     GetInteger(pElement, "percentseekforwardbig", g_advancedSettings.m_videoPercentSeekForwardBig, 0, 100);
1183     GetInteger(pElement, "percentseekbackwardbig", g_advancedSettings.m_videoPercentSeekBackwardBig, -100, 0);
1184     GetInteger(pElement, "blackbarcolour", g_advancedSettings.m_videoBlackBarColour, 0, 255);
1185     XMLUtils::GetBoolean(pElement, "fullscreenonmoviestart", g_advancedSettings.m_fullScreenOnMovieStart);
1186   }
1187
1188   pElement = pRootElement->FirstChildElement("musiclibrary");
1189   if (pElement)
1190   {
1191     XMLUtils::GetBoolean(pElement, "hideallitems", g_advancedSettings.m_bMusicLibraryHideAllItems);
1192     XMLUtils::GetBoolean(pElement, "prioritiseapetags", g_advancedSettings.m_prioritiseAPEv2tags);
1193     XMLUtils::GetBoolean(pElement, "allitemsonbottom", g_advancedSettings.m_bMusicLibraryAllItemsOnBottom);
1194     XMLUtils::GetBoolean(pElement, "albumssortbyartistthenyear", g_advancedSettings.m_bMusicLibraryAlbumsSortByArtistThenYear);
1195     GetString(pElement, "albumformat", g_advancedSettings.m_strMusicLibraryAlbumFormat);
1196     GetString(pElement, "albumformatright", g_advancedSettings.m_strMusicLibraryAlbumFormatRight);
1197     GetString(pElement, "itemseparator", g_advancedSettings.m_musicItemSeparator);
1198   }
1199
1200   pElement = pRootElement->FirstChildElement("videolibrary");
1201   if (pElement)
1202   {
1203     XMLUtils::GetBoolean(pElement, "hideallitems", g_advancedSettings.m_bVideoLibraryHideAllItems);
1204     XMLUtils::GetBoolean(pElement, "allitemsonbottom", g_advancedSettings.m_bVideoLibraryAllItemsOnBottom);
1205     XMLUtils::GetBoolean(pElement, "hiderecentlyaddeditems", g_advancedSettings.m_bVideoLibraryHideRecentlyAddedItems);
1206     XMLUtils::GetBoolean(pElement, "hideemptyseries", g_advancedSettings.m_bVideoLibraryHideEmptySeries);
1207     XMLUtils::GetBoolean(pElement, "cleanonupdate", g_advancedSettings.m_bVideoLibraryCleanOnUpdate);
1208     GetString(pElement, "itemseparator", g_advancedSettings.m_videoItemSeparator);
1209   }
1210
1211   pElement = pRootElement->FirstChildElement("slideshow");
1212   if (pElement)
1213   {
1214     GetFloat(pElement, "panamount", g_advancedSettings.m_slideshowPanAmount, 0.0f, 20.0f);
1215     GetFloat(pElement, "zoomamount", g_advancedSettings.m_slideshowZoomAmount, 0.0f, 20.0f);
1216     GetFloat(pElement, "blackbarcompensation", g_advancedSettings.m_slideshowBlackBarCompensation, 0.0f, 50.0f);
1217   }
1218
1219   pElement = pRootElement->FirstChildElement("lcd");
1220   if (pElement)
1221   {
1222     GetInteger(pElement, "rows", g_advancedSettings.m_lcdRows, 1, 4);
1223     GetInteger(pElement, "columns", g_advancedSettings.m_lcdColumns, 1, 40);
1224     GetInteger(pElement, "address1", g_advancedSettings.m_lcdAddress1, 0, 0x100);
1225     GetInteger(pElement, "address2", g_advancedSettings.m_lcdAddress2, 0, 0x100);
1226     GetInteger(pElement, "address3", g_advancedSettings.m_lcdAddress3, 0, 0x100);
1227     GetInteger(pElement, "address4", g_advancedSettings.m_lcdAddress4, 0, 0x100);
1228     XMLUtils::GetBoolean(pElement, "heartbeat", g_advancedSettings.m_lcdHeartbeat);
1229   }
1230   pElement = pRootElement->FirstChildElement("network");
1231   if (pElement)
1232   {
1233     GetInteger(pElement, "autodetectpingtime", g_advancedSettings.m_autoDetectPingTime, 1, 240);
1234     GetInteger(pElement, "curlclienttimeout", g_advancedSettings.m_curlclienttimeout, 1, 1000);
1235   }
1236
1237   GetFloat(pRootElement, "playcountminimumpercent", g_advancedSettings.m_playCountMinimumPercent, 1.0f, 100.0f);
1238
1239   pElement = pRootElement->FirstChildElement("samba");
1240   if (pElement)
1241   {
1242     GetString(pElement,  "doscodepage",   g_advancedSettings.m_sambadoscodepage);
1243     GetInteger(pElement, "clienttimeout", g_advancedSettings.m_sambaclienttimeout, 5, 100);
1244   }
1245
1246   if (GetInteger(pRootElement, "loglevel", g_advancedSettings.m_logLevel, LOG_LEVEL_NONE, LOG_LEVEL_MAX))
1247   { // read the loglevel setting, so set the setting advanced to hide it in GUI
1248     // as altering it will do nothing - we don't write to advancedsettings.xml
1249     CSettingBool *setting = (CSettingBool *)g_guiSettings.GetSetting("system.debuglogging");
1250     if (setting)
1251     {
1252       setting->SetData(g_advancedSettings.m_logLevel >= LOG_LEVEL_DEBUG_FREEMEM);
1253       setting->SetAdvanced();
1254     }
1255   }
1256   GetString(pRootElement, "cddbaddress", g_advancedSettings.m_cddbAddress);
1257 #ifdef HAS_HAL
1258   XMLUtils::GetBoolean(pRootElement, "usehalmount", g_advancedSettings.m_useHalMount);
1259   XMLUtils::GetBoolean(pRootElement, "systempowermanagement", g_advancedSettings.m_useSystemPowerManagement);
1260 #endif
1261   XMLUtils::GetBoolean(pRootElement, "nodvdrom", g_advancedSettings.m_noDVDROM);
1262   XMLUtils::GetBoolean(pRootElement, "usemultipaths", g_advancedSettings.m_useMultipaths);
1263   XMLUtils::GetBoolean(pRootElement, "disablemodchipdetection", g_advancedSettings.m_DisableModChipDetection);
1264 #ifdef HAS_SDL
1265   XMLUtils::GetBoolean(pRootElement, "fullscreen", g_advancedSettings.m_startFullScreen);
1266 #endif
1267
1268   GetInteger(pRootElement, "songinfoduration", g_advancedSettings.m_songInfoDuration, 1, 15);
1269   GetInteger(pRootElement, "busydialogdelay", g_advancedSettings.m_busyDialogDelay, 0, 5000);
1270   GetInteger(pRootElement, "playlistretries", g_advancedSettings.m_playlistRetries, -1, 5000);
1271   GetInteger(pRootElement, "playlisttimeout", g_advancedSettings.m_playlistTimeout, 0, 5000);
1272
1273   XMLUtils::GetBoolean(pRootElement,"rootovershoot",g_advancedSettings.m_bUseEvilB);
1274   XMLUtils::GetBoolean(pRootElement,"glrectanglehack", g_advancedSettings.m_GLRectangleHack);
1275   GetInteger(pRootElement,"skiploopfilter", g_advancedSettings.m_iSkipLoopFilter, 0, -16, 48);
1276         GetFloat(pRootElement, "forcedswaptime", g_advancedSettings.m_ForcedSwapTime, 0.0, 100.0);
1277   XMLUtils::GetBoolean(pRootElement,"osx_gl_fullscreen", g_advancedSettings.m_osx_GLFullScreen);
1278
1279   //Tuxbox
1280   pElement = pRootElement->FirstChildElement("tuxbox");
1281   if (pElement)
1282   {
1283     XMLUtils::GetBoolean(pElement, "audiochannelselection", g_advancedSettings.m_bTuxBoxAudioChannelSelection);
1284     XMLUtils::GetBoolean(pElement, "submenuselection", g_advancedSettings.m_bTuxBoxSubMenuSelection);
1285     XMLUtils::GetBoolean(pElement, "pictureicon", g_advancedSettings.m_bTuxBoxPictureIcon);
1286     XMLUtils::GetBoolean(pElement, "sendallaudiopids", g_advancedSettings.m_bTuxBoxSendAllAPids);
1287     GetInteger(pElement, "epgrequesttime", g_advancedSettings.m_iTuxBoxEpgRequestTime, 0, 3600);
1288     GetInteger(pElement, "defaultsubmenu", g_advancedSettings.m_iTuxBoxDefaultSubMenu, 1, 4);
1289     GetInteger(pElement, "defaultrootmenu", g_advancedSettings.m_iTuxBoxDefaultRootMenu, 0, 4);
1290     GetInteger(pElement, "zapwaittime", g_advancedSettings.m_iTuxBoxZapWaitTime, 0, 120);
1291
1292   }
1293
1294   CStdString extraExtensions;
1295   TiXmlElement* pExts = pRootElement->FirstChildElement("pictureextensions");
1296   if (pExts)
1297   {
1298     GetString(pExts,"add",extraExtensions,"");
1299     if (extraExtensions != "")
1300       g_stSettings.m_pictureExtensions += "|" + extraExtensions;
1301     GetString(pExts,"remove",extraExtensions,"");
1302     if (extraExtensions != "")
1303     {
1304       CStdStringArray exts;
1305       StringUtils::SplitString(extraExtensions,"|",exts);
1306       for (unsigned int i=0;i<exts.size();++i)
1307       {
1308         int iPos = g_stSettings.m_pictureExtensions.Find(exts[i]);
1309         if (iPos == -1)
1310           continue;
1311         g_stSettings.m_pictureExtensions.erase(iPos,exts[i].size()+1);
1312       }
1313     }
1314   }
1315   pExts = pRootElement->FirstChildElement("musicextensions");
1316   if (pExts)
1317   {
1318     GetString(pExts,"add",extraExtensions,"");
1319     if (extraExtensions != "")
1320       g_stSettings.m_musicExtensions += "|" + extraExtensions;
1321     GetString(pExts,"remove",extraExtensions,"");
1322     if (extraExtensions != "")
1323     {
1324       CStdStringArray exts;
1325       StringUtils::SplitString(extraExtensions,"|",exts);
1326       for (unsigned int i=0;i<exts.size();++i)
1327       {
1328         int iPos = g_stSettings.m_musicExtensions.Find(exts[i]);
1329         if (iPos == -1)
1330           continue;
1331         g_stSettings.m_musicExtensions.erase(iPos,exts[i].size()+1);
1332       }
1333     }
1334   }
1335   pExts = pRootElement->FirstChildElement("videoextensions");
1336   if (pExts)
1337   {
1338     GetString(pExts,"add",extraExtensions,"");
1339     if (extraExtensions != "")
1340       g_stSettings.m_videoExtensions += "|" + extraExtensions;
1341     GetString(pExts,"remove",extraExtensions,"");
1342     if (extraExtensions != "")
1343     {
1344       CStdStringArray exts;
1345       StringUtils::SplitString(extraExtensions,"|",exts);
1346       for (unsigned int i=0;i<exts.size();++i)
1347       {
1348         int iPos = g_stSettings.m_videoExtensions.Find(exts[i]);
1349         if (iPos == -1)
1350           continue;
1351         g_stSettings.m_videoExtensions.erase(iPos,exts[i].size()+1);
1352       }
1353     }
1354   }
1355
1356   const TiXmlNode *pTokens = pRootElement->FirstChild("sorttokens");
1357   g_advancedSettings.m_vecTokens.clear();
1358   if (pTokens && !pTokens->NoChildren())
1359   {
1360     const TiXmlNode *pToken = pTokens->FirstChild("token");
1361     while (pToken)
1362     {
1363       if (pToken->FirstChild() && pToken->FirstChild()->Value())
1364         g_advancedSettings.m_vecTokens.push_back(CStdString(pToken->FirstChild()->Value()) + " ");
1365       pToken = pToken->NextSibling();
1366     }
1367   }
1368
1369   XMLUtils::GetBoolean(pRootElement, "displayremotecodes", g_advancedSettings.m_displayRemoteCodes);
1370
1371   // TODO: Should cache path be given in terms of our predefined paths??
1372   //       Are we even going to have predefined paths??
1373   GetString(pRootElement, "cachepath", g_advancedSettings.m_cachePath);
1374   g_advancedSettings.m_cachePath = CUtil::TranslateSpecialSource(g_advancedSettings.m_cachePath);
1375   CUtil::AddSlashAtEnd(g_advancedSettings.m_cachePath);
1376
1377   XMLUtils::GetBoolean(pRootElement, "ftpshowcache", g_advancedSettings.m_FTPShowCache);
1378
1379   g_LangCodeExpander.LoadUserCodes(pRootElement->FirstChildElement("languagecodes"));
1380
1381   // exclude regexps
1382   TiXmlElement* pScanExcludes = pRootElement->FirstChildElement("excludefromscan");
1383   if (pScanExcludes)
1384     GetCustomRegexps(pScanExcludes, g_advancedSettings.m_videoExcludeRegExps);
1385
1386   // stacking regexps
1387   TiXmlElement* pVideoStacking = pRootElement->FirstChildElement("moviestacking");
1388   if (pVideoStacking)
1389     GetCustomRegexps(pVideoStacking, g_advancedSettings.m_videoStackRegExps);
1390
1391   //tv stacking regexps
1392   TiXmlElement* pTVStacking = pRootElement->FirstChildElement("tvshowmatching");
1393   if (pTVStacking)
1394     GetCustomRegexps(pTVStacking, g_advancedSettings.m_tvshowStackRegExps);
1395
1396   // path substitutions
1397   TiXmlElement* pPathSubstitution = pRootElement->FirstChildElement("pathsubstitution");
1398   if (pPathSubstitution)
1399   {
1400     g_advancedSettings.m_pathSubstitutions.clear();
1401     CLog::Log(LOGDEBUG,"Configuring path substitutions");
1402     TiXmlNode* pSubstitute = pPathSubstitution->FirstChildElement("substitute");
1403     while (pSubstitute)
1404     {
1405       CStdString strFrom, strTo;
1406       TiXmlNode* pFrom = pSubstitute->FirstChild("from");
1407       if (pFrom)
1408         strFrom = pFrom->FirstChild()->Value();
1409       TiXmlNode* pTo = pSubstitute->FirstChild("to");
1410       if (pTo)
1411         strTo = pTo->FirstChild()->Value();
1412
1413       if (!strFrom.IsEmpty() && !strTo.IsEmpty())
1414       {
1415         CLog::Log(LOGDEBUG,"  Registering substition pair:");
1416         CLog::Log(LOGDEBUG,"    From: [%s]", strFrom.c_str());
1417         CLog::Log(LOGDEBUG,"    To:   [%s]", strTo.c_str());
1418         // keep literal commas since we use comma as a seperator
1419         strFrom.Replace(",",",,");
1420         strTo.Replace(",",",,");
1421         g_advancedSettings.m_pathSubstitutions.push_back(strFrom + " , " + strTo);
1422       }
1423       else
1424       {
1425         // error message about missing tag
1426         if (strFrom.IsEmpty())
1427           CLog::Log(LOGERROR,"  Missing <from> tag");
1428         else
1429           CLog::Log(LOGERROR,"  Missing <to> tag");
1430       }
1431
1432       // get next one
1433       pSubstitute = pSubstitute->NextSiblingElement("substitute");
1434     }
1435   }
1436
1437   GetInteger(pRootElement, "remoterepeat", g_advancedSettings.m_remoteRepeat, 1, INT_MAX);
1438   GetFloat(pRootElement, "controllerdeadzone", g_advancedSettings.m_controllerDeadzone, 0.0f, 1.0f);
1439   GetInteger(pRootElement, "thumbsize", g_advancedSettings.m_thumbSize, g_advancedSettings.m_thumbSize, 64, 1024);
1440
1441   XMLUtils::GetBoolean(pRootElement, "playlistasfolders", g_advancedSettings.m_playlistAsFolders);
1442   XMLUtils::GetBoolean(pRootElement, "detectasudf", g_advancedSettings.m_detectAsUdf);
1443
1444   // music thumbs
1445   CStdString extraThumbs;
1446   TiXmlElement* pThumbs = pRootElement->FirstChildElement("musicthumbs");
1447   if (pThumbs)
1448   {
1449     // remove before add so that the defaults can be restored after user defined ones
1450     // (ie, the list can be:cover.jpg|cover.png|folder.jpg)
1451     GetString(pThumbs, "remove", extraThumbs, "");
1452     if (extraThumbs != "")
1453     {
1454       CStdStringArray thumbs;
1455       StringUtils::SplitString(extraThumbs, "|", thumbs);
1456       for (unsigned int i = 0; i < thumbs.size(); ++i)
1457       {
1458         int iPos = g_advancedSettings.m_musicThumbs.Find(thumbs[i]);
1459         if (iPos == -1)
1460           continue;
1461         g_advancedSettings.m_musicThumbs.erase(iPos, thumbs[i].size() + 1);
1462       }
1463     }
1464     GetString(pThumbs, "add", extraThumbs,"");
1465     if (extraThumbs != "")
1466     {
1467       if (!g_advancedSettings.m_musicThumbs.IsEmpty())
1468         g_advancedSettings.m_musicThumbs += "|";
1469       g_advancedSettings.m_musicThumbs += extraThumbs;
1470     }
1471   }
1472
1473   // dvd thumbs
1474   pThumbs = pRootElement->FirstChildElement("dvdthumbs");
1475   if (pThumbs)
1476   {
1477     // remove before add so that the defaults can be restored after user defined ones
1478     // (ie, the list can be:cover.jpg|cover.png|folder.jpg)
1479     GetString(pThumbs, "remove", extraThumbs, "");
1480     if (extraThumbs != "")
1481     {
1482       CStdStringArray thumbs;
1483       StringUtils::SplitString(extraThumbs, "|", thumbs);
1484       for (unsigned int i = 0; i < thumbs.size(); ++i)
1485       {
1486         int iPos = g_advancedSettings.m_musicThumbs.Find(thumbs[i]);
1487         if (iPos == -1)
1488           continue;
1489         g_advancedSettings.m_musicThumbs.erase(iPos, thumbs[i].size() + 1);
1490       }
1491     }
1492     GetString(pThumbs, "add", extraThumbs,"");
1493     if (extraThumbs != "")
1494     {
1495       if (!g_advancedSettings.m_musicThumbs.IsEmpty())
1496         g_advancedSettings.m_musicThumbs += "|";
1497       g_advancedSettings.m_musicThumbs += extraThumbs;
1498     }
1499   }
1500
1501   // music filename->tag filters
1502   TiXmlElement* filters = pRootElement->FirstChildElement("musicfilenamefilters");
1503   if (filters)
1504   {
1505     TiXmlNode* filter = filters->FirstChild("filter");
1506     while (filter)
1507     {
1508       if (filter->FirstChild())
1509         g_advancedSettings.m_musicTagsFromFileFilters.push_back(filter->FirstChild()->ValueStr());
1510       filter = filter->NextSibling("filter");
1511     }
1512   }
1513
1514   TiXmlElement* pHostEntries = pRootElement->FirstChildElement("hosts");
1515   if (pHostEntries)
1516   {
1517     TiXmlElement* element = pHostEntries->FirstChildElement("entry");
1518     while(element)
1519     {
1520       CStdString name  = element->Attribute("name");
1521       CStdString value;
1522       if(element->GetText())
1523         value = element->GetText();
1524
1525       if(name.length() > 0 && value.length() > 0)
1526         CDNSNameCache::Add(name, value);
1527       element = element->NextSiblingElement("entry");
1528     }
1529   }
1530
1531   // load in the GUISettings overrides:
1532   g_guiSettings.LoadXML(pRootElement, true);  // true to hide the settings we read in
1533 }
1534
1535 void CSettings::GetCustomRegexps(TiXmlElement *pRootElement, CStdStringArray& settings)
1536 {
1537   int iAction = 0; // overwrite
1538   // for backward compatibility
1539   const char* szAppend = pRootElement->Attribute("append");
1540   if ((szAppend && stricmp(szAppend, "yes") == 0))
1541     iAction = 1;
1542   // action takes precedence if both attributes exist
1543   const char* szAction = pRootElement->Attribute("action");
1544   if (szAction)
1545   {
1546     iAction = 0; // overwrite
1547     if (stricmp(szAction, "append") == 0)
1548       iAction = 1; // append
1549     else if (stricmp(szAction, "prepend") == 0)
1550       iAction = 2; // prepend
1551   }
1552   if (iAction == 0)
1553     settings.clear();
1554   TiXmlNode* pRegExp = pRootElement->FirstChild("regexp");
1555   int i = 0;
1556   while (pRegExp)
1557   {
1558     if (pRegExp->FirstChild())
1559     {
1560       CStdString regExp = pRegExp->FirstChild()->Value();
1561       regExp.MakeLower();
1562       if (iAction == 2)
1563         settings.insert(settings.begin() + i++, 1, regExp);
1564       else
1565         settings.push_back(regExp);
1566     }
1567     pRegExp = pRegExp->NextSibling("regexp");
1568   }
1569 }
1570
1571 bool CSettings::SaveSettings(const CStdString& strSettingsFile, CGUISettings *localSettings /* = NULL */) const
1572 {
1573   TiXmlDocument xmlDoc;
1574   TiXmlElement xmlRootElement("settings");
1575   TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);
1576   if (!pRoot) return false;
1577   // write our tags one by one - just a big list for now (can be flashed up later)
1578
1579   // mymusic settings
1580   TiXmlElement musicNode("mymusic");
1581   TiXmlNode *pNode = pRoot->InsertEndChild(musicNode);
1582   if (!pNode) return false;
1583   {
1584     TiXmlElement childNode("playlist");
1585     TiXmlNode *pChild = pNode->InsertEndChild(childNode);
1586     if (!pChild) return false;
1587     SetBoolean(pChild, "repeat", g_stSettings.m_bMyMusicPlaylistRepeat);
1588     SetBoolean(pChild, "shuffle", g_stSettings.m_bMyMusicPlaylistShuffle);
1589   }
1590   {
1591     TiXmlElement childNode("scanning");
1592     TiXmlNode *pChild = pNode->InsertEndChild(childNode);
1593     if (!pChild) return false;
1594     SetBoolean(pChild, "isscanning", g_stSettings.m_bMyMusicIsScanning);
1595   }
1596
1597   SetInteger(pNode, "startwindow", g_stSettings.m_iMyMusicStartWindow);
1598   SetBoolean(pNode, "songinfoinvis", g_stSettings.m_bMyMusicSongInfoInVis);
1599   SetBoolean(pNode, "songthumbinvis", g_stSettings.m_bMyMusicSongThumbInVis);
1600   SetString(pNode, "defaultlibview", g_settings.m_defaultMusicLibSource);
1601   SetString(pNode, "defaultscraper", g_stSettings.m_defaultMusicScraper);
1602
1603   // myvideos settings
1604   TiXmlElement videosNode("myvideos");
1605   pNode = pRoot->InsertEndChild(videosNode);
1606   if (!pNode) return false;
1607
1608   SetInteger(pNode, "startwindow", g_stSettings.m_iVideoStartWindow);
1609
1610   SetInteger(pNode, "stackvideomode", g_stSettings.m_iMyVideoStack);
1611
1612   SetString(pNode, "cleantokens", g_stSettings.m_szMyVideoCleanTokens);
1613   SetString(pNode, "cleanseparators", g_stSettings.m_szMyVideoCleanSeparators);
1614   SetString(pNode, "defaultlibview", g_settings.m_defaultVideoLibSource);
1615
1616   SetInteger(pNode, "watchmode", g_stSettings.m_iMyVideoWatchMode);
1617   SetBoolean(pNode, "flatten", g_stSettings.m_bMyVideoNavFlatten);
1618
1619   { // playlist window
1620     TiXmlElement childNode("playlist");
1621     TiXmlNode *pChild = pNode->InsertEndChild(childNode);
1622     if (!pChild) return false;
1623     SetBoolean(pChild, "repeat", g_stSettings.m_bMyVideoPlaylistRepeat);
1624     SetBoolean(pChild, "shuffle", g_stSettings.m_bMyVideoPlaylistShuffle);
1625   }
1626
1627   // view states
1628   TiXmlElement viewStateNode("viewstates");
1629   pNode = pRoot->InsertEndChild(viewStateNode);
1630   if (pNode)
1631   {
1632     SetViewState(pNode, "musicnavartists", g_stSettings.m_viewStateMusicNavArtists);
1633     SetViewState(pNode, "musicnavalbums", g_stSettings.m_viewStateMusicNavAlbums);
1634     SetViewState(pNode, "musicnavsongs", g_stSettings.m_viewStateMusicNavSongs);
1635     SetViewState(pNode, "musicshoutcast", g_stSettings.m_viewStateMusicShoutcast);
1636     SetViewState(pNode, "musiclastfm", g_stSettings.m_viewStateMusicLastFM);
1637     SetViewState(pNode, "videonavactors", g_stSettings.m_viewStateVideoNavActors);
1638     SetViewState(pNode, "videonavyears", g_stSettings.m_viewStateVideoNavYears);
1639     SetViewState(pNode, "videonavgenres", g_stSettings.m_viewStateVideoNavGenres);
1640     SetViewState(pNode, "videonavtitles", g_stSettings.m_viewStateVideoNavTitles);
1641     SetViewState(pNode, "videonavepisodes", g_stSettings.m_viewStateVideoNavEpisodes);
1642     SetViewState(pNode, "videonavseasons", g_stSettings.m_viewStateVideoNavSeasons);
1643     SetViewState(pNode, "videonavtvshows", g_stSettings.m_viewStateVideoNavTvShows);
1644     SetViewState(pNode, "videonavmusicvideos", g_stSettings.m_viewStateVideoNavMusicVideos);
1645
1646     SetViewState(pNode, "programs", g_stSettings.m_viewStatePrograms);
1647     SetViewState(pNode, "pictures", g_stSettings.m_viewStatePictures);
1648     SetViewState(pNode, "videofiles", g_stSettings.m_viewStateVideoFiles);
1649     SetViewState(pNode, "musicfiles", g_stSettings.m_viewStateMusicFiles);
1650   }
1651
1652   // general settings
1653   TiXmlElement generalNode("general");
1654   pNode = pRoot->InsertEndChild(generalNode);
1655   if (!pNode) return false;
1656   SetInteger(pNode, "systemtotaluptime", g_stSettings.m_iSystemTimeTotalUp);
1657   SetInteger(pNode, "httpapibroadcastport", g_stSettings.m_HttpApiBroadcastPort);
1658   SetInteger(pNode, "httpapibroadcastlevel", g_stSettings.m_HttpApiBroadcastLevel);
1659
1660   // default video settings
1661   TiXmlElement videoSettingsNode("defaultvideosettings");
1662   pNode = pRoot->InsertEndChild(videoSettingsNode);
1663   if (!pNode) return false;
1664   SetInteger(pNode, "interlacemethod", g_stSettings.m_defaultVideoSettings.m_InterlaceMethod);
1665   SetInteger(pNode, "filmgrain", g_stSettings.m_defaultVideoSettings.m_FilmGrain);
1666   SetInteger(pNode, "viewmode", g_stSettings.m_defaultVideoSettings.m_ViewMode);
1667   SetFloat(pNode, "zoomamount", g_stSettings.m_defaultVideoSettings.m_CustomZoomAmount);
1668   SetFloat(pNode, "pixelratio", g_stSettings.m_defaultVideoSettings.m_CustomPixelRatio);
1669   SetFloat(pNode, "volumeamplification", g_stSettings.m_defaultVideoSettings.m_VolumeAmplification);
1670   SetBoolean(pNode, "outputtoallspeakers", g_stSettings.m_defaultVideoSettings.m_OutputToAllSpeakers);
1671   SetBoolean(pNode, "showsubtitles", g_stSettings.m_defaultVideoSettings.m_SubtitleOn);
1672   SetInteger(pNode, "brightness", g_stSettings.m_defaultVideoSettings.m_Brightness);
1673   SetInteger(pNode, "contrast", g_stSettings.m_defaultVideoSettings.m_Contrast);
1674   SetInteger(pNode, "gamma", g_stSettings.m_defaultVideoSettings.m_Gamma);
1675   SetFloat(pNode, "audiodelay", g_stSettings.m_defaultVideoSettings.m_AudioDelay);
1676   SetFloat(pNode, "subtitledelay", g_stSettings.m_defaultVideoSettings.m_SubtitleDelay);
1677
1678
1679   // audio settings
1680   TiXmlElement volumeNode("audio");
1681   pNode = pRoot->InsertEndChild(volumeNode);
1682   if (!pNode) return false;
1683   SetInteger(pNode, "volumelevel", g_stSettings.m_nVolumeLevel);
1684   SetInteger(pNode, "dynamicrangecompression", g_stSettings.m_dynamicRangeCompressionLevel);
1685   for (int i = 0; i < 4; i++)
1686   {
1687     CStdString setting;
1688     setting.Format("karaoke%i", i);
1689     SetFloat(pNode, setting + "energy", g_stSettings.m_karaokeVoiceMask[i].energy);
1690     SetFloat(pNode, setting + "pitch", g_stSettings.m_karaokeVoiceMask[i].pitch);
1691     SetFloat(pNode, setting + "whisper", g_stSettings.m_karaokeVoiceMask[i].whisper);
1692     SetFloat(pNode, setting + "robotic", g_stSettings.m_karaokeVoiceMask[i].robotic);
1693   }
1694
1695   SaveCalibration(pRoot);
1696
1697   if (localSettings) // local settings to save
1698     localSettings->SaveXML(pRoot);
1699   else // save the global settings
1700     g_guiSettings.SaveXML(pRoot);
1701
1702   SaveSkinSettings(pRoot);
1703
1704   // For mastercode
1705   SaveProfiles( PROFILES_FILE );
1706
1707   // save the file
1708   return xmlDoc.SaveFile(_P(strSettingsFile));
1709 }
1710
1711 bool CSettings::LoadProfile(int index)
1712 {
1713   int iOldIndex = m_iLastLoadedProfileIndex;
1714   m_iLastLoadedProfileIndex = index;
1715   bool bSourcesXML=true;
1716   CStdString strOldSkin = g_guiSettings.GetString("lookandfeel.skin");
1717   CStdString strOldFont = g_guiSettings.GetString("lookandfeel.font");
1718   CStdString strOldTheme = g_guiSettings.GetString("lookandfeel.skintheme");
1719   CStdString strOldColors = g_guiSettings.GetString("lookandfeel.skincolors");
1720   //int iOldRes = g_guiSettings.GetInt("videoscreen.resolution");
1721   if (Load(bSourcesXML,bSourcesXML))
1722   {
1723     g_settings.CreateProfileFolders();
1724     CreateDirectory(_P("P:\\visualisations"),NULL);
1725
1726     // initialize our charset converter
1727     g_charsetConverter.reset();
1728
1729     // Load the langinfo to have user charset <-> utf-8 conversion
1730     CStdString strLanguage = g_guiSettings.GetString("locale.language");
1731     strLanguage[0] = toupper(strLanguage[0]);
1732
1733     CStdString strLangInfoPath;
1734     strLangInfoPath.Format("Q:\\language\\%s\\langinfo.xml", strLanguage.c_str());
1735     strLangInfoPath = _P(strLangInfoPath);
1736     CLog::Log(LOGINFO, "load language info file:%s", strLangInfoPath.c_str());
1737     g_langInfo.Load(strLangInfoPath);
1738
1739 #ifdef _XBOX
1740     CStdString strKeyboardLayoutConfigurationPath;
1741     strKeyboardLayoutConfigurationPath.Format("Q:\\language\\%s\\keyboardmap.xml", strLanguage.c_str());
1742     strKeyboardLayoutConfigurationPath = _P(strKeyboardLayoutConfigurationPath);
1743     CLog::Log(LOGINFO, "load keyboard layout configuration info file: %s", strKeyboardLayoutConfigurationPath.c_str());
1744     g_keyboardLayoutConfiguration.Load(strKeyboardLayoutConfigurationPath);
1745 #endif
1746
1747     CStdString strLanguagePath;
1748     strLanguagePath.Format("Q:\\language\\%s\\strings.xml", strLanguage.c_str());
1749
1750     g_buttonTranslator.Load();
1751     g_localizeStrings.Load(_P(strLanguagePath));
1752
1753     g_infoManager.ResetCache();
1754
1755     // always reload the skin - we need it for the new language strings
1756     g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1757
1758     if (m_iLastLoadedProfileIndex != 0)
1759     {
1760       TiXmlDocument doc;
1761       if (doc.LoadFile(GetUserDataFolder()+"\\guisettings.xml"))
1762         g_guiSettings.LoadMasterLock(doc.RootElement());
1763     }
1764
1765     // to set labels - shares are reloaded
1766     CDetectDVDMedia::UpdateState();
1767     // init windows
1768     CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_WINDOW_RESET);
1769     m_gWindowManager.SendMessage(msg);
1770
1771     CUtil::DeleteMusicDatabaseDirectoryCache();
1772     CUtil::DeleteVideoDatabaseDirectoryCache();
1773
1774     return true;
1775   }
1776
1777   m_iLastLoadedProfileIndex = iOldIndex;
1778
1779   return false;
1780 }
1781
1782 bool CSettings::DeleteProfile(int index)
1783 {
1784   if (index < 0 && index >= (int)g_settings.m_vecProfiles.size())
1785     return false;
1786
1787   CGUIDialogYesNo* dlgYesNo = (CGUIDialogYesNo*)m_gWindowManager.GetWindow(WINDOW_DIALOG_YES_NO);
1788   if (dlgYesNo)
1789   {
1790     CStdString message;
1791     CStdString str = g_localizeStrings.Get(13201);
1792     message.Format(str.c_str(), g_settings.m_vecProfiles.at(index).getName());
1793     dlgYesNo->SetHeading(13200);
1794     dlgYesNo->SetLine(0, message);
1795     dlgYesNo->SetLine(1, "");
1796     dlgYesNo->SetLine(2, "");
1797     dlgYesNo->DoModal();
1798
1799     if (dlgYesNo->IsConfirmed())
1800     {
1801       //delete profile
1802       CStdString strDirectory = g_settings.m_vecProfiles[index].getDirectory();
1803       m_vecProfiles.erase(g_settings.m_vecProfiles.begin()+index);
1804       if (index == g_settings.m_iLastLoadedProfileIndex)
1805       {
1806         g_settings.LoadProfile(0);
1807         g_settings.Save();
1808       }
1809
1810       CFileItem item(g_settings.GetUserDataFolder()+"\\"+strDirectory);
1811       item.m_strPath = g_settings.GetUserDataFolder()+"\\"+strDirectory+"\\";
1812       item.m_bIsFolder = true;
1813       item.Select(true);
1814       CGUIWindowFileManager::DeleteItem(&item);
1815     }
1816     else
1817       return false;
1818   }
1819
1820   SaveProfiles( PROFILES_FILE );
1821
1822   return true;
1823 }
1824
1825 bool CSettings::SaveSettingsToProfile(int index)
1826 {
1827   /*CProfile& profile = m_vecProfiles.at(index);
1828   return SaveSettings(profile.getFileName(), false);*/
1829   return true;
1830 }
1831
1832
1833 bool CSettings::LoadProfiles(const CStdString& strSettingsFile)
1834 {
1835   TiXmlDocument profilesDoc;
1836   if (!CFile::Exists(strSettingsFile))
1837   { // set defaults, or assume no rss feeds??
1838     return false;
1839   }
1840   if (!profilesDoc.LoadFile(strSettingsFile.c_str()))
1841   {
1842     CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", strSettingsFile.c_str(), profilesDoc.ErrorRow(), profilesDoc.ErrorDesc());
1843     return false;
1844   }
1845
1846   TiXmlElement *pRootElement = profilesDoc.RootElement();
1847   if (!pRootElement || strcmpi(pRootElement->Value(),"profiles") != 0)
1848   {
1849     CLog::Log(LOGERROR, "Error loading %s, no <profiles> node", strSettingsFile.c_str());
1850     return false;
1851   }
1852   GetInteger(pRootElement,"lastloaded",m_iLastLoadedProfileIndex,0,0,1000);
1853   if (m_iLastLoadedProfileIndex < 0)
1854     m_iLastLoadedProfileIndex = 0;
1855
1856   XMLUtils::GetBoolean(pRootElement,"useloginscreen",bUseLoginScreen);
1857
1858   TiXmlElement* pProfile = pRootElement->FirstChildElement("profile");
1859   CProfile profile;
1860
1861   while (pProfile)
1862   {
1863     profile.setName("Master user");
1864     if (CDirectory::Exists(_P("u:\\userdata")))
1865       profile.setDirectory("u:\\userdata");
1866     else
1867       profile.setDirectory("q:\\userdata");
1868
1869     CStdString strName;
1870     XMLUtils::GetString(pProfile,"name",strName);
1871     profile.setName(strName);
1872
1873     CStdString strDirectory;
1874     XMLUtils::GetString(pProfile,"directory",strDirectory);
1875   strDirectory.Replace("U:\\userdata",_P("U:\\userdata"));
1876 #ifdef _LINUX
1877     strDirectory.Replace("\\","/");
1878 #endif
1879     profile.setDirectory(strDirectory);
1880
1881     CStdString strThumb;
1882     XMLUtils::GetString(pProfile,"thumbnail",strThumb);
1883     profile.setThumb(strThumb);
1884
1885     bool bHas=true;
1886     XMLUtils::GetBoolean(pProfile, "hasdatabases", bHas);
1887     profile.setDatabases(bHas);
1888
1889     bHas = true;
1890     XMLUtils::GetBoolean(pProfile, "canwritedatabases", bHas);
1891     profile.setWriteDatabases(bHas);
1892
1893     bHas = true;
1894     XMLUtils::GetBoolean(pProfile, "hassources", bHas);
1895     profile.setSources(bHas);
1896
1897     bHas = true;
1898     XMLUtils::GetBoolean(pProfile, "canwritesources", bHas);
1899     profile.setWriteSources(bHas);
1900
1901     bHas = false;
1902     XMLUtils::GetBoolean(pProfile, "locksettings", bHas);
1903     profile.setSettingsLocked(bHas);
1904
1905     bHas = false;
1906     XMLUtils::GetBoolean(pProfile, "lockfiles", bHas);
1907     profile.setFilesLocked(bHas);
1908
1909     bHas = false;
1910     XMLUtils::GetBoolean(pProfile, "lockmusic", bHas);
1911     profile.setMusicLocked(bHas);
1912
1913     bHas = false;
1914     XMLUtils::GetBoolean(pProfile, "lockvideo", bHas);
1915     profile.setVideoLocked(bHas);
1916
1917     bHas = false;
1918     XMLUtils::GetBoolean(pProfile, "lockpictures", bHas);
1919     profile.setPicturesLocked(bHas);
1920
1921     bHas = false;
1922     XMLUtils::GetBoolean(pProfile, "lockprograms", bHas);
1923     profile.setProgramsLocked(bHas);
1924
1925     LockType iLockMode=LOCK_MODE_EVERYONE;
1926     XMLUtils::GetInt(pProfile,"lockmode",(int&)iLockMode);
1927     if (iLockMode > LOCK_MODE_QWERTY || iLockMode < LOCK_MODE_EVERYONE)
1928       iLockMode = LOCK_MODE_EVERYONE;
1929     profile.setLockMode(iLockMode);
1930
1931     CStdString strLockCode;
1932     XMLUtils::GetString(pProfile,"lockcode",strLockCode);
1933     profile.setLockCode(strLockCode);
1934
1935     CStdString strDate;
1936     XMLUtils::GetString(pProfile,"lastdate",strDate);
1937     profile.setDate(strDate);
1938
1939     m_vecProfiles.push_back(profile);
1940     pProfile = pProfile->NextSiblingElement("profile");
1941   }
1942
1943   if (m_iLastLoadedProfileIndex >= (int)m_vecProfiles.size() || m_iLastLoadedProfileIndex < 0)
1944     m_iLastLoadedProfileIndex = 0;
1945
1946   return true;
1947 }
1948
1949 bool CSettings::SaveProfiles(const CStdString& strSettingsFile) const
1950 {
1951   TiXmlDocument xmlDoc;
1952   TiXmlElement xmlRootElement("profiles");
1953   TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);
1954   if (!pRoot) return false;
1955   SetInteger(pRoot,"lastloaded",m_iLastLoadedProfileIndex);
1956   SetBoolean(pRoot,"useloginscreen",bUseLoginScreen);
1957   for (unsigned int iProfile=0;iProfile<g_settings.m_vecProfiles.size();++iProfile)
1958   {
1959     TiXmlElement profileNode("profile");
1960     TiXmlNode *pNode = pRoot->InsertEndChild(profileNode);
1961     SetString(pNode,"name",g_settings.m_vecProfiles[iProfile].getName());
1962     CStdString strDir(g_settings.m_vecProfiles[iProfile].getDirectory());
1963     strDir.Replace(_P("U:\\userdata"),"U:\\userdata");
1964     strDir.Replace("/","\\");
1965     SetString(pNode,"directory",strDir);
1966     SetString(pNode,"thumbnail",g_settings.m_vecProfiles[iProfile].getThumb());
1967     SetString(pNode,"lastdate",g_settings.m_vecProfiles[iProfile].getDate());
1968
1969     if (g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE)
1970     {
1971       SetInteger(pNode,"lockmode",g_settings.m_vecProfiles[iProfile].getLockMode());
1972       SetString(pNode,"lockcode",g_settings.m_vecProfiles[iProfile].getLockCode());
1973       SetBoolean(pNode,"lockmusic",g_settings.m_vecProfiles[iProfile].musicLocked());
1974       SetBoolean(pNode,"lockvideo",g_settings.m_vecProfiles[iProfile].videoLocked());
1975       SetBoolean(pNode,"lockpictures",g_settings.m_vecProfiles[iProfile].picturesLocked());
1976       SetBoolean(pNode,"lockprograms",g_settings.m_vecProfiles[iProfile].programsLocked());
1977       SetBoolean(pNode,"locksettings",g_settings.m_vecProfiles[iProfile].settingsLocked());
1978       SetBoolean(pNode,"lockfiles",g_settings.m_vecProfiles[iProfile].filesLocked());
1979     }
1980
1981     if (iProfile > 0)
1982     {
1983       SetBoolean(pNode,"hasdatabases",g_settings.m_vecProfiles[iProfile].hasDatabases());
1984       SetBoolean(pNode,"canwritedatabases",g_settings.m_vecProfiles[iProfile].canWriteDatabases());
1985       SetBoolean(pNode,"hassources",g_settings.m_vecProfiles[iProfile].hasSources());
1986       SetBoolean(pNode,"canwritesources",g_settings.m_vecProfiles[iProfile].canWriteSources());
1987     }
1988   }
1989   // save the file
1990   return xmlDoc.SaveFile(_P(strSettingsFile));
1991 }
1992
1993 bool CSettings::LoadUPnPXml(const CStdString& strSettingsFile)
1994 {
1995   TiXmlDocument UPnPDoc;
1996
1997   if (!CFile::Exists(strSettingsFile))
1998   { // set defaults, or assume no rss feeds??
1999     return false;
2000   }
2001   if (!UPnPDoc.LoadFile(strSettingsFile.c_str()))
2002   {
2003     CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", strSettingsFile.c_str(), UPnPDoc.ErrorRow(), UPnPDoc.ErrorDesc());
2004     return false;
2005   }
2006
2007   TiXmlElement *pRootElement = UPnPDoc.RootElement();
2008   if (!pRootElement || strcmpi(pRootElement->Value(),"upnpserver") != 0)
2009   {
2010     CLog::Log(LOGERROR, "Error loading %s, no <upnpserver> node", strSettingsFile.c_str());
2011     return false;
2012   }
2013   // load settings
2014   XMLUtils::GetString(pRootElement, "UUID", g_settings.m_UPnPUUID);
2015   XMLUtils::GetString(pRootElement, "UUIDRenderer", g_settings.m_UPnPUUIDRenderer);
2016
2017   CStdString strDefault;
2018   GetSources(pRootElement,"music",g_settings.m_UPnPMusicSources,strDefault);
2019   GetSources(pRootElement,"video",g_settings.m_UPnPVideoSources,strDefault);
2020   GetSources(pRootElement,"pictures",g_settings.m_UPnPPictureSources,strDefault);
2021
2022   return true;
2023 }
2024
2025 bool CSettings::SaveUPnPXml(const CStdString& strSettingsFile) const
2026 {
2027   TiXmlDocument xmlDoc;
2028   TiXmlElement xmlRootElement("upnpserver");
2029   TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);
2030   if (!pRoot) return false;
2031
2032   // create a new Element for UUID
2033   XMLUtils::SetString(pRoot, "UUID", g_settings.m_UPnPUUID);
2034   XMLUtils::SetString(pRoot, "UUIDRenderer", g_settings.m_UPnPUUIDRenderer);
2035
2036   VECSOURCES* pShares[3];
2037   pShares[0] = &g_settings.m_UPnPMusicSources;
2038   pShares[1] = &g_settings.m_UPnPVideoSources;
2039   pShares[2] = &g_settings.m_UPnPPictureSources;
2040   for (int k=0;k<3;++k)
2041   {
2042     if ((*pShares)[k].size()==0)
2043       continue;
2044
2045     TiXmlElement xmlType("");
2046     if (k==0)
2047       xmlType = TiXmlElement("music");
2048     if (k==1)
2049       xmlType = TiXmlElement("video");
2050     if (k==2)
2051       xmlType = TiXmlElement("pictures");
2052
2053     TiXmlNode* pNode = pRoot->InsertEndChild(xmlType);
2054
2055     for (unsigned int j=0;j<(*pShares)[k].size();++j)
2056     {
2057       // create a new Element
2058       TiXmlText xmlName((*pShares)[k][j].strName);
2059       TiXmlElement eName("name");
2060       eName.InsertEndChild(xmlName);
2061
2062       TiXmlElement source("source");
2063       source.InsertEndChild(eName);
2064
2065       for (unsigned int i = 0; i < (*pShares)[k][j].vecPaths.size(); i++)
2066       {
2067         TiXmlText xmlPath((*pShares)[k][j].vecPaths[i]);
2068         TiXmlElement ePath("path");
2069         ePath.InsertEndChild(xmlPath);
2070         source.InsertEndChild(ePath);
2071       }
2072
2073       if (pNode)
2074         pNode->ToElement()->InsertEndChild(source);
2075     }
2076   }
2077   // save the file
2078   return xmlDoc.SaveFile(_P(strSettingsFile));
2079 }
2080
2081 bool CSettings::UpdateShare(const CStdString &type, const CStdString oldName, const CMediaSource &share)
2082 {
2083   VECSOURCES *pShares = GetSourcesFromType(type);
2084
2085   if (!pShares) return false;
2086
2087   // update our current share list
2088   CMediaSource* pShare=NULL;
2089   for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++)
2090   {
2091     if ((*it).strName == oldName)
2092     {
2093       (*it).strName = share.strName;
2094       (*it).strPath = share.strPath;
2095       (*it).vecPaths = share.vecPaths;
2096       pShare = &(*it);
2097       break;
2098     }
2099   }
2100
2101   if (!pShare)
2102     return false;
2103
2104   // Update our XML file as well
2105   return SaveSources();
2106 }
2107
2108 // NOTE: This function does NOT save the sources.xml file - you need to call SaveSources() separately.
2109 bool CSettings::UpdateSource(const CStdString &strType, const CStdString strOldName, const CStdString &strUpdateElement, const CStdString &strUpdateText)
2110 {
2111   VECSOURCES *pShares = GetSourcesFromType(strType);
2112
2113   if (!pShares) return false;
2114
2115   // disallow virtual paths
2116   if (strUpdateElement.Equals("path") && CUtil::IsVirtualPath(strUpdateText))
2117     return false;
2118
2119   for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++)
2120   {
2121     if ((*it).strName == strOldName)
2122     {
2123       if ("name" == strUpdateElement)
2124         (*it).strName = strUpdateText;
2125       else if ("lockmode" == strUpdateElement)
2126         (*it).m_iLockMode = LockType(atoi(strUpdateText));
2127       else if ("lockcode" == strUpdateElement)
2128         (*it).m_strLockCode = strUpdateText;
2129       else if ("badpwdcount" == strUpdateElement)
2130         (*it).m_iBadPwdCount = atoi(strUpdateText);
2131       else if ("thumbnail" == strUpdateElement)
2132         (*it).m_strThumbnailImage = strUpdateText;
2133       else if ("path" == strUpdateElement)
2134       {
2135         (*it).vecPaths.clear();
2136         (*it).strPath = strUpdateText;
2137         (*it).vecPaths.push_back(strUpdateText);
2138       }
2139       else
2140         return false;
2141       return true;
2142     }
2143   }
2144   return false;
2145 }
2146
2147 bool CSettings::DeleteSource(const CStdString &strType, const CStdString strName, const CStdString strPath)
2148 {
2149   VECSOURCES *pShares = GetSourcesFromType(strType);
2150   if (!pShares) return false;
2151
2152   bool found(false);
2153
2154   for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++)
2155   {
2156     if ((*it).strName == strName && (*it).strPath == strPath)
2157     {
2158       CLog::Log(LOGDEBUG,"found share, removing!");
2159       pShares->erase(it);
2160       found = true;
2161       break;
2162     }
2163   }
2164
2165   if (strType.Find("upnp") > -1)
2166     return found;
2167
2168   return SaveSources();
2169 }
2170
2171 bool CSettings::AddShare(const CStdString &type, const CMediaSource &share)
2172 {
2173   VECSOURCES *pShares = GetSourcesFromType(type);
2174   if (!pShares) return false;
2175
2176   // translate dir and add to our current shares
2177   CStdString strPath1 = share.strPath;
2178   strPath1.ToUpper();
2179
2180   CMediaSource shareToAdd = share;
2181   if (strPath1.at(0) == '$')
2182   {
2183     shareToAdd.strPath = CUtil::TranslateSpecialSource(strPath1);
2184     if (!share.strPath.IsEmpty())
2185       CLog::Log(LOGDEBUG, "%s Translated (%s) to Path (%s)",__FUNCTION__ ,strPath1.c_str(),shareToAdd.strPath.c_str());
2186     else
2187     {
2188       CLog::Log(LOGDEBUG, "%s Skipping invalid special directory token: %s",__FUNCTION__,strPath1.c_str());
2189       return false;
2190     }
2191   }
2192   pShares->push_back(shareToAdd);
2193
2194   if (type.Find("upnp") < 0)
2195   {
2196     return SaveSources();
2197   }
2198   return true;
2199 }
2200
2201 bool CSettings::SaveSources()
2202 {
2203   // TODO: Should we be specifying utf8 here??
2204   TiXmlDocument doc;
2205   TiXmlElement xmlRootElement("sources");
2206   TiXmlNode *pRoot = doc.InsertEndChild(xmlRootElement);
2207   if (!pRoot) return false;
2208
2209   // ok, now run through and save each sources section
2210   SetSources(pRoot, "programs", g_settings.m_programSources, g_settings.m_defaultProgramSource);
2211   SetSources(pRoot, "video", g_settings.m_videoSources, g_settings.m_defaultVideoSource);
2212   SetSources(pRoot, "music", g_settings.m_musicSources, g_settings.m_defaultMusicSource);
2213   SetSources(pRoot, "pictures", g_settings.m_pictureSources, g_settings.m_defaultPictureSource);
2214   SetSources(pRoot, "files", g_settings.m_fileSources, g_settings.m_defaultFileSource);
2215
2216   return doc.SaveFile(g_settings.GetSourcesFile());
2217 }
2218
2219 bool CSettings::SetSources(TiXmlNode *root, const char *section, const VECSOURCES &shares, const char *defaultPath)
2220 {
2221   TiXmlElement sectionElement(section);
2222   TiXmlNode *sectionNode = root->InsertEndChild(sectionElement);
2223   if (sectionNode)
2224   {
2225     SetString(sectionNode, "default", defaultPath);
2226     for (unsigned int i = 0; i < shares.size(); i++)
2227     {
2228       const CMediaSource &share = shares[i];
2229       if (share.m_ignore)
2230         continue;
2231       TiXmlElement source("source");
2232
2233       SetString(&source, "name", share.strName);
2234
2235       for (unsigned int i = 0; i < share.vecPaths.size(); i++)
2236         SetString(&source, "path", share.vecPaths[i]);
2237
2238       if (share.m_iHasLock)
2239       {
2240         SetInteger(&source, "lockmode", share.m_iLockMode);
2241         SetString(&source, "lockcode", share.m_strLockCode);
2242         SetInteger(&source, "badpwdcount", share.m_iBadPwdCount);
2243       }
2244       if (!share.m_strThumbnailImage.IsEmpty())
2245         SetString(&source, "thumbnail", share.m_strThumbnailImage);
2246
2247       sectionNode->InsertEndChild(source);
2248     }
2249   }
2250   return true;
2251 }
2252
2253 void CSettings::LoadSkinSettings(const TiXmlElement* pRootElement)
2254 {
2255   int number = 0;
2256   const TiXmlElement *pElement = pRootElement->FirstChildElement("skinsettings");
2257   if (pElement)
2258   {
2259     m_skinStrings.clear();
2260     m_skinBools.clear();
2261     const TiXmlElement *pChild = pElement->FirstChildElement("setting");
2262     while (pChild)
2263     {
2264       CStdString settingName = pChild->Attribute("name");
2265       if (pChild->Attribute("type") && strcmpi(pChild->Attribute("type"),"string") == 0)
2266       { // string setting
2267         CSkinString string;
2268         string.name = settingName;
2269         string.value = pChild->FirstChild() ? pChild->FirstChild()->Value() : "";
2270         m_skinStrings.insert(pair<int, CSkinString>(number++, string));
2271       }
2272       else
2273       { // bool setting
2274         CSkinBool setting;
2275         setting.name = settingName;
2276         setting.value = pChild->FirstChild() ? strcmpi(pChild->FirstChild()->Value(), "true") == 0 : false;
2277         m_skinBools.insert(pair<int, CSkinBool>(number++, setting));
2278       }
2279       pChild = pChild->NextSiblingElement("setting");
2280     }
2281   }
2282 }
2283
2284 void CSettings::SaveSkinSettings(TiXmlNode *pRootElement) const
2285 {
2286   // add the <skinsettings> tag
2287   TiXmlElement xmlSettingsElement("skinsettings");
2288   TiXmlNode *pSettingsNode = pRootElement->InsertEndChild(xmlSettingsElement);
2289   if (!pSettingsNode) return;
2290   for (std::map<int, CSkinBool>::const_iterator it = m_skinBools.begin(); it != m_skinBools.end(); ++it)
2291   {
2292     // Add a <setting type="bool" name="name">true/false</setting>
2293     TiXmlElement xmlSetting("setting");
2294     xmlSetting.SetAttribute("type", "bool");
2295     xmlSetting.SetAttribute("name", (*it).second.name.c_str());
2296     TiXmlText xmlBool((*it).second.value ? "true" : "false");
2297     xmlSetting.InsertEndChild(xmlBool);
2298     pSettingsNode->InsertEndChild(xmlSetting);
2299   }
2300   for (std::map<int, CSkinString>::const_iterator it = m_skinStrings.begin(); it != m_skinStrings.end(); ++it)
2301   {
2302     // Add a <setting type="string" name="name">string</setting>
2303     TiXmlElement xmlSetting("setting");
2304     xmlSetting.SetAttribute("type", "string");
2305     xmlSetting.SetAttribute("name", (*it).second.name.c_str());
2306     TiXmlText xmlLabel((*it).second.value);
2307     xmlSetting.InsertEndChild(xmlLabel);
2308     pSettingsNode->InsertEndChild(xmlSetting);
2309   }
2310 }
2311
2312 void CSettings::Clear()
2313 {
2314   m_programSources.clear();
2315   m_pictureSources.clear();
2316   m_fileSources.clear();
2317   m_musicSources.clear();
2318   m_videoSources.clear();
2319 //  m_vecIcons.clear();
2320   m_vecProfiles.clear();
2321   m_szMyVideoStackTokensArray.clear();
2322   m_szMyVideoCleanTokensArray.clear();
2323   g_advancedSettings.m_videoStackRegExps.clear();
2324   g_advancedSettings.m_videoExcludeRegExps.clear();
2325   m_mapRssUrls.clear();
2326   m_skinBools.clear();
2327   m_skinStrings.clear();
2328 }
2329
2330 int CSettings::TranslateSkinString(const CStdString &setting)
2331 {
2332   CStdString settingName;
2333   settingName.Format("%s.%s", g_guiSettings.GetString("lookandfeel.skin").c_str(), setting);
2334   // run through and see if we have this setting
2335   for (std::map<int, CSkinString>::const_iterator it = m_skinStrings.begin(); it != m_skinStrings.end(); it++)
2336   {
2337     if (settingName.Equals((*it).second.name))
2338       return (*it).first;
2339   }
2340   // didn't find it - insert it
2341   CSkinString skinString;
2342   skinString.name = settingName;
2343   m_skinStrings.insert(pair<int, CSkinString>(m_skinStrings.size() + m_skinBools.size(), skinString));
2344   return m_skinStrings.size() + m_skinBools.size() - 1;
2345 }
2346
2347 const CStdString &CSettings::GetSkinString(int setting) const
2348 {
2349   std::map<int, CSkinString>::const_iterator it = m_skinStrings.find(setting);
2350   if (it != m_skinStrings.end())
2351   {
2352     return (*it).second.value;
2353   }
2354   return StringUtils::EmptyString;
2355 }
2356
2357 void CSettings::SetSkinString(int setting, const CStdString &label)
2358 {
2359   std::map<int, CSkinString>::iterator it = m_skinStrings.find(setting);
2360   if (it != m_skinStrings.end())
2361   {
2362     (*it).second.value = label;
2363     return;
2364   }
2365   assert(false);
2366   CLog::Log(LOGFATAL, "%s : Unknown setting requested", __FUNCTION__);
2367 }
2368
2369 void CSettings::ResetSkinSetting(const CStdString &setting)
2370 {
2371   CStdString settingName;
2372   settingName.Format("%s.%s", g_guiSettings.GetString("lookandfeel.skin").c_str(), setting);
2373   // run through and see if we have this setting as a string
2374   for (std::map<int, CSkinString>::iterator it = m_skinStrings.begin(); it != m_skinStrings.end(); it++)
2375   {
2376     if (settingName.Equals((*it).second.name))
2377     {
2378       (*it).second.value = "";
2379       return;
2380     }
2381   }
2382   // and now check for the skin bool
2383   for (std::map<int, CSkinBool>::iterator it = m_skinBools.begin(); it != m_skinBools.end(); it++)
2384   {
2385     if (settingName.Equals((*it).second.name))
2386     {
2387       (*it).second.value = false;
2388       return;
2389     }
2390   }
2391 }
2392
2393 int CSettings::TranslateSkinBool(const CStdString &setting)
2394 {
2395   CStdString settingName;
2396   settingName.Format("%s.%s", g_guiSettings.GetString("lookandfeel.skin").c_str(), setting);
2397   // run through and see if we have this setting
2398   for (std::map<int, CSkinBool>::const_iterator it = m_skinBools.begin(); it != m_skinBools.end(); it++)
2399   {
2400     if (settingName.Equals((*it).second.name))
2401       return (*it).first;
2402   }
2403   // didn't find it - insert it
2404   CSkinBool skinBool;
2405   skinBool.name = settingName;
2406   skinBool.value = false;
2407   m_skinBools.insert(pair<int, CSkinBool>(m_skinBools.size() + m_skinStrings.size(), skinBool));
2408   return m_skinBools.size() + m_skinStrings.size() - 1;
2409 }
2410
2411 bool CSettings::GetSkinBool(int setting) const
2412 {
2413   std::map<int, CSkinBool>::const_iterator it = m_skinBools.find(setting);
2414   if (it != m_skinBools.end())
2415   {
2416     return (*it).second.value;
2417   }
2418   // default is to return false
2419   return false;
2420 }
2421
2422 void CSettings::SetSkinBool(int setting, bool set)
2423 {
2424   std::map<int, CSkinBool>::iterator it = m_skinBools.find(setting);
2425   if (it != m_skinBools.end())
2426   {
2427     (*it).second.value = set;
2428     return;
2429   }
2430   assert(false);
2431   CLog::Log(LOGFATAL,"%s : Unknown setting requested", __FUNCTION__);
2432 }
2433
2434 void CSettings::ResetSkinSettings()
2435 {
2436   CStdString currentSkin = g_guiSettings.GetString("lookandfeel.skin") + ".";
2437   // clear all the settings and strings from this skin.
2438   std::map<int, CSkinBool>::iterator it = m_skinBools.begin();
2439   while (it != m_skinBools.end())
2440   {
2441     CStdString skinName = (*it).second.name;
2442     if (skinName.Left(currentSkin.size()) == currentSkin)
2443       (*it).second.value = false;
2444
2445     it++;
2446   }
2447   std::map<int, CSkinString>::iterator it2 = m_skinStrings.begin();
2448   while (it2 != m_skinStrings.end())
2449   {
2450     CStdString skinName = (*it2).second.name;
2451     if (skinName.Left(currentSkin.size()) == currentSkin)
2452       (*it2).second.value = "";
2453
2454     it2++;
2455   }
2456   g_infoManager.ResetCache();
2457 }
2458
2459 void CSettings::LoadUserFolderLayout()
2460 {
2461   // check them all
2462   CStdString strDir = g_guiSettings.GetString("system.playlistspath");
2463   if (strDir == "set default")
2464   {
2465     strDir = "P:\\playlists\\";
2466     g_guiSettings.SetString("system.playlistspath",strDir.c_str());
2467   }
2468   CDirectory::Create(strDir);
2469   CStdString strDir2;
2470   CUtil::AddFileToFolder(strDir,"music",strDir2);
2471   CDirectory::Create(strDir2);
2472   CUtil::AddFileToFolder(strDir,"video",strDir2);
2473   CDirectory::Create(strDir2);
2474   CUtil::AddFileToFolder(strDir,"mixed",strDir2);
2475   CDirectory::Create(strDir2);
2476 }
2477
2478 CStdString CSettings::GetProfileUserDataFolder() const
2479 {
2480   CStdString folder;
2481   if (m_iLastLoadedProfileIndex == 0)
2482     return GetUserDataFolder();
2483
2484   CUtil::AddFileToFolder(GetUserDataFolder(),m_vecProfiles[m_iLastLoadedProfileIndex].getDirectory(),folder);
2485
2486   return _P(folder);
2487 }
2488
2489 CStdString CSettings::GetUserDataItem(const CStdString& strFile) const
2490 {
2491   CStdString folder;
2492   folder = "P:\\"+strFile;
2493   if (!CFile::Exists(folder))
2494     folder = "T:\\"+strFile;
2495   return _P(folder);
2496 }
2497
2498 CStdString CSettings::GetUserDataFolder() const
2499 {
2500   return _P(m_vecProfiles[0].getDirectory());
2501 }
2502
2503 CStdString CSettings::GetDatabaseFolder() const
2504 {
2505   CStdString folder;
2506   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2507     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), "Database", folder);
2508   else
2509     CUtil::AddFileToFolder(GetUserDataFolder(), "Database", folder);
2510
2511   return folder;
2512 }
2513
2514 CStdString CSettings::GetCDDBFolder() const
2515 {
2516   CStdString folder;
2517   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2518     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Database\\CDDB"), folder);
2519   else
2520     CUtil::AddFileToFolder(GetUserDataFolder(), _P("Database\\CDDB"), folder);
2521
2522   return folder;
2523 }
2524
2525 CStdString CSettings::GetThumbnailsFolder() const
2526 {
2527   CStdString folder;
2528   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2529     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), "Thumbnails", folder);
2530   else
2531     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), "Thumbnails", folder);
2532
2533   return folder;
2534 }
2535
2536 CStdString CSettings::GetMusicThumbFolder() const
2537 {
2538   CStdString folder;
2539   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2540     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Music"), folder);
2541   else
2542     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Music"), folder);
2543
2544   return folder;
2545 }
2546
2547 CStdString CSettings::GetLastFMThumbFolder() const
2548 {
2549   CStdString folder;
2550   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2551     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Music\\LastFM"), folder);
2552   else
2553     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Music\\LastFM"), folder);
2554
2555   return folder;
2556 }
2557
2558 CStdString CSettings::GetMusicArtistThumbFolder() const
2559 {
2560   CStdString folder;
2561   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2562     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Music\\Artists"), folder);
2563   else
2564     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Music\\Artists"), folder);
2565
2566   return folder;
2567 }
2568
2569 CStdString CSettings::GetVideoThumbFolder() const
2570 {
2571   CStdString folder;
2572   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2573     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Video"), folder);
2574   else
2575     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Video"), folder);
2576
2577   return folder;
2578 }
2579
2580 CStdString CSettings::GetVideoFanartFolder() const
2581 {
2582   CStdString folder;
2583   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2584     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), "Thumbnails\\Video\\Fanart", folder);
2585   else
2586     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), "Thumbnails\\Video\\Fanart", folder);
2587
2588   return folder;
2589 }
2590
2591 CStdString CSettings::GetBookmarksThumbFolder() const
2592 {
2593   CStdString folder;
2594   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2595     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Video\\Bookmarks"), folder);
2596   else
2597     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Video\\Bookmarks"), folder);
2598
2599   return folder;
2600 }
2601
2602 CStdString CSettings::GetPicturesThumbFolder() const
2603 {
2604   CStdString folder;
2605   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2606     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Pictures"), folder);
2607   else
2608     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Pictures"), folder);
2609
2610   return folder;
2611 }
2612
2613 CStdString CSettings::GetProgramsThumbFolder() const
2614 {
2615   CStdString folder;
2616   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2617     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\Programs"), folder);
2618   else
2619     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Programs"), folder);
2620
2621   return folder;
2622 }
2623
2624 CStdString CSettings::GetGameSaveThumbFolder() const
2625 {
2626   CStdString folder;
2627   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasDatabases())
2628     CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(), _P("Thumbnails\\GameSaves"), folder);
2629   else
2630     CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\GameSaves"), folder);
2631
2632   return folder;
2633 }
2634
2635 CStdString CSettings::GetProfilesThumbFolder() const
2636 {
2637   CStdString folder;
2638   CUtil::AddFileToFolder(g_settings.GetUserDataFolder(), _P("Thumbnails\\Profiles"), folder);
2639
2640   return folder;
2641 }
2642
2643 CStdString CSettings::GetSourcesFile() const
2644 {
2645   CStdString folder;
2646   if (m_vecProfiles[m_iLastLoadedProfileIndex].hasSources())
2647     CUtil::AddFileToFolder(GetProfileUserDataFolder(),"sources.xml",folder);
2648   else
2649     CUtil::AddFileToFolder(GetUserDataFolder(),"sources.xml",folder);
2650
2651   return folder;
2652 }
2653
2654 CStdString CSettings::GetSkinFolder() const
2655 {
2656   CStdString folder;
2657
2658   // Get the Current Skin Path
2659   return GetSkinFolder(g_guiSettings.GetString("lookandfeel.skin"));
2660 }
2661
2662 CStdString CSettings::GetScriptsFolder() const
2663 {
2664   CStdString folder = _P("U:\\scripts");
2665
2666   if ( CDirectory::Exists(folder) )
2667     return folder;
2668
2669   folder = "Q:\\scripts";
2670   return _P(folder);
2671 }
2672
2673 CStdString CSettings::GetSkinFolder(const CStdString &skinName) const
2674 {
2675   CStdString folder;
2676
2677   // Get the Current Skin Path
2678   CUtil::AddFileToFolder("U:\\skin\\", skinName, folder);
2679   if ( ! CDirectory::Exists(_P(folder)) )
2680     CUtil::AddFileToFolder("Q:\\skin\\", skinName, folder);
2681
2682   return _P(folder);
2683 }
2684
2685 void CSettings::LoadRSSFeeds()
2686 {
2687   CStdString rssXML;
2688   //rssXML.Format("%s\\RSSFeeds.xml", GetUserDataFolder().c_str());
2689   rssXML = GetUserDataItem("RssFeeds.xml");
2690   TiXmlDocument rssDoc;
2691   if (!CFile::Exists(rssXML))
2692   { // set defaults, or assume no rss feeds??
2693     return;
2694   }
2695   if (!rssDoc.LoadFile(rssXML.c_str()))
2696   {
2697     CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", rssXML.c_str(), rssDoc.ErrorRow(), rssDoc.ErrorDesc());
2698     return;
2699   }
2700
2701   TiXmlElement *pRootElement = rssDoc.RootElement();
2702   if (!pRootElement || strcmpi(pRootElement->Value(),"rssfeeds") != 0)
2703   {
2704     CLog::Log(LOGERROR, "Error loading %s, no <rssfeeds> node", rssXML.c_str());
2705     return;
2706   }
2707
2708   g_settings.m_mapRssUrls.clear();
2709   TiXmlElement* pSet = pRootElement->FirstChildElement("set");
2710   while (pSet)
2711   {
2712     int iId;
2713     if (pSet->QueryIntAttribute("id", &iId) == TIXML_SUCCESS)
2714     {
2715       std::vector<string> vecSet;
2716       std::vector<int> vecIntervals;
2717       TiXmlElement* pFeed = pSet->FirstChildElement("feed");
2718       while (pFeed)
2719       {
2720         int iInterval;
2721         if ( pFeed->QueryIntAttribute("updateinterval",&iInterval) != TIXML_SUCCESS)
2722         {
2723           iInterval=30; // default to 30 min
2724           CLog::Log(LOGDEBUG,"no interval set, default to 30!");
2725         }
2726         if (pFeed->FirstChild())
2727         {
2728           // TODO: UTF-8: Do these URLs need to be converted to UTF-8?
2729           //              What about the xml encoding?
2730           CStdString strUrl = pFeed->FirstChild()->Value();
2731           vecSet.push_back(strUrl);
2732           vecIntervals.push_back(iInterval);
2733         }
2734         pFeed = pFeed->NextSiblingElement("feed");
2735       }
2736       g_settings.m_mapRssUrls.insert(std::make_pair<int,std::pair<std::vector<int>,std::vector<string> > >(iId,std::make_pair<std::vector<int>,std::vector<string> >(vecIntervals,vecSet)));
2737     }
2738     else
2739       CLog::Log(LOGERROR,"found rss url set with no id in RssFeeds.xml, ignored");
2740
2741     pSet = pSet->NextSiblingElement("set");
2742   }
2743 }
2744
2745 CStdString CSettings::GetSettingsFile() const
2746 {
2747   CStdString settings;
2748   if (g_settings.m_iLastLoadedProfileIndex == 0)
2749     settings = "T:\\guisettings.xml";
2750   else
2751     settings = "P:\\guisettings.xml";
2752   return _P(settings);
2753 }
2754
2755 void CSettings::CreateProfileFolders()
2756 {
2757   CreateDirectory(GetDatabaseFolder(), NULL);
2758   CreateDirectory(GetCDDBFolder().c_str(), NULL);
2759
2760   // Thumbnails/
2761   CreateDirectory(GetThumbnailsFolder().c_str(), NULL);
2762   CreateDirectory(GetMusicThumbFolder().c_str(), NULL);
2763   CreateDirectory(GetMusicArtistThumbFolder().c_str(), NULL);
2764   CreateDirectory(GetLastFMThumbFolder().c_str(), NULL);
2765   CreateDirectory(GetVideoThumbFolder().c_str(), NULL);
2766   CreateDirectory(GetVideoFanartFolder().c_str(), NULL);
2767   CreateDirectory(GetBookmarksThumbFolder().c_str(), NULL);
2768   CreateDirectory(GetProgramsThumbFolder().c_str(), NULL);
2769   CreateDirectory(GetPicturesThumbFolder().c_str(), NULL);
2770   CLog::Log(LOGINFO, "  thumbnails folder:%s", GetThumbnailsFolder().c_str());
2771   for (unsigned int hex=0; hex < 16; hex++)
2772   {
2773     CStdString strHex;
2774     strHex.Format("%x",hex);
2775     CStdString strThumbLoc;
2776     CUtil::AddFileToFolder(GetPicturesThumbFolder(), strHex, strThumbLoc);
2777     CreateDirectory(strThumbLoc.c_str(),NULL);
2778     CUtil::AddFileToFolder(GetMusicThumbFolder(), strHex, strThumbLoc);
2779     CreateDirectory(strThumbLoc.c_str(),NULL);
2780     CUtil::AddFileToFolder(GetVideoThumbFolder(), strHex, strThumbLoc);
2781     CreateDirectory(strThumbLoc.c_str(),NULL);
2782   }
2783 }