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