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