Merge pull request #3886 from FernetMenta/aefixes
[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   if (processEvents)
2863   {
2864     // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2865     float frameTime = m_frameTime.GetElapsedSeconds();
2866     m_frameTime.StartZero();
2867     // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2868     if( frameTime > 0.5 ) frameTime = 0.5;
2869
2870     if (processGUI && m_renderGUI)
2871     {
2872       g_graphicsContext.Lock();
2873       // check if there are notifications to display
2874       CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2875       if (toast && toast->DoWork())
2876       {
2877         if (!toast->IsDialogRunning())
2878         {
2879           toast->Show();
2880         }
2881       }
2882       g_graphicsContext.Unlock();
2883     }
2884     CWinEvents::MessagePump();
2885
2886 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2887     // Read the input from a remote
2888     g_RemoteControl.Update();
2889 #endif
2890
2891     // process input actions
2892     ProcessRemote(frameTime);
2893     ProcessGamepad(frameTime);
2894     ProcessEventServer(frameTime);
2895     ProcessPeripherals(frameTime);
2896     if (processGUI && m_renderGUI)
2897     {
2898       m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2899       m_seekHandler->Process();
2900     }
2901   }
2902   if (processGUI && m_renderGUI)
2903   {
2904     if (!m_bStop)
2905       g_windowManager.Process(CTimeUtils::GetFrameTime());
2906     g_windowManager.FrameMove();
2907   }
2908 }
2909
2910 bool CApplication::ProcessGamepad(float frameTime)
2911 {
2912 #ifdef HAS_SDL_JOYSTICK
2913   if (!m_AppFocused)
2914     return false;
2915
2916   int iWin = GetActiveWindowID();
2917   int bid = 0;
2918   g_Joystick.Update();
2919   if (g_Joystick.GetButton(bid))
2920   {
2921     // reset Idle Timer
2922     m_idleTimer.StartZero();
2923
2924     ResetScreenSaver();
2925     if (WakeUpScreenSaverAndDPMS())
2926     {
2927       g_Joystick.Reset(true);
2928       return true;
2929     }
2930
2931     int actionID;
2932     CStdString actionName;
2933     bool fullrange;
2934     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2935     {
2936       CAction action(actionID, 1.0f, 0.0f, actionName);
2937       g_Joystick.Reset();
2938       g_Mouse.SetActive(false);
2939       return ExecuteInputAction(action);
2940     }
2941     else
2942     {
2943       g_Joystick.Reset();
2944     }
2945   }
2946   if (g_Joystick.GetAxis(bid))
2947   {
2948     if (g_Joystick.GetAmount() < 0)
2949     {
2950       bid = -bid;
2951     }
2952
2953     int actionID;
2954     CStdString actionName;
2955     bool fullrange;
2956     if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2957     {
2958       ResetScreenSaver();
2959       if (WakeUpScreenSaverAndDPMS())
2960       {
2961         return true;
2962       }
2963
2964       CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2965       g_Joystick.Reset();
2966       g_Mouse.SetActive(false);
2967       return ExecuteInputAction(action);
2968     }
2969     else
2970     {
2971       g_Joystick.ResetAxis(abs(bid));
2972     }
2973   }
2974   int position = 0;
2975   if (g_Joystick.GetHat(bid, position))
2976   {
2977     // reset Idle Timer
2978     m_idleTimer.StartZero();
2979
2980     ResetScreenSaver();
2981     if (WakeUpScreenSaverAndDPMS())
2982     {
2983       g_Joystick.Reset();
2984       return true;
2985     }
2986
2987     int actionID;
2988     CStdString actionName;
2989     bool fullrange;
2990
2991     bid = position<<16|bid;
2992
2993     if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2994     {
2995       CAction action(actionID, 1.0f, 0.0f, actionName);
2996       g_Joystick.Reset();
2997       g_Mouse.SetActive(false);
2998       return ExecuteInputAction(action);
2999     }
3000   }
3001 #endif
3002   return false;
3003 }
3004
3005 bool CApplication::ProcessRemote(float frameTime)
3006 {
3007 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3008   if (g_RemoteControl.GetButton())
3009   {
3010     CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3011     g_RemoteControl.Reset();
3012     return OnKey(key);
3013   }
3014 #endif
3015   return false;
3016 }
3017
3018 bool CApplication::ProcessPeripherals(float frameTime)
3019 {
3020   CKey key;
3021   if (g_peripherals.GetNextKeypress(frameTime, key))
3022     return OnKey(key);
3023   return false;
3024 }
3025
3026 bool CApplication::ProcessMouse()
3027 {
3028   MEASURE_FUNCTION;
3029
3030   if (!g_Mouse.IsActive() || !m_AppFocused)
3031     return false;
3032
3033   // Get the mouse command ID
3034   uint32_t mousecommand = g_Mouse.GetAction();
3035   if (mousecommand == ACTION_NOOP)
3036     return true;
3037
3038   // Reset the screensaver and idle timers
3039   m_idleTimer.StartZero();
3040   ResetScreenSaver();
3041   if (WakeUpScreenSaverAndDPMS())
3042     return true;
3043
3044   // Retrieve the corresponding action
3045   int iWin = GetActiveWindowID();
3046   CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3047   CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3048
3049   // Deactivate mouse if non-mouse action
3050   if (!mouseaction.IsMouse())
3051     g_Mouse.SetActive(false);
3052
3053   // Consume ACTION_NOOP.
3054   // Some views or dialogs gets closed after any ACTION and
3055   // a sensitive mouse might cause problems.
3056   if (mouseaction.GetID() == ACTION_NOOP)
3057     return false;
3058
3059   // If we couldn't find an action return false to indicate we have not
3060   // handled this mouse action
3061   if (!mouseaction.GetID())
3062   {
3063     CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3064     return false;
3065   }
3066
3067   // Log mouse actions except for move and noop
3068   if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3069     CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3070
3071   // The action might not be a mouse action. For example wheel moves might
3072   // be mapped to volume up/down in mouse.xml. In this case we do not want
3073   // the mouse position saved in the action.
3074   if (!mouseaction.IsMouse())
3075     return OnAction(mouseaction);
3076
3077   // This is a mouse action so we need to record the mouse position
3078   return OnAction(CAction(mouseaction.GetID(),
3079                           g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3080                           (float)g_Mouse.GetX(),
3081                           (float)g_Mouse.GetY(),
3082                           (float)g_Mouse.GetDX(),
3083                           (float)g_Mouse.GetDY(),
3084                           mouseaction.GetName()));
3085 }
3086
3087 bool CApplication::ProcessEventServer(float frameTime)
3088 {
3089 #ifdef HAS_EVENT_SERVER
3090   CEventServer* es = CEventServer::GetInstance();
3091   if (!es || !es->Running() || es->GetNumberOfClients()==0)
3092     return false;
3093
3094   // process any queued up actions
3095   if (es->ExecuteNextAction())
3096   {
3097     // reset idle timers
3098     m_idleTimer.StartZero();
3099     ResetScreenSaver();
3100     WakeUpScreenSaverAndDPMS();
3101   }
3102
3103   // now handle any buttons or axis
3104   std::string joystickName;
3105   bool isAxis = false;
3106   float fAmount = 0.0;
3107
3108   // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3109   // when the action exits XBMC
3110   es = CEventServer::GetInstance();
3111   if (!es || !es->Running() || es->GetNumberOfClients()==0)
3112     return false;
3113   unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3114
3115   if (wKeyID)
3116   {
3117     if (joystickName.length() > 0)
3118     {
3119       if (isAxis == true)
3120       {
3121         if (fabs(fAmount) >= 0.08)
3122           m_lastAxisMap[joystickName][wKeyID] = fAmount;
3123         else
3124           m_lastAxisMap[joystickName].erase(wKeyID);
3125       }
3126
3127       return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3128     }
3129     else
3130     {
3131       CKey key;
3132       if (wKeyID & ES_FLAG_UNICODE)
3133       {
3134         key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3135         return OnKey(key);
3136       }
3137
3138       if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3139         key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3140       else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3141         key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3142       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3143         key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3144       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3145         key = CKey(wKeyID, 0, 0,  fAmount, 0.0, 0.0, 0.0, frameTime);
3146       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3147         key = CKey(wKeyID, 0, 0, 0.0,  fAmount, 0.0, 0.0, frameTime);
3148       else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3149         key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3150       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3151         key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3152       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3153         key = CKey(wKeyID, 0, 0, 0.0, 0.0,  fAmount, 0.0, frameTime);
3154       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3155         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0,  fAmount, frameTime);
3156       else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3157         key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3158       else
3159         key = CKey(wKeyID);
3160       key.SetFromService(true);
3161       return OnKey(key);
3162     }
3163   }
3164
3165   if (m_lastAxisMap.size() > 0)
3166   {
3167     // Process all the stored axis.
3168     for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3169     {
3170       for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3171         ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3172     }
3173   }
3174
3175   {
3176     CPoint pos;
3177     if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3178     {
3179       XBMC_Event newEvent;
3180       newEvent.type = XBMC_MOUSEMOTION;
3181       newEvent.motion.xrel = 0;
3182       newEvent.motion.yrel = 0;
3183       newEvent.motion.state = 0;
3184       newEvent.motion.which = 0x10;  // just a different value to distinguish between mouse and event client device.
3185       newEvent.motion.x = (uint16_t)pos.x;
3186       newEvent.motion.y = (uint16_t)pos.y;
3187       OnEvent(newEvent);  // had to call this to update g_Mouse position
3188       return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3189     }
3190   }
3191 #endif
3192   return false;
3193 }
3194
3195 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3196 {
3197 #if defined(HAS_EVENT_SERVER)
3198   m_idleTimer.StartZero();
3199
3200    // Make sure to reset screen saver, mouse.
3201    ResetScreenSaver();
3202    if (WakeUpScreenSaverAndDPMS())
3203      return true;
3204
3205 #ifdef HAS_SDL_JOYSTICK
3206    g_Joystick.Reset();
3207 #endif
3208    g_Mouse.SetActive(false);
3209
3210    int iWin = GetActiveWindowID();
3211    int actionID;
3212    CStdString actionName;
3213    bool fullRange = false;
3214
3215    // Translate using regular joystick translator.
3216    if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3217      return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3218    else
3219      CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3220 #endif
3221
3222    return false;
3223 }
3224
3225 bool CApplication::ExecuteInputAction(const CAction &action)
3226 {
3227   bool bResult = false;
3228
3229   // play sound before the action unless the button is held,
3230   // where we execute after the action as held actions aren't fired every time.
3231   if(action.GetHoldTime())
3232   {
3233     bResult = OnAction(action);
3234     if(bResult)
3235       g_audioManager.PlayActionSound(action);
3236   }
3237   else
3238   {
3239     g_audioManager.PlayActionSound(action);
3240     bResult = OnAction(action);
3241   }
3242   return bResult;
3243 }
3244
3245 int CApplication::GetActiveWindowID(void)
3246 {
3247   // Get the currently active window
3248   int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3249
3250   // If there is a dialog active get the dialog id instead
3251   if (g_windowManager.HasModalDialog())
3252     iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3253
3254   // If the window is FullScreenVideo check for special cases
3255   if (iWin == WINDOW_FULLSCREEN_VIDEO)
3256   {
3257     // check if we're in a DVD menu
3258     if(g_application.m_pPlayer->IsInMenu())
3259       iWin = WINDOW_VIDEO_MENU;
3260     // check for LiveTV and switch to it's virtual window
3261     else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3262       iWin = WINDOW_FULLSCREEN_LIVETV;
3263   }
3264
3265   // Return the window id
3266   return iWin;
3267 }
3268
3269 bool CApplication::Cleanup()
3270 {
3271   try
3272   {
3273     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3274     g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3275     g_windowManager.Delete(WINDOW_MUSIC_FILES);
3276     g_windowManager.Delete(WINDOW_MUSIC_NAV);
3277     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3278     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3279     g_windowManager.Delete(WINDOW_VIDEO_FILES);
3280     g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3281     g_windowManager.Delete(WINDOW_VIDEO_NAV);
3282     g_windowManager.Delete(WINDOW_FILES);
3283     g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3284     g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3285     g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3286     g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3287     g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3288     g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3289     g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3290     g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3291     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3292     g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3293     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3294     g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3295     g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3296     g_windowManager.Delete(WINDOW_DIALOG_OK);
3297     g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3298     g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3299     g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3300     g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3301     g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3302     g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3303     g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3304     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3305     g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3306     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3307     g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3308     g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3309     g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3310     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3311     g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3312     g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3313     g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3314     g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3315     g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3316     g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3317     g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3318     g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3319     g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3320
3321     /* Delete PVR related windows and dialogs */
3322     g_windowManager.Delete(WINDOW_PVR);
3323     g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3324     g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3325     g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3326     g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3327     g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3328     g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3329     g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3330     g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3331     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3332     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3333     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3334     g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3335     g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3336
3337     g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3338     g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3339     g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3340     g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3341     g_windowManager.Delete(WINDOW_VISUALISATION);
3342     g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3343     g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3344     g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3345     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);  // all the settings categories
3346     g_windowManager.Delete(WINDOW_TEST_PATTERN);
3347     g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3348     g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3349     g_windowManager.Delete(WINDOW_SCREENSAVER);
3350     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3351     g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3352     g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3353     g_windowManager.Delete(WINDOW_SLIDESHOW);
3354     g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3355     g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3356
3357     g_windowManager.Delete(WINDOW_HOME);
3358     g_windowManager.Delete(WINDOW_PROGRAMS);
3359     g_windowManager.Delete(WINDOW_PICTURES);
3360     g_windowManager.Delete(WINDOW_WEATHER);
3361
3362     g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3363     g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3364     g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3365     g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3366     g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3367     g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3368     g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3369     g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3370     g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3371     g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3372
3373     g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3374     g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3375
3376     CAddonMgr::Get().DeInit();
3377
3378 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3379     CLog::Log(LOGNOTICE, "closing down remote control service");
3380     g_RemoteControl.Disconnect();
3381 #endif
3382
3383     CLog::Log(LOGNOTICE, "unload sections");
3384
3385 #ifdef HAS_PERFORMANCE_SAMPLE
3386     CLog::Log(LOGNOTICE, "performance statistics");
3387     m_perfStats.DumpStats();
3388 #endif
3389
3390     //  Shutdown as much as possible of the
3391     //  application, to reduce the leaks dumped
3392     //  to the vc output window before calling
3393     //  _CrtDumpMemoryLeaks(). Most of the leaks
3394     //  shown are no real leaks, as parts of the app
3395     //  are still allocated.
3396
3397     g_localizeStrings.Clear();
3398     g_LangCodeExpander.Clear();
3399     g_charsetConverter.clear();
3400     g_directoryCache.Clear();
3401     CButtonTranslator::GetInstance().Clear();
3402 #ifdef HAS_EVENT_SERVER
3403     CEventServer::RemoveInstance();
3404 #endif
3405     DllLoaderContainer::Clear();
3406     g_playlistPlayer.Clear();
3407     CSettings::Get().Uninitialize();
3408     g_advancedSettings.Clear();
3409
3410 #ifdef TARGET_POSIX
3411     CXHandle::DumpObjectTracker();
3412
3413 #ifdef HAS_DVD_DRIVE
3414     CLibcdio::ReleaseInstance();
3415 #endif
3416 #endif 
3417 #if defined(TARGET_ANDROID)
3418     // enable for all platforms once it's safe
3419     g_sectionLoader.UnloadAll();
3420 #endif
3421 #ifdef _CRTDBG_MAP_ALLOC
3422     _CrtDumpMemoryLeaks();
3423     while(1); // execution ends
3424 #endif
3425
3426     delete m_network;
3427     m_network = NULL;
3428
3429     return true;
3430   }
3431   catch (...)
3432   {
3433     CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3434     return false;
3435   }
3436 }
3437
3438 void CApplication::Stop(int exitCode)
3439 {
3440   try
3441   {
3442     CVariant vExitCode(exitCode);
3443     CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3444
3445     SaveFileState(true);
3446
3447     g_alarmClock.StopThread();
3448
3449     if( m_bSystemScreenSaverEnable )
3450       g_Windowing.EnableSystemScreenSaver(true);
3451
3452     CLog::Log(LOGNOTICE, "Storing total System Uptime");
3453     g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3454
3455     // Update the settings information (volume, uptime etc. need saving)
3456     if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3457     {
3458       CLog::Log(LOGNOTICE, "Saving settings");
3459       CSettings::Get().Save();
3460     }
3461     else
3462       CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3463
3464     m_bStop = true;
3465     m_AppFocused = false;
3466     m_ExitCode = exitCode;
3467     CLog::Log(LOGNOTICE, "stop all");
3468
3469     // cancel any jobs from the jobmanager
3470     CJobManager::GetInstance().CancelJobs();
3471
3472     // stop scanning before we kill the network and so on
3473     if (m_musicInfoScanner->IsScanning())
3474       m_musicInfoScanner->Stop();
3475
3476     if (m_videoInfoScanner->IsScanning())
3477       m_videoInfoScanner->Stop();
3478
3479     CApplicationMessenger::Get().Cleanup();
3480
3481     StopPVRManager();
3482     StopServices();
3483     //Sleep(5000);
3484
3485     CLog::Log(LOGNOTICE, "stop player");
3486     m_pPlayer->ClosePlayer();
3487
3488 #if HAS_FILESYTEM_DAAP
3489     CLog::Log(LOGNOTICE, "stop daap clients");
3490     g_DaapClient.Release();
3491 #endif
3492 #ifdef HAS_FILESYSTEM_SAP
3493     CLog::Log(LOGNOTICE, "stop sap announcement listener");
3494     g_sapsessions.StopThread();
3495 #endif
3496 #ifdef HAS_ZEROCONF
3497     if(CZeroconfBrowser::IsInstantiated())
3498     {
3499       CLog::Log(LOGNOTICE, "stop zeroconf browser");
3500       CZeroconfBrowser::GetInstance()->Stop();
3501       CZeroconfBrowser::ReleaseInstance();
3502     }
3503 #endif
3504
3505     CLog::Log(LOGNOTICE, "clean cached files!");
3506 #ifdef HAS_FILESYSTEM_RAR
3507     g_RarManager.ClearCache(true);
3508 #endif
3509
3510 #ifdef HAS_FILESYSTEM_SFTP
3511     CSFTPSessionManager::DisconnectAllSessions();
3512 #endif
3513
3514     CLog::Log(LOGNOTICE, "unload skin");
3515     UnloadSkin();
3516
3517 #if defined(TARGET_DARWIN_OSX)
3518     if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3519       XBMCHelper::GetInstance().Stop();
3520 #endif
3521
3522 #if defined(HAVE_LIBCRYSTALHD)
3523     CCrystalHD::RemoveInstance();
3524 #endif
3525
3526     g_mediaManager.Stop();
3527
3528     // Stop services before unloading Python
3529     CAddonMgr::Get().StopServices(false);
3530
3531     // stop all remaining scripts; must be done after skin has been unloaded,
3532     // not before some windows still need it when deinitializing during skin
3533     // unloading
3534     CScriptInvocationManager::Get().Uninitialize();
3535
3536     g_Windowing.DestroyRenderSystem();
3537     g_Windowing.DestroyWindow();
3538     g_Windowing.DestroyWindowSystem();
3539
3540     // shutdown the AudioEngine
3541     CAEFactory::Shutdown();
3542     CAEFactory::UnLoadEngine();
3543
3544     CLog::Log(LOGNOTICE, "stopped");
3545   }
3546   catch (...)
3547   {
3548     CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3549   }
3550
3551   // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3552   // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3553   Destroy();
3554
3555   //
3556   Sleep(200);
3557 }
3558
3559 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3560 {
3561   //If item is a plugin, expand out now and run ourselves again
3562   if (item.IsPlugin())
3563   {
3564     CFileItem item_new(item);
3565     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3566       return PlayMedia(item_new, iPlaylist);
3567     return false;
3568   }
3569   if (item.IsSmartPlayList())
3570   {
3571     CFileItemList items;
3572     CUtil::GetRecursiveListing(item.GetPath(), items, "");
3573     if (items.Size())
3574     {
3575       CSmartPlaylist smartpl;
3576       //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3577       smartpl.OpenAndReadName(item.GetPath());
3578       CPlayList playlist;
3579       playlist.Add(items);
3580       return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3581     }
3582   }
3583   else if (item.IsPlayList() || item.IsInternetStream())
3584   {
3585     CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3586
3587     //is or could be a playlist
3588     auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3589     bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3590
3591     if (dlgCache)
3592     {
3593        dlgCache->Close();
3594        if (dlgCache->IsCanceled())
3595           return true;
3596     }
3597
3598     if (gotPlayList)
3599     {
3600
3601       if (iPlaylist != PLAYLIST_NONE)
3602       {
3603         int track=0;
3604         if (item.HasProperty("playlist_starting_track"))
3605           track = (int)item.GetProperty("playlist_starting_track").asInteger();
3606         return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3607       }
3608       else
3609       {
3610         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());
3611         if(pPlayList->size())
3612           return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3613       }
3614     }
3615   }
3616
3617   //nothing special just play
3618   return PlayFile(item, false) == PLAYBACK_OK;
3619 }
3620
3621 // PlayStack()
3622 // For playing a multi-file video.  Particularly inefficient
3623 // on startup, as we are required to calculate the length
3624 // of each video, so we open + close each one in turn.
3625 // A faster calculation of video time would improve this
3626 // substantially.
3627 // return value: same with PlayFile()
3628 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3629 {
3630   if (!item.IsStack())
3631     return PLAYBACK_FAIL;
3632
3633   CVideoDatabase dbs;
3634
3635   // case 1: stacked ISOs
3636   if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3637   {
3638     CStackDirectory dir;
3639     CFileItemList movieList;
3640     dir.GetDirectory(item.GetPath(), movieList);
3641
3642     // first assume values passed to the stack
3643     int selectedFile = item.m_lStartPartNumber;
3644     int startoffset = item.m_lStartOffset;
3645
3646     // check if we instructed the stack to resume from default
3647     if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3648     {
3649       if (dbs.Open())
3650       {
3651         CBookmark bookmark;
3652         if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3653         {
3654           startoffset = (int)(bookmark.timeInSeconds*75);
3655           selectedFile = bookmark.partNumber;
3656         }
3657         dbs.Close();
3658       }
3659       else
3660         CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3661     }
3662
3663     // make sure that the selected part is within the boundaries
3664     if (selectedFile <= 0)
3665     {
3666       CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3667       selectedFile = 1;
3668     }
3669     else if (selectedFile > movieList.Size())
3670     {
3671       CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3672       selectedFile = movieList.Size();
3673     }
3674
3675     // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3676     movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3677     movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3678     *m_stackFileItemToUpdate = item;
3679     return PlayFile(*(movieList[selectedFile - 1]));
3680   }
3681   // case 2: all other stacks
3682   else
3683   {
3684     // see if we have the info in the database
3685     // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3686     //       then these times will be wrong.
3687     //       Also, this is really just a hack for the slow load up times we have
3688     //       A much better solution is a fast reader of FPS and fileLength
3689     //       that we can use on a file to get it's time.
3690     vector<int> times;
3691     bool haveTimes(false);
3692     CVideoDatabase dbs;
3693     if (dbs.Open())
3694     {
3695       dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3696       haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3697       dbs.Close();
3698     }
3699
3700
3701     // calculate the total time of the stack
3702     CStackDirectory dir;
3703     dir.GetDirectory(item.GetPath(), *m_currentStack);
3704     long totalTime = 0;
3705     for (int i = 0; i < m_currentStack->Size(); i++)
3706     {
3707       if (haveTimes)
3708         (*m_currentStack)[i]->m_lEndOffset = times[i];
3709       else
3710       {
3711         int duration;
3712         if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3713         {
3714           m_currentStack->Clear();
3715           return PLAYBACK_FAIL;
3716         }
3717         totalTime += duration / 1000;
3718         (*m_currentStack)[i]->m_lEndOffset = totalTime;
3719         times.push_back(totalTime);
3720       }
3721     }
3722
3723     double seconds = item.m_lStartOffset / 75.0;
3724
3725     if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3726     {  // have our times now, so update the dB
3727       if (dbs.Open())
3728       {
3729         if( !haveTimes )
3730           dbs.SetStackTimes(item.GetPath(), times);
3731
3732         if( item.m_lStartOffset == STARTOFFSET_RESUME )
3733         {
3734           // can only resume seek here, not dvdstate
3735           CBookmark bookmark;
3736           if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3737             seconds = bookmark.timeInSeconds;
3738           else
3739             seconds = 0.0f;
3740         }
3741         dbs.Close();
3742       }
3743     }
3744
3745     *m_itemCurrentFile = item;
3746     m_currentStackPosition = 0;
3747     m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3748
3749     if (seconds > 0)
3750     {
3751       // work out where to seek to
3752       for (int i = 0; i < m_currentStack->Size(); i++)
3753       {
3754         if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3755         {
3756           CFileItem item(*(*m_currentStack)[i]);
3757           long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3758           item.m_lStartOffset = (long)(seconds - start) * 75;
3759           m_currentStackPosition = i;
3760           return PlayFile(item, true);
3761         }
3762       }
3763     }
3764
3765     return PlayFile(*(*m_currentStack)[0], true);
3766   }
3767   return PLAYBACK_FAIL;
3768 }
3769
3770 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3771 {
3772   // Ensure the MIME type has been retrieved for http:// and shout:// streams
3773   if (item.GetMimeType().empty())
3774     const_cast<CFileItem&>(item).FillInMimeType();
3775
3776   if (!bRestart)
3777   {
3778     SaveCurrentFileSettings();
3779
3780     OutputDebugString("new file set audiostream:0\n");
3781     // Switch to default options
3782     CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3783     // see if we have saved options in the database
3784
3785     m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3786     m_pPlayer->m_iPlaySpeed = 1;     // Reset both CApp's & Player's speed else we'll get confused
3787
3788     *m_itemCurrentFile = item;
3789     m_nextPlaylistItem = -1;
3790     m_currentStackPosition = 0;
3791     m_currentStack->Clear();
3792
3793     if (item.IsVideo())
3794       CUtil::ClearSubtitles();
3795   }
3796
3797   if (item.IsDiscStub())
3798   {
3799 #ifdef HAS_DVD_DRIVE
3800     // Display the Play Eject dialog if there is any optical disc drive
3801     if (g_mediaManager.HasOpticalDrive())
3802     {
3803       if (CGUIDialogPlayEject::ShowAndGetInput(item))
3804         // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3805         // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3806         return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3807     }
3808     else
3809 #endif
3810       CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3811
3812     return PLAYBACK_OK;
3813   }
3814
3815   if (item.IsPlayList())
3816     return PLAYBACK_FAIL;
3817
3818   if (item.IsPlugin())
3819   { // we modify the item so that it becomes a real URL
3820     CFileItem item_new(item);
3821     if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3822       return PlayFile(item_new, false);
3823     return PLAYBACK_FAIL;
3824   }
3825
3826 #ifdef HAS_UPNP
3827   if (URIUtils::IsUPnP(item.GetPath()))
3828   {
3829     CFileItem item_new(item);
3830     if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3831       return PlayFile(item_new, false);
3832     return PLAYBACK_FAIL;
3833   }
3834 #endif
3835
3836   // if we have a stacked set of files, we need to setup our stack routines for
3837   // "seamless" seeking and total time of the movie etc.
3838   // will recall with restart set to true
3839   if (item.IsStack())
3840     return PlayStack(item, bRestart);
3841
3842   //Is TuxBox, this should probably be moved to CTuxBoxFile
3843   if(item.IsTuxBox())
3844   {
3845     CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3846
3847     if(g_tuxboxService.IsRunning())
3848       g_tuxboxService.Stop();
3849
3850     PlayBackRet ret = PLAYBACK_FAIL;
3851     CFileItem item_new;
3852     if(g_tuxbox.CreateNewItem(item, item_new))
3853     {
3854
3855       // Make sure it doesn't have a player
3856       // so we actually select one normally
3857       m_pPlayer->ResetPlayer();
3858
3859       // keep the tuxbox:// url as playing url
3860       // and give the new url to the player
3861       ret = PlayFile(item_new, true);
3862       if(ret == PLAYBACK_OK)
3863       {
3864         if(!g_tuxboxService.IsRunning())
3865           g_tuxboxService.Start();
3866       }
3867     }
3868     return ret;
3869   }
3870
3871   CPlayerOptions options;
3872
3873   if( item.HasProperty("StartPercent") )
3874   {
3875     double fallback = 0.0f;
3876     if(item.GetProperty("StartPercent").isString())
3877       fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3878     options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3879   }
3880
3881   PLAYERCOREID eNewCore = EPC_NONE;
3882   if( bRestart )
3883   {
3884     // have to be set here due to playstack using this for starting the file
3885     options.starttime = item.m_lStartOffset / 75.0;
3886     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3887       m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3888
3889     if( m_eForcedNextPlayer != EPC_NONE )
3890       eNewCore = m_eForcedNextPlayer;
3891     else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3892       eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3893     else
3894       eNewCore = m_pPlayer->GetCurrentPlayer();
3895   }
3896   else
3897   {
3898     options.starttime = item.m_lStartOffset / 75.0;
3899
3900     if (item.IsVideo())
3901     {
3902       // open the d/b and retrieve the bookmarks for the current movie
3903       CVideoDatabase dbs;
3904       dbs.Open();
3905       dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3906
3907       if( item.m_lStartOffset == STARTOFFSET_RESUME )
3908       {
3909         options.starttime = 0.0f;
3910         CBookmark bookmark;
3911         CStdString path = item.GetPath();
3912         if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3913           path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3914         else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3915           path = item.GetProperty("original_listitem_url").asString();
3916         if(dbs.GetResumeBookMark(path, bookmark))
3917         {
3918           options.starttime = bookmark.timeInSeconds;
3919           options.state = bookmark.playerState;
3920         }
3921         /*
3922          override with information from the actual item if available.  We do this as the VFS (eg plugins)
3923          may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3924          should the playerState be required, it is fetched from the database.
3925          See the note in CGUIWindowVideoBase::ShowResumeMenu.
3926          */
3927         if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3928           options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3929       }
3930       else if (item.HasVideoInfoTag())
3931       {
3932         const CVideoInfoTag *tag = item.GetVideoInfoTag();
3933
3934         if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3935         {
3936           CBookmark bookmark;
3937           dbs.GetBookMarkForEpisode(*tag, bookmark);
3938           options.starttime = bookmark.timeInSeconds;
3939           options.state = bookmark.playerState;
3940         }
3941       }
3942
3943       dbs.Close();
3944     }
3945
3946     if (m_eForcedNextPlayer != EPC_NONE)
3947       eNewCore = m_eForcedNextPlayer;
3948     else
3949       eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3950   }
3951
3952   // this really aught to be inside !bRestart, but since PlayStack
3953   // uses that to init playback, we have to keep it outside
3954   int playlist = g_playlistPlayer.GetCurrentPlaylist();
3955   if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3956   { // playing from a playlist by the looks
3957     // don't switch to fullscreen if we are not playing the first item...
3958     options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3959   }
3960   else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3961   {
3962     // TODO - this will fail if user seeks back to first file in stack
3963     if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3964       options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3965     else
3966       options.fullscreen = false;
3967     // reset this so we don't think we are resuming on seek
3968     m_itemCurrentFile->m_lStartOffset = 0;
3969   }
3970   else
3971     options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3972
3973   // reset VideoStartWindowed as it's a temp setting
3974   CMediaSettings::Get().SetVideoStartWindowed(false);
3975
3976 #ifdef HAS_KARAOKE
3977   //We have to stop parsing a cdg before mplayer is deallocated
3978   // WHY do we have to do this????
3979   if (m_pKaraokeMgr)
3980     m_pKaraokeMgr->Stop();
3981 #endif
3982
3983   {
3984     CSingleLock lock(m_playStateMutex);
3985     // tell system we are starting a file
3986     m_bPlaybackStarting = true;
3987     
3988     // for playing a new item, previous playing item's callback may already
3989     // pushed some delay message into the threadmessage list, they are not
3990     // expected be processed after or during the new item playback starting.
3991     // so we clean up previous playing item's playback callback delay messages here.
3992     int previousMsgsIgnoredByNewPlaying[] = {
3993       GUI_MSG_PLAYBACK_STARTED,
3994       GUI_MSG_PLAYBACK_ENDED,
3995       GUI_MSG_PLAYBACK_STOPPED,
3996       GUI_MSG_PLAYLIST_CHANGED,
3997       GUI_MSG_PLAYLISTPLAYER_STOPPED,
3998       GUI_MSG_PLAYLISTPLAYER_STARTED,
3999       GUI_MSG_PLAYLISTPLAYER_CHANGED,
4000       GUI_MSG_QUEUE_NEXT_ITEM,
4001       0
4002     };
4003     int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4004     if (dMsgCount > 0)
4005       CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4006   }
4007
4008   // We should restart the player, unless the previous and next tracks are using
4009   // one of the players that allows gapless playback (paplayer, dvdplayer)
4010   m_pPlayer->ClosePlayerGapless(eNewCore);
4011
4012   // now reset play state to starting, since we already stopped the previous playing item if there is.
4013   // and from now there should be no playback callback from previous playing item be called.
4014   m_ePlayState = PLAY_STATE_STARTING;
4015
4016   m_pPlayer->CreatePlayer(eNewCore, *this);
4017
4018   PlayBackRet iResult;
4019   if (m_pPlayer->HasPlayer())
4020   {
4021     /* When playing video pause any low priority jobs, they will be unpaused  when playback stops.
4022      * This should speed up player startup for files on internet filesystems (eg. webdav) and
4023      * increase performance on low powered systems (Atom/ARM).
4024      */
4025     if (item.IsVideo())
4026     {
4027       CJobManager::GetInstance().PauseJobs();
4028     }
4029
4030     // don't hold graphicscontext here since player
4031     // may wait on another thread, that requires gfx
4032     CSingleExit ex(g_graphicsContext);
4033
4034     iResult = m_pPlayer->OpenFile(item, options);
4035   }
4036   else
4037   {
4038     CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4039     iResult = PLAYBACK_FAIL;
4040   }
4041
4042   if(iResult == PLAYBACK_OK)
4043   {
4044     if (m_pPlayer->GetPlaySpeed() != 1)
4045     {
4046       int iSpeed = m_pPlayer->GetPlaySpeed();
4047       m_pPlayer->m_iPlaySpeed = 1;
4048       m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4049     }
4050
4051     // if player has volume control, set it.
4052     if (m_pPlayer->ControlsVolume())
4053     {
4054        m_pPlayer->SetVolume(m_volumeLevel);
4055        m_pPlayer->SetMute(m_muted);
4056     }
4057
4058     if( m_pPlayer->IsPlayingAudio() )
4059     {
4060       if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4061         g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4062     }
4063
4064 #ifdef HAS_VIDEO_PLAYBACK
4065     else if( m_pPlayer->IsPlayingVideo() )
4066     {
4067       if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4068         g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4069
4070       // if player didn't manange to switch to fullscreen by itself do it here
4071       if( options.fullscreen && g_renderManager.IsStarted()
4072        && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4073        SwitchToFullScreen();
4074     }
4075 #endif
4076     else
4077     {
4078       if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4079       ||  g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4080         g_windowManager.PreviousWindow();
4081
4082     }
4083
4084 #if !defined(TARGET_POSIX)
4085     g_audioManager.Enable(false);
4086 #endif
4087
4088     if (item.HasPVRChannelInfoTag())
4089       g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4090   }
4091
4092   CSingleLock lock(m_playStateMutex);
4093   m_bPlaybackStarting = false;
4094
4095   if (iResult == PLAYBACK_OK)
4096   {
4097     // play state: none, starting; playing; stopped; ended.
4098     // last 3 states are set by playback callback, they are all ignored during starting,
4099     // but we recorded the state, here we can make up the callback for the state.
4100     CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4101     switch (m_ePlayState)
4102     {
4103       case PLAY_STATE_PLAYING:
4104         OnPlayBackStarted();
4105         break;
4106       // FIXME: it seems no meaning to callback started here if there was an started callback
4107       //        before this stopped/ended callback we recorded. if we callback started here
4108       //        first, it will delay send OnPlay announce, but then we callback stopped/ended
4109       //        which will send OnStop announce at once, so currently, just call stopped/ended.
4110       case PLAY_STATE_ENDED:
4111         OnPlayBackEnded();
4112         break;
4113       case PLAY_STATE_STOPPED:
4114         OnPlayBackStopped();
4115         break;
4116       case PLAY_STATE_STARTING:
4117         // neither started nor stopped/ended callback be called, that means the item still
4118         // not started, we need not make up any callback, just leave this and
4119         // let the player callback do its work.
4120         break;
4121       default:
4122         break;
4123     }
4124   }
4125   else if (iResult == PLAYBACK_FAIL)
4126   {
4127     // we send this if it isn't playlistplayer that is doing this
4128     int next = g_playlistPlayer.GetNextSong();
4129     int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4130     if(next < 0
4131     || next >= size)
4132       OnPlayBackStopped();
4133     m_ePlayState = PLAY_STATE_NONE;
4134   }
4135
4136   return iResult;
4137 }
4138
4139 void CApplication::OnPlayBackEnded()
4140 {
4141   CSingleLock lock(m_playStateMutex);
4142   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4143   m_ePlayState = PLAY_STATE_ENDED;
4144   if(m_bPlaybackStarting)
4145     return;
4146
4147   // informs python script currently running playback has ended
4148   // (does nothing if python is not loaded)
4149 #ifdef HAS_PYTHON
4150   g_pythonParser.OnPlayBackEnded();
4151 #endif
4152
4153   CVariant data(CVariant::VariantTypeObject);
4154   data["end"] = true;
4155   CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4156
4157   CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4158   g_windowManager.SendThreadMessage(msg);
4159 }
4160
4161 void CApplication::OnPlayBackStarted()
4162 {
4163   CSingleLock lock(m_playStateMutex);
4164   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4165   m_ePlayState = PLAY_STATE_PLAYING;
4166   if(m_bPlaybackStarting)
4167     return;
4168
4169 #ifdef HAS_PYTHON
4170   // informs python script currently running playback has started
4171   // (does nothing if python is not loaded)
4172   g_pythonParser.OnPlayBackStarted();
4173 #endif
4174
4175   CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4176   g_windowManager.SendThreadMessage(msg);
4177 }
4178
4179 void CApplication::OnQueueNextItem()
4180 {
4181   CSingleLock lock(m_playStateMutex);
4182   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4183   if(m_bPlaybackStarting)
4184     return;
4185   // informs python script currently running that we are requesting the next track
4186   // (does nothing if python is not loaded)
4187 #ifdef HAS_PYTHON
4188   g_pythonParser.OnQueueNextItem(); // currently unimplemented
4189 #endif
4190
4191   CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4192   g_windowManager.SendThreadMessage(msg);
4193 }
4194
4195 void CApplication::OnPlayBackStopped()
4196 {
4197   CSingleLock lock(m_playStateMutex);
4198   CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4199   m_ePlayState = PLAY_STATE_STOPPED;
4200   if(m_bPlaybackStarting)
4201     return;
4202
4203   // informs python script currently running playback has ended
4204   // (does nothing if python is not loaded)
4205 #ifdef HAS_PYTHON
4206   g_pythonParser.OnPlayBackStopped();
4207 #endif
4208
4209   CVariant data(CVariant::VariantTypeObject);
4210   data["end"] = false;
4211   CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4212
4213   CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4214   g_windowManager.SendThreadMessage(msg);
4215 }
4216
4217 void CApplication::OnPlayBackPaused()
4218 {
4219 #ifdef HAS_PYTHON
4220   g_pythonParser.OnPlayBackPaused();
4221 #endif
4222
4223   CVariant param;
4224   param["player"]["speed"] = 0;
4225   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4226   CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4227 }
4228
4229 void CApplication::OnPlayBackResumed()
4230 {
4231 #ifdef HAS_PYTHON
4232   g_pythonParser.OnPlayBackResumed();
4233 #endif
4234
4235   CVariant param;
4236   param["player"]["speed"] = 1;
4237   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4238   CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4239 }
4240
4241 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4242 {
4243 #ifdef HAS_PYTHON
4244   g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4245 #endif
4246
4247   CVariant param;
4248   param["player"]["speed"] = iSpeed;
4249   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4250   CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4251 }
4252
4253 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4254 {
4255 #ifdef HAS_PYTHON
4256   g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4257 #endif
4258
4259   CVariant param;
4260   CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4261   CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4262   param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4263   param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4264   CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4265   g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4266 }
4267
4268 void CApplication::OnPlayBackSeekChapter(int iChapter)
4269 {
4270 #ifdef HAS_PYTHON
4271   g_pythonParser.OnPlayBackSeekChapter(iChapter);
4272 #endif
4273 }
4274
4275 bool CApplication::IsPlayingFullScreenVideo() const
4276 {
4277   return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4278 }
4279
4280 bool CApplication::IsFullScreen()
4281 {
4282   return IsPlayingFullScreenVideo() ||
4283         (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4284          g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4285 }
4286
4287 void CApplication::SaveFileState(bool bForeground /* = false */)
4288 {
4289   if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4290     return;
4291
4292   if (bForeground)
4293   {
4294     CSaveFileStateJob job(*m_progressTrackingItem,
4295     *m_stackFileItemToUpdate,
4296     m_progressTrackingVideoResumeBookmark,
4297     m_progressTrackingPlayCountUpdate);
4298
4299     // Run job in the foreground to make sure it finishes
4300     job.DoWork();
4301   }
4302   else
4303   {
4304     CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4305         *m_stackFileItemToUpdate,
4306         m_progressTrackingVideoResumeBookmark,
4307         m_progressTrackingPlayCountUpdate);
4308     CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4309   }
4310 }
4311
4312 void CApplication::UpdateFileState()
4313 {
4314   // Did the file change?
4315   if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4316   {
4317     SaveFileState();
4318
4319     // Reset tracking item
4320     m_progressTrackingItem->Reset();
4321   }
4322   else
4323   {
4324     if (m_pPlayer->IsPlaying())
4325     {
4326       if (m_progressTrackingItem->GetPath() == "")
4327       {
4328         // Init some stuff
4329         *m_progressTrackingItem = CurrentFileItem();
4330         m_progressTrackingPlayCountUpdate = false;
4331       }
4332
4333       if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4334           GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4335           (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4336           GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4337       {
4338         m_progressTrackingPlayCountUpdate = true;
4339       }
4340
4341       // Check whether we're *really* playing video else we may race when getting eg. stream details
4342       if (m_pPlayer->IsPlayingVideo())
4343       {
4344         /* Always update streamdetails, except for DVDs where we only update
4345            streamdetails if title length > 15m (Should yield more correct info) */
4346         if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4347         {
4348           CStreamDetails details;
4349           // Update with stream details from player, if any
4350           if (m_pPlayer->GetStreamDetails(details))
4351             m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4352
4353           if (m_progressTrackingItem->IsStack())
4354             m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4355         }
4356
4357         // Update bookmark for save
4358         m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4359         m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4360         m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4361
4362         if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4363             GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4364         {
4365           // Delete the bookmark
4366           m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4367         }
4368         else
4369         if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4370         {
4371           // Update the bookmark
4372           m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4373           m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4374         }
4375         else
4376         {
4377           // Do nothing
4378           m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4379         }
4380       }
4381     }
4382   }
4383 }
4384
4385 void CApplication::StopPlaying()
4386 {
4387   int iWin = g_windowManager.GetActiveWindow();
4388   if ( m_pPlayer->IsPlaying() )
4389   {
4390 #ifdef HAS_KARAOKE
4391     if( m_pKaraokeMgr )
4392       m_pKaraokeMgr->Stop();
4393 #endif
4394
4395     if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4396       g_PVRManager.SaveCurrentChannelSettings();
4397
4398     m_pPlayer->CloseFile();
4399
4400     // turn off visualisation window when stopping
4401     if ((iWin == WINDOW_VISUALISATION
4402     ||  iWin == WINDOW_FULLSCREEN_VIDEO)
4403     && !m_bStop)
4404       g_windowManager.PreviousWindow();
4405
4406     g_partyModeManager.Disable();
4407   }
4408 }
4409
4410 void CApplication::ResetSystemIdleTimer()
4411 {
4412   // reset system idle timer
4413   m_idleTimer.StartZero();
4414 }
4415
4416 void CApplication::ResetScreenSaver()
4417 {
4418   // reset our timers
4419   m_shutdownTimer.StartZero();
4420
4421   // screen saver timer is reset only if we're not already in screensaver or
4422   // DPMS mode
4423   if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4424     ResetScreenSaverTimer();
4425 }
4426
4427 void CApplication::ResetScreenSaverTimer()
4428 {
4429   m_screenSaverTimer.StartZero();
4430 }
4431
4432 void CApplication::StopScreenSaverTimer()
4433 {
4434   m_screenSaverTimer.Stop();
4435 }
4436
4437 bool CApplication::ToggleDPMS(bool manual)
4438 {
4439   if (manual || (m_dpmsIsManual == manual))
4440   {
4441     if (m_dpmsIsActive)
4442     {
4443       m_dpmsIsActive = false;
4444       m_dpmsIsManual = false;
4445       return m_dpms->DisablePowerSaving();
4446     }
4447     else
4448     {
4449       if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4450       {
4451         m_dpmsIsActive = true;
4452         m_dpmsIsManual = manual;
4453         return true;
4454       }
4455     }
4456   }
4457   return false;
4458 }
4459
4460 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4461 {
4462   bool result;
4463
4464   // First reset DPMS, if active
4465   if (m_dpmsIsActive)
4466   {
4467     if (m_dpmsIsManual)
4468       return false;
4469     // TODO: if screensaver lock is specified but screensaver is not active
4470     // (DPMS came first), activate screensaver now.
4471     ToggleDPMS(false);
4472     ResetScreenSaverTimer();
4473     result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4474   }
4475   else
4476     result = WakeUpScreenSaver(bPowerOffKeyPressed);
4477
4478   if(result)
4479   {
4480     // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4481     CVariant data(bPowerOffKeyPressed);
4482     CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4483   }
4484
4485   return result;
4486 }
4487
4488 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4489 {
4490   if (m_iScreenSaveLock == 2)
4491     return false;
4492
4493   // if Screen saver is active
4494   if (m_bScreenSave && m_screenSaver)
4495   {
4496     if (m_iScreenSaveLock == 0)
4497       if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4498           (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4499           CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4500           m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4501       {
4502         m_iScreenSaveLock = 2;
4503         CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4504
4505         CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4506         if (pWindow)
4507           pWindow->OnMessage(msg);
4508       }
4509     if (m_iScreenSaveLock == -1)
4510     {
4511       m_iScreenSaveLock = 0;
4512       return true;
4513     }
4514
4515     // disable screensaver
4516     m_bScreenSave = false;
4517     m_iScreenSaveLock = 0;
4518     ResetScreenSaverTimer();
4519
4520     if (m_screenSaver->ID() == "visualization")
4521     {
4522       // we can just continue as usual from vis mode
4523       return false;
4524     }
4525     else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4526       return true;
4527     else if (!m_screenSaver->ID().empty())
4528     { // we're in screensaver window
4529       if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4530         g_windowManager.PreviousWindow();  // show the previous window
4531       if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4532         CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4533     }
4534     return true;
4535   }
4536   else
4537     return false;
4538 }
4539
4540 void CApplication::CheckScreenSaverAndDPMS()
4541 {
4542   if (m_bInBackground)
4543     return;
4544   if (!m_dpmsIsActive)
4545     g_Windowing.ResetOSScreensaver();
4546
4547   bool maybeScreensaver =
4548       !m_dpmsIsActive && !m_bScreenSave
4549       && !CSettings::Get().GetString("screensaver.mode").empty();
4550   bool maybeDPMS =
4551       !m_dpmsIsActive && m_dpms->IsSupported()
4552       && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4553
4554   // Has the screen saver window become active?
4555   if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4556   {
4557     m_bScreenSave = true;
4558     maybeScreensaver = false;
4559   }
4560
4561   if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4562   {
4563     WakeUpScreenSaverAndDPMS();
4564     return;
4565   }
4566
4567   if (!maybeScreensaver && !maybeDPMS) return;  // Nothing to do.
4568
4569   // See if we need to reset timer.
4570   // * Are we playing a video and it is not paused?
4571   if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4572       // * Are we playing some music in fullscreen vis?
4573       || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4574           && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4575   {
4576     ResetScreenSaverTimer();
4577     return;
4578   }
4579
4580   float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4581
4582   // DPMS has priority (it makes the screensaver not needed)
4583   if (maybeDPMS
4584       && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4585   {
4586     ToggleDPMS(false);
4587     WakeUpScreenSaver();
4588   }
4589   else if (maybeScreensaver
4590            && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4591   {
4592     ActivateScreenSaver();
4593   }
4594 }
4595
4596 // activate the screensaver.
4597 // if forceType is true, we ignore the various conditions that can alter
4598 // the type of screensaver displayed
4599 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4600 {
4601   if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4602   { // just activate the visualisation if user toggled the usemusicvisinstead option
4603     g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4604     return;
4605   }
4606
4607   m_bScreenSave = true;
4608
4609   // Get Screensaver Mode
4610   m_screenSaver.reset();
4611   if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4612     m_screenSaver.reset(new CScreenSaver(""));
4613
4614   CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4615
4616   // disable screensaver lock from the login screen
4617   m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4618   if (!forceType)
4619   {
4620     // set to Dim in the case of a dialog on screen or playing video
4621     if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4622     {
4623       if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4624         m_screenSaver.reset(new CScreenSaver(""));
4625     }
4626   }
4627   if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4628     return;
4629   else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4630     return;
4631   else if (!m_screenSaver->ID().empty())
4632     g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4633 }
4634
4635 void CApplication::SetInBackground(bool background)
4636 {
4637   if (!background)
4638   {
4639     ResetScreenSaverTimer();
4640   }
4641   m_bInBackground = background;
4642 }
4643
4644 void CApplication::CheckShutdown()
4645 {
4646   // first check if we should reset the timer
4647   bool resetTimer = m_bInhibitIdleShutdown;
4648
4649   if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4650     resetTimer = true;
4651
4652   if (m_musicInfoScanner->IsScanning())
4653     resetTimer = true;
4654
4655   if (m_videoInfoScanner->IsScanning())
4656     resetTimer = true;
4657
4658   if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4659     resetTimer = true;
4660
4661   if (CSettings::Get().GetBool("pvrmanager.enabled") &&  !g_PVRManager.IsIdle())
4662     resetTimer = true;
4663
4664   if (resetTimer)
4665   {
4666     m_shutdownTimer.StartZero();
4667     return;
4668   }
4669
4670   if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4671   {
4672     // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4673     m_shutdownTimer.Stop();
4674
4675     // Sleep the box
4676     CApplicationMessenger::Get().Shutdown();
4677   }
4678 }
4679
4680 void CApplication::InhibitIdleShutdown(bool inhibit)
4681 {
4682   m_bInhibitIdleShutdown = inhibit;
4683 }
4684
4685 bool CApplication::IsIdleShutdownInhibited() const
4686 {
4687   return m_bInhibitIdleShutdown;
4688 }
4689
4690 bool CApplication::OnMessage(CGUIMessage& message)
4691 {
4692   switch ( message.GetMessage() )
4693   {
4694   case GUI_MSG_NOTIFY_ALL:
4695     {
4696       if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4697       {
4698         // Update general playlist: Remove DVD playlist items
4699         int nRemoved = g_playlistPlayer.RemoveDVDItems();
4700         if ( nRemoved > 0 )
4701         {
4702           CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4703           g_windowManager.SendMessage( msg );
4704         }
4705         // stop the file if it's on dvd (will set the resume point etc)
4706         if (m_itemCurrentFile->IsOnDVD())
4707           StopPlaying();
4708       }
4709     }
4710     break;
4711
4712   case GUI_MSG_PLAYBACK_STARTED:
4713     {
4714 #ifdef TARGET_DARWIN
4715       DarwinSetScheduling(message.GetMessage());
4716 #endif
4717       // reset the seek handler
4718       m_seekHandler->Reset();
4719       CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4720
4721       // Update our infoManager with the new details etc.
4722       if (m_nextPlaylistItem >= 0)
4723       { 
4724         // playing an item which is not in the list - player might be stopped already
4725         // so do nothing
4726         if (playList.size() <= m_nextPlaylistItem)
4727           return true;
4728
4729         // we've started a previously queued item
4730         CFileItemPtr item = playList[m_nextPlaylistItem];
4731         // update the playlist manager
4732         int currentSong = g_playlistPlayer.GetCurrentSong();
4733         int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4734         CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4735         g_windowManager.SendThreadMessage(msg);
4736         g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4737         *m_itemCurrentFile = *item;
4738       }
4739       g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4740       g_partyModeManager.OnSongChange(true);
4741
4742       CVariant param;
4743       param["player"]["speed"] = 1;
4744       param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4745       CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4746
4747       if (m_pPlayer->IsPlayingAudio())
4748       {
4749         // Start our cdg parser as appropriate
4750 #ifdef HAS_KARAOKE
4751         if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4752         {
4753           m_pKaraokeMgr->Stop();
4754           if (m_itemCurrentFile->IsMusicDb())
4755           {
4756             if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4757             {
4758               IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4759               tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4760               delete tagloader;
4761             }
4762             m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4763           }
4764           else
4765             m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4766         }
4767 #endif
4768       }
4769
4770       return true;
4771     }
4772     break;
4773
4774   case GUI_MSG_QUEUE_NEXT_ITEM:
4775     {
4776       // Check to see if our playlist player has a new item for us,
4777       // and if so, we check whether our current player wants the file
4778       int iNext = g_playlistPlayer.GetNextSong();
4779       CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4780       if (iNext < 0 || iNext >= playlist.size())
4781       {
4782         m_pPlayer->OnNothingToQueueNotify();
4783         return true; // nothing to do
4784       }
4785
4786       // ok, grab the next song
4787       CFileItem file(*playlist[iNext]);
4788       // handle plugin://
4789       CURL url(file.GetPath());
4790       if (url.GetProtocol() == "plugin")
4791         XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4792
4793 #ifdef HAS_UPNP
4794       if (URIUtils::IsUPnP(file.GetPath()))
4795       {
4796         if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4797           return true;
4798       }
4799 #endif
4800
4801       // ok - send the file to the player, if it accepts it
4802       if (m_pPlayer->QueueNextFile(file))
4803       {
4804         // player accepted the next file
4805         m_nextPlaylistItem = iNext;
4806       }
4807       else
4808       {
4809         /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4810             queue the next (if it wants to) and it doesn't keep looping on this song */
4811         g_playlistPlayer.SetCurrentSong(iNext);
4812       }
4813
4814       return true;
4815     }
4816     break;
4817
4818   case GUI_MSG_PLAYBACK_STOPPED:
4819   case GUI_MSG_PLAYBACK_ENDED:
4820   case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4821     {
4822 #ifdef HAS_KARAOKE
4823       if (m_pKaraokeMgr )
4824         m_pKaraokeMgr->Stop();
4825 #endif
4826 #ifdef TARGET_DARWIN
4827       DarwinSetScheduling(message.GetMessage());
4828 #endif
4829       // first check if we still have items in the stack to play
4830       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4831       {
4832         if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4833         { // just play the next item in the stack
4834           PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4835           return true;
4836         }
4837       }
4838
4839       // In case playback ended due to user eg. skipping over the end, clear
4840       // our resume bookmark here
4841       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4842       {
4843         // Delete the bookmark
4844         m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4845       }
4846
4847       // reset the current playing file
4848       m_itemCurrentFile->Reset();
4849       g_infoManager.ResetCurrentItem();
4850       m_currentStack->Clear();
4851
4852       if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4853       {
4854         g_playlistPlayer.PlayNext(1, true);
4855       }
4856       else
4857       {
4858         // reset any forced player
4859         m_eForcedNextPlayer = EPC_NONE;
4860
4861         m_pPlayer->ClosePlayer();
4862
4863         // Reset playspeed
4864         m_pPlayer->m_iPlaySpeed = 1;
4865       }
4866
4867       if (!m_pPlayer->IsPlaying())
4868       {
4869         g_audioManager.Enable(true);
4870       }
4871
4872       if (!m_pPlayer->IsPlayingVideo())
4873       {
4874         if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4875         {
4876           g_windowManager.PreviousWindow();
4877         }
4878         else
4879         {
4880           CSingleLock lock(g_graphicsContext);
4881           //  resets to res_desktop or look&feel resolution (including refreshrate)
4882           g_graphicsContext.SetFullScreenVideo(false);
4883         }
4884       }
4885
4886       if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4887       {
4888         CSettings::Get().Save();  // save vis settings
4889         WakeUpScreenSaverAndDPMS();
4890         g_windowManager.PreviousWindow();
4891       }
4892
4893       // DVD ejected while playing in vis ?
4894       if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4895       {
4896         // yes, disable vis
4897         CSettings::Get().Save();    // save vis settings
4898         WakeUpScreenSaverAndDPMS();
4899         g_windowManager.PreviousWindow();
4900       }
4901
4902       if (IsEnableTestMode())
4903         CApplicationMessenger::Get().Quit();
4904       return true;
4905     }
4906     break;
4907
4908   case GUI_MSG_PLAYLISTPLAYER_STARTED:
4909   case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4910     {
4911       return true;
4912     }
4913     break;
4914   case GUI_MSG_FULLSCREEN:
4915     { // Switch to fullscreen, if we can
4916       SwitchToFullScreen();
4917       return true;
4918     }
4919     break;
4920   case GUI_MSG_EXECUTE:
4921     if (message.GetNumStringParams())
4922       return ExecuteXBMCAction(message.GetStringParam());
4923     break;
4924   }
4925   return false;
4926 }
4927
4928 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4929 {
4930   // see if it is a user set string
4931
4932   //We don't know if there is unsecure information in this yet, so we
4933   //postpone any logging
4934   const std::string in_actionStr(actionStr);
4935   CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
4936   CGUIInfoLabel info(actionStr, "");
4937   actionStr = info.GetLabel(0);
4938
4939   // user has asked for something to be executed
4940   if (CBuiltins::HasCommand(actionStr))
4941     CBuiltins::Execute(actionStr);
4942   else
4943   {
4944     // try translating the action from our ButtonTranslator
4945     int actionID;
4946     if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4947     {
4948       OnAction(CAction(actionID));
4949       return true;
4950     }
4951     CFileItem item(actionStr, false);
4952 #ifdef HAS_PYTHON
4953     if (item.IsPythonScript())
4954     { // a python script
4955       CScriptInvocationManager::Get().Execute(item.GetPath());
4956     }
4957     else
4958 #endif
4959     if (item.IsAudio() || item.IsVideo())
4960     { // an audio or video file
4961       PlayFile(item);
4962     }
4963     else
4964     {
4965       //At this point we have given up to translate, so even though
4966       //there may be insecure information, we log it.
4967       CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
4968       return false;
4969     }
4970   }
4971   return true;
4972 }
4973
4974 void CApplication::Process()
4975 {
4976   MEASURE_FUNCTION;
4977
4978   // dispatch the messages generated by python or other threads to the current window
4979   g_windowManager.DispatchThreadMessages();
4980
4981   // process messages which have to be send to the gui
4982   // (this can only be done after g_windowManager.Render())
4983   CApplicationMessenger::Get().ProcessWindowMessages();
4984
4985   if (m_loggingIn)
4986   {
4987     m_loggingIn = false;
4988
4989     // autoexec.py - profile
4990     CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
4991
4992     if (XFILE::CFile::Exists(strAutoExecPy))
4993       CScriptInvocationManager::Get().Execute(strAutoExecPy);
4994     else
4995       CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
4996   }
4997
4998   // handle any active scripts
4999   CScriptInvocationManager::Get().Process();
5000
5001   // process messages, even if a movie is playing
5002   CApplicationMessenger::Get().ProcessMessages();
5003   if (g_application.m_bStop) return; //we're done, everything has been unloaded
5004
5005   // check how far we are through playing the current item
5006   // and do anything that needs doing (playcount updates etc)
5007   CheckPlayingProgress();
5008
5009   // update sound
5010   m_pPlayer->DoAudioWork();
5011
5012   // do any processing that isn't needed on each run
5013   if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5014   {
5015     m_slowTimer.Reset();
5016     ProcessSlow();
5017   }
5018
5019   g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5020 }
5021
5022 // We get called every 500ms
5023 void CApplication::ProcessSlow()
5024 {
5025   g_powerManager.ProcessEvents();
5026
5027 #if defined(TARGET_DARWIN_OSX)
5028   // There is an issue on OS X that several system services ask the cursor to become visible
5029   // during their startup routines.  Given that we can't control this, we hack it in by
5030   // forcing the
5031   if (g_Windowing.IsFullScreen())
5032   { // SDL thinks it's hidden
5033     Cocoa_HideMouse();
5034   }
5035 #endif
5036
5037   // Temporarely pause pausable jobs when viewing video/picture
5038   int currentWindow = g_windowManager.GetActiveWindow();
5039   if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5040   {
5041     CJobManager::GetInstance().PauseJobs();
5042   }
5043   else
5044   {
5045     CJobManager::GetInstance().UnPauseJobs();
5046   }
5047
5048   // Store our file state for use on close()
5049   UpdateFileState();
5050
5051   // Check if we need to activate the screensaver / DPMS.
5052   CheckScreenSaverAndDPMS();
5053
5054   // Check if we need to shutdown (if enabled).
5055 #if defined(TARGET_DARWIN)
5056   if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5057 #else
5058   if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5059 #endif
5060   {
5061     CheckShutdown();
5062   }
5063
5064   // check if we should restart the player
5065   CheckDelayedPlayerRestart();
5066
5067   //  check if we can unload any unreferenced dlls or sections
5068   if (!m_pPlayer->IsPlayingVideo())
5069     CSectionLoader::UnloadDelayed();
5070
5071   // check for any idle curl connections
5072   g_curlInterface.CheckIdle();
5073
5074   // check for any idle myth sessions
5075   CMythSession::CheckIdle();
5076
5077 #ifdef HAS_FILESYSTEM_HTSP
5078   // check for any idle htsp sessions
5079   HTSP::CHTSPDirectorySession::CheckIdle();
5080 #endif
5081
5082 #ifdef HAS_KARAOKE
5083   if ( m_pKaraokeMgr )
5084     m_pKaraokeMgr->ProcessSlow();
5085 #endif
5086
5087   if (!m_pPlayer->IsPlayingVideo())
5088     g_largeTextureManager.CleanupUnusedImages();
5089
5090   g_TextureManager.FreeUnusedTextures(5000);
5091
5092 #ifdef HAS_DVD_DRIVE
5093   // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5094   if (!m_pPlayer->IsPlayingVideo())
5095     m_Autorun->HandleAutorun();
5096 #endif
5097
5098   // update upnp server/renderer states
5099 #ifdef HAS_UPNP
5100   if(UPNP::CUPnP::IsInstantiated())
5101     UPNP::CUPnP::GetInstance()->UpdateState();
5102 #endif
5103
5104 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5105   smb.CheckIfIdle();
5106 #endif
5107
5108 #ifdef HAS_FILESYSTEM_NFS
5109   gNfsConnection.CheckIfIdle();
5110 #endif
5111
5112 #ifdef HAS_FILESYSTEM_AFP
5113   gAfpConnection.CheckIfIdle();
5114 #endif
5115
5116 #ifdef HAS_FILESYSTEM_SFTP
5117   CSFTPSessionManager::ClearOutIdleSessions();
5118 #endif
5119
5120   g_mediaManager.ProcessEvents();
5121
5122 #ifdef HAS_LIRC
5123   if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5124     g_RemoteControl.Initialize();
5125 #endif
5126
5127   if (!m_pPlayer->IsPlayingVideo())
5128     CAddonInstaller::Get().UpdateRepos();
5129
5130   CAEFactory::GarbageCollect();
5131 }
5132
5133 // Global Idle Time in Seconds
5134 // idle time will be resetet if on any OnKey()
5135 // int return: system Idle time in seconds! 0 is no idle!
5136 int CApplication::GlobalIdleTime()
5137 {
5138   if(!m_idleTimer.IsRunning())
5139   {
5140     m_idleTimer.Stop();
5141     m_idleTimer.StartZero();
5142   }
5143   return (int)m_idleTimer.GetElapsedSeconds();
5144 }
5145
5146 float CApplication::NavigationIdleTime()
5147 {
5148   if (!m_navigationTimer.IsRunning())
5149   {
5150     m_navigationTimer.Stop();
5151     m_navigationTimer.StartZero();
5152   }
5153   return m_navigationTimer.GetElapsedSeconds();
5154 }
5155
5156 void CApplication::DelayedPlayerRestart()
5157 {
5158   m_restartPlayerTimer.StartZero();
5159 }
5160
5161 void CApplication::CheckDelayedPlayerRestart()
5162 {
5163   if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5164   {
5165     m_restartPlayerTimer.Stop();
5166     m_restartPlayerTimer.Reset();
5167     Restart(true);
5168   }
5169 }
5170
5171 void CApplication::Restart(bool bSamePosition)
5172 {
5173   // this function gets called when the user changes a setting (like noninterleaved)
5174   // and which means we gotta close & reopen the current playing file
5175
5176   // first check if we're playing a file
5177   if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5178     return ;
5179
5180   if( !m_pPlayer->HasPlayer() )
5181     return ;
5182
5183   SaveFileState();
5184
5185   // do we want to return to the current position in the file
5186   if (false == bSamePosition)
5187   {
5188     // no, then just reopen the file and start at the beginning
5189     PlayFile(*m_itemCurrentFile, true);
5190     return ;
5191   }
5192
5193   // else get current position
5194   double time = GetTime();
5195
5196   // get player state, needed for dvd's
5197   CStdString state = m_pPlayer->GetPlayerState();
5198
5199   // set the requested starttime
5200   m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5201
5202   // reopen the file
5203   if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5204     m_pPlayer->SetPlayerState(state);
5205 }
5206
5207 const CStdString& CApplication::CurrentFile()
5208 {
5209   return m_itemCurrentFile->GetPath();
5210 }
5211
5212 CFileItem& CApplication::CurrentFileItem()
5213 {
5214   return *m_itemCurrentFile;
5215 }
5216
5217 void CApplication::ShowVolumeBar(const CAction *action)
5218 {
5219   CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5220   if (volumeBar)
5221   {
5222     volumeBar->Show();
5223     if (action)
5224       volumeBar->OnAction(*action);
5225   }
5226 }
5227
5228 bool CApplication::IsMuted() const
5229 {
5230   if (g_peripherals.IsMuted())
5231     return true;
5232   return CAEFactory::IsMuted();
5233 }
5234
5235 void CApplication::ToggleMute(void)
5236 {
5237   if (m_muted)
5238     UnMute();
5239   else
5240     Mute();
5241 }
5242
5243 void CApplication::SetMute(bool mute)
5244 {
5245   if (m_muted != mute)
5246   {
5247     ToggleMute();
5248     m_muted = mute;
5249   }
5250 }
5251
5252 void CApplication::Mute()
5253 {
5254   if (g_peripherals.Mute())
5255     return;
5256
5257   CAEFactory::SetMute(true);
5258   m_muted = true;
5259   VolumeChanged();
5260 }
5261
5262 void CApplication::UnMute()
5263 {
5264   if (g_peripherals.UnMute())
5265     return;
5266
5267   CAEFactory::SetMute(false);
5268   m_muted = false;
5269   VolumeChanged();
5270 }
5271
5272 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5273 {
5274   float hardwareVolume = iValue;
5275
5276   if(isPercentage)
5277     hardwareVolume /= 100.0f;
5278
5279   SetHardwareVolume(hardwareVolume);
5280   VolumeChanged();
5281 }
5282
5283 void CApplication::SetHardwareVolume(float hardwareVolume)
5284 {
5285   hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5286   m_volumeLevel = hardwareVolume;
5287
5288   float value = 0.0f;
5289   if (hardwareVolume > VOLUME_MINIMUM)
5290   {
5291     float dB = CAEUtil::PercentToGain(hardwareVolume);
5292     value = CAEUtil::GainToScale(dB);
5293   }
5294   if (value >= 0.99f)
5295     value = 1.0f;
5296
5297   CAEFactory::SetVolume(value);
5298 }
5299
5300 float CApplication::GetVolume(bool percentage /* = true */) const
5301 {
5302   if (percentage)
5303   {
5304     // converts the hardware volume to a percentage
5305     return m_volumeLevel * 100.0f;
5306   }
5307   
5308   return m_volumeLevel;
5309 }
5310
5311 void CApplication::VolumeChanged() const
5312 {
5313   CVariant data(CVariant::VariantTypeObject);
5314   data["volume"] = GetVolume();
5315   data["muted"] = m_muted;
5316   CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5317
5318   // if player has volume control, set it.
5319   if (m_pPlayer->ControlsVolume())
5320   {
5321      m_pPlayer->SetVolume(m_volumeLevel);
5322      m_pPlayer->SetMute(m_muted);
5323   }
5324 }
5325
5326 int CApplication::GetSubtitleDelay() const
5327 {
5328   // converts subtitle delay to a percentage
5329   return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5330 }
5331
5332 int CApplication::GetAudioDelay() const
5333 {
5334   // converts audio delay to a percentage
5335   return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5336 }
5337
5338 // Returns the total time in seconds of the current media.  Fractional
5339 // portions of a second are possible - but not necessarily supported by the
5340 // player class.  This returns a double to be consistent with GetTime() and
5341 // SeekTime().
5342 double CApplication::GetTotalTime() const
5343 {
5344   double rc = 0.0;
5345
5346   if (m_pPlayer->IsPlaying())
5347   {
5348     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5349       rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5350     else
5351       rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5352   }
5353
5354   return rc;
5355 }
5356
5357 void CApplication::StopShutdownTimer()
5358 {
5359   if (m_shutdownTimer.IsRunning())
5360     m_shutdownTimer.Stop();
5361 }
5362
5363 void CApplication::ResetShutdownTimers()
5364 {
5365   // reset system shutdown timer
5366   m_shutdownTimer.StartZero();
5367
5368   // delete custom shutdown timer
5369   if (g_alarmClock.HasAlarm("shutdowntimer"))
5370     g_alarmClock.Stop("shutdowntimer", true);
5371 }
5372
5373 // Returns the current time in seconds of the currently playing media.
5374 // Fractional portions of a second are possible.  This returns a double to
5375 // be consistent with GetTotalTime() and SeekTime().
5376 double CApplication::GetTime() const
5377 {
5378   double rc = 0.0;
5379
5380   if (m_pPlayer->IsPlaying())
5381   {
5382     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5383     {
5384       long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5385       rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5386     }
5387     else
5388       rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5389   }
5390
5391   return rc;
5392 }
5393
5394 // Sets the current position of the currently playing media to the specified
5395 // time in seconds.  Fractional portions of a second are valid.  The passed
5396 // time is the time offset from the beginning of the file as opposed to a
5397 // delta from the current position.  This method accepts a double to be
5398 // consistent with GetTime() and GetTotalTime().
5399 void CApplication::SeekTime( double dTime )
5400 {
5401   if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5402   {
5403     if (!m_pPlayer->CanSeek()) return;
5404     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5405     {
5406       // find the item in the stack we are seeking to, and load the new
5407       // file if necessary, and calculate the correct seek within the new
5408       // file.  Otherwise, just fall through to the usual routine if the
5409       // time is higher than our total time.
5410       for (int i = 0; i < m_currentStack->Size(); i++)
5411       {
5412         if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5413         {
5414           long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5415           if (m_currentStackPosition == i)
5416             m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5417           else
5418           { // seeking to a new file
5419             m_currentStackPosition = i;
5420             CFileItem item(*(*m_currentStack)[i]);
5421             item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5422             // don't just call "PlayFile" here, as we are quite likely called from the
5423             // player thread, so we won't be able to delete ourselves.
5424             CApplicationMessenger::Get().PlayFile(item, true);
5425           }
5426           return;
5427         }
5428       }
5429     }
5430     // convert to milliseconds and perform seek
5431     m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5432   }
5433 }
5434
5435 float CApplication::GetPercentage() const
5436 {
5437   if (m_pPlayer->IsPlaying())
5438   {
5439     if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5440     {
5441       const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5442       if (tag.GetDuration() > 0)
5443         return (float)(GetTime() / tag.GetDuration() * 100);
5444     }
5445
5446     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5447     {
5448       double totalTime = GetTotalTime();
5449       if (totalTime > 0.0f)
5450         return (float)(GetTime() / totalTime * 100);
5451     }
5452     else
5453       return m_pPlayer->GetPercentage();
5454   }
5455   return 0.0f;
5456 }
5457
5458 float CApplication::GetCachePercentage() const
5459 {
5460   if (m_pPlayer->IsPlaying())
5461   {
5462     // Note that the player returns a relative cache percentage and we want an absolute percentage
5463     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5464     {
5465       float stackedTotalTime = (float) GetTotalTime();
5466       // We need to take into account the stack's total time vs. currently playing file's total time
5467       if (stackedTotalTime > 0.0f)
5468         return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5469     }
5470     else
5471       return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5472   }
5473   return 0.0f;
5474 }
5475
5476 void CApplication::SeekPercentage(float percent)
5477 {
5478   if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5479   {
5480     if (!m_pPlayer->CanSeek()) return;
5481     if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5482       SeekTime(percent * 0.01 * GetTotalTime());
5483     else
5484       m_pPlayer->SeekPercentage(percent);
5485   }
5486 }
5487
5488 // SwitchToFullScreen() returns true if a switch is made, else returns false
5489 bool CApplication::SwitchToFullScreen()
5490 {
5491   // if playing from the video info window, close it first!
5492   if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5493   {
5494     CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5495     if (pDialog) pDialog->Close(true);
5496   }
5497
5498   // don't switch if there is a dialog on screen or the slideshow is active
5499   if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5500     return false;
5501
5502   // See if we're playing a video, and are in GUI mode
5503   if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5504   {
5505     // then switch to fullscreen mode
5506     g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5507     return true;
5508   }
5509   // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5510   if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5511   { // then switch to visualisation
5512     g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5513     return true;
5514   }
5515   return false;
5516 }
5517
5518 void CApplication::Minimize()
5519 {
5520   g_Windowing.Minimize();
5521 }
5522
5523 PLAYERCOREID CApplication::GetCurrentPlayer()
5524 {
5525   return m_pPlayer->GetCurrentPlayer();
5526 }
5527
5528 void CApplication::UpdateLibraries()
5529 {
5530   if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5531   {
5532     CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5533     StartVideoScan("");
5534   }
5535
5536   if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5537   {
5538     CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5539     StartMusicScan("");
5540   }
5541 }
5542
5543 bool CApplication::IsVideoScanning() const
5544 {
5545   return m_videoInfoScanner->IsScanning();
5546 }
5547
5548 bool CApplication::IsMusicScanning() const
5549 {
5550   return m_musicInfoScanner->IsScanning();
5551 }
5552
5553 void CApplication::StopVideoScan()
5554 {
5555   if (m_videoInfoScanner->IsScanning())
5556     m_videoInfoScanner->Stop();
5557 }
5558
5559 void CApplication::StopMusicScan()
5560 {
5561   if (m_musicInfoScanner->IsScanning())
5562     m_musicInfoScanner->Stop();
5563 }
5564
5565 void CApplication::StartVideoCleanup()
5566 {
5567   if (m_videoInfoScanner->IsScanning())
5568     return;
5569
5570   m_videoInfoScanner->CleanDatabase();
5571 }
5572
5573 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5574 {
5575   if (m_videoInfoScanner->IsScanning())
5576     return;
5577
5578   m_videoInfoScanner->ShowDialog(true);
5579
5580   m_videoInfoScanner->Start(strDirectory,scanAll);
5581 }
5582
5583 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5584 {
5585   if (m_musicInfoScanner->IsScanning())
5586     return;
5587
5588   if (!flags)
5589   { // setup default flags
5590     if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5591       flags |= CMusicInfoScanner::SCAN_ONLINE;
5592     if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5593       flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5594   }
5595
5596   if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5597     m_musicInfoScanner->ShowDialog(true);
5598
5599   m_musicInfoScanner->Start(strDirectory, flags);
5600 }
5601
5602 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5603                                        bool refresh)
5604 {
5605   if (m_musicInfoScanner->IsScanning())
5606     return;
5607
5608   m_musicInfoScanner->ShowDialog(true);
5609
5610   m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5611 }
5612
5613 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5614                                         bool refresh)
5615 {
5616   if (m_musicInfoScanner->IsScanning())
5617     return;
5618
5619   m_musicInfoScanner->ShowDialog(true);
5620
5621   m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5622 }
5623
5624 void CApplication::CheckPlayingProgress()
5625 {
5626   // check if we haven't rewound past the start of the file
5627   if (m_pPlayer->IsPlaying())
5628   {
5629     int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5630     if (iSpeed < 1)
5631     {
5632       iSpeed *= -1;
5633       int iPower = 0;
5634       while (iSpeed != 1)
5635       {
5636         iSpeed >>= 1;
5637         iPower++;
5638       }
5639       if (g_infoManager.GetPlayTime() / 1000 < iPower)
5640       {
5641         g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5642         g_application.SeekTime(0);
5643       }
5644     }
5645   }
5646 }
5647
5648 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5649 {
5650   CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5651
5652   // initial exit conditions
5653   // no songs in playlist just return
5654   if (playlist.size() == 0)
5655     return false;
5656
5657   // illegal playlist
5658   if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5659     return false;
5660
5661   // setup correct playlist
5662   g_playlistPlayer.ClearPlaylist(iPlaylist);
5663
5664   // if the playlist contains an internet stream, this file will be used
5665   // to generate a thumbnail for musicplayer.cover
5666   g_application.m_strPlayListFile = strPlayList;
5667
5668   // add the items to the playlist player
5669   g_playlistPlayer.Add(iPlaylist, playlist);
5670
5671   // if we have a playlist
5672   if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5673   {
5674     // start playing it
5675     g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5676     g_playlistPlayer.Reset();
5677     g_playlistPlayer.Play(track);
5678     return true;
5679   }
5680   return false;
5681 }
5682
5683 void CApplication::SaveCurrentFileSettings()
5684 {
5685   // don't store settings for PVR in video database
5686   if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5687   {
5688     // save video settings
5689     if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5690     {
5691       CVideoDatabase dbs;
5692       dbs.Open();
5693       dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5694       dbs.Close();
5695     }
5696   }
5697   else if (m_itemCurrentFile->IsPVRChannel())
5698   {
5699     g_PVRManager.SaveCurrentChannelSettings();
5700   }
5701 }
5702
5703 bool CApplication::AlwaysProcess(const CAction& action)
5704 {
5705   // check if this button is mapped to a built-in function
5706   if (!action.GetName().empty())
5707   {
5708     CStdString builtInFunction;
5709     vector<CStdString> params;
5710     CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5711     StringUtils::ToLower(builtInFunction);
5712
5713     // should this button be handled normally or just cancel the screensaver?
5714     if (   builtInFunction.Equals("powerdown")
5715         || builtInFunction.Equals("reboot")
5716         || builtInFunction.Equals("restart")
5717         || builtInFunction.Equals("restartapp")
5718         || builtInFunction.Equals("suspend")
5719         || builtInFunction.Equals("hibernate")
5720         || builtInFunction.Equals("quit")
5721         || builtInFunction.Equals("shutdown"))
5722     {
5723       return true;
5724     }
5725   }
5726
5727   return false;
5728 }
5729
5730 bool CApplication::IsCurrentThread() const
5731 {
5732   return CThread::IsCurrentThread(m_threadID);
5733 }
5734
5735 void CApplication::SetRenderGUI(bool renderGUI)
5736 {
5737   if (renderGUI && ! m_renderGUI)
5738     g_windowManager.MarkDirty();
5739   m_renderGUI = renderGUI;
5740 }
5741
5742 CNetwork& CApplication::getNetwork()
5743 {
5744   return *m_network;
5745 }
5746 #ifdef HAS_PERFORMANCE_SAMPLE
5747 CPerformanceStats &CApplication::GetPerformanceStats()
5748 {
5749   return m_perfStats;
5750 }
5751 #endif
5752
5753 bool CApplication::SetLanguage(const CStdString &strLanguage)
5754 {
5755   CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5756   CStdString strNewLanguage = strLanguage;
5757   if (strNewLanguage != strPreviousLanguage)
5758   {
5759     CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5760     if (!g_langInfo.Load(strLangInfoPath))
5761       return false;
5762
5763     if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5764     {
5765       CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5766       CStdString strFontSet;
5767       if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5768         strNewLanguage = strFontSet;
5769       else
5770         CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5771     }
5772     CSettings::Get().SetString("locale.language", strNewLanguage);
5773
5774     if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5775       return false;
5776
5777     // also tell our weather and skin to reload as these are localized
5778     g_weatherManager.Refresh();
5779     g_PVRManager.LocalizationChanged();
5780     ReloadSkin();
5781   }
5782
5783   return true;
5784 }
5785
5786 void CApplication::CloseNetworkShares()
5787 {
5788   CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5789
5790 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5791   smb.Deinit();
5792 #endif
5793   
5794 #ifdef HAS_FILESYSTEM_NFS
5795   gNfsConnection.Deinit();
5796 #endif
5797   
5798 #ifdef HAS_FILESYSTEM_AFP
5799   gAfpConnection.Deinit();
5800 #endif
5801   
5802 #ifdef HAS_FILESYSTEM_SFTP
5803   CSFTPSessionManager::DisconnectAllSessions();
5804 #endif
5805 }