Merge pull request #567 from Montellese/jsonrpc_12279
[vuplus_xbmc] / xbmc / Application.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "threads/SystemClock.h"
23 #include "system.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
28 #include "input/KeyboardLayoutConfiguration.h"
29 #include "LangInfo.h"
30 #include "Util.h"
31 #include "pictures/Picture.h"
32 #include "guilib/TextureManager.h"
33 #include "cores/dvdplayer/DVDFileInfo.h"
34 #include "PlayListPlayer.h"
35 #include "Autorun.h"
36 #include "video/Bookmark.h"
37 #ifdef HAS_WEB_SERVER
38 #include "network/WebServer.h"
39 #endif
40 #ifdef HAS_LCD
41 #include "utils/LCDFactory.h"
42 #endif
43 #include "guilib/GUIControlProfiler.h"
44 #include "utils/LangCodeExpander.h"
45 #include "GUIInfoManager.h"
46 #include "playlists/PlayListFactory.h"
47 #include "guilib/GUIFontManager.h"
48 #include "guilib/GUIColorManager.h"
49 #include "guilib/GUITextLayout.h"
50 #include "addons/Skin.h"
51 #ifdef HAS_PYTHON
52 #include "interfaces/python/XBPython.h"
53 #endif
54 #include "input/ButtonTranslator.h"
55 #include "guilib/GUIAudioManager.h"
56 #include "network/libscrobbler/lastfmscrobbler.h"
57 #include "network/libscrobbler/librefmscrobbler.h"
58 #include "GUIPassword.h"
59 #include "input/InertialScrollingHandler.h"
60 #include "ApplicationMessenger.h"
61 #include "SectionLoader.h"
62 #include "cores/DllLoader/DllLoaderContainer.h"
63 #include "GUIUserMessages.h"
64 #include "filesystem/DirectoryCache.h"
65 #include "filesystem/StackDirectory.h"
66 #include "filesystem/SpecialProtocol.h"
67 #include "filesystem/DllLibCurl.h"
68 #include "filesystem/MythSession.h"
69 #include "filesystem/PluginDirectory.h"
70 #ifdef HAS_FILESYSTEM_SAP
71 #include "filesystem/SAPDirectory.h"
72 #endif
73 #ifdef HAS_FILESYSTEM_HTSP
74 #include "filesystem/HTSPDirectory.h"
75 #endif
76 #include "utils/TuxBoxUtil.h"
77 #include "utils/SystemInfo.h"
78 #include "utils/TimeUtils.h"
79 #include "GUILargeTextureManager.h"
80 #include "TextureCache.h"
81 #include "music/LastFmManager.h"
82 #include "playlists/SmartPlayList.h"
83 #ifdef HAS_FILESYSTEM_RAR
84 #include "filesystem/RarManager.h"
85 #endif
86 #include "playlists/PlayList.h"
87 #include "windowing/WindowingFactory.h"
88 #include "powermanagement/PowerManager.h"
89 #include "powermanagement/DPMSSupport.h"
90 #include "settings/Settings.h"
91 #include "settings/AdvancedSettings.h"
92 #include "guilib/LocalizeStrings.h"
93 #include "utils/CPUInfo.h"
94
95 #include "input/KeyboardStat.h"
96 #include "input/XBMC_vkeys.h"
97 #include "input/MouseStat.h"
98
99 #if defined(FILESYSTEM) && !defined(_LINUX)
100 #include "filesystem/FileDAAP.h"
101 #endif
102 #ifdef HAS_UPNP
103 #include "network/UPnP.h"
104 #include "filesystem/UPnPDirectory.h"
105 #endif
106 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
107 #include "filesystem/SMBDirectory.h"
108 #endif
109 #ifdef HAS_FILESYSTEM_NFS
110 #include "filesystem/FileNFS.h"
111 #endif
112 #ifdef HAS_FILESYSTEM_AFP
113 #include "filesystem/FileAFP.h"
114 #endif
115 #ifdef HAS_FILESYSTEM_SFTP
116 #include "filesystem/FileSFTP.h"
117 #endif
118 #include "PartyModeManager.h"
119 #ifdef HAS_VIDEO_PLAYBACK
120 #include "cores/VideoRenderers/RenderManager.h"
121 #endif
122 #ifdef HAS_KARAOKE
123 #include "music/karaoke/karaokelyricsmanager.h"
124 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
125 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
126 #endif
127 #include "guilib/AudioContext.h"
128 #include "guilib/GUIFontTTF.h"
129 #include "network/Network.h"
130 #include "storage/IoSupport.h"
131 #include "network/Zeroconf.h"
132 #include "network/ZeroconfBrowser.h"
133 #ifndef _LINUX
134 #include "utils/Win32Exception.h"
135 #endif
136 #ifdef HAS_EVENT_SERVER
137 #include "network/EventServer.h"
138 #endif
139 #ifdef HAS_DBUS
140 #include <dbus/dbus.h>
141 #endif
142 #ifdef HAS_HTTPAPI
143 #include "interfaces/http-api/XBMChttp.h"
144 #endif
145 #ifdef HAS_JSONRPC
146 #include "interfaces/json-rpc/JSONRPC.h"
147 #include "network/TCPServer.h"
148 #endif
149 #ifdef HAS_AIRPLAY
150 #include "network/AirPlayServer.h"
151 #endif
152 #ifdef HAS_AIRTUNES
153 #include "network/AirTunesServer.h"
154 #endif
155 #if defined(HAVE_LIBCRYSTALHD)
156 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
157 #endif
158 #include "interfaces/AnnouncementManager.h"
159 #include "peripherals/Peripherals.h"
160 #ifdef HAVE_LIBCEC
161 #include "peripherals/devices/PeripheralCecAdapter.h"
162 #endif
163 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
165
166 // Windows includes
167 #include "guilib/GUIWindowManager.h"
168 #include "windows/GUIWindowHome.h"
169 #include "guilib/GUIStandardWindow.h"
170 #include "settings/GUIWindowSettings.h"
171 #include "windows/GUIWindowFileManager.h"
172 #include "settings/GUIWindowSettingsCategory.h"
173 #include "music/windows/GUIWindowMusicPlaylist.h"
174 #include "music/windows/GUIWindowMusicSongs.h"
175 #include "music/windows/GUIWindowMusicNav.h"
176 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
177 #include "video/windows/GUIWindowVideoPlaylist.h"
178 #include "music/dialogs/GUIDialogMusicInfo.h"
179 #include "video/dialogs/GUIDialogVideoInfo.h"
180 #include "video/windows/GUIWindowVideoNav.h"
181 #include "settings/GUIWindowSettingsProfile.h"
182 #ifdef HAS_GL
183 #include "rendering/gl/GUIWindowTestPatternGL.h"
184 #endif
185 #ifdef HAS_DX
186 #include "rendering/dx/GUIWindowTestPatternDX.h"
187 #endif
188 #include "settings/GUIWindowSettingsScreenCalibration.h"
189 #include "programs/GUIWindowPrograms.h"
190 #include "pictures/GUIWindowPictures.h"
191 #include "windows/GUIWindowWeather.h"
192 #include "windows/GUIWindowLoginScreen.h"
193 #include "addons/GUIWindowAddonBrowser.h"
194 #include "music/windows/GUIWindowVisualisation.h"
195 #include "windows/GUIWindowDebugInfo.h"
196 #include "windows/GUIWindowPointer.h"
197 #include "windows/GUIWindowSystemInfo.h"
198 #include "windows/GUIWindowScreensaver.h"
199 #include "windows/GUIWindowScreensaverDim.h"
200 #include "pictures/GUIWindowSlideShow.h"
201 #include "windows/GUIWindowStartup.h"
202 #include "video/windows/GUIWindowFullScreen.h"
203 #include "video/dialogs/GUIDialogVideoOSD.h"
204 #include "music/dialogs/GUIDialogMusicOverlay.h"
205 #include "video/dialogs/GUIDialogVideoOverlay.h"
206
207 // Dialog includes
208 #include "music/dialogs/GUIDialogMusicOSD.h"
209 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
210 #include "dialogs/GUIDialogTextViewer.h"
211 #include "network/GUIDialogNetworkSetup.h"
212 #include "dialogs/GUIDialogMediaSource.h"
213 #include "video/dialogs/GUIDialogVideoSettings.h"
214 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
215 #include "video/dialogs/GUIDialogVideoBookmarks.h"
216 #include "settings/GUIDialogProfileSettings.h"
217 #include "settings/GUIDialogLockSettings.h"
218 #include "settings/GUIDialogContentSettings.h"
219 #include "video/dialogs/GUIDialogVideoScan.h"
220 #include "dialogs/GUIDialogBusy.h"
221 #include "dialogs/GUIDialogKeyboard.h"
222 #include "dialogs/GUIDialogYesNo.h"
223 #include "dialogs/GUIDialogOK.h"
224 #include "dialogs/GUIDialogProgress.h"
225 #include "dialogs/GUIDialogSelect.h"
226 #include "dialogs/GUIDialogSeekBar.h"
227 #include "dialogs/GUIDialogKaiToast.h"
228 #include "dialogs/GUIDialogVolumeBar.h"
229 #include "dialogs/GUIDialogMuteBug.h"
230 #include "video/dialogs/GUIDialogFileStacking.h"
231 #include "dialogs/GUIDialogNumeric.h"
232 #include "dialogs/GUIDialogGamepad.h"
233 #include "dialogs/GUIDialogSubMenu.h"
234 #include "dialogs/GUIDialogFavourites.h"
235 #include "dialogs/GUIDialogButtonMenu.h"
236 #include "dialogs/GUIDialogContextMenu.h"
237 #include "music/dialogs/GUIDialogMusicScan.h"
238 #include "dialogs/GUIDialogPlayerControls.h"
239 #include "music/dialogs/GUIDialogSongInfo.h"
240 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
241 #include "dialogs/GUIDialogSmartPlaylistRule.h"
242 #include "pictures/GUIDialogPictureInfo.h"
243 #include "addons/GUIDialogAddonSettings.h"
244 #include "addons/GUIDialogAddonInfo.h"
245 #ifdef HAS_LINUX_NETWORK
246 #include "network/GUIDialogAccessPoints.h"
247 #endif
248 #include "video/dialogs/GUIDialogFullScreenInfo.h"
249 #include "video/dialogs/GUIDialogTeletext.h"
250 #include "dialogs/GUIDialogSlider.h"
251 #include "guilib/GUIControlFactory.h"
252 #include "dialogs/GUIDialogCache.h"
253 #include "dialogs/GUIDialogPlayEject.h"
254 #include "utils/XMLUtils.h"
255 #include "addons/AddonInstaller.h"
256
257 #ifdef HAS_PERFORMANCE_SAMPLE
258 #include "utils/PerformanceSample.h"
259 #else
260 #define MEASURE_FUNCTION
261 #endif
262
263 #ifdef HAS_SDL_AUDIO
264 #include <SDL/SDL_mixer.h>
265 #endif
266 #ifdef _WIN32
267 #include <shlobj.h>
268 #include "win32util.h"
269 #endif
270 #ifdef HAS_XRANDR
271 #include "windowing/X11/XRandR.h"
272 #endif
273
274 #ifdef TARGET_DARWIN_OSX
275 #include "CocoaInterface.h"
276 #include "XBMCHelper.h"
277 #endif
278 #ifdef TARGET_DARWIN
279 #include "DarwinUtils.h"
280 #endif
281
282
283 #ifdef HAS_DVD_DRIVE
284 #include <cdio/logging.h>
285 #endif
286
287 #ifdef HAS_HAL
288 #include "linux/HALManager.h"
289 #endif
290
291 #include "storage/MediaManager.h"
292 #include "utils/JobManager.h"
293 #include "utils/SaveFileStateJob.h"
294 #include "utils/AlarmClock.h"
295
296 #ifdef _LINUX
297 #include "XHandle.h"
298 #endif
299
300 #ifdef HAS_LIRC
301 #include "input/linux/LIRC.h"
302 #endif
303 #ifdef HAS_IRSERVERSUITE
304   #include "input/windows/IRServerSuite.h"
305 #endif
306
307 using namespace std;
308 using namespace ADDON;
309 using namespace XFILE;
310 #ifdef HAS_DVD_DRIVE
311 using namespace MEDIA_DETECT;
312 #endif
313 using namespace PLAYLIST;
314 using namespace VIDEO;
315 using namespace MUSIC_INFO;
316 #ifdef HAS_EVENT_SERVER
317 using namespace EVENTSERVER;
318 #endif
319 #ifdef HAS_JSONRPC
320 using namespace JSONRPC;
321 #endif
322 using namespace ANNOUNCEMENT;
323 using namespace PERIPHERALS;
324
325 using namespace XbmcThreads;
326
327 // uncomment this if you want to use release libs in the debug build.
328 // Atm this saves you 7 mb of memory
329 #define USE_RELEASE_LIBS
330
331 #define MAX_FFWD_SPEED 5
332
333 //extern IDirectSoundRenderer* m_pAudioDecoder;
334 CApplication::CApplication(void) : m_itemCurrentFile(new CFileItem), m_progressTrackingItem(new CFileItem)
335   , m_progressTrackingVideoResumeBookmark(*new CBookmark)
336   , m_WebServer(*new CWebServer)
337 {
338   m_iPlaySpeed = 1;
339   m_pPlayer = NULL;
340   m_bScreenSave = false;
341   m_dpms = NULL;
342   m_dpmsIsActive = false;
343   m_dpmsIsManual = false;
344   m_iScreenSaveLock = 0;
345   m_bInitializing = true;
346   m_eForcedNextPlayer = EPC_NONE;
347   m_strPlayListFile = "";
348   m_nextPlaylistItem = -1;
349   m_bPlaybackStarting = false;
350   m_skinReloading = false;
351
352 #ifdef HAS_GLX
353   XInitThreads();
354 #endif
355
356   //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
357   m_bIsPaused = false;
358
359   /* for now always keep this around */
360 #ifdef HAS_KARAOKE
361   m_pKaraokeMgr = new CKaraokeLyricsManager();
362 #endif
363   m_currentStack = new CFileItemList;
364
365   m_frameCount = 0;
366
367   m_bPresentFrame = false;
368   m_bPlatformDirectories = true;
369
370   m_bStandalone = false;
371   m_bEnableLegacyRes = false;
372   m_bSystemScreenSaverEnable = false;
373   m_pInertialScrollingHandler = new CInertialScrollingHandler();
374   m_Autorun = new CAutorun();
375 }
376
377 CApplication::~CApplication(void)
378 {
379   delete &m_WebServer;
380   delete &m_progressTrackingVideoResumeBookmark;
381   delete m_Autorun;
382   delete m_currentStack;
383
384 #ifdef HAS_KARAOKE
385   delete m_pKaraokeMgr;
386 #endif
387
388   delete m_dpms;
389   delete m_pInertialScrollingHandler;
390 }
391
392 bool CApplication::OnEvent(XBMC_Event& newEvent)
393 {
394   switch(newEvent.type)
395   {
396     case XBMC_QUIT:
397       if (!g_application.m_bStop)
398         g_application.getApplicationMessenger().Quit();
399       break;
400     case XBMC_KEYDOWN:
401       g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
402       break;
403     case XBMC_KEYUP:
404       g_Keyboard.ProcessKeyUp();
405       break;
406     case XBMC_MOUSEBUTTONDOWN:
407     case XBMC_MOUSEBUTTONUP:
408     case XBMC_MOUSEMOTION:
409       g_Mouse.HandleEvent(newEvent);
410       g_application.ProcessMouse();
411       break;
412     case XBMC_VIDEORESIZE:
413       if (!g_application.m_bInitializing &&
414           !g_advancedSettings.m_fullScreen)
415       {
416         g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
417         g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
418         g_guiSettings.SetInt("window.width", newEvent.resize.w);
419         g_guiSettings.SetInt("window.height", newEvent.resize.h);
420         g_settings.Save();
421       }
422       break;
423     case XBMC_USEREVENT:
424       g_application.getApplicationMessenger().UserEvent(newEvent.user.code);
425       break;
426     case XBMC_APPCOMMAND:
427       return g_application.OnAppCommand(newEvent.appcommand.action);
428   }
429   return true;
430 }
431
432 // This function does not return!
433 void CApplication::FatalErrorHandler(bool WindowSystemInitialized, bool MapDrives, bool InitNetwork)
434 {
435   fprintf(stderr, "Fatal error encountered, aborting\n");
436   fprintf(stderr, "Error log at %sxbmc.log\n", g_settings.m_logFolder.c_str());
437   abort();
438 }
439
440 extern "C" void __stdcall init_emu_environ();
441 extern "C" void __stdcall update_emu_environ();
442
443 //
444 // Utility function used to copy files from the application bundle
445 // over to the user data directory in Application Support/XBMC.
446 //
447 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
448 {
449   CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
450   if (!CFile::Exists(destPath))
451   {
452     // need to copy it across
453     CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
454     CFile::Cache(srcPath, destPath);
455   }
456 }
457
458 void CApplication::Preflight()
459 {
460 #ifdef HAS_DBUS
461   // call 'dbus_threads_init_default' before any other dbus calls in order to
462   // avoid race conditions with other threads using dbus connections
463   dbus_threads_init_default();
464 #endif
465
466   // run any platform preflight scripts.
467 #if defined(__APPLE__) && !defined(__arm__)
468   CStdString install_path;
469
470   CUtil::GetHomePath(install_path);
471   setenv("XBMC_HOME", install_path.c_str(), 0);
472   install_path += "/tools/darwin/runtime/preflight";
473   system(install_path.c_str());
474 #endif
475 }
476
477 bool CApplication::Create()
478 {
479   g_settings.Initialize(); //Initialize default AdvancedSettings
480
481   m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
482   g_Windowing.EnableSystemScreenSaver(false);
483
484 #ifdef _LINUX
485   tzset();   // Initialize timezone information variables
486 #endif
487
488   // Grab a handle to our thread to be used later in identifying the render thread.
489   m_threadID = CThread::GetCurrentThreadId();
490
491 #ifndef _LINUX
492   //floating point precision to 24 bits (faster performance)
493   _controlfp(_PC_24, _MCW_PC);
494
495   /* install win32 exception translator, win32 exceptions
496    * can now be caught using c++ try catch */
497   win32_exception::install_handler();
498
499 #endif
500
501   // only the InitDirectories* for the current platform should return true
502   // putting this before the first log entries saves another ifdef for g_settings.m_logFolder
503   bool inited = InitDirectoriesLinux();
504   if (!inited)
505     inited = InitDirectoriesOSX();
506   if (!inited)
507     inited = InitDirectoriesWin32();
508
509   // copy required files
510   CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
511   CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
512   CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
513   CopyUserDataIfNeeded("special://masterprofile/", "LCD.xml");
514
515   if (!CLog::Init(_P(g_settings.m_logFolder).c_str()))
516   {
517     fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc?\n");
518     return false;
519   }
520
521   g_settings.LoadProfiles(PROFILES_FILE);
522
523   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
524 #if defined(TARGET_DARWIN_OSX)
525   CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
526 #elif defined(TARGET_DARWIN_IOS)
527   CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
528 #elif defined(__FreeBSD__)
529   CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
530 #elif defined(_LINUX)
531   CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Linux (%s, %s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
532 #elif defined(_WIN32)
533   CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: %s. Built on %s (compiler %i)", g_infoManager.GetVersion().c_str(), g_sysinfo.GetKernelVersion().c_str(), __DATE__, _MSC_VER);
534   CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
535   CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
536   CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
537   CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
538 #endif
539   CSpecialProtocol::LogPaths();
540
541   CStdString executable = CUtil::ResolveExecutablePath();
542   CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
543   CLog::Log(LOGNOTICE, "Local hostname: %s", m_network.GetHostName().c_str());
544   CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str());
545   CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
546
547   CStdString strExecutablePath;
548   CUtil::GetHomePath(strExecutablePath);
549
550   // if we are running from DVD our UserData location will be TDATA
551   if (URIUtils::IsDVD(strExecutablePath))
552   {
553     // TODO: Should we copy over any UserData folder from the DVD?
554     if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
555     {
556       CFileItemList items;
557       CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
558       for (int i=0;i<items.Size();++i)
559           CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
560     }
561     g_settings.m_logFolder = "special://masterprofile/";
562   }
563
564 #ifdef HAS_XRANDR
565   g_xrandr.LoadCustomModeLinesToAllOutputs();
566 #endif
567
568   // Init our DllLoaders emu env
569   init_emu_environ();
570
571
572 #ifdef HAS_SDL
573   CLog::Log(LOGNOTICE, "Setup SDL");
574
575   /* Clean up on exit, exit on window close and interrupt */
576   atexit(SDL_Quit);
577
578   uint32_t sdlFlags = 0;
579
580 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
581   sdlFlags |= SDL_INIT_VIDEO;
582 #endif
583
584 #ifdef HAS_SDL_AUDIO
585   sdlFlags |= SDL_INIT_AUDIO;
586 #endif
587
588 #ifdef HAS_SDL_JOYSTICK
589   sdlFlags |= SDL_INIT_JOYSTICK;
590 #endif
591
592   //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
593   //this might bring the monitor out of standby, so we have to disable it explicitly
594   //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
595 #if defined(_LINUX) && !defined(__APPLE__)
596   setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
597 #endif
598
599 #endif // HAS_SDL
600
601 #ifdef _LINUX
602   // for nvidia cards - vsync currently ALWAYS enabled.
603   // the reason is that after screen has been setup changing this env var will make no difference.
604   setenv("__GL_SYNC_TO_VBLANK", "1", 0);
605   setenv("__GL_YIELD", "USLEEP", 0);
606 #endif
607
608 #ifdef HAS_SDL
609   if (SDL_Init(sdlFlags) != 0)
610   {
611     CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
612     return false;
613   }
614   #if defined(TARGET_DARWIN)
615   // SDL_Init will install a handler for segfaults, restore the default handler.
616   signal(SIGSEGV, SIG_DFL);
617   #endif
618 #endif
619
620   // for python scripts that check the OS
621 #ifdef __APPLE__
622   setenv("OS","OS X",true);
623 #elif defined(_LINUX)
624   setenv("OS","Linux",true);
625 #elif defined(_WIN32)
626   SetEnvironmentVariable("OS","win32");
627 #endif
628
629   // Initialize core peripheral port support. Note: If these parameters
630   // are 0 and NULL, respectively, then the default number and types of
631   // controllers will be initialized.
632   if (!g_Windowing.InitWindowSystem())
633   {
634     CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
635     return false;
636   }
637
638   g_powerManager.Initialize();
639
640   CLog::Log(LOGNOTICE, "load settings...");
641
642   g_guiSettings.Initialize();  // Initialize default Settings - don't move
643   g_powerManager.SetDefaults();
644   if (!g_settings.Load())
645     FatalErrorHandler(true, true, true);
646
647   CLog::Log(LOGINFO, "creating subdirectories");
648   CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
649   CLog::Log(LOGINFO, "recording folder:%s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
650   CLog::Log(LOGINFO, "screenshots folder:%s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
651   CDirectory::Create(g_settings.GetUserDataFolder());
652   CDirectory::Create(g_settings.GetProfileUserDataFolder());
653   g_settings.CreateProfileFolders();
654
655   update_emu_environ();//apply the GUI settings
656
657   // initialize our charset converter
658   g_charsetConverter.reset();
659
660   // Load the langinfo to have user charset <-> utf-8 conversion
661   CStdString strLanguage = g_guiSettings.GetString("locale.language");
662   strLanguage[0] = toupper(strLanguage[0]);
663
664   CStdString strLangInfoPath;
665   strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
666
667   CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
668   g_langInfo.Load(strLangInfoPath);
669
670   CStdString strLanguagePath;
671   strLanguagePath.Format("special://xbmc/language/%s/strings.xml", strLanguage.c_str());
672
673   CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
674   if (!g_localizeStrings.Load(strLanguagePath))
675     FatalErrorHandler(false, false, true);
676
677   // start-up Addons Framework
678   // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
679   if (!CAddonMgr::Get().Init())
680   {
681     CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
682     FatalErrorHandler(true, true, true);
683   }
684
685   g_peripherals.Initialise();
686
687   // Create the Mouse, Keyboard, Remote, and Joystick devices
688   // Initialize after loading settings to get joystick deadzone setting
689   g_Mouse.Initialize();
690   g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
691
692   g_Keyboard.Initialize();
693 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
694   g_RemoteControl.Initialize();
695 #endif
696 #ifdef HAS_SDL_JOYSTICK
697   g_Joystick.Initialize();
698 #endif
699
700 #if defined(__APPLE__) && !defined(__arm__)
701   // Configure and possible manually start the helper.
702   XBMCHelper::GetInstance().Configure();
703 #endif
704
705   // update the window resolution
706   g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
707
708   if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
709     g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
710
711   if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
712   {
713     // Oh uh - doesn't look good for starting in their wanted screenmode
714     CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
715     g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
716   }
717
718 #ifdef __APPLE__
719   // force initial window creation to be windowed, if fullscreen, it will switch to it below
720   // fixes the white screen of death if starting fullscreen and switching to windowed.
721   bool bFullScreen = false;
722   if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
723   {
724     CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
725     return false;
726   }
727 #else
728   bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
729   if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
730   {
731     CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
732     return false;
733   }
734 #endif
735
736   if (!g_Windowing.InitRenderSystem())
737   {
738     CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
739     return false;
740   }
741
742   // set GUI res and force the clear of the screen
743   g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
744
745   if (g_advancedSettings.m_splashImage)
746   {
747     CStdString strUserSplash = "special://home/media/Splash.png";
748     if (CFile::Exists(strUserSplash))
749     {
750       CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
751       m_splash = new CSplash(strUserSplash);
752     }
753     else
754     {
755       CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
756       m_splash = new CSplash("special://xbmc/media/Splash.png");
757     }
758     m_splash->Show();
759   }
760
761   // The key mappings may already have been loaded by a peripheral
762   CLog::Log(LOGINFO, "load keymapping");
763   if (!CButtonTranslator::GetInstance().Load())
764       FatalErrorHandler(false, false, true);
765
766   int iResolution = g_graphicsContext.GetVideoResolution();
767   CLog::Log(LOGINFO, "GUI format %ix%i %s",
768             g_settings.m_ResInfo[iResolution].iWidth,
769             g_settings.m_ResInfo[iResolution].iHeight,
770             g_settings.m_ResInfo[iResolution].strMode.c_str());
771   g_windowManager.Initialize();
772
773   CUtil::InitRandomSeed();
774
775   g_mediaManager.Initialize();
776
777   m_lastFrameTime = XbmcThreads::SystemClockMillis();
778   m_lastRenderTime = m_lastFrameTime;
779
780   return Initialize();
781 }
782
783 bool CApplication::InitDirectoriesLinux()
784 {
785 /*
786    The following is the directory mapping for Platform Specific Mode:
787
788    special://xbmc/          => [read-only] system directory (/usr/share/xbmc)
789    special://home/          => [read-write] user's directory that will override special://xbmc/ system-wide
790                                installations like skins, screensavers, etc.
791                                ($HOME/.xbmc)
792                                NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
793    special://masterprofile/ => [read-write] userdata of master profile. It will by default be
794                                mapped to special://home/userdata ($HOME/.xbmc/userdata)
795    special://profile/       => [read-write] current profile's userdata directory.
796                                Generally special://masterprofile for the master profile or
797                                special://masterprofile/profiles/<profile_name> for other profiles.
798
799    NOTE: All these root directories are lowercase. Some of the sub-directories
800          might be mixed case.
801 */
802
803 #if defined(_LINUX) && !defined(__APPLE__)
804   CStdString userName;
805   if (getenv("USER"))
806     userName = getenv("USER");
807   else
808     userName = "root";
809
810   CStdString userHome;
811   if (getenv("HOME"))
812     userHome = getenv("HOME");
813   else
814     userHome = "/root";
815
816   CStdString xbmcBinPath, xbmcPath;
817   CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
818   xbmcPath = getenv("XBMC_HOME");
819
820   if (xbmcPath.IsEmpty())
821   {
822     xbmcPath = xbmcBinPath;
823     /* Check if xbmc binaries and arch independent data files are being kept in
824      * separate locations. */
825     if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
826     {
827       /* Attempt to locate arch independent data files. */
828       CUtil::GetHomePath(xbmcPath);
829       if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
830       {
831         fprintf(stderr, "Unable to find path to XBMC data files!\n");
832         exit(1);
833       }
834     }
835   }
836
837   /* Set some environment variables */
838   setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
839   setenv("XBMC_HOME", xbmcPath.c_str(), 0);
840
841   if (m_bPlatformDirectories)
842   {
843     // map our special drives
844     CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
845     CSpecialProtocol::SetXBMCPath(xbmcPath);
846     CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
847     CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
848
849     CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
850     CSpecialProtocol::SetTempPath(strTempPath);
851
852     URIUtils::AddSlashAtEnd(strTempPath);
853     g_settings.m_logFolder = strTempPath;
854
855     CreateUserDirs();
856
857   }
858   else
859   {
860     URIUtils::AddSlashAtEnd(xbmcPath);
861     g_settings.m_logFolder = xbmcPath;
862
863     CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
864     CSpecialProtocol::SetXBMCPath(xbmcPath);
865     CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
866     CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
867
868     CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
869     CSpecialProtocol::SetTempPath(strTempPath);
870     CreateUserDirs();
871
872     URIUtils::AddSlashAtEnd(strTempPath);
873     g_settings.m_logFolder = strTempPath;
874   }
875
876   return true;
877 #else
878   return false;
879 #endif
880 }
881
882 bool CApplication::InitDirectoriesOSX()
883 {
884 #ifdef __APPLE__
885   CStdString userName;
886   if (getenv("USER"))
887     userName = getenv("USER");
888   else
889     userName = "root";
890
891   CStdString userHome;
892   if (getenv("HOME"))
893     userHome = getenv("HOME");
894   else
895     userHome = "/root";
896
897   CStdString xbmcPath;
898   CUtil::GetHomePath(xbmcPath);
899   setenv("XBMC_HOME", xbmcPath.c_str(), 0);
900
901 #if defined(__arm__)
902   CStdString fontconfigPath;
903   fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
904   setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
905 #endif
906   
907   // setup path to our internal dylibs so loader can find them
908   CStdString frameworksPath = CUtil::GetFrameworksPath();
909   CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
910
911   // OSX always runs with m_bPlatformDirectories == true
912   if (m_bPlatformDirectories)
913   {
914     // map our special drives
915     CSpecialProtocol::SetXBMCBinPath(xbmcPath);
916     CSpecialProtocol::SetXBMCPath(xbmcPath);
917     #if defined(__arm__)
918       CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
919       CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
920     #else
921       CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
922       CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
923     #endif
924
925     // location for temp files
926     #if defined(__arm__)
927       CStdString strTempPath = URIUtils::AddFileToFolder(userHome,  "Library/Preferences/XBMC/temp");
928     #else
929       CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
930       CDirectory::Create(strTempPath);
931       strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
932     #endif
933     CSpecialProtocol::SetTempPath(strTempPath);
934
935     // xbmc.log file location
936     #if defined(__arm__)
937       strTempPath = userHome + "/Library/Preferences";
938     #else
939       strTempPath = userHome + "/Library/Logs";
940     #endif
941     URIUtils::AddSlashAtEnd(strTempPath);
942     g_settings.m_logFolder = strTempPath;
943
944     CreateUserDirs();
945   }
946   else
947   {
948     URIUtils::AddSlashAtEnd(xbmcPath);
949     g_settings.m_logFolder = xbmcPath;
950
951     CSpecialProtocol::SetXBMCBinPath(xbmcPath);
952     CSpecialProtocol::SetXBMCPath(xbmcPath);
953     CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
954     CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
955
956     CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
957     CSpecialProtocol::SetTempPath(strTempPath);
958
959     URIUtils::AddSlashAtEnd(strTempPath);
960     g_settings.m_logFolder = strTempPath;
961   }
962
963   return true;
964 #else
965   return false;
966 #endif
967 }
968
969 bool CApplication::InitDirectoriesWin32()
970 {
971 #ifdef _WIN32
972   CStdString xbmcPath;
973
974   CUtil::GetHomePath(xbmcPath);
975   SetEnvironmentVariable("XBMC_HOME", xbmcPath.c_str());
976   CSpecialProtocol::SetXBMCBinPath(xbmcPath);
977   CSpecialProtocol::SetXBMCPath(xbmcPath);
978
979   CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
980
981   g_settings.m_logFolder = strWin32UserFolder;
982   CSpecialProtocol::SetHomePath(strWin32UserFolder);
983   CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
984   CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
985
986   SetEnvironmentVariable("XBMC_PROFILE_USERDATA",_P("special://masterprofile/").c_str());
987
988   CreateUserDirs();
989
990   // Expand the DLL search path with our directories
991   CWIN32Util::ExtendDllPath();
992
993   // check for a DVD drive
994   VECSOURCES vShare;
995   CWIN32Util::GetDrivesByType(vShare, DVD_DRIVES);
996   if(!vShare.empty())
997     g_mediaManager.SetHasOpticalDrive(true);
998
999   // Can be removed once the StorageHandler supports optical media
1000   VECSOURCES::const_iterator it;
1001   for(it=vShare.begin();it!=vShare.end();++it)
1002     if(g_mediaManager.GetDriveStatus(it->strPath) == DRIVE_CLOSED_MEDIA_PRESENT)
1003       g_application.getApplicationMessenger().OpticalMount(it->strPath);
1004   // remove end
1005
1006   return true;
1007 #else
1008   return false;
1009 #endif
1010 }
1011
1012 void CApplication::CreateUserDirs()
1013 {
1014   CDirectory::Create("special://home/");
1015   CDirectory::Create("special://home/addons");
1016   CDirectory::Create("special://home/addons/packages");
1017   CDirectory::Create("special://home/media");
1018   CDirectory::Create("special://home/sounds");
1019   CDirectory::Create("special://home/system");
1020   CDirectory::Create("special://masterprofile/");
1021   CDirectory::Create("special://temp/");
1022   CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1023 }
1024
1025 bool CApplication::Initialize()
1026 {
1027 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1028   // turn off cdio logging
1029   cdio_loglevel_default = CDIO_LOG_ERROR;
1030 #endif
1031
1032 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1033               //       must create these here. Ideally this should be using special://home/ and
1034               //       be platform agnostic (i.e. unify the InitDirectories*() functions)
1035   if (!m_bPlatformDirectories)
1036 #endif
1037   {
1038     CDirectory::Create("special://xbmc/language");
1039     CDirectory::Create("special://xbmc/addons");
1040     CDirectory::Create("special://xbmc/sounds");
1041   }
1042
1043   StartServices();
1044
1045   // Init DPMS, before creating the corresponding setting control.
1046   m_dpms = new DPMSSupport();
1047   g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1048
1049   g_windowManager.Add(new CGUIWindowHome);                     // window id = 0
1050   g_windowManager.Add(new CGUIWindowPrograms);                 // window id = 1
1051   g_windowManager.Add(new CGUIWindowPictures);                 // window id = 2
1052   g_windowManager.Add(new CGUIWindowFileManager);      // window id = 3
1053   g_windowManager.Add(new CGUIWindowSettings);                 // window id = 4
1054   g_windowManager.Add(new CGUIWindowSystemInfo);               // window id = 7
1055 #ifdef HAS_GL
1056   g_windowManager.Add(new CGUIWindowTestPatternGL);      // window id = 8
1057 #endif
1058 #ifdef HAS_DX
1059   g_windowManager.Add(new CGUIWindowTestPatternDX);      // window id = 8
1060 #endif
1061   g_windowManager.Add(new CGUIDialogTeletext);               // window id =
1062   g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
1063   g_windowManager.Add(new CGUIWindowSettingsCategory);         // window id = 12 slideshow:window id 2007
1064   g_windowManager.Add(new CGUIWindowVideoNav);                 // window id = 36
1065   g_windowManager.Add(new CGUIWindowVideoPlaylist);            // window id = 28
1066   g_windowManager.Add(new CGUIWindowLoginScreen);            // window id = 29
1067   g_windowManager.Add(new CGUIWindowSettingsProfile);          // window id = 34
1068   g_windowManager.Add(new CGUIWindowAddonBrowser);          // window id = 40
1069   g_windowManager.Add(new CGUIWindowScreensaverDim);            // window id = 97  
1070   g_windowManager.Add(new CGUIWindowDebugInfo);            // window id = 98
1071   g_windowManager.Add(new CGUIWindowPointer);            // window id = 99
1072   g_windowManager.Add(new CGUIDialogYesNo);              // window id = 100
1073   g_windowManager.Add(new CGUIDialogProgress);           // window id = 101
1074   g_windowManager.Add(new CGUIDialogKeyboard);           // window id = 103
1075   g_windowManager.Add(new CGUIDialogVolumeBar);          // window id = 104
1076   g_windowManager.Add(new CGUIDialogSeekBar);            // window id = 115
1077   g_windowManager.Add(new CGUIDialogSubMenu);            // window id = 105
1078   g_windowManager.Add(new CGUIDialogContextMenu);        // window id = 106
1079   g_windowManager.Add(new CGUIDialogKaiToast);           // window id = 107
1080   g_windowManager.Add(new CGUIDialogNumeric);            // window id = 109
1081   g_windowManager.Add(new CGUIDialogGamepad);            // window id = 110
1082   g_windowManager.Add(new CGUIDialogButtonMenu);         // window id = 111
1083   g_windowManager.Add(new CGUIDialogMusicScan);          // window id = 112
1084   g_windowManager.Add(new CGUIDialogMuteBug);            // window id = 113
1085   g_windowManager.Add(new CGUIDialogPlayerControls);     // window id = 114
1086 #ifdef HAS_KARAOKE
1087   g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall); // window id 143
1088   g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge); // window id 144
1089 #endif
1090   g_windowManager.Add(new CGUIDialogSlider);             // window id = 145
1091   g_windowManager.Add(new CGUIDialogMusicOSD);           // window id = 120
1092   g_windowManager.Add(new CGUIDialogVisualisationPresetList);   // window id = 122
1093   g_windowManager.Add(new CGUIDialogVideoSettings);             // window id = 123
1094   g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);     // window id = 124
1095   g_windowManager.Add(new CGUIDialogVideoBookmarks);      // window id = 125
1096   // Don't add the filebrowser dialog - it's created and added when it's needed
1097   g_windowManager.Add(new CGUIDialogNetworkSetup);  // window id = 128
1098   g_windowManager.Add(new CGUIDialogMediaSource);   // window id = 129
1099   g_windowManager.Add(new CGUIDialogProfileSettings); // window id = 130
1100   g_windowManager.Add(new CGUIDialogVideoScan);      // window id = 133
1101   g_windowManager.Add(new CGUIDialogFavourites);     // window id = 134
1102   g_windowManager.Add(new CGUIDialogSongInfo);       // window id = 135
1103   g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);       // window id = 136
1104   g_windowManager.Add(new CGUIDialogSmartPlaylistRule);       // window id = 137
1105   g_windowManager.Add(new CGUIDialogBusy);      // window id = 138
1106   g_windowManager.Add(new CGUIDialogPictureInfo);      // window id = 139
1107   g_windowManager.Add(new CGUIDialogAddonInfo);
1108   g_windowManager.Add(new CGUIDialogAddonSettings);      // window id = 140
1109 #ifdef HAS_LINUX_NETWORK
1110   g_windowManager.Add(new CGUIDialogAccessPoints);      // window id = 141
1111 #endif
1112
1113   g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131
1114
1115   g_windowManager.Add(new CGUIDialogContentSettings);        // window id = 132
1116
1117   g_windowManager.Add(new CGUIDialogPlayEject);
1118
1119   g_windowManager.Add(new CGUIDialogPeripheralManager);
1120   g_windowManager.Add(new CGUIDialogPeripheralSettings);
1121
1122   g_windowManager.Add(new CGUIWindowMusicPlayList);          // window id = 500
1123   g_windowManager.Add(new CGUIWindowMusicSongs);             // window id = 501
1124   g_windowManager.Add(new CGUIWindowMusicNav);               // window id = 502
1125   g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);    // window id = 503
1126
1127   g_windowManager.Add(new CGUIDialogSelect);             // window id = 2000
1128   g_windowManager.Add(new CGUIDialogMusicInfo);          // window id = 2001
1129   g_windowManager.Add(new CGUIDialogOK);                 // window id = 2002
1130   g_windowManager.Add(new CGUIDialogVideoInfo);          // window id = 2003
1131   g_windowManager.Add(new CGUIDialogTextViewer);
1132   g_windowManager.Add(new CGUIWindowFullScreen);         // window id = 2005
1133   g_windowManager.Add(new CGUIWindowVisualisation);      // window id = 2006
1134   g_windowManager.Add(new CGUIWindowSlideShow);          // window id = 2007
1135   g_windowManager.Add(new CGUIDialogFileStacking);       // window id = 2008
1136 #ifdef HAS_KARAOKE
1137   g_windowManager.Add(new CGUIWindowKaraokeLyrics);      // window id = 2009
1138 #endif
1139
1140   g_windowManager.Add(new CGUIDialogVideoOSD);           // window id = 2901
1141   g_windowManager.Add(new CGUIDialogMusicOverlay);       // window id = 2903
1142   g_windowManager.Add(new CGUIDialogVideoOverlay);       // window id = 2904
1143   g_windowManager.Add(new CGUIWindowScreensaver);        // window id = 2900 Screensaver
1144   g_windowManager.Add(new CGUIWindowWeather);            // window id = 2600 WEATHER
1145   g_windowManager.Add(new CGUIWindowStartup);            // startup window (id 2999)
1146
1147   /* window id's 3000 - 3100 are reserved for python */
1148
1149   // Make sure we have at least the default skin
1150   if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
1151   {
1152       CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
1153       FatalErrorHandler(true, true, true);
1154   }
1155
1156   if (g_advancedSettings.m_splashImage)
1157     SAFE_DELETE(m_splash);
1158
1159   if (g_guiSettings.GetBool("masterlock.startuplock") &&
1160       g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1161      !g_settings.GetMasterProfile().getLockCode().IsEmpty())
1162   {
1163      g_passwordManager.CheckStartUpLock();
1164   }
1165
1166   // check if we should use the login screen
1167   if (g_settings.UsingLoginScreen())
1168     g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1169   else
1170   {
1171 #ifdef HAS_JSONRPC
1172     CJSONRPC::Initialize();
1173 #endif
1174     g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1175   }
1176
1177   g_sysinfo.Refresh();
1178
1179   CLog::Log(LOGINFO, "removing tempfiles");
1180   CUtil::RemoveTempFiles();
1181
1182   //  Show mute symbol
1183   if (g_settings.m_bMute)
1184     Mute();
1185
1186   // if the user shutoff the xbox during music scan
1187   // restore the settings
1188   if (g_settings.m_bMyMusicIsScanning)
1189   {
1190     CLog::Log(LOGWARNING,"System rebooted during music scan! ... restoring UseTags and FindRemoteThumbs");
1191     RestoreMusicScanSettings();
1192   }
1193
1194   if (!g_settings.UsingLoginScreen())
1195   {
1196     UpdateLibraries();
1197 #ifdef HAS_PYTHON
1198     g_pythonParser.m_bLogin = true;
1199 #endif
1200   }
1201
1202   m_slowTimer.StartZero();
1203
1204 #if defined(__APPLE__) && !defined(__arm__)
1205   XBMCHelper::GetInstance().CaptureAllInput();
1206 #endif
1207 #if defined(HAVE_LIBCRYSTALHD)
1208   CCrystalHD::GetInstance();
1209 #endif
1210
1211   CAddonMgr::Get().StartServices(false);
1212
1213   CLog::Log(LOGNOTICE, "initialize done");
1214
1215   m_bInitializing = false;
1216
1217   // reset our screensaver (starts timers etc.)
1218   ResetScreenSaver();
1219   return true;
1220 }
1221
1222 bool CApplication::StartWebServer()
1223 {
1224 #ifdef HAS_WEB_SERVER
1225   if (g_guiSettings.GetBool("services.webserver") && m_network.IsAvailable())
1226   {
1227     int webPort = atoi(g_guiSettings.GetString("services.webserverport"));
1228     CLog::Log(LOGNOTICE, "Webserver: Starting...");
1229 #ifdef _LINUX
1230     if (webPort < 1024 && geteuid() != 0)
1231     {
1232         CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
1233         return false;
1234     }
1235 #endif
1236
1237     bool started = false;
1238     if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")))
1239     {
1240       std::map<std::string, std::string> txt; 
1241       started = true;
1242       // publish web frontend and API services
1243 #ifdef HAS_WEB_INTERFACE
1244       CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", "XBMC Web Server", webPort, txt);
1245 #endif
1246 #ifdef HAS_HTTPAPI
1247       CZeroconf::GetInstance()->PublishService("servers.webapi", "_xbmc-web._tcp", "XBMC HTTP API", webPort, txt);
1248 #endif
1249 #ifdef HAS_JSONRPC
1250       CZeroconf::GetInstance()->PublishService("servers.webjsonrpc", "_xbmc-jsonrpc._tcp", "XBMC JSONRPC", webPort, txt);
1251 #endif
1252     }
1253 #ifdef HAS_HTTPAPI
1254     if (g_settings.m_HttpApiBroadcastLevel >= 1)
1255       getApplicationMessenger().HttpApi("broadcastlevel; StartUp;1");
1256 #endif
1257
1258     return started;
1259   }
1260 #endif
1261
1262   return true;
1263 }
1264
1265 void CApplication::StopWebServer()
1266 {
1267 #ifdef HAS_WEB_SERVER
1268   if (m_WebServer.IsStarted())
1269   {
1270     CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1271     m_WebServer.Stop();
1272     if(! m_WebServer.IsStarted() )
1273     {
1274       CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1275       CZeroconf::GetInstance()->RemoveService("servers.webserver");
1276       CZeroconf::GetInstance()->RemoveService("servers.webjsonrpc");
1277       CZeroconf::GetInstance()->RemoveService("servers.webapi");
1278     } else
1279       CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
1280   }
1281 #endif
1282 }
1283
1284 void CApplication::StartAirplayServer()
1285 {
1286 #ifdef HAS_AIRPLAY
1287   if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1288   {
1289     int listenPort = g_advancedSettings.m_airPlayPort;
1290     CStdString password = g_guiSettings.GetString("services.airplaypassword");
1291     bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1292     
1293     if (CAirPlayServer::StartServer(listenPort, true))
1294     {
1295       CAirPlayServer::SetCredentials(usePassword, password);
1296       std::map<std::string, std::string> txt;
1297       CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
1298       if (iface)
1299       {
1300         txt["deviceid"] = iface->GetMacAddress();
1301       }
1302       else
1303       {
1304         txt["deviceid"] = "FF:FF:FF:FF:FF:F2";
1305       }
1306       txt["features"] = "0x77";
1307       txt["model"] = "AppleTV2,1";
1308       txt["srcvers"] = "101.28";
1309       CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt);
1310     }
1311   }
1312 #endif
1313 #ifdef HAS_AIRTUNES
1314   if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1315   {   
1316     int listenPort = g_advancedSettings.m_airTunesPort;  
1317     CStdString password = g_guiSettings.GetString("services.airplaypassword");
1318     bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1319       
1320     if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password))
1321     {
1322       CLog::Log(LOGERROR, "Failed to start AirTunes Server");
1323     }
1324   }
1325 #endif
1326 }
1327
1328 void CApplication::StopAirplayServer(bool bWait)
1329 {
1330 #ifdef HAS_AIRPLAY
1331   CAirPlayServer::StopServer(bWait);
1332   CZeroconf::GetInstance()->RemoveService("servers.airplay");
1333 #endif
1334 #ifdef HAS_AIRTUNES
1335   CAirTunesServer::StopServer(bWait);
1336 #endif
1337 }
1338
1339 bool CApplication::StartJSONRPCServer()
1340 {
1341 #ifdef HAS_JSONRPC
1342   if (g_guiSettings.GetBool("services.esenabled"))
1343   {
1344     if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces")))
1345     {
1346       std::map<std::string, std::string> txt;  
1347       CZeroconf::GetInstance()->PublishService("servers.jsonrpc", "_xbmc-jsonrpc._tcp", "XBMC JSONRPC", g_advancedSettings.m_jsonTcpPort, txt);
1348       return true;
1349     }
1350     else
1351       return false;
1352   }
1353 #endif
1354
1355   return true;
1356 }
1357
1358 void CApplication::StopJSONRPCServer(bool bWait)
1359 {
1360 #ifdef HAS_JSONRPC
1361   CTCPServer::StopServer(bWait);
1362   CZeroconf::GetInstance()->RemoveService("servers.jsonrpc");
1363 #endif
1364 }
1365
1366 void CApplication::StartUPnP()
1367 {
1368 #ifdef HAS_UPNP
1369   StartUPnPServer();
1370   StartUPnPRenderer();
1371 #endif
1372 }
1373
1374 void CApplication::StopUPnP(bool bWait)
1375 {
1376 #ifdef HAS_UPNP
1377   if (CUPnP::IsInstantiated())
1378   {
1379     CLog::Log(LOGNOTICE, "stopping upnp");
1380     CUPnP::ReleaseInstance(bWait);
1381   }
1382 #endif
1383 }
1384
1385 bool CApplication::StartEventServer()
1386 {
1387 #ifdef HAS_EVENT_SERVER
1388   CEventServer* server = CEventServer::GetInstance();
1389   if (!server)
1390   {
1391     CLog::Log(LOGERROR, "ES: Out of memory");
1392     return false;
1393   }
1394   if (g_guiSettings.GetBool("services.esenabled"))
1395   {
1396     CLog::Log(LOGNOTICE, "ES: Starting event server");
1397     server->StartServer();
1398     return true;
1399   }
1400 #endif
1401   return true;
1402 }
1403
1404 bool CApplication::StopEventServer(bool bWait, bool promptuser)
1405 {
1406 #ifdef HAS_EVENT_SERVER
1407   CEventServer* server = CEventServer::GetInstance();
1408   if (!server)
1409   {
1410     CLog::Log(LOGERROR, "ES: Out of memory");
1411     return false;
1412   }
1413   if (promptuser)
1414   {
1415     if (server->GetNumberOfClients() > 0)
1416     {
1417       bool cancelled = false;
1418       if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1419                                             -1, -1, cancelled, 10000)
1420           || cancelled)
1421       {
1422         CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1423         return false;
1424       }
1425     }
1426     CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1427
1428     CEventServer::GetInstance()->StopServer(true);
1429   }
1430   else
1431   {
1432     if (!bWait)
1433       CLog::Log(LOGNOTICE, "ES: Stopping event server");
1434
1435     CEventServer::GetInstance()->StopServer(bWait);
1436   }
1437
1438   return true;
1439 #endif
1440 }
1441
1442 void CApplication::RefreshEventServer()
1443 {
1444 #ifdef HAS_EVENT_SERVER
1445   if (g_guiSettings.GetBool("services.esenabled"))
1446   {
1447     CEventServer::GetInstance()->RefreshSettings();
1448   }
1449 #endif
1450 }
1451
1452 void CApplication::StartUPnPRenderer()
1453 {
1454 #ifdef HAS_UPNP
1455   if (g_guiSettings.GetBool("services.upnprenderer"))
1456   {
1457     CLog::Log(LOGNOTICE, "starting upnp renderer");
1458     CUPnP::GetInstance()->StartRenderer();
1459   }
1460 #endif
1461 }
1462
1463 void CApplication::StopUPnPRenderer()
1464 {
1465 #ifdef HAS_UPNP
1466   if (CUPnP::IsInstantiated())
1467   {
1468     CLog::Log(LOGNOTICE, "stopping upnp renderer");
1469     CUPnP::GetInstance()->StopRenderer();
1470   }
1471 #endif
1472 }
1473
1474 void CApplication::StartUPnPServer()
1475 {
1476 #ifdef HAS_UPNP
1477   if (g_guiSettings.GetBool("services.upnpserver"))
1478   {
1479     CLog::Log(LOGNOTICE, "starting upnp server");
1480     CUPnP::GetInstance()->StartServer();
1481   }
1482 #endif
1483 }
1484
1485 void CApplication::StopUPnPServer()
1486 {
1487 #ifdef HAS_UPNP
1488   if (CUPnP::IsInstantiated())
1489   {
1490     CLog::Log(LOGNOTICE, "stopping upnp server");
1491     CUPnP::GetInstance()->StopServer();
1492   }
1493 #endif
1494 }
1495
1496 void CApplication::StartZeroconf()
1497 {
1498 #ifdef HAS_ZEROCONF
1499   //entry in guisetting only present if HAS_ZEROCONF is set
1500   if(g_guiSettings.GetBool("services.zeroconf"))
1501   {
1502     CLog::Log(LOGNOTICE, "starting zeroconf publishing");
1503     CZeroconf::GetInstance()->Start();
1504   }
1505 #endif
1506 }
1507
1508 void CApplication::StopZeroconf()
1509 {
1510 #ifdef HAS_ZEROCONF
1511   if(CZeroconf::IsInstantiated())
1512   {
1513     CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
1514     CZeroconf::GetInstance()->Stop();
1515   }
1516 #endif
1517 }
1518
1519 void CApplication::DimLCDOnPlayback(bool dim)
1520 {
1521 #ifdef HAS_LCD
1522   if (g_lcd)
1523   {
1524     if (dim)
1525       g_lcd->DisableOnPlayback(IsPlayingVideo(), IsPlayingAudio());
1526     else
1527       g_lcd->SetBackLight(1);
1528   }
1529 #endif
1530 }
1531
1532 void CApplication::StartServices()
1533 {
1534 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1535   // Start Thread for DVD Mediatype detection
1536   CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1537   m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1538 #endif
1539
1540   CLog::Log(LOGNOTICE, "initializing playlistplayer");
1541   g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1542   g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistShuffle);
1543   g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1544   g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistShuffle);
1545   CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1546
1547 #ifdef HAS_LCD
1548   CLCDFactory factory;
1549   g_lcd = factory.Create();
1550   if (g_lcd)
1551   {
1552     g_lcd->Initialize();
1553   }
1554 #endif
1555 }
1556
1557 void CApplication::StopServices()
1558 {
1559   m_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1560
1561 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1562   CLog::Log(LOGNOTICE, "stop dvd detect media");
1563   m_DetectDVDType.StopThread();
1564 #endif
1565
1566   g_peripherals.Clear();
1567 }
1568
1569 void CApplication::ReloadSkin()
1570 {
1571   m_skinReloading = false;
1572   CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1573   g_windowManager.SendMessage(msg);
1574   // Reload the skin, restoring the previously focused control.  We need this as
1575   // the window unload will reset all control states.
1576   CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1577   int iCtrlID = pWindow->GetFocusedControlID();
1578   g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1579   pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1580   if (pWindow && pWindow->HasSaveLastControl())
1581   {
1582     CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1583     pWindow->OnMessage(msg3);
1584   }
1585 }
1586
1587 bool CApplication::LoadSkin(const CStdString& skinID)
1588 {
1589   if (m_skinReloading)
1590     return false;
1591
1592   AddonPtr addon;
1593   if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1594   {
1595     LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1596     return true;
1597   }
1598   return false;
1599 }
1600
1601 void CApplication::LoadSkin(const SkinPtr& skin)
1602 {
1603   if (!skin)
1604   {
1605     CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN);
1606     g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1607     LoadSkin(DEFAULT_SKIN);
1608     return ;
1609   }
1610
1611   bool bPreviousPlayingState=false;
1612   bool bPreviousRenderingState=false;
1613   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1614   {
1615     bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1616     if (bPreviousPlayingState)
1617       g_application.m_pPlayer->Pause();
1618 #ifdef HAS_VIDEO_PLAYBACK
1619     if (!g_renderManager.Paused())
1620     {
1621       if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1622      {
1623         g_windowManager.ActivateWindow(WINDOW_HOME);
1624         bPreviousRenderingState = true;
1625       }
1626     }
1627 #endif
1628   }
1629   // close the music and video overlays (they're re-opened automatically later)
1630   CSingleLock lock(g_graphicsContext);
1631
1632   // save the current window details
1633   int currentWindow = g_windowManager.GetActiveWindow();
1634   vector<int> currentModelessWindows;
1635   g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1636
1637   UnloadSkin();
1638
1639   CLog::Log(LOGINFO, "  load skin from:%s", skin->Path().c_str());
1640   g_SkinInfo = skin;
1641   g_SkinInfo->Start();
1642
1643   CLog::Log(LOGINFO, "  load fonts for skin...");
1644   g_graphicsContext.SetMediaDir(skin->Path());
1645   g_directoryCache.ClearSubPaths(skin->Path());
1646   if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1647   {
1648     CLog::Log(LOGINFO, "    language needs a ttf font, loading first ttf font available");
1649     CStdString strFontSet;
1650     if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1651     {
1652       CLog::Log(LOGINFO, "    new font is '%s'", strFontSet.c_str());
1653       g_guiSettings.SetString("lookandfeel.font", strFontSet);
1654       g_settings.Save();
1655     }
1656     else
1657       CLog::Log(LOGERROR, "    no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1658   }
1659   g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1660
1661   g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1662
1663   // load in the skin strings
1664   CStdString langPath, skinEnglishPath;
1665   URIUtils::AddFileToFolder(skin->Path(), "language", langPath);
1666   URIUtils::AddFileToFolder(langPath, g_guiSettings.GetString("locale.language"), langPath);
1667   URIUtils::AddFileToFolder(langPath, "strings.xml", langPath);
1668
1669   URIUtils::AddFileToFolder(skin->Path(), "language", skinEnglishPath);
1670   URIUtils::AddFileToFolder(skinEnglishPath, "English", skinEnglishPath);
1671   URIUtils::AddFileToFolder(skinEnglishPath, "strings.xml", skinEnglishPath);
1672
1673   g_localizeStrings.LoadSkinStrings(langPath, skinEnglishPath);
1674
1675   g_SkinInfo->LoadIncludes();
1676
1677   int64_t start;
1678   start = CurrentHostCounter();
1679
1680   CLog::Log(LOGINFO, "  load new skin...");
1681   CGUIWindowHome *pHome = (CGUIWindowHome *)g_windowManager.GetWindow(WINDOW_HOME);
1682   if (!pHome || !pHome->Load("Home.xml"))
1683   {
1684     // failed to load home.xml
1685     // fallback to default skin
1686     if ( strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
1687     {
1688       CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
1689       g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1690       LoadSkin(DEFAULT_SKIN);
1691       return ;
1692     }
1693   }
1694
1695   // Load the user windows
1696   LoadUserWindows();
1697
1698   int64_t end, freq;
1699   end = CurrentHostCounter();
1700   freq = CurrentHostFrequency();
1701   CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1702
1703   CLog::Log(LOGINFO, "  initialize new skin...");
1704   g_windowManager.AddMsgTarget(this);
1705   g_windowManager.AddMsgTarget(&g_playlistPlayer);
1706   g_windowManager.AddMsgTarget(&g_infoManager);
1707   g_windowManager.AddMsgTarget(&g_fontManager);
1708   g_windowManager.SetCallback(*this);
1709   g_windowManager.Initialize();
1710   CTextureCache::Get().Initialize();
1711   g_audioManager.Enable(true);
1712   g_audioManager.Load();
1713
1714   if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1715     g_windowManager.Add(new CGUIDialogFullScreenInfo);
1716
1717   { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1718     CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1719     if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1720     overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1721     if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1722   }
1723
1724   CLog::Log(LOGINFO, "  skin loaded...");
1725
1726   // leave the graphics lock
1727   lock.Leave();
1728
1729   // restore windows
1730   if (currentWindow != WINDOW_INVALID)
1731   {
1732     g_windowManager.ActivateWindow(currentWindow);
1733     for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1734     {
1735       CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1736       if (dialog) dialog->Show();
1737     }
1738   }
1739
1740   if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1741   {
1742     if (bPreviousPlayingState)
1743       g_application.m_pPlayer->Pause();
1744     if (bPreviousRenderingState)
1745       g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1746   }
1747 }
1748
1749 void CApplication::UnloadSkin(bool forReload /* = false */)
1750 {
1751   m_skinReloading = forReload;
1752
1753   CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1754
1755   g_audioManager.Enable(false);
1756
1757   g_windowManager.DeInitialize();
1758   CTextureCache::Get().Deinitialize();
1759
1760   // remove the skin-dependent window
1761   g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1762
1763   g_TextureManager.Cleanup();
1764   g_largeTextureManager.CleanupUnusedImages(true);
1765
1766   g_fontManager.Clear();
1767
1768   g_colorManager.Clear();
1769
1770   g_charsetConverter.reset();
1771
1772   g_infoManager.Clear();
1773 }
1774
1775 bool CApplication::LoadUserWindows()
1776 {
1777   // Start from wherever home.xml is
1778   std::vector<CStdString> vecSkinPath;
1779   g_SkinInfo->GetSkinPaths(vecSkinPath);
1780   for (unsigned int i = 0;i < vecSkinPath.size();++i)
1781   {
1782     CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1783     CFileItemList items;
1784     if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", false))
1785     {
1786       for (int i = 0; i < items.Size(); ++i)
1787       {
1788         if (items[i]->m_bIsFolder)
1789           continue;
1790         CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1791         if (skinFile.Left(6).CompareNoCase("custom") == 0)
1792         {
1793           TiXmlDocument xmlDoc;
1794           if (!xmlDoc.LoadFile(items[i]->GetPath()))
1795           {
1796             CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1797             continue;
1798           }
1799
1800           // Root element should be <window>
1801           TiXmlElement* pRootElement = xmlDoc.RootElement();
1802           CStdString strValue = pRootElement->Value();
1803           if (!strValue.Equals("window"))
1804           {
1805             CLog::Log(LOGERROR, "file :%s doesnt contain <window>", skinFile.c_str());
1806             continue;
1807           }
1808
1809           // Read the <type> element to get the window type to create
1810           // If no type is specified, create a CGUIWindow as default
1811           CGUIWindow* pWindow = NULL;
1812           CStdString strType;
1813           if (pRootElement->Attribute("type"))
1814             strType = pRootElement->Attribute("type");
1815           else
1816           {
1817             const TiXmlNode *pType = pRootElement->FirstChild("type");
1818             if (pType && pType->FirstChild())
1819               strType = pType->FirstChild()->Value();
1820           }
1821           int id = WINDOW_INVALID;
1822           if (!pRootElement->Attribute("id", &id))
1823           {
1824             const TiXmlNode *pType = pRootElement->FirstChild("id");
1825             if (pType && pType->FirstChild())
1826               id = atol(pType->FirstChild()->Value());
1827           }
1828           CStdString visibleCondition;
1829           CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1830
1831           if (strType.Equals("dialog"))
1832             pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1833           else if (strType.Equals("submenu"))
1834             pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
1835           else if (strType.Equals("buttonmenu"))
1836             pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
1837           else
1838             pWindow = new CGUIStandardWindow(id + WINDOW_HOME, skinFile);
1839
1840           // Check to make sure the pointer isn't still null
1841           if (pWindow == NULL)
1842           {
1843             CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
1844             return false;
1845           }
1846           if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
1847           {
1848             delete pWindow;
1849             continue;
1850           }
1851           pWindow->SetVisibleCondition(visibleCondition);
1852           g_windowManager.AddCustomWindow(pWindow);
1853         }
1854       }
1855     }
1856   }
1857   return true;
1858 }
1859
1860 bool CApplication::RenderNoPresent()
1861 {
1862   MEASURE_FUNCTION;
1863
1864 // DXMERGE: This may have been important?
1865 //  g_graphicsContext.AcquireCurrentContext();
1866
1867   g_graphicsContext.Lock();
1868
1869   // dont show GUI when playing full screen video
1870   if (g_graphicsContext.IsFullScreenVideo())
1871   {
1872     if (m_bPresentFrame && IsPlaying() && !IsPaused())
1873     {
1874       ResetScreenSaver();
1875       g_renderManager.Present();
1876     }
1877     else
1878       g_renderManager.RenderUpdate(true);
1879
1880     // close window overlays
1881     CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1882     if (overlay) overlay->Close(true);
1883     overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1884     if (overlay) overlay->Close(true);
1885
1886   }
1887
1888   bool hasRendered = g_windowManager.Render();
1889
1890   // if we're recording an audio stream then show blinking REC
1891   if (!g_graphicsContext.IsFullScreenVideo())
1892   {
1893     if (m_pPlayer && m_pPlayer->IsRecording() )
1894     {
1895       static int iBlinkRecord = 0;
1896       iBlinkRecord++;
1897       if (iBlinkRecord > 25)
1898       {
1899         CGUIFont* pFont = g_fontManager.GetFont("font13");
1900         CGUITextLayout::DrawText(pFont, 60, 50, 0xffff0000, 0, "REC", 0);
1901       }
1902
1903       if (iBlinkRecord > 50)
1904         iBlinkRecord = 0;
1905     }
1906   }
1907
1908   g_graphicsContext.Unlock();
1909
1910   return hasRendered;
1911 }
1912
1913 float CApplication::GetDimScreenSaverLevel() const
1914 {
1915   if (!m_bScreenSave || !m_screenSaver ||
1916       (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
1917        m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
1918        m_screenSaver->ID() != "screensaver.xbmc.builtin.slideshow"))
1919     return 0;
1920
1921   if (!m_screenSaver->GetSetting("level").IsEmpty())
1922     return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
1923   return 100.0f;
1924 }
1925
1926 bool CApplication::WaitFrame(unsigned int timeout)
1927 {
1928   bool done = false;
1929
1930   // Wait for all other frames to be presented
1931   CSingleLock lock(m_frameMutex);
1932   //wait until event is set, but modify remaining time
1933
1934   TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
1935   cv.wait(lock,timeout);
1936   done = m_frameCount == 0;
1937
1938   return done;
1939 }
1940
1941 void CApplication::NewFrame()
1942 {
1943   // We just posted another frame. Keep track and notify.
1944   {
1945     CSingleLock lock(m_frameMutex);
1946     m_frameCount++;
1947   }
1948
1949   m_frameCond.notifyAll();
1950 }
1951
1952 void CApplication::Render()
1953 {
1954   // do not render if we are stopped
1955   if (m_bStop)
1956     return;
1957
1958   if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
1959   {
1960     Sleep(1);
1961     ResetScreenSaver();
1962     return;
1963   }
1964
1965   MEASURE_FUNCTION;
1966
1967   int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
1968
1969   bool decrement = false;
1970   bool hasRendered = false;
1971   bool limitFrames = false;
1972   unsigned int singleFrameTime = 10; // default limit 100 fps
1973
1974   {
1975     // Less fps in DPMS
1976     bool lowfps = m_dpmsIsActive;
1977     // Whether externalplayer is playing and we're unfocused
1978     bool extPlayerActive = m_eCurrentPlayer >= EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
1979
1980     m_bPresentFrame = false;
1981     if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
1982     {
1983       CSingleLock lock(m_frameMutex);
1984
1985       TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
1986       cv.wait(lock,100);
1987
1988       m_bPresentFrame = m_frameCount > 0;
1989       decrement = m_bPresentFrame;
1990       hasRendered = true;
1991     }
1992     else
1993     {
1994       // engage the frame limiter as needed
1995       limitFrames = lowfps || extPlayerActive;
1996       // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
1997       //           perhaps allowing it to be set differently than the UI option??
1998       if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
1999         limitFrames = true; // not using vsync.
2000       else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2001         limitFrames = true; // using vsync, but it isn't working.
2002
2003       if (limitFrames)
2004       {
2005         if (extPlayerActive)
2006         {
2007           ResetScreenSaver();  // Prevent screensaver dimming the screen
2008           singleFrameTime = 1000;  // 1 fps, high wakeup latency but v.low CPU usage
2009         }
2010         else if (lowfps)
2011           singleFrameTime = 200;  // 5 fps, <=200 ms latency to wake up
2012       }
2013
2014       decrement = true;
2015     }
2016   }
2017
2018   CSingleLock lock(g_graphicsContext);
2019   g_infoManager.UpdateFPS();
2020
2021   if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2022     g_Windowing.SetVSync(true);
2023   else if (vsync_mode == VSYNC_ALWAYS)
2024     g_Windowing.SetVSync(true);
2025   else if (vsync_mode != VSYNC_DRIVER)
2026     g_Windowing.SetVSync(false);
2027
2028   if(!g_Windowing.BeginRender())
2029     return;
2030
2031   CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2032   if (RenderNoPresent())
2033     hasRendered = true;
2034
2035   g_Windowing.EndRender();
2036
2037   g_TextureManager.FreeUnusedTextures();
2038
2039   // reset our info cache - we do this at the end of Render so that it is
2040   // fresh for the next process(), or after a windowclose animation (where process()
2041   // isn't called)
2042   g_infoManager.ResetCache();
2043
2044   lock.Leave();
2045
2046   unsigned int now = XbmcThreads::SystemClockMillis();
2047   if (hasRendered)
2048     m_lastRenderTime = now;
2049
2050   //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2051   //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2052   bool flip;
2053   if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2054     flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2055   else
2056     flip = true;
2057
2058   //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2059   if (limitFrames || !flip)
2060   {
2061     if (!limitFrames)
2062       singleFrameTime = 40; //if not flipping, loop at 25 fps
2063
2064     unsigned int frameTime = now - m_lastFrameTime;
2065     if (frameTime < singleFrameTime)
2066       Sleep(singleFrameTime - frameTime);
2067   }
2068   m_lastFrameTime = XbmcThreads::SystemClockMillis();
2069
2070   if (flip)
2071     g_graphicsContext.Flip(dirtyRegions);
2072   CTimeUtils::UpdateFrameTime(flip);
2073
2074   g_renderManager.UpdateResolution();
2075   g_renderManager.ManageCaptures();
2076
2077   {
2078     CSingleLock lock(m_frameMutex);
2079     if(m_frameCount > 0 && decrement)
2080       m_frameCount--;
2081   }
2082   m_frameCond.notifyAll();
2083 }
2084
2085 void CApplication::SetStandAlone(bool value)
2086 {
2087   g_advancedSettings.m_handleMounting = m_bStandalone = value;
2088 }
2089
2090 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2091 // The window manager will return true if the event is processed, false otherwise.
2092 // If not already processed, this routine handles global keypresses.  It returns
2093 // true if the key has been processed, false otherwise.
2094
2095 bool CApplication::OnKey(const CKey& key)
2096 {
2097
2098   // Turn the mouse off, as we've just got a keypress from controller or remote
2099   g_Mouse.SetActive(false);
2100
2101   // get the current active window
2102   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2103
2104   // this will be checked for certain keycodes that need
2105   // special handling if the screensaver is active
2106   CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2107
2108   // a key has been pressed.
2109   // reset Idle Timer
2110   m_idleTimer.StartZero();
2111   bool processKey = AlwaysProcess(action);
2112
2113   ResetScreenSaver();
2114
2115   // allow some keys to be processed while the screensaver is active
2116   if (WakeUpScreenSaverAndDPMS() && !processKey)
2117   {
2118     CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2119     return true;
2120   }
2121
2122   // change this if we have a dialog up
2123   if (g_windowManager.HasModalDialog())
2124   {
2125     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2126   }
2127   if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2128   { // fullscreen info dialog - special case
2129     action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2130
2131     if (!key.IsAnalogButton())
2132       CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2133
2134     if (OnAction(action))
2135       return true;
2136
2137     // fallthrough to the main window
2138     iWin = WINDOW_FULLSCREEN_VIDEO;
2139   }
2140   if (iWin == WINDOW_FULLSCREEN_VIDEO)
2141   {
2142     // current active window is full screen video.
2143     if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2144     {
2145       // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2146       action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2147     }
2148     else
2149     {
2150       // no then use the fullscreen window section of keymap.xml to map key->action
2151       action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2152     }
2153   }
2154   else
2155   {
2156     // current active window isnt the fullscreen window
2157     // just use corresponding section from keymap.xml
2158     // to map key->action
2159
2160     // first determine if we should use keyboard input directly
2161     bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2162     CGUIWindow *window = g_windowManager.GetWindow(iWin);
2163     if (window)
2164     {
2165       CGUIControl *control = window->GetFocusedControl();
2166       if (control)
2167       {
2168         // If this is an edit control set usekeyboard to true. This causes the
2169         // keypress to be processed directly not through the key mappings.
2170         if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2171           useKeyboard = true;
2172
2173         // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2174         // This causes the keypress to be used for list navigation.
2175         if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2176           useKeyboard = true;
2177       }
2178     }
2179     if (useKeyboard)
2180     {
2181       action = CAction(0); // reset our action
2182       if (g_guiSettings.GetBool("input.remoteaskeyboard"))
2183       {
2184         // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2185         // and send those rather than actual keyboard presses.  Only for navigation-type commands though
2186         action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2187         if (!(action.GetID() == ACTION_MOVE_LEFT ||
2188               action.GetID() == ACTION_MOVE_RIGHT ||
2189               action.GetID() == ACTION_MOVE_UP ||
2190               action.GetID() == ACTION_MOVE_DOWN ||
2191               action.GetID() == ACTION_SELECT_ITEM ||
2192               action.GetID() == ACTION_ENTER ||
2193               action.GetID() == ACTION_PREVIOUS_MENU ||
2194               action.GetID() == ACTION_NAV_BACK))
2195         {
2196           // the action isn't plain navigation - check for a keyboard-specific keymap
2197           action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2198           if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2199                 action.GetID() == ACTION_BACKSPACE ||
2200                 action.GetID() == ACTION_SHIFT ||
2201                 action.GetID() == ACTION_SYMBOLS ||
2202                 action.GetID() == ACTION_CURSOR_LEFT ||
2203                 action.GetID() == ACTION_CURSOR_RIGHT)
2204             action = CAction(0); // don't bother with this action
2205         }
2206       }
2207       if (!action.GetID())
2208       {
2209         // keyboard entry - pass the keys through directly
2210         if (key.GetFromHttpApi())
2211           action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2212         else
2213         { // see if we've got an ascii key
2214           if (key.GetUnicode())
2215             action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2216           else
2217             action = CAction(key.GetVKey() | KEY_VKEY);
2218         }
2219       }
2220
2221       CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2222
2223       if (OnAction(action))
2224         return true;
2225       // failed to handle the keyboard action, drop down through to standard action
2226     }
2227     if (key.GetFromHttpApi())
2228     {
2229       if (key.GetButtonCode() != KEY_INVALID)
2230         action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2231     }
2232     else
2233       action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2234   }
2235   if (!key.IsAnalogButton())
2236     CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2237
2238   //  Play a sound based on the action
2239   g_audioManager.PlayActionSound(action);
2240
2241   return OnAction(action);
2242 }
2243
2244 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2245 // This needs to return true if it processed the appcommand or false if it didn't
2246 bool CApplication::OnAppCommand(const CAction &action)
2247 {
2248   // Reset the screen saver
2249   ResetScreenSaver();
2250
2251   // If we were currently in the screen saver wake up and don't process the appcommand
2252   if (WakeUpScreenSaverAndDPMS())
2253     return true;
2254
2255   // The action ID is the APPCOMMAND code. We need to retrieve the action
2256   // associated with this appcommand from the mapping table.
2257   uint32_t appcmd = action.GetID();
2258   CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2259   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2260   CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2261
2262   // If we couldn't find an action return false to indicate we have not
2263   // handled this appcommand
2264   if (!appcmdaction.GetID())
2265   {
2266     CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2267     return false;
2268   }
2269
2270   // Process the appcommand
2271   CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2272   OnAction(appcmdaction);
2273
2274   // Always return true regardless of whether the action succeeded or not.
2275   // This stops Windows handling the appcommand itself.
2276   return true;
2277 }
2278
2279 bool CApplication::OnAction(const CAction &action)
2280 {
2281 #ifdef HAS_HTTPAPI
2282   // Let's tell the outside world about this action, ignoring mouse moves
2283   if (g_settings.m_HttpApiBroadcastLevel>=2 && action.GetID() != ACTION_MOUSE_MOVE)
2284   {
2285     CStdString tmp;
2286     tmp.Format("%i",action.GetID());
2287     getApplicationMessenger().HttpApi("broadcastlevel; OnAction:"+tmp+";2");
2288   }
2289 #endif
2290
2291   // special case for switching between GUI & fullscreen mode.
2292   if (action.GetID() == ACTION_SHOW_GUI)
2293   { // Switch to fullscreen mode if we can
2294     if (SwitchToFullScreen())
2295     {
2296       m_navigationTimer.StartZero();
2297       return true;
2298     }
2299   }
2300
2301   if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2302   {
2303     g_graphicsContext.ToggleFullScreenRoot();
2304     return true;
2305   }
2306
2307   if (action.IsMouse())
2308     g_Mouse.SetActive(true);
2309
2310   // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2311   // playing or ACTION_PLAYER_PLAY if we are not playing.
2312   if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2313   {
2314     if (IsPlaying())
2315       return OnAction(CAction(ACTION_PAUSE));
2316     else
2317       return OnAction(CAction(ACTION_PLAYER_PLAY));
2318   }
2319
2320   //if the action would start or stop inertial scrolling
2321   //by gesture - bypass the normal OnAction handler of current window
2322   if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2323   {
2324     // in normal case
2325     // just pass the action to the current window and let it handle it
2326     if (g_windowManager.OnAction(action))
2327     {
2328       m_navigationTimer.StartZero();
2329       return true;
2330     }
2331   } 
2332
2333   // handle extra global presses
2334
2335   // screenshot : take a screenshot :)
2336   if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2337   {
2338     CUtil::TakeScreenshot();
2339     return true;
2340   }
2341   // built in functions : execute the built-in
2342   if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2343   {
2344     CBuiltins::Execute(action.GetName());
2345     m_navigationTimer.StartZero();
2346     return true;
2347   }
2348
2349   // reload keymaps
2350   if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2351   {
2352     CButtonTranslator::GetInstance().Clear();
2353     CButtonTranslator::GetInstance().Load();
2354   }
2355
2356   // show info : Shows the current video or song information
2357   if (action.GetID() == ACTION_SHOW_INFO)
2358   {
2359     g_infoManager.ToggleShowInfo();
2360     return true;
2361   }
2362
2363   // codec info : Shows the current song, video or picture codec information
2364   if (action.GetID() == ACTION_SHOW_CODEC)
2365   {
2366     g_infoManager.ToggleShowCodec();
2367     return true;
2368   }
2369
2370   if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2371   {
2372     const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2373     if (tag)
2374     {
2375       *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2376       char rating = tag->GetRating();
2377       bool needsUpdate(false);
2378       if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2379       {
2380         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2381         needsUpdate = true;
2382       }
2383       else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2384       {
2385         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2386         needsUpdate = true;
2387       }
2388       if (needsUpdate)
2389       {
2390         CMusicDatabase db;
2391         if (db.Open())      // OpenForWrite() ?
2392         {
2393           db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2394           db.Close();
2395         }
2396         // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2397         CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2398         g_windowManager.SendMessage(msg);
2399       }
2400     }
2401     return true;
2402   }
2403
2404   // stop : stops playing current audio song
2405   if (action.GetID() == ACTION_STOP)
2406   {
2407     StopPlaying();
2408     return true;
2409   }
2410
2411   // previous : play previous song from playlist
2412   if (action.GetID() == ACTION_PREV_ITEM)
2413   {
2414     // first check whether we're within 3 seconds of the start of the track
2415     // if not, we just revert to the start of the track
2416     if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2417     {
2418       SeekTime(0);
2419       SetPlaySpeed(1);
2420     }
2421     else
2422     {
2423       g_playlistPlayer.PlayPrevious();
2424     }
2425     return true;
2426   }
2427
2428   // next : play next song from playlist
2429   if (action.GetID() == ACTION_NEXT_ITEM)
2430   {
2431     if (IsPlaying() && m_pPlayer->SkipNext())
2432       return true;
2433
2434     g_playlistPlayer.PlayNext();
2435
2436     return true;
2437   }
2438
2439   if ( IsPlaying())
2440   {
2441     // pause : pauses current audio song
2442     if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2443     {
2444       m_pPlayer->Pause();
2445 #ifdef HAS_KARAOKE
2446       m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2447 #endif
2448       if (!m_pPlayer->IsPaused())
2449       { // unpaused - set the playspeed back to normal
2450         SetPlaySpeed(1);
2451       }
2452       g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2453       return true;
2454     }
2455     if (!m_pPlayer->IsPaused())
2456     {
2457       // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2458       // if we are playing at normal speed, then allow play to pause
2459       if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2460       {
2461         if (m_iPlaySpeed != 1)
2462         {
2463           SetPlaySpeed(1);
2464         }
2465         else
2466         {
2467           m_pPlayer->Pause();
2468         }
2469         return true;
2470       }
2471       if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2472       {
2473         int iPlaySpeed = m_iPlaySpeed;
2474         if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2475           iPlaySpeed *= -2;
2476         else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2477           iPlaySpeed /= 2;
2478         else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2479           iPlaySpeed /= 2;
2480         else
2481           iPlaySpeed *= 2;
2482
2483         if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2484           iPlaySpeed = 1;
2485         if (iPlaySpeed > 32 || iPlaySpeed < -32)
2486           iPlaySpeed = 1;
2487
2488         SetPlaySpeed(iPlaySpeed);
2489         return true;
2490       }
2491       else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2492       {
2493         // calculate the speed based on the amount the button is held down
2494         int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2495         // returns 0 -> MAX_FFWD_SPEED
2496         int iSpeed = 1 << iPower;
2497         if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2498           iSpeed = -iSpeed;
2499         g_application.SetPlaySpeed(iSpeed);
2500         if (iSpeed == 1)
2501           CLog::Log(LOGDEBUG,"Resetting playspeed");
2502         return true;
2503       }
2504     }
2505     // allow play to unpause
2506     else
2507     {
2508       if (action.GetID() == ACTION_PLAYER_PLAY)
2509       {
2510         // unpause, and set the playspeed back to normal
2511         m_pPlayer->Pause();
2512         g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2513
2514         g_application.SetPlaySpeed(1);
2515         return true;
2516       }
2517     }
2518   }
2519   if (action.GetID() == ACTION_MUTE)
2520   {
2521     ToggleMute();
2522     return true;
2523   }
2524
2525   if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2526   {
2527     switch(g_guiSettings.GetInt("audiooutput.mode"))
2528     {
2529       case AUDIO_ANALOG: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958); break;
2530       case AUDIO_IEC958: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI  ); break;
2531       case AUDIO_HDMI  : g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG); break;
2532     }
2533
2534     g_application.Restart();
2535     if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2536     {
2537       CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2538       g_windowManager.SendMessage(msg);
2539     }
2540     return true;
2541   }
2542
2543   // Check for global volume control
2544   if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2545   {
2546     if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2547     {
2548       // increase or decrease the volume
2549       int volume;
2550       if (g_settings.m_bMute)
2551       {
2552         volume = (int)((float)g_settings.m_iPreMuteVolumeLevel * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
2553         UnMute();
2554       }
2555       else
2556         volume = g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel;
2557
2558       // calculate speed so that a full press will equal 1 second from min to max
2559       float speed = float(VOLUME_MAXIMUM - VOLUME_MINIMUM);
2560       if (action.GetRepeat())
2561         speed *= action.GetRepeat();
2562       else
2563         speed /= 50; //50 fps
2564
2565       if (action.GetID() == ACTION_VOLUME_UP)
2566         volume += (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2567       else
2568         volume -= (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2569
2570       SetVolume(volume, false);
2571     }
2572     // show visual feedback of volume change...
2573     ShowVolumeBar(&action);
2574     return true;
2575   }
2576   // Check for global seek control
2577   if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2578   {
2579     if (!m_pPlayer->CanSeek()) return false;
2580     CGUIWindow *seekBar = g_windowManager.GetWindow(WINDOW_DIALOG_SEEK_BAR);
2581     if (seekBar)
2582       seekBar->OnAction(action);
2583     return true;
2584   }
2585   if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2586   {
2587     CGUIControlProfiler::Instance().SetOutputFile(_P("special://home/guiprofiler.xml"));
2588     CGUIControlProfiler::Instance().Start();
2589     return true;
2590   }
2591   if (action.GetID() == ACTION_SHOW_PLAYLIST)
2592   {
2593     int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2594     if (iPlaylist == PLAYLIST_VIDEO)
2595       g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2596     else if (iPlaylist == PLAYLIST_MUSIC)
2597       g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2598     return true;
2599   }
2600   return false;
2601 }
2602
2603 void CApplication::UpdateLCD()
2604 {
2605 #ifdef HAS_LCD
2606   static unsigned int lTickCount = 0;
2607
2608   if (!g_lcd || !g_guiSettings.GetBool("videoscreen.haslcd"))
2609     return ;
2610   unsigned int lTimeOut = 1000;
2611   if ( m_iPlaySpeed != 1)
2612     lTimeOut = 0;
2613   if ( (XbmcThreads::SystemClockMillis() - lTickCount) >= lTimeOut)
2614   {
2615     if (g_application.NavigationIdleTime() < 5)
2616       g_lcd->Render(ILCD::LCD_MODE_NAVIGATION);
2617     else if (IsPlayingVideo())
2618       g_lcd->Render(ILCD::LCD_MODE_VIDEO);
2619     else if (IsPlayingAudio())
2620       g_lcd->Render(ILCD::LCD_MODE_MUSIC);
2621     else if (IsInScreenSaver())
2622       g_lcd->Render(ILCD::LCD_MODE_SCREENSAVER);
2623     else
2624       g_lcd->Render(ILCD::LCD_MODE_GENERAL);
2625
2626     // reset tick count
2627     lTickCount = XbmcThreads::SystemClockMillis();
2628   }
2629 #endif
2630 }
2631
2632 void CApplication::FrameMove(bool processEvents)
2633 {
2634   MEASURE_FUNCTION;
2635
2636   if (processEvents)
2637   {
2638     // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2639     float frameTime = m_frameTime.GetElapsedSeconds();
2640     m_frameTime.StartZero();
2641     // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2642     if( frameTime > 0.5 ) frameTime = 0.5;
2643
2644     g_graphicsContext.Lock();
2645     // check if there are notifications to display
2646     CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2647     if (toast && toast->DoWork())
2648     {
2649       if (!toast->IsDialogRunning())
2650       {
2651         toast->Show();
2652       }
2653     }
2654     g_graphicsContext.Unlock();
2655
2656     UpdateLCD();
2657
2658 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2659     // Read the input from a remote
2660     g_RemoteControl.Update();
2661 #endif
2662
2663     // process input actions
2664     CWinEvents::MessagePump();
2665     ProcessHTTPApiButtons();
2666     ProcessRemote(frameTime);
2667     ProcessGamepad(frameTime);
2668     ProcessEventServer(frameTime);
2669     ProcessPeripherals(frameTime);
2670     m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2671   }
2672   if (!m_bStop)
2673     g_windowManager.Process(CTimeUtils::GetFrameTime());
2674   g_windowManager.FrameMove();
2675 }
2676
2677 bool CApplication::ProcessGamepad(float frameTime)
2678 {
2679 #ifdef HAS_SDL_JOYSTICK
2680   if (!m_AppFocused)
2681     return false;
2682   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2683   if (g_windowManager.HasModalDialog())
2684   {
2685     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2686   }
2687   int bid;
2688   g_Joystick.Update();
2689   if (g_Joystick.GetButton(bid))
2690   {
2691     // reset Idle Timer
2692     m_idleTimer.StartZero();
2693
2694     ResetScreenSaver();
2695     if (WakeUpScreenSaverAndDPMS())
2696     {
2697       g_Joystick.Reset(true);
2698       return true;
2699     }
2700
2701     int actionID;
2702     CStdString actionName;
2703     bool fullrange;
2704     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2705     {
2706       CAction action(actionID, 1.0f, 0.0f, actionName);
2707       g_audioManager.PlayActionSound(action);
2708       g_Joystick.Reset();
2709       g_Mouse.SetActive(false);
2710       return OnAction(action);
2711     }
2712     else
2713     {
2714       g_Joystick.Reset();
2715     }
2716   }
2717   if (g_Joystick.GetAxis(bid))
2718   {
2719     if (g_Joystick.GetAmount() < 0)
2720     {
2721       bid = -bid;
2722     }
2723
2724     int actionID;
2725     CStdString actionName;
2726     bool fullrange;
2727     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2728     {
2729       ResetScreenSaver();
2730       if (WakeUpScreenSaverAndDPMS())
2731       {
2732         return true;
2733       }
2734
2735       CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2736       g_audioManager.PlayActionSound(action);
2737       g_Joystick.Reset();
2738       g_Mouse.SetActive(false);
2739       return OnAction(action);
2740     }
2741     else
2742     {
2743       g_Joystick.ResetAxis(abs(bid));
2744     }
2745   }
2746   int position;
2747   if (g_Joystick.GetHat(bid, position))
2748   {
2749     // reset Idle Timer
2750     m_idleTimer.StartZero();
2751
2752     ResetScreenSaver();
2753     if (WakeUpScreenSaverAndDPMS())
2754     {
2755       g_Joystick.Reset();
2756       return true;
2757     }
2758
2759     int actionID;
2760     CStdString actionName;
2761     bool fullrange;
2762
2763     bid = position<<16|bid;
2764
2765     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2766     {
2767       CAction action(actionID, 1.0f, 0.0f, actionName);
2768       g_audioManager.PlayActionSound(action);
2769       g_Joystick.Reset();
2770       g_Mouse.SetActive(false);
2771       return OnAction(action);
2772     }
2773   }
2774 #endif
2775   return false;
2776 }
2777
2778 bool CApplication::ProcessRemote(float frameTime)
2779 {
2780 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2781   if (g_RemoteControl.GetButton())
2782   {
2783     CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2784     g_RemoteControl.Reset();
2785     return OnKey(key);
2786   }
2787 #endif
2788   return false;
2789 }
2790
2791 bool CApplication::ProcessPeripherals(float frameTime)
2792 {
2793 #ifdef HAVE_LIBCEC
2794   vector<CPeripheral *> peripherals;
2795   if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
2796   {
2797     for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
2798     {
2799       CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
2800       if (cecDevice && cecDevice->GetButton())
2801       {
2802         CKey key(cecDevice->GetButton(), cecDevice->GetHoldTime());
2803         cecDevice->ResetButton();
2804         return OnKey(key);
2805       }
2806     }
2807   }
2808 #endif
2809
2810   return false;
2811 }
2812
2813 bool CApplication::ProcessMouse()
2814 {
2815   MEASURE_FUNCTION;
2816
2817   if (!g_Mouse.IsActive() || !m_AppFocused)
2818     return false;
2819
2820   // Get the mouse command ID
2821   uint32_t mousecommand = g_Mouse.GetAction();
2822   if (mousecommand == ACTION_NOOP)
2823     return true;
2824
2825   // Reset the screensaver and idle timers
2826   m_idleTimer.StartZero();
2827   ResetScreenSaver();
2828   if (WakeUpScreenSaverAndDPMS())
2829     return true;
2830
2831   // Retrieve the corresponding action
2832   int iWin;
2833   CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2834   if (g_windowManager.HasModalDialog())
2835     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2836   else
2837     iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2838   CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2839
2840   // If we couldn't find an action return false to indicate we have not
2841   // handled this mouse action
2842   if (!mouseaction.GetID())
2843   {
2844     CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
2845     return false;
2846   }
2847
2848   // Log mouse actions except for move and noop
2849   if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
2850     CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
2851
2852   // The action might not be a mouse action. For example wheel moves might
2853   // be mapped to volume up/down in mouse.xml. In this case we do not want
2854   // the mouse position saved in the action.
2855   if (!mouseaction.IsMouse())
2856     return OnAction(mouseaction);
2857
2858   // This is a mouse action so we need to record the mouse position
2859   return OnAction(CAction(mouseaction.GetID(), 
2860                           g_Mouse.GetHold(MOUSE_LEFT_BUTTON), 
2861                           (float)g_Mouse.GetX(), 
2862                           (float)g_Mouse.GetY(), 
2863                           (float)g_Mouse.GetDX(), 
2864                           (float)g_Mouse.GetDY(),
2865                           mouseaction.GetName()));
2866 }
2867
2868 void  CApplication::CheckForTitleChange()
2869 {
2870 #ifdef HAS_HTTPAPI
2871   if (g_settings.m_HttpApiBroadcastLevel>=1)
2872   {
2873     if (IsPlayingVideo())
2874     {
2875       const CVideoInfoTag* tagVal = g_infoManager.GetCurrentMovieTag();
2876       if (m_pXbmcHttp && tagVal && !(tagVal->m_strTitle.IsEmpty()))
2877       {
2878         CStdString msg=m_pXbmcHttp->GetOpenTag()+"MovieTitle:"+tagVal->m_strTitle+m_pXbmcHttp->GetCloseTag();
2879         if (m_prevMedia!=msg && g_settings.m_HttpApiBroadcastLevel>=1)
2880         {
2881           getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2882           m_prevMedia=msg;
2883         }
2884       }
2885     }
2886     else if (IsPlayingAudio())
2887     {
2888       const CMusicInfoTag* tagVal=g_infoManager.GetCurrentSongTag();
2889       if (m_pXbmcHttp && tagVal)
2890       {
2891         CStdString msg="";
2892         if (!tagVal->GetTitle().IsEmpty())
2893           msg=m_pXbmcHttp->GetOpenTag()+"AudioTitle:"+tagVal->GetTitle()+m_pXbmcHttp->GetCloseTag();
2894         if (!tagVal->GetArtist().IsEmpty())
2895           msg+=m_pXbmcHttp->GetOpenTag()+"AudioArtist:"+tagVal->GetArtist()+m_pXbmcHttp->GetCloseTag();
2896         if (m_prevMedia!=msg)
2897         {
2898           getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2899           m_prevMedia=msg;
2900         }
2901       }
2902     }
2903   }
2904 #endif
2905 }
2906
2907 bool CApplication::ProcessHTTPApiButtons()
2908 {
2909 #ifdef HAS_HTTPAPI
2910   if (m_pXbmcHttp)
2911   {
2912     // copy key from webserver, and reset it in case we're called again before
2913     // whatever happens in OnKey()
2914     CKey keyHttp(m_pXbmcHttp->GetKey());
2915     m_pXbmcHttp->ResetKey();
2916     if (keyHttp.GetButtonCode() != KEY_INVALID)
2917     {
2918       if (keyHttp.GetButtonCode() == KEY_VMOUSE) //virtual mouse
2919       {
2920         int actionID = ACTION_MOUSE_MOVE;
2921         if (keyHttp.GetLeftTrigger() == 1)
2922           actionID = ACTION_MOUSE_LEFT_CLICK;
2923         else if (keyHttp.GetLeftTrigger() == 2)
2924           actionID = ACTION_MOUSE_RIGHT_CLICK;
2925         else if (keyHttp.GetLeftTrigger() == 3)
2926           actionID = ACTION_MOUSE_MIDDLE_CLICK;
2927         else if (keyHttp.GetRightTrigger() == 1)
2928           actionID = ACTION_MOUSE_DOUBLE_CLICK;
2929         CAction action(actionID, keyHttp.GetLeftThumbX(), keyHttp.GetLeftThumbY());
2930         OnAction(action);
2931       }
2932       else
2933         OnKey(keyHttp);
2934       return true;
2935     }
2936   }
2937   return false;
2938 #endif
2939 }
2940
2941 bool CApplication::ProcessEventServer(float frameTime)
2942 {
2943 #ifdef HAS_EVENT_SERVER
2944   CEventServer* es = CEventServer::GetInstance();
2945   if (!es || !es->Running() || es->GetNumberOfClients()==0)
2946     return false;
2947
2948   // process any queued up actions
2949   if (es->ExecuteNextAction())
2950   {
2951     // reset idle timers
2952     m_idleTimer.StartZero();
2953     ResetScreenSaver();
2954     WakeUpScreenSaverAndDPMS();
2955   }
2956
2957   // now handle any buttons or axis
2958   std::string joystickName;
2959   bool isAxis = false;
2960   float fAmount = 0.0;
2961
2962   WORD wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
2963
2964   if (wKeyID)
2965   {
2966     if (joystickName.length() > 0)
2967     {
2968       if (isAxis == true)
2969       {
2970         if (fabs(fAmount) >= 0.08)
2971           m_lastAxisMap[joystickName][wKeyID] = fAmount;
2972         else
2973           m_lastAxisMap[joystickName].erase(wKeyID);
2974       }
2975
2976       return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
2977     }
2978     else
2979     {
2980       CKey key;
2981       if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
2982         key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
2983       else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
2984         key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
2985       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
2986         key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
2987       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
2988         key = CKey(wKeyID, 0, 0,  fAmount, 0.0, 0.0, 0.0, frameTime);
2989       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
2990         key = CKey(wKeyID, 0, 0, 0.0,  fAmount, 0.0, 0.0, frameTime);
2991       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
2992         key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
2993       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
2994         key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
2995       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
2996         key = CKey(wKeyID, 0, 0, 0.0, 0.0,  fAmount, 0.0, frameTime);
2997       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
2998         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0,  fAmount, frameTime);
2999       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3000         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3001       else
3002         key = CKey(wKeyID);
3003       return OnKey(key);
3004     }
3005   }
3006
3007   if (m_lastAxisMap.size() > 0)
3008   {
3009     // Process all the stored axis.
3010     for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3011     {
3012       for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3013         ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3014     }
3015   }
3016
3017   {
3018     CPoint pos;
3019     if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3020       return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3021   }
3022 #endif
3023   return false;
3024 }
3025
3026 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount)
3027 {
3028 #if defined(HAS_EVENT_SERVER)
3029   m_idleTimer.StartZero();
3030
3031    // Make sure to reset screen saver, mouse.
3032    ResetScreenSaver();
3033    if (WakeUpScreenSaverAndDPMS())
3034      return true;
3035
3036 #ifdef HAS_SDL_JOYSTICK
3037    g_Joystick.Reset();
3038 #endif
3039    g_Mouse.SetActive(false);
3040
3041    // Figure out what window we're taking the event for.
3042    int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3043    if (g_windowManager.HasModalDialog())
3044        iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3045
3046    // This code is copied from the OnKey handler, it should be factored out.
3047    if (iWin == WINDOW_FULLSCREEN_VIDEO &&
3048        g_application.m_pPlayer &&
3049        g_application.m_pPlayer->IsInMenu())
3050    {
3051      // If player is in some sort of menu, (ie DVDMENU) map buttons differently.
3052      iWin = WINDOW_VIDEO_MENU;
3053    }
3054
3055    int actionID;
3056    CStdString actionName;
3057    bool fullRange = false;
3058
3059    // Translate using regular joystick translator.
3060    if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3061    {
3062      CAction action(actionID, fAmount, 0.0f, actionName);
3063      g_audioManager.PlayActionSound(action);
3064      return OnAction(action);
3065    }
3066    else
3067    {
3068      CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3069    }
3070 #endif
3071
3072    return false;
3073 }
3074
3075 bool CApplication::Cleanup()
3076 {
3077   try
3078   {
3079     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3080     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3081     g_windowManager.Delete(WINDOW_MUSIC_FILES);
3082     g_windowManager.Delete(WINDOW_MUSIC_NAV);
3083     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3084     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3085     g_windowManager.Delete(WINDOW_VIDEO_FILES);
3086     g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3087     g_windowManager.Delete(WINDOW_VIDEO_NAV);
3088     g_windowManager.Delete(WINDOW_FILES);
3089     g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3090     g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3091     g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3092     g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3093     g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3094     g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3095     g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3096     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_SCAN);
3097     g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3098     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3099     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3100     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3101     g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3102     g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3103     g_windowManager.Delete(WINDOW_DIALOG_OK);
3104     g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3105     g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3106     g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3107     g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3108     g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3109     g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3110     g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3111     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3112     g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3113     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3114     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_SCAN);
3115     g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3116     g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3117     g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3118     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3119     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3120     g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3121     g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3122     g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3123     g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3124     g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3125     g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3126
3127     g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3128     g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3129
3130     g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3131
3132     g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3133     g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3134     g_windowManager.Delete(WINDOW_VISUALISATION);
3135     g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3136     g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3137     g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3138     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);  // all the settings categories
3139     g_windowManager.Delete(WINDOW_TEST_PATTERN);
3140     g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3141     g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3142     g_windowManager.Delete(WINDOW_SCREENSAVER);
3143     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3144     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3145     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3146     g_windowManager.Delete(WINDOW_SLIDESHOW);
3147
3148     g_windowManager.Delete(WINDOW_HOME);
3149     g_windowManager.Delete(WINDOW_PROGRAMS);
3150     g_windowManager.Delete(WINDOW_PICTURES);
3151     g_windowManager.Delete(WINDOW_WEATHER);
3152
3153     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3154     g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3155     g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3156     g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3157     g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3158     g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3159     g_windowManager.Remove(WINDOW_SETTINGS_NETWORK);
3160     g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3161     g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3162
3163     g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3164     g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3165
3166     CAddonMgr::Get().DeInit();
3167
3168 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3169     CLog::Log(LOGNOTICE, "closing down remote control service");
3170     g_RemoteControl.Disconnect();
3171 #endif
3172
3173     CLog::Log(LOGNOTICE, "unload sections");
3174
3175 #ifdef HAS_PERFORMANCE_SAMPLE
3176     CLog::Log(LOGNOTICE, "performance statistics");
3177     m_perfStats.DumpStats();
3178 #endif
3179
3180     //  Shutdown as much as possible of the
3181     //  application, to reduce the leaks dumped
3182     //  to the vc output window before calling
3183     //  _CrtDumpMemoryLeaks(). Most of the leaks
3184     //  shown are no real leaks, as parts of the app
3185     //  are still allocated.
3186
3187     g_localizeStrings.Clear();
3188     g_LangCodeExpander.Clear();
3189     g_charsetConverter.clear();
3190     g_directoryCache.Clear();
3191     CButtonTranslator::GetInstance().Clear();
3192     CLastfmScrobbler::RemoveInstance();
3193     CLibrefmScrobbler::RemoveInstance();
3194     CLastFmManager::RemoveInstance();
3195 #ifdef HAS_EVENT_SERVER
3196     CEventServer::RemoveInstance();
3197 #endif
3198     DllLoaderContainer::Clear();
3199     g_playlistPlayer.Clear();
3200     g_settings.Clear();
3201     g_guiSettings.Clear();
3202     g_advancedSettings.Clear();
3203
3204 #ifdef _LINUX
3205     CXHandle::DumpObjectTracker();
3206 #endif
3207
3208 #ifdef _CRTDBG_MAP_ALLOC
3209     _CrtDumpMemoryLeaks();
3210     while(1); // execution ends
3211 #endif
3212 #ifdef _WIN32
3213     WSACleanup();
3214
3215     //Uninitialize COM
3216     CoUninitialize();
3217 #endif
3218     return true;
3219   }
3220   catch (...)
3221   {
3222     CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3223     return false;
3224   }
3225 }
3226
3227 void CApplication::Stop(int exitCode)
3228 {
3229   try
3230   {
3231     CAnnouncementManager::Announce(System, "xbmc", "OnQuit");
3232
3233     // cancel any jobs from the jobmanager
3234     CJobManager::GetInstance().CancelJobs();
3235
3236     g_alarmClock.StopThread();
3237
3238 #ifdef HAS_HTTPAPI
3239     if (m_pXbmcHttp)
3240     {
3241       if (g_settings.m_HttpApiBroadcastLevel >= 1)
3242         getApplicationMessenger().HttpApi("broadcastlevel; ShutDown;1");
3243
3244       m_pXbmcHttp->shuttingDown = true;
3245     }
3246 #endif
3247
3248     if( m_bSystemScreenSaverEnable )
3249       g_Windowing.EnableSystemScreenSaver(true);
3250
3251     CLog::Log(LOGNOTICE, "Storing total System Uptime");
3252     g_settings.m_iSystemTimeTotalUp = g_settings.m_iSystemTimeTotalUp + (int)(CTimeUtils::GetFrameTime() / 60000);
3253
3254     // Update the settings information (volume, uptime etc. need saving)
3255     if (CFile::Exists(g_settings.GetSettingsFile()))
3256     {
3257       CLog::Log(LOGNOTICE, "Saving settings");
3258       g_settings.Save();
3259     }
3260     else
3261       CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3262
3263     m_bStop = true;
3264     m_AppActive = false;
3265     m_AppFocused = false;
3266     m_ExitCode = exitCode;
3267     CLog::Log(LOGNOTICE, "stop all");
3268
3269     // stop scanning before we kill the network and so on
3270     CGUIDialogMusicScan *musicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
3271     if (musicScan)
3272       musicScan->StopScanning();
3273
3274     CGUIDialogVideoScan *videoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
3275     if (videoScan)
3276       videoScan->StopScanning();
3277
3278     m_applicationMessenger.Cleanup();
3279
3280     StopServices();
3281     //Sleep(5000);
3282
3283 #if defined(__APPLE__) && !defined(__arm__)
3284     XBMCHelper::GetInstance().ReleaseAllInput();
3285 #endif
3286
3287     if (m_pPlayer)
3288     {
3289       CLog::Log(LOGNOTICE, "stop player");
3290       delete m_pPlayer;
3291       m_pPlayer = NULL;
3292     }
3293
3294 #if HAS_FILESYTEM_DAAP
3295     CLog::Log(LOGNOTICE, "stop daap clients");
3296     g_DaapClient.Release();
3297 #endif
3298 #ifdef HAS_FILESYSTEM_SAP
3299     CLog::Log(LOGNOTICE, "stop sap announcement listener");
3300     g_sapsessions.StopThread();
3301 #endif
3302 #ifdef HAS_ZEROCONF
3303     if(CZeroconfBrowser::IsInstantiated())
3304     {
3305       CLog::Log(LOGNOTICE, "stop zeroconf browser");
3306       CZeroconfBrowser::GetInstance()->Stop();
3307       CZeroconfBrowser::ReleaseInstance();
3308     }
3309 #endif
3310
3311     CLog::Log(LOGNOTICE, "clean cached files!");
3312 #ifdef HAS_FILESYSTEM_RAR
3313     g_RarManager.ClearCache(true);
3314 #endif
3315
3316 #ifdef HAS_FILESYSTEM_SFTP
3317     CSFTPSessionManager::DisconnectAllSessions();
3318 #endif
3319
3320     CLog::Log(LOGNOTICE, "unload skin");
3321     UnloadSkin();
3322
3323 #if defined(__APPLE__) && !defined(__arm__)
3324     if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3325       XBMCHelper::GetInstance().Stop();
3326 #endif
3327
3328 #if defined(HAVE_LIBCRYSTALHD)
3329     CCrystalHD::RemoveInstance();
3330 #endif
3331
3332   g_mediaManager.Stop();
3333
3334   // Stop services before unloading Python
3335   CAddonMgr::Get().StopServices(false);
3336
3337 /* Python resource freeing must be done after skin has been unloaded, not before
3338    some windows still need it when deinitializing during skin unloading. */
3339 #ifdef HAS_PYTHON
3340   CLog::Log(LOGNOTICE, "stop python");
3341   g_pythonParser.FreeResources();
3342 #endif
3343 #ifdef HAS_LCD
3344     if (g_lcd)
3345     {
3346       g_lcd->Stop();
3347       delete g_lcd;
3348       g_lcd=NULL;
3349     }
3350 #endif
3351
3352     g_Windowing.DestroyRenderSystem();
3353     g_Windowing.DestroyWindow();
3354     g_Windowing.DestroyWindowSystem();
3355
3356     CLog::Log(LOGNOTICE, "stopped");
3357   }
3358   catch (...)
3359   {
3360     CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3361   }
3362
3363   // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3364   // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3365   Destroy();
3366
3367   // 
3368   Sleep(200);
3369 }
3370
3371 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3372 {
3373   //If item is a plugin, expand out now and run ourselves again
3374   if (item.IsPlugin())
3375   {
3376     CFileItem item_new(item);
3377     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3378       return PlayMedia(item_new, iPlaylist);
3379     return false;
3380   }
3381   if (item.IsLastFM())
3382   {
3383     g_partyModeManager.Disable();
3384     return CLastFmManager::GetInstance()->ChangeStation(item.GetAsUrl());
3385   }
3386   if (item.IsSmartPlayList())
3387   {
3388     CFileItemList items;
3389     CUtil::GetRecursiveListing(item.GetPath(), items, "");
3390     if (items.Size())
3391     {
3392       CSmartPlaylist smartpl;
3393       //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3394       smartpl.OpenAndReadName(item.GetPath());
3395       CPlayList playlist;
3396       playlist.Add(items);
3397       return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3398     }
3399   }
3400   else if (item.IsPlayList() || item.IsInternetStream())
3401   {
3402     CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3403
3404     //is or could be a playlist
3405     auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3406     bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3407
3408     if (dlgCache)
3409     {
3410        dlgCache->Close();
3411        if (dlgCache->IsCanceled())
3412           return true;
3413     }
3414
3415     if (gotPlayList)
3416     {
3417
3418       if (iPlaylist != PLAYLIST_NONE)
3419       {
3420         int track=0;
3421         if (item.HasProperty("playlist_starting_track"))
3422           track = item.GetProperty("playlist_starting_track").asInteger();
3423         return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3424       }
3425       else
3426       {
3427         CLog::Log(LOGWARNING, "CApplication::PlayMedia called to play a playlist %s but no idea which playlist to use, playing first item", item.GetPath().c_str());
3428         if(pPlayList->size())
3429           return PlayFile(*(*pPlayList)[0], false);
3430       }
3431     }
3432   }
3433
3434   //nothing special just play
3435   return PlayFile(item, false);
3436 }
3437
3438 // PlayStack()
3439 // For playing a multi-file video.  Particularly inefficient
3440 // on startup, as we are required to calculate the length
3441 // of each video, so we open + close each one in turn.
3442 // A faster calculation of video time would improve this
3443 // substantially.
3444 bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3445 {
3446   if (!item.IsStack())
3447     return false;
3448
3449   // see if we have the info in the database
3450   // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3451   //       then these times will be wrong.
3452   //       Also, this is really just a hack for the slow load up times we have
3453   //       A much better solution is a fast reader of FPS and fileLength
3454   //       that we can use on a file to get it's time.
3455   vector<int> times;
3456   bool haveTimes(false);
3457   CVideoDatabase dbs;
3458   if (dbs.Open())
3459   {
3460     dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3461     haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3462     dbs.Close();
3463   }
3464
3465
3466   // calculate the total time of the stack
3467   CStackDirectory dir;
3468   dir.GetDirectory(item.GetPath(), *m_currentStack);
3469   long totalTime = 0;
3470   for (int i = 0; i < m_currentStack->Size(); i++)
3471   {
3472     if (haveTimes)
3473       (*m_currentStack)[i]->m_lEndOffset = times[i];
3474     else
3475     {
3476       int duration;
3477       if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3478       {
3479         m_currentStack->Clear();
3480         return false;
3481       }
3482       totalTime += duration / 1000;
3483       (*m_currentStack)[i]->m_lEndOffset = totalTime;
3484       times.push_back(totalTime);
3485     }
3486   }
3487
3488   double seconds = item.m_lStartOffset / 75.0;
3489
3490   if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3491   {  // have our times now, so update the dB
3492     if (dbs.Open())
3493     {
3494       if( !haveTimes )
3495         dbs.SetStackTimes(item.GetPath(), times);
3496
3497       if( item.m_lStartOffset == STARTOFFSET_RESUME )
3498       {
3499         // can only resume seek here, not dvdstate
3500         CBookmark bookmark;
3501         if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3502           seconds = bookmark.timeInSeconds;
3503         else
3504           seconds = 0.0f;
3505       }
3506       dbs.Close();
3507     }
3508   }
3509
3510   *m_itemCurrentFile = item;
3511   m_currentStackPosition = 0;
3512   m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3513
3514   if (seconds > 0)
3515   {
3516     // work out where to seek to
3517     for (int i = 0; i < m_currentStack->Size(); i++)
3518     {
3519       if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3520       {
3521         CFileItem item(*(*m_currentStack)[i]);
3522         long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3523         item.m_lStartOffset = (long)(seconds - start) * 75;
3524         m_currentStackPosition = i;
3525         return PlayFile(item, true);
3526       }
3527     }
3528   }
3529
3530   return PlayFile(*(*m_currentStack)[0], true);
3531 }
3532
3533 bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
3534 {
3535   if (!bRestart)
3536   {
3537     SaveCurrentFileSettings();
3538
3539     OutputDebugString("new file set audiostream:0\n");
3540     // Switch to default options
3541     g_settings.m_currentVideoSettings = g_settings.m_defaultVideoSettings;
3542     // see if we have saved options in the database
3543
3544     m_iPlaySpeed = 1;
3545     *m_itemCurrentFile = item;
3546     m_nextPlaylistItem = -1;
3547     m_currentStackPosition = 0;
3548     m_currentStack->Clear();
3549
3550     if (item.IsVideo())
3551       CUtil::ClearSubtitles();
3552   }
3553
3554   if (item.IsDiscStub())
3555   {
3556 #ifdef HAS_DVD_DRIVE
3557     // Display the Play Eject dialog
3558     if (CGUIDialogPlayEject::ShowAndGetInput(item))
3559       // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3560       // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3561       return MEDIA_DETECT::CAutorun::PlayDiscAskResume(); 
3562 #endif
3563     return true;
3564   }
3565
3566   if (item.IsPlayList())
3567     return false;
3568
3569   if (item.IsPlugin())
3570   { // we modify the item so that it becomes a real URL
3571     CFileItem item_new(item);
3572     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3573       return PlayFile(item_new, false);
3574     return false;
3575   }
3576
3577   if (URIUtils::IsUPnP(item.GetPath()))
3578   {
3579     CFileItem item_new(item);
3580     if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3581       return PlayFile(item_new, false);
3582     return false;
3583   }
3584
3585   // if we have a stacked set of files, we need to setup our stack routines for
3586   // "seamless" seeking and total time of the movie etc.
3587   // will recall with restart set to true
3588   if (item.IsStack())
3589     return PlayStack(item, bRestart);
3590
3591   //Is TuxBox, this should probably be moved to CFileTuxBox
3592   if(item.IsTuxBox())
3593   {
3594     CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3595
3596     if(g_tuxboxService.IsRunning())
3597       g_tuxboxService.Stop();
3598
3599     CFileItem item_new;
3600     if(g_tuxbox.CreateNewItem(item, item_new))
3601     {
3602
3603       // Make sure it doesn't have a player
3604       // so we actually select one normally
3605       m_eCurrentPlayer = EPC_NONE;
3606
3607       // keep the tuxbox:// url as playing url
3608       // and give the new url to the player
3609       if(PlayFile(item_new, true))
3610       {
3611         if(!g_tuxboxService.IsRunning())
3612           g_tuxboxService.Start();
3613         return true;
3614       }
3615     }
3616     return false;
3617   }
3618
3619   CPlayerOptions options;
3620   
3621   if( item.HasProperty("StartPercent") )
3622   {
3623     options.startpercent = item.GetProperty("StartPercent").asDouble();
3624   }
3625   
3626   PLAYERCOREID eNewCore = EPC_NONE;
3627   if( bRestart )
3628   {
3629     // have to be set here due to playstack using this for starting the file
3630     options.starttime = item.m_lStartOffset / 75.0;
3631     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3632       m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3633
3634     if( m_eForcedNextPlayer != EPC_NONE )
3635       eNewCore = m_eForcedNextPlayer;
3636     else if( m_eCurrentPlayer == EPC_NONE )
3637       eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3638     else
3639       eNewCore = m_eCurrentPlayer;
3640   }
3641   else
3642   {
3643     options.starttime = item.m_lStartOffset / 75.0;
3644
3645     if (item.IsVideo())
3646     {
3647       // open the d/b and retrieve the bookmarks for the current movie
3648       CVideoDatabase dbs;
3649       dbs.Open();
3650       dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3651
3652       if( item.m_lStartOffset == STARTOFFSET_RESUME )
3653       {
3654         options.starttime = 0.0f;
3655         CBookmark bookmark;
3656         CStdString path = item.GetPath();
3657         if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0) 
3658           path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3659         else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3660           path = item.GetProperty("original_listitem_url").asString();
3661         if(dbs.GetResumeBookMark(path, bookmark))
3662         {
3663           options.starttime = bookmark.timeInSeconds;
3664           options.state = bookmark.playerState;
3665         }
3666       }
3667       else if (item.HasVideoInfoTag())
3668       {
3669         const CVideoInfoTag *tag = item.GetVideoInfoTag();
3670
3671         if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3672         {
3673           CBookmark bookmark;
3674           dbs.GetBookMarkForEpisode(*tag, bookmark);
3675           options.starttime = bookmark.timeInSeconds;
3676           options.state = bookmark.playerState;
3677         }
3678       }
3679
3680       dbs.Close();
3681     }
3682
3683     if (m_eForcedNextPlayer != EPC_NONE)
3684       eNewCore = m_eForcedNextPlayer;
3685     else
3686       eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3687   }
3688
3689   // this really aught to be inside !bRestart, but since PlayStack
3690   // uses that to init playback, we have to keep it outside
3691   int playlist = g_playlistPlayer.GetCurrentPlaylist();
3692   if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3693   { // playing from a playlist by the looks
3694     // don't switch to fullscreen if we are not playing the first item...
3695     options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3696   }
3697   else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3698   {
3699     // TODO - this will fail if user seeks back to first file in stack
3700     if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3701       options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3702     else
3703       options.fullscreen = false;
3704     // reset this so we don't think we are resuming on seek
3705     m_itemCurrentFile->m_lStartOffset = 0;
3706   }
3707   else
3708     options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3709
3710   // reset m_bStartVideoWindowed as it's a temp setting
3711   g_settings.m_bStartVideoWindowed = false;
3712   // reset any forced player
3713   m_eForcedNextPlayer = EPC_NONE;
3714
3715 #ifdef HAS_KARAOKE
3716   //We have to stop parsing a cdg before mplayer is deallocated
3717   // WHY do we have to do this????
3718   if (m_pKaraokeMgr)
3719     m_pKaraokeMgr->Stop();
3720 #endif
3721
3722   // tell system we are starting a file
3723   m_bPlaybackStarting = true;
3724
3725   // We should restart the player, unless the previous and next tracks are using
3726   // one of the players that allows gapless playback (paplayer, dvdplayer)
3727   if (m_pPlayer)
3728   {
3729     if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer  == EPC_PAPLAYER)) )
3730     {
3731       delete m_pPlayer;
3732       m_pPlayer = NULL;
3733     }
3734   }
3735
3736   if (!m_pPlayer)
3737   {
3738     m_eCurrentPlayer = eNewCore;
3739     m_pPlayer = CPlayerCoreFactory::CreatePlayer(eNewCore, *this);
3740   }
3741
3742   // Workaround for bug/quirk in SDL_Mixer on OSX.
3743   // TODO: Remove after GUI Sounds redux
3744 #if defined(__APPLE__)
3745   g_audioManager.Enable(false);
3746 #endif
3747
3748   bool bResult;
3749   if (m_pPlayer)
3750   {
3751     // don't hold graphicscontext here since player
3752     // may wait on another thread, that requires gfx
3753     CSingleExit ex(g_graphicsContext);
3754     bResult = m_pPlayer->OpenFile(item, options);
3755   }
3756   else
3757   {
3758     CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3759     bResult = false;
3760   }
3761
3762   if(bResult)
3763   {
3764     if (m_iPlaySpeed != 1)
3765     {
3766       int iSpeed = m_iPlaySpeed;
3767       m_iPlaySpeed = 1;
3768       SetPlaySpeed(iSpeed);
3769     }
3770
3771     if( IsPlayingAudio() )
3772     {
3773       if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3774         g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
3775     }
3776
3777 #ifdef HAS_VIDEO_PLAYBACK
3778     if( IsPlayingVideo() )
3779     {
3780       if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
3781         g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
3782
3783       // if player didn't manange to switch to fullscreen by itself do it here
3784       if( options.fullscreen && g_renderManager.IsStarted()
3785        && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
3786        SwitchToFullScreen();
3787
3788       if (!item.IsDVDImage() && !item.IsDVDFile())
3789       {
3790         CVideoInfoTag *details = m_itemCurrentFile->GetVideoInfoTag();
3791         // Save information about the stream if we currently have no data
3792         if (!details->HasStreamDetails() ||
3793              details->m_streamDetails.GetVideoDuration() <= 0)
3794         {
3795           if (m_pPlayer->GetStreamDetails(details->m_streamDetails) && details->HasStreamDetails())
3796           {
3797             CVideoDatabase dbs;
3798             dbs.Open();
3799             dbs.SetStreamDetailsForFileId(details->m_streamDetails, details->m_iFileId);
3800             dbs.Close();
3801             CUtil::DeleteVideoDatabaseDirectoryCache();
3802           }
3803         }
3804       }
3805     }
3806 #endif
3807
3808 #if !defined(__APPLE__)
3809     g_audioManager.Enable(false);
3810 #endif
3811   }
3812   m_bPlaybackStarting = false;
3813   if(bResult)
3814   {
3815     // we must have started, otherwise player might send this later
3816     if(IsPlaying())
3817       OnPlayBackStarted();
3818     else
3819       OnPlayBackEnded();
3820   }
3821   else
3822   {
3823     // we send this if it isn't playlistplayer that is doing this
3824     int next = g_playlistPlayer.GetNextSong();
3825     int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
3826     if(next < 0
3827     || next >= size)
3828       OnPlayBackStopped();
3829   }
3830
3831   return bResult;
3832 }
3833
3834 void CApplication::OnPlayBackEnded()
3835 {
3836   if(m_bPlaybackStarting)
3837     return;
3838
3839   // informs python script currently running playback has ended
3840   // (does nothing if python is not loaded)
3841 #ifdef HAS_PYTHON
3842   g_pythonParser.OnPlayBackEnded();
3843 #endif
3844
3845 #ifdef HAS_HTTPAPI
3846   // Let's tell the outside world as well
3847   if (g_settings.m_HttpApiBroadcastLevel>=1)
3848     getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackEnded;1");
3849 #endif
3850
3851   CAnnouncementManager::Announce(Player, "xbmc", "OnStop");
3852
3853   if (IsPlayingAudio())
3854   {
3855     CLastfmScrobbler::GetInstance()->SubmitQueue();
3856     CLibrefmScrobbler::GetInstance()->SubmitQueue();
3857   }
3858
3859   CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
3860   g_windowManager.SendThreadMessage(msg);
3861 }
3862
3863 void CApplication::OnPlayBackStarted()
3864 {
3865   if(m_bPlaybackStarting)
3866     return;
3867
3868 #ifdef HAS_PYTHON
3869   // informs python script currently running playback has started
3870   // (does nothing if python is not loaded)
3871   g_pythonParser.OnPlayBackStarted();
3872 #endif
3873
3874 #ifdef HAS_HTTPAPI
3875   // Let's tell the outside world as well
3876   if (g_settings.m_HttpApiBroadcastLevel>=1)
3877     getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStarted;1");
3878 #endif
3879
3880   CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
3881   g_windowManager.SendThreadMessage(msg);
3882 }
3883
3884 void CApplication::OnQueueNextItem()
3885 {
3886   // informs python script currently running that we are requesting the next track
3887   // (does nothing if python is not loaded)
3888 #ifdef HAS_PYTHON
3889   g_pythonParser.OnQueueNextItem(); // currently unimplemented
3890 #endif
3891
3892 #ifdef HAS_HTTPAPI
3893   // Let's tell the outside world as well
3894   if (g_settings.m_HttpApiBroadcastLevel>=1)
3895     getApplicationMessenger().HttpApi("broadcastlevel; OnQueueNextItem;1");
3896 #endif
3897
3898   if(IsPlayingAudio())
3899   {
3900     CLastfmScrobbler::GetInstance()->SubmitQueue();
3901     CLibrefmScrobbler::GetInstance()->SubmitQueue();
3902   }
3903
3904   CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
3905   g_windowManager.SendThreadMessage(msg);
3906 }
3907
3908 void CApplication::OnPlayBackStopped()
3909 {
3910   if(m_bPlaybackStarting)
3911     return;
3912
3913   // informs python script currently running playback has ended
3914   // (does nothing if python is not loaded)
3915 #ifdef HAS_PYTHON
3916   g_pythonParser.OnPlayBackStopped();
3917 #endif
3918
3919 #ifdef HAS_HTTPAPI
3920   // Let's tell the outside world as well
3921   if (g_settings.m_HttpApiBroadcastLevel>=1)
3922     getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStopped;1");
3923 #endif
3924
3925   CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile);
3926
3927   CLastfmScrobbler::GetInstance()->SubmitQueue();
3928   CLibrefmScrobbler::GetInstance()->SubmitQueue();
3929
3930   CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
3931   g_windowManager.SendThreadMessage(msg);
3932 }
3933
3934 void CApplication::OnPlayBackPaused()
3935 {
3936 #ifdef HAS_PYTHON
3937   g_pythonParser.OnPlayBackPaused();
3938 #endif
3939
3940 #ifdef HAS_HTTPAPI
3941   // Let's tell the outside world as well
3942   if (g_settings.m_HttpApiBroadcastLevel>=1)
3943     getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackPaused;1");
3944 #endif
3945
3946   CVariant param;
3947   param["player"]["speed"] = 0;
3948   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3949   CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
3950 }
3951
3952 void CApplication::OnPlayBackResumed()
3953 {
3954 #ifdef HAS_PYTHON
3955   g_pythonParser.OnPlayBackResumed();
3956 #endif
3957
3958 #ifdef HAS_HTTPAPI
3959   // Let's tell the outside world as well
3960   if (g_settings.m_HttpApiBroadcastLevel>=1)
3961     getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackResumed;1");
3962 #endif
3963
3964   CVariant param;
3965   param["player"]["speed"] = 1;
3966   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3967   CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
3968 }
3969
3970 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
3971 {
3972 #ifdef HAS_PYTHON
3973   g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
3974 #endif
3975
3976 #ifdef HAS_HTTPAPI
3977   // Let's tell the outside world as well
3978   if (g_settings.m_HttpApiBroadcastLevel>=1)
3979   {
3980     CStdString tmp;
3981     tmp.Format("broadcastlevel; OnPlayBackSpeedChanged:%i;1",iSpeed);
3982     getApplicationMessenger().HttpApi(tmp);
3983   }
3984 #endif
3985
3986   CVariant param;
3987   param["player"]["speed"] = iSpeed;
3988   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3989   CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
3990 }
3991
3992 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
3993 {
3994 #ifdef HAS_PYTHON
3995   g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
3996 #endif
3997
3998 #ifdef HAS_HTTPAPI
3999   // Let's tell the outside world as well
4000   if (g_settings.m_HttpApiBroadcastLevel>=1)
4001   {
4002     CStdString tmp;
4003     tmp.Format("broadcastlevel; OnPlayBackSeek:%i;1",iTime);
4004     getApplicationMessenger().HttpApi(tmp);
4005   }
4006 #endif
4007
4008   CVariant param;
4009   CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4010   CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4011   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4012   param["player"]["speed"] = GetPlaySpeed();
4013   CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4014   g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4015 }
4016
4017 void CApplication::OnPlayBackSeekChapter(int iChapter)
4018 {
4019 #ifdef HAS_PYTHON
4020   g_pythonParser.OnPlayBackSeekChapter(iChapter);
4021 #endif
4022
4023 #ifdef HAS_HTTPAPI
4024   // Let's tell the outside world as well
4025   if (g_settings.m_HttpApiBroadcastLevel>=1)
4026   {
4027     CStdString tmp;
4028     tmp.Format("broadcastlevel; OnPlayBackSkeekChapter:%i;1",iChapter);
4029     getApplicationMessenger().HttpApi(tmp);
4030   }
4031 #endif
4032 }
4033
4034 bool CApplication::IsPlaying() const
4035 {
4036   if (!m_pPlayer)
4037     return false;
4038   if (!m_pPlayer->IsPlaying())
4039     return false;
4040   return true;
4041 }
4042
4043 bool CApplication::IsPaused() const
4044 {
4045   if (!m_pPlayer)
4046     return false;
4047   if (!m_pPlayer->IsPlaying())
4048     return false;
4049   return m_pPlayer->IsPaused();
4050 }
4051
4052 bool CApplication::IsPlayingAudio() const
4053 {
4054   if (!m_pPlayer)
4055     return false;
4056   if (!m_pPlayer->IsPlaying())
4057     return false;
4058   if (m_pPlayer->HasVideo())
4059     return false;
4060   if (m_pPlayer->HasAudio())
4061     return true;
4062   return false;
4063 }
4064
4065 bool CApplication::IsPlayingVideo() const
4066 {
4067   if (!m_pPlayer)
4068     return false;
4069   if (!m_pPlayer->IsPlaying())
4070     return false;
4071   if (m_pPlayer->HasVideo())
4072     return true;
4073
4074   return false;
4075 }
4076
4077 bool CApplication::IsPlayingFullScreenVideo() const
4078 {
4079   return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4080 }
4081
4082 void CApplication::SaveFileState()
4083 {
4084   if (!g_settings.GetCurrentProfile().canWriteDatabases())
4085     return;
4086   CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4087       m_progressTrackingVideoResumeBookmark,
4088       m_progressTrackingPlayCountUpdate);
4089   CJobManager::GetInstance().AddJob(job, NULL);
4090 }
4091
4092 void CApplication::UpdateFileState()
4093 {
4094   // Did the file change?
4095   if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4096   {
4097     SaveFileState();
4098
4099     // Reset tracking item
4100     m_progressTrackingItem->Reset();
4101   }
4102   else
4103   {
4104     if (IsPlayingVideo() || IsPlayingAudio())
4105     {
4106       if (m_progressTrackingItem->GetPath() == "")
4107       {
4108         // Init some stuff
4109         *m_progressTrackingItem = CurrentFileItem();
4110         m_progressTrackingPlayCountUpdate = false;
4111       }
4112
4113       if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4114           GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4115           (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4116           GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4117       {
4118         m_progressTrackingPlayCountUpdate = true;
4119       }
4120
4121       if (m_progressTrackingItem->IsVideo())
4122       {
4123         if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60)
4124         {
4125           m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset();
4126           m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails);
4127         }
4128         // Update bookmark for save
4129         m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::GetPlayerName(m_eCurrentPlayer);
4130         m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4131         m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4132
4133         if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4134             GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4135         {
4136           // Delete the bookmark
4137           m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4138         }
4139         else
4140         if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4141         {
4142           // Update the bookmark
4143           m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4144           m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4145         }
4146         else
4147         {
4148           // Do nothing
4149           m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4150         }
4151       }
4152     }
4153   }
4154 }
4155
4156 void CApplication::StopPlaying()
4157 {
4158   int iWin = g_windowManager.GetActiveWindow();
4159   if ( IsPlaying() )
4160   {
4161 #ifdef HAS_KARAOKE
4162     if( m_pKaraokeMgr )
4163       m_pKaraokeMgr->Stop();
4164 #endif
4165
4166     if (m_pPlayer)
4167       m_pPlayer->CloseFile();
4168
4169     // turn off visualisation window when stopping
4170     if (iWin == WINDOW_VISUALISATION
4171     ||  iWin == WINDOW_FULLSCREEN_VIDEO)
4172       g_windowManager.PreviousWindow();
4173
4174     g_partyModeManager.Disable();
4175   }
4176 }
4177
4178 void CApplication::ResetScreenSaver()
4179 {
4180   // reset our timers
4181   m_shutdownTimer.StartZero();
4182
4183   // screen saver timer is reset only if we're not already in screensaver or
4184   // DPMS mode
4185   if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4186     ResetScreenSaverTimer();
4187 }
4188
4189 void CApplication::ResetScreenSaverTimer()
4190 {
4191 #if defined(__APPLE__) && !defined(__arm__)
4192   Cocoa_UpdateSystemActivity();
4193 #endif
4194   m_screenSaverTimer.StartZero();
4195 }
4196
4197 void CApplication::StopScreenSaverTimer()
4198 {
4199   m_screenSaverTimer.Stop();
4200 }
4201
4202 bool CApplication::ToggleDPMS(bool manual)
4203 {
4204   if (manual || (m_dpmsIsManual == manual))
4205   {
4206     if (m_dpmsIsActive)
4207     {
4208       m_dpmsIsActive = false;
4209       m_dpmsIsManual = false;
4210       return m_dpms->DisablePowerSaving();
4211     }
4212     else
4213     {
4214       if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4215       {
4216         m_dpmsIsActive = true;
4217         m_dpmsIsManual = manual;
4218         return true;
4219       }
4220     }
4221   }
4222   return false;
4223 }
4224
4225 bool CApplication::WakeUpScreenSaverAndDPMS()
4226 {
4227
4228 #ifdef HAS_LCD
4229     // turn on lcd backlight
4230     if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4231       g_lcd->SetBackLight(1);
4232 #endif
4233
4234   // First reset DPMS, if active
4235   if (m_dpmsIsActive)
4236   {
4237     if (m_dpmsIsManual)
4238       return false;
4239     // TODO: if screensaver lock is specified but screensaver is not active
4240     // (DPMS came first), activate screensaver now.
4241     ToggleDPMS(false);
4242     ResetScreenSaverTimer();
4243     return !m_bScreenSave || WakeUpScreenSaver();
4244   }
4245   else
4246     return WakeUpScreenSaver();
4247 }
4248
4249 bool CApplication::WakeUpScreenSaver()
4250 {
4251   if (m_iScreenSaveLock == 2)
4252     return false;
4253
4254   // if Screen saver is active
4255   if (m_bScreenSave && m_screenSaver)
4256   {
4257     if (m_iScreenSaveLock == 0)
4258       if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4259           (g_settings.UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) &&
4260           g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4261           m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && m_screenSaver->ID() != "visualization")
4262       {
4263         m_iScreenSaveLock = 2;
4264         CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4265         g_windowManager.GetWindow(WINDOW_SCREENSAVER)->OnMessage(msg);
4266       }
4267     if (m_iScreenSaveLock == -1)
4268     {
4269       m_iScreenSaveLock = 0;
4270       return true;
4271     }
4272
4273     // disable screensaver
4274     m_bScreenSave = false;
4275     m_iScreenSaveLock = 0;
4276     ResetScreenSaverTimer();
4277
4278     CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated");
4279
4280     if (m_screenSaver->ID() == "visualization")
4281     {
4282       // we can just continue as usual from vis mode
4283       return false;
4284     }
4285     else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4286       return true;
4287     else if (!m_screenSaver->ID().IsEmpty())
4288     { // we're in screensaver window
4289       if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4290         g_windowManager.PreviousWindow();  // show the previous window
4291       if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4292         g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4293     }
4294     return true;
4295   }
4296   else
4297     return false;
4298 }
4299
4300 void CApplication::CheckScreenSaverAndDPMS()
4301 {
4302   if (!m_dpmsIsActive)
4303     g_Windowing.ResetOSScreensaver();
4304
4305   bool maybeScreensaver =
4306       !m_dpmsIsActive && !m_bScreenSave
4307       && !g_guiSettings.GetString("screensaver.mode").IsEmpty();
4308   bool maybeDPMS =
4309       !m_dpmsIsActive && m_dpms->IsSupported()
4310       && g_guiSettings.GetInt("powermanagement.displaysoff") > 0;
4311
4312   // Has the screen saver window become active?
4313   if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4314   {
4315     m_bScreenSave = true;
4316     maybeScreensaver = false;
4317   }
4318
4319   if (!maybeScreensaver && !maybeDPMS) return;  // Nothing to do.
4320
4321   // See if we need to reset timer.
4322   // * Are we playing a video and it is not paused?
4323   if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4324       // * Are we playing some music in fullscreen vis?
4325       || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION 
4326           && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()))
4327   {
4328     ResetScreenSaverTimer();
4329     return;
4330   }
4331
4332   float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4333
4334   // DPMS has priority (it makes the screensaver not needed)
4335   if (maybeDPMS
4336       && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60)
4337   {
4338     ToggleDPMS(false);
4339     WakeUpScreenSaver();
4340   }
4341   else if (maybeScreensaver
4342            && elapsed > g_guiSettings.GetInt("screensaver.time") * 60)
4343   {
4344     ActivateScreenSaver();
4345   }
4346 }
4347
4348 // activate the screensaver.
4349 // if forceType is true, we ignore the various conditions that can alter
4350 // the type of screensaver displayed
4351 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4352 {
4353   m_bScreenSave = true;
4354
4355   // Get Screensaver Mode
4356   m_screenSaver.reset();
4357   if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver))
4358     m_screenSaver.reset(new CScreenSaver(""));
4359
4360 #ifdef HAS_LCD
4361   // turn off lcd backlight if requested
4362   if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4363     g_lcd->SetBackLight(0);
4364 #endif
4365
4366   CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4367
4368   // disable screensaver lock from the login screen
4369   m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4370   if (!forceType)
4371   {
4372     // set to Dim in the case of a dialog on screen or playing video
4373     if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")))
4374     {
4375       if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4376         m_screenSaver.reset(new CScreenSaver(""));
4377     }
4378     // Check if we are Playing Audio and Vis instead Screensaver!
4379     else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())
4380     { // activate the visualisation
4381       m_screenSaver.reset(new CScreenSaver("visualization"));
4382       g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4383       return;
4384     }
4385   }
4386   // Picture slideshow
4387   if (m_screenSaver->ID() == "screensaver.xbmc.builtin.slideshow")
4388   {
4389     // reset our codec info - don't want that on screen
4390     g_infoManager.SetShowCodec(false);
4391     CStdString type = m_screenSaver->GetSetting("type");
4392     CStdString path = m_screenSaver->GetSetting("path");
4393     if (type == "2" && path.IsEmpty())
4394       type = "0";
4395     if (type == "0")
4396       path = "special://profile/Thumbnails/Video/Fanart";
4397     if (type == "1")
4398       path = "special://profile/Thumbnails/Music/Fanart";
4399     m_applicationMessenger.PictureSlideShow(path, true, type != "2");
4400   }
4401   else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim")
4402     return;
4403   else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4404     return;
4405   else if (!m_screenSaver->ID().IsEmpty())
4406     g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4407 }
4408
4409 void CApplication::CheckShutdown()
4410 {
4411   CGUIDialogMusicScan *pMusicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
4412   CGUIDialogVideoScan *pVideoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
4413
4414   // first check if we should reset the timer
4415   bool resetTimer = false;
4416   if (IsPlaying() || IsPaused()) // is something playing?
4417     resetTimer = true;
4418
4419   if (pMusicScan && pMusicScan->IsScanning()) // music scanning?
4420     resetTimer = true;
4421
4422   if (pVideoScan && pVideoScan->IsScanning()) // video scanning?
4423     resetTimer = true;
4424
4425   if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4426     resetTimer = true;
4427
4428   if (resetTimer)
4429   {
4430     m_shutdownTimer.StartZero();
4431     return;
4432   }
4433
4434   if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 )
4435   {
4436     // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4437     m_shutdownTimer.Stop();
4438
4439     // Sleep the box
4440     getApplicationMessenger().Shutdown();
4441   }
4442 }
4443
4444 bool CApplication::OnMessage(CGUIMessage& message)
4445 {
4446   switch ( message.GetMessage() )
4447   {
4448   case GUI_MSG_NOTIFY_ALL:
4449     {
4450       if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4451       {
4452         // Update general playlist: Remove DVD playlist items
4453         int nRemoved = g_playlistPlayer.RemoveDVDItems();
4454         if ( nRemoved > 0 )
4455         {
4456           CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4457           g_windowManager.SendMessage( msg );
4458         }
4459         // stop the file if it's on dvd (will set the resume point etc)
4460         if (m_itemCurrentFile->IsOnDVD())
4461           StopPlaying();
4462       }
4463     }
4464     break;
4465
4466   case GUI_MSG_PLAYBACK_STARTED:
4467     {
4468 #ifdef TARGET_DARWIN
4469       DarwinSetScheduling(message.GetMessage());
4470 #endif
4471       // Update our infoManager with the new details etc.
4472       if (m_nextPlaylistItem >= 0)
4473       { // we've started a previously queued item
4474         CFileItemPtr item = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist())[m_nextPlaylistItem];
4475         // update the playlist manager
4476         int currentSong = g_playlistPlayer.GetCurrentSong();
4477         int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4478         CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4479         g_windowManager.SendThreadMessage(msg);
4480         g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4481         *m_itemCurrentFile = *item;
4482       }
4483       g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4484       CLastFmManager::GetInstance()->OnSongChange(*m_itemCurrentFile);
4485       g_partyModeManager.OnSongChange(true);
4486
4487       CVariant param;
4488       param["player"]["speed"] = 1;
4489       param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4490       CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4491
4492       DimLCDOnPlayback(true);
4493
4494       if (IsPlayingAudio())
4495       {
4496         // Start our cdg parser as appropriate
4497 #ifdef HAS_KARAOKE
4498         if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4499         {
4500           m_pKaraokeMgr->Stop();
4501           if (m_itemCurrentFile->IsMusicDb())
4502           {
4503             if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4504             {
4505               IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4506               tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4507               delete tagloader;
4508             }
4509             m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4510           }
4511           else
4512             m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4513         }
4514 #endif
4515         // Let scrobbler know about the track
4516         const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag();
4517         if (tag)
4518         {
4519           CLastfmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4520           CLibrefmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4521         }
4522       }
4523
4524       return true;
4525     }
4526     break;
4527
4528   case GUI_MSG_QUEUE_NEXT_ITEM:
4529     {
4530       // Check to see if our playlist player has a new item for us,
4531       // and if so, we check whether our current player wants the file
4532       int iNext = g_playlistPlayer.GetNextSong();
4533       CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4534       if (iNext < 0 || iNext >= playlist.size())
4535       {
4536         if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4537         return true; // nothing to do
4538       }
4539       // ok, grab the next song
4540       CFileItemPtr item = playlist[iNext];
4541       // ok - send the file to the player if it wants it
4542       if (m_pPlayer && m_pPlayer->QueueNextFile(*item))
4543       { // player wants the next file
4544         m_nextPlaylistItem = iNext;
4545       }
4546       return true;
4547     }
4548     break;
4549
4550   case GUI_MSG_PLAYBACK_STOPPED:
4551   case GUI_MSG_PLAYBACK_ENDED:
4552   case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4553     {
4554 #ifdef HAS_KARAOKE
4555       if (m_pKaraokeMgr )
4556         m_pKaraokeMgr->Stop();
4557 #endif
4558 #ifdef TARGET_DARWIN
4559       DarwinSetScheduling(message.GetMessage());
4560 #endif
4561       // first check if we still have items in the stack to play
4562       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4563       {
4564         if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4565         { // just play the next item in the stack
4566           PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4567           return true;
4568         }
4569       }
4570       
4571       // In case playback ended due to user eg. skipping over the end, clear
4572       // our resume bookmark here
4573       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4574       {
4575         // Delete the bookmark
4576         m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4577       }
4578
4579       // reset the current playing file
4580       m_itemCurrentFile->Reset();
4581       g_infoManager.ResetCurrentItem();
4582       m_currentStack->Clear();
4583
4584       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4585       {
4586         g_playlistPlayer.PlayNext(1, true);
4587       }
4588       else
4589       {
4590         // stop lastfm
4591         if (CLastFmManager::GetInstance()->IsRadioEnabled())
4592           CLastFmManager::GetInstance()->StopRadio();
4593
4594         delete m_pPlayer;
4595         m_pPlayer = 0;
4596
4597         // Reset playspeed
4598         m_iPlaySpeed = 1;
4599       }
4600
4601       if (!IsPlaying())
4602       {
4603         g_audioManager.Enable(true);
4604         DimLCDOnPlayback(false);
4605       }
4606
4607       if (!IsPlayingVideo() && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4608       {
4609         g_windowManager.PreviousWindow();
4610       }
4611
4612       if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4613       {
4614         g_settings.Save();  // save vis settings
4615         WakeUpScreenSaverAndDPMS();
4616         g_windowManager.PreviousWindow();
4617       }
4618
4619       // DVD ejected while playing in vis ?
4620       if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4621       {
4622         // yes, disable vis
4623         g_settings.Save();    // save vis settings
4624         WakeUpScreenSaverAndDPMS();
4625         g_windowManager.PreviousWindow();
4626       }
4627
4628       if (IsEnableTestMode()) g_application.getApplicationMessenger().Quit();
4629       return true;
4630     }
4631     break;
4632
4633   case GUI_MSG_PLAYLISTPLAYER_STARTED:
4634   case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4635     {
4636       return true;
4637     }
4638     break;
4639   case GUI_MSG_FULLSCREEN:
4640     { // Switch to fullscreen, if we can
4641       SwitchToFullScreen();
4642       return true;
4643     }
4644     break;
4645   case GUI_MSG_EXECUTE:
4646     if (message.GetNumStringParams())
4647       return ExecuteXBMCAction(message.GetStringParam());
4648     break;
4649   }
4650   return false;
4651 }
4652
4653 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4654     {
4655       // see if it is a user set string
4656       CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4657       CGUIInfoLabel info(actionStr, "");
4658       actionStr = info.GetLabel(0);
4659       CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4660
4661       // user has asked for something to be executed
4662       if (CBuiltins::HasCommand(actionStr))
4663         CBuiltins::Execute(actionStr);
4664       else
4665       {
4666         // try translating the action from our ButtonTranslator
4667         int actionID;
4668         if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4669         {
4670           OnAction(CAction(actionID));
4671           return true;
4672         }
4673         CFileItem item(actionStr, false);
4674 #ifdef HAS_PYTHON
4675         if (item.IsPythonScript())
4676         { // a python script
4677           g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
4678         }
4679         else
4680 #endif
4681         if (item.IsAudio() || item.IsVideo())
4682         { // an audio or video file
4683           PlayFile(item);
4684         }
4685         else
4686           return false;
4687       }
4688       return true;
4689     }
4690
4691 void CApplication::Process()
4692 {
4693   MEASURE_FUNCTION;
4694
4695   // dispatch the messages generated by python or other threads to the current window
4696   g_windowManager.DispatchThreadMessages();
4697
4698   // process messages which have to be send to the gui
4699   // (this can only be done after g_windowManager.Render())
4700   m_applicationMessenger.ProcessWindowMessages();
4701
4702 #ifdef HAS_PYTHON
4703   // process any Python scripts
4704   g_pythonParser.Process();
4705 #endif
4706
4707   // process messages, even if a movie is playing
4708   m_applicationMessenger.ProcessMessages();
4709   if (g_application.m_bStop) return; //we're done, everything has been unloaded
4710
4711   // check if we can free unused memory
4712 #ifndef _LINUX
4713   g_audioManager.FreeUnused();
4714 #endif
4715
4716   // check how far we are through playing the current item
4717   // and do anything that needs doing (lastfm submission, playcount updates etc)
4718   CheckPlayingProgress();
4719
4720   // update sound
4721   if (m_pPlayer)
4722     m_pPlayer->DoAudioWork();
4723
4724   // do any processing that isn't needed on each run
4725   if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4726   {
4727     m_slowTimer.Reset();
4728     ProcessSlow();
4729   }
4730
4731   g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4732 }
4733
4734 // We get called every 500ms
4735 void CApplication::ProcessSlow()
4736 {
4737   g_powerManager.ProcessEvents();
4738
4739 #if defined(__APPLE__) &&  !defined(__arm__)
4740   // There is an issue on OS X that several system services ask the cursor to become visible
4741   // during their startup routines.  Given that we can't control this, we hack it in by
4742   // forcing the
4743   if (g_Windowing.IsFullScreen())
4744   { // SDL thinks it's hidden
4745     Cocoa_HideMouse();
4746   }
4747 #endif
4748
4749   // Store our file state for use on close()
4750   UpdateFileState();
4751
4752   if (IsPlayingAudio())
4753   {
4754     CLastfmScrobbler::GetInstance()->UpdateStatus();
4755     CLibrefmScrobbler::GetInstance()->UpdateStatus();
4756   }
4757
4758   // Check if we need to activate the screensaver / DPMS.
4759   CheckScreenSaverAndDPMS();
4760
4761   // Check if we need to shutdown (if enabled).
4762 #ifdef __APPLE__
4763   if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
4764 #else
4765   if (g_guiSettings.GetInt("powermanagement.shutdowntime"))
4766 #endif
4767   {
4768     CheckShutdown();
4769   }
4770
4771   // check if we should restart the player
4772   CheckDelayedPlayerRestart();
4773
4774   //  check if we can unload any unreferenced dlls or sections
4775   if (!IsPlayingVideo())
4776     CSectionLoader::UnloadDelayed();
4777
4778   // check for any idle curl connections
4779   g_curlInterface.CheckIdle();
4780
4781   // check for any idle myth sessions
4782   CMythSession::CheckIdle();
4783
4784 #ifdef HAS_FILESYSTEM_HTSP
4785   // check for any idle htsp sessions
4786   HTSP::CHTSPDirectorySession::CheckIdle();
4787 #endif
4788
4789 #ifdef HAS_KARAOKE
4790   if ( m_pKaraokeMgr )
4791     m_pKaraokeMgr->ProcessSlow();
4792 #endif
4793
4794   // LED - LCD SwitchOn On Paused! m_bIsPaused=TRUE -> LED/LCD is ON!
4795   if(IsPaused() != m_bIsPaused)
4796   {
4797 #ifdef HAS_LCD
4798     DimLCDOnPlayback(m_bIsPaused);
4799 #endif
4800     m_bIsPaused = IsPaused();
4801   }
4802
4803   if (!IsPlayingVideo())
4804     g_largeTextureManager.CleanupUnusedImages();
4805
4806 #ifdef HAS_DVD_DRIVE
4807   // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
4808   if (!IsPlayingVideo())
4809     m_Autorun->HandleAutorun();
4810 #endif
4811
4812   // update upnp server/renderer states
4813   if(CUPnP::IsInstantiated())
4814     CUPnP::GetInstance()->UpdateState();
4815
4816   //Check to see if current playing Title has changed and whether we should broadcast the fact
4817   CheckForTitleChange();
4818
4819 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
4820   smb.CheckIfIdle();
4821 #endif
4822   
4823 #ifdef HAS_FILESYSTEM_NFS
4824   gNfsConnection.CheckIfIdle();
4825 #endif
4826
4827 #ifdef HAS_FILESYSTEM_AFP
4828   gAfpConnection.CheckIfIdle();
4829 #endif
4830
4831 #ifdef HAS_FILESYSTEM_SFTP
4832   CSFTPSessionManager::ClearOutIdleSessions();
4833 #endif
4834
4835   g_mediaManager.ProcessEvents();
4836
4837 #ifdef HAS_LIRC
4838   if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
4839     g_RemoteControl.Initialize();
4840 #endif
4841
4842 #ifdef HAS_LCD
4843   // attempt to reinitialize the LCD (e.g. after resuming from sleep)
4844   if (!IsPlayingVideo())
4845   {
4846     if (g_lcd && !g_lcd->IsConnected())
4847     {
4848       g_lcd->Stop();
4849       g_lcd->Initialize();
4850     }
4851   }
4852 #endif
4853   
4854   if (!IsPlayingVideo())
4855     CAddonInstaller::Get().UpdateRepos();
4856 }
4857
4858 // Global Idle Time in Seconds
4859 // idle time will be resetet if on any OnKey()
4860 // int return: system Idle time in seconds! 0 is no idle!
4861 int CApplication::GlobalIdleTime()
4862 {
4863   if(!m_idleTimer.IsRunning())
4864   {
4865     m_idleTimer.Stop();
4866     m_idleTimer.StartZero();
4867   }
4868   return (int)m_idleTimer.GetElapsedSeconds();
4869 }
4870
4871 float CApplication::NavigationIdleTime()
4872 {
4873   if (!m_navigationTimer.IsRunning())
4874   {
4875     m_navigationTimer.Stop();
4876     m_navigationTimer.StartZero();
4877   }
4878   return m_navigationTimer.GetElapsedSeconds();
4879 }
4880
4881 void CApplication::DelayedPlayerRestart()
4882 {
4883   m_restartPlayerTimer.StartZero();
4884 }
4885
4886 void CApplication::CheckDelayedPlayerRestart()
4887 {
4888   if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
4889   {
4890     m_restartPlayerTimer.Stop();
4891     m_restartPlayerTimer.Reset();
4892     Restart(true);
4893   }
4894 }
4895
4896 void CApplication::Restart(bool bSamePosition)
4897 {
4898   // this function gets called when the user changes a setting (like noninterleaved)
4899   // and which means we gotta close & reopen the current playing file
4900
4901   // first check if we're playing a file
4902   if ( !IsPlayingVideo() && !IsPlayingAudio())
4903     return ;
4904
4905   if( !m_pPlayer )
4906     return ;
4907
4908   SaveFileState();
4909
4910   // do we want to return to the current position in the file
4911   if (false == bSamePosition)
4912   {
4913     // no, then just reopen the file and start at the beginning
4914     PlayFile(*m_itemCurrentFile, true);
4915     return ;
4916   }
4917
4918   // else get current position
4919   double time = GetTime();
4920
4921   // get player state, needed for dvd's
4922   CStdString state = m_pPlayer->GetPlayerState();
4923
4924   // set the requested starttime
4925   m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
4926
4927   // reopen the file
4928   if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer )
4929     m_pPlayer->SetPlayerState(state);
4930 }
4931
4932 const CStdString& CApplication::CurrentFile()
4933 {
4934   return m_itemCurrentFile->GetPath();
4935 }
4936
4937 CFileItem& CApplication::CurrentFileItem()
4938 {
4939   return *m_itemCurrentFile;
4940 }
4941
4942 void CApplication::ShowVolumeBar(const CAction *action)
4943 {
4944   CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
4945   if (volumeBar)
4946   {
4947     volumeBar->Show();
4948     if (action)
4949       volumeBar->OnAction(*action);
4950   }
4951 }
4952
4953 bool CApplication::IsMuted() const
4954 {
4955   return g_settings.m_bMute;
4956 }
4957
4958 void CApplication::ToggleMute(void)
4959 {
4960   if (g_settings.m_bMute)
4961     UnMute();
4962   else
4963     Mute();
4964 }
4965
4966 void CApplication::Mute()
4967 {
4968   g_settings.m_iPreMuteVolumeLevel = GetVolume();
4969   SetVolume(0);
4970   g_settings.m_bMute = true;
4971 }
4972
4973 void CApplication::UnMute()
4974 {
4975   SetVolume(g_settings.m_iPreMuteVolumeLevel);
4976   g_settings.m_iPreMuteVolumeLevel = 0;
4977   g_settings.m_bMute = false;
4978 }
4979
4980 void CApplication::SetVolume(long iValue, bool isPercentage /* = true */)
4981 {
4982   // convert the percentage to a mB (milliBell) value (*100 for dB)
4983   if (isPercentage)
4984     iValue = (long)((float)iValue * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
4985
4986   SetHardwareVolume(iValue);
4987 #ifndef HAS_SDL_AUDIO
4988   g_audioManager.SetVolume(g_settings.m_nVolumeLevel);
4989 #else
4990   g_audioManager.SetVolume((int)(128.f * (g_settings.m_nVolumeLevel - VOLUME_MINIMUM) / (float)(VOLUME_MAXIMUM - VOLUME_MINIMUM)));
4991 #endif
4992 }
4993
4994 void CApplication::SetHardwareVolume(long hardwareVolume)
4995 {
4996   // TODO DRC
4997   if (hardwareVolume >= VOLUME_MAXIMUM) // + VOLUME_DRC_MAXIMUM
4998     hardwareVolume = VOLUME_MAXIMUM;// + VOLUME_DRC_MAXIMUM;
4999   if (hardwareVolume <= VOLUME_MINIMUM)
5000     hardwareVolume = VOLUME_MINIMUM;
5001
5002   // update our settings
5003   if (hardwareVolume > VOLUME_MAXIMUM)
5004   {
5005     g_settings.m_dynamicRangeCompressionLevel = hardwareVolume - VOLUME_MAXIMUM;
5006     g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
5007   }
5008   else
5009   {
5010     g_settings.m_dynamicRangeCompressionLevel = 0;
5011     g_settings.m_nVolumeLevel = hardwareVolume;
5012   }
5013
5014   // and tell our player to update the volume
5015   if (m_pPlayer)
5016   {
5017     m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5018     // TODO DRC
5019 //    m_pPlayer->SetDynamicRangeCompression(g_settings.m_dynamicRangeCompressionLevel);
5020   }
5021 }
5022
5023 int CApplication::GetVolume() const
5024 {
5025   // converts the hardware volume (in mB) to a percentage
5026   return int(((float)(g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel - VOLUME_MINIMUM)) / (VOLUME_MAXIMUM - VOLUME_MINIMUM)*100.0f + 0.5f);
5027 }
5028
5029 int CApplication::GetSubtitleDelay() const
5030 {
5031   // converts subtitle delay to a percentage
5032   return int(((float)(g_settings.m_currentVideoSettings.m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5033 }
5034
5035 int CApplication::GetAudioDelay() const
5036 {
5037   // converts subtitle delay to a percentage
5038   return int(((float)(g_settings.m_currentVideoSettings.m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5039 }
5040
5041 void CApplication::SetPlaySpeed(int iSpeed)
5042 {
5043   if (!IsPlayingAudio() && !IsPlayingVideo())
5044     return ;
5045   if (m_iPlaySpeed == iSpeed)
5046     return ;
5047   if (!m_pPlayer->CanSeek())
5048     return;
5049   if (m_pPlayer->IsPaused())
5050   {
5051     if (
5052       ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5053       ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5054     )
5055     {
5056       iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5057     }
5058     m_pPlayer->Pause();
5059   }
5060   m_iPlaySpeed = iSpeed;
5061
5062   m_pPlayer->ToFFRW(m_iPlaySpeed);
5063   if (m_iPlaySpeed == 1)
5064   { // restore volume
5065     m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5066   }
5067   else
5068   { // mute volume
5069     m_pPlayer->SetVolume(VOLUME_MINIMUM);
5070   }
5071 }
5072
5073 int CApplication::GetPlaySpeed() const
5074 {
5075   return m_iPlaySpeed;
5076 }
5077
5078 // Returns the total time in seconds of the current media.  Fractional
5079 // portions of a second are possible - but not necessarily supported by the
5080 // player class.  This returns a double to be consistent with GetTime() and
5081 // SeekTime().
5082 double CApplication::GetTotalTime() const
5083 {
5084   double rc = 0.0;
5085
5086   if (IsPlaying() && m_pPlayer)
5087   {
5088     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5089       rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5090     else
5091       rc = m_pPlayer->GetTotalTime();
5092   }
5093
5094   return rc;
5095 }
5096
5097 void CApplication::StopShutdownTimer()
5098 {
5099   if (m_shutdownTimer.IsRunning())
5100     m_shutdownTimer.Stop();
5101 }
5102
5103 void CApplication::ResetShutdownTimers()
5104 {
5105   // reset system shutdown timer
5106   m_shutdownTimer.StartZero();
5107
5108   // delete custom shutdown timer
5109   if (g_alarmClock.HasAlarm("shutdowntimer"))
5110     g_alarmClock.Stop("shutdowntimer", true);
5111 }
5112
5113 // Returns the current time in seconds of the currently playing media.
5114 // Fractional portions of a second are possible.  This returns a double to
5115 // be consistent with GetTotalTime() and SeekTime().
5116 double CApplication::GetTime() const
5117 {
5118   double rc = 0.0;
5119
5120   if (IsPlaying() && m_pPlayer)
5121   {
5122     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5123     {
5124       long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5125       rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5126     }
5127     else
5128       rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5129   }
5130
5131   return rc;
5132 }
5133
5134 // Sets the current position of the currently playing media to the specified
5135 // time in seconds.  Fractional portions of a second are valid.  The passed
5136 // time is the time offset from the beginning of the file as opposed to a
5137 // delta from the current position.  This method accepts a double to be
5138 // consistent with GetTime() and GetTotalTime().
5139 void CApplication::SeekTime( double dTime )
5140 {
5141   if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5142   {
5143     if (!m_pPlayer->CanSeek()) return;
5144     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5145     {
5146       // find the item in the stack we are seeking to, and load the new
5147       // file if necessary, and calculate the correct seek within the new
5148       // file.  Otherwise, just fall through to the usual routine if the
5149       // time is higher than our total time.
5150       for (int i = 0; i < m_currentStack->Size(); i++)
5151       {
5152         if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5153         {
5154           long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5155           if (m_currentStackPosition == i)
5156             m_pPlayer->SeekTime((__int64)((dTime - startOfNewFile) * 1000.0));
5157           else
5158           { // seeking to a new file
5159             m_currentStackPosition = i;
5160             CFileItem item(*(*m_currentStack)[i]);
5161             item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5162             // don't just call "PlayFile" here, as we are quite likely called from the
5163             // player thread, so we won't be able to delete ourselves.
5164             m_applicationMessenger.PlayFile(item, true);
5165           }
5166           return;
5167         }
5168       }
5169     }
5170     // convert to milliseconds and perform seek
5171     m_pPlayer->SeekTime( static_cast<__int64>( dTime * 1000.0 ) );
5172   }
5173 }
5174
5175 float CApplication::GetPercentage() const
5176 {
5177   if (IsPlaying() && m_pPlayer)
5178   {
5179     if (IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5180     {
5181       const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5182       if (tag.GetDuration() > 0)
5183         return (float)(GetTime() / tag.GetDuration() * 100);
5184     }
5185
5186     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5187       return (float)(GetTime() / GetTotalTime() * 100);
5188     else
5189       return m_pPlayer->GetPercentage();
5190   }
5191   return 0.0f;
5192 }
5193
5194 float CApplication::GetCachePercentage() const
5195 {
5196   if (IsPlaying() && m_pPlayer)
5197     return m_pPlayer->GetCachePercentage();
5198
5199   return 0.0f;
5200 }
5201
5202 void CApplication::SeekPercentage(float percent)
5203 {
5204   if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5205   {
5206     if (!m_pPlayer->CanSeek()) return;
5207     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5208       SeekTime(percent * 0.01 * GetTotalTime());
5209     else
5210       m_pPlayer->SeekPercentage(percent);
5211   }
5212 }
5213
5214 // SwitchToFullScreen() returns true if a switch is made, else returns false
5215 bool CApplication::SwitchToFullScreen()
5216 {
5217   // if playing from the video info window, close it first!
5218   if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5219   {
5220     CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5221     if (pDialog) pDialog->Close(true);
5222   }
5223
5224   // don't switch if there is a dialog on screen or the slideshow is active
5225   if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5226     return false;
5227
5228   // See if we're playing a video, and are in GUI mode
5229   if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5230   {
5231     // Reset frame count so that timing is FPS will be correct.
5232     {
5233       CSingleLock lock(m_frameMutex);
5234       m_frameCount = 0;
5235     }
5236
5237     // then switch to fullscreen mode
5238     g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5239     return true;
5240   }
5241   // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5242   if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5243   { // then switch to visualisation
5244     g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5245     return true;
5246   }
5247   return false;
5248 }
5249
5250 void CApplication::Minimize()
5251 {
5252   g_Windowing.Minimize();
5253 }
5254
5255 PLAYERCOREID CApplication::GetCurrentPlayer()
5256 {
5257   return m_eCurrentPlayer;
5258 }
5259
5260 // when a scan is initiated, save current settings
5261 // and enable tag reading and remote thums
5262 void CApplication::SaveMusicScanSettings()
5263 {
5264   CLog::Log(LOGINFO,"Music scan has started... Enabling tag reading, and remote thumbs");
5265   g_settings.m_bMyMusicIsScanning = true;
5266   g_settings.Save();
5267 }
5268
5269 void CApplication::RestoreMusicScanSettings()
5270 {
5271   g_settings.m_bMyMusicIsScanning = false;
5272   g_settings.Save();
5273 }
5274
5275 void CApplication::UpdateLibraries()
5276 {
5277   if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
5278   {
5279     CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5280     CGUIDialogVideoScan *scanner = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
5281     if (scanner && !scanner->IsScanning())
5282       scanner->StartScanning("");
5283   }
5284
5285   if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
5286   {
5287     CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5288     CGUIDialogMusicScan *scanner = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
5289     if (scanner && !scanner->IsScanning())
5290       scanner->StartScanning("");
5291   }
5292 }
5293
5294 void CApplication::CheckPlayingProgress()
5295 {
5296   // check if we haven't rewound past the start of the file
5297   if (IsPlaying())
5298   {
5299     int iSpeed = g_application.GetPlaySpeed();
5300     if (iSpeed < 1)
5301     {
5302       iSpeed *= -1;
5303       int iPower = 0;
5304       while (iSpeed != 1)
5305       {
5306         iSpeed >>= 1;
5307         iPower++;
5308       }
5309       if (g_infoManager.GetPlayTime() / 1000 < iPower)
5310       {
5311         g_application.SetPlaySpeed(1);
5312         g_application.SeekTime(0);
5313       }
5314     }
5315   }
5316 }
5317
5318 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5319 {
5320   CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5321
5322   // initial exit conditions
5323   // no songs in playlist just return
5324   if (playlist.size() == 0)
5325     return false;
5326
5327   // illegal playlist
5328   if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5329     return false;
5330
5331   // setup correct playlist
5332   g_playlistPlayer.ClearPlaylist(iPlaylist);
5333
5334   // if the playlist contains an internet stream, this file will be used
5335   // to generate a thumbnail for musicplayer.cover
5336   g_application.m_strPlayListFile = strPlayList;
5337
5338   // add the items to the playlist player
5339   g_playlistPlayer.Add(iPlaylist, playlist);
5340
5341   // if we have a playlist
5342   if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5343   {
5344     // start playing it
5345     g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5346     g_playlistPlayer.Reset();
5347     g_playlistPlayer.Play(track);
5348     return true;
5349   }
5350   return false;
5351 }
5352
5353 void CApplication::SaveCurrentFileSettings()
5354 {
5355   if (m_itemCurrentFile->IsVideo())
5356   {
5357     // save video settings
5358     if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings)
5359     {
5360       CVideoDatabase dbs;
5361       dbs.Open();
5362       dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), g_settings.m_currentVideoSettings);
5363       dbs.Close();
5364     }
5365   }
5366 }
5367
5368 bool CApplication::AlwaysProcess(const CAction& action)
5369 {
5370   // check if this button is mapped to a built-in function
5371   if (!action.GetName().IsEmpty())
5372   {
5373     CStdString builtInFunction;
5374     vector<CStdString> params;
5375     CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5376     builtInFunction.ToLower();
5377
5378     // should this button be handled normally or just cancel the screensaver?
5379     if (   builtInFunction.Equals("powerdown")
5380         || builtInFunction.Equals("reboot")
5381         || builtInFunction.Equals("restart")
5382         || builtInFunction.Equals("restartapp")
5383         || builtInFunction.Equals("suspend")
5384         || builtInFunction.Equals("hibernate")
5385         || builtInFunction.Equals("quit")
5386         || builtInFunction.Equals("shutdown"))
5387     {
5388       return true;
5389     }
5390   }
5391
5392   return false;
5393 }
5394
5395 CApplicationMessenger& CApplication::getApplicationMessenger()
5396 {
5397    return m_applicationMessenger;
5398 }
5399
5400 bool CApplication::IsCurrentThread() const
5401 {
5402   return CThread::IsCurrentThread(m_threadID);
5403 }
5404
5405 bool CApplication::IsPresentFrame()
5406 {
5407   CSingleLock lock(m_frameMutex);
5408   bool ret = m_bPresentFrame;
5409
5410   return ret;
5411 }
5412
5413 #if defined(HAS_LINUX_NETWORK)
5414 CNetworkLinux& CApplication::getNetwork()
5415 {
5416   return m_network;
5417 }
5418 #elif defined(HAS_WIN32_NETWORK)
5419 CNetworkWin32& CApplication::getNetwork()
5420 {
5421   return m_network;
5422 }
5423 #else
5424 CNetwork& CApplication::getNetwork()
5425 {
5426   return m_network;
5427 }
5428
5429 #endif
5430 #ifdef HAS_PERFORMANCE_SAMPLE
5431 CPerformanceStats &CApplication::GetPerformanceStats()
5432 {
5433   return m_perfStats;
5434 }
5435 #endif