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