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