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