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