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