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