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