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