fixed: Make sure Destroy() is called on shutdown in win32.
[xbmc:xbmc-antiquated.git] / XBMC / xbmc / Application.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://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 "Application.h"
24 #include "KeyboardLayoutConfiguration.h"
25 #include "Util.h"
26 #include "TextureManager.h"
27 #include "cores/PlayerCoreFactory.h"
28 #include "cores/dvdplayer/DVDFileInfo.h"
29 #include "PlayListPlayer.h"
30 #include "MusicDatabase.h"
31 #include "VideoDatabase.h"
32 #include "Autorun.h"
33 #include "ActionManager.h"
34 #ifdef HAS_LCD
35 #include "utils/LCDFactory.h"
36 #else
37 #include "GUILabelControl.h"  // needed for CInfoLabel
38 #include "GUIImage.h"
39 #endif
40 #include "XBVideoConfig.h"
41 #include "LangCodeExpander.h"
42 #include "utils/GUIInfoManager.h"
43 #include "PlayListFactory.h"
44 #include "GUIFontManager.h"
45 #include "GUIColorManager.h"
46 #include "SkinInfo.h"
47 #ifdef HAS_PYTHON
48 #include "lib/libPython/XBPython.h"
49 #endif
50 #include "ButtonTranslator.h"
51 #include "GUIAudioManager.h"
52 #include "lib/libscrobbler/scrobbler.h"
53 #include "GUIPassword.h"
54 #include "ApplicationMessenger.h"
55 #include "SectionLoader.h"
56 #include "cores/DllLoader/DllLoaderContainer.h"
57 #include "GUIUserMessages.h"
58 #include "FileSystem/DirectoryCache.h"
59 #include "FileSystem/StackDirectory.h"
60 #include "FileSystem/DllLibCurl.h"
61 #include "FileSystem/CMythSession.h"
62 #ifdef HAS_FILESYSTEM_SAP
63 #include "FileSystem/SAPDirectory.h"
64 #endif
65 #include "utils/TuxBoxUtil.h"
66 #include "utils/SystemInfo.h"
67 #include "ApplicationRenderer.h"
68 #include "GUILargeTextureManager.h"
69 #include "LastFmManager.h"
70 #include "SmartPlaylist.h"
71 #include "FileSystem/RarManager.h"
72 #include "PlayList.h"
73 #include "Surface.h"
74
75 #if defined(FILESYSTEM) && !defined(_LINUX)
76 #include "FileSystem/FileDAAP.h"
77 #endif
78 #ifdef HAS_UPNP
79 #include "UPnP.h"
80 #include "FileSystem/UPnPDirectory.h"
81 #endif
82 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
83 #include "FileSystem/SMBDirectory.h"
84 #endif
85 #include "PartyModeManager.h"
86 #ifdef HAS_VIDEO_PLAYBACK
87 #include "cores/VideoRenderers/RenderManager.h"
88 #endif
89 #ifdef HAS_KARAOKE
90 #include "CdgParser.h"
91 #endif
92 #include "AudioContext.h"
93 #include "GUIFontTTF.h"
94 #include "utils/Network.h"
95 #ifndef _LINUX
96 #include "utils/Win32Exception.h"
97 #endif
98 #ifdef HAS_WEB_SERVER
99 #include "lib/libGoAhead/XBMChttp.h"
100 #include "lib/libGoAhead/WebServer.h"
101 #endif
102 #ifdef HAS_FTP_SERVER
103 #include "lib/libfilezilla/xbfilezilla.h"
104 #endif
105 #ifdef HAS_TIME_SERVER
106 #include "utils/Sntp.h"
107 #endif
108 #ifdef HAS_XFONT
109 #include <xfont.h>  // for textout functions
110 #endif
111 #ifdef HAS_EVENT_SERVER
112 #include "utils/EventServer.h"
113 #endif
114
115 // Windows includes
116 #include "GUIWindowManager.h"
117 #include "GUIWindowHome.h"
118 #include "GUIStandardWindow.h"
119 #include "GUIWindowSettings.h"
120 #include "GUIWindowFileManager.h"
121 #include "GUIWindowSettingsCategory.h"
122 #include "GUIWindowMusicPlaylist.h"
123 #include "GUIWindowMusicSongs.h"
124 #include "GUIWindowMusicNav.h"
125 #include "GUIWindowMusicPlaylistEditor.h"
126 #include "GUIWindowVideoPlaylist.h"
127 #include "GUIWindowMusicInfo.h"
128 #include "GUIWindowVideoInfo.h"
129 #include "GUIWindowVideoFiles.h"
130 #include "GUIWindowVideoNav.h"
131 #include "GUIWindowSettingsProfile.h"
132 #include "GUIWindowTestPattern.h"
133 #include "GUIWindowSettingsScreenCalibration.h"
134 #include "GUIWindowPrograms.h"
135 #include "GUIWindowPictures.h"
136 #include "GUIWindowScripts.h"
137 #include "GUIWindowWeather.h"
138 #include "GUIWindowLoginScreen.h"
139 #include "GUIWindowVisualisation.h"
140 #include "GUIWindowSystemInfo.h"
141 #include "GUIWindowScreensaver.h"
142 #include "GUIWindowSlideShow.h"
143 #include "GUIWindowStartup.h"
144 #include "GUIWindowFullScreen.h"
145 #include "GUIWindowOSD.h"
146 #include "GUIWindowMusicOverlay.h"
147 #include "GUIWindowVideoOverlay.h"
148
149 // Dialog includes
150 #include "GUIDialogMusicOSD.h"
151 #include "GUIDialogVisualisationSettings.h"
152 #include "GUIDialogVisualisationPresetList.h"
153 #include "GUIWindowScriptsInfo.h"
154 #include "GUIDialogNetworkSetup.h"
155 #include "GUIDialogMediaSource.h"
156 #include "GUIDialogVideoSettings.h"
157 #include "GUIDialogAudioSubtitleSettings.h"
158 #include "GUIDialogVideoBookmarks.h"
159 #include "GUIDialogProfileSettings.h"
160 #include "GUIDialogLockSettings.h"
161 #include "GUIDialogContentSettings.h"
162 #include "GUIDialogVideoScan.h"
163 #include "GUIDialogBusy.h"
164
165 #include "GUIDialogKeyboard.h"
166 #include "GUIDialogYesNo.h"
167 #include "GUIDialogOK.h"
168 #include "GUIDialogProgress.h"
169 #include "GUIDialogSelect.h"
170 #include "GUIDialogFileStacking.h"
171 #include "GUIDialogNumeric.h"
172 #include "GUIDialogGamepad.h"
173 #include "GUIDialogSubMenu.h"
174 #include "GUIDialogFavourites.h"
175 #include "GUIDialogButtonMenu.h"
176 #include "GUIDialogContextMenu.h"
177 #include "GUIDialogMusicScan.h"
178 #include "GUIDialogPlayerControls.h"
179 #include "GUIDialogSongInfo.h"
180 #include "GUIDialogSmartPlaylistEditor.h"
181 #include "GUIDialogSmartPlaylistRule.h"
182 #include "GUIDialogPictureInfo.h"
183 #include "GUIDialogPluginSettings.h"
184 #ifdef HAS_LINUX_NETWORK
185 #include "GUIDialogAccessPoints.h"
186 #endif
187 #include "GUIDialogFullScreenInfo.h"
188
189 #ifdef HAS_PERFORMACE_SAMPLE
190 #include "utils/PerformanceSample.h"
191 #else
192 #define MEASURE_FUNCTION
193 #endif
194
195 #ifdef HAS_SDL_AUDIO
196 #include <SDL/SDL_mixer.h>
197 #endif
198 #if defined(HAS_SDL) && defined(_WIN32)
199 #include <SDL/SDL_syswm.h>
200 #endif
201 #ifdef _WIN32
202 #include <shlobj.h>
203 #include <win32/MockXboxSymbols.h>
204 #include "win32util.h"
205 #endif
206 #ifdef HAS_XRANDR
207 #include "XRandR.h"
208 #endif
209 #ifdef __APPLE__
210 #include "CocoaUtils.h"
211 #include "XBMCHelper.h"
212 #endif
213 #ifdef HAS_HAL
214 #include "linux/LinuxFileSystem.h"
215 #endif
216 #ifdef HAS_EVENT_SERVER
217 #include "utils/EventServer.h"
218 #endif
219
220 #include "lib/libcdio/logging.h"
221
222 using namespace std;
223 using namespace XFILE;
224 using namespace DIRECTORY;
225 using namespace MEDIA_DETECT;
226 using namespace PLAYLIST;
227 using namespace VIDEO;
228 using namespace MUSIC_INFO;
229 #ifdef HAS_EVENT_SERVER
230 using namespace EVENTSERVER;
231 #endif
232
233 // uncomment this if you want to use release libs in the debug build.
234 // Atm this saves you 7 mb of memory
235 #define USE_RELEASE_LIBS
236
237 #if defined(_WIN32)
238  #if defined(_DEBUG) && !defined(USE_RELEASE_LIBS)
239   #if defined(HAS_FILESYSTEM)
240     #pragma comment (lib,"../../xbmc/lib/libXBMS/libXBMSd.lib")    // SECTIONNAME=LIBXBMS
241     #pragma comment (lib,"../../xbmc/lib/libxdaap/libxdaapd.lib") // SECTIONNAME=LIBXDAAP
242     #pragma comment (lib,"../../xbmc/lib/libRTV/libRTVd_win32.lib")
243   #endif
244   #pragma comment (lib,"../../xbmc/lib/libGoAhead/goahead_win32d.lib") // SECTIONNAME=LIBHTTP
245   #pragma comment (lib,"../../xbmc/lib/sqLite/libSQLite3_win32d.lib")
246   #pragma comment (lib,"../../xbmc/lib/libshout/libshout_win32d.lib" )
247   #pragma comment (lib,"../../xbmc/lib/libcdio/libcdio_win32d.lib" )
248   #pragma comment (lib,"../../xbmc/lib/libiconv/libiconvd.lib")
249   #pragma comment (lib,"../../xbmc/lib/libfribidi/libfribidid.lib")
250   #pragma comment (lib,"../../xbmc/lib/libpcre/libpcred.lib")
251  #else
252   #ifdef HAS_FILESYSTEM
253     #pragma comment (lib,"../../xbmc/lib/libXBMS/libXBMS.lib")
254     #pragma comment (lib,"../../xbmc/lib/libxdaap/libxdaap.lib")
255     #pragma comment (lib,"../../xbmc/lib/libRTV/libRTV_win32.lib")
256   #endif
257   #pragma comment (lib,"../../xbmc/lib/libGoAhead/goahead_win32.lib")
258   #pragma comment (lib,"../../xbmc/lib/sqLite/libSQLite3_win32.lib")
259   #pragma comment (lib,"../../xbmc/lib/libshout/libshout_win32.lib" )
260   #pragma comment (lib,"../../xbmc/lib/libcdio/libcdio_win32.lib" )
261   #pragma comment (lib,"../../xbmc/lib/libiconv/libiconv.lib")
262   #pragma comment (lib,"../../xbmc/lib/libfribidi/libfribidi.lib")
263   #pragma comment (lib,"../../xbmc/lib/libpcre/libpcre.lib")
264  #endif
265 #endif
266
267 #define MAX_FFWD_SPEED 5
268
269 CStdString g_LoadErrorStr;
270
271 CBackgroundPlayer::CBackgroundPlayer(const CFileItem &item, int iPlayList) : m_iPlayList(iPlayList)
272 {
273   m_item = new CFileItem;
274   *m_item = item;
275 }
276
277 CBackgroundPlayer::~CBackgroundPlayer()
278 {
279 }
280
281 void CBackgroundPlayer::Process()
282 {
283   g_application.PlayMediaSync(*m_item, m_iPlayList);
284 }
285
286 //extern IDirectSoundRenderer* m_pAudioDecoder;
287 CApplication::CApplication(void) : m_ctrDpad(220, 220), m_itemCurrentFile(new CFileItem)
288 {
289   m_iPlaySpeed = 1;
290 #ifdef HAS_WEB_SERVER
291   m_pWebServer = NULL;
292   m_pXbmcHttp = NULL;
293   m_prevMedia="";
294 #endif
295   m_pFileZilla = NULL;
296   m_pPlayer = NULL;
297   m_bScreenSave = false;
298   m_iScreenSaveLock = 0;
299 #ifdef __APPLE__
300   m_dwOSXscreensaverTicks = timeGetTime();
301 #endif
302   m_dwSkinTime = 0;
303   m_bInitializing = true;
304   m_eForcedNextPlayer = EPC_NONE;
305   m_strPlayListFile = "";
306   m_nextPlaylistItem = -1;
307   m_playCountUpdated = false;
308   m_bPlaybackStarting = false;
309
310   //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
311   m_bIsPaused = false;
312
313   /* for now allways keep this around */
314 #ifdef HAS_KARAOKE
315   m_pCdgParser = new CCdgParser();
316 #endif
317   m_currentStack = new CFileItemList;
318
319 #ifdef HAS_SDL
320   m_frameCount = 0;
321   m_frameMutex = SDL_CreateMutex();
322   m_frameCond = SDL_CreateCond();
323 #endif
324
325   m_bPresentFrame = false;
326   m_bPlatformDirectories = false;
327
328   m_bStandalone = false;
329   m_bEnableLegacyRes = false;
330   m_restartLirc = false;
331   m_restartLCD = false;
332 }
333
334 CApplication::~CApplication(void)
335 {
336   delete m_currentStack;
337
338   if (m_frameMutex)
339     SDL_DestroyMutex(m_frameMutex);
340
341   if (m_frameCond)
342     SDL_DestroyCond(m_frameCond);
343 }
344
345 // text out routine for below
346 #ifdef HAS_XFONT
347 static void __cdecl FEH_TextOut(XFONT* pFont, int iLine, const wchar_t* fmt, ...)
348 {
349   wchar_t buf[100];
350   va_list args;
351   va_start(args, fmt);
352   _vsnwprintf(buf, 100, fmt, args);
353   va_end(args);
354
355   if (!(iLine & 0x8000))
356     CLog::Log(LOGFATAL, "%S", buf);
357
358   bool Center = (iLine & 0x10000) > 0;
359   pFont->SetTextAlignment(Center ? XFONT_TOP | XFONT_CENTER : XFONT_TOP | XFONT_LEFT);
360
361   iLine &= 0x7fff;
362
363   for (int i = 0; i < 2; i++)
364   {
365     D3DRECT rc = { 0, 50 + 25 * iLine, 720, 50 + 25 * (iLine + 1) };
366     D3DDevice::Clear(1, &rc, D3DCLEAR_TARGET, 0, 0, 0);
367     pFont->TextOut(g_application.m_pBackBuffer, buf, -1, Center ? 360 : 80, 50 + 25*iLine);
368     D3DDevice::Present(0, 0, 0, 0);
369   }
370 }
371 #endif
372
373 HWND g_hWnd = NULL;
374
375 void CApplication::InitBasicD3D()
376 {
377 #ifndef HAS_SDL
378   bool bPal = g_videoConfig.HasPAL();
379   CLog::Log(LOGINFO, "Init display in default mode: %s", bPal ? "PAL" : "NTSC");
380   // init D3D with defaults (NTSC or PAL standard res)
381   m_d3dpp.BackBufferWidth = 720;
382   m_d3dpp.BackBufferHeight = bPal ? 576 : 480;
383   m_d3dpp.BackBufferFormat = D3DFMT_LIN_X8R8G8B8;
384   m_d3dpp.BackBufferCount = 1;
385   m_d3dpp.EnableAutoDepthStencil = FALSE;
386   m_d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
387   m_d3dpp.FullScreen_PresentationInterval = 0;
388   m_d3dpp.Windowed = TRUE;
389   m_d3dpp.hDeviceWindow = g_hWnd;
390
391   if (!(m_pD3D = Direct3DCreate8(D3D_SDK_VERSION)))
392   {
393     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to create Direct3D!");
394     Sleep(INFINITE); // die
395   }
396 #endif
397
398   // Check if we have the required modes available
399 #ifndef HAS_SDL
400   g_videoConfig.GetModes(m_pD3D);
401 #else
402   g_videoConfig.GetModes();
403 #endif
404   if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
405   {
406     // Oh uh - doesn't look good for starting in their wanted screenmode
407     CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
408     g_guiSettings.m_LookAndFeelResolution = g_videoConfig.GetSafeMode();
409     CLog::Log(LOGERROR, "Resetting to mode %s", g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution].strMode);
410     CLog::Log(LOGERROR, "Done reset");
411   }
412
413   // Transfer the resolution information to our graphics context
414 #ifndef HAS_SDL
415   g_graphicsContext.SetD3DParameters(&m_d3dpp);
416 #endif
417   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
418
419   // Create the device
420 #if !defined(HAS_SDL)
421   if (m_pD3D->CreateDevice(0, D3DDEVTYPE_REF, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &m_d3dpp, &m_pd3dDevice) != S_OK)
422   {
423     CLog::Log(LOGFATAL, "FATAL ERROR: Unable to create D3D Device!");
424     Sleep(INFINITE); // die
425   }
426 #endif
427
428   if (m_splash)
429   {
430 #ifndef HAS_SDL_OPENGL
431     m_splash->Stop();
432 #else
433     m_splash->Hide();
434 #endif
435   }
436
437 #ifndef HAS_SDL
438
439   m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0, 0);
440   m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
441 #endif
442 }
443
444 // This function does not return!
445 void CApplication::FatalErrorHandler(bool InitD3D, bool MapDrives, bool InitNetwork)
446 {
447   // XBMC couldn't start for some reason...
448   // g_LoadErrorStr should contain the reason
449   CLog::Log(LOGWARNING, "Emergency recovery console starting...");
450
451   fprintf(stderr, "Fatal error encountered, aborting\n");
452   fprintf(stderr, "Error log at %sxbmc.log\n", g_stSettings.m_logFolder.c_str());
453   abort();
454 }
455
456 #ifndef _LINUX
457 LONG WINAPI CApplication::UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
458 {
459   PCSTR pExceptionString = "Unknown exception code";
460
461 #define STRINGIFY_EXCEPTION(code) case code: pExceptionString = #code; break
462
463   switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
464   {
465     STRINGIFY_EXCEPTION(EXCEPTION_ACCESS_VIOLATION);
466     STRINGIFY_EXCEPTION(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
467     STRINGIFY_EXCEPTION(EXCEPTION_BREAKPOINT);
468     STRINGIFY_EXCEPTION(EXCEPTION_FLT_DENORMAL_OPERAND);
469     STRINGIFY_EXCEPTION(EXCEPTION_FLT_DIVIDE_BY_ZERO);
470     STRINGIFY_EXCEPTION(EXCEPTION_FLT_INEXACT_RESULT);
471     STRINGIFY_EXCEPTION(EXCEPTION_FLT_INVALID_OPERATION);
472     STRINGIFY_EXCEPTION(EXCEPTION_FLT_OVERFLOW);
473     STRINGIFY_EXCEPTION(EXCEPTION_FLT_STACK_CHECK);
474     STRINGIFY_EXCEPTION(EXCEPTION_ILLEGAL_INSTRUCTION);
475     STRINGIFY_EXCEPTION(EXCEPTION_INT_DIVIDE_BY_ZERO);
476     STRINGIFY_EXCEPTION(EXCEPTION_INT_OVERFLOW);
477     STRINGIFY_EXCEPTION(EXCEPTION_INVALID_DISPOSITION);
478     STRINGIFY_EXCEPTION(EXCEPTION_NONCONTINUABLE_EXCEPTION);
479     STRINGIFY_EXCEPTION(EXCEPTION_SINGLE_STEP);
480   }
481 #undef STRINGIFY_EXCEPTION
482
483   g_LoadErrorStr.Format("%s (0x%08x)\n at 0x%08x",
484                         pExceptionString, ExceptionInfo->ExceptionRecord->ExceptionCode,
485                         ExceptionInfo->ExceptionRecord->ExceptionAddress);
486
487   CLog::Log(LOGFATAL, "%s", g_LoadErrorStr.c_str());
488
489   return ExceptionInfo->ExceptionRecord->ExceptionCode;
490 }
491 #endif
492
493 extern "C" void __stdcall init_emu_environ();
494 extern "C" void __stdcall update_emu_environ();
495
496 //
497 // Utility function used to copy files from the application bundle
498 // over to the user data directory in Application Support/XBMC.
499 //
500 static void CopyUserDataIfNeeded(CStdString strPath, LPCTSTR file)
501 {
502   strPath.append(PATH_SEPARATOR_STRING);
503   strPath.append(file);
504   if (access(strPath.c_str(), 0) == -1)
505   {
506     CStdString srcFile = _P("q:\\userdata\\");
507     srcFile.append(file);
508 #ifdef _WIN32PC
509     CStdStringW srcFileW,strPathW;
510     g_charsetConverter.utf8ToW(srcFile, srcFileW, false);
511     g_charsetConverter.utf8ToW(strPath, strPathW, false);
512     CopyFileW(srcFileW, strPathW, TRUE);
513 #else
514     CopyFile(srcFile.c_str(), strPath.c_str(), TRUE);
515 #endif 
516   }
517 }
518
519 HRESULT CApplication::Create(HWND hWnd)
520 {
521   g_guiSettings.Initialize();  // Initialize default Settings
522   g_settings.Initialize(); //Initialize default AdvancedSettings
523
524 #ifdef _LINUX
525   tzset();   // Initialize timezone information variables
526 #endif
527
528   g_hWnd = hWnd;
529
530 #ifndef HAS_SDL
531   HRESULT hr = S_OK;
532 #endif
533
534   // Grab a handle to our thread to be used later in identifying the render thread.
535   m_threadID = GetCurrentThreadId();
536
537 #ifndef _LINUX
538   //floating point precision to 24 bits (faster performance)
539   _controlfp(_PC_24, _MCW_PC);
540
541
542   /* install win32 exception translator, win32 exceptions
543    * can now be caught using c++ try catch */
544   win32_exception::install_handler();
545 #endif
546
547   CProfile *profile;
548
549   // only the InitDirectories* for the current platform should return
550   // non-null (if at all i.e. to set a profile)
551   // putting this before the first log entries saves another ifdef for g_stSettings.m_logFolder
552   profile = InitDirectoriesLinux();
553   if (!profile)
554     profile = InitDirectoriesOSX();
555   if (!profile)
556     profile = InitDirectoriesWin32();
557   if (profile)
558   {
559     profile->setName("Master user");
560     profile->setLockMode(LOCK_MODE_EVERYONE);
561     profile->setLockCode("");
562     profile->setDate("");
563     g_settings.m_vecProfiles.push_back(*profile);
564     delete profile;
565   }
566
567   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
568 #if defined(_LINUX) && !defined(__APPLE__)
569   CLog::Log(LOGNOTICE, "Starting XBMC, Platform: GNU/Linux.  Built on %s (SVN:%s)", __DATE__, SVN_REV);
570 #elif defined(__APPLE__)
571   CLog::Log(LOGNOTICE, "Starting XBMC, Platform: Mac OS X.  Built on %s", __DATE__);
572 #elif defined(_WIN32)
573   CLog::Log(LOGNOTICE, "Starting XBMC, Platform: %s.  Built on %s (compiler %i)",g_sysinfo.GetKernelVersion().c_str(), __DATE__, _MSC_VER);
574   CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
575   CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
576 #endif
577   CLog::Log(LOGNOTICE, "Q is mapped to: %s", _P("Q:").c_str());
578   char szXBEFileName[1024];
579   CIoSupport::GetXbePath(szXBEFileName);
580   CLog::Log(LOGNOTICE, "The executable running is: %s", szXBEFileName);
581   CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_stSettings.m_logFolder.c_str());
582   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
583
584   CStdString strExecutablePath;
585   CUtil::GetHomePath(strExecutablePath);
586
587   // if we are running from DVD our UserData location will be TDATA
588   if (CUtil::IsDVD(strExecutablePath))
589   {
590     // TODO: Should we copy over any UserData folder from the DVD?
591     if (!CFile::Exists("T:\\guisettings.xml")) // first run - cache userdata folder
592     {
593       CFileItemList items;
594       CUtil::GetRecursiveListing("q:\\userdata",items,"");
595       for (int i=0;i<items.Size();++i)
596           CFile::Cache(items[i]->m_strPath,"T:\\"+CUtil::GetFileName(items[i]->m_strPath));
597     }
598     g_settings.m_vecProfiles[0].setDirectory("T:\\");
599     g_stSettings.m_logFolder = "T:\\";
600   }
601
602 #ifdef HAS_XRANDR
603   g_xrandr.LoadCustomModeLinesToAllOutputs();
604 #endif
605
606   // Init our DllLoaders emu env
607   init_emu_environ();
608
609
610 #ifndef HAS_SDL
611   CLog::Log(LOGNOTICE, "Setup DirectX");
612   // Create the Direct3D object
613   if ( NULL == ( m_pD3D = Direct3DCreate8(D3D_SDK_VERSION) ) )
614   {
615     CLog::Log(LOGFATAL, "XBAppEx: Unable to create Direct3D!" );
616     return E_FAIL;
617   }
618 #else
619   CLog::Log(LOGNOTICE, "Setup SDL");
620
621   /* Clean up on exit, exit on window close and interrupt */
622   atexit(SDL_Quit);
623
624   Uint32 sdlFlags = SDL_INIT_VIDEO;
625
626 #ifdef HAS_SDL_AUDIO
627   sdlFlags |= SDL_INIT_AUDIO;
628 #endif
629
630 #ifdef HAS_SDL_JOYSTICK
631   sdlFlags |= SDL_INIT_JOYSTICK;
632 #endif
633
634
635 #ifdef _LINUX
636   // for nvidia cards - vsync currently ALWAYS enabled.
637   // the reason is that after screen has been setup changing this env var will make no difference.
638   setenv("__GL_SYNC_TO_VBLANK", "1", 0);
639   setenv("__GL_YIELD", "USLEEP", 0);
640 #endif
641
642   if (SDL_Init(sdlFlags) != 0)
643   {
644         CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
645         return E_FAIL;
646   }
647
648
649   // for python scripts that check the OS
650 #ifdef __APPLE__
651   setenv("OS","OS X",true);
652 #elif defined(_LINUX)
653   SDL_WM_SetIcon(IMG_Load(_P("Q:/media/icon.png")), NULL);
654   setenv("OS","Linux",true);
655 #else
656   SDL_WM_SetIcon(IMG_Load(_P("Q:/media/icon.png")), NULL);
657 #endif
658 #endif
659
660   //list available videomodes
661 #ifndef HAS_SDL
662   g_videoConfig.GetModes(m_pD3D);
663   //init the present parameters with values that are supported
664   RESOLUTION initialResolution = g_videoConfig.GetInitialMode(m_pD3D, &m_d3dpp);
665   g_graphicsContext.SetD3DParameters(&m_d3dpp);
666 #else
667   g_videoConfig.GetModes();
668   //init the present parameters with values that are supported
669   RESOLUTION initialResolution = g_videoConfig.GetInitialMode();
670 #endif
671
672   // Initialize core peripheral port support. Note: If these parameters
673   // are 0 and NULL, respectively, then the default number and types of
674   // controllers will be initialized.
675
676 #if defined(HAS_SDL) && defined(_WIN32)
677   SDL_SysWMinfo wmInfo;
678   SDL_VERSION(&wmInfo.version)
679   int te = SDL_GetWMInfo( &wmInfo );
680   g_hWnd = wmInfo.window;
681 #endif
682
683   // Create the Mouse and Keyboard devices
684   g_Mouse.Initialize(&hWnd);
685   g_Keyboard.Initialize(hWnd);
686 #ifdef HAS_LIRC
687   g_RemoteControl.Initialize();
688 #endif
689 #ifdef HAS_SDL_JOYSTICK
690   g_Joystick.Initialize(hWnd);
691 #endif
692
693 #ifdef HAS_GAMEPAD
694   //Check for LTHUMBCLICK+RTHUMBCLICK and BLACK+WHITE, no LTRIGGER+RTRIGGER
695   if (((m_DefaultGamepad.wButtons & (XINPUT_GAMEPAD_LEFT_THUMB + XINPUT_GAMEPAD_RIGHT_THUMB)) && !(m_DefaultGamepad.wButtons & (KEY_BUTTON_LEFT_TRIGGER+KEY_BUTTON_RIGHT_TRIGGER))) ||
696       ((m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE]) && !(m_DefaultGamepad.wButtons & KEY_BUTTON_LEFT_TRIGGER+KEY_BUTTON_RIGHT_TRIGGER)))
697   {
698     CLog::Log(LOGINFO, "Key combination detected for userdata deletion (LTHUMB+RTHUMB or BLACK+WHITE)");
699     InitBasicD3D();
700     // D3D is up, load default font
701     XFONT* pFont;
702     if (XFONT_OpenDefaultFont(&pFont) != S_OK)
703     {
704       CLog::Log(LOGFATAL, "FATAL ERROR: Unable to open default font!");
705       Sleep(INFINITE); // die
706     }
707     // defaults for text
708     pFont->SetBkMode(XFONT_OPAQUE);
709     pFont->SetBkColor(D3DCOLOR_XRGB(0, 0, 0));
710     pFont->SetTextColor(D3DCOLOR_XRGB(0xff, 0x20, 0x20));
711     int iLine = 0;
712     FEH_TextOut(pFont, iLine++, L"Key combination for userdata deletion detected!");
713     FEH_TextOut(pFont, iLine++, L"Are you sure you want to proceed?");
714     iLine++;
715     FEH_TextOut(pFont, iLine++, L"A for yes, any other key for no");
716     bool bAnyAnalogKey = false;
717     while (m_DefaultGamepad.wPressedButtons != XBGAMEPAD_NONE) // wait for user to let go of lclick + rclick
718     {
719       ReadInput();
720     }
721     while (m_DefaultGamepad.wPressedButtons == XBGAMEPAD_NONE && !bAnyAnalogKey)
722     {
723       ReadInput();
724       bAnyAnalogKey = m_DefaultGamepad.bPressedAnalogButtons[0] || m_DefaultGamepad.bPressedAnalogButtons[1] || m_DefaultGamepad.bPressedAnalogButtons[2] || m_DefaultGamepad.bPressedAnalogButtons[3] || m_DefaultGamepad.bPressedAnalogButtons[4] || m_DefaultGamepad.bPressedAnalogButtons[5] || m_DefaultGamepad.bPressedAnalogButtons[6] || m_DefaultGamepad.bPressedAnalogButtons[7];
725     }
726     if (m_DefaultGamepad.bPressedAnalogButtons[XINPUT_GAMEPAD_A])
727     {
728       CUtil::DeleteGUISettings();
729       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\database\\");
730       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\thumbnails\\");
731       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\playlists\\");
732       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\cache\\");
733       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\profiles\\");
734       CUtil::WipeDir(g_settings.GetUserDataFolder()+"\\visualisations\\");
735       CFile::Delete(g_settings.GetUserDataFolder()+"\\avpacksettings.xml");
736       g_settings.m_vecProfiles.erase(g_settings.m_vecProfiles.begin()+1,g_settings.m_vecProfiles.end());
737
738       g_settings.SaveProfiles( PROFILES_FILE );
739
740       char szXBEFileName[1024];
741
742       CIoSupport::GetXbePath(szXBEFileName);
743       CUtil::RunXBE(szXBEFileName);
744     }
745     m_pd3dDevice->Release();
746   }
747 #endif
748
749   CLog::Log(LOGINFO, "Drives are mapped");
750
751   CLog::Log(LOGNOTICE, "load settings...");
752   g_LoadErrorStr = "Unable to load settings";
753   g_settings.m_iLastUsedProfileIndex = g_settings.m_iLastLoadedProfileIndex;
754   if (g_settings.bUseLoginScreen && g_settings.m_iLastLoadedProfileIndex != 0)
755     g_settings.m_iLastLoadedProfileIndex = 0;
756
757   m_bAllSettingsLoaded = g_settings.Load(m_bXboxMediacenterLoaded, m_bSettingsLoaded);
758   if (!m_bAllSettingsLoaded)
759     FatalErrorHandler(true, true, true);
760
761   update_emu_environ();//apply the GUI settings
762
763   // Check for WHITE + Y for forced Error Handler (to recover if something screwy happens)
764 #ifdef HAS_GAMEPAD
765   if (m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_Y] && m_DefaultGamepad.bAnalogButtons[XINPUT_GAMEPAD_WHITE])
766   {
767     g_LoadErrorStr = "Key code detected for Error Recovery mode";
768     FatalErrorHandler(true, true, true);
769   }
770 #endif
771
772   //Check for X+Y - if pressed, set debug log mode and mplayer debuging on
773   CheckForDebugButtonCombo();
774
775 #ifdef __APPLE__
776   // Configure and possible manually start the helper.
777   g_xbmcHelper.Configure();
778 #endif
779
780   CStdString strHomePath = "Q:";
781   CLog::Log(LOGINFO, "Checking skinpath existence, and existence of keymap.xml:%s...", (strHomePath + "\\skin").c_str());
782   //CStdString keymapPath;
783
784   //keymapPath = g_settings.GetUserDataItem("Keymap.xml");
785
786   if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
787   {
788     // Oh uh - doesn't look good for starting in their wanted screenmode
789     CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
790     g_guiSettings.m_LookAndFeelResolution = initialResolution;
791   }
792   // Transfer the new resolution information to our graphics context
793 #if !defined(HAS_SDL)
794   m_d3dpp.Windowed = TRUE;
795   m_d3dpp.hDeviceWindow = g_hWnd;
796 #else
797 #define D3DCREATE_MULTITHREADED 0
798 #endif
799
800 #ifndef HAS_SDL
801   g_graphicsContext.SetD3DParameters(&m_d3dpp);
802 #endif
803   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE);
804
805   // TODO LINUX SDL - Check that the resolution is ok
806 #ifndef HAS_SDL
807   if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL,
808                                          D3DCREATE_MULTITHREADED | D3DCREATE_HARDWARE_VERTEXPROCESSING,
809                                          &m_d3dpp, &m_pd3dDevice ) ) )
810   {
811     // try software vertex processing
812     if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, NULL,
813                                           D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
814                                           &m_d3dpp, &m_pd3dDevice ) ) )
815     {
816       // and slow as arse reference processing
817       if ( FAILED( hr = m_pD3D->CreateDevice(0, D3DDEVTYPE_REF, NULL,
818                                             D3DCREATE_MULTITHREADED | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
819                                             &m_d3dpp, &m_pd3dDevice ) ) )
820       {
821
822         CLog::Log(LOGFATAL, "XBAppEx: Could not create D3D device!" );
823         CLog::Log(LOGFATAL, " width/height:(%ix%i)" , m_d3dpp.BackBufferWidth, m_d3dpp.BackBufferHeight);
824         CLog::Log(LOGFATAL, " refreshrate:%i" , m_d3dpp.FullScreen_RefreshRateInHz);
825         if (m_d3dpp.Flags & D3DPRESENTFLAG_WIDESCREEN)
826           CLog::Log(LOGFATAL, " 16:9 widescreen");
827         else
828           CLog::Log(LOGFATAL, " 4:3");
829
830         if (m_d3dpp.Flags & D3DPRESENTFLAG_INTERLACED)
831           CLog::Log(LOGFATAL, " interlaced");
832         if (m_d3dpp.Flags & D3DPRESENTFLAG_PROGRESSIVE)
833           CLog::Log(LOGFATAL, " progressive");
834         return hr;
835       }
836     }
837   }
838   g_graphicsContext.SetD3DDevice(m_pd3dDevice);
839   g_graphicsContext.CaptureStateBlock();
840   // set filters
841   g_graphicsContext.Get3DDevice()->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR /*g_stSettings.m_minFilter*/ );
842   g_graphicsContext.Get3DDevice()->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR /*g_stSettings.m_maxFilter*/ );
843   CUtil::InitGamma();
844 #endif
845
846   // set GUI res and force the clear of the screen
847   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution, TRUE, true);
848
849   // initialize our charset converter
850   g_charsetConverter.reset();
851
852   // Load the langinfo to have user charset <-> utf-8 conversion
853   CStdString strLanguage = g_guiSettings.GetString("locale.language");
854   strLanguage[0] = toupper(strLanguage[0]);
855
856   CStdString strLangInfoPath;
857   strLangInfoPath.Format("Q:\\language\\%s\\langinfo.xml", strLanguage.c_str());
858   strLangInfoPath = _P(strLangInfoPath);
859
860   CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
861   g_langInfo.Load(strLangInfoPath);
862
863   m_splash = new CSplash(_P("Q:\\media\\splash.png"));
864 #ifndef HAS_SDL_OPENGL
865   m_splash->Start();
866 #else
867   m_splash->Show();
868 #endif
869
870   CStdString strLanguagePath;
871   strLanguagePath.Format("Q:\\language\\%s\\strings.xml", strLanguage.c_str());
872   strLanguagePath = _P(strLanguagePath);
873
874   CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
875   if (!g_localizeStrings.Load(_P(strLanguagePath)))
876     FatalErrorHandler(false, false, true);
877
878   CLog::Log(LOGINFO, "load keymapping");
879   if (!g_buttonTranslator.Load())
880     FatalErrorHandler(false, false, true);
881
882   // check the skin file for testing purposes
883   CStdString strSkinBase = _P("Q:\\skin\\");
884   CStdString strSkinPath = strSkinBase + g_guiSettings.GetString("lookandfeel.skin");
885   CLog::Log(LOGINFO, "Checking skin version of: %s", g_guiSettings.GetString("lookandfeel.skin").c_str());
886   if (!g_SkinInfo.Check(strSkinPath))
887   {
888     // reset to the default skin (DEFAULT_SKIN)
889     CLog::Log(LOGINFO, "The above skin isn't suitable - checking the version of the default: %s", DEFAULT_SKIN);
890     strSkinPath = strSkinBase + DEFAULT_SKIN;
891     if (!g_SkinInfo.Check(strSkinPath))
892     {
893       g_LoadErrorStr.Format("No suitable skin version found.\nWe require at least version %5.4f \n", g_SkinInfo.GetMinVersion());
894       FatalErrorHandler(false, false, true);
895     }
896   }
897   int iResolution = g_graphicsContext.GetVideoResolution();
898   CLog::Log(LOGINFO, " GUI format %ix%i %s",
899             g_settings.m_ResInfo[iResolution].iWidth,
900             g_settings.m_ResInfo[iResolution].iHeight,
901             g_settings.m_ResInfo[iResolution].strMode);
902   m_gWindowManager.Initialize();
903
904 #ifdef HAS_PYTHON
905   g_actionManager.SetScriptActionCallback(&g_pythonParser);
906 #endif
907
908   // show recovery console on fatal error instead of freezing
909   CLog::Log(LOGINFO, "install unhandled exception filter");
910 #ifndef _LINUX
911   SetUnhandledExceptionFilter(UnhandledExceptionFilter);
912 #endif
913
914   g_Mouse.SetEnabled(g_guiSettings.GetBool("lookandfeel.enablemouse"));
915
916   return CXBApplicationEx::Create(hWnd);
917 }
918
919 CProfile* CApplication::InitDirectoriesLinux()
920 {
921 /*
922    The following is the directory mapping for Platform Specific Mode:
923
924    Q: => [read-only] system directory (/usr/share/xbmc)
925    U: => [read-write] user's directory that will override Q: system-wide
926          installations like skins, screensavers, etc.
927          ($HOME/.xbmc)
928          NOTE: XBMC will look in both Q:\skin and U:\skin for skins. Same
929          applies to screensavers, sounds, etc.
930    T: => [read-write] userdata of master profile. It will by default be
931          mapped to U:\userdata ($HOME/.xbmc/userdata)
932    P: => [read-write] current profile's userdata directory.
933          Generally T:\ for the master profile or T:\profiles\<profile_name>
934          for other profiles.
935
936    NOTE: All these root directories are lowercase. Some of the sub-directories
937          might be mixed case.
938 */
939
940 #if defined(_LINUX) && !defined(__APPLE__)
941   CProfile* profile = NULL;
942
943   CStdString userName;
944   if (getenv("USER"))
945     userName = getenv("USER");
946   else
947     userName = "root";
948
949   CStdString userHome;
950   if (getenv("HOME"))
951     userHome = getenv("HOME");
952   else
953     userHome = "/root";
954
955   CStdString xbmcDir;
956   xbmcDir.Format("/tmp/xbmc-%s", userName.c_str());
957
958   // Z: common for both
959   CIoSupport::RemapDriveLetter('Z',xbmcDir);
960   CreateDirectory(_P("Z:\\"), NULL);
961
962   if (m_bPlatformDirectories)
963   {
964     CStdString logDir = "/var/tmp/";
965     if (getenv("USER"))
966     {
967       logDir += getenv("USER");
968       logDir += "-";
969     }
970     g_stSettings.m_logFolder = logDir;
971
972     setenv("XBMC_HOME", INSTALL_PATH, 0);
973
974     CStdString str = INSTALL_PATH;
975     CIoSupport::RemapDriveLetter('Q', (char*) str.c_str());
976
977
978     // make the $HOME/.xbmc directory
979     CStdString xbmcHome = userHome + "/.xbmc";
980     CreateDirectory(xbmcHome, NULL);
981     CIoSupport::RemapDriveLetter('U', xbmcHome.c_str());
982
983     // make the $HOME/.xbmc/userdata directory
984     CStdString xbmcUserdata = xbmcHome + "/userdata";
985     CreateDirectory(xbmcUserdata.c_str(), NULL);
986     CIoSupport::RemapDriveLetter('T', xbmcUserdata.c_str());
987
988     xbmcDir = _P("u:\\skin");
989     CreateDirectory(xbmcDir.c_str(), NULL);
990
991     xbmcDir = _P("u:\\visualisations");
992     CreateDirectory(xbmcDir.c_str(), NULL);
993
994     xbmcDir = _P("u:\\screensavers");
995     CreateDirectory(xbmcDir.c_str(), NULL);
996
997     xbmcDir = _P("u:\\sounds");
998     CreateDirectory(xbmcDir.c_str(), NULL);
999
1000     xbmcDir = _P("u:\\system");
1001     CreateDirectory(xbmcDir.c_str(), NULL);
1002
1003     xbmcDir = _P("u:\\plugins");
1004     CreateDirectory(xbmcDir.c_str(), NULL);
1005     xbmcDir = _P("u:\\plugins\\video");
1006     CreateDirectory(xbmcDir.c_str(), NULL);
1007     xbmcDir = _P("u:\\plugins\\music");
1008     CreateDirectory(xbmcDir.c_str(), NULL);
1009     xbmcDir = _P("u:\\plugins\\pictures");
1010     CreateDirectory(xbmcDir.c_str(), NULL);
1011
1012     xbmcDir = _P("u:\\scripts");
1013     CreateDirectory(xbmcDir.c_str(), NULL);
1014     xbmcDir = _P("u:\\scripts\\My Scripts"); // FIXME: both scripts should be in 1 directory
1015     CreateDirectory(xbmcDir.c_str(), NULL);
1016
1017     xbmcDir = _P("u:\\scripts\\Common Scripts"); // FIXME:
1018     symlink( INSTALL_PATH "/scripts",  xbmcDir.c_str() );
1019
1020     // copy required files
1021     //CopyUserDataIfNeeded(_P("t:\\"), "Keymap.xml");  // Eventual FIXME.
1022     CopyUserDataIfNeeded(_P("t:\\"), "RssFeeds.xml");
1023     CopyUserDataIfNeeded(_P("t:\\"), "Lircmap.xml");
1024     CopyUserDataIfNeeded(_P("t:\\"), "LCD.xml");
1025   }
1026   else
1027   {
1028     CStdString strHomePath;
1029     CUtil::GetHomePath(strHomePath);
1030     setenv("XBMC_HOME", strHomePath.c_str(), 0);
1031
1032     CUtil::AddDirectorySeperator(strHomePath);
1033     g_stSettings.m_logFolder = strHomePath;
1034
1035     CIoSupport::RemapDriveLetter('Q', (char*)strHomePath.c_str());
1036     CIoSupport::RemapDriveLetter('T', _P("Q:\\userdata"));
1037     CIoSupport::RemapDriveLetter('U', _P("Q:"));
1038   }
1039
1040   g_settings.m_vecProfiles.clear();
1041   g_settings.LoadProfiles(_P( PROFILES_FILE ));
1042
1043   if (g_settings.m_vecProfiles.size()==0)
1044   {
1045     profile = new CProfile;
1046     profile->setDirectory(_P("t:\\"));
1047   }
1048   return profile;
1049 #else
1050   return NULL;
1051 #endif
1052 }
1053
1054 CProfile* CApplication::InitDirectoriesOSX()
1055 {
1056 #ifdef __APPLE__
1057   // these two lines should move elsewhere
1058   Cocoa_Initialize(this);
1059   // We're going to manually manage the screensaver.
1060   setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", true);
1061
1062   CProfile* profile = NULL;
1063
1064   // Z: common for both
1065   CIoSupport::RemapDriveLetter('Z',"/tmp/xbmc");
1066   CreateDirectory(_P("Z:\\"), NULL);
1067
1068   CStdString userHome;
1069   if (getenv("HOME"))
1070   {
1071     userHome = getenv("HOME");
1072   }
1073   else
1074   {
1075     userHome = "/root";
1076   }
1077
1078   // OSX always runs with m_bPlatformDirectories == true
1079   if (m_bPlatformDirectories)
1080   {
1081
1082     #ifdef __APPLE__
1083         CStdString logDir = userHome + "/Library/Logs/";
1084         g_stSettings.m_logFolder = logDir;
1085
1086         // //Library/Application\ Support/XBMC/
1087         CStdString install_path;
1088         CUtil::GetHomePath(install_path);
1089         setenv("XBMC_HOME", install_path.c_str(), 0);
1090         CIoSupport::RemapDriveLetter('Q', (char*) install_path.c_str());
1091
1092         // /Users/<username>/Library/Application Support/XBMC
1093         CStdString xbmcHome = userHome + "/Library/Application Support/XBMC";
1094         CreateDirectory(xbmcHome, NULL);
1095         CIoSupport::RemapDriveLetter('U', xbmcHome.c_str());
1096
1097         // /Users/<username>/Library/Application Support/XBMC/userdata
1098         CStdString xbmcUserdata = xbmcHome + "/userdata";
1099         CreateDirectory(xbmcUserdata, NULL);
1100         CIoSupport::RemapDriveLetter('T', xbmcUserdata.c_str());
1101     #else
1102         CStdString logDir = "/var/tmp/";
1103         if (getenv("USER"))
1104         {
1105           logDir += getenv("USER");
1106           logDir += "-";
1107         }
1108         g_stSettings.m_logFolder = logDir;
1109
1110         setenv("XBMC_HOME", INSTALL_PATH, 0);
1111         CStdString str = INSTALL_PATH;
1112         CIoSupport::RemapDriveLetter('Q', (char*) str.c_str());
1113
1114         // make the $HOME/.xbmc directory
1115         CStdString xbmcHome = userHome + "/.xbmc";
1116         CreateDirectory(xbmcHome, NULL);
1117         CIoSupport::RemapDriveLetter('U', xbmcHome.c_str());
1118
1119         // make the $HOME/.xbmc/userdata directory
1120         CStdString xbmcUserdata = xbmcHome + "/userdata";
1121         CreateDirectory(xbmcUserdata.c_str(), NULL);
1122         CIoSupport::RemapDriveLetter('T', xbmcUserdata.c_str());
1123     #endif
1124
1125
1126     CStdString xbmcDir;
1127     xbmcDir = _P("u:\\skin");
1128     CreateDirectory(xbmcDir.c_str(), NULL);
1129
1130     xbmcDir = _P("u:\\visualisations");
1131     CreateDirectory(xbmcDir.c_str(), NULL);
1132
1133     xbmcDir = _P("u:\\screensavers");
1134     CreateDirectory(xbmcDir.c_str(), NULL);
1135
1136     xbmcDir = _P("u:\\sounds");
1137     CreateDirectory(xbmcDir.c_str(), NULL);
1138
1139     xbmcDir = _P("u:\\system");
1140     CreateDirectory(xbmcDir.c_str(), NULL);
1141
1142     xbmcDir = _P("u:\\plugins");
1143     CreateDirectory(xbmcDir.c_str(), NULL);
1144     xbmcDir = _P("u:\\plugins\\video");
1145     CreateDirectory(xbmcDir.c_str(), NULL);
1146     xbmcDir = _P("u:\\plugins\\music");
1147     CreateDirectory(xbmcDir.c_str(), NULL);
1148     xbmcDir = _P("u:\\plugins\\pictures");
1149     CreateDirectory(xbmcDir.c_str(), NULL);
1150     xbmcDir = _P("u:\\plugins\\programs");
1151     CreateDirectory(xbmcDir.c_str(), NULL);
1152     
1153     xbmcDir = _P("u:\\scripts");
1154     CreateDirectory(xbmcDir.c_str(), NULL);
1155     xbmcDir = _P("u:\\scripts\\My Scripts"); // FIXME: both scripts should be in 1 directory
1156     CreateDirectory(xbmcDir.c_str(), NULL);
1157
1158     xbmcDir = _P("u:\\scripts\\Common Scripts"); // FIXME:
1159     #ifdef __APPLE__
1160         CStdString str = install_path + "/scripts";
1161         symlink( str.c_str(),  xbmcDir.c_str() );
1162     #else
1163         symlink( INSTALL_PATH "/scripts",  xbmcDir.c_str() );
1164     #endif
1165
1166     // copy required files
1167     //CopyUserDataIfNeeded(_P("t:\\"), "Keymap.xml");
1168     CopyUserDataIfNeeded(_P("t:\\"), "RssFeeds.xml");
1169     // this is wrong, CopyUserDataIfNeeded pulls from q:\\userdata, Lircmap.xml is in q:\\system
1170     CopyUserDataIfNeeded(_P("t:\\"), "Lircmap.xml");    
1171     CopyUserDataIfNeeded(_P("t:\\"), "LCD.xml");
1172   }
1173   else
1174   {
1175     CStdString strHomePath;
1176     CUtil::GetHomePath(strHomePath);
1177     setenv("XBMC_HOME", strHomePath.c_str(), 0);
1178
1179     CUtil::AddDirectorySeperator(strHomePath);
1180     g_stSettings.m_logFolder = strHomePath;
1181
1182     CIoSupport::RemapDriveLetter('Q', (char*)strHomePath.c_str());
1183     CIoSupport::RemapDriveLetter('T', _P("Q:\\userdata"));
1184     CIoSupport::RemapDriveLetter('U', _P("Q:"));
1185   }
1186
1187   g_settings.m_vecProfiles.clear();
1188   g_settings.LoadProfiles(_P( PROFILES_FILE ));
1189
1190   if (g_settings.m_vecProfiles.size()==0)
1191   {
1192     profile = new CProfile;
1193     profile->setDirectory(_P("t:\\"));
1194   }
1195   return profile;
1196 #else
1197   return NULL;
1198 #endif
1199 }
1200
1201 CProfile* CApplication::InitDirectoriesWin32()
1202 {
1203 #ifdef _WIN32PC
1204
1205   CProfile* profile = NULL;
1206   CStdString strExecutablePath;
1207   CStdString strWin32UserFolder,strPath;
1208
1209   CUtil::GetHomePath(strExecutablePath);
1210   SetEnvironmentVariable("XBMC_HOME", strExecutablePath.c_str());
1211
1212   if (m_bPlatformDirectories)
1213   {
1214     WCHAR szPath[MAX_PATH];
1215
1216     if(SUCCEEDED(SHGetFolderPathW(NULL,CSIDL_APPDATA|CSIDL_FLAG_CREATE,NULL,0,szPath)))
1217       g_charsetConverter.wToUTF8(szPath, strWin32UserFolder);
1218     else
1219       strWin32UserFolder = strExecutablePath;
1220
1221     // create user/app data/XBMC
1222     CUtil::AddFileToFolder(strWin32UserFolder,"XBMC",strPath);
1223     CDirectory::Create(strPath.c_str());
1224     // move log to platform dirs
1225     g_stSettings.m_logFolder = strPath;
1226     CUtil::AddSlashAtEnd(g_stSettings.m_logFolder);
1227     // create user/app data/XBMC/cache
1228     CUtil::AddFileToFolder(strPath,"cache",strPath);
1229     CDirectory::Create(strPath.c_str());
1230     CIoSupport::RemapDriveLetter('Z',strPath.c_str());
1231     // create user/app data/XBMC/UserData
1232     CUtil::AddFileToFolder(strWin32UserFolder,"XBMC\\userdata",strPath);
1233     CDirectory::Create(strPath.c_str());
1234     CIoSupport::RemapDriveLetter('T', strPath.c_str());
1235   }
1236   else
1237   {
1238     g_stSettings.m_logFolder = strExecutablePath;
1239     CUtil::AddSlashAtEnd(g_stSettings.m_logFolder);
1240     CUtil::AddFileToFolder(strExecutablePath,"cache",strPath);
1241     CIoSupport::RemapDriveLetter('Z',strPath.c_str());
1242     CDirectory::Create(_P("Z:\\"));
1243     CUtil::AddFileToFolder(strExecutablePath,"userdata",strPath);
1244     CIoSupport::RemapDriveLetter('T',strPath.c_str());
1245   }
1246
1247   CIoSupport::RemapDriveLetter('Q', (char*) strExecutablePath.c_str());
1248   CIoSupport::RemapDriveLetter('U', _P("Q:"));
1249
1250   g_settings.m_vecProfiles.clear();
1251   g_settings.LoadProfiles(_P(PROFILES_FILE));
1252
1253   if (m_bPlatformDirectories)
1254   {
1255     // See if the keymap file exists, and if not, copy it from our "virgin" one.
1256     //CopyUserDataIfNeeded(strPath, "Keymap.xml");
1257     CopyUserDataIfNeeded(strPath, "RssFeeds.xml");
1258     CopyUserDataIfNeeded(strPath, "favourites.xml");
1259     CopyUserDataIfNeeded(strPath, "IRSSmap.xml");
1260     CopyUserDataIfNeeded(strPath, "LCD.xml");
1261
1262     CUtil::AddFileToFolder(strWin32UserFolder,"XBMC\\userdata",strPath);
1263     SetEnvironmentVariable("XBMC_PROFILE_USERDATA",strPath.c_str());
1264     if (g_settings.m_vecProfiles.size()==0)
1265     {
1266       profile = new CProfile;
1267       profile->setDirectory(strPath.c_str());
1268     }
1269   }
1270   else
1271   {
1272     SetEnvironmentVariable("XBMC_PROFILE_USERDATA",_P("q:\\userdata"));
1273     if (g_settings.m_vecProfiles.size()==0)
1274     {
1275       profile = new CProfile;
1276       profile->setDirectory(_P("q:\\userdata"));
1277     }
1278   }
1279
1280     return profile;
1281 #else
1282   return NULL;
1283 #endif
1284
1285 }
1286
1287 HRESULT CApplication::Initialize()
1288 {
1289   // turn off cdio logging
1290   cdio_loglevel_default = CDIO_LOG_ERROR;
1291
1292   CLog::Log(LOGINFO, "creating subdirectories");
1293
1294   //CLog::Log(LOGINFO, "userdata folder: %s", g_stSettings.m_userDataFolder.c_str());
1295   CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
1296   CLog::Log(LOGINFO, "  recording folder:%s", g_guiSettings.GetString("mymusic.recordingpath",false).c_str());
1297   CLog::Log(LOGINFO, "  screenshots folder:%s", g_guiSettings.GetString("pictures.screenshotpath",false).c_str());
1298
1299   // UserData folder layout:
1300   // UserData/
1301   //   Database/
1302   //     CDDb/
1303   //   Thumbnails/
1304   //     Music/
1305   //       temp/
1306   //     0 .. F/
1307
1308   CreateDirectory(g_settings.GetUserDataFolder().c_str(), NULL);
1309   CreateDirectory(g_settings.GetProfileUserDataFolder().c_str(), NULL);
1310   g_settings.CreateProfileFolders();
1311
1312   CreateDirectory(g_settings.GetProfilesThumbFolder().c_str(),NULL);
1313
1314   CreateDirectory(_P("Z:\\temp"), NULL); // temp directory for python and dllGetTempPathA
1315   CreateDirectory(_P("Q:\\scripts"), NULL);
1316   CreateDirectory(_P("Q:\\plugins"), NULL);
1317   CreateDirectory(_P("Q:\\plugins\\music"), NULL);
1318   CreateDirectory(_P("Q:\\plugins\\video"), NULL);
1319   CreateDirectory(_P("Q:\\plugins\\pictures"), NULL);
1320   CreateDirectory(_P("Q:\\language"), NULL);
1321   CreateDirectory(_P("Q:\\visualisations"), NULL);
1322   CreateDirectory(_P("Q:\\sounds"), NULL);
1323   CreateDirectory(_P(g_settings.GetUserDataFolder()+"\\visualisations"),NULL);
1324
1325   // initialize network
1326   if (!m_bXboxMediacenterLoaded)
1327   {
1328     CLog::Log(LOGINFO, "using default network settings");
1329     g_guiSettings.SetString("network.ipaddress", "192.168.0.100");
1330     g_guiSettings.SetString("network.subnet", "255.255.255.0");
1331     g_guiSettings.SetString("network.gateway", "192.168.0.1");
1332     g_guiSettings.SetString("network.dns", "192.168.0.1");
1333     g_guiSettings.SetBool("servers.ftpserver", true);
1334     g_guiSettings.SetBool("servers.webserver", false);
1335     g_guiSettings.SetBool("locale.timeserver", false);
1336   }
1337
1338   StartServices();
1339
1340   m_gWindowManager.Add(new CGUIWindowHome);                     // window id = 0
1341
1342   CLog::Log(LOGNOTICE, "load default skin:[%s]", g_guiSettings.GetString("lookandfeel.skin").c_str());
1343   LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1344
1345   m_gWindowManager.Add(new CGUIWindowPrograms);                 // window id = 1
1346   m_gWindowManager.Add(new CGUIWindowPictures);                 // window id = 2
1347   m_gWindowManager.Add(new CGUIWindowFileManager);      // window id = 3
1348   m_gWindowManager.Add(new CGUIWindowVideoFiles);          // window id = 6
1349   m_gWindowManager.Add(new CGUIWindowSettings);                 // window id = 4
1350   m_gWindowManager.Add(new CGUIWindowSystemInfo);               // window id = 7
1351   m_gWindowManager.Add(new CGUIWindowTestPattern);      // window id = 8
1352   m_gWindowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
1353   m_gWindowManager.Add(new CGUIWindowSettingsCategory);         // window id = 12 slideshow:window id 2007
1354   m_gWindowManager.Add(new CGUIWindowScripts);                  // window id = 20
1355   m_gWindowManager.Add(new CGUIWindowVideoNav);                 // window id = 36
1356   m_gWindowManager.Add(new CGUIWindowVideoPlaylist);            // window id = 28
1357   m_gWindowManager.Add(new CGUIWindowLoginScreen);            // window id = 29
1358   m_gWindowManager.Add(new CGUIWindowSettingsProfile);          // window id = 34
1359   m_gWindowManager.Add(new CGUIDialogYesNo);              // window id = 100
1360   m_gWindowManager.Add(new CGUIDialogProgress);           // window id = 101
1361   m_gWindowManager.Add(new CGUIDialogKeyboard);           // window id = 103
1362   m_gWindowManager.Add(&m_guiDialogVolumeBar);          // window id = 104
1363   m_gWindowManager.Add(&m_guiDialogSeekBar);            // window id = 115
1364   m_gWindowManager.Add(new CGUIDialogSubMenu);            // window id = 105
1365   m_gWindowManager.Add(new CGUIDialogContextMenu);        // window id = 106
1366   m_gWindowManager.Add(&m_guiDialogKaiToast);           // window id = 107
1367   m_gWindowManager.Add(new CGUIDialogNumeric);            // window id = 109
1368   m_gWindowManager.Add(new CGUIDialogGamepad);            // window id = 110
1369   m_gWindowManager.Add(new CGUIDialogButtonMenu);         // window id = 111
1370   m_gWindowManager.Add(new CGUIDialogMusicScan);          // window id = 112
1371   m_gWindowManager.Add(new CGUIDialogPlayerControls);     // window id = 113
1372   m_gWindowManager.Add(new CGUIDialogMusicOSD);           // window id = 120
1373   m_gWindowManager.Add(new CGUIDialogVisualisationSettings);     // window id = 121
1374   m_gWindowManager.Add(new CGUIDialogVisualisationPresetList);   // window id = 122
1375   m_gWindowManager.Add(new CGUIDialogVideoSettings);             // window id = 123
1376   m_gWindowManager.Add(new CGUIDialogAudioSubtitleSettings);     // window id = 124
1377   m_gWindowManager.Add(new CGUIDialogVideoBookmarks);      // window id = 125
1378   // Don't add the filebrowser dialog - it's created and added when it's needed
1379   m_gWindowManager.Add(new CGUIDialogNetworkSetup);  // window id = 128
1380   m_gWindowManager.Add(new CGUIDialogMediaSource);   // window id = 129
1381   m_gWindowManager.Add(new CGUIDialogProfileSettings); // window id = 130
1382   m_gWindowManager.Add(new CGUIDialogVideoScan);      // window id = 133
1383   m_gWindowManager.Add(new CGUIDialogFavourites);     // window id = 134
1384   m_gWindowManager.Add(new CGUIDialogSongInfo);       // window id = 135
1385   m_gWindowManager.Add(new CGUIDialogSmartPlaylistEditor);       // window id = 136
1386   m_gWindowManager.Add(new CGUIDialogSmartPlaylistRule);       // window id = 137
1387   m_gWindowManager.Add(new CGUIDialogBusy);      // window id = 138
1388   m_gWindowManager.Add(new CGUIDialogPictureInfo);      // window id = 139
1389   m_gWindowManager.Add(new CGUIDialogPluginSettings);      // window id = 140
1390 #ifdef HAS_LINUX_NETWORK
1391   m_gWindowManager.Add(new CGUIDialogAccessPoints);      // window id = 141
1392 #endif
1393
1394   m_gWindowManager.Add(new CGUIDialogLockSettings); // window id = 131
1395
1396   m_gWindowManager.Add(new CGUIDialogContentSettings);        // window id = 132
1397
1398   m_gWindowManager.Add(new CGUIWindowMusicPlayList);          // window id = 500
1399   m_gWindowManager.Add(new CGUIWindowMusicSongs);             // window id = 501
1400   m_gWindowManager.Add(new CGUIWindowMusicNav);               // window id = 502
1401   m_gWindowManager.Add(new CGUIWindowMusicPlaylistEditor);    // window id = 503
1402
1403   m_gWindowManager.Add(new CGUIDialogSelect);             // window id = 2000
1404   m_gWindowManager.Add(new CGUIWindowMusicInfo);                // window id = 2001
1405   m_gWindowManager.Add(new CGUIDialogOK);                 // window id = 2002
1406   m_gWindowManager.Add(new CGUIWindowVideoInfo);                // window id = 2003
1407   m_gWindowManager.Add(new CGUIWindowScriptsInfo);              // window id = 2004
1408   m_gWindowManager.Add(new CGUIWindowFullScreen);         // window id = 2005
1409   m_gWindowManager.Add(new CGUIWindowVisualisation);      // window id = 2006
1410   m_gWindowManager.Add(new CGUIWindowSlideShow);          // window id = 2007
1411   m_gWindowManager.Add(new CGUIDialogFileStacking);       // window id = 2008
1412
1413   m_gWindowManager.Add(new CGUIWindowOSD);                // window id = 2901
1414   m_gWindowManager.Add(new CGUIWindowMusicOverlay);       // window id = 2903
1415   m_gWindowManager.Add(new CGUIWindowVideoOverlay);       // window id = 2904
1416   m_gWindowManager.Add(new CGUIWindowScreensaver);        // window id = 2900 Screensaver
1417   m_gWindowManager.Add(new CGUIWindowWeather);            // window id = 2600 WEATHER
1418   m_gWindowManager.Add(new CGUIWindowStartup);            // startup window (id 2999)
1419
1420   /* window id's 3000 - 3100 are reserved for python */
1421   m_ctrDpad.SetDelays(100, 500); //g_stSettings.m_iMoveDelayController, g_stSettings.m_iRepeatDelayController);
1422
1423   SAFE_DELETE(m_splash);
1424
1425   if (g_guiSettings.GetBool("masterlock.startuplock") &&
1426       g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE &&
1427      !g_settings.m_vecProfiles[0].getLockCode().IsEmpty())
1428   {
1429      g_passwordManager.CheckStartUpLock();
1430   }
1431
1432   // check if we should use the login screen
1433   if (g_settings.bUseLoginScreen)
1434   {
1435     m_gWindowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1436   }
1437   else
1438   {
1439     RESOLUTION res = INVALID;
1440     CStdString startupPath = g_SkinInfo.GetSkinPath("startup.xml", &res);
1441     int startWindow = g_guiSettings.GetInt("lookandfeel.startupwindow");
1442     // test for a startup window, and activate that instead of home
1443     if (CFile::Exists(startupPath) && (!g_SkinInfo.OnlyAnimateToHome() || startWindow == WINDOW_HOME))
1444     {
1445       m_gWindowManager.ActivateWindow(WINDOW_STARTUP);
1446     }
1447     else
1448     {
1449       // We need to Popup the WindowHome to initiate the GUIWindowManger for MasterCode popup dialog!
1450       // Then we can start the StartUpWindow! To prevent BlackScreen if the target Window is Protected with MasterCode!
1451       m_gWindowManager.ActivateWindow(WINDOW_HOME);
1452       if (startWindow != WINDOW_HOME)
1453         m_gWindowManager.ActivateWindow(startWindow);
1454     }
1455   }
1456
1457 #ifdef HAS_PYTHON
1458   g_pythonParser.bStartup = true;
1459 #endif
1460   g_sysinfo.Refresh();
1461
1462   CLog::Log(LOGINFO, "removing tempfiles");
1463   CUtil::RemoveTempFiles();
1464
1465   if (!m_bAllSettingsLoaded)
1466   {
1467     CLog::Log(LOGWARNING, "settings not correct, show dialog");
1468     CStdString test;
1469     CUtil::GetHomePath(test);
1470     CGUIDialogOK *dialog = (CGUIDialogOK *)m_gWindowManager.GetWindow(WINDOW_DIALOG_OK);
1471     if (dialog)
1472     {
1473       dialog->SetHeading(279);
1474       dialog->SetLine(0, "Error while loading settings");
1475       dialog->SetLine(1, test);
1476       dialog->SetLine(2, "");;
1477       dialog->DoModal();
1478     }
1479   }
1480
1481   //  Show mute symbol
1482   if (g_stSettings.m_nVolumeLevel == VOLUME_MINIMUM)
1483     Mute();
1484
1485   // if the user shutoff the xbox during music scan
1486   // restore the settings
1487   if (g_stSettings.m_bMyMusicIsScanning)
1488   {
1489     CLog::Log(LOGWARNING,"System rebooted during music scan! ... restoring UseTags and FindRemoteThumbs");
1490     RestoreMusicScanSettings();
1491   }
1492
1493   if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
1494   {
1495     CLog::Log(LOGNOTICE, "Updating video library on startup");
1496     CGUIDialogVideoScan *scanner = (CGUIDialogVideoScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1497     SScraperInfo info;
1498     VIDEO::SScanSettings settings;
1499     if (scanner && !scanner->IsScanning())
1500       scanner->StartScanning("",info,settings,false);
1501   }
1502
1503 #ifdef HAS_HAL
1504   g_HalManager.Initialize();
1505 #endif
1506
1507   if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
1508   {
1509     CLog::Log(LOGNOTICE, "Updating music library on startup");
1510     CGUIDialogMusicScan *scanner = (CGUIDialogMusicScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
1511     if (scanner && !scanner->IsScanning())
1512       scanner->StartScanning("");
1513   }
1514
1515   m_slowTimer.StartZero();
1516
1517 #ifdef __APPLE__
1518   g_xbmcHelper.CaptureAllInput();
1519 #endif
1520
1521   CLog::Log(LOGNOTICE, "initialize done");
1522
1523   m_bInitializing = false;
1524
1525   // final check for debugging combo
1526   CheckForDebugButtonCombo();
1527
1528   // reset our screensaver (starts timers etc.)
1529   ResetScreenSaver();
1530   return S_OK;
1531 }
1532
1533 void CApplication::StartWebServer()
1534 {
1535 #ifdef HAS_WEB_SERVER
1536   if (g_guiSettings.GetBool("servers.webserver") && m_network.IsAvailable())
1537   {
1538     CLog::Log(LOGNOTICE, "Webserver: Starting...");
1539 #ifdef _LINUX
1540     if (atoi(g_guiSettings.GetString("servers.webserverport")) < 1024 && geteuid() != 0)
1541     {
1542         CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
1543         return;
1544     }
1545 #endif
1546     CSectionLoader::Load("LIBHTTP");
1547 #if defined(HAS_LINUX_NETWORK) || defined(HAS_WIN32_NETWORK)
1548     if (m_network.GetFirstConnectedInterface())
1549     {
1550        m_pWebServer = new CWebServer();
1551        m_pWebServer->Start(m_network.GetFirstConnectedInterface()->GetCurrentIPAddress().c_str(), atoi(g_guiSettings.GetString("servers.webserverport")), _P("Q:\\web"), false);
1552     }
1553 #else
1554     m_pWebServer = new CWebServer();
1555     m_pWebServer->Start(m_network.m_networkinfo.ip, atoi(g_guiSettings.GetString("servers.webserverport")), _P("Q:\\web"), false);
1556 #endif
1557     if (m_pWebServer)
1558       m_pWebServer->SetPassword(g_guiSettings.GetString("servers.webserverpassword").c_str());
1559     if (m_pWebServer && m_pXbmcHttp && g_stSettings.m_HttpApiBroadcastLevel>=1)
1560       getApplicationMessenger().HttpApi("broadcastlevel; StartUp;1");
1561   }
1562 #endif
1563 }
1564
1565 void CApplication::StopWebServer()
1566 {
1567 #ifdef HAS_WEB_SERVER
1568   if (m_pWebServer)
1569   {
1570     CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1571     m_pWebServer->Stop();
1572     delete m_pWebServer;
1573     m_pWebServer = NULL;
1574     CSectionLoader::Unload("LIBHTTP");
1575     CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1576   }
1577 #endif
1578 }
1579
1580 void CApplication::StartFtpServer()
1581 {
1582 #ifdef HAS_FTP_SERVER
1583   if ( g_guiSettings.GetBool("servers.ftpserver") && m_network.IsAvailable() )
1584   {
1585     CLog::Log(LOGNOTICE, "XBFileZilla: Starting...");
1586     if (!m_pFileZilla)
1587     {
1588       CStdString xmlpath = _P("Q:\\System\\");
1589       // if user didn't upgrade properly,
1590       // check whether P:\\FileZilla Server.xml exists (UserData/FileZilla Server.xml)
1591       if (CFile::Exists(g_settings.GetUserDataItem("FileZilla Server.xml")))
1592         xmlpath = g_settings.GetUserDataFolder();
1593
1594       // check file size and presence
1595       CFile xml;
1596       if (xml.Open(xmlpath+"FileZilla Server.xml",true) && xml.GetLength() > 0)
1597       {
1598         m_pFileZilla = new CXBFileZilla(xmlpath);
1599         m_pFileZilla->Start(false);
1600       }
1601       else
1602       {
1603         // 'FileZilla Server.xml' does not exist or is corrupt,
1604         // falling back to ftp emergency recovery mode
1605         CLog::Log(LOGNOTICE, "XBFileZilla: 'FileZilla Server.xml' is missing or is corrupt!");
1606         CLog::Log(LOGNOTICE, "XBFileZilla: Starting ftp emergency recovery mode");
1607         StartFtpEmergencyRecoveryMode();
1608       }
1609       xml.Close();
1610     }
1611   }
1612 #endif
1613 }
1614
1615 void CApplication::StopFtpServer()
1616 {
1617 #ifdef HAS_FTP_SERVER
1618   if (m_pFileZilla)
1619   {
1620     CLog::Log(LOGINFO, "XBFileZilla: Stopping...");
1621
1622     std::vector<SXFConnection> mConnections;
1623     std::vector<SXFConnection>::iterator it;
1624
1625     m_pFileZilla->GetAllConnections(mConnections);
1626
1627     for(it = mConnections.begin();it != mConnections.end();it++)
1628     {
1629       m_pFileZilla->CloseConnection(it->mId);
1630     }
1631
1632     m_pFileZilla->Stop();
1633     delete m_pFileZilla;
1634     m_pFileZilla = NULL;
1635
1636     CLog::Log(LOGINFO, "XBFileZilla: Stopped");
1637   }
1638 #endif
1639 }
1640
1641 void CApplication::StartTimeServer()
1642 {
1643 #ifdef HAS_TIME_SERVER
1644   if (g_guiSettings.GetBool("locale.timeserver") && m_network.IsAvailable() )
1645   {
1646     if( !m_psntpClient )
1647     {
1648       CSectionLoader::Load("SNTP");
1649       CLog::Log(LOGNOTICE, "start timeserver client");
1650
1651       m_psntpClient = new CSNTPClient();
1652       m_psntpClient->Update();
1653     }
1654   }
1655 #endif
1656 }
1657
1658 void CApplication::StopTimeServer()
1659 {
1660 #ifdef HAS_TIME_SERVER
1661   if( m_psntpClient )
1662   {
1663     CLog::Log(LOGNOTICE, "stop time server client");
1664     SAFE_DELETE(m_psntpClient);
1665     CSectionLoader::Unload("SNTP");
1666   }
1667 #endif
1668 }
1669
1670 void CApplication::StartUPnP()
1671 {
1672 #ifdef HAS_UPNP
1673     StartUPnPClient();
1674     StartUPnPServer();
1675     StartUPnPRenderer();
1676 #endif
1677 }
1678
1679 void CApplication::StopUPnP()
1680 {
1681 #ifdef HAS_UPNP
1682   if (CUPnP::IsInstantiated())
1683   {
1684     CLog::Log(LOGNOTICE, "stopping upnp");
1685     CUPnP::ReleaseInstance();
1686   }
1687 #endif
1688 }
1689
1690 void CApplication::StartEventServer()
1691 {
1692 #ifdef HAS_EVENT_SERVER
1693   CEventServer* server = CEventServer::GetInstance();
1694   if (!server)
1695   {
1696     CLog::Log(LOGERROR, "ES: Out of memory");
1697     return;
1698   }
1699   if (g_guiSettings.GetBool("remoteevents.enabled"))
1700   {
1701     CLog::Log(LOGNOTICE, "ES: Starting event server");
1702     server->StartServer();
1703   }
1704 #endif
1705 }
1706
1707 bool CApplication::StopEventServer(bool promptuser)
1708 {
1709 #ifdef HAS_EVENT_SERVER
1710   CEventServer* server = CEventServer::GetInstance();
1711   if (!server)
1712   {
1713     CLog::Log(LOGERROR, "ES: Out of memory");
1714     return false;
1715   }
1716   if (promptuser)
1717   {
1718     if (server->GetNumberOfClients() > 0)
1719     {
1720       bool cancelled = false;
1721       if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1722                                             -1, -1, cancelled, 10000)
1723           || cancelled)
1724       {
1725         CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1726         return false;
1727       }
1728     }
1729     CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1730   }
1731   else
1732   {
1733     CLog::Log(LOGNOTICE, "ES: Stopping event server");
1734   }
1735   CEventServer::GetInstance()->StopServer();
1736   return true;
1737 #endif
1738 }
1739
1740 void CApplication::RefreshEventServer()
1741 {
1742 #ifdef HAS_EVENT_SERVER
1743   if (g_guiSettings.GetBool("remoteevents.enabled"))
1744   {
1745     CEventServer::GetInstance()->RefreshSettings();
1746   }
1747 #endif
1748 }
1749
1750 void CApplication::StartUPnPRenderer()
1751 {
1752 #ifdef HAS_UPNP
1753   if (g_guiSettings.GetBool("upnp.renderer"))
1754   {
1755     CLog::Log(LOGNOTICE, "starting upnp renderer");
1756     CUPnP::GetInstance()->StartRenderer();
1757   }
1758 #endif
1759 }
1760
1761 void CApplication::StopUPnPRenderer()
1762 {
1763 #ifdef HAS_UPNP
1764   if (CUPnP::IsInstantiated())
1765   {
1766     CLog::Log(LOGNOTICE, "stopping upnp renderer");
1767     CUPnP::GetInstance()->StopRenderer();
1768   }
1769 #endif
1770 }
1771
1772 void CApplication::StartUPnPClient()
1773 {
1774 #ifdef HAS_UPNP
1775   if (g_guiSettings.GetBool("upnp.client"))
1776   {
1777     CLog::Log(LOGNOTICE, "starting upnp client");
1778     CUPnP::GetInstance()->StartClient();
1779   }
1780 #endif
1781 }
1782
1783 void CApplication::StopUPnPClient()
1784 {
1785 #ifdef HAS_UPNP
1786   if (CUPnP::IsInstantiated())
1787   {
1788     CLog::Log(LOGNOTICE, "stopping upnp client");
1789     CUPnP::GetInstance()->StopClient();
1790   }
1791 #endif
1792 }
1793
1794 void CApplication::StartUPnPServer()
1795 {
1796 #ifdef HAS_UPNP
1797   if (g_guiSettings.GetBool("upnp.server"))
1798   {
1799     CLog::Log(LOGNOTICE, "starting upnp server");
1800     CUPnP::GetInstance()->StartServer();
1801   }
1802 #endif
1803 }
1804
1805 void CApplication::StopUPnPServer()
1806 {
1807 #ifdef HAS_UPNP
1808   if (CUPnP::IsInstantiated())
1809   {
1810     CLog::Log(LOGNOTICE, "stopping upnp server");
1811     CUPnP::GetInstance()->StopServer();
1812   }
1813 #endif
1814 }
1815
1816 void CApplication::DimLCDOnPlayback(bool dim)
1817 {
1818 #ifdef HAS_LCD
1819   if(g_lcd && dim && (g_guiSettings.GetInt("lcd.disableonplayback") != LED_PLAYBACK_OFF) && (g_guiSettings.GetInt("lcd.type") != LCD_TYPE_NONE))
1820   {
1821     if ( (IsPlayingVideo()) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_VIDEO)
1822       g_lcd->SetBackLight(0);
1823     if ( (IsPlayingAudio()) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_MUSIC)
1824       g_lcd->SetBackLight(0);
1825     if ( ((IsPlayingVideo() || IsPlayingAudio())) && g_guiSettings.GetInt("lcd.disableonplayback") == LED_PLAYBACK_VIDEO_MUSIC)
1826       g_lcd->SetBackLight(0);
1827   }
1828   else if(!dim)
1829 #ifdef _LINUX
1830     g_lcd->SetBackLight(1);
1831 #else
1832     g_lcd->SetBackLight(g_guiSettings.GetInt("lcd.backlight"));
1833 #endif
1834 #endif
1835 }
1836
1837 void CApplication::StartServices()
1838 {
1839   // Start Thread for DVD Mediatype detection
1840   CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1841   m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1842
1843   CLog::Log(LOGNOTICE, "initializing playlistplayer");
1844   g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_stSettings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1845   g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_stSettings.m_bMyMusicPlaylistShuffle);
1846   g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_stSettings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1847   g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_stSettings.m_bMyVideoPlaylistShuffle);
1848   CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1849
1850 #ifdef HAS_LCD
1851   CLCDFactory factory;
1852   g_lcd = factory.Create();
1853   if (g_lcd)
1854   {
1855     g_lcd->Initialize();
1856   }
1857 #endif
1858 }
1859
1860 void CApplication::StopServices()
1861 {
1862   m_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1863
1864   CLog::Log(LOGNOTICE, "stop dvd detect media");
1865   m_DetectDVDType.StopThread();
1866 }
1867
1868 void CApplication::DelayLoadSkin()
1869 {
1870   m_dwSkinTime = timeGetTime() + 2000;
1871   return ;
1872 }
1873
1874 void CApplication::CancelDelayLoadSkin()
1875 {
1876   m_dwSkinTime = 0;
1877 }
1878
1879 void CApplication::ReloadSkin()
1880 {
1881   CGUIMessage msg(GUI_MSG_LOAD_SKIN, (DWORD) -1, m_gWindowManager.GetActiveWindow());
1882   g_graphicsContext.SendMessage(msg);
1883   // Reload the skin, restoring the previously focused control
1884   CGUIWindow* pWindow = m_gWindowManager.GetWindow(m_gWindowManager.GetActiveWindow());
1885   unsigned iCtrlID = pWindow->GetFocusedControlID();
1886   g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1887   pWindow = m_gWindowManager.GetWindow(m_gWindowManager.GetActiveWindow());
1888   if (pWindow)
1889   {
1890     CGUIMessage msg3(GUI_MSG_SETFOCUS, m_gWindowManager.GetActiveWindow(), iCtrlID, 0);
1891     pWindow->OnMessage(msg3);
1892   }
1893 }
1894
1895 void CApplication::LoadSkin(const CStdString& strSkin)
1896 {
1897   bool bPreviousPlayingState=false;
1898   bool bPreviousRenderingState=false;
1899   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1900   {
1901     bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1902     if (bPreviousPlayingState)
1903       g_application.m_pPlayer->Pause();
1904 #ifdef HAS_VIDEO_PLAYBACK
1905     if (!g_renderManager.Paused())
1906     {
1907       if (m_gWindowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1908      {
1909         m_gWindowManager.ActivateWindow(WINDOW_HOME);
1910         bPreviousRenderingState = true;
1911       }
1912     }
1913 #endif
1914   }
1915   //stop the busy renderer if it's running before we lock the graphiccontext or we could deadlock.
1916   g_ApplicationRenderer.Stop();
1917   // close the music and video overlays (they're re-opened automatically later)
1918   CSingleLock lock(g_graphicsContext);
1919
1920   m_dwSkinTime = 0;
1921
1922   CStdString strHomePath;
1923   CStdString strSkinPath = g_settings.GetSkinFolder(strSkin);
1924
1925   CLog::Log(LOGINFO, "  load skin from:%s", strSkinPath.c_str());
1926
1927   // save the current window details
1928   int currentWindow = m_gWindowManager.GetActiveWindow();
1929   vector<DWORD> currentModelessWindows;
1930   m_gWindowManager.GetActiveModelessWindows(currentModelessWindows);
1931
1932   CLog::Log(LOGINFO, "  delete old skin...");
1933   UnloadSkin();
1934
1935   // Load in the skin.xml file if it exists
1936   g_SkinInfo.Load(strSkinPath);
1937
1938   CLog::Log(LOGINFO, "  load fonts for skin...");
1939   g_graphicsContext.SetMediaDir(strSkinPath);
1940   if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1941   {
1942     CLog::Log(LOGINFO, "    language needs a ttf font, loading first ttf font available");
1943     CStdString strFontSet;
1944     if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1945     {
1946       CLog::Log(LOGINFO, "    new font is '%s'", strFontSet.c_str());
1947       g_guiSettings.SetString("lookandfeel.font", strFontSet);
1948       g_settings.Save();
1949     }
1950     else
1951       CLog::Log(LOGERROR, "    no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1952   }
1953   g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1954
1955   g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1956
1957   // load in the skin strings
1958   CStdString skinPath, skinEnglishPath;
1959   CUtil::AddFileToFolder(strSkinPath, "language", skinPath);
1960   CUtil::AddFileToFolder(skinPath, g_guiSettings.GetString("locale.language"), skinPath);
1961   CUtil::AddFileToFolder(skinPath, "strings.xml", skinPath);
1962
1963   CUtil::AddFileToFolder(strSkinPath, "language", skinEnglishPath);
1964   CUtil::AddFileToFolder(skinEnglishPath, "English", skinEnglishPath);
1965   CUtil::AddFileToFolder(skinEnglishPath, "strings.xml", skinEnglishPath);
1966
1967   g_localizeStrings.LoadSkinStrings(skinPath, skinEnglishPath);
1968
1969   LARGE_INTEGER start;
1970   QueryPerformanceCounter(&start);
1971
1972   CLog::Log(LOGINFO, "  load new skin...");
1973   CGUIWindowHome *pHome = (CGUIWindowHome *)m_gWindowManager.GetWindow(WINDOW_HOME);
1974   if (!g_SkinInfo.Check(strSkinPath) || !pHome || !pHome->Load("Home.xml"))
1975   {
1976     // failed to load home.xml
1977     // fallback to default skin
1978     if ( strcmpi(strSkin.c_str(), DEFAULT_SKIN) != 0)
1979     {
1980       CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"%s\" skin", strSkin.c_str(), DEFAULT_SKIN);
1981       g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1982       LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1983       return ;
1984     }
1985   }
1986
1987   // Load the user windows
1988   LoadUserWindows(strSkinPath);
1989
1990   LARGE_INTEGER end, freq;
1991   QueryPerformanceCounter(&end);
1992   QueryPerformanceFrequency(&freq);
1993   CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end.QuadPart - start.QuadPart) / freq.QuadPart);
1994
1995   CLog::Log(LOGINFO, "  initialize new skin...");
1996   m_guiPointer.AllocResources(true);
1997   m_guiDialogVolumeBar.AllocResources(true);
1998   m_guiDialogSeekBar.AllocResources(true);
1999   m_guiDialogKaiToast.AllocResources(true);
2000   m_guiDialogMuteBug.AllocResources(true);
2001   m_gWindowManager.AddMsgTarget(this);
2002   m_gWindowManager.AddMsgTarget(&g_playlistPlayer);
2003   m_gWindowManager.AddMsgTarget(&g_infoManager);
2004   m_gWindowManager.SetCallback(*this);
2005   m_gWindowManager.Initialize();
2006   g_audioManager.Initialize(CAudioContext::DEFAULT_DEVICE);
2007   g_audioManager.Load();
2008
2009   CGUIDialogFullScreenInfo* pDialog = NULL;
2010   RESOLUTION res;
2011   CStdString strPath = g_SkinInfo.GetSkinPath("DialogFullScreenInfo.xml", &res);
2012   if (CFile::Exists(strPath))
2013     pDialog = new CGUIDialogFullScreenInfo;
2014
2015   if (pDialog)
2016     m_gWindowManager.Add(pDialog); // window id = 142
2017
2018   CLog::Log(LOGINFO, "  skin loaded...");
2019
2020   // leave the graphics lock
2021   lock.Leave();
2022   g_ApplicationRenderer.Start();
2023
2024   // restore windows
2025   if (currentWindow != WINDOW_INVALID)
2026   {
2027     m_gWindowManager.ActivateWindow(currentWindow);
2028     for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2029     {
2030       CGUIDialog *dialog = (CGUIDialog *)m_gWindowManager.GetWindow(currentModelessWindows[i]);
2031       if (dialog) dialog->Show();
2032     }
2033   }
2034
2035   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
2036   {
2037     if (bPreviousPlayingState)
2038       g_application.m_pPlayer->Pause();
2039     if (bPreviousRenderingState)
2040       m_gWindowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2041   }
2042 }
2043
2044 void CApplication::UnloadSkin()
2045 {
2046   g_ApplicationRenderer.Stop();
2047   g_audioManager.DeInitialize(CAudioContext::DEFAULT_DEVICE);
2048
2049   m_gWindowManager.DeInitialize();
2050
2051   //These windows are not handled by the windowmanager (why not?) so we should unload them manually
2052   CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
2053   m_guiPointer.OnMessage(msg);
2054   m_guiPointer.ResetControlStates();
2055   m_guiPointer.FreeResources(true);
2056   m_guiDialogMuteBug.OnMessage(msg);
2057   m_guiDialogMuteBug.ResetControlStates();
2058   m_guiDialogMuteBug.FreeResources(true);
2059
2060   // remove the skin-dependent window
2061   m_gWindowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2062
2063   CGUIWindow::FlushReferenceCache(); // flush the cache
2064
2065   g_TextureManager.Cleanup();
2066
2067   g_fontManager.Clear();
2068
2069   g_colorManager.Clear();
2070
2071   g_charsetConverter.reset();
2072
2073   g_infoManager.Clear();
2074 }
2075
2076 bool CApplication::LoadUserWindows(const CStdString& strSkinPath)
2077 {
2078   WIN32_FIND_DATA FindFileData;
2079   WIN32_FIND_DATA NextFindFileData;
2080   HANDLE hFind;
2081   TiXmlDocument xmlDoc;
2082   RESOLUTION resToUse = INVALID;
2083
2084   // Start from wherever home.xml is
2085   g_SkinInfo.GetSkinPath("Home.xml", &resToUse);
2086   std::vector<CStdString> vecSkinPath;
2087   if (resToUse == HDTV_1080i)
2088     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(HDTV_1080i));
2089   if (resToUse == HDTV_720p)
2090     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(HDTV_720p));
2091   if (resToUse == PAL_16x9 || resToUse == NTSC_16x9 || resToUse == HDTV_480p_16x9 || resToUse == HDTV_720p || resToUse == HDTV_1080i)
2092     vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(g_SkinInfo.GetDefaultWideResolution()));
2093   vecSkinPath.push_back(strSkinPath+g_SkinInfo.GetDirFromRes(g_SkinInfo.GetDefaultResolution()));
2094   for (unsigned int i=0;i<vecSkinPath.size();++i)
2095   {
2096     CStdString strPath;
2097 #ifndef _LINUX
2098     strPath.Format("%s\\%s", vecSkinPath[i], "custom*.xml");
2099 #else
2100     strPath.Format("%s/%s", vecSkinPath[i], "custom*.xml");
2101 #endif
2102     CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2103     hFind = FindFirstFile(strPath.c_str(), &NextFindFileData);
2104
2105     CStdString strFileName;
2106     while (hFind != INVALID_HANDLE_VALUE)
2107     {
2108       FindFileData = NextFindFileData;
2109
2110       if (!FindNextFile(hFind, &NextFindFileData))
2111       {
2112         FindClose(hFind);
2113         hFind = INVALID_HANDLE_VALUE;
2114       }
2115
2116       // skip "up" directories, which come in all queries
2117 #ifndef _LINUX
2118       if (!_tcscmp(FindFileData.cFileName, _T(".")) || !_tcscmp(FindFileData.cFileName, _T("..")))
2119         continue;
2120 #else
2121       if (!strcmp(FindFileData.cFileName, ".") || !strcmp(FindFileData.cFileName, ".."))
2122         continue;
2123 #endif
2124
2125 #ifndef _LINUX
2126       strFileName = vecSkinPath[i]+"\\"+FindFileData.cFileName;
2127 #else
2128       strFileName = vecSkinPath[i]+"/"+FindFileData.cFileName;
2129 #endif
2130       CLog::Log(LOGINFO, "Loading skin file: %s", strFileName.c_str());
2131       CStdString strLower(FindFileData.cFileName);
2132       strLower.MakeLower();
2133       strLower = vecSkinPath[i] + "/" + strLower;
2134       if (!xmlDoc.LoadFile(strFileName.c_str()) && !xmlDoc.LoadFile(strLower.c_str()))
2135       {
2136         CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", strFileName.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2137         continue;
2138       }
2139
2140       // Root element should be <window>
2141       TiXmlElement* pRootElement = xmlDoc.RootElement();
2142       CStdString strValue = pRootElement->Value();
2143       if (!strValue.Equals("window"))
2144       {
2145         CLog::Log(LOGERROR, "file :%s doesnt contain <window>", strFileName.c_str());
2146         continue;
2147       }
2148
2149       // Read the <type> element to get the window type to create
2150       // If no type is specified, create a CGUIWindow as default
2151       CGUIWindow* pWindow = NULL;
2152       CStdString strType;
2153       if (pRootElement->Attribute("type"))
2154         strType = pRootElement->Attribute("type");
2155       else
2156       {
2157         const TiXmlNode *pType = pRootElement->FirstChild("type");
2158         if (pType && pType->FirstChild())
2159           strType = pType->FirstChild()->Value();
2160       }
2161       if (strType.Equals("dialog"))
2162         pWindow = new CGUIDialog(0, "");
2163       else if (strType.Equals("submenu"))
2164         pWindow = new CGUIDialogSubMenu();
2165       else if (strType.Equals("buttonmenu"))
2166         pWindow = new CGUIDialogButtonMenu();
2167       else
2168         pWindow = new CGUIStandardWindow();
2169
2170       int id = WINDOW_INVALID;
2171       if (!pRootElement->Attribute("id", &id))
2172       {
2173         const TiXmlNode *pType = pRootElement->FirstChild("id");
2174         if (pType && pType->FirstChild())
2175           id = atol(pType->FirstChild()->Value());
2176       }
2177       // Check to make sure the pointer isn't still null
2178       if (pWindow == NULL || id == WINDOW_INVALID)
2179       {
2180         CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2181         return false;
2182       }
2183       if (m_gWindowManager.GetWindow(WINDOW_HOME + id))
2184       {
2185         delete pWindow;
2186         continue;
2187       }
2188       // set the window's xml file, and add it to the window manager.
2189       pWindow->SetXMLFile(FindFileData.cFileName);
2190       pWindow->SetID(WINDOW_HOME + id);
2191       m_gWindowManager.AddCustomWindow(pWindow);
2192     }
2193     CloseHandle(hFind);
2194   }
2195   return true;
2196 }
2197
2198 void CApplication::RenderNoPresent()
2199 {
2200   MEASURE_FUNCTION;
2201
2202   // don't do anything that would require graphiccontext to be locked before here in fullscreen.
2203   // that stuff should go into renderfullscreen instead as that is called from the renderin thread
2204
2205   // dont show GUI when playing full screen video
2206   if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && !IsPaused())
2207   {
2208     //g_ApplicationRenderer.Render();
2209
2210 #ifdef HAS_SDL
2211     if (g_videoConfig.GetVSyncMode()==VSYNC_VIDEO)
2212       g_graphicsContext.getScreenSurface()->EnableVSync(true);
2213 #endif
2214     // release the context so the async renderer can draw to it
2215 #ifdef HAS_SDL_OPENGL
2216     // Video rendering occuring from main thread for OpenGL
2217     if (m_bPresentFrame)
2218       g_renderManager.Present();
2219     else
2220       g_renderManager.RenderUpdate(true, 0, 255);
2221 #else
2222     //g_graphicsContext.ReleaseCurrentContext();
2223     g_graphicsContext.Unlock(); // unlock to allow the async renderer to render
2224     Sleep(25);
2225     g_graphicsContext.Lock();
2226 #endif
2227     ResetScreenSaver();
2228     g_infoManager.ResetCache();
2229     return;
2230   }
2231
2232   g_graphicsContext.AcquireCurrentContext();
2233
2234 #ifdef HAS_SDL
2235   if (g_videoConfig.GetVSyncMode()==VSYNC_ALWAYS)
2236     g_graphicsContext.getScreenSurface()->EnableVSync(true);
2237   else if (g_videoConfig.GetVSyncMode()!=VSYNC_DRIVER)
2238     g_graphicsContext.getScreenSurface()->EnableVSync(false);
2239 #endif
2240
2241   g_ApplicationRenderer.Render();
2242
2243 }
2244
2245 void CApplication::DoRender()
2246 {
2247 #ifndef HAS_SDL
2248   if(!m_pd3dDevice)
2249     return;
2250 #endif
2251
2252   g_graphicsContext.Lock();
2253
2254 #ifndef HAS_SDL
2255   m_pd3dDevice->BeginScene();
2256 #endif
2257
2258   m_gWindowManager.UpdateModelessVisibility();
2259
2260   // draw GUI
2261   g_graphicsContext.Clear();
2262   //SWATHWIDTH of 4 improves fillrates (performance investigator)
2263   m_gWindowManager.Render();
2264
2265
2266   // if we're recording an audio stream then show blinking REC
2267   if (!g_graphicsContext.IsFullScreenVideo())
2268   {
2269     if (m_pPlayer && m_pPlayer->IsRecording() )
2270     {
2271       static int iBlinkRecord = 0;
2272       iBlinkRecord++;
2273       if (iBlinkRecord > 25)
2274       {
2275         CGUIFont* pFont = g_fontManager.GetFont("font13");
2276         CGUITextLayout::DrawText(pFont, 60, 50, 0xffff0000, 0, "REC", 0);
2277       }
2278
2279       if (iBlinkRecord > 50)
2280         iBlinkRecord = 0;
2281     }
2282   }
2283
2284   // Now render any dialogs
2285   m_gWindowManager.RenderDialogs();
2286
2287   // Render the mouse pointer
2288   if (g_Mouse.IsActive())
2289   {
2290     m_guiPointer.Render();
2291   }
2292
2293   {
2294     // free memory if we got les then 10megs free ram
2295     MEMORYSTATUS stat;
2296     GlobalMemoryStatus(&stat);
2297     DWORD dwMegFree = (DWORD)(stat.dwAvailPhys / (1024 * 1024));
2298     if (dwMegFree <= 10)
2299     {
2300       g_TextureManager.Flush();
2301     }
2302
2303     // reset image scaling and effect states
2304     g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), 0, 0, false);
2305
2306     // If we have the remote codes enabled, then show them
2307     if (g_advancedSettings.m_displayRemoteCodes)
2308     {
2309 #ifdef HAS_IR_REMOTE
2310       XBIR_REMOTE* pRemote = &m_DefaultIR_Remote;
2311       static iRemoteCode = 0;
2312       static iShowRemoteCode = 0;
2313       if (pRemote->wButtons)
2314       {
2315         iRemoteCode = 255 - pRemote->wButtons; // remote OBC code is 255-wButtons
2316         iShowRemoteCode = 50;
2317       }
2318       if (iShowRemoteCode > 0)
2319       {
2320         CStdStringW wszText;
2321         wszText.Format(L"Remote Code: %i", iRemoteCode);
2322         float x = 0.08f * g_graphicsContext.GetWidth();
2323         float y = 0.12f * g_graphicsContext.GetHeight();
2324 #ifndef _DEBUG
2325         if (LOG_LEVEL_DEBUG_FREEMEM > g_advancedSettings.m_logLevel)
2326           y = 0.08f * g_graphicsContext.GetHeight();
2327 #endif
2328         CGUITextLayout::DrawOutlineText(g_fontManager.GetFont("font13"), x, y, 0xffffffff, 0xff000000, 2, wszText);
2329         iShowRemoteCode--;
2330       }
2331 #endif
2332     }
2333
2334     RenderMemoryStatus();
2335   }
2336
2337 #ifndef HAS_SDL
2338   m_pd3dDevice->EndScene();
2339 #endif
2340
2341   g_graphicsContext.Unlock();
2342
2343   // reset our info cache - we do this at the end of Render so that it is
2344   // fresh for the next process(), or after a windowclose animation (where process()
2345   // isn't called)
2346   g_infoManager.ResetCache();
2347 }
2348
2349 bool CApplication::WaitFrame(DWORD timeout)
2350 {
2351   bool done = false;
2352 #ifdef HAS_SDL
2353   // Wait for all other frames to be presented
2354   SDL_mutexP(m_frameMutex);
2355   if(m_frameCount > 0)
2356     SDL_CondWaitTimeout(m_frameCond, m_frameMutex, timeout);
2357   done = m_frameCount == 0;
2358   SDL_mutexV(m_frameMutex);
2359 #endif
2360   return done;
2361 }
2362
2363 void CApplication::NewFrame()
2364 {
2365 #ifdef HAS_SDL
2366   // We just posted another frame. Keep track and notify.
2367   SDL_mutexP(m_frameMutex);
2368   m_frameCount++;
2369   SDL_mutexV(m_frameMutex);
2370
2371   SDL_CondSignal(m_frameCond);
2372 #endif
2373 }
2374
2375 void CApplication::Render()
2376 {
2377   if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
2378   {
2379     Sleep(1);
2380     ResetScreenSaver();
2381     return;
2382   }
2383
2384   MEASURE_FUNCTION;
2385
2386   { // frame rate limiter (really bad, but it does the trick :p)
2387     static unsigned int lastFrameTime = 0;
2388     unsigned int currentTime = timeGetTime();
2389     int nDelayTime = 0;
2390     bool lowfps = m_bScreenSave && (m_screenSaverMode == "Black");
2391     unsigned int singleFrameTime = 10; // default limit 100 fps
2392
2393
2394     m_bPresentFrame = false;
2395     if (g_graphicsContext.IsFullScreenVideo() && !IsPaused())
2396     {
2397 #ifdef HAS_SDL
2398       SDL_mutexP(m_frameMutex);
2399
2400       // If we have frames or if we get notified of one, consume it.
2401       if (m_frameCount > 0 || SDL_CondWaitTimeout(m_frameCond, m_frameMutex, 100) == 0)
2402         m_bPresentFrame = true;
2403
2404       SDL_mutexV(m_frameMutex);
2405 #else
2406       m_bPresentFrame = true;
2407 #endif
2408     }
2409     else
2410     {
2411       // only "limit frames" if we are not using vsync.
2412       if (g_videoConfig.GetVSyncMode() != VSYNC_ALWAYS || lowfps)
2413       {
2414         if(lowfps)
2415           singleFrameTime *= 10;
2416
2417         if (lastFrameTime + singleFrameTime > currentTime)
2418           nDelayTime = lastFrameTime + singleFrameTime - currentTime;
2419         Sleep(nDelayTime);
2420       }
2421       else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000/singleFrameTime)
2422       {
2423         //The driver is ignoring vsync. Was set to ALWAYS, set to VIDEO. Framerate will be limited from next render.
2424         CLog::Log(LOGWARNING, "VSYNC ignored by driver, enabling framerate limiter.");
2425         g_videoConfig.SetVSyncMode(VSYNC_VIDEO);
2426       }
2427     }
2428
2429     lastFrameTime = timeGetTime();
2430   }
2431   g_graphicsContext.Lock();
2432   RenderNoPresent();
2433   // Present the backbuffer contents to the display
2434 #ifdef HAS_SDL
2435   g_graphicsContext.Flip();
2436 #else
2437   if (m_pd3dDevice) m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
2438 #endif
2439   g_graphicsContext.Unlock();
2440
2441 #ifdef HAS_SDL
2442   SDL_mutexP(m_frameMutex);
2443   if(m_frameCount > 0)
2444     m_frameCount--;
2445   SDL_mutexV(m_frameMutex);
2446   SDL_CondSignal(m_frameCond);
2447 #endif
2448 }
2449
2450 void CApplication::RenderMemoryStatus()
2451 {
2452   MEASURE_FUNCTION;
2453
2454   g_infoManager.UpdateFPS();
2455   g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
2456
2457   if (LOG_LEVEL_DEBUG_FREEMEM <= g_advancedSettings.m_logLevel)
2458   {
2459     // reset the window scaling and fade status
2460     RESOLUTION res = g_graphicsContext.GetVideoResolution();
2461     g_graphicsContext.SetRenderingResolution(res, 0, 0, false);
2462
2463     CStdString info;
2464     MEMORYSTATUS stat;
2465     GlobalMemoryStatus(&stat);
2466 #ifdef __APPLE__
2467     double dCPU = m_resourceCounter.GetCPUUsage();
2468     info.Format("FreeMem %ju/%ju MB, FPS %2.1f, CPU-Total %d%%. CPU-XBMC %4.2f%%", stat.dwAvailPhys/(1024*1024), stat.dwTotalPhys/(1024*1024),
2469               g_infoManager.GetFPS(), g_cpuInfo.getUsedPercentage(), dCPU);
2470 #elif !defined(_LINUX)
2471     CStdString strCores = g_cpuInfo.GetCoresUsageString();
2472     info.Format("FreeMem %d/%d Kb, FPS %2.1f, %s.", stat.dwAvailPhys/1024, stat.dwTotalPhys/1024, g_infoManager.GetFPS(), strCores.c_str());
2473 #else
2474     double dCPU = m_resourceCounter.GetCPUUsage();
2475     CStdString strCores = g_cpuInfo.GetCoresUsageString();
2476     info.Format("FreeMem %d/%d Kb, FPS %2.1f, %s. CPU-XBMC %4.2f%%", stat.dwAvailPhys/1024, stat.dwTotalPhys/1024,
2477               g_infoManager.GetFPS(), strCores.c_str(), dCPU);
2478 #endif
2479
2480     static int yShift = 20;
2481     static int xShift = 40;
2482     static unsigned int lastShift = time(NULL);
2483     time_t now = time(NULL);
2484     if (now - lastShift > 10)
2485     {
2486       yShift *= -1;
2487       if (now % 5 == 0)
2488         xShift *= -1;
2489       lastShift = now;
2490     }
2491
2492     float x = xShift + 0.04f * g_graphicsContext.GetWidth() + g_settings.m_ResInfo[res].Overscan.left;
2493     float y = yShift + 0.04f * g_graphicsContext.GetHeight() + g_settings.m_ResInfo[res].Overscan.top;
2494
2495     CGUITextLayout::DrawOutlineText(g_fontManager.GetFont("font13"), x, y, 0xffffffff, 0xff000000, 2, info);
2496   }
2497 }
2498 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2499 // The window manager will return true if the event is processed, false otherwise.
2500 // If not already processed, this routine handles global keypresses.  It returns
2501 // true if the key has been processed, false otherwise.
2502
2503 bool CApplication::OnKey(CKey& key)
2504 {
2505   // Turn the mouse off, as we've just got a keypress from controller or remote
2506   g_Mouse.SetInactive();
2507   CAction action;
2508   
2509   // get the current active window
2510   int iWin = m_gWindowManager.GetActiveWindow() & WINDOW_ID_MASK;
2511
2512   // this will be checked for certain keycodes that need 
2513   // special handling if the screensaver is active   
2514   g_buttonTranslator.GetAction(iWin, key, action);  
2515
2516   // a key has been pressed.
2517   // Reset the screensaver timer
2518   // but not for the analog thumbsticks/triggers
2519   if (!key.IsAnalogButton())
2520   {
2521     // reset Idle Timer
2522     m_idleTimer.StartZero();
2523     bool processKey = AlwaysProcess(action);
2524
2525     ResetScreenSaver();
2526
2527     // allow some keys to be processed while the screensaver is active
2528     if (ResetScreenSaverWindow() && !processKey)
2529     {
2530       g_Keyboard.Reset();
2531       return true;
2532     }
2533   }
2534
2535   // change this if we have a dialog up
2536   if (m_gWindowManager.HasModalDialog())
2537   {
2538     iWin = m_gWindowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2539   }
2540   if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2541   { // fullscreen info dialog - special case
2542     g_buttonTranslator.GetAction(iWin, key, action);
2543
2544 #ifdef HAS_SDL
2545     g_Keyboard.Reset();
2546 #endif
2547     if (OnAction(action))
2548       return true;
2549
2550     // fallthrough to the main window
2551     iWin = WINDOW_FULLSCREEN_VIDEO;
2552   }
2553   if (iWin == WINDOW_FULLSCREEN_VIDEO)
2554   {
2555     // current active window is full screen video.
2556     if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2557     {
2558       // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2559       g_buttonTranslator.GetAction(WINDOW_VIDEO_MENU, key, action);
2560     }
2561     else
2562     {
2563       // no then use the fullscreen window section of keymap.xml to map key->action
2564       g_buttonTranslator.GetAction(iWin, key, action);
2565     }
2566   }
2567   else
2568   {
2569     // current active window isnt the fullscreen window
2570     // just use corresponding section from keymap.xml
2571     // to map key->action
2572
2573     // first determine if we should use keyboard input directly
2574     bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2575     CGUIWindow *window = m_gWindowManager.GetWindow(iWin);
2576     if (window)
2577     {
2578       CGUIControl *control = window->GetFocusedControl();
2579       if (control && control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2580         useKeyboard = true;
2581     }
2582     if (useKeyboard)
2583     {
2584       if (key.GetFromHttpApi())
2585       {
2586         if (key.GetButtonCode() != KEY_INVALID)
2587           action.wID = (WORD) key.GetButtonCode();
2588         action.unicode = key.GetUnicode();
2589       }
2590       else
2591       { // see if we've got an ascii key
2592         if (g_Keyboard.GetUnicode())
2593         {
2594           action.wID = (WORD)g_Keyboard.GetAscii() | KEY_ASCII; // Only for backwards compatibility
2595           action.unicode = g_Keyboard.GetUnicode();
2596         }
2597         else
2598         {
2599           action.wID = (WORD)g_Keyboard.GetKey() | KEY_VKEY;
2600           action.unicode = 0;
2601         }
2602       }
2603 #ifdef HAS_SDL
2604       g_Keyboard.Reset();
2605 #endif
2606       if (OnAction(action))
2607         return true;
2608       // failed to handle the keyboard action, drop down through to standard action
2609     }
2610     if (key.GetFromHttpApi())
2611     {
2612       if (key.GetButtonCode() != KEY_INVALID)
2613       {
2614         action.wID = (WORD) key.GetButtonCode();
2615         g_buttonTranslator.GetAction(iWin, key, action);
2616       }
2617     }
2618     else
2619       g_buttonTranslator.GetAction(iWin, key, action);
2620   }
2621   if (!key.IsAnalogButton())
2622     CLog::Log(LOGDEBUG, "%s: %i pressed, action is %i", __FUNCTION__, (int) key.GetButtonCode(), action.wID);
2623
2624   //  Play a sound based on the action
2625   g_audioManager.PlayActionSound(action);
2626
2627 #ifdef HAS_SDL
2628   g_Keyboard.Reset();
2629 #endif
2630
2631   return OnAction(action);
2632 }
2633
2634 bool CApplication::OnAction(const CAction &action)
2635 {
2636 #ifdef HAS_WEB_SERVER
2637   // Let's tell the outside world about this action
2638   if (m_pXbmcHttp && g_stSettings.m_HttpApiBroadcastLevel>=2)
2639   {
2640     CStdString tmp;
2641     tmp.Format("%i",action.wID);
2642     getApplicationMessenger().HttpApi("broadcastlevel; OnAction:"+tmp+";2");
2643   }
2644 #endif
2645
2646   // special case for switching between GUI & fullscreen mode.
2647   if (action.wID == ACTION_SHOW_GUI)
2648   { // Switch to fullscreen mode if we can
2649     if (SwitchToFullScreen())
2650     {
2651       m_navigationTimer.StartZero();
2652       return true;
2653     }
2654   }
2655
2656   if (action.wID == ACTION_TOGGLE_FULLSCREEN)
2657   {
2658     g_graphicsContext.ToggleFullScreenRoot();
2659     return true;
2660   }
2661
2662   // in normal case
2663   // just pass the action to the current window and let it handle it
2664   if (m_gWindowManager.OnAction(action))
2665   {
2666     m_navigationTimer.StartZero();
2667     return true;
2668   }
2669
2670   // handle extra global presses
2671
2672   // screenshot : take a screenshot :)
2673   if (action.wID == ACTION_TAKE_SCREENSHOT)
2674   {
2675     CUtil::TakeScreenshot();
2676     return true;
2677   }
2678   // built in functions : execute the built-in
2679   if (action.wID == ACTION_BUILT_IN_FUNCTION)
2680   {
2681     CUtil::ExecBuiltIn(action.strAction);
2682     m_navigationTimer.StartZero();
2683     return true;
2684   }
2685
2686   // power down : turn off after 3 seconds of button down
2687   static bool PowerButtonDown = false;
2688   static DWORD PowerButtonCode;
2689   static DWORD MarkTime;
2690   if (action.wID == ACTION_POWERDOWN)
2691   {
2692     // Hold button for 3 secs to power down
2693     if (!PowerButtonDown)
2694     {
2695       MarkTime = GetTickCount();
2696       PowerButtonDown = true;
2697       PowerButtonCode = action.m_dwButtonCode;
2698     }
2699   }
2700   if (PowerButtonDown)
2701   {
2702     if (g_application.IsButtonDown(PowerButtonCode))
2703     {
2704       if (GetTickCount() >= MarkTime + 3000)
2705       {
2706         m_applicationMessenger.Shutdown();
2707         return true;
2708       }
2709     }
2710     else
2711       PowerButtonDown = false;
2712   }
2713   // show info : Shows the current video or song information
2714   if (action.wID == ACTION_SHOW_INFO)
2715   {
2716     g_infoManager.ToggleShowInfo();
2717     return true;
2718   }
2719
2720   // codec info : Shows the current song, video or picture codec information
2721   if (action.wID == ACTION_SHOW_CODEC)
2722   {
2723     g_infoManager.ToggleShowCodec();
2724     return true;
2725   }
2726
2727   if ((action.wID == ACTION_INCREASE_RATING || action.wID == ACTION_DECREASE_RATING) && IsPlayingAudio())
2728   {
2729     const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2730     if (tag)
2731     {
2732       *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2733       char rating = tag->GetRating();
2734       bool needsUpdate(false);
2735       if (rating > '0' && action.wID == ACTION_DECREASE_RATING)
2736       {
2737         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2738         needsUpdate = true;
2739       }
2740       else if (rating < '5' && action.wID == ACTION_INCREASE_RATING)
2741       {
2742         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2743         needsUpdate = true;
2744       }
2745       if (needsUpdate)
2746       {
2747         CMusicDatabase db;
2748         if (db.Open())      // OpenForWrite() ?
2749         {
2750           db.SetSongRating(m_itemCurrentFile->m_strPath, m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2751           db.Close();
2752         }
2753         // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2754         CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2755         g_graphicsContext.SendMessage(msg);
2756       }
2757     }
2758     return true;
2759   }
2760
2761   // stop : stops playing current audio song
2762   if (action.wID == ACTION_STOP)
2763   {
2764     StopPlaying();
2765     return true;
2766   }
2767
2768   // previous : play previous song from playlist
2769   if (action.wID == ACTION_PREV_ITEM)
2770   {
2771     // first check whether we're within 3 seconds of the start of the track
2772     // if not, we just revert to the start of the track
2773     if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2774     {
2775       SeekTime(0);
2776       SetPlaySpeed(1);
2777     }
2778     else
2779     {
2780       SaveCurrentFileSettings();
2781       g_playlistPlayer.PlayPrevious();
2782     }
2783     return true;
2784   }
2785
2786   // next : play next song from playlist
2787   if (action.wID == ACTION_NEXT_ITEM)
2788   {
2789     if (IsPlaying() && m_pPlayer->SkipNext())
2790       return true;
2791
2792     SaveCurrentFileSettings();
2793     g_playlistPlayer.PlayNext();
2794
2795     return true;
2796   }
2797
2798   if ( IsPlaying())
2799   {
2800     // OSD toggling
2801     if (action.wID == ACTION_SHOW_OSD)
2802     {
2803       if (IsPlayingVideo() && IsPlayingFullScreenVideo())
2804       {
2805         CGUIWindowOSD *pOSD = (CGUIWindowOSD *)m_gWindowManager.GetWindow(WINDOW_OSD);
2806         if (pOSD)
2807         {
2808           if (pOSD->IsDialogRunning())
2809             pOSD->Close();
2810           else
2811             pOSD->DoModal();
2812           return true;
2813         }
2814       }
2815     }
2816
2817     // pause : pauses current audio song
2818     if (action.wID == ACTION_PAUSE && m_iPlaySpeed == 1)
2819     {
2820       m_pPlayer->Pause();
2821       if (!m_pPlayer->IsPaused())
2822       { // unpaused - set the playspeed back to normal
2823         SetPlaySpeed(1);
2824       }
2825       if (!g_guiSettings.GetBool("lookandfeel.soundsduringplayback"))
2826         g_audioManager.Enable(m_pPlayer->IsPaused());
2827       return true;
2828     }
2829     if (!m_pPlayer->IsPaused())
2830     {
2831       // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2832       // if we are playing at normal speed, then allow play to pause
2833       if (action.wID == ACTION_PLAYER_PLAY || action.wID == ACTION_PAUSE)
2834       {
2835         if (m_iPlaySpeed != 1)
2836         {
2837           SetPlaySpeed(1);
2838         }
2839         else
2840         {
2841           m_pPlayer->Pause();
2842         }
2843         return true;
2844       }
2845       if (action.wID == ACTION_PLAYER_FORWARD || action.wID == ACTION_PLAYER_REWIND)
2846       {
2847         int iPlaySpeed = m_iPlaySpeed;
2848         if (action.wID == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2849           iPlaySpeed *= -2;
2850         else if (action.wID == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2851           iPlaySpeed /= 2;
2852         else if (action.wID == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2853           iPlaySpeed /= 2;
2854         else
2855           iPlaySpeed *= 2;
2856
2857         if (action.wID == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2858           iPlaySpeed = 1;
2859         if (iPlaySpeed > 32 || iPlaySpeed < -32)
2860           iPlaySpeed = 1;
2861
2862         SetPlaySpeed(iPlaySpeed);
2863         return true;
2864       }
2865       else if ((action.fAmount1 || GetPlaySpeed() != 1) && (action.wID == ACTION_ANALOG_REWIND || action.wID == ACTION_ANALOG_FORWARD))
2866       {
2867         // calculate the speed based on the amount the button is held down
2868         int iPower = (int)(action.fAmount1 * MAX_FFWD_SPEED + 0.5f);
2869         // returns 0 -> MAX_FFWD_SPEED
2870         int iSpeed = 1 << iPower;
2871         if (iSpeed != 1 && action.wID == ACTION_ANALOG_REWIND)
2872           iSpeed = -iSpeed;
2873         g_application.SetPlaySpeed(iSpeed);
2874         if (iSpeed == 1)
2875           CLog::Log(LOGDEBUG,"Resetting playspeed");
2876         return true;
2877       }
2878     }
2879     // allow play to unpause
2880     else
2881     {
2882       if (action.wID == ACTION_PLAYER_PLAY)
2883       {
2884         // unpause, and set the playspeed back to normal
2885         m_pPlayer->Pause();
2886         if (!g_guiSettings.GetBool("lookandfeel.soundsduringplayback"))
2887           g_audioManager.Enable(m_pPlayer->IsPaused());
2888
2889         g_application.SetPlaySpeed(1);
2890         return true;
2891       }
2892     }
2893   }
2894   if (action.wID == ACTION_MUTE)
2895   {
2896     Mute();
2897     return true;
2898   }
2899  
2900   if (action.wID == ACTION_TOGGLE_DIGITAL_ANALOG)
2901   { 
2902     if(g_guiSettings.GetInt("audiooutput.mode")==AUDIO_DIGITAL)
2903       g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG);
2904     else
2905       g_guiSettings.SetInt("audiooutput.mode", AUDIO_DIGITAL);
2906     g_application.Restart();
2907     if (m_gWindowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2908     {
2909       CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,m_gWindowManager.GetActiveWindow());
2910       m_gWindowManager.SendMessage(msg);
2911     }
2912     return true;
2913   }
2914
2915   // Check for global volume control
2916   if (action.fAmount1 && (action.wID == ACTION_VOLUME_UP || action.wID == ACTION_VOLUME_DOWN))
2917   {
2918     // increase or decrease the volume
2919     int volume = g_stSettings.m_nVolumeLevel + g_stSettings.m_dynamicRangeCompressionLevel;
2920
2921     // calculate speed so that a full press will equal 1 second from min to max
2922     float speed = float(VOLUME_MAXIMUM - VOLUME_MINIMUM);
2923     if( action.fRepeat )
2924       speed *= action.fRepeat;
2925     else
2926       speed /= 50; //50 fps
2927
2928     if (action.wID == ACTION_VOLUME_UP)
2929     {
2930       volume += (int)((float)fabs(action.fAmount1) * action.fAmount1 * speed);
2931     }
2932     else
2933     {
2934       volume -= (int)((float)fabs(action.fAmount1) * action.fAmount1 * speed);
2935     }
2936
2937     SetHardwareVolume(volume);
2938 #ifndef HAS_SDL_AUDIO
2939     g_audioManager.SetVolume(g_stSettings.m_nVolumeLevel);
2940 #else
2941     g_audioManager.SetVolume((int)(128.f * (g_stSettings.m_nVolumeLevel - VOLUME_MINIMUM) / (float)(VOLUME_MAXIMUM - VOLUME_MINIMUM)));
2942 #endif
2943
2944     // show visual feedback of volume change...
2945     m_guiDialogVolumeBar.Show();
2946     m_guiDialogVolumeBar.OnAction(action);
2947     return true;
2948   }
2949   // Check for global seek control
2950   if (IsPlaying() && action.fAmount1 && (action.wID == ACTION_ANALOG_SEEK_FORWARD || action.wID == ACTION_ANALOG_SEEK_BACK))
2951   {
2952     if (!m_pPlayer->CanSeek()) return false;
2953     CScrobbler::GetInstance()->SetSubmitSong(false);  // Do not submit songs to Audioscrobbler when seeking, see CheckAudioScrobblerStatus()
2954     m_guiDialogSeekBar.OnAction(action);
2955     return true;
2956   }
2957   return false;
2958 }
2959
2960 void CApplication::UpdateLCD()
2961 {