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