Merge pull request #3878 from jmarshallnz/more_dep_checks
[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.empty())
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().empty())
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     CSettingBool *usestagefright = (CSettingBool*)setting;
1727     usestagefright->SetValue(false);
1728   }
1729 #endif
1730
1731   return false;
1732 }
1733
1734 bool CApplication::OnSettingsSaving() const
1735 {
1736   // don't save settings when we're busy stopping the application
1737   // a lot of screens try to save settings on deinit and deinit is
1738   // called for every screen when the application is stopping
1739   if (m_bStop)
1740     return false;
1741
1742   return true;
1743 }
1744
1745 void CApplication::ReloadSkin(bool confirm/*=false*/)
1746 {
1747   m_skinReloading = false;
1748   std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1749
1750   CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1751   g_windowManager.SendMessage(msg);
1752   
1753   // Reload the skin, restoring the previously focused control.  We need this as
1754   // the window unload will reset all control states.
1755   int iCtrlID = -1;
1756   CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1757   if (pWindow)
1758     iCtrlID = pWindow->GetFocusedControlID();
1759   
1760   g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1761  
1762   if (iCtrlID != -1)
1763   {
1764     pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1765     if (pWindow && pWindow->HasSaveLastControl())
1766     {
1767       CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1768       pWindow->OnMessage(msg3);
1769     }
1770   }
1771
1772   if (!m_skinReverting && confirm)
1773   {
1774     bool cancelled;
1775     if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1776     {
1777       m_skinReverting = true;
1778       if (oldSkin.empty())
1779         CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1780       else
1781         CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1782     }
1783   }
1784
1785   m_skinReverting = false;
1786 }
1787
1788 bool CApplication::Load(const TiXmlNode *settings)
1789 {
1790   if (settings == NULL)
1791     return false;
1792
1793   const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1794   if (audioElement != NULL)
1795   {
1796     XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1797     if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1798       m_volumeLevel = VOLUME_MAXIMUM;
1799   }
1800
1801   return true;
1802 }
1803
1804 bool CApplication::Save(TiXmlNode *settings) const
1805 {
1806   if (settings == NULL)
1807     return false;
1808
1809   TiXmlElement volumeNode("audio");
1810   TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1811   if (audioNode == NULL)
1812     return false;
1813
1814   XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1815   XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1816
1817   return true;
1818 }
1819
1820 bool CApplication::LoadSkin(const CStdString& skinID)
1821 {
1822   if (m_skinReloading)
1823     return false;
1824
1825   AddonPtr addon;
1826   if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1827   {
1828     LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1829     return true;
1830   }
1831   return false;
1832 }
1833
1834 void CApplication::LoadSkin(const SkinPtr& skin)
1835 {
1836   string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1837   if (!skin)
1838   {
1839     CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1840     CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1841     return ;
1842   }
1843
1844   skin->Start();
1845   if (!skin->HasSkinFile("Home.xml"))
1846   {
1847     // failed to find home.xml
1848     // fallback to default skin
1849     if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1850     {
1851       CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1852       CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1853       CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1854       return ;
1855     }
1856   }
1857
1858   bool bPreviousPlayingState=false;
1859   bool bPreviousRenderingState=false;
1860   if (g_application.m_pPlayer->IsPlayingVideo())
1861   {
1862     bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1863     if (bPreviousPlayingState)
1864       g_application.m_pPlayer->Pause();
1865 #ifdef HAS_VIDEO_PLAYBACK
1866     if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1867     {
1868       g_windowManager.ActivateWindow(WINDOW_HOME);
1869       bPreviousRenderingState = true;
1870     }
1871 #endif
1872   }
1873   // close the music and video overlays (they're re-opened automatically later)
1874   CSingleLock lock(g_graphicsContext);
1875
1876   // save the current window details
1877   int currentWindow = g_windowManager.GetActiveWindow();
1878   vector<int> currentModelessWindows;
1879   g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1880
1881   UnloadSkin();
1882
1883   CLog::Log(LOGINFO, "  load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1884   g_SkinInfo = skin;
1885   g_SkinInfo->Start();
1886
1887   CLog::Log(LOGINFO, "  load fonts for skin...");
1888   g_graphicsContext.SetMediaDir(skin->Path());
1889   g_directoryCache.ClearSubPaths(skin->Path());
1890   if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1891   {
1892     CLog::Log(LOGINFO, "    language needs a ttf font, loading first ttf font available");
1893     CStdString strFontSet;
1894     if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1895     {
1896       CLog::Log(LOGINFO, "    new font is '%s'", strFontSet.c_str());
1897       CSettings::Get().SetString("lookandfeel.font", strFontSet);
1898       CSettings::Get().Save();
1899     }
1900     else
1901       CLog::Log(LOGERROR, "    no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1902   }
1903   g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1904
1905   g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1906
1907   // load in the skin strings
1908   CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1909   URIUtils::AddSlashAtEnd(langPath);
1910
1911   g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1912
1913   g_SkinInfo->LoadIncludes();
1914
1915   int64_t start;
1916   start = CurrentHostCounter();
1917
1918   CLog::Log(LOGINFO, "  load new skin...");
1919
1920   // Load the user windows
1921   LoadUserWindows();
1922
1923   int64_t end, freq;
1924   end = CurrentHostCounter();
1925   freq = CurrentHostFrequency();
1926   CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1927
1928   CLog::Log(LOGINFO, "  initialize new skin...");
1929   g_windowManager.AddMsgTarget(this);
1930   g_windowManager.AddMsgTarget(&g_playlistPlayer);
1931   g_windowManager.AddMsgTarget(&g_infoManager);
1932   g_windowManager.AddMsgTarget(&g_fontManager);
1933   g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1934   g_windowManager.SetCallback(*this);
1935   g_windowManager.Initialize();
1936   CTextureCache::Get().Initialize();
1937   g_audioManager.Enable(true);
1938   g_audioManager.Load();
1939
1940   if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1941     g_windowManager.Add(new CGUIDialogFullScreenInfo);
1942
1943   { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1944     CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1945     if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1946     overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1947     if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1948   }
1949
1950   CLog::Log(LOGINFO, "  skin loaded...");
1951
1952   // leave the graphics lock
1953   lock.Leave();
1954
1955   // restore windows
1956   if (currentWindow != WINDOW_INVALID)
1957   {
1958     g_windowManager.ActivateWindow(currentWindow);
1959     for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1960     {
1961       CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1962       if (dialog) dialog->Show();
1963     }
1964   }
1965
1966   if (g_application.m_pPlayer->IsPlayingVideo())
1967   {
1968     if (bPreviousPlayingState)
1969       g_application.m_pPlayer->Pause();
1970     if (bPreviousRenderingState)
1971       g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1972   }
1973 }
1974
1975 void CApplication::UnloadSkin(bool forReload /* = false */)
1976 {
1977   m_skinReloading = forReload;
1978
1979   CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1980
1981   g_audioManager.Enable(false);
1982
1983   g_windowManager.DeInitialize();
1984   CTextureCache::Get().Deinitialize();
1985
1986   // remove the skin-dependent window
1987   g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1988
1989   g_TextureManager.Cleanup();
1990   g_largeTextureManager.CleanupUnusedImages(true);
1991
1992   g_fontManager.Clear();
1993
1994   g_colorManager.Clear();
1995
1996   g_infoManager.Clear();
1997
1998 //  The g_SkinInfo boost shared_ptr ought to be reset here
1999 // but there are too many places it's used without checking for NULL
2000 // and as a result a race condition on exit can cause a crash.
2001 }
2002
2003 bool CApplication::LoadUserWindows()
2004 {
2005   // Start from wherever home.xml is
2006   std::vector<CStdString> vecSkinPath;
2007   g_SkinInfo->GetSkinPaths(vecSkinPath);
2008   for (unsigned int i = 0;i < vecSkinPath.size();++i)
2009   {
2010     CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2011     CFileItemList items;
2012     if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2013     {
2014       for (int i = 0; i < items.Size(); ++i)
2015       {
2016         if (items[i]->m_bIsFolder)
2017           continue;
2018         CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2019         if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2020         {
2021           CXBMCTinyXML xmlDoc;
2022           if (!xmlDoc.LoadFile(items[i]->GetPath()))
2023           {
2024             CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2025             continue;
2026           }
2027
2028           // Root element should be <window>
2029           TiXmlElement* pRootElement = xmlDoc.RootElement();
2030           CStdString strValue = pRootElement->Value();
2031           if (!strValue.Equals("window"))
2032           {
2033             CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2034             continue;
2035           }
2036
2037           // Read the <type> element to get the window type to create
2038           // If no type is specified, create a CGUIWindow as default
2039           CGUIWindow* pWindow = NULL;
2040           CStdString strType;
2041           if (pRootElement->Attribute("type"))
2042             strType = pRootElement->Attribute("type");
2043           else
2044           {
2045             const TiXmlNode *pType = pRootElement->FirstChild("type");
2046             if (pType && pType->FirstChild())
2047               strType = pType->FirstChild()->Value();
2048           }
2049           int id = WINDOW_INVALID;
2050           if (!pRootElement->Attribute("id", &id))
2051           {
2052             const TiXmlNode *pType = pRootElement->FirstChild("id");
2053             if (pType && pType->FirstChild())
2054               id = atol(pType->FirstChild()->Value());
2055           }
2056           CStdString visibleCondition;
2057           CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2058
2059           if (strType.Equals("dialog"))
2060             pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2061           else if (strType.Equals("submenu"))
2062             pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2063           else if (strType.Equals("buttonmenu"))
2064             pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2065           else
2066             pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2067
2068           // Check to make sure the pointer isn't still null
2069           if (pWindow == NULL)
2070           {
2071             CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2072             return false;
2073           }
2074           if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2075           {
2076             delete pWindow;
2077             continue;
2078           }
2079           pWindow->SetVisibleCondition(visibleCondition);
2080           pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2081           g_windowManager.AddCustomWindow(pWindow);
2082         }
2083       }
2084     }
2085   }
2086   return true;
2087 }
2088
2089 bool CApplication::RenderNoPresent()
2090 {
2091   MEASURE_FUNCTION;
2092
2093 // DXMERGE: This may have been important?
2094 //  g_graphicsContext.AcquireCurrentContext();
2095
2096   g_graphicsContext.Lock();
2097
2098   // dont show GUI when playing full screen video
2099   if (g_graphicsContext.IsFullScreenVideo())
2100   {
2101     g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2102     g_renderManager.Render(true, 0, 255);
2103
2104     // close window overlays
2105     CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2106     if (overlay) overlay->Close(true);
2107     overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2108     if (overlay) overlay->Close(true);
2109
2110   }
2111
2112   bool hasRendered = g_windowManager.Render();
2113
2114   g_graphicsContext.Unlock();
2115
2116   return hasRendered;
2117 }
2118
2119 float CApplication::GetDimScreenSaverLevel() const
2120 {
2121   if (!m_bScreenSave || !m_screenSaver ||
2122       (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2123        m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2124        !m_screenSaver->ID().empty()))
2125     return 0;
2126
2127   if (!m_screenSaver->GetSetting("level").empty())
2128     return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2129   return 100.0f;
2130 }
2131
2132 void CApplication::Render()
2133 {
2134   // do not render if we are stopped or in background
2135   if (m_bStop || m_bInBackground)
2136     return;
2137
2138   MEASURE_FUNCTION;
2139
2140   int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2141
2142   bool hasRendered = false;
2143   bool limitFrames = false;
2144   unsigned int singleFrameTime = 10; // default limit 100 fps
2145
2146   {
2147     // Less fps in DPMS
2148     bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2149     // Whether externalplayer is playing and we're unfocused
2150     bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2151
2152     m_bPresentFrame = false;
2153     if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2154     {
2155       m_bPresentFrame = g_renderManager.FrameWait(100);
2156       hasRendered = true;
2157     }
2158     else
2159     {
2160       // engage the frame limiter as needed
2161       limitFrames = lowfps || extPlayerActive;
2162       // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2163       //           perhaps allowing it to be set differently than the UI option??
2164       if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2165         limitFrames = true; // not using vsync.
2166       else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2167         limitFrames = true; // using vsync, but it isn't working.
2168
2169       if (limitFrames)
2170       {
2171         if (extPlayerActive)
2172         {
2173           ResetScreenSaver();  // Prevent screensaver dimming the screen
2174           singleFrameTime = 1000;  // 1 fps, high wakeup latency but v.low CPU usage
2175         }
2176         else if (lowfps)
2177           singleFrameTime = 200;  // 5 fps, <=200 ms latency to wake up
2178       }
2179
2180     }
2181   }
2182
2183   CSingleLock lock(g_graphicsContext);
2184   g_infoManager.UpdateFPS();
2185
2186   if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2187     g_Windowing.SetVSync(true);
2188   else if (vsync_mode == VSYNC_ALWAYS)
2189     g_Windowing.SetVSync(true);
2190   else if (vsync_mode != VSYNC_DRIVER)
2191     g_Windowing.SetVSync(false);
2192
2193   if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2194     ResetScreenSaver();
2195
2196   if(!g_Windowing.BeginRender())
2197     return;
2198
2199   g_renderManager.FrameMove();
2200
2201   CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2202   if(g_graphicsContext.GetStereoMode())
2203   {
2204     g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2205     if(RenderNoPresent())
2206       hasRendered = true;
2207
2208     if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2209     {
2210       g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2211       if(RenderNoPresent())
2212         hasRendered = true;
2213     }
2214     g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2215   }
2216   else
2217   {
2218     if(RenderNoPresent())
2219       hasRendered = true;
2220   }
2221
2222   g_renderManager.FrameFinish();
2223
2224   g_Windowing.EndRender();
2225
2226   // execute post rendering actions (finalize window closing)
2227   g_windowManager.AfterRender();
2228
2229   // reset our info cache - we do this at the end of Render so that it is
2230   // fresh for the next process(), or after a windowclose animation (where process()
2231   // isn't called)
2232   g_infoManager.ResetCache();
2233   lock.Leave();
2234
2235   unsigned int now = XbmcThreads::SystemClockMillis();
2236   if (hasRendered)
2237     m_lastRenderTime = now;
2238
2239   //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2240   //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2241   bool flip;
2242   if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2243     flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2244   else
2245     flip = true;
2246
2247   //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2248   if (limitFrames || !flip)
2249   {
2250     if (!limitFrames)
2251       singleFrameTime = 40; //if not flipping, loop at 25 fps
2252
2253     unsigned int frameTime = now - m_lastFrameTime;
2254     if (frameTime < singleFrameTime)
2255       Sleep(singleFrameTime - frameTime);
2256   }
2257   m_lastFrameTime = XbmcThreads::SystemClockMillis();
2258
2259   if (flip)
2260     g_graphicsContext.Flip(dirtyRegions);
2261   CTimeUtils::UpdateFrameTime(flip);
2262
2263   g_renderManager.UpdateResolution();
2264   g_renderManager.ManageCaptures();
2265 }
2266
2267 void CApplication::SetStandAlone(bool value)
2268 {
2269   g_advancedSettings.m_handleMounting = m_bStandalone = value;
2270 }
2271
2272 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2273 // The window manager will return true if the event is processed, false otherwise.
2274 // If not already processed, this routine handles global keypresses.  It returns
2275 // true if the key has been processed, false otherwise.
2276
2277 bool CApplication::OnKey(const CKey& key)
2278 {
2279
2280   // Turn the mouse off, as we've just got a keypress from controller or remote
2281   g_Mouse.SetActive(false);
2282
2283   // get the current active window
2284   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2285
2286   // this will be checked for certain keycodes that need
2287   // special handling if the screensaver is active
2288   CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2289
2290   // a key has been pressed.
2291   // reset Idle Timer
2292   m_idleTimer.StartZero();
2293   bool processKey = AlwaysProcess(action);
2294
2295   if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2296   {
2297     bool ret = true;
2298
2299     CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2300     // do not wake up the screensaver right after switching off the playing device
2301     if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2302       ret = CApplicationMessenger::Get().CECToggleState();
2303     else
2304       ret = CApplicationMessenger::Get().CECStandby();
2305     if (!ret) /* display is switched off */
2306       return true;
2307   }
2308
2309   ResetScreenSaver();
2310
2311   // allow some keys to be processed while the screensaver is active
2312   if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2313   {
2314     CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2315     return true;
2316   }
2317
2318   // change this if we have a dialog up
2319   if (g_windowManager.HasModalDialog())
2320   {
2321     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2322   }
2323   if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2324   { // fullscreen info dialog - special case
2325     action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2326
2327     if (!key.IsAnalogButton())
2328       CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2329
2330     if (OnAction(action))
2331       return true;
2332
2333     // fallthrough to the main window
2334     iWin = WINDOW_FULLSCREEN_VIDEO;
2335   }
2336   if (iWin == WINDOW_FULLSCREEN_VIDEO)
2337   {
2338     // current active window is full screen video.
2339     if (g_application.m_pPlayer->IsInMenu())
2340     {
2341       // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2342       action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2343     }
2344     else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2345     {
2346       // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2347       action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2348
2349       // if no PVR specific action/mapping is found, fall back to default
2350       if (action.GetID() == 0)
2351         action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2352     }
2353     else
2354     {
2355       // in any other case use the fullscreen window section of keymap.xml to map key->action
2356       action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2357     }
2358   }
2359   else
2360   {
2361     // current active window isnt the fullscreen window
2362     // just use corresponding section from keymap.xml
2363     // to map key->action
2364
2365     // first determine if we should use keyboard input directly
2366     bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2367     CGUIWindow *window = g_windowManager.GetWindow(iWin);
2368     if (window)
2369     {
2370       CGUIControl *control = window->GetFocusedControl();
2371       if (control)
2372       {
2373         // If this is an edit control set usekeyboard to true. This causes the
2374         // keypress to be processed directly not through the key mappings.
2375         if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2376           useKeyboard = true;
2377
2378         // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2379         // This causes the keypress to be used for list navigation.
2380         if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2381           useKeyboard = true;
2382       }
2383     }
2384     if (useKeyboard)
2385     {
2386       action = CAction(0); // reset our action
2387       if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2388       {
2389         // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2390         // and send those rather than actual keyboard presses.  Only for navigation-type commands though
2391         action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2392         if (!(action.GetID() == ACTION_MOVE_LEFT ||
2393               action.GetID() == ACTION_MOVE_RIGHT ||
2394               action.GetID() == ACTION_MOVE_UP ||
2395               action.GetID() == ACTION_MOVE_DOWN ||
2396               action.GetID() == ACTION_SELECT_ITEM ||
2397               action.GetID() == ACTION_ENTER ||
2398               action.GetID() == ACTION_PREVIOUS_MENU ||
2399               action.GetID() == ACTION_NAV_BACK))
2400         {
2401           // the action isn't plain navigation - check for a keyboard-specific keymap
2402           action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2403           if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2404                 action.GetID() == ACTION_BACKSPACE ||
2405                 action.GetID() == ACTION_SHIFT ||
2406                 action.GetID() == ACTION_SYMBOLS ||
2407                 action.GetID() == ACTION_CURSOR_LEFT ||
2408                 action.GetID() == ACTION_CURSOR_RIGHT)
2409             action = CAction(0); // don't bother with this action
2410         }
2411       }
2412       if (!action.GetID())
2413       {
2414         // keyboard entry - pass the keys through directly
2415         if (key.GetFromService())
2416           action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2417         else
2418         {
2419           // Check for paste keypress
2420 #ifdef TARGET_WINDOWS
2421           // In Windows paste is ctrl-V
2422           if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2423 #elif defined(TARGET_LINUX)
2424           // In Linux paste is ctrl-V
2425           if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2426 #elif defined(TARGET_DARWIN_OSX)
2427           // In OSX paste is cmd-V
2428           if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2429 #else
2430           // Placeholder for other operating systems
2431           if (false)
2432 #endif
2433             action = CAction(ACTION_PASTE);
2434           // If the unicode is non-zero the keypress is a non-printing character
2435           else if (key.GetUnicode())
2436             action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2437           // The keypress is a non-printing character
2438           else
2439             action = CAction(key.GetVKey() | KEY_VKEY);
2440         }
2441       }
2442
2443       CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2444
2445       if (OnAction(action))
2446         return true;
2447       // failed to handle the keyboard action, drop down through to standard action
2448     }
2449     if (key.GetFromService())
2450     {
2451       if (key.GetButtonCode() != KEY_INVALID)
2452         action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2453     }
2454     else
2455       action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2456   }
2457   if (!key.IsAnalogButton())
2458     CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2459
2460   return ExecuteInputAction(action);
2461 }
2462
2463 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2464 // This needs to return true if it processed the appcommand or false if it didn't
2465 bool CApplication::OnAppCommand(const CAction &action)
2466 {
2467   // Reset the screen saver
2468   ResetScreenSaver();
2469
2470   // If we were currently in the screen saver wake up and don't process the appcommand
2471   if (WakeUpScreenSaverAndDPMS())
2472     return true;
2473
2474   // The action ID is the APPCOMMAND code. We need to retrieve the action
2475   // associated with this appcommand from the mapping table.
2476   uint32_t appcmd = action.GetID();
2477   CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2478   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2479   CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2480
2481   // If we couldn't find an action return false to indicate we have not
2482   // handled this appcommand
2483   if (!appcmdaction.GetID())
2484   {
2485     CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2486     return false;
2487   }
2488
2489   // Process the appcommand
2490   CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2491   OnAction(appcmdaction);
2492
2493   // Always return true regardless of whether the action succeeded or not.
2494   // This stops Windows handling the appcommand itself.
2495   return true;
2496 }
2497
2498 bool CApplication::OnAction(const CAction &action)
2499 {
2500   // special case for switching between GUI & fullscreen mode.
2501   if (action.GetID() == ACTION_SHOW_GUI)
2502   { // Switch to fullscreen mode if we can
2503     if (SwitchToFullScreen())
2504     {
2505       m_navigationTimer.StartZero();
2506       return true;
2507     }
2508   }
2509
2510   if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2511   {
2512     g_graphicsContext.ToggleFullScreenRoot();
2513     return true;
2514   }
2515
2516   if (action.IsMouse())
2517     g_Mouse.SetActive(true);
2518
2519   
2520   if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)   
2521   {
2522     CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2523   }
2524   if (action.GetID() == ACTION_CREATE_BOOKMARK)
2525   {
2526     CGUIDialogVideoBookmarks::OnAddBookmark();
2527   }
2528   
2529   // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2530   // playing or ACTION_PLAYER_PLAY if we are not playing.
2531   if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2532   {
2533     if (m_pPlayer->IsPlaying())
2534       return OnAction(CAction(ACTION_PAUSE));
2535     else
2536       return OnAction(CAction(ACTION_PLAYER_PLAY));
2537   }
2538
2539   //if the action would start or stop inertial scrolling
2540   //by gesture - bypass the normal OnAction handler of current window
2541   if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2542   {
2543     // in normal case
2544     // just pass the action to the current window and let it handle it
2545     if (g_windowManager.OnAction(action))
2546     {
2547       m_navigationTimer.StartZero();
2548       return true;
2549     }
2550   }
2551
2552   // handle extra global presses
2553
2554   // screenshot : take a screenshot :)
2555   if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2556   {
2557     CScreenShot::TakeScreenshot();
2558     return true;
2559   }
2560   // built in functions : execute the built-in
2561   if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2562   {
2563     CBuiltins::Execute(action.GetName());
2564     m_navigationTimer.StartZero();
2565     return true;
2566   }
2567
2568   // reload keymaps
2569   if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2570   {
2571     CButtonTranslator::GetInstance().Clear();
2572     CButtonTranslator::GetInstance().Load();
2573   }
2574
2575   // show info : Shows the current video or song information
2576   if (action.GetID() == ACTION_SHOW_INFO)
2577   {
2578     g_infoManager.ToggleShowInfo();
2579     return true;
2580   }
2581
2582   // codec info : Shows the current song, video or picture codec information
2583   if (action.GetID() == ACTION_SHOW_CODEC)
2584   {
2585     g_infoManager.ToggleShowCodec();
2586     return true;
2587   }
2588
2589   if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2590   {
2591     const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2592     if (tag)
2593     {
2594       *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2595       char rating = tag->GetRating();
2596       bool needsUpdate(false);
2597       if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2598       {
2599         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2600         needsUpdate = true;
2601       }
2602       else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2603       {
2604         m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2605         needsUpdate = true;
2606       }
2607       if (needsUpdate)
2608       {
2609         CMusicDatabase db;
2610         if (db.Open())      // OpenForWrite() ?
2611         {
2612           db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2613           db.Close();
2614         }
2615         // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2616         CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2617         g_windowManager.SendMessage(msg);
2618       }
2619     }
2620     return true;
2621   }
2622
2623   // Now check with the playlist player if action can be handled.
2624   // 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.
2625   if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2626   {
2627     if (g_playlistPlayer.OnAction(action))
2628       return true;
2629   }
2630
2631   // Now check with the player if action can be handled.
2632   if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2633       (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)))
2634   {
2635     if (m_pPlayer->OnAction(action))
2636       return true;
2637   }
2638
2639   // stop : stops playing current audio song
2640   if (action.GetID() == ACTION_STOP)
2641   {
2642     StopPlaying();
2643     return true;
2644   }
2645
2646   // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2647   // If so, we just jump to the start of the track.
2648   if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2649   {
2650     SeekTime(0);
2651     m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2652     return true;
2653   }
2654
2655   // forward action to g_PVRManager and break if it was able to handle it
2656   if (g_PVRManager.OnAction(action))
2657     return true;
2658
2659   // forward action to graphic context and see if it can handle it
2660   if (CStereoscopicsManager::Get().OnAction(action))
2661     return true;
2662
2663   if (m_pPlayer->IsPlaying())
2664   {
2665     // forward channel switches to the player - he knows what to do
2666     if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2667     {
2668       m_pPlayer->OnAction(action);
2669       return true;
2670     }
2671
2672     // pause : pauses current audio song
2673     if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2674     {
2675       m_pPlayer->Pause();
2676 #ifdef HAS_KARAOKE
2677       m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2678 #endif
2679       if (!m_pPlayer->IsPaused())
2680       { // unpaused - set the playspeed back to normal
2681         m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2682       }
2683       g_audioManager.Enable(m_pPlayer->IsPaused());
2684       return true;
2685     }
2686     if (!m_pPlayer->IsPaused())
2687     {
2688       // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2689       // if we are playing at normal speed, then allow play to pause
2690       if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2691       {
2692         if (m_pPlayer->GetPlaySpeed() != 1)
2693         {
2694           m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2695         }
2696         else
2697         {
2698           m_pPlayer->Pause();
2699         }
2700         return true;
2701       }
2702       if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2703       {
2704         int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2705         if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2706           iPlaySpeed *= -2;
2707         else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2708           iPlaySpeed /= 2;
2709         else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2710           iPlaySpeed /= 2;
2711         else
2712           iPlaySpeed *= 2;
2713
2714         if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2715           iPlaySpeed = 1;
2716         if (iPlaySpeed > 32 || iPlaySpeed < -32)
2717           iPlaySpeed = 1;
2718
2719         m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2720         return true;
2721       }
2722       else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2723       {
2724         // calculate the speed based on the amount the button is held down
2725         int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2726         // returns 0 -> MAX_FFWD_SPEED
2727         int iSpeed = 1 << iPower;
2728         if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2729           iSpeed = -iSpeed;
2730         g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2731         if (iSpeed == 1)
2732           CLog::Log(LOGDEBUG,"Resetting playspeed");
2733         return true;
2734       }
2735     }
2736     // allow play to unpause
2737     else
2738     {
2739       if (action.GetID() == ACTION_PLAYER_PLAY)
2740       {
2741         // unpause, and set the playspeed back to normal
2742         m_pPlayer->Pause();
2743         g_audioManager.Enable(m_pPlayer->IsPaused());
2744
2745         g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2746         return true;
2747       }
2748     }
2749
2750     if (m_playerController->OnAction(action))
2751       return true;
2752   }
2753
2754
2755   if (action.GetID() == ACTION_SWITCH_PLAYER)
2756   {
2757     if(m_pPlayer->IsPlaying())
2758     {
2759       VECPLAYERCORES cores;
2760       CFileItem item(*m_itemCurrentFile.get());
2761       CPlayerCoreFactory::Get().GetPlayers(item, cores);
2762       PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2763       if(core != EPC_NONE)
2764       {
2765         g_application.m_eForcedNextPlayer = core;
2766         item.m_lStartOffset = (int)(GetTime() * 75);
2767         PlayFile(item, true);
2768       }
2769     }
2770     else
2771     {
2772       VECPLAYERCORES cores;
2773       CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2774       PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2775       if(core != EPC_NONE)
2776       {
2777         CFileItem item;
2778         g_application.m_eForcedNextPlayer = core;
2779         PlayFile(item, false);
2780       }
2781     }
2782   }
2783
2784   if (g_peripherals.OnAction(action))
2785     return true;
2786
2787   if (action.GetID() == ACTION_MUTE)
2788   {
2789     ToggleMute();
2790     return true;
2791   }
2792
2793   if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2794   {
2795     bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2796     CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2797
2798     if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2799     {
2800       CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2801       g_windowManager.SendMessage(msg);
2802     }
2803     return true;
2804   }
2805
2806   // Check for global volume control
2807   if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2808   {
2809     if (!m_pPlayer->IsPassthrough())
2810     {
2811       if (m_muted)
2812         UnMute();
2813       float volume = m_volumeLevel;
2814 // Android has steps based on the max available volume level
2815 #if defined(TARGET_ANDROID)
2816       float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2817 #else
2818       float step   = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2819
2820       if (action.GetRepeat())
2821         step *= action.GetRepeat() * 50; // 50 fps
2822 #endif
2823       if (action.GetID() == ACTION_VOLUME_UP)
2824         volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2825       else
2826         volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2827       SetVolume(volume, false);
2828     }
2829     // show visual feedback of volume change...
2830     ShowVolumeBar(&action);
2831     return true;
2832   }
2833   // Check for global seek control
2834   if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2835   {
2836     if (!m_pPlayer->CanSeek()) return false;
2837     m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2838     return true;
2839   }
2840   if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2841   {
2842     CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2843     CGUIControlProfiler::Instance().Start();
2844     return true;
2845   }
2846   if (action.GetID() == ACTION_SHOW_PLAYLIST)
2847   {
2848     int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2849     if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2850       g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2851     else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2852       g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2853     return true;
2854   }
2855   return false;
2856 }
2857
2858 void CApplication::FrameMove(bool processEvents, bool processGUI)
2859 {
2860   MEASURE_FUNCTION;
2861
2862   CWinEvents::MessagePump();
2863
2864   if (processEvents)
2865   {
2866     // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2867     float frameTime = m_frameTime.GetElapsedSeconds();
2868     m_frameTime.StartZero();
2869     // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2870     if( frameTime > 0.5 ) frameTime = 0.5;
2871
2872     if (processGUI && m_renderGUI)
2873     {
2874       g_graphicsContext.Lock();
2875       // check if there are notifications to display
2876       CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2877       if (toast && toast->DoWork())
2878       {
2879         if (!toast->IsDialogRunning())
2880         {
2881           toast->Show();
2882         }
2883       }
2884       g_graphicsContext.Unlock();
2885     }
2886
2887 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2888     // Read the input from a remote
2889     g_RemoteControl.Update();
2890 #endif
2891
2892     // process input actions
2893     ProcessRemote(frameTime);
2894     ProcessGamepad(frameTime);
2895     ProcessEventServer(frameTime);
2896     ProcessPeripherals(frameTime);
2897     if (processGUI && m_renderGUI)
2898     {
2899       m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2900       m_seekHandler->Process();
2901     }
2902   }
2903   if (processGUI && m_renderGUI)
2904   {
2905     if (!m_bStop)
2906       g_windowManager.Process(CTimeUtils::GetFrameTime());
2907     g_windowManager.FrameMove();
2908   }
2909 }
2910
2911 bool CApplication::ProcessGamepad(float frameTime)
2912 {
2913 #ifdef HAS_SDL_JOYSTICK
2914   if (!m_AppFocused)
2915     return false;
2916
2917   int iWin = GetActiveWindowID();
2918   int bid = 0;
2919   g_Joystick.Update();
2920   if (g_Joystick.GetButton(bid))
2921   {
2922     // reset Idle Timer
2923     m_idleTimer.StartZero();
2924
2925     ResetScreenSaver();
2926     if (WakeUpScreenSaverAndDPMS())
2927     {
2928       g_Joystick.Reset(true);
2929       return true;
2930     }
2931
2932     int actionID;
2933     CStdString actionName;
2934     bool fullrange;
2935     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2936     {
2937       CAction action(actionID, 1.0f, 0.0f, actionName);
2938       g_Joystick.Reset();
2939       g_Mouse.SetActive(false);
2940       return ExecuteInputAction(action);
2941     }
2942     else
2943     {
2944       g_Joystick.Reset();
2945     }
2946   }
2947   if (g_Joystick.GetAxis(bid))
2948   {
2949     if (g_Joystick.GetAmount() < 0)
2950     {
2951       bid = -bid;
2952     }
2953
2954     int actionID;
2955     CStdString actionName;
2956     bool fullrange;
2957     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2958     {
2959       ResetScreenSaver();
2960       if (WakeUpScreenSaverAndDPMS())
2961       {
2962         return true;
2963       }
2964
2965       CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2966       g_Joystick.Reset();
2967       g_Mouse.SetActive(false);
2968       return ExecuteInputAction(action);
2969     }
2970     else
2971     {
2972       g_Joystick.ResetAxis(abs(bid));
2973     }
2974   }
2975   int position = 0;
2976   if (g_Joystick.GetHat(bid, position))
2977   {
2978     // reset Idle Timer
2979     m_idleTimer.StartZero();
2980
2981     ResetScreenSaver();
2982     if (WakeUpScreenSaverAndDPMS())
2983     {
2984       g_Joystick.Reset();
2985       return true;
2986     }
2987
2988     int actionID;
2989     CStdString actionName;
2990     bool fullrange;
2991
2992     bid = position<<16|bid;
2993
2994     if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2995     {
2996       CAction action(actionID, 1.0f, 0.0f, actionName);
2997       g_Joystick.Reset();
2998       g_Mouse.SetActive(false);
2999       return ExecuteInputAction(action);
3000     }
3001   }
3002 #endif
3003   return false;
3004 }
3005
3006 bool CApplication::ProcessRemote(float frameTime)
3007 {
3008 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3009   if (g_RemoteControl.GetButton())
3010   {
3011     CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3012     g_RemoteControl.Reset();
3013     return OnKey(key);
3014   }
3015 #endif
3016   return false;
3017 }
3018
3019 bool CApplication::ProcessPeripherals(float frameTime)
3020 {
3021   CKey key;
3022   if (g_peripherals.GetNextKeypress(frameTime, key))
3023     return OnKey(key);
3024   return false;
3025 }
3026
3027 bool CApplication::ProcessMouse()
3028 {
3029   MEASURE_FUNCTION;
3030
3031   if (!g_Mouse.IsActive() || !m_AppFocused)
3032     return false;
3033
3034   // Get the mouse command ID
3035   uint32_t mousecommand = g_Mouse.GetAction();
3036   if (mousecommand == ACTION_NOOP)
3037     return true;
3038
3039   // Reset the screensaver and idle timers
3040   m_idleTimer.StartZero();
3041   ResetScreenSaver();
3042   if (WakeUpScreenSaverAndDPMS())
3043     return true;
3044
3045   // Retrieve the corresponding action
3046   int iWin = GetActiveWindowID();
3047   CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3048   CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3049
3050   // Deactivate mouse if non-mouse action
3051   if (!mouseaction.IsMouse())
3052     g_Mouse.SetActive(false);
3053
3054   // Consume ACTION_NOOP.
3055   // Some views or dialogs gets closed after any ACTION and
3056   // a sensitive mouse might cause problems.
3057   if (mouseaction.GetID() == ACTION_NOOP)
3058     return false;
3059
3060   // If we couldn't find an action return false to indicate we have not
3061   // handled this mouse action
3062   if (!mouseaction.GetID())
3063   {
3064     CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3065     return false;
3066   }
3067
3068   // Log mouse actions except for move and noop
3069   if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3070     CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3071
3072   // The action might not be a mouse action. For example wheel moves might
3073   // be mapped to volume up/down in mouse.xml. In this case we do not want
3074   // the mouse position saved in the action.
3075   if (!mouseaction.IsMouse())
3076     return OnAction(mouseaction);
3077
3078   // This is a mouse action so we need to record the mouse position
3079   return OnAction(CAction(mouseaction.GetID(),
3080                           g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3081                           (float)g_Mouse.GetX(),
3082                           (float)g_Mouse.GetY(),
3083                           (float)g_Mouse.GetDX(),
3084                           (float)g_Mouse.GetDY(),
3085                           mouseaction.GetName()));
3086 }
3087
3088 bool CApplication::ProcessEventServer(float frameTime)
3089 {
3090 #ifdef HAS_EVENT_SERVER
3091   CEventServer* es = CEventServer::GetInstance();
3092   if (!es || !es->Running() || es->GetNumberOfClients()==0)
3093     return false;
3094
3095   // process any queued up actions
3096   if (es->ExecuteNextAction())
3097   {
3098     // reset idle timers
3099     m_idleTimer.StartZero();
3100     ResetScreenSaver();
3101     WakeUpScreenSaverAndDPMS();
3102   }
3103
3104   // now handle any buttons or axis
3105   std::string joystickName;
3106   bool isAxis = false;
3107   float fAmount = 0.0;
3108
3109   // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3110   // when the action exits XBMC
3111   es = CEventServer::GetInstance();
3112   if (!es || !es->Running() || es->GetNumberOfClients()==0)
3113     return false;
3114   unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3115
3116   if (wKeyID)
3117   {
3118     if (joystickName.length() > 0)
3119     {
3120       if (isAxis == true)
3121       {
3122         if (fabs(fAmount) >= 0.08)
3123           m_lastAxisMap[joystickName][wKeyID] = fAmount;
3124         else
3125           m_lastAxisMap[joystickName].erase(wKeyID);
3126       }
3127
3128       return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3129     }
3130     else
3131     {
3132       CKey key;
3133       if (wKeyID & ES_FLAG_UNICODE)
3134       {
3135         key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3136         return OnKey(key);
3137       }
3138
3139       if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3140         key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3141       else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3142         key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3143       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3144         key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3145       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3146         key = CKey(wKeyID, 0, 0,  fAmount, 0.0, 0.0, 0.0, frameTime);
3147       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3148         key = CKey(wKeyID, 0, 0, 0.0,  fAmount, 0.0, 0.0, frameTime);
3149       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3150         key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3151       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3152         key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3153       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3154         key = CKey(wKeyID, 0, 0, 0.0, 0.0,  fAmount, 0.0, frameTime);
3155       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3156         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0,  fAmount, frameTime);
3157       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3158         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3159       else
3160         key = CKey(wKeyID);
3161       key.SetFromService(true);
3162       return OnKey(key);
3163     }
3164   }
3165
3166   if (m_lastAxisMap.size() > 0)
3167   {
3168     // Process all the stored axis.
3169     for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3170     {
3171       for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3172         ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3173     }
3174   }
3175
3176   {
3177     CPoint pos;
3178     if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3179     {
3180       XBMC_Event newEvent;
3181       newEvent.type = XBMC_MOUSEMOTION;
3182       newEvent.motion.xrel = 0;
3183       newEvent.motion.yrel = 0;
3184       newEvent.motion.state = 0;
3185       newEvent.motion.which = 0x10;  // just a different value to distinguish between mouse and event client device.
3186       newEvent.motion.x = (uint16_t)pos.x;
3187       newEvent.motion.y = (uint16_t)pos.y;
3188       OnEvent(newEvent);  // had to call this to update g_Mouse position
3189       return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3190     }
3191   }
3192 #endif
3193   return false;
3194 }
3195
3196 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3197 {
3198 #if defined(HAS_EVENT_SERVER)
3199   m_idleTimer.StartZero();
3200
3201    // Make sure to reset screen saver, mouse.
3202    ResetScreenSaver();
3203    if (WakeUpScreenSaverAndDPMS())
3204      return true;
3205
3206 #ifdef HAS_SDL_JOYSTICK
3207    g_Joystick.Reset();
3208 #endif
3209    g_Mouse.SetActive(false);
3210
3211    int iWin = GetActiveWindowID();
3212    int actionID;
3213    CStdString actionName;
3214    bool fullRange = false;
3215
3216    // Translate using regular joystick translator.
3217    if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3218      return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3219    else
3220      CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3221 #endif
3222
3223    return false;
3224 }
3225
3226 bool CApplication::ExecuteInputAction(const CAction &action)
3227 {
3228   bool bResult = false;
3229
3230   // play sound before the action unless the button is held,
3231   // where we execute after the action as held actions aren't fired every time.
3232   if(action.GetHoldTime())
3233   {
3234     bResult = OnAction(action);
3235     if(bResult)
3236       g_audioManager.PlayActionSound(action);
3237   }
3238   else
3239   {
3240     g_audioManager.PlayActionSound(action);
3241     bResult = OnAction(action);
3242   }
3243   return bResult;
3244 }
3245
3246 int CApplication::GetActiveWindowID(void)
3247 {
3248   // Get the currently active window
3249   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3250
3251   // If there is a dialog active get the dialog id instead
3252   if (g_windowManager.HasModalDialog())
3253     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3254
3255   // If the window is FullScreenVideo check for special cases
3256   if (iWin == WINDOW_FULLSCREEN_VIDEO)
3257   {
3258     // check if we're in a DVD menu
3259     if(g_application.m_pPlayer->IsInMenu())
3260       iWin = WINDOW_VIDEO_MENU;
3261     // check for LiveTV and switch to it's virtual window
3262     else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3263       iWin = WINDOW_FULLSCREEN_LIVETV;
3264   }
3265
3266   // Return the window id
3267   return iWin;
3268 }
3269
3270 bool CApplication::Cleanup()
3271 {
3272   try
3273   {
3274     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3275     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3276     g_windowManager.Delete(WINDOW_MUSIC_FILES);
3277     g_windowManager.Delete(WINDOW_MUSIC_NAV);
3278     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3279     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3280     g_windowManager.Delete(WINDOW_VIDEO_FILES);
3281     g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3282     g_windowManager.Delete(WINDOW_VIDEO_NAV);
3283     g_windowManager.Delete(WINDOW_FILES);
3284     g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3285     g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3286     g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3287     g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3288     g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3289     g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3290     g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3291     g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3292     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3293     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3294     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3295     g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3296     g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3297     g_windowManager.Delete(WINDOW_DIALOG_OK);
3298     g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3299     g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3300     g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3301     g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3302     g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3303     g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3304     g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3305     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3306     g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3307     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3308     g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3309     g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3310     g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3311     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3312     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3313     g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3314     g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3315     g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3316     g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3317     g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3318     g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3319     g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3320     g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3321
3322     /* Delete PVR related windows and dialogs */
3323     g_windowManager.Delete(WINDOW_PVR);
3324     g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3325     g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3326     g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3327     g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3328     g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3329     g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3330     g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3331     g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3332     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3333     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3334     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3335     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3336     g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3337
3338     g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3339     g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3340     g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3341     g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3342     g_windowManager.Delete(WINDOW_VISUALISATION);
3343     g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3344     g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3345     g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3346     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);  // all the settings categories
3347     g_windowManager.Delete(WINDOW_TEST_PATTERN);
3348     g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3349     g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3350     g_windowManager.Delete(WINDOW_SCREENSAVER);
3351     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3352     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3353     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3354     g_windowManager.Delete(WINDOW_SLIDESHOW);
3355     g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3356     g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3357
3358     g_windowManager.Delete(WINDOW_HOME);
3359     g_windowManager.Delete(WINDOW_PROGRAMS);
3360     g_windowManager.Delete(WINDOW_PICTURES);
3361     g_windowManager.Delete(WINDOW_WEATHER);
3362
3363     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3364     g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3365     g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3366     g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3367     g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3368     g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3369     g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3370     g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3371     g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3372     g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3373
3374     g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3375     g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3376
3377     CAddonMgr::Get().DeInit();
3378
3379 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3380     CLog::Log(LOGNOTICE, "closing down remote control service");
3381     g_RemoteControl.Disconnect();
3382 #endif
3383
3384     CLog::Log(LOGNOTICE, "unload sections");
3385
3386 #ifdef HAS_PERFORMANCE_SAMPLE
3387     CLog::Log(LOGNOTICE, "performance statistics");
3388     m_perfStats.DumpStats();
3389 #endif
3390
3391     //  Shutdown as much as possible of the
3392     //  application, to reduce the leaks dumped
3393     //  to the vc output window before calling
3394     //  _CrtDumpMemoryLeaks(). Most of the leaks
3395     //  shown are no real leaks, as parts of the app
3396     //  are still allocated.
3397
3398     g_localizeStrings.Clear();
3399     g_LangCodeExpander.Clear();
3400     g_charsetConverter.clear();
3401     g_directoryCache.Clear();
3402     CButtonTranslator::GetInstance().Clear();
3403 #ifdef HAS_EVENT_SERVER
3404     CEventServer::RemoveInstance();
3405 #endif
3406     DllLoaderContainer::Clear();
3407     g_playlistPlayer.Clear();
3408     CSettings::Get().Uninitialize();
3409     g_advancedSettings.Clear();
3410
3411 #ifdef TARGET_POSIX
3412     CXHandle::DumpObjectTracker();
3413
3414 #ifdef HAS_DVD_DRIVE
3415     CLibcdio::ReleaseInstance();
3416 #endif
3417 #endif 
3418 #if defined(TARGET_ANDROID)
3419     // enable for all platforms once it's safe
3420     g_sectionLoader.UnloadAll();
3421 #endif
3422 #ifdef _CRTDBG_MAP_ALLOC
3423     _CrtDumpMemoryLeaks();
3424     while(1); // execution ends
3425 #endif
3426
3427     delete m_network;
3428     m_network = NULL;
3429
3430     return true;
3431   }
3432   catch (...)
3433   {
3434     CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3435     return false;
3436   }
3437 }
3438
3439 void CApplication::Stop(int exitCode)
3440 {
3441   try
3442   {
3443     CVariant vExitCode(exitCode);
3444     CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3445
3446     SaveFileState(true);
3447
3448     g_alarmClock.StopThread();
3449
3450     if( m_bSystemScreenSaverEnable )
3451       g_Windowing.EnableSystemScreenSaver(true);
3452
3453     CLog::Log(LOGNOTICE, "Storing total System Uptime");
3454     g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3455
3456     // Update the settings information (volume, uptime etc. need saving)
3457     if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3458     {
3459       CLog::Log(LOGNOTICE, "Saving settings");
3460       CSettings::Get().Save();
3461     }
3462     else
3463       CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3464
3465     m_bStop = true;
3466     m_AppFocused = false;
3467     m_ExitCode = exitCode;
3468     CLog::Log(LOGNOTICE, "stop all");
3469
3470     // cancel any jobs from the jobmanager
3471     CJobManager::GetInstance().CancelJobs();
3472
3473     // stop scanning before we kill the network and so on
3474     if (m_musicInfoScanner->IsScanning())
3475       m_musicInfoScanner->Stop();
3476
3477     if (m_videoInfoScanner->IsScanning())
3478       m_videoInfoScanner->Stop();
3479
3480     CApplicationMessenger::Get().Cleanup();
3481
3482     StopPVRManager();
3483     StopServices();
3484     //Sleep(5000);
3485
3486     CLog::Log(LOGNOTICE, "stop player");
3487     m_pPlayer->ClosePlayer();
3488
3489 #if HAS_FILESYTEM_DAAP
3490     CLog::Log(LOGNOTICE, "stop daap clients");
3491     g_DaapClient.Release();
3492 #endif
3493 #ifdef HAS_FILESYSTEM_SAP
3494     CLog::Log(LOGNOTICE, "stop sap announcement listener");
3495     g_sapsessions.StopThread();
3496 #endif
3497 #ifdef HAS_ZEROCONF
3498     if(CZeroconfBrowser::IsInstantiated())
3499     {
3500       CLog::Log(LOGNOTICE, "stop zeroconf browser");
3501       CZeroconfBrowser::GetInstance()->Stop();
3502       CZeroconfBrowser::ReleaseInstance();
3503     }
3504 #endif
3505
3506     CLog::Log(LOGNOTICE, "clean cached files!");
3507 #ifdef HAS_FILESYSTEM_RAR
3508     g_RarManager.ClearCache(true);
3509 #endif
3510
3511 #ifdef HAS_FILESYSTEM_SFTP
3512     CSFTPSessionManager::DisconnectAllSessions();
3513 #endif
3514
3515     CLog::Log(LOGNOTICE, "unload skin");
3516     UnloadSkin();
3517
3518 #if defined(TARGET_DARWIN_OSX)
3519     if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3520       XBMCHelper::GetInstance().Stop();
3521 #endif
3522
3523 #if defined(HAVE_LIBCRYSTALHD)
3524     CCrystalHD::RemoveInstance();
3525 #endif
3526
3527     g_mediaManager.Stop();
3528
3529     // Stop services before unloading Python
3530     CAddonMgr::Get().StopServices(false);
3531
3532     // stop all remaining scripts; must be done after skin has been unloaded,
3533     // not before some windows still need it when deinitializing during skin
3534     // unloading
3535     CScriptInvocationManager::Get().Uninitialize();
3536
3537     g_Windowing.DestroyRenderSystem();
3538     g_Windowing.DestroyWindow();
3539     g_Windowing.DestroyWindowSystem();
3540
3541     // shutdown the AudioEngine
3542     CAEFactory::Shutdown();
3543     CAEFactory::UnLoadEngine();
3544
3545     CLog::Log(LOGNOTICE, "stopped");
3546   }
3547   catch (...)
3548   {
3549     CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3550   }
3551
3552   // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3553   // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3554   Destroy();
3555
3556   //
3557   Sleep(200);
3558 }
3559
3560 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3561 {
3562   //If item is a plugin, expand out now and run ourselves again
3563   if (item.IsPlugin())
3564   {
3565     CFileItem item_new(item);
3566     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3567       return PlayMedia(item_new, iPlaylist);
3568     return false;
3569   }
3570   if (item.IsSmartPlayList())
3571   {
3572     CFileItemList items;
3573     CUtil::GetRecursiveListing(item.GetPath(), items, "");
3574     if (items.Size())
3575     {
3576       CSmartPlaylist smartpl;
3577       //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3578       smartpl.OpenAndReadName(item.GetPath());
3579       CPlayList playlist;
3580       playlist.Add(items);
3581       return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3582     }
3583   }
3584   else if (item.IsPlayList() || item.IsInternetStream())
3585   {
3586     CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3587
3588     //is or could be a playlist
3589     auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3590     bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3591
3592     if (dlgCache)
3593     {
3594        dlgCache->Close();
3595        if (dlgCache->IsCanceled())
3596           return true;
3597     }
3598
3599     if (gotPlayList)
3600     {
3601
3602       if (iPlaylist != PLAYLIST_NONE)
3603       {
3604         int track=0;
3605         if (item.HasProperty("playlist_starting_track"))
3606           track = (int)item.GetProperty("playlist_starting_track").asInteger();
3607         return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3608       }
3609       else
3610       {
3611         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());
3612         if(pPlayList->size())
3613           return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3614       }
3615     }
3616   }
3617
3618   //nothing special just play
3619   return PlayFile(item, false) == PLAYBACK_OK;
3620 }
3621
3622 // PlayStack()
3623 // For playing a multi-file video.  Particularly inefficient
3624 // on startup, as we are required to calculate the length
3625 // of each video, so we open + close each one in turn.
3626 // A faster calculation of video time would improve this
3627 // substantially.
3628 // return value: same with PlayFile()
3629 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3630 {
3631   if (!item.IsStack())
3632     return PLAYBACK_FAIL;
3633
3634   CVideoDatabase dbs;
3635
3636   // case 1: stacked ISOs
3637   if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3638   {
3639     CStackDirectory dir;
3640     CFileItemList movieList;
3641     dir.GetDirectory(item.GetPath(), movieList);
3642
3643     // first assume values passed to the stack
3644     int selectedFile = item.m_lStartPartNumber;
3645     int startoffset = item.m_lStartOffset;
3646
3647     // check if we instructed the stack to resume from default
3648     if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3649     {
3650       if (dbs.Open())
3651       {
3652         CBookmark bookmark;
3653         if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3654         {
3655           startoffset = (int)(bookmark.timeInSeconds*75);
3656           selectedFile = bookmark.partNumber;
3657         }
3658         dbs.Close();
3659       }
3660       else
3661         CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3662     }
3663
3664     // make sure that the selected part is within the boundaries
3665     if (selectedFile <= 0)
3666     {
3667       CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3668       selectedFile = 1;
3669     }
3670     else if (selectedFile > movieList.Size())
3671     {
3672       CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3673       selectedFile = movieList.Size();
3674     }
3675
3676     // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3677     movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3678     movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3679     *m_stackFileItemToUpdate = item;
3680     return PlayFile(*(movieList[selectedFile - 1]));
3681   }
3682   // case 2: all other stacks
3683   else
3684   {
3685     // see if we have the info in the database
3686     // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3687     //       then these times will be wrong.
3688     //       Also, this is really just a hack for the slow load up times we have
3689     //       A much better solution is a fast reader of FPS and fileLength
3690     //       that we can use on a file to get it's time.
3691     vector<int> times;
3692     bool haveTimes(false);
3693     CVideoDatabase dbs;
3694     if (dbs.Open())
3695     {
3696       dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3697       haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3698       dbs.Close();
3699     }
3700
3701
3702     // calculate the total time of the stack
3703     CStackDirectory dir;
3704     dir.GetDirectory(item.GetPath(), *m_currentStack);
3705     long totalTime = 0;
3706     for (int i = 0; i < m_currentStack->Size(); i++)
3707     {
3708       if (haveTimes)
3709         (*m_currentStack)[i]->m_lEndOffset = times[i];
3710       else
3711       {
3712         int duration;
3713         if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3714         {
3715           m_currentStack->Clear();
3716           return PLAYBACK_FAIL;
3717         }
3718         totalTime += duration / 1000;
3719         (*m_currentStack)[i]->m_lEndOffset = totalTime;
3720         times.push_back(totalTime);
3721       }
3722     }
3723
3724     double seconds = item.m_lStartOffset / 75.0;
3725
3726     if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3727     {  // have our times now, so update the dB
3728       if (dbs.Open())
3729       {
3730         if( !haveTimes )
3731           dbs.SetStackTimes(item.GetPath(), times);
3732
3733         if( item.m_lStartOffset == STARTOFFSET_RESUME )
3734         {
3735           // can only resume seek here, not dvdstate
3736           CBookmark bookmark;
3737           if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3738             seconds = bookmark.timeInSeconds;
3739           else
3740             seconds = 0.0f;
3741         }
3742         dbs.Close();
3743       }
3744     }
3745
3746     *m_itemCurrentFile = item;
3747     m_currentStackPosition = 0;
3748     m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3749
3750     if (seconds > 0)
3751     {
3752       // work out where to seek to
3753       for (int i = 0; i < m_currentStack->Size(); i++)
3754       {
3755         if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3756         {
3757           CFileItem item(*(*m_currentStack)[i]);
3758           long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3759           item.m_lStartOffset = (long)(seconds - start) * 75;
3760           m_currentStackPosition = i;
3761           return PlayFile(item, true);
3762         }
3763       }
3764     }
3765
3766     return PlayFile(*(*m_currentStack)[0], true);
3767   }
3768   return PLAYBACK_FAIL;
3769 }
3770
3771 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3772 {
3773   // Ensure the MIME type has been retrieved for http:// and shout:// streams
3774   if (item.GetMimeType().empty())
3775     const_cast<CFileItem&>(item).FillInMimeType();
3776
3777   if (!bRestart)
3778   {
3779     SaveCurrentFileSettings();
3780
3781     OutputDebugString("new file set audiostream:0\n");
3782     // Switch to default options
3783     CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3784     // see if we have saved options in the database
3785
3786     m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3787     m_pPlayer->m_iPlaySpeed = 1;     // Reset both CApp's & Player's speed else we'll get confused
3788
3789     *m_itemCurrentFile = item;
3790     m_nextPlaylistItem = -1;
3791     m_currentStackPosition = 0;
3792     m_currentStack->Clear();
3793
3794     if (item.IsVideo())
3795       CUtil::ClearSubtitles();
3796   }
3797
3798   if (item.IsDiscStub())
3799   {
3800 #ifdef HAS_DVD_DRIVE
3801     // Display the Play Eject dialog if there is any optical disc drive
3802     if (g_mediaManager.HasOpticalDrive())
3803     {
3804       if (CGUIDialogPlayEject::ShowAndGetInput(item))
3805         // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3806         // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3807         return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3808     }
3809     else
3810 #endif
3811       CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3812
3813     return PLAYBACK_OK;
3814   }
3815
3816   if (item.IsPlayList())
3817     return PLAYBACK_FAIL;
3818
3819   if (item.IsPlugin())
3820   { // we modify the item so that it becomes a real URL
3821     CFileItem item_new(item);
3822     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3823       return PlayFile(item_new, false);
3824     return PLAYBACK_FAIL;
3825   }
3826
3827 #ifdef HAS_UPNP
3828   if (URIUtils::IsUPnP(item.GetPath()))
3829   {
3830     CFileItem item_new(item);
3831     if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3832       return PlayFile(item_new, false);
3833     return PLAYBACK_FAIL;
3834   }
3835 #endif
3836
3837   // if we have a stacked set of files, we need to setup our stack routines for
3838   // "seamless" seeking and total time of the movie etc.
3839   // will recall with restart set to true
3840   if (item.IsStack())
3841     return PlayStack(item, bRestart);
3842
3843   //Is TuxBox, this should probably be moved to CTuxBoxFile
3844   if(item.IsTuxBox())
3845   {
3846     CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3847
3848     if(g_tuxboxService.IsRunning())
3849       g_tuxboxService.Stop();
3850
3851     PlayBackRet ret = PLAYBACK_FAIL;
3852     CFileItem item_new;
3853     if(g_tuxbox.CreateNewItem(item, item_new))
3854     {
3855
3856       // Make sure it doesn't have a player
3857       // so we actually select one normally
3858       m_pPlayer->ResetPlayer();
3859
3860       // keep the tuxbox:// url as playing url
3861       // and give the new url to the player
3862       ret = PlayFile(item_new, true);
3863       if(ret == PLAYBACK_OK)
3864       {
3865         if(!g_tuxboxService.IsRunning())
3866           g_tuxboxService.Start();
3867       }
3868     }
3869     return ret;
3870   }
3871
3872   CPlayerOptions options;
3873
3874   if( item.HasProperty("StartPercent") )
3875   {
3876     double fallback = 0.0f;
3877     if(item.GetProperty("StartPercent").isString())
3878       fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3879     options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3880   }
3881
3882   PLAYERCOREID eNewCore = EPC_NONE;
3883   if( bRestart )
3884   {
3885     // have to be set here due to playstack using this for starting the file
3886     options.starttime = item.m_lStartOffset / 75.0;
3887     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3888       m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3889
3890     if( m_eForcedNextPlayer != EPC_NONE )
3891       eNewCore = m_eForcedNextPlayer;
3892     else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3893       eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3894     else
3895       eNewCore = m_pPlayer->GetCurrentPlayer();
3896   }
3897   else
3898   {
3899     options.starttime = item.m_lStartOffset / 75.0;
3900
3901     if (item.IsVideo())
3902     {
3903       // open the d/b and retrieve the bookmarks for the current movie
3904       CVideoDatabase dbs;
3905       dbs.Open();
3906       dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3907
3908       if( item.m_lStartOffset == STARTOFFSET_RESUME )
3909       {
3910         options.starttime = 0.0f;
3911         CBookmark bookmark;
3912         CStdString path = item.GetPath();
3913         if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3914           path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3915         else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3916           path = item.GetProperty("original_listitem_url").asString();
3917         if(dbs.GetResumeBookMark(path, bookmark))
3918         {
3919           options.starttime = bookmark.timeInSeconds;
3920           options.state = bookmark.playerState;
3921         }
3922         /*
3923          override with information from the actual item if available.  We do this as the VFS (eg plugins)
3924          may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3925          should the playerState be required, it is fetched from the database.
3926          See the note in CGUIWindowVideoBase::ShowResumeMenu.
3927          */
3928         if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3929           options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3930       }
3931       else if (item.HasVideoInfoTag())
3932       {
3933         const CVideoInfoTag *tag = item.GetVideoInfoTag();
3934
3935         if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3936         {
3937           CBookmark bookmark;
3938           dbs.GetBookMarkForEpisode(*tag, bookmark);
3939           options.starttime = bookmark.timeInSeconds;
3940           options.state = bookmark.playerState;
3941         }
3942       }
3943
3944       dbs.Close();
3945     }
3946
3947     if (m_eForcedNextPlayer != EPC_NONE)
3948       eNewCore = m_eForcedNextPlayer;
3949     else
3950       eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3951   }
3952
3953   // this really aught to be inside !bRestart, but since PlayStack
3954   // uses that to init playback, we have to keep it outside
3955   int playlist = g_playlistPlayer.GetCurrentPlaylist();
3956   if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3957   { // playing from a playlist by the looks
3958     // don't switch to fullscreen if we are not playing the first item...
3959     options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3960   }
3961   else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3962   {
3963     // TODO - this will fail if user seeks back to first file in stack
3964     if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3965       options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3966     else
3967       options.fullscreen = false;
3968     // reset this so we don't think we are resuming on seek
3969     m_itemCurrentFile->m_lStartOffset = 0;
3970   }
3971   else
3972     options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3973
3974   // reset VideoStartWindowed as it's a temp setting
3975   CMediaSettings::Get().SetVideoStartWindowed(false);
3976
3977 #ifdef HAS_KARAOKE
3978   //We have to stop parsing a cdg before mplayer is deallocated
3979   // WHY do we have to do this????
3980   if (m_pKaraokeMgr)
3981     m_pKaraokeMgr->Stop();
3982 #endif
3983
3984   {
3985     CSingleLock lock(m_playStateMutex);
3986     // tell system we are starting a file
3987     m_bPlaybackStarting = true;
3988     
3989     // for playing a new item, previous playing item's callback may already
3990     // pushed some delay message into the threadmessage list, they are not
3991     // expected be processed after or during the new item playback starting.
3992     // so we clean up previous playing item's playback callback delay messages here.
3993     int previousMsgsIgnoredByNewPlaying[] = {
3994       GUI_MSG_PLAYBACK_STARTED,
3995       GUI_MSG_PLAYBACK_ENDED,
3996       GUI_MSG_PLAYBACK_STOPPED,
3997       GUI_MSG_PLAYLIST_CHANGED,
3998       GUI_MSG_PLAYLISTPLAYER_STOPPED,
3999       GUI_MSG_PLAYLISTPLAYER_STARTED,
4000       GUI_MSG_PLAYLISTPLAYER_CHANGED,
4001       GUI_MSG_QUEUE_NEXT_ITEM,
4002       0
4003     };
4004     int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4005     if (dMsgCount > 0)
4006       CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4007   }
4008
4009   // We should restart the player, unless the previous and next tracks are using
4010   // one of the players that allows gapless playback (paplayer, dvdplayer)
4011   m_pPlayer->ClosePlayerGapless(eNewCore);
4012
4013   // now reset play state to starting, since we already stopped the previous playing item if there is.
4014   // and from now there should be no playback callback from previous playing item be called.
4015   m_ePlayState = PLAY_STATE_STARTING;
4016
4017   m_pPlayer->CreatePlayer(eNewCore, *this);
4018
4019   PlayBackRet iResult;
4020   if (m_pPlayer->HasPlayer())
4021   {
4022     /* When playing video pause any low priority jobs, they will be unpaused  when playback stops.
4023      * This should speed up player startup for files on internet filesystems (eg. webdav) and
4024      * increase performance on low powered systems (Atom/ARM).
4025      */
4026     if (item.IsVideo())
4027     {
4028       CJobManager::GetInstance().PauseJobs();
4029     }
4030
4031     // don't hold graphicscontext here since player
4032     // may wait on another thread, that requires gfx
4033     CSingleExit ex(g_graphicsContext);
4034
4035     iResult = m_pPlayer->OpenFile(item, options);
4036   }
4037   else
4038   {
4039     CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4040     iResult = PLAYBACK_FAIL;
4041   }
4042
4043   if(iResult == PLAYBACK_OK)
4044   {
4045     if (m_pPlayer->GetPlaySpeed() != 1)
4046     {
4047       int iSpeed = m_pPlayer->GetPlaySpeed();
4048       m_pPlayer->m_iPlaySpeed = 1;
4049       m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4050     }
4051
4052     // if player has volume control, set it.
4053     if (m_pPlayer->ControlsVolume())
4054     {
4055        m_pPlayer->SetVolume(m_volumeLevel);
4056        m_pPlayer->SetMute(m_muted);
4057     }
4058
4059     if( m_pPlayer->IsPlayingAudio() )
4060     {
4061       if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4062         g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4063     }
4064
4065 #ifdef HAS_VIDEO_PLAYBACK
4066     else if( m_pPlayer->IsPlayingVideo() )
4067     {
4068       if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4069         g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4070
4071       // if player didn't manange to switch to fullscreen by itself do it here
4072       if( options.fullscreen && g_renderManager.IsStarted()
4073        && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4074        SwitchToFullScreen();
4075     }
4076 #endif
4077     else
4078     {
4079       if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4080       ||  g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4081         g_windowManager.PreviousWindow();
4082
4083     }
4084
4085 #if !defined(TARGET_POSIX)
4086     g_audioManager.Enable(false);
4087 #endif
4088
4089     if (item.HasPVRChannelInfoTag())
4090       g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4091   }
4092
4093   CSingleLock lock(m_playStateMutex);
4094   m_bPlaybackStarting = false;
4095
4096   if (iResult == PLAYBACK_OK)
4097   {
4098     // play state: none, starting; playing; stopped; ended.
4099     // last 3 states are set by playback callback, they are all ignored during starting,
4100     // but we recorded the state, here we can make up the callback for the state.
4101     CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4102     switch (m_ePlayState)
4103     {
4104       case PLAY_STATE_PLAYING:
4105         OnPlayBackStarted();
4106         break;
4107       // FIXME: it seems no meaning to callback started here if there was an started callback
4108       //        before this stopped/ended callback we recorded. if we callback started here
4109       //        first, it will delay send OnPlay announce, but then we callback stopped/ended
4110       //        which will send OnStop announce at once, so currently, just call stopped/ended.
4111       case PLAY_STATE_ENDED:
4112         OnPlayBackEnded();
4113         break;
4114       case PLAY_STATE_STOPPED:
4115         OnPlayBackStopped();
4116         break;
4117       case PLAY_STATE_STARTING:
4118         // neither started nor stopped/ended callback be called, that means the item still
4119         // not started, we need not make up any callback, just leave this and
4120         // let the player callback do its work.
4121         break;
4122       default:
4123         break;
4124     }
4125   }
4126   else if (iResult == PLAYBACK_FAIL)
4127   {
4128     // we send this if it isn't playlistplayer that is doing this
4129     int next = g_playlistPlayer.GetNextSong();
4130     int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4131     if(next < 0
4132     || next >= size)
4133       OnPlayBackStopped();
4134     m_ePlayState = PLAY_STATE_NONE;
4135   }
4136
4137   return iResult;
4138 }
4139
4140 void CApplication::OnPlayBackEnded()
4141 {
4142   CSingleLock lock(m_playStateMutex);
4143   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4144   m_ePlayState = PLAY_STATE_ENDED;
4145   if(m_bPlaybackStarting)
4146     return;
4147
4148   // informs python script currently running playback has ended
4149   // (does nothing if python is not loaded)
4150 #ifdef HAS_PYTHON
4151   g_pythonParser.OnPlayBackEnded();
4152 #endif
4153
4154   CVariant data(CVariant::VariantTypeObject);
4155   data["end"] = true;
4156   CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4157
4158   CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4159   g_windowManager.SendThreadMessage(msg);
4160 }
4161
4162 void CApplication::OnPlayBackStarted()
4163 {
4164   CSingleLock lock(m_playStateMutex);
4165   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4166   m_ePlayState = PLAY_STATE_PLAYING;
4167   if(m_bPlaybackStarting)
4168     return;
4169
4170 #ifdef HAS_PYTHON
4171   // informs python script currently running playback has started
4172   // (does nothing if python is not loaded)
4173   g_pythonParser.OnPlayBackStarted();
4174 #endif
4175
4176   CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4177   g_windowManager.SendThreadMessage(msg);
4178 }
4179
4180 void CApplication::OnQueueNextItem()
4181 {
4182   CSingleLock lock(m_playStateMutex);
4183   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4184   if(m_bPlaybackStarting)
4185     return;
4186   // informs python script currently running that we are requesting the next track
4187   // (does nothing if python is not loaded)
4188 #ifdef HAS_PYTHON
4189   g_pythonParser.OnQueueNextItem(); // currently unimplemented
4190 #endif
4191
4192   CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4193   g_windowManager.SendThreadMessage(msg);
4194 }
4195
4196 void CApplication::OnPlayBackStopped()
4197 {
4198   CSingleLock lock(m_playStateMutex);
4199   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4200   m_ePlayState = PLAY_STATE_STOPPED;
4201   if(m_bPlaybackStarting)
4202     return;
4203
4204   // informs python script currently running playback has ended
4205   // (does nothing if python is not loaded)
4206 #ifdef HAS_PYTHON
4207   g_pythonParser.OnPlayBackStopped();
4208 #endif
4209
4210   CVariant data(CVariant::VariantTypeObject);
4211   data["end"] = false;
4212   CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4213
4214   CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4215   g_windowManager.SendThreadMessage(msg);
4216 }
4217
4218 void CApplication::OnPlayBackPaused()
4219 {
4220 #ifdef HAS_PYTHON
4221   g_pythonParser.OnPlayBackPaused();
4222 #endif
4223
4224   CVariant param;
4225   param["player"]["speed"] = 0;
4226   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4227   CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4228 }
4229
4230 void CApplication::OnPlayBackResumed()
4231 {
4232 #ifdef HAS_PYTHON
4233   g_pythonParser.OnPlayBackResumed();
4234 #endif
4235
4236   CVariant param;
4237   param["player"]["speed"] = 1;
4238   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4239   CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4240 }
4241
4242 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4243 {
4244 #ifdef HAS_PYTHON
4245   g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4246 #endif
4247
4248   CVariant param;
4249   param["player"]["speed"] = iSpeed;
4250   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4251   CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4252 }
4253
4254 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4255 {
4256 #ifdef HAS_PYTHON
4257   g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4258 #endif
4259
4260   CVariant param;
4261   CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4262   CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4263   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4264   param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4265   CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4266   g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4267 }
4268
4269 void CApplication::OnPlayBackSeekChapter(int iChapter)
4270 {
4271 #ifdef HAS_PYTHON
4272   g_pythonParser.OnPlayBackSeekChapter(iChapter);
4273 #endif
4274 }
4275
4276 bool CApplication::IsPlayingFullScreenVideo() const
4277 {
4278   return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4279 }
4280
4281 bool CApplication::IsFullScreen()
4282 {
4283   return IsPlayingFullScreenVideo() ||
4284         (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4285          g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4286 }
4287
4288 void CApplication::SaveFileState(bool bForeground /* = false */)
4289 {
4290   if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4291     return;
4292
4293   if (bForeground)
4294   {
4295     CSaveFileStateJob job(*m_progressTrackingItem,
4296     *m_stackFileItemToUpdate,
4297     m_progressTrackingVideoResumeBookmark,
4298     m_progressTrackingPlayCountUpdate);
4299
4300     // Run job in the foreground to make sure it finishes
4301     job.DoWork();
4302   }
4303   else
4304   {
4305     CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4306         *m_stackFileItemToUpdate,
4307         m_progressTrackingVideoResumeBookmark,
4308         m_progressTrackingPlayCountUpdate);
4309     CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4310   }
4311 }
4312
4313 void CApplication::UpdateFileState()
4314 {
4315   // Did the file change?
4316   if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4317   {
4318     SaveFileState();
4319
4320     // Reset tracking item
4321     m_progressTrackingItem->Reset();
4322   }
4323   else
4324   {
4325     if (m_pPlayer->IsPlaying())
4326     {
4327       if (m_progressTrackingItem->GetPath() == "")
4328       {
4329         // Init some stuff
4330         *m_progressTrackingItem = CurrentFileItem();
4331         m_progressTrackingPlayCountUpdate = false;
4332       }
4333
4334       if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4335           GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4336           (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4337           GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4338       {
4339         m_progressTrackingPlayCountUpdate = true;
4340       }
4341
4342       // Check whether we're *really* playing video else we may race when getting eg. stream details
4343       if (m_pPlayer->IsPlayingVideo())
4344       {
4345         /* Always update streamdetails, except for DVDs where we only update
4346            streamdetails if title length > 15m (Should yield more correct info) */
4347         if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4348         {
4349           CStreamDetails details;
4350           // Update with stream details from player, if any
4351           if (m_pPlayer->GetStreamDetails(details))
4352             m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4353
4354           if (m_progressTrackingItem->IsStack())
4355             m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4356         }
4357
4358         // Update bookmark for save
4359         m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4360         m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4361         m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4362
4363         if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4364             GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4365         {
4366           // Delete the bookmark
4367           m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4368         }
4369         else
4370         if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4371         {
4372           // Update the bookmark
4373           m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4374           m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4375         }
4376         else
4377         {
4378           // Do nothing
4379           m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4380         }
4381       }
4382     }
4383   }
4384 }
4385
4386 void CApplication::StopPlaying()
4387 {
4388   int iWin = g_windowManager.GetActiveWindow();
4389   if ( m_pPlayer->IsPlaying() )
4390   {
4391 #ifdef HAS_KARAOKE
4392     if( m_pKaraokeMgr )
4393       m_pKaraokeMgr->Stop();
4394 #endif
4395
4396     if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4397       g_PVRManager.SaveCurrentChannelSettings();
4398
4399     m_pPlayer->CloseFile();
4400
4401     // turn off visualisation window when stopping
4402     if ((iWin == WINDOW_VISUALISATION
4403     ||  iWin == WINDOW_FULLSCREEN_VIDEO)
4404     && !m_bStop)
4405       g_windowManager.PreviousWindow();
4406
4407     g_partyModeManager.Disable();
4408   }
4409 }
4410
4411 void CApplication::ResetSystemIdleTimer()
4412 {
4413   // reset system idle timer
4414   m_idleTimer.StartZero();
4415 }
4416
4417 void CApplication::ResetScreenSaver()
4418 {
4419   // reset our timers
4420   m_shutdownTimer.StartZero();
4421
4422   // screen saver timer is reset only if we're not already in screensaver or
4423   // DPMS mode
4424   if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4425     ResetScreenSaverTimer();
4426 }
4427
4428 void CApplication::ResetScreenSaverTimer()
4429 {
4430   m_screenSaverTimer.StartZero();
4431 }
4432
4433 void CApplication::StopScreenSaverTimer()
4434 {
4435   m_screenSaverTimer.Stop();
4436 }
4437
4438 bool CApplication::ToggleDPMS(bool manual)
4439 {
4440   if (manual || (m_dpmsIsManual == manual))
4441   {
4442     if (m_dpmsIsActive)
4443     {
4444       m_dpmsIsActive = false;
4445       m_dpmsIsManual = false;
4446       return m_dpms->DisablePowerSaving();
4447     }
4448     else
4449     {
4450       if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4451       {
4452         m_dpmsIsActive = true;
4453         m_dpmsIsManual = manual;
4454         return true;
4455       }
4456     }
4457   }
4458   return false;
4459 }
4460
4461 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4462 {
4463   bool result;
4464
4465   // First reset DPMS, if active
4466   if (m_dpmsIsActive)
4467   {
4468     if (m_dpmsIsManual)
4469       return false;
4470     // TODO: if screensaver lock is specified but screensaver is not active
4471     // (DPMS came first), activate screensaver now.
4472     ToggleDPMS(false);
4473     ResetScreenSaverTimer();
4474     result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4475   }
4476   else
4477     result = WakeUpScreenSaver(bPowerOffKeyPressed);
4478
4479   if(result)
4480   {
4481     // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4482     CVariant data(bPowerOffKeyPressed);
4483     CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4484   }
4485
4486   return result;
4487 }
4488
4489 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4490 {
4491   if (m_iScreenSaveLock == 2)
4492     return false;
4493
4494   // if Screen saver is active
4495   if (m_bScreenSave && m_screenSaver)
4496   {
4497     if (m_iScreenSaveLock == 0)
4498       if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4499           (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4500           CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4501           m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4502       {
4503         m_iScreenSaveLock = 2;
4504         CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4505
4506         CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4507         if (pWindow)
4508           pWindow->OnMessage(msg);
4509       }
4510     if (m_iScreenSaveLock == -1)
4511     {
4512       m_iScreenSaveLock = 0;
4513       return true;
4514     }
4515
4516     // disable screensaver
4517     m_bScreenSave = false;
4518     m_iScreenSaveLock = 0;
4519     ResetScreenSaverTimer();
4520
4521     if (m_screenSaver->ID() == "visualization")
4522     {
4523       // we can just continue as usual from vis mode
4524       return false;
4525     }
4526     else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4527       return true;
4528     else if (!m_screenSaver->ID().empty())
4529     { // we're in screensaver window
4530       if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4531         g_windowManager.PreviousWindow();  // show the previous window
4532       if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4533         CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4534     }
4535     return true;
4536   }
4537   else
4538     return false;
4539 }
4540
4541 void CApplication::CheckScreenSaverAndDPMS()
4542 {
4543   if (m_bInBackground)
4544     return;
4545   if (!m_dpmsIsActive)
4546     g_Windowing.ResetOSScreensaver();
4547
4548   bool maybeScreensaver =
4549       !m_dpmsIsActive && !m_bScreenSave
4550       && !CSettings::Get().GetString("screensaver.mode").empty();
4551   bool maybeDPMS =
4552       !m_dpmsIsActive && m_dpms->IsSupported()
4553       && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4554
4555   // Has the screen saver window become active?
4556   if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4557   {
4558     m_bScreenSave = true;
4559     maybeScreensaver = false;
4560   }
4561
4562   if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4563   {
4564     WakeUpScreenSaverAndDPMS();
4565     return;
4566   }
4567
4568   if (!maybeScreensaver && !maybeDPMS) return;  // Nothing to do.
4569
4570   // See if we need to reset timer.
4571   // * Are we playing a video and it is not paused?
4572   if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4573       // * Are we playing some music in fullscreen vis?
4574       || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4575           && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4576   {
4577     ResetScreenSaverTimer();
4578     return;
4579   }
4580
4581   float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4582
4583   // DPMS has priority (it makes the screensaver not needed)
4584   if (maybeDPMS
4585       && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4586   {
4587     ToggleDPMS(false);
4588     WakeUpScreenSaver();
4589   }
4590   else if (maybeScreensaver
4591            && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4592   {
4593     ActivateScreenSaver();
4594   }
4595 }
4596
4597 // activate the screensaver.
4598 // if forceType is true, we ignore the various conditions that can alter
4599 // the type of screensaver displayed
4600 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4601 {
4602   if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4603   { // just activate the visualisation if user toggled the usemusicvisinstead option
4604     g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4605     return;
4606   }
4607
4608   m_bScreenSave = true;
4609
4610   // Get Screensaver Mode
4611   m_screenSaver.reset();
4612   if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4613     m_screenSaver.reset(new CScreenSaver(""));
4614
4615   CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4616
4617   // disable screensaver lock from the login screen
4618   m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4619   if (!forceType)
4620   {
4621     // set to Dim in the case of a dialog on screen or playing video
4622     if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4623     {
4624       if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4625         m_screenSaver.reset(new CScreenSaver(""));
4626     }
4627   }
4628   if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4629     return;
4630   else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4631     return;
4632   else if (!m_screenSaver->ID().empty())
4633     g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4634 }
4635
4636 void CApplication::SetInBackground(bool background)
4637 {
4638   if (!background)
4639   {
4640     ResetScreenSaverTimer();
4641   }
4642   m_bInBackground = background;
4643 }
4644
4645 void CApplication::CheckShutdown()
4646 {
4647   // first check if we should reset the timer
4648   bool resetTimer = m_bInhibitIdleShutdown;
4649
4650   if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4651     resetTimer = true;
4652
4653   if (m_musicInfoScanner->IsScanning())
4654     resetTimer = true;
4655
4656   if (m_videoInfoScanner->IsScanning())
4657     resetTimer = true;
4658
4659   if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4660     resetTimer = true;
4661
4662   if (CSettings::Get().GetBool("pvrmanager.enabled") &&  !g_PVRManager.IsIdle())
4663     resetTimer = true;
4664
4665   if (resetTimer)
4666   {
4667     m_shutdownTimer.StartZero();
4668     return;
4669   }
4670
4671   if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4672   {
4673     // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4674     m_shutdownTimer.Stop();
4675
4676     // Sleep the box
4677     CApplicationMessenger::Get().Shutdown();
4678   }
4679 }
4680
4681 void CApplication::InhibitIdleShutdown(bool inhibit)
4682 {
4683   m_bInhibitIdleShutdown = inhibit;
4684 }
4685
4686 bool CApplication::IsIdleShutdownInhibited() const
4687 {
4688   return m_bInhibitIdleShutdown;
4689 }
4690
4691 bool CApplication::OnMessage(CGUIMessage& message)
4692 {
4693   switch ( message.GetMessage() )
4694   {
4695   case GUI_MSG_NOTIFY_ALL:
4696     {
4697       if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4698       {
4699         // Update general playlist: Remove DVD playlist items
4700         int nRemoved = g_playlistPlayer.RemoveDVDItems();
4701         if ( nRemoved > 0 )
4702         {
4703           CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4704           g_windowManager.SendMessage( msg );
4705         }
4706         // stop the file if it's on dvd (will set the resume point etc)
4707         if (m_itemCurrentFile->IsOnDVD())
4708           StopPlaying();
4709       }
4710     }
4711     break;
4712
4713   case GUI_MSG_PLAYBACK_STARTED:
4714     {
4715 #ifdef TARGET_DARWIN
4716       DarwinSetScheduling(message.GetMessage());
4717 #endif
4718       // reset the seek handler
4719       m_seekHandler->Reset();
4720       CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4721
4722       // Update our infoManager with the new details etc.
4723       if (m_nextPlaylistItem >= 0)
4724       { 
4725         // playing an item which is not in the list - player might be stopped already
4726         // so do nothing
4727         if (playList.size() <= m_nextPlaylistItem)
4728           return true;
4729
4730         // we've started a previously queued item
4731         CFileItemPtr item = playList[m_nextPlaylistItem];
4732         // update the playlist manager
4733         int currentSong = g_playlistPlayer.GetCurrentSong();
4734         int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4735         CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4736         g_windowManager.SendThreadMessage(msg);
4737         g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4738         *m_itemCurrentFile = *item;
4739       }
4740       g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4741       g_partyModeManager.OnSongChange(true);
4742
4743       CVariant param;
4744       param["player"]["speed"] = 1;
4745       param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4746       CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4747
4748       if (m_pPlayer->IsPlayingAudio())
4749       {
4750         // Start our cdg parser as appropriate
4751 #ifdef HAS_KARAOKE
4752         if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4753         {
4754           m_pKaraokeMgr->Stop();
4755           if (m_itemCurrentFile->IsMusicDb())
4756           {
4757             if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4758             {
4759               IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4760               tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4761               delete tagloader;
4762             }
4763             m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4764           }
4765           else
4766             m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4767         }
4768 #endif
4769       }
4770
4771       return true;
4772     }
4773     break;
4774
4775   case GUI_MSG_QUEUE_NEXT_ITEM:
4776     {
4777       // Check to see if our playlist player has a new item for us,
4778       // and if so, we check whether our current player wants the file
4779       int iNext = g_playlistPlayer.GetNextSong();
4780       CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4781       if (iNext < 0 || iNext >= playlist.size())
4782       {
4783         m_pPlayer->OnNothingToQueueNotify();
4784         return true; // nothing to do
4785       }
4786
4787       // ok, grab the next song
4788       CFileItem file(*playlist[iNext]);
4789       // handle plugin://
4790       CURL url(file.GetPath());
4791       if (url.GetProtocol() == "plugin")
4792         XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4793
4794 #ifdef HAS_UPNP
4795       if (URIUtils::IsUPnP(file.GetPath()))
4796       {
4797         if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4798           return true;
4799       }
4800 #endif
4801
4802       // ok - send the file to the player, if it accepts it
4803       if (m_pPlayer->QueueNextFile(file))
4804       {
4805         // player accepted the next file
4806         m_nextPlaylistItem = iNext;
4807       }
4808       else
4809       {
4810         /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4811             queue the next (if it wants to) and it doesn't keep looping on this song */
4812         g_playlistPlayer.SetCurrentSong(iNext);
4813       }
4814
4815       return true;
4816     }
4817     break;
4818
4819   case GUI_MSG_PLAYBACK_STOPPED:
4820   case GUI_MSG_PLAYBACK_ENDED:
4821   case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4822     {
4823 #ifdef HAS_KARAOKE
4824       if (m_pKaraokeMgr )
4825         m_pKaraokeMgr->Stop();
4826 #endif
4827 #ifdef TARGET_DARWIN
4828       DarwinSetScheduling(message.GetMessage());
4829 #endif
4830       // first check if we still have items in the stack to play
4831       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4832       {
4833         if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4834         { // just play the next item in the stack
4835           PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4836           return true;
4837         }
4838       }
4839
4840       // In case playback ended due to user eg. skipping over the end, clear
4841       // our resume bookmark here
4842       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4843       {
4844         // Delete the bookmark
4845         m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4846       }
4847
4848       // reset the current playing file
4849       m_itemCurrentFile->Reset();
4850       g_infoManager.ResetCurrentItem();
4851       m_currentStack->Clear();
4852
4853       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4854       {
4855         g_playlistPlayer.PlayNext(1, true);
4856       }
4857       else
4858       {
4859         // reset any forced player
4860         m_eForcedNextPlayer = EPC_NONE;
4861
4862         m_pPlayer->ClosePlayer();
4863
4864         // Reset playspeed
4865         m_pPlayer->m_iPlaySpeed = 1;
4866       }
4867
4868       if (!m_pPlayer->IsPlaying())
4869       {
4870         g_audioManager.Enable(true);
4871       }
4872
4873       if (!m_pPlayer->IsPlayingVideo())
4874       {
4875         if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4876         {
4877           g_windowManager.PreviousWindow();
4878         }
4879         else
4880         {
4881           CSingleLock lock(g_graphicsContext);
4882           //  resets to res_desktop or look&feel resolution (including refreshrate)
4883           g_graphicsContext.SetFullScreenVideo(false);
4884         }
4885       }
4886
4887       if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4888       {
4889         CSettings::Get().Save();  // save vis settings
4890         WakeUpScreenSaverAndDPMS();
4891         g_windowManager.PreviousWindow();
4892       }
4893
4894       // DVD ejected while playing in vis ?
4895       if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4896       {
4897         // yes, disable vis
4898         CSettings::Get().Save();    // save vis settings
4899         WakeUpScreenSaverAndDPMS();
4900         g_windowManager.PreviousWindow();
4901       }
4902
4903       if (IsEnableTestMode())
4904         CApplicationMessenger::Get().Quit();
4905       return true;
4906     }
4907     break;
4908
4909   case GUI_MSG_PLAYLISTPLAYER_STARTED:
4910   case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4911     {
4912       return true;
4913     }
4914     break;
4915   case GUI_MSG_FULLSCREEN:
4916     { // Switch to fullscreen, if we can
4917       SwitchToFullScreen();
4918       return true;
4919     }
4920     break;
4921   case GUI_MSG_EXECUTE:
4922     if (message.GetNumStringParams())
4923       return ExecuteXBMCAction(message.GetStringParam());
4924     break;
4925   }
4926   return false;
4927 }
4928
4929 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4930 {
4931   // see if it is a user set string
4932
4933   //We don't know if there is unsecure information in this yet, so we
4934   //postpone any logging
4935   const std::string in_actionStr(actionStr);
4936   CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
4937   CGUIInfoLabel info(actionStr, "");
4938   actionStr = info.GetLabel(0);
4939
4940   // user has asked for something to be executed
4941   if (CBuiltins::HasCommand(actionStr))
4942     CBuiltins::Execute(actionStr);
4943   else
4944   {
4945     // try translating the action from our ButtonTranslator
4946     int actionID;
4947     if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4948     {
4949       OnAction(CAction(actionID));
4950       return true;
4951     }
4952     CFileItem item(actionStr, false);
4953 #ifdef HAS_PYTHON
4954     if (item.IsPythonScript())
4955     { // a python script
4956       CScriptInvocationManager::Get().Execute(item.GetPath());
4957     }
4958     else
4959 #endif
4960     if (item.IsAudio() || item.IsVideo())
4961     { // an audio or video file
4962       PlayFile(item);
4963     }
4964     else
4965     {
4966       //At this point we have given up to translate, so even though
4967       //there may be insecure information, we log it.
4968       CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
4969       return false;
4970     }
4971   }
4972   return true;
4973 }
4974
4975 void CApplication::Process()
4976 {
4977   MEASURE_FUNCTION;
4978
4979   // dispatch the messages generated by python or other threads to the current window
4980   g_windowManager.DispatchThreadMessages();
4981
4982   // process messages which have to be send to the gui
4983   // (this can only be done after g_windowManager.Render())
4984   CApplicationMessenger::Get().ProcessWindowMessages();
4985
4986   if (m_loggingIn)
4987   {
4988     m_loggingIn = false;
4989
4990     // autoexec.py - profile
4991     CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
4992
4993     if (XFILE::CFile::Exists(strAutoExecPy))
4994       CScriptInvocationManager::Get().Execute(strAutoExecPy);
4995     else
4996       CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
4997   }
4998
4999   // handle any active scripts
5000   CScriptInvocationManager::Get().Process();
5001
5002   // process messages, even if a movie is playing
5003   CApplicationMessenger::Get().ProcessMessages();
5004   if (g_application.m_bStop) return; //we're done, everything has been unloaded
5005
5006   // check how far we are through playing the current item
5007   // and do anything that needs doing (playcount updates etc)
5008   CheckPlayingProgress();
5009
5010   // update sound
5011   m_pPlayer->DoAudioWork();
5012
5013   // do any processing that isn't needed on each run
5014   if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5015   {
5016     m_slowTimer.Reset();
5017     ProcessSlow();
5018   }
5019
5020   g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5021 }
5022
5023 // We get called every 500ms
5024 void CApplication::ProcessSlow()
5025 {
5026   g_powerManager.ProcessEvents();
5027
5028 #if defined(TARGET_DARWIN_OSX)
5029   // There is an issue on OS X that several system services ask the cursor to become visible
5030   // during their startup routines.  Given that we can't control this, we hack it in by
5031   // forcing the
5032   if (g_Windowing.IsFullScreen())
5033   { // SDL thinks it's hidden
5034     Cocoa_HideMouse();
5035   }
5036 #endif
5037
5038   // Temporarely pause pausable jobs when viewing video/picture
5039   int currentWindow = g_windowManager.GetActiveWindow();
5040   if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5041   {
5042     CJobManager::GetInstance().PauseJobs();
5043   }
5044   else
5045   {
5046     CJobManager::GetInstance().UnPauseJobs();
5047   }
5048
5049   // Store our file state for use on close()
5050   UpdateFileState();
5051
5052   // Check if we need to activate the screensaver / DPMS.
5053   CheckScreenSaverAndDPMS();
5054
5055   // Check if we need to shutdown (if enabled).
5056 #if defined(TARGET_DARWIN)
5057   if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5058 #else
5059   if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5060 #endif
5061   {
5062     CheckShutdown();
5063   }
5064
5065   // check if we should restart the player
5066   CheckDelayedPlayerRestart();
5067
5068   //  check if we can unload any unreferenced dlls or sections
5069   if (!m_pPlayer->IsPlayingVideo())
5070     CSectionLoader::UnloadDelayed();
5071
5072   // check for any idle curl connections
5073   g_curlInterface.CheckIdle();
5074
5075   // check for any idle myth sessions
5076   CMythSession::CheckIdle();
5077
5078 #ifdef HAS_FILESYSTEM_HTSP
5079   // check for any idle htsp sessions
5080   HTSP::CHTSPDirectorySession::CheckIdle();
5081 #endif
5082
5083 #ifdef HAS_KARAOKE
5084   if ( m_pKaraokeMgr )
5085     m_pKaraokeMgr->ProcessSlow();
5086 #endif
5087
5088   if (!m_pPlayer->IsPlayingVideo())
5089     g_largeTextureManager.CleanupUnusedImages();
5090
5091   g_TextureManager.FreeUnusedTextures(5000);
5092
5093 #ifdef HAS_DVD_DRIVE
5094   // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5095   if (!m_pPlayer->IsPlayingVideo())
5096     m_Autorun->HandleAutorun();
5097 #endif
5098
5099   // update upnp server/renderer states
5100 #ifdef HAS_UPNP
5101   if(UPNP::CUPnP::IsInstantiated())
5102     UPNP::CUPnP::GetInstance()->UpdateState();
5103 #endif
5104
5105 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5106   smb.CheckIfIdle();
5107 #endif
5108
5109 #ifdef HAS_FILESYSTEM_NFS
5110   gNfsConnection.CheckIfIdle();
5111 #endif
5112
5113 #ifdef HAS_FILESYSTEM_AFP
5114   gAfpConnection.CheckIfIdle();
5115 #endif
5116
5117 #ifdef HAS_FILESYSTEM_SFTP
5118   CSFTPSessionManager::ClearOutIdleSessions();
5119 #endif
5120
5121   g_mediaManager.ProcessEvents();
5122
5123 #ifdef HAS_LIRC
5124   if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5125     g_RemoteControl.Initialize();
5126 #endif
5127
5128   if (!m_pPlayer->IsPlayingVideo())
5129     CAddonInstaller::Get().UpdateRepos();
5130
5131   CAEFactory::GarbageCollect();
5132 }
5133
5134 // Global Idle Time in Seconds
5135 // idle time will be resetet if on any OnKey()
5136 // int return: system Idle time in seconds! 0 is no idle!
5137 int CApplication::GlobalIdleTime()
5138 {
5139   if(!m_idleTimer.IsRunning())
5140   {
5141     m_idleTimer.Stop();
5142     m_idleTimer.StartZero();
5143   }
5144   return (int)m_idleTimer.GetElapsedSeconds();
5145 }
5146
5147 float CApplication::NavigationIdleTime()
5148 {
5149   if (!m_navigationTimer.IsRunning())
5150   {
5151     m_navigationTimer.Stop();
5152     m_navigationTimer.StartZero();
5153   }
5154   return m_navigationTimer.GetElapsedSeconds();
5155 }
5156
5157 void CApplication::DelayedPlayerRestart()
5158 {
5159   m_restartPlayerTimer.StartZero();
5160 }
5161
5162 void CApplication::CheckDelayedPlayerRestart()
5163 {
5164   if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5165   {
5166     m_restartPlayerTimer.Stop();
5167     m_restartPlayerTimer.Reset();
5168     Restart(true);
5169   }
5170 }
5171
5172 void CApplication::Restart(bool bSamePosition)
5173 {
5174   // this function gets called when the user changes a setting (like noninterleaved)
5175   // and which means we gotta close & reopen the current playing file
5176
5177   // first check if we're playing a file
5178   if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5179     return ;
5180
5181   if( !m_pPlayer->HasPlayer() )
5182     return ;
5183
5184   SaveFileState();
5185
5186   // do we want to return to the current position in the file
5187   if (false == bSamePosition)
5188   {
5189     // no, then just reopen the file and start at the beginning
5190     PlayFile(*m_itemCurrentFile, true);
5191     return ;
5192   }
5193
5194   // else get current position
5195   double time = GetTime();
5196
5197   // get player state, needed for dvd's
5198   CStdString state = m_pPlayer->GetPlayerState();
5199
5200   // set the requested starttime
5201   m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5202
5203   // reopen the file
5204   if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5205     m_pPlayer->SetPlayerState(state);
5206 }
5207
5208 const CStdString& CApplication::CurrentFile()
5209 {
5210   return m_itemCurrentFile->GetPath();
5211 }
5212
5213 CFileItem& CApplication::CurrentFileItem()
5214 {
5215   return *m_itemCurrentFile;
5216 }
5217
5218 void CApplication::ShowVolumeBar(const CAction *action)
5219 {
5220   CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5221   if (volumeBar)
5222   {
5223     volumeBar->Show();
5224     if (action)
5225       volumeBar->OnAction(*action);
5226   }
5227 }
5228
5229 bool CApplication::IsMuted() const
5230 {
5231   if (g_peripherals.IsMuted())
5232     return true;
5233   return CAEFactory::IsMuted();
5234 }
5235
5236 void CApplication::ToggleMute(void)
5237 {
5238   if (m_muted)
5239     UnMute();
5240   else
5241     Mute();
5242 }
5243
5244 void CApplication::SetMute(bool mute)
5245 {
5246   if (m_muted != mute)
5247   {
5248     ToggleMute();
5249     m_muted = mute;
5250   }
5251 }
5252
5253 void CApplication::Mute()
5254 {
5255   if (g_peripherals.Mute())
5256     return;
5257
5258   CAEFactory::SetMute(true);
5259   m_muted = true;
5260   VolumeChanged();
5261 }
5262
5263 void CApplication::UnMute()
5264 {
5265   if (g_peripherals.UnMute())
5266     return;
5267
5268   CAEFactory::SetMute(false);
5269   m_muted = false;
5270   VolumeChanged();
5271 }
5272
5273 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5274 {
5275   float hardwareVolume = iValue;
5276
5277   if(isPercentage)
5278     hardwareVolume /= 100.0f;
5279
5280   SetHardwareVolume(hardwareVolume);
5281   VolumeChanged();
5282 }
5283
5284 void CApplication::SetHardwareVolume(float hardwareVolume)
5285 {
5286   hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5287   m_volumeLevel = hardwareVolume;
5288
5289   float value = 0.0f;
5290   if (hardwareVolume > VOLUME_MINIMUM)
5291   {
5292     float dB = CAEUtil::PercentToGain(hardwareVolume);
5293     value = CAEUtil::GainToScale(dB);
5294   }
5295   if (value >= 0.99f)
5296     value = 1.0f;
5297
5298   CAEFactory::SetVolume(value);
5299 }
5300
5301 float CApplication::GetVolume(bool percentage /* = true */) const
5302 {
5303   if (percentage)
5304   {
5305     // converts the hardware volume to a percentage
5306     return m_volumeLevel * 100.0f;
5307   }
5308   
5309   return m_volumeLevel;
5310 }
5311
5312 void CApplication::VolumeChanged() const
5313 {
5314   CVariant data(CVariant::VariantTypeObject);
5315   data["volume"] = GetVolume();
5316   data["muted"] = m_muted;
5317   CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5318
5319   // if player has volume control, set it.
5320   if (m_pPlayer->ControlsVolume())
5321   {
5322      m_pPlayer->SetVolume(m_volumeLevel);
5323      m_pPlayer->SetMute(m_muted);
5324   }
5325 }
5326
5327 int CApplication::GetSubtitleDelay() const
5328 {
5329   // converts subtitle delay to a percentage
5330   return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5331 }
5332
5333 int CApplication::GetAudioDelay() const
5334 {
5335   // converts audio delay to a percentage
5336   return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5337 }
5338
5339 // Returns the total time in seconds of the current media.  Fractional
5340 // portions of a second are possible - but not necessarily supported by the
5341 // player class.  This returns a double to be consistent with GetTime() and
5342 // SeekTime().
5343 double CApplication::GetTotalTime() const
5344 {
5345   double rc = 0.0;
5346
5347   if (m_pPlayer->IsPlaying())
5348   {
5349     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5350       rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5351     else
5352       rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5353   }
5354
5355   return rc;
5356 }
5357
5358 void CApplication::StopShutdownTimer()
5359 {
5360   if (m_shutdownTimer.IsRunning())
5361     m_shutdownTimer.Stop();
5362 }
5363
5364 void CApplication::ResetShutdownTimers()
5365 {
5366   // reset system shutdown timer
5367   m_shutdownTimer.StartZero();
5368
5369   // delete custom shutdown timer
5370   if (g_alarmClock.HasAlarm("shutdowntimer"))
5371     g_alarmClock.Stop("shutdowntimer", true);
5372 }
5373
5374 // Returns the current time in seconds of the currently playing media.
5375 // Fractional portions of a second are possible.  This returns a double to
5376 // be consistent with GetTotalTime() and SeekTime().
5377 double CApplication::GetTime() const
5378 {
5379   double rc = 0.0;
5380
5381   if (m_pPlayer->IsPlaying())
5382   {
5383     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5384     {
5385       long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5386       rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5387     }
5388     else
5389       rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5390   }
5391
5392   return rc;
5393 }
5394
5395 // Sets the current position of the currently playing media to the specified
5396 // time in seconds.  Fractional portions of a second are valid.  The passed
5397 // time is the time offset from the beginning of the file as opposed to a
5398 // delta from the current position.  This method accepts a double to be
5399 // consistent with GetTime() and GetTotalTime().
5400 void CApplication::SeekTime( double dTime )
5401 {
5402   if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5403   {
5404     if (!m_pPlayer->CanSeek()) return;
5405     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5406     {
5407       // find the item in the stack we are seeking to, and load the new
5408       // file if necessary, and calculate the correct seek within the new
5409       // file.  Otherwise, just fall through to the usual routine if the
5410       // time is higher than our total time.
5411       for (int i = 0; i < m_currentStack->Size(); i++)
5412       {
5413         if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5414         {
5415           long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5416           if (m_currentStackPosition == i)
5417             m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5418           else
5419           { // seeking to a new file
5420             m_currentStackPosition = i;
5421             CFileItem item(*(*m_currentStack)[i]);
5422             item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5423             // don't just call "PlayFile" here, as we are quite likely called from the
5424             // player thread, so we won't be able to delete ourselves.
5425             CApplicationMessenger::Get().PlayFile(item, true);
5426           }
5427           return;
5428         }
5429       }
5430     }
5431     // convert to milliseconds and perform seek
5432     m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5433   }
5434 }
5435
5436 float CApplication::GetPercentage() const
5437 {
5438   if (m_pPlayer->IsPlaying())
5439   {
5440     if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5441     {
5442       const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5443       if (tag.GetDuration() > 0)
5444         return (float)(GetTime() / tag.GetDuration() * 100);
5445     }
5446
5447     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5448     {
5449       double totalTime = GetTotalTime();
5450       if (totalTime > 0.0f)
5451         return (float)(GetTime() / totalTime * 100);
5452     }
5453     else
5454       return m_pPlayer->GetPercentage();
5455   }
5456   return 0.0f;
5457 }
5458
5459 float CApplication::GetCachePercentage() const
5460 {
5461   if (m_pPlayer->IsPlaying())
5462   {
5463     // Note that the player returns a relative cache percentage and we want an absolute percentage
5464     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5465     {
5466       float stackedTotalTime = (float) GetTotalTime();
5467       // We need to take into account the stack's total time vs. currently playing file's total time
5468       if (stackedTotalTime > 0.0f)
5469         return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5470     }
5471     else
5472       return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5473   }
5474   return 0.0f;
5475 }
5476
5477 void CApplication::SeekPercentage(float percent)
5478 {
5479   if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5480   {
5481     if (!m_pPlayer->CanSeek()) return;
5482     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5483       SeekTime(percent * 0.01 * GetTotalTime());
5484     else
5485       m_pPlayer->SeekPercentage(percent);
5486   }
5487 }
5488
5489 // SwitchToFullScreen() returns true if a switch is made, else returns false
5490 bool CApplication::SwitchToFullScreen()
5491 {
5492   // if playing from the video info window, close it first!
5493   if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5494   {
5495     CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5496     if (pDialog) pDialog->Close(true);
5497   }
5498
5499   // don't switch if there is a dialog on screen or the slideshow is active
5500   if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5501     return false;
5502
5503   // See if we're playing a video, and are in GUI mode
5504   if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5505   {
5506     // then switch to fullscreen mode
5507     g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5508     return true;
5509   }
5510   // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5511   if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5512   { // then switch to visualisation
5513     g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5514     return true;
5515   }
5516   return false;
5517 }
5518
5519 void CApplication::Minimize()
5520 {
5521   g_Windowing.Minimize();
5522 }
5523
5524 PLAYERCOREID CApplication::GetCurrentPlayer()
5525 {
5526   return m_pPlayer->GetCurrentPlayer();
5527 }
5528
5529 void CApplication::UpdateLibraries()
5530 {
5531   if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5532   {
5533     CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5534     StartVideoScan("");
5535   }
5536
5537   if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5538   {
5539     CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5540     StartMusicScan("");
5541   }
5542 }
5543
5544 bool CApplication::IsVideoScanning() const
5545 {
5546   return m_videoInfoScanner->IsScanning();
5547 }
5548
5549 bool CApplication::IsMusicScanning() const
5550 {
5551   return m_musicInfoScanner->IsScanning();
5552 }
5553
5554 void CApplication::StopVideoScan()
5555 {
5556   if (m_videoInfoScanner->IsScanning())
5557     m_videoInfoScanner->Stop();
5558 }
5559
5560 void CApplication::StopMusicScan()
5561 {
5562   if (m_musicInfoScanner->IsScanning())
5563     m_musicInfoScanner->Stop();
5564 }
5565
5566 void CApplication::StartVideoCleanup()
5567 {
5568   if (m_videoInfoScanner->IsScanning())
5569     return;
5570
5571   m_videoInfoScanner->CleanDatabase();
5572 }
5573
5574 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5575 {
5576   if (m_videoInfoScanner->IsScanning())
5577     return;
5578
5579   m_videoInfoScanner->ShowDialog(true);
5580
5581   m_videoInfoScanner->Start(strDirectory,scanAll);
5582 }
5583
5584 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5585 {
5586   if (m_musicInfoScanner->IsScanning())
5587     return;
5588
5589   if (!flags)
5590   { // setup default flags
5591     if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5592       flags |= CMusicInfoScanner::SCAN_ONLINE;
5593     if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5594       flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5595   }
5596
5597   if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5598     m_musicInfoScanner->ShowDialog(true);
5599
5600   m_musicInfoScanner->Start(strDirectory, flags);
5601 }
5602
5603 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5604                                        bool refresh)
5605 {
5606   if (m_musicInfoScanner->IsScanning())
5607     return;
5608
5609   m_musicInfoScanner->ShowDialog(true);
5610
5611   m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5612 }
5613
5614 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5615                                         bool refresh)
5616 {
5617   if (m_musicInfoScanner->IsScanning())
5618     return;
5619
5620   m_musicInfoScanner->ShowDialog(true);
5621
5622   m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5623 }
5624
5625 void CApplication::CheckPlayingProgress()
5626 {
5627   // check if we haven't rewound past the start of the file
5628   if (m_pPlayer->IsPlaying())
5629   {
5630     int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5631     if (iSpeed < 1)
5632     {
5633       iSpeed *= -1;
5634       int iPower = 0;
5635       while (iSpeed != 1)
5636       {
5637         iSpeed >>= 1;
5638         iPower++;
5639       }
5640       if (g_infoManager.GetPlayTime() / 1000 < iPower)
5641       {
5642         g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5643         g_application.SeekTime(0);
5644       }
5645     }
5646   }
5647 }
5648
5649 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5650 {
5651   CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5652
5653   // initial exit conditions
5654   // no songs in playlist just return
5655   if (playlist.size() == 0)
5656     return false;
5657
5658   // illegal playlist
5659   if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5660     return false;
5661
5662   // setup correct playlist
5663   g_playlistPlayer.ClearPlaylist(iPlaylist);
5664
5665   // if the playlist contains an internet stream, this file will be used
5666   // to generate a thumbnail for musicplayer.cover
5667   g_application.m_strPlayListFile = strPlayList;
5668
5669   // add the items to the playlist player
5670   g_playlistPlayer.Add(iPlaylist, playlist);
5671
5672   // if we have a playlist
5673   if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5674   {
5675     // start playing it
5676     g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5677     g_playlistPlayer.Reset();
5678     g_playlistPlayer.Play(track);
5679     return true;
5680   }
5681   return false;
5682 }
5683
5684 void CApplication::SaveCurrentFileSettings()
5685 {
5686   // don't store settings for PVR in video database
5687   if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5688   {
5689     // save video settings
5690     if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5691     {
5692       CVideoDatabase dbs;
5693       dbs.Open();
5694       dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5695       dbs.Close();
5696     }
5697   }
5698   else if (m_itemCurrentFile->IsPVRChannel())
5699   {
5700     g_PVRManager.SaveCurrentChannelSettings();
5701   }
5702 }
5703
5704 bool CApplication::AlwaysProcess(const CAction& action)
5705 {
5706   // check if this button is mapped to a built-in function
5707   if (!action.GetName().empty())
5708   {
5709     CStdString builtInFunction;
5710     vector<CStdString> params;
5711     CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5712     StringUtils::ToLower(builtInFunction);
5713
5714     // should this button be handled normally or just cancel the screensaver?
5715     if (   builtInFunction.Equals("powerdown")
5716         || builtInFunction.Equals("reboot")
5717         || builtInFunction.Equals("restart")
5718         || builtInFunction.Equals("restartapp")
5719         || builtInFunction.Equals("suspend")
5720         || builtInFunction.Equals("hibernate")
5721         || builtInFunction.Equals("quit")
5722         || builtInFunction.Equals("shutdown"))
5723     {
5724       return true;
5725     }
5726   }
5727
5728   return false;
5729 }
5730
5731 bool CApplication::IsCurrentThread() const
5732 {
5733   return CThread::IsCurrentThread(m_threadID);
5734 }
5735
5736 void CApplication::SetRenderGUI(bool renderGUI)
5737 {
5738   if (renderGUI && ! m_renderGUI)
5739     g_windowManager.MarkDirty();
5740   m_renderGUI = renderGUI;
5741 }
5742
5743 CNetwork& CApplication::getNetwork()
5744 {
5745   return *m_network;
5746 }
5747 #ifdef HAS_PERFORMANCE_SAMPLE
5748 CPerformanceStats &CApplication::GetPerformanceStats()
5749 {
5750   return m_perfStats;
5751 }
5752 #endif
5753
5754 bool CApplication::SetLanguage(const CStdString &strLanguage)
5755 {
5756   CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5757   CStdString strNewLanguage = strLanguage;
5758   if (strNewLanguage != strPreviousLanguage)
5759   {
5760     CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5761     if (!g_langInfo.Load(strLangInfoPath))
5762       return false;
5763
5764     if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5765     {
5766       CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5767       CStdString strFontSet;
5768       if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5769         strNewLanguage = strFontSet;
5770       else
5771         CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5772     }
5773     CSettings::Get().SetString("locale.language", strNewLanguage);
5774
5775     if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5776       return false;
5777
5778     // also tell our weather and skin to reload as these are localized
5779     g_weatherManager.Refresh();
5780     g_PVRManager.LocalizationChanged();
5781     ReloadSkin();
5782   }
5783
5784   return true;
5785 }
5786
5787 void CApplication::CloseNetworkShares()
5788 {
5789   CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5790
5791 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5792   smb.Deinit();
5793 #endif
5794   
5795 #ifdef HAS_FILESYSTEM_NFS
5796   gNfsConnection.Deinit();
5797 #endif
5798   
5799 #ifdef HAS_FILESYSTEM_AFP
5800   gAfpConnection.Deinit();
5801 #endif
5802   
5803 #ifdef HAS_FILESYSTEM_SFTP
5804   CSFTPSessionManager::DisconnectAllSessions();
5805 #endif
5806 }