Merge pull request #2688 from ace20022/cleanup_settings
[vuplus_xbmc] / xbmc / settings / AdvancedSettings.cpp
1 /*
2  *      Copyright (C) 2005-2013 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, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <limits.h>
22
23 #include "system.h"
24 #include "AdvancedSettings.h"
25 #include "Application.h"
26 #include "network/DNSNameCache.h"
27 #include "filesystem/File.h"
28 #include "utils/LangCodeExpander.h"
29 #include "LangInfo.h"
30 #include "profiles/ProfilesManager.h"
31 #include "settings/Setting.h"
32 #include "settings/Settings.h"
33 #include "utils/StringUtils.h"
34 #include "utils/SystemInfo.h"
35 #include "utils/URIUtils.h"
36 #include "utils/XMLUtils.h"
37 #include "utils/log.h"
38 #include "filesystem/SpecialProtocol.h"
39 #include "addons/IAddon.h"
40 #include "addons/AddonManager.h"
41 #include "addons/GUIDialogAddonSettings.h"
42
43 using namespace ADDON;
44 using namespace XFILE;
45 using namespace std;
46
47 CAdvancedSettings::CAdvancedSettings()
48 {
49   m_initialized = false;
50 }
51
52 void CAdvancedSettings::OnSettingsLoaded()
53 {
54   // load advanced settings
55   Load();
56
57   // default players?
58   CLog::Log(LOGNOTICE, "Default DVD Player: %s", m_videoDefaultDVDPlayer.c_str());
59   CLog::Log(LOGNOTICE, "Default Video Player: %s", m_videoDefaultPlayer.c_str());
60   CLog::Log(LOGNOTICE, "Default Audio Player: %s", m_audioDefaultPlayer.c_str());
61
62   // setup any logging...
63   if (CSettings::Get().GetBool("debug.showloginfo"))
64   {
65     m_logLevel = std::max(m_logLevelHint, LOG_LEVEL_DEBUG_FREEMEM);
66     CLog::Log(LOGNOTICE, "Enabled debug logging due to GUI setting (%d)", m_logLevel);
67   }
68   else
69   {
70     m_logLevel = std::min(m_logLevelHint, LOG_LEVEL_DEBUG/*LOG_LEVEL_NORMAL*/);
71     CLog::Log(LOGNOTICE, "Disabled debug logging due to GUI setting. Level %d.", m_logLevel);
72   }
73   CLog::SetLogLevel(m_logLevel);
74 }
75
76 void CAdvancedSettings::OnSettingsUnloaded()
77 {
78   m_initialized = false;
79 }
80
81 void CAdvancedSettings::OnSettingChanged(const CSetting *setting)
82 {
83   if (setting == NULL)
84     return;
85
86   const std::string &settingId = setting->GetId();
87   if (settingId == "debug.showloginfo")
88     SetDebugMode(((CSettingBool*)setting)->GetValue());
89 }
90
91 void CAdvancedSettings::OnSettingAction(const CSetting *setting)
92 {
93   if (setting == NULL)
94     return;
95
96   const std::string settingId = setting->GetId();
97   if (settingId == "debug.setextraloglevel")
98   {
99     AddonPtr addon;
100     CAddonMgr::Get().GetAddon("xbmc.debug", addon);
101     CGUIDialogAddonSettings::ShowAndGetInput(addon, true);
102     SetExtraLogsFromAddon(addon.get());
103   }
104 }
105
106 void CAdvancedSettings::Initialize()
107 {
108   if (m_initialized)
109     return;
110
111   m_audioHeadRoom = 0;
112   m_ac3Gain = 12.0f;
113   m_audioApplyDrc = true;
114   m_dvdplayerIgnoreDTSinWAV = false;
115   m_audioResample = 0;
116   m_allowTranscode44100 = false;
117   m_audioForceDirectSound = false;
118   m_audioAudiophile = false;
119   m_allChannelStereo = false;
120   m_streamSilence = false;
121   m_audioSinkBufferDurationMsec = 50;
122
123   //default hold time of 25 ms, this allows a 20 hertz sine to pass undistorted
124   m_limiterHold = 0.025f;
125   m_limiterRelease = 0.1f;
126
127   m_omxHWAudioDecode = false;
128   m_omxDecodeStartWithValidFrame = false;
129
130   m_karaokeSyncDelayCDG = 0.0f;
131   m_karaokeSyncDelayLRC = 0.0f;
132   m_karaokeChangeGenreForKaraokeSongs = false;
133   m_karaokeKeepDelay = true;
134   m_karaokeStartIndex = 1;
135   m_karaokeAlwaysEmptyOnCdgs = 1;
136   m_karaokeUseSongSpecificBackground = 0;
137
138   m_audioDefaultPlayer = "paplayer";
139   m_audioPlayCountMinimumPercent = 90.0f;
140   m_audioHost = "default";
141
142   m_videoSubsDelayRange = 10;
143   m_videoAudioDelayRange = 10;
144   m_videoSmallStepBackSeconds = 7;
145   m_videoSmallStepBackTries = 3;
146   m_videoSmallStepBackDelay = 300;
147   m_videoUseTimeSeeking = true;
148   m_videoTimeSeekForward = 30;
149   m_videoTimeSeekBackward = -30;
150   m_videoTimeSeekForwardBig = 600;
151   m_videoTimeSeekBackwardBig = -600;
152   m_videoPercentSeekForward = 2;
153   m_videoPercentSeekBackward = -2;
154   m_videoPercentSeekForwardBig = 10;
155   m_videoPercentSeekBackwardBig = -10;
156   m_videoBlackBarColour = 0;
157   m_videoPPFFmpegDeint = "linblenddeint";
158   m_videoPPFFmpegPostProc = "ha:128:7,va,dr";
159   m_videoDefaultPlayer = "dvdplayer";
160   m_videoDefaultDVDPlayer = "dvdplayer";
161   m_videoIgnoreSecondsAtStart = 3*60;
162   m_videoIgnorePercentAtEnd   = 8.0f;
163   m_videoPlayCountMinimumPercent = 90.0f;
164   m_videoVDPAUScaling = false;
165   m_videoNonLinStretchRatio = 0.5f;
166   m_videoEnableHighQualityHwScalers = false;
167   m_videoAutoScaleMaxFps = 30.0f;
168   m_videoAllowMpeg4VDPAU = false;
169   m_videoAllowMpeg4VAAPI = false;  
170   m_videoDisableBackgroundDeinterlace = false;
171   m_videoCaptureUseOcclusionQuery = -1; //-1 is auto detect
172   m_DXVACheckCompatibility = false;
173   m_DXVACheckCompatibilityPresent = false;
174   m_DXVAForceProcessorRenderer = true;
175   m_DXVANoDeintProcForProgressive = false;
176   m_videoFpsDetect = 1;
177   m_videoDefaultLatency = 0.0;
178   m_videoDisableHi10pMultithreading = false;
179
180   m_musicUseTimeSeeking = true;
181   m_musicTimeSeekForward = 10;
182   m_musicTimeSeekBackward = -10;
183   m_musicTimeSeekForwardBig = 60;
184   m_musicTimeSeekBackwardBig = -60;
185   m_musicPercentSeekForward = 1;
186   m_musicPercentSeekBackward = -1;
187   m_musicPercentSeekForwardBig = 10;
188   m_musicPercentSeekBackwardBig = -10;
189
190   m_slideshowPanAmount = 2.5f;
191   m_slideshowZoomAmount = 5.0f;
192   m_slideshowBlackBarCompensation = 20.0f;
193
194   m_songInfoDuration = 10;
195
196   m_cddbAddress = "freedb.freedb.org";
197
198   m_handleMounting = g_application.IsStandAlone();
199
200   m_fullScreenOnMovieStart = true;
201   m_cachePath = "special://temp/";
202
203   m_videoCleanDateTimeRegExp = "(.*[^ _\\,\\.\\(\\)\\[\\]\\-])[ _\\.\\(\\)\\[\\]\\-]+(19[0-9][0-9]|20[0-1][0-9])([ _\\,\\.\\(\\)\\[\\]\\-]|[^0-9]$)";
204
205   m_videoCleanStringRegExps.push_back("[ _\\,\\.\\(\\)\\[\\]\\-](ac3|dts|custom|dc|remastered|divx|divx5|dsr|dsrip|dutch|dvd|dvd5|dvd9|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|extended|ws|telesync|ts|telecine|tc|brrip|bdrip|480p|480i|576p|576i|720p|720i|1080p|1080i|3d|hrhd|hrhdtv|hddvd|bluray|x264|h264|xvid|xvidvd|xxx|www.www|cd[1-9]|\\[.*\\])([ _\\,\\.\\(\\)\\[\\]\\-]|$)");
206   m_videoCleanStringRegExps.push_back("(\\[.*\\])");
207
208   m_moviesExcludeFromScanRegExps.push_back("-trailer");
209   m_moviesExcludeFromScanRegExps.push_back("[!-._ \\\\/]sample[-._ \\\\/]");
210   m_tvshowExcludeFromScanRegExps.push_back("[!-._ \\\\/]sample[-._ \\\\/]");
211
212   m_folderStackRegExps.push_back("((cd|dvd|dis[ck])[0-9]+)$");
213
214   m_videoStackRegExps.push_back("(.*?)([ _.-]*(?:cd|dvd|p(?:(?:ar)?t)|dis[ck]|d)[ _.-]*[0-9]+)(.*?)(\\.[^.]+)$");
215   m_videoStackRegExps.push_back("(.*?)([ _.-]*(?:cd|dvd|p(?:(?:ar)?t)|dis[ck]|d)[ _.-]*[a-d])(.*?)(\\.[^.]+)$");
216   m_videoStackRegExps.push_back("(.*?)([ ._-]*[a-d])(.*?)(\\.[^.]+)$");
217   // This one is a bit too greedy to enable by default.  It will stack sequels
218   // in a flat dir structure, but is perfectly safe in a dir-per-vid one.
219   //m_videoStackRegExps.push_back("(.*?)([ ._-]*[0-9])(.*?)(\\.[^.]+)$");
220
221   // foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02
222   m_tvshowEnumRegExps.push_back(TVShowRegexp(false,"s([0-9]+)[ ._-]*e([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$"));
223   // foo.ep01, foo.EP_01
224   m_tvshowEnumRegExps.push_back(TVShowRegexp(false,"[\\._ -]()ep_?([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$"));
225   // foo.yyyy.mm.dd.* (byDate=true)
226   m_tvshowEnumRegExps.push_back(TVShowRegexp(true,"([0-9]{4})[\\.-]([0-9]{2})[\\.-]([0-9]{2})"));
227   // foo.mm.dd.yyyy.* (byDate=true)
228   m_tvshowEnumRegExps.push_back(TVShowRegexp(true,"([0-9]{2})[\\.-]([0-9]{2})[\\.-]([0-9]{4})"));
229   // foo.1x09* or just /1x09*
230   m_tvshowEnumRegExps.push_back(TVShowRegexp(false,"[\\\\/\\._ \\[\\(-]([0-9]+)x([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([^\\\\/]*)$"));
231   // foo.103*, 103 foo
232   m_tvshowEnumRegExps.push_back(TVShowRegexp(false,"[\\\\/\\._ -]([0-9]+)([0-9][0-9](?:(?:[a-i]|\\.[1-9])(?![0-9]))?)([\\._ -][^\\\\/]*)$"));
233   // Part I, Pt.VI
234   m_tvshowEnumRegExps.push_back(TVShowRegexp(false,"[\\/._ -]p(?:ar)?t[_. -]()([ivx]+)([._ -][^\\/]*)$"));
235
236   m_tvshowMultiPartEnumRegExp = "^[-_ex]+([0-9]+(?:(?:[a-i]|\\.[1-9])(?![0-9]))?)";
237
238   m_remoteDelay = 3;
239   m_controllerDeadzone = 0.2f;
240
241   m_playlistAsFolders = true;
242   m_detectAsUdf = false;
243
244   m_fanartRes = 1080;
245   m_imageRes = 720;
246   m_useDDSFanart = false;
247
248   m_sambaclienttimeout = 10;
249   m_sambadoscodepage = "";
250   m_sambastatfiles = true;
251
252   m_bHTTPDirectoryStatFilesize = false;
253
254   m_bFTPThumbs = false;
255
256   m_musicThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG|cover.jpg|Cover.jpg|cover.jpeg|thumb.jpg|Thumb.jpg|thumb.JPG|Thumb.JPG";
257   m_fanartImages = "fanart.jpg|fanart.png";
258
259   m_bMusicLibraryHideAllItems = false;
260   m_bMusicLibraryAllItemsOnBottom = false;
261   m_bMusicLibraryAlbumsSortByArtistThenYear = false;
262   m_iMusicLibraryRecentlyAddedItems = 25;
263   m_strMusicLibraryAlbumFormat = "";
264   m_strMusicLibraryAlbumFormatRight = "";
265   m_prioritiseAPEv2tags = false;
266   m_musicItemSeparator = " / ";
267   m_videoItemSeparator = " / ";
268
269   m_bVideoLibraryHideAllItems = false;
270   m_bVideoLibraryAllItemsOnBottom = false;
271   m_iVideoLibraryRecentlyAddedItems = 25;
272   m_bVideoLibraryHideEmptySeries = false;
273   m_bVideoLibraryCleanOnUpdate = false;
274   m_bVideoLibraryExportAutoThumbs = false;
275   m_bVideoLibraryImportWatchedState = false;
276   m_bVideoLibraryImportResumePoint = false;
277   m_bVideoScannerIgnoreErrors = false;
278   m_iVideoLibraryDateAdded = 1; // prefer mtime over ctime and current time
279
280   m_iTuxBoxStreamtsPort = 31339;
281   m_bTuxBoxAudioChannelSelection = false;
282   m_bTuxBoxSubMenuSelection = false;
283   m_bTuxBoxPictureIcon= true;
284   m_bTuxBoxSendAllAPids= false;
285   m_iTuxBoxEpgRequestTime = 10; //seconds
286   m_iTuxBoxDefaultSubMenu = 4;
287   m_iTuxBoxDefaultRootMenu = 0; //default TV Mode
288   m_iTuxBoxZapWaitTime = 0; // Time in sec. Default 0:OFF
289   m_bTuxBoxZapstream = true;
290   m_iTuxBoxZapstreamPort = 31344;
291
292   m_iMythMovieLength = 0; // 0 == Off
293
294   m_iEpgLingerTime = 60;           /* keep 1 hour by default */
295   m_iEpgUpdateCheckInterval = 300; /* check if tables need to be updated every 5 minutes */
296   m_iEpgCleanupInterval = 900;     /* remove old entries from the EPG every 15 minutes */
297   m_iEpgActiveTagCheckInterval = 60; /* check for updated active tags every minute */
298   m_iEpgRetryInterruptedUpdateInterval = 30; /* retry an interrupted epg update after 30 seconds */
299   m_iEpgUpdateEmptyTagsInterval = 60; /* override user selectable EPG update interval for empty EPG tags */
300   m_bEpgDisplayUpdatePopup = true; /* display a progress popup while updating EPG data from clients */
301   m_bEpgDisplayIncrementalUpdatePopup = false; /* also display a progress popup while doing incremental EPG updates */
302
303   m_bEdlMergeShortCommBreaks = false;      // Off by default
304   m_iEdlMaxCommBreakLength = 8 * 30 + 10;  // Just over 8 * 30 second commercial break.
305   m_iEdlMinCommBreakLength = 3 * 30;       // 3 * 30 second commercial breaks.
306   m_iEdlMaxCommBreakGap = 4 * 30;          // 4 * 30 second commercial breaks.
307   m_iEdlMaxStartGap = 5 * 60;              // 5 minutes.
308   m_iEdlCommBreakAutowait = 0;             // Off by default
309   m_iEdlCommBreakAutowind = 0;             // Off by default
310
311   m_curlconnecttimeout = 10;
312   m_curllowspeedtime = 20;
313   m_curlretries = 2;
314   m_curlDisableIPV6 = false;      //Certain hardware/OS combinations have trouble
315                                   //with ipv6.
316
317   m_fullScreen = m_startFullScreen = false;
318   m_showExitButton = true;
319   m_splashImage = true;
320
321   m_playlistRetries = 100;
322   m_playlistTimeout = 20; // 20 seconds timeout
323   m_GLRectangleHack = false;
324   m_iSkipLoopFilter = 0;
325   m_AllowD3D9Ex = true;
326   m_ForceD3D9Ex = false;
327   m_AllowDynamicTextures = true;
328   m_RestrictCapsMask = 0;
329   m_sleepBeforeFlip = 0;
330   m_bVirtualShares = true;
331
332 //caused lots of jerks
333 //#ifdef TARGET_WINDOWS
334 //  m_ForcedSwapTime = 2.0;
335 //#else
336   m_ForcedSwapTime = 0.0;
337 //#endif
338
339   m_cpuTempCmd = "";
340   m_gpuTempCmd = "";
341 #if defined(TARGET_DARWIN)
342   // default for osx is fullscreen always on top
343   m_alwaysOnTop = true;
344 #else
345   // default for windows is not always on top
346   m_alwaysOnTop = false;
347 #endif
348
349   m_bgInfoLoaderMaxThreads = 5;
350
351   m_iPVRTimeCorrection             = 0;
352   m_iPVRInfoToggleInterval         = 3000;
353   m_bPVRShowEpgInfoOnEpgItemSelect = true;
354   m_iPVRMinVideoCacheLevel         = 5;
355   m_iPVRMinAudioCacheLevel         = 10;
356   m_bPVRCacheInDvdPlayer           = true;
357   m_bPVRChannelIconsAutoScan       = true;
358   m_bPVRAutoScanIconsUserSet       = false;
359   m_iPVRNumericChannelSwitchTimeout = 1000;
360
361   m_measureRefreshrate = false;
362
363   m_cacheMemBufferSize = 1024 * 1024 * 20;
364   m_alwaysForceBuffer = false;
365   m_addonPackageFolderSize = 200;
366
367   m_jsonOutputCompact = true;
368   m_jsonTcpPort = 9090;
369
370   m_enableMultimediaKeys = false;
371
372   m_canWindowed = true;
373   m_guiVisualizeDirtyRegions = false;
374   m_guiAlgorithmDirtyRegions = 3;
375   m_guiDirtyRegionNoFlipTimeout = 0;
376   m_logEnableAirtunes = false;
377   m_airTunesPort = 36666;
378   m_airPlayPort = 36667;
379
380   m_databaseMusic.Reset();
381   m_databaseVideo.Reset();
382
383   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|.rss";
384   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|.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|.tta|.rss|.cm3|.cms|.dlt|.brstm|.wtv|.mka";
385   m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.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|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv";
386   m_discStubExtensions = ".disc";
387   // internal music extensions
388   m_musicExtensions += "|.sidstream|.oggstream|.nsfstream|.asapstream|.cdda";
389   // internal video extensions
390   m_videoExtensions += "|.pvr";
391
392   m_logLevelHint = m_logLevel = LOG_LEVEL_NORMAL;
393   m_extraLogLevels = 0;
394
395   #if defined(TARGET_DARWIN)
396     CStdString logDir = getenv("HOME");
397     logDir += "/Library/Logs/";
398     m_logFolder = logDir;
399   #else
400     m_logFolder = "special://home/";              // log file location
401   #endif
402
403   m_userAgent = g_sysinfo.GetUserAgent();
404
405   m_initialized = true;
406 }
407
408 bool CAdvancedSettings::Load()
409 {
410   // NOTE: This routine should NOT set the default of any of these parameters
411   //       it should instead use the versions of GetString/Integer/Float that
412   //       don't take defaults in.  Defaults are set in the constructor above
413   Initialize(); // In case of profile switch.
414   ParseSettingsFile("special://xbmc/system/advancedsettings.xml");
415   for (unsigned int i = 0; i < m_settingsFiles.size(); i++)
416     ParseSettingsFile(m_settingsFiles[i]);
417   ParseSettingsFile(CProfilesManager::Get().GetUserDataItem("advancedsettings.xml"));
418   return true;
419 }
420
421 void CAdvancedSettings::ParseSettingsFile(const CStdString &file)
422 {
423   CXBMCTinyXML advancedXML;
424   if (!CFile::Exists(file))
425   {
426     CLog::Log(LOGNOTICE, "No settings file to load (%s)", file.c_str());
427     return;
428   }
429
430   if (!advancedXML.LoadFile(file))
431   {
432     CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", file.c_str(), advancedXML.ErrorRow(), advancedXML.ErrorDesc());
433     return;
434   }
435
436   TiXmlElement *pRootElement = advancedXML.RootElement();
437   if (!pRootElement || strcmpi(pRootElement->Value(),"advancedsettings") != 0)
438   {
439     CLog::Log(LOGERROR, "Error loading %s, no <advancedsettings> node", file.c_str());
440     return;
441   }
442
443   // succeeded - tell the user it worked
444   CLog::Log(LOGNOTICE, "Loaded settings file from %s", file.c_str());
445
446   // Dump contents of AS.xml to debug log
447   TiXmlPrinter printer;
448   printer.SetLineBreak("\n");
449   printer.SetIndent("  ");
450   advancedXML.Accept(&printer);
451   CLog::Log(LOGNOTICE, "Contents of %s are...\n%s", file.c_str(), printer.CStr());
452
453   TiXmlElement *pElement = pRootElement->FirstChildElement("audio");
454   if (pElement)
455   {
456     XMLUtils::GetFloat(pElement, "ac3downmixgain", m_ac3Gain, -96.0f, 96.0f);
457     XMLUtils::GetInt(pElement, "headroom", m_audioHeadRoom, 0, 12);
458     XMLUtils::GetString(pElement, "defaultplayer", m_audioDefaultPlayer);
459     // 101 on purpose - can be used to never automark as watched
460     XMLUtils::GetFloat(pElement, "playcountminimumpercent", m_audioPlayCountMinimumPercent, 0.0f, 101.0f);
461
462     XMLUtils::GetBoolean(pElement, "usetimeseeking", m_musicUseTimeSeeking);
463     XMLUtils::GetInt(pElement, "timeseekforward", m_musicTimeSeekForward, 0, 6000);
464     XMLUtils::GetInt(pElement, "timeseekbackward", m_musicTimeSeekBackward, -6000, 0);
465     XMLUtils::GetInt(pElement, "timeseekforwardbig", m_musicTimeSeekForwardBig, 0, 6000);
466     XMLUtils::GetInt(pElement, "timeseekbackwardbig", m_musicTimeSeekBackwardBig, -6000, 0);
467
468     XMLUtils::GetInt(pElement, "percentseekforward", m_musicPercentSeekForward, 0, 100);
469     XMLUtils::GetInt(pElement, "percentseekbackward", m_musicPercentSeekBackward, -100, 0);
470     XMLUtils::GetInt(pElement, "percentseekforwardbig", m_musicPercentSeekForwardBig, 0, 100);
471     XMLUtils::GetInt(pElement, "percentseekbackwardbig", m_musicPercentSeekBackwardBig, -100, 0);
472
473     XMLUtils::GetInt(pElement, "resample", m_audioResample, 0, 192000);
474     XMLUtils::GetBoolean(pElement, "allowtranscode44100", m_allowTranscode44100);
475     XMLUtils::GetBoolean(pElement, "forceDirectSound", m_audioForceDirectSound);
476     XMLUtils::GetBoolean(pElement, "audiophile", m_audioAudiophile);
477     XMLUtils::GetBoolean(pElement, "allchannelstereo", m_allChannelStereo);
478     XMLUtils::GetBoolean(pElement, "streamsilence", m_streamSilence);
479     XMLUtils::GetString(pElement, "transcodeto", m_audioTranscodeTo);
480     XMLUtils::GetInt(pElement, "audiosinkbufferdurationmsec", m_audioSinkBufferDurationMsec);
481
482     TiXmlElement* pAudioExcludes = pElement->FirstChildElement("excludefromlisting");
483     if (pAudioExcludes)
484       GetCustomRegexps(pAudioExcludes, m_audioExcludeFromListingRegExps);
485
486     pAudioExcludes = pElement->FirstChildElement("excludefromscan");
487     if (pAudioExcludes)
488       GetCustomRegexps(pAudioExcludes, m_audioExcludeFromScanRegExps);
489
490     XMLUtils::GetString(pElement, "audiohost", m_audioHost);
491     XMLUtils::GetBoolean(pElement, "applydrc", m_audioApplyDrc);
492     XMLUtils::GetBoolean(pElement, "dvdplayerignoredtsinwav", m_dvdplayerIgnoreDTSinWAV);
493
494     XMLUtils::GetFloat(pElement, "limiterhold", m_limiterHold, 0.0f, 100.0f);
495     XMLUtils::GetFloat(pElement, "limiterrelease", m_limiterRelease, 0.001f, 100.0f);
496   }
497
498   pElement = pRootElement->FirstChildElement("omx");
499   if (pElement)
500   {
501     XMLUtils::GetBoolean(pElement, "omxhwaudiodecode", m_omxHWAudioDecode);
502     XMLUtils::GetBoolean(pElement, "omxdecodestartwithvalidframe", m_omxDecodeStartWithValidFrame);
503   }
504
505   pElement = pRootElement->FirstChildElement("karaoke");
506   if (pElement)
507   {
508     XMLUtils::GetFloat(pElement, "syncdelaycdg", m_karaokeSyncDelayCDG, -3.0f, 3.0f); // keep the old name for comp
509     XMLUtils::GetFloat(pElement, "syncdelaylrc", m_karaokeSyncDelayLRC, -3.0f, 3.0f);
510     XMLUtils::GetBoolean(pElement, "alwaysreplacegenre", m_karaokeChangeGenreForKaraokeSongs );
511     XMLUtils::GetBoolean(pElement, "storedelay", m_karaokeKeepDelay );
512     XMLUtils::GetInt(pElement, "autoassignstartfrom", m_karaokeStartIndex, 1, 2000000000);
513     XMLUtils::GetBoolean(pElement, "nocdgbackground", m_karaokeAlwaysEmptyOnCdgs );
514     XMLUtils::GetBoolean(pElement, "lookupsongbackground", m_karaokeUseSongSpecificBackground );
515
516     TiXmlElement* pKaraokeBackground = pElement->FirstChildElement("defaultbackground");
517     if (pKaraokeBackground)
518     {
519       const char* attr = pKaraokeBackground->Attribute("type");
520       if ( attr )
521         m_karaokeDefaultBackgroundType = attr;
522
523       attr = pKaraokeBackground->Attribute("path");
524       if ( attr )
525         m_karaokeDefaultBackgroundFilePath = attr;
526     }
527   }
528
529   pElement = pRootElement->FirstChildElement("video");
530   if (pElement)
531   {
532     XMLUtils::GetFloat(pElement, "subsdelayrange", m_videoSubsDelayRange, 10, 600);
533     XMLUtils::GetFloat(pElement, "audiodelayrange", m_videoAudioDelayRange, 10, 600);
534     XMLUtils::GetInt(pElement, "blackbarcolour", m_videoBlackBarColour, 0, 255);
535     XMLUtils::GetString(pElement, "defaultplayer", m_videoDefaultPlayer);
536     XMLUtils::GetString(pElement, "defaultdvdplayer", m_videoDefaultDVDPlayer);
537     XMLUtils::GetBoolean(pElement, "fullscreenonmoviestart", m_fullScreenOnMovieStart);
538     // 101 on purpose - can be used to never automark as watched
539     XMLUtils::GetFloat(pElement, "playcountminimumpercent", m_videoPlayCountMinimumPercent, 0.0f, 101.0f);
540     XMLUtils::GetInt(pElement, "ignoresecondsatstart", m_videoIgnoreSecondsAtStart, 0, 900);
541     XMLUtils::GetFloat(pElement, "ignorepercentatend", m_videoIgnorePercentAtEnd, 0, 100.0f);
542
543     XMLUtils::GetInt(pElement, "smallstepbackseconds", m_videoSmallStepBackSeconds, 1, INT_MAX);
544     XMLUtils::GetInt(pElement, "smallstepbacktries", m_videoSmallStepBackTries, 1, 10);
545     XMLUtils::GetInt(pElement, "smallstepbackdelay", m_videoSmallStepBackDelay, 100, 5000); //MS
546
547     XMLUtils::GetBoolean(pElement, "usetimeseeking", m_videoUseTimeSeeking);
548     XMLUtils::GetInt(pElement, "timeseekforward", m_videoTimeSeekForward, 0, 6000);
549     XMLUtils::GetInt(pElement, "timeseekbackward", m_videoTimeSeekBackward, -6000, 0);
550     XMLUtils::GetInt(pElement, "timeseekforwardbig", m_videoTimeSeekForwardBig, 0, 6000);
551     XMLUtils::GetInt(pElement, "timeseekbackwardbig", m_videoTimeSeekBackwardBig, -6000, 0);
552
553     XMLUtils::GetInt(pElement, "percentseekforward", m_videoPercentSeekForward, 0, 100);
554     XMLUtils::GetInt(pElement, "percentseekbackward", m_videoPercentSeekBackward, -100, 0);
555     XMLUtils::GetInt(pElement, "percentseekforwardbig", m_videoPercentSeekForwardBig, 0, 100);
556     XMLUtils::GetInt(pElement, "percentseekbackwardbig", m_videoPercentSeekBackwardBig, -100, 0);
557
558     TiXmlElement* pVideoExcludes = pElement->FirstChildElement("excludefromlisting");
559     if (pVideoExcludes)
560       GetCustomRegexps(pVideoExcludes, m_videoExcludeFromListingRegExps);
561
562     pVideoExcludes = pElement->FirstChildElement("excludefromscan");
563     if (pVideoExcludes)
564       GetCustomRegexps(pVideoExcludes, m_moviesExcludeFromScanRegExps);
565
566     pVideoExcludes = pElement->FirstChildElement("excludetvshowsfromscan");
567     if (pVideoExcludes)
568       GetCustomRegexps(pVideoExcludes, m_tvshowExcludeFromScanRegExps);
569
570     pVideoExcludes = pElement->FirstChildElement("cleanstrings");
571     if (pVideoExcludes)
572       GetCustomRegexps(pVideoExcludes, m_videoCleanStringRegExps);
573
574     XMLUtils::GetString(pElement,"cleandatetime", m_videoCleanDateTimeRegExp);
575     XMLUtils::GetString(pElement,"ppffmpegdeinterlacing",m_videoPPFFmpegDeint);
576     XMLUtils::GetString(pElement,"ppffmpegpostprocessing",m_videoPPFFmpegPostProc);
577     XMLUtils::GetBoolean(pElement,"vdpauscaling",m_videoVDPAUScaling);
578     XMLUtils::GetFloat(pElement, "nonlinearstretchratio", m_videoNonLinStretchRatio, 0.01f, 1.0f);
579     XMLUtils::GetBoolean(pElement,"enablehighqualityhwscalers", m_videoEnableHighQualityHwScalers);
580     XMLUtils::GetFloat(pElement,"autoscalemaxfps",m_videoAutoScaleMaxFps, 0.0f, 1000.0f);
581     XMLUtils::GetBoolean(pElement,"allowmpeg4vdpau",m_videoAllowMpeg4VDPAU);
582     XMLUtils::GetBoolean(pElement,"disablehi10pmultithreading",m_videoDisableHi10pMultithreading);
583     XMLUtils::GetBoolean(pElement,"allowmpeg4vaapi",m_videoAllowMpeg4VAAPI);    
584     XMLUtils::GetBoolean(pElement, "disablebackgrounddeinterlace", m_videoDisableBackgroundDeinterlace);
585     XMLUtils::GetInt(pElement, "useocclusionquery", m_videoCaptureUseOcclusionQuery, -1, 1);
586
587     TiXmlElement* pAdjustRefreshrate = pElement->FirstChildElement("adjustrefreshrate");
588     if (pAdjustRefreshrate)
589     {
590       TiXmlElement* pRefreshOverride = pAdjustRefreshrate->FirstChildElement("override");
591       while (pRefreshOverride)
592       {
593         RefreshOverride override = {0};
594
595         float fps;
596         if (XMLUtils::GetFloat(pRefreshOverride, "fps", fps))
597         {
598           override.fpsmin = fps - 0.01f;
599           override.fpsmax = fps + 0.01f;
600         }
601
602         float fpsmin, fpsmax;
603         if (XMLUtils::GetFloat(pRefreshOverride, "fpsmin", fpsmin) &&
604             XMLUtils::GetFloat(pRefreshOverride, "fpsmax", fpsmax))
605         {
606           override.fpsmin = fpsmin;
607           override.fpsmax = fpsmax;
608         }
609
610         float refresh;
611         if (XMLUtils::GetFloat(pRefreshOverride, "refresh", refresh))
612         {
613           override.refreshmin = refresh - 0.01f;
614           override.refreshmax = refresh + 0.01f;
615         }
616
617         float refreshmin, refreshmax;
618         if (XMLUtils::GetFloat(pRefreshOverride, "refreshmin", refreshmin) &&
619             XMLUtils::GetFloat(pRefreshOverride, "refreshmax", refreshmax))
620         {
621           override.refreshmin = refreshmin;
622           override.refreshmax = refreshmax;
623         }
624
625         bool fpsCorrect     = (override.fpsmin > 0.0f && override.fpsmax >= override.fpsmin);
626         bool refreshCorrect = (override.refreshmin > 0.0f && override.refreshmax >= override.refreshmin);
627
628         if (fpsCorrect && refreshCorrect)
629           m_videoAdjustRefreshOverrides.push_back(override);
630         else
631           CLog::Log(LOGWARNING, "Ignoring malformed refreshrate override, fpsmin:%f fpsmax:%f refreshmin:%f refreshmax:%f",
632               override.fpsmin, override.fpsmax, override.refreshmin, override.refreshmax);
633
634         pRefreshOverride = pRefreshOverride->NextSiblingElement("override");
635       }
636
637       TiXmlElement* pRefreshFallback = pAdjustRefreshrate->FirstChildElement("fallback");
638       while (pRefreshFallback)
639       {
640         RefreshOverride fallback = {0};
641         fallback.fallback = true;
642
643         float refresh;
644         if (XMLUtils::GetFloat(pRefreshFallback, "refresh", refresh))
645         {
646           fallback.refreshmin = refresh - 0.01f;
647           fallback.refreshmax = refresh + 0.01f;
648         }
649
650         float refreshmin, refreshmax;
651         if (XMLUtils::GetFloat(pRefreshFallback, "refreshmin", refreshmin) &&
652             XMLUtils::GetFloat(pRefreshFallback, "refreshmax", refreshmax))
653         {
654           fallback.refreshmin = refreshmin;
655           fallback.refreshmax = refreshmax;
656         }
657
658         if (fallback.refreshmin > 0.0f && fallback.refreshmax >= fallback.refreshmin)
659           m_videoAdjustRefreshOverrides.push_back(fallback);
660         else
661           CLog::Log(LOGWARNING, "Ignoring malformed refreshrate fallback, fpsmin:%f fpsmax:%f refreshmin:%f refreshmax:%f",
662               fallback.fpsmin, fallback.fpsmax, fallback.refreshmin, fallback.refreshmax);
663
664         pRefreshFallback = pRefreshFallback->NextSiblingElement("fallback");
665       }
666     }
667
668     m_DXVACheckCompatibilityPresent = XMLUtils::GetBoolean(pElement,"checkdxvacompatibility", m_DXVACheckCompatibility);
669
670     XMLUtils::GetBoolean(pElement,"forcedxvarenderer", m_DXVAForceProcessorRenderer);
671     XMLUtils::GetBoolean(pElement,"dxvanodeintforprogressive", m_DXVANoDeintProcForProgressive);
672     //0 = disable fps detect, 1 = only detect on timestamps with uniform spacing, 2 detect on all timestamps
673     XMLUtils::GetInt(pElement, "fpsdetect", m_videoFpsDetect, 0, 2);
674
675     // Store global display latency settings
676     TiXmlElement* pVideoLatency = pElement->FirstChildElement("latency");
677     if (pVideoLatency)
678     {
679       float refresh, refreshmin, refreshmax, delay;
680       TiXmlElement* pRefreshVideoLatency = pVideoLatency->FirstChildElement("refresh");
681
682       while (pRefreshVideoLatency)
683       {
684         RefreshVideoLatency videolatency = {0};
685
686         if (XMLUtils::GetFloat(pRefreshVideoLatency, "rate", refresh))
687         {
688           videolatency.refreshmin = refresh - 0.01f;
689           videolatency.refreshmax = refresh + 0.01f;
690         }
691         else if (XMLUtils::GetFloat(pRefreshVideoLatency, "min", refreshmin) &&
692                  XMLUtils::GetFloat(pRefreshVideoLatency, "max", refreshmax))
693         {
694           videolatency.refreshmin = refreshmin;
695           videolatency.refreshmax = refreshmax;
696         }
697         if (XMLUtils::GetFloat(pRefreshVideoLatency, "delay", delay, -600.0f, 600.0f))
698           videolatency.delay = delay;
699
700         if (videolatency.refreshmin > 0.0f && videolatency.refreshmax >= videolatency.refreshmin)
701           m_videoRefreshLatency.push_back(videolatency);
702         else
703           CLog::Log(LOGWARNING, "Ignoring malformed display latency <refresh> entry, min:%f max:%f", videolatency.refreshmin, videolatency.refreshmax);
704
705         pRefreshVideoLatency = pRefreshVideoLatency->NextSiblingElement("refresh");
706       }
707
708       // Get default global display latency
709       XMLUtils::GetFloat(pVideoLatency, "delay", m_videoDefaultLatency, -600.0f, 600.0f);
710     }
711   }
712
713   pElement = pRootElement->FirstChildElement("musiclibrary");
714   if (pElement)
715   {
716     XMLUtils::GetBoolean(pElement, "hideallitems", m_bMusicLibraryHideAllItems);
717     XMLUtils::GetInt(pElement, "recentlyaddeditems", m_iMusicLibraryRecentlyAddedItems, 1, INT_MAX);
718     XMLUtils::GetBoolean(pElement, "prioritiseapetags", m_prioritiseAPEv2tags);
719     XMLUtils::GetBoolean(pElement, "allitemsonbottom", m_bMusicLibraryAllItemsOnBottom);
720     XMLUtils::GetBoolean(pElement, "albumssortbyartistthenyear", m_bMusicLibraryAlbumsSortByArtistThenYear);
721     XMLUtils::GetString(pElement, "albumformat", m_strMusicLibraryAlbumFormat);
722     XMLUtils::GetString(pElement, "albumformatright", m_strMusicLibraryAlbumFormatRight);
723     XMLUtils::GetString(pElement, "itemseparator", m_musicItemSeparator);
724   }
725
726   pElement = pRootElement->FirstChildElement("videolibrary");
727   if (pElement)
728   {
729     XMLUtils::GetBoolean(pElement, "hideallitems", m_bVideoLibraryHideAllItems);
730     XMLUtils::GetBoolean(pElement, "allitemsonbottom", m_bVideoLibraryAllItemsOnBottom);
731     XMLUtils::GetInt(pElement, "recentlyaddeditems", m_iVideoLibraryRecentlyAddedItems, 1, INT_MAX);
732     XMLUtils::GetBoolean(pElement, "hideemptyseries", m_bVideoLibraryHideEmptySeries);
733     XMLUtils::GetBoolean(pElement, "cleanonupdate", m_bVideoLibraryCleanOnUpdate);
734     XMLUtils::GetString(pElement, "itemseparator", m_videoItemSeparator);
735     XMLUtils::GetBoolean(pElement, "exportautothumbs", m_bVideoLibraryExportAutoThumbs);
736     XMLUtils::GetBoolean(pElement, "importwatchedstate", m_bVideoLibraryImportWatchedState);
737     XMLUtils::GetBoolean(pElement, "importresumepoint", m_bVideoLibraryImportResumePoint);
738     XMLUtils::GetInt(pElement, "dateadded", m_iVideoLibraryDateAdded);
739   }
740
741   pElement = pRootElement->FirstChildElement("videoscanner");
742   if (pElement)
743   {
744     XMLUtils::GetBoolean(pElement, "ignoreerrors", m_bVideoScannerIgnoreErrors);
745   }
746
747   // Backward-compatibility of ExternalPlayer config
748   pElement = pRootElement->FirstChildElement("externalplayer");
749   if (pElement)
750   {
751     CLog::Log(LOGWARNING, "External player configuration has been removed from advancedsettings.xml.  It can now be configed in userdata/playercorefactory.xml");
752   }
753   pElement = pRootElement->FirstChildElement("slideshow");
754   if (pElement)
755   {
756     XMLUtils::GetFloat(pElement, "panamount", m_slideshowPanAmount, 0.0f, 20.0f);
757     XMLUtils::GetFloat(pElement, "zoomamount", m_slideshowZoomAmount, 0.0f, 20.0f);
758     XMLUtils::GetFloat(pElement, "blackbarcompensation", m_slideshowBlackBarCompensation, 0.0f, 50.0f);
759   }
760
761   pElement = pRootElement->FirstChildElement("network");
762   if (pElement)
763   {
764     XMLUtils::GetInt(pElement, "curlclienttimeout", m_curlconnecttimeout, 1, 1000);
765     XMLUtils::GetInt(pElement, "curllowspeedtime", m_curllowspeedtime, 1, 1000);
766     XMLUtils::GetInt(pElement, "curlretries", m_curlretries, 0, 10);
767     XMLUtils::GetBoolean(pElement,"disableipv6", m_curlDisableIPV6);
768     XMLUtils::GetUInt(pElement, "cachemembuffersize", m_cacheMemBufferSize);
769     XMLUtils::GetBoolean(pElement, "alwaysforcebuffer", m_alwaysForceBuffer);
770   }
771
772   pElement = pRootElement->FirstChildElement("jsonrpc");
773   if (pElement)
774   {
775     XMLUtils::GetBoolean(pElement, "compactoutput", m_jsonOutputCompact);
776     XMLUtils::GetUInt(pElement, "tcpport", m_jsonTcpPort);
777   }
778
779   pElement = pRootElement->FirstChildElement("samba");
780   if (pElement)
781   {
782     XMLUtils::GetString(pElement,  "doscodepage",   m_sambadoscodepage);
783     XMLUtils::GetInt(pElement, "clienttimeout", m_sambaclienttimeout, 5, 100);
784     XMLUtils::GetBoolean(pElement, "statfiles", m_sambastatfiles);
785   }
786
787   pElement = pRootElement->FirstChildElement("httpdirectory");
788   if (pElement)
789     XMLUtils::GetBoolean(pElement, "statfilesize", m_bHTTPDirectoryStatFilesize);
790
791   pElement = pRootElement->FirstChildElement("ftp");
792   if (pElement)
793   {
794     XMLUtils::GetBoolean(pElement, "remotethumbs", m_bFTPThumbs);
795   }
796
797   pElement = pRootElement->FirstChildElement("loglevel");
798   if (pElement)
799   { // read the loglevel setting, so set the setting advanced to hide it in GUI
800     // as altering it will do nothing - we don't write to advancedsettings.xml
801     XMLUtils::GetInt(pRootElement, "loglevel", m_logLevelHint, LOG_LEVEL_NONE, LOG_LEVEL_MAX);
802     CSettingBool *setting = (CSettingBool *)CSettings::Get().GetSetting("debug.showloginfo");
803     if (setting != NULL)
804     {
805       const char* hide;
806       if (!((hide = pElement->Attribute("hide")) && strnicmp("false", hide, 4) == 0))
807         setting->SetVisible(false);
808     }
809     g_advancedSettings.m_logLevel = std::max(g_advancedSettings.m_logLevel, g_advancedSettings.m_logLevelHint);
810     CLog::SetLogLevel(g_advancedSettings.m_logLevel);
811   }
812
813   XMLUtils::GetString(pRootElement, "cddbaddress", m_cddbAddress);
814
815   //airtunes + airplay
816   XMLUtils::GetBoolean(pRootElement, "enableairtunesdebuglog", m_logEnableAirtunes);
817   XMLUtils::GetInt(pRootElement,     "airtunesport", m_airTunesPort);
818   XMLUtils::GetInt(pRootElement,     "airplayport", m_airPlayPort);  
819
820   XMLUtils::GetBoolean(pRootElement, "handlemounting", m_handleMounting);
821
822 #if defined(HAS_SDL) || defined(TARGET_WINDOWS)
823   XMLUtils::GetBoolean(pRootElement, "fullscreen", m_startFullScreen);
824 #endif
825   XMLUtils::GetBoolean(pRootElement, "splash", m_splashImage);
826   XMLUtils::GetBoolean(pRootElement, "showexitbutton", m_showExitButton);
827   XMLUtils::GetBoolean(pRootElement, "canwindowed", m_canWindowed);
828
829   XMLUtils::GetInt(pRootElement, "songinfoduration", m_songInfoDuration, 0, INT_MAX);
830   XMLUtils::GetInt(pRootElement, "playlistretries", m_playlistRetries, -1, 5000);
831   XMLUtils::GetInt(pRootElement, "playlisttimeout", m_playlistTimeout, 0, 5000);
832
833   XMLUtils::GetBoolean(pRootElement,"glrectanglehack", m_GLRectangleHack);
834   XMLUtils::GetInt(pRootElement,"skiploopfilter", m_iSkipLoopFilter, -16, 48);
835   XMLUtils::GetFloat(pRootElement, "forcedswaptime", m_ForcedSwapTime, 0.0, 100.0);
836
837   XMLUtils::GetBoolean(pRootElement,"allowd3d9ex", m_AllowD3D9Ex);
838   XMLUtils::GetBoolean(pRootElement,"forced3d9ex", m_ForceD3D9Ex);
839   XMLUtils::GetBoolean(pRootElement,"allowdynamictextures", m_AllowDynamicTextures);
840   XMLUtils::GetUInt(pRootElement,"restrictcapsmask", m_RestrictCapsMask);
841   XMLUtils::GetFloat(pRootElement,"sleepbeforeflip", m_sleepBeforeFlip, 0.0f, 1.0f);
842   XMLUtils::GetBoolean(pRootElement,"virtualshares", m_bVirtualShares);
843   XMLUtils::GetUInt(pRootElement, "packagefoldersize", m_addonPackageFolderSize);
844
845   //Tuxbox
846   pElement = pRootElement->FirstChildElement("tuxbox");
847   if (pElement)
848   {
849     XMLUtils::GetInt(pElement, "streamtsport", m_iTuxBoxStreamtsPort, 0, 65535);
850     XMLUtils::GetBoolean(pElement, "audiochannelselection", m_bTuxBoxAudioChannelSelection);
851     XMLUtils::GetBoolean(pElement, "submenuselection", m_bTuxBoxSubMenuSelection);
852     XMLUtils::GetBoolean(pElement, "pictureicon", m_bTuxBoxPictureIcon);
853     XMLUtils::GetBoolean(pElement, "sendallaudiopids", m_bTuxBoxSendAllAPids);
854     XMLUtils::GetInt(pElement, "epgrequesttime", m_iTuxBoxEpgRequestTime, 0, 3600);
855     XMLUtils::GetInt(pElement, "defaultsubmenu", m_iTuxBoxDefaultSubMenu, 1, 4);
856     XMLUtils::GetInt(pElement, "defaultrootmenu", m_iTuxBoxDefaultRootMenu, 0, 4);
857     XMLUtils::GetInt(pElement, "zapwaittime", m_iTuxBoxZapWaitTime, 0, 120);
858     XMLUtils::GetBoolean(pElement, "zapstream", m_bTuxBoxZapstream);
859     XMLUtils::GetInt(pElement, "zapstreamport", m_iTuxBoxZapstreamPort, 0, 65535);
860   }
861
862   // Myth TV
863   pElement = pRootElement->FirstChildElement("myth");
864   if (pElement)
865   {
866     XMLUtils::GetInt(pElement, "movielength", m_iMythMovieLength);
867   }
868
869   // EPG
870   pElement = pRootElement->FirstChildElement("epg");
871   if (pElement)
872   {
873     XMLUtils::GetInt(pElement, "lingertime", m_iEpgLingerTime);
874     XMLUtils::GetInt(pElement, "updatecheckinterval", m_iEpgUpdateCheckInterval);
875     XMLUtils::GetInt(pElement, "cleanupinterval", m_iEpgCleanupInterval);
876     XMLUtils::GetInt(pElement, "activetagcheckinterval", m_iEpgActiveTagCheckInterval);
877     XMLUtils::GetInt(pElement, "retryinterruptedupdateinterval", m_iEpgRetryInterruptedUpdateInterval);
878     XMLUtils::GetInt(pElement, "updateemptytagsinterval", m_iEpgUpdateEmptyTagsInterval);
879     XMLUtils::GetBoolean(pElement, "displayupdatepopup", m_bEpgDisplayUpdatePopup);
880     XMLUtils::GetBoolean(pElement, "displayincrementalupdatepopup", m_bEpgDisplayIncrementalUpdatePopup);
881   }
882
883   // EDL commercial break handling
884   pElement = pRootElement->FirstChildElement("edl");
885   if (pElement)
886   {
887     XMLUtils::GetBoolean(pElement, "mergeshortcommbreaks", m_bEdlMergeShortCommBreaks);
888     XMLUtils::GetInt(pElement, "maxcommbreaklength", m_iEdlMaxCommBreakLength, 0, 10 * 60); // Between 0 and 10 minutes
889     XMLUtils::GetInt(pElement, "mincommbreaklength", m_iEdlMinCommBreakLength, 0, 5 * 60);  // Between 0 and 5 minutes
890     XMLUtils::GetInt(pElement, "maxcommbreakgap", m_iEdlMaxCommBreakGap, 0, 5 * 60);        // Between 0 and 5 minutes.
891     XMLUtils::GetInt(pElement, "maxstartgap", m_iEdlMaxStartGap, 0, 10 * 60);               // Between 0 and 10 minutes
892     XMLUtils::GetInt(pElement, "commbreakautowait", m_iEdlCommBreakAutowait, 0, 10);        // Between 0 and 10 seconds
893     XMLUtils::GetInt(pElement, "commbreakautowind", m_iEdlCommBreakAutowind, 0, 10);        // Between 0 and 10 seconds
894   }
895
896   // picture exclude regexps
897   TiXmlElement* pPictureExcludes = pRootElement->FirstChildElement("pictureexcludes");
898   if (pPictureExcludes)
899     GetCustomRegexps(pPictureExcludes, m_pictureExcludeFromListingRegExps);
900
901   // picture extensions
902   TiXmlElement* pExts = pRootElement->FirstChildElement("pictureextensions");
903   if (pExts)
904     GetCustomExtensions(pExts, m_pictureExtensions);
905
906   // music extensions
907   pExts = pRootElement->FirstChildElement("musicextensions");
908   if (pExts)
909     GetCustomExtensions(pExts, m_musicExtensions);
910
911   // video extensions
912   pExts = pRootElement->FirstChildElement("videoextensions");
913   if (pExts)
914     GetCustomExtensions(pExts, m_videoExtensions);
915
916   // stub extensions
917   pExts = pRootElement->FirstChildElement("discstubextensions");
918   if (pExts)
919     GetCustomExtensions(pExts, m_discStubExtensions);
920
921   // Add the list of disc stub extensions (if any) to the list of video extensions
922   if (!m_discStubExtensions.IsEmpty())
923     m_videoExtensions += "|" + m_discStubExtensions;
924
925   m_vecTokens.clear();
926   CLangInfo::LoadTokens(pRootElement->FirstChild("sorttokens"),m_vecTokens);
927
928   // TODO: Should cache path be given in terms of our predefined paths??
929   //       Are we even going to have predefined paths??
930   CStdString tmp;
931   if (XMLUtils::GetPath(pRootElement, "cachepath", tmp))
932     m_cachePath = tmp;
933   URIUtils::AddSlashAtEnd(m_cachePath);
934
935   g_LangCodeExpander.LoadUserCodes(pRootElement->FirstChildElement("languagecodes"));
936
937   // trailer matching regexps
938   TiXmlElement* pTrailerMatching = pRootElement->FirstChildElement("trailermatching");
939   if (pTrailerMatching)
940     GetCustomRegexps(pTrailerMatching, m_trailerMatchRegExps);
941
942   //everything thats a trailer is not a movie
943   m_moviesExcludeFromScanRegExps.insert(m_moviesExcludeFromScanRegExps.end(),
944                                         m_trailerMatchRegExps.begin(),
945                                         m_trailerMatchRegExps.end());
946
947   // video stacking regexps
948   TiXmlElement* pVideoStacking = pRootElement->FirstChildElement("moviestacking");
949   if (pVideoStacking)
950     GetCustomRegexps(pVideoStacking, m_videoStackRegExps);
951
952   // folder stacking regexps
953   TiXmlElement* pFolderStacking = pRootElement->FirstChildElement("folderstacking");
954   if (pFolderStacking)
955     GetCustomRegexps(pFolderStacking, m_folderStackRegExps);
956
957   //tv stacking regexps
958   TiXmlElement* pTVStacking = pRootElement->FirstChildElement("tvshowmatching");
959   if (pTVStacking)
960     GetCustomTVRegexps(pTVStacking, m_tvshowEnumRegExps);
961
962   //tv multipart enumeration regexp
963   XMLUtils::GetString(pRootElement, "tvmultipartmatching", m_tvshowMultiPartEnumRegExp);
964
965   // path substitutions
966   TiXmlElement* pPathSubstitution = pRootElement->FirstChildElement("pathsubstitution");
967   if (pPathSubstitution)
968   {
969     m_pathSubstitutions.clear();
970     CLog::Log(LOGDEBUG,"Configuring path substitutions");
971     TiXmlNode* pSubstitute = pPathSubstitution->FirstChildElement("substitute");
972     while (pSubstitute)
973     {
974       CStdString strFrom, strTo;
975       TiXmlNode* pFrom = pSubstitute->FirstChild("from");
976       if (pFrom)
977         strFrom = CSpecialProtocol::TranslatePath(pFrom->FirstChild()->Value()).c_str();
978       TiXmlNode* pTo = pSubstitute->FirstChild("to");
979       if (pTo)
980         strTo = pTo->FirstChild()->Value();
981
982       if (!strFrom.IsEmpty() && !strTo.IsEmpty())
983       {
984         CLog::Log(LOGDEBUG,"  Registering substition pair:");
985         CLog::Log(LOGDEBUG,"    From: [%s]", strFrom.c_str());
986         CLog::Log(LOGDEBUG,"    To:   [%s]", strTo.c_str());
987         m_pathSubstitutions.push_back(make_pair(strFrom,strTo));
988       }
989       else
990       {
991         // error message about missing tag
992         if (strFrom.IsEmpty())
993           CLog::Log(LOGERROR,"  Missing <from> tag");
994         else
995           CLog::Log(LOGERROR,"  Missing <to> tag");
996       }
997
998       // get next one
999       pSubstitute = pSubstitute->NextSiblingElement("substitute");
1000     }
1001   }
1002
1003   XMLUtils::GetInt(pRootElement, "remotedelay", m_remoteDelay, 1, 20);
1004   XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f);
1005   XMLUtils::GetUInt(pRootElement, "fanartres", m_fanartRes, 0, 1080);
1006   XMLUtils::GetUInt(pRootElement, "imageres", m_imageRes, 0, 1080);
1007   XMLUtils::GetBoolean(pRootElement, "useddsfanart", m_useDDSFanart);
1008
1009   XMLUtils::GetBoolean(pRootElement, "playlistasfolders", m_playlistAsFolders);
1010   XMLUtils::GetBoolean(pRootElement, "detectasudf", m_detectAsUdf);
1011
1012   // music thumbs
1013   TiXmlElement* pThumbs = pRootElement->FirstChildElement("musicthumbs");
1014   if (pThumbs)
1015     GetCustomExtensions(pThumbs,m_musicThumbs);
1016
1017   // movie fanarts
1018   TiXmlElement* pFanart = pRootElement->FirstChildElement("fanart");
1019   if (pFanart)
1020     GetCustomExtensions(pFanart,m_fanartImages);
1021
1022   // music filename->tag filters
1023   TiXmlElement* filters = pRootElement->FirstChildElement("musicfilenamefilters");
1024   if (filters)
1025   {
1026     TiXmlNode* filter = filters->FirstChild("filter");
1027     while (filter)
1028     {
1029       if (filter->FirstChild())
1030         m_musicTagsFromFileFilters.push_back(filter->FirstChild()->ValueStr());
1031       filter = filter->NextSibling("filter");
1032     }
1033   }
1034
1035   TiXmlElement* pHostEntries = pRootElement->FirstChildElement("hosts");
1036   if (pHostEntries)
1037   {
1038     TiXmlElement* element = pHostEntries->FirstChildElement("entry");
1039     while(element)
1040     {
1041       CStdString name  = element->Attribute("name");
1042       CStdString value;
1043       if(element->GetText())
1044         value = element->GetText();
1045
1046       if(name.length() > 0 && value.length() > 0)
1047         CDNSNameCache::Add(name, value);
1048       element = element->NextSiblingElement("entry");
1049     }
1050   }
1051
1052   XMLUtils::GetString(pRootElement, "cputempcommand", m_cpuTempCmd);
1053   XMLUtils::GetString(pRootElement, "gputempcommand", m_gpuTempCmd);
1054
1055   XMLUtils::GetBoolean(pRootElement, "alwaysontop", m_alwaysOnTop);
1056
1057   XMLUtils::GetInt(pRootElement, "bginfoloadermaxthreads", m_bgInfoLoaderMaxThreads);
1058   m_bgInfoLoaderMaxThreads = std::max(1, m_bgInfoLoaderMaxThreads);
1059
1060   TiXmlElement *pPVR = pRootElement->FirstChildElement("pvr");
1061   if (pPVR)
1062   {
1063     XMLUtils::GetInt(pPVR, "timecorrection", m_iPVRTimeCorrection, 0, 1440);
1064     XMLUtils::GetInt(pPVR, "infotoggleinterval", m_iPVRInfoToggleInterval, 0, 30000);
1065     XMLUtils::GetBoolean(pPVR, "showepginfoonselect", m_bPVRShowEpgInfoOnEpgItemSelect);
1066     XMLUtils::GetInt(pPVR, "minvideocachelevel", m_iPVRMinVideoCacheLevel, 0, 100);
1067     XMLUtils::GetInt(pPVR, "minaudiocachelevel", m_iPVRMinAudioCacheLevel, 0, 100);
1068     XMLUtils::GetBoolean(pPVR, "cacheindvdplayer", m_bPVRCacheInDvdPlayer);
1069     XMLUtils::GetBoolean(pPVR, "channeliconsautoscan", m_bPVRChannelIconsAutoScan);
1070     XMLUtils::GetBoolean(pPVR, "autoscaniconsuserset", m_bPVRAutoScanIconsUserSet);
1071     XMLUtils::GetInt(pPVR, "numericchannelswitchtimeout", m_iPVRNumericChannelSwitchTimeout, 50, 60000);
1072   }
1073
1074   XMLUtils::GetBoolean(pRootElement, "measurerefreshrate", m_measureRefreshrate);
1075
1076   TiXmlElement* pDatabase = pRootElement->FirstChildElement("videodatabase");
1077   if (pDatabase)
1078   {
1079     CLog::Log(LOGWARNING, "VIDEO database configuration is experimental.");
1080     XMLUtils::GetString(pDatabase, "type", m_databaseVideo.type);
1081     XMLUtils::GetString(pDatabase, "host", m_databaseVideo.host);
1082     XMLUtils::GetString(pDatabase, "port", m_databaseVideo.port);
1083     XMLUtils::GetString(pDatabase, "user", m_databaseVideo.user);
1084     XMLUtils::GetString(pDatabase, "pass", m_databaseVideo.pass);
1085     XMLUtils::GetString(pDatabase, "name", m_databaseVideo.name);
1086   }
1087
1088   pDatabase = pRootElement->FirstChildElement("musicdatabase");
1089   if (pDatabase)
1090   {
1091     XMLUtils::GetString(pDatabase, "type", m_databaseMusic.type);
1092     XMLUtils::GetString(pDatabase, "host", m_databaseMusic.host);
1093     XMLUtils::GetString(pDatabase, "port", m_databaseMusic.port);
1094     XMLUtils::GetString(pDatabase, "user", m_databaseMusic.user);
1095     XMLUtils::GetString(pDatabase, "pass", m_databaseMusic.pass);
1096     XMLUtils::GetString(pDatabase, "name", m_databaseMusic.name);
1097   }
1098
1099   pDatabase = pRootElement->FirstChildElement("tvdatabase");
1100   if (pDatabase)
1101   {
1102     XMLUtils::GetString(pDatabase, "type", m_databaseTV.type);
1103     XMLUtils::GetString(pDatabase, "host", m_databaseTV.host);
1104     XMLUtils::GetString(pDatabase, "port", m_databaseTV.port);
1105     XMLUtils::GetString(pDatabase, "user", m_databaseTV.user);
1106     XMLUtils::GetString(pDatabase, "pass", m_databaseTV.pass);
1107     XMLUtils::GetString(pDatabase, "name", m_databaseTV.name);
1108   }
1109
1110   pDatabase = pRootElement->FirstChildElement("epgdatabase");
1111   if (pDatabase)
1112   {
1113     XMLUtils::GetString(pDatabase, "type", m_databaseEpg.type);
1114     XMLUtils::GetString(pDatabase, "host", m_databaseEpg.host);
1115     XMLUtils::GetString(pDatabase, "port", m_databaseEpg.port);
1116     XMLUtils::GetString(pDatabase, "user", m_databaseEpg.user);
1117     XMLUtils::GetString(pDatabase, "pass", m_databaseEpg.pass);
1118     XMLUtils::GetString(pDatabase, "name", m_databaseEpg.name);
1119   }
1120
1121   pElement = pRootElement->FirstChildElement("enablemultimediakeys");
1122   if (pElement)
1123   {
1124     XMLUtils::GetBoolean(pRootElement, "enablemultimediakeys", m_enableMultimediaKeys);
1125   }
1126   
1127   pElement = pRootElement->FirstChildElement("gui");
1128   if (pElement)
1129   {
1130     XMLUtils::GetBoolean(pElement, "visualizedirtyregions", m_guiVisualizeDirtyRegions);
1131     XMLUtils::GetInt(pElement, "algorithmdirtyregions",     m_guiAlgorithmDirtyRegions);
1132     XMLUtils::GetInt(pElement, "nofliptimeout",             m_guiDirtyRegionNoFlipTimeout);
1133   }
1134
1135   // load in the settings overrides
1136   CSettings::Get().Load(pRootElement, true);  // true to hide the settings we read in
1137 }
1138
1139 void CAdvancedSettings::Clear()
1140 {
1141   m_videoCleanStringRegExps.clear();
1142   m_moviesExcludeFromScanRegExps.clear();
1143   m_tvshowExcludeFromScanRegExps.clear();
1144   m_videoExcludeFromListingRegExps.clear();
1145   m_videoStackRegExps.clear();
1146   m_folderStackRegExps.clear();
1147   m_audioExcludeFromScanRegExps.clear();
1148   m_audioExcludeFromListingRegExps.clear();
1149   m_pictureExcludeFromListingRegExps.clear();
1150
1151   m_pictureExtensions.clear();
1152   m_musicExtensions.clear();
1153   m_videoExtensions.clear();
1154   m_discStubExtensions.clear();
1155
1156   m_logFolder.clear();
1157   m_userAgent.clear();
1158 }
1159
1160 void CAdvancedSettings::GetCustomTVRegexps(TiXmlElement *pRootElement, SETTINGS_TVSHOWLIST& settings)
1161 {
1162   TiXmlElement *pElement = pRootElement;
1163   while (pElement)
1164   {
1165     int iAction = 0; // overwrite
1166     // for backward compatibility
1167     const char* szAppend = pElement->Attribute("append");
1168     if ((szAppend && stricmp(szAppend, "yes") == 0))
1169       iAction = 1;
1170     // action takes precedence if both attributes exist
1171     const char* szAction = pElement->Attribute("action");
1172     if (szAction)
1173     {
1174       iAction = 0; // overwrite
1175       if (stricmp(szAction, "append") == 0)
1176         iAction = 1; // append
1177       else if (stricmp(szAction, "prepend") == 0)
1178         iAction = 2; // prepend
1179     }
1180     if (iAction == 0)
1181       settings.clear();
1182     TiXmlNode* pRegExp = pElement->FirstChild("regexp");
1183     int i = 0;
1184     while (pRegExp)
1185     {
1186       if (pRegExp->FirstChild())
1187       {
1188         bool bByDate = false;
1189         int iDefaultSeason = 1;
1190         if (pRegExp->ToElement())
1191         {
1192           CStdString byDate = pRegExp->ToElement()->Attribute("bydate");
1193           if(byDate && stricmp(byDate, "true") == 0)
1194           {
1195             bByDate = true;
1196           }
1197           CStdString defaultSeason = pRegExp->ToElement()->Attribute("defaultseason");
1198           if(!defaultSeason.empty())
1199           {
1200             iDefaultSeason = atoi(defaultSeason.c_str());
1201           }
1202         }
1203         CStdString regExp = pRegExp->FirstChild()->Value();
1204         if (iAction == 2)
1205           settings.insert(settings.begin() + i++, 1, TVShowRegexp(bByDate,regExp,iDefaultSeason));
1206         else
1207           settings.push_back(TVShowRegexp(bByDate,regExp,iDefaultSeason));
1208       }
1209       pRegExp = pRegExp->NextSibling("regexp");
1210     }
1211
1212     pElement = pElement->NextSiblingElement(pRootElement->Value());
1213   }
1214 }
1215
1216 void CAdvancedSettings::GetCustomRegexps(TiXmlElement *pRootElement, CStdStringArray& settings)
1217 {
1218   TiXmlElement *pElement = pRootElement;
1219   while (pElement)
1220   {
1221     int iAction = 0; // overwrite
1222     // for backward compatibility
1223     const char* szAppend = pElement->Attribute("append");
1224     if ((szAppend && stricmp(szAppend, "yes") == 0))
1225       iAction = 1;
1226     // action takes precedence if both attributes exist
1227     const char* szAction = pElement->Attribute("action");
1228     if (szAction)
1229     {
1230       iAction = 0; // overwrite
1231       if (stricmp(szAction, "append") == 0)
1232         iAction = 1; // append
1233       else if (stricmp(szAction, "prepend") == 0)
1234         iAction = 2; // prepend
1235     }
1236     if (iAction == 0)
1237       settings.clear();
1238     TiXmlNode* pRegExp = pElement->FirstChild("regexp");
1239     int i = 0;
1240     while (pRegExp)
1241     {
1242       if (pRegExp->FirstChild())
1243       {
1244         CStdString regExp = pRegExp->FirstChild()->Value();
1245         if (iAction == 2)
1246           settings.insert(settings.begin() + i++, 1, regExp);
1247         else
1248           settings.push_back(regExp);
1249       }
1250       pRegExp = pRegExp->NextSibling("regexp");
1251     }
1252
1253     pElement = pElement->NextSiblingElement(pRootElement->Value());
1254   }
1255 }
1256
1257 void CAdvancedSettings::GetCustomExtensions(TiXmlElement *pRootElement, CStdString& extensions)
1258 {
1259   CStdString extraExtensions;
1260   if (XMLUtils::GetString(pRootElement, "add", extraExtensions) && !extraExtensions.empty())
1261     extensions += "|" + extraExtensions;
1262   if (XMLUtils::GetString(pRootElement, "remove", extraExtensions) && !extraExtensions.empty())
1263   {
1264     CStdStringArray exts;
1265     StringUtils::SplitString(extraExtensions,"|",exts);
1266     for (unsigned int i=0;i<exts.size();++i)
1267     {
1268       int iPos = extensions.Find(exts[i]);
1269       if (iPos == -1)
1270         continue;
1271       extensions.erase(iPos,exts[i].size()+1);
1272     }
1273   }
1274 }
1275
1276 void CAdvancedSettings::AddSettingsFile(const CStdString &filename)
1277 {
1278   m_settingsFiles.push_back(filename);
1279 }
1280
1281 float CAdvancedSettings::GetDisplayLatency(float refreshrate)
1282 {
1283   float delay = m_videoDefaultLatency / 1000.0f;
1284   for (int i = 0; i < (int) m_videoRefreshLatency.size(); i++)
1285   {
1286     RefreshVideoLatency& videolatency = m_videoRefreshLatency[i];
1287     if (refreshrate >= videolatency.refreshmin && refreshrate <= videolatency.refreshmax)
1288       delay = videolatency.delay / 1000.0f;
1289   }
1290
1291   return delay; // in seconds
1292 }
1293
1294 void CAdvancedSettings::SetDebugMode(bool debug)
1295 {
1296   if (debug)
1297   {
1298     int level = std::max(m_logLevelHint, LOG_LEVEL_DEBUG_FREEMEM);
1299     m_logLevel = level;
1300     CLog::SetLogLevel(level);
1301     CLog::Log(LOGNOTICE, "Enabled debug logging due to GUI setting. Level %d.", level);
1302   }
1303   else
1304   {
1305     int level = std::min(m_logLevelHint, LOG_LEVEL_DEBUG/*LOG_LEVEL_NORMAL*/);
1306     CLog::Log(LOGNOTICE, "Disabled debug logging due to GUI setting. Level %d.", level);
1307     m_logLevel = level;
1308     CLog::SetLogLevel(level);
1309   }
1310 }
1311
1312 void CAdvancedSettings::SetExtraLogsFromAddon(ADDON::IAddon* addon)
1313 {
1314   m_extraLogLevels = 0;
1315   for (int i=LOGMASKBIT;i<31;++i)
1316   {
1317     CStdString str;
1318     str.Format("bit%i", i-LOGMASKBIT+1);
1319     if (addon->GetSetting(str) == "true")
1320       m_extraLogLevels |= (1 << i);
1321   }
1322   CLog::SetExtraLogLevels(m_extraLogLevels);
1323 }