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