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