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