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