2 * Copyright (C) 2005-2013 Team XBMC
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)
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.
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/>.
21 #include "network/Network.h"
22 #include "threads/SystemClock.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
29 #include "utils/Screenshot.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"
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"
52 #include "interfaces/python/XBPython.h"
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"
71 #ifdef HAS_FILESYSTEM_HTSP
72 #include "filesystem/HTSPDirectory.h"
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"
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"
101 #include "input/KeyboardStat.h"
102 #include "input/XBMC_vkeys.h"
103 #include "input/MouseStat.h"
109 #if defined(FILESYSTEM) && !defined(TARGET_POSIX)
110 #include "filesystem/FileDAAP.h"
113 #include "network/upnp/UPnP.h"
114 #include "network/upnp/UPnPSettings.h"
115 #include "filesystem/UPnPDirectory.h"
117 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
118 #include "filesystem/SMBDirectory.h"
120 #ifdef HAS_FILESYSTEM_NFS
121 #include "filesystem/NFSFile.h"
123 #ifdef HAS_FILESYSTEM_AFP
124 #include "filesystem/AFPFile.h"
126 #ifdef HAS_FILESYSTEM_SFTP
127 #include "filesystem/SFTPFile.h"
129 #include "PartyModeManager.h"
130 #ifdef HAS_VIDEO_PLAYBACK
131 #include "cores/VideoRenderers/RenderManager.h"
134 #include "music/karaoke/karaokelyricsmanager.h"
135 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
136 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
138 #include "network/Zeroconf.h"
139 #include "network/ZeroconfBrowser.h"
141 #include "threads/platform/win/Win32Exception.h"
143 #ifdef HAS_EVENT_SERVER
144 #include "network/EventServer.h"
147 #include <dbus/dbus.h>
150 #include "interfaces/json-rpc/JSONRPC.h"
151 #include "network/TCPServer.h"
154 #include "network/AirPlayServer.h"
157 #include "network/AirTunesServer.h"
159 #if defined(HAVE_LIBCRYSTALHD)
160 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
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"
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"
185 #include "rendering/gl/GUIWindowTestPatternGL.h"
188 #include "rendering/dx/GUIWindowTestPatternDX.h"
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"
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"
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"
267 #include "epg/EpgContainer.h"
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"
280 #ifdef HAS_PERFORMANCE_SAMPLE
281 #include "utils/PerformanceSample.h"
283 #define MEASURE_FUNCTION
286 #ifdef TARGET_WINDOWS
288 #include "win32util.h"
291 #include "windowing/X11/XRandR.h"
294 #ifdef TARGET_DARWIN_OSX
295 #include "osx/CocoaInterface.h"
296 #include "osx/XBMCHelper.h"
299 #include "osx/DarwinUtils.h"
304 #include <cdio/logging.h>
308 #include "linux/HALManager.h"
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"
325 #include "input/linux/LIRC.h"
327 #ifdef HAS_IRSERVERSUITE
328 #include "input/windows/IRServerSuite.h"
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"
337 #if defined(TARGET_ANDROID)
338 #include "android/activity/XBMCApp.h"
339 #include "android/activity/AndroidFeatures.h"
340 #include "android/jni/Build.h"
343 #ifdef TARGET_WINDOWS
344 #include "utils/Environment.h"
347 #if defined(HAS_LIBAMCODEC)
348 #include "utils/AMLUtils.h"
352 using namespace ADDON;
353 using namespace XFILE;
355 using namespace MEDIA_DETECT;
357 using namespace PLAYLIST;
358 using namespace VIDEO;
359 using namespace MUSIC_INFO;
360 #ifdef HAS_EVENT_SERVER
361 using namespace EVENTSERVER;
364 using namespace JSONRPC;
366 using namespace ANNOUNCEMENT;
369 using namespace PERIPHERALS;
371 using namespace XbmcThreads;
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
377 #define MAX_FFWD_SPEED 5
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)
392 TiXmlBase::SetCondenseWhiteSpace(false);
393 m_bInhibitIdleShutdown = false;
394 m_bScreenSave = false;
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;
414 /* for now always keep this around */
416 m_pKaraokeMgr = new CKaraokeLyricsManager();
418 m_currentStack = new CFileItemList;
420 m_bPresentFrame = false;
421 m_bPlatformDirectories = true;
423 m_bStandalone = false;
424 m_bEnableLegacyRes = false;
425 m_bSystemScreenSaverEnable = false;
426 m_pInertialScrollingHandler = new CInertialScrollingHandler();
428 m_Autorun = new CAutorun();
433 m_progressTrackingPlayCountUpdate = false;
434 m_currentStackPosition = 0;
436 m_lastRenderTime = 0;
440 m_volumeLevel = 1.0f;
443 CApplication::~CApplication(void)
445 delete m_musicInfoScanner;
446 delete m_videoInfoScanner;
447 delete &m_progressTrackingVideoResumeBookmark;
451 delete m_currentStack;
454 delete m_pKaraokeMgr;
458 delete m_seekHandler;
459 delete m_playerController;
460 delete m_pInertialScrollingHandler;
464 bool CApplication::OnEvent(XBMC_Event& newEvent)
466 switch(newEvent.type)
469 if (!g_application.m_bStop)
470 CApplicationMessenger::Get().Quit();
473 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
476 g_Keyboard.ProcessKeyUp();
478 case XBMC_MOUSEBUTTONDOWN:
479 case XBMC_MOUSEBUTTONUP:
480 case XBMC_MOUSEMOTION:
481 g_Mouse.HandleEvent(newEvent);
482 g_application.ProcessMouse();
484 case XBMC_VIDEORESIZE:
485 if (!g_application.m_bInitializing &&
486 !g_advancedSettings.m_fullScreen)
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();
496 #ifdef TARGET_WINDOWS
497 if (g_advancedSettings.m_fullScreen)
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);
507 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
511 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
513 case XBMC_APPCOMMAND:
514 return g_application.OnAppCommand(newEvent.appcommand.action);
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));
522 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
523 actionId = newEvent.touch.action;
526 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
527 // change this if we have a dialog up
528 if (g_windowManager.HasModalDialog())
530 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
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);
536 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
540 if (iWin == WINDOW_FULLSCREEN_VIDEO)
542 // current active window is full screen video.
543 if (g_application.m_pPlayer->IsInMenu())
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);
548 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
550 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
551 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
553 // if no PVR specific action/mapping is found, fall back to default
555 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
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);
563 else // iWin != WINDOW_FULLSCREEN_VIDEO
564 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
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);
575 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
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)
580 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
581 CApplicationMessenger::Get().SendGUIMessage(msg);
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));
596 extern "C" void __stdcall init_emu_environ();
597 extern "C" void __stdcall update_emu_environ();
600 // Utility function used to copy files from the application bundle
601 // over to the user data directory in Application Support/XBMC.
603 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
605 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
606 if (!CFile::Exists(destPath))
608 // need to copy it across
609 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
610 CFile::Cache(srcPath, destPath);
614 void CApplication::Preflight()
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();
622 // run any platform preflight scripts.
623 #if defined(TARGET_DARWIN_OSX)
624 CStdString install_path;
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());
633 bool CApplication::Create()
635 #if defined(HAS_LINUX_NETWORK)
636 m_network = new CNetworkLinux();
637 #elif defined(HAS_WIN32_NETWORK)
638 m_network = new CNetworkWin32();
640 m_network = new CNetwork();
645 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
647 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
648 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
652 tzset(); // Initialize timezone information variables
655 // Grab a handle to our thread to be used later in identifying the render thread.
656 m_threadID = CThread::GetCurrentThreadId();
659 //floating point precision to 24 bits (faster performance)
660 _controlfp(_PC_24, _MCW_PC);
662 /* install win32 exception translator, win32 exceptions
663 * can now be caught using c++ try catch */
664 win32_exception::install_handler();
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();
672 inited = InitDirectoriesOSX();
674 inited = InitDirectoriesWin32();
676 // copy required files
677 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
678 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
679 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
681 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
683 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
684 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
688 // Init our DllLoaders emu env
691 CProfilesManager::Get().Load();
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());
697 /* Expand macro before stringify */
698 #define STR_MACRO(x) #x
699 #define XSTR_MACRO(x) STR_MACRO(x)
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__)
708 /* Note: this will not detect GCC + DragonEgg */
709 compilerStr = "llvm-gcc ";
711 compilerStr = "GCC ";
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);
717 compilerStr = "unknown compiler";
719 std::string buildType;
722 #elif defined(NDEBUG)
723 buildType = "Release";
725 buildType = "Unknown";
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());
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());
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");
750 #if defined(TARGET_ANDROID)
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());
758 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
759 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
761 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
763 CSpecialProtocol::LogPaths();
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, "-----------------------------------------------------------------------");
772 CStdString strExecutablePath;
773 CUtil::GetHomePath(strExecutablePath);
776 g_xrandr.LoadCustomModeLinesToAllOutputs();
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");
788 g_powerManager.Initialize();
790 // Load the AudioEngine before settings as they need to query the engine
791 if (!CAEFactory::LoadEngine())
793 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
797 // Initialize default Settings - don't move
798 CLog::Log(LOGNOTICE, "load settings...");
799 if (!CSettings::Get().Initialize())
802 g_powerManager.SetDefaults();
804 // load the actual values
805 if (!CSettings::Get().Load())
807 CLog::Log(LOGFATAL, "unable to load settings");
810 CSettings::Get().SetLoaded();
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();
820 update_emu_environ();//apply the GUI settings
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]);
826 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
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"));
833 CStdString strLanguagePath = "special://xbmc/language/";
835 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
836 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
838 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
842 // start the AudioEngine
843 if (!CAEFactory::StartEngine())
845 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
849 // restore AE's previous volume state
850 SetHardwareVolume(m_volumeLevel);
851 CAEFactory::SetMute (m_muted);
852 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
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");
860 // initialize the addon database (must be before the addon manager is init'd)
861 CDatabaseManager::Get().Initialize(true);
864 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
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())
871 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
874 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
875 g_RemoteControl.Initialize();
878 // set logging from debug add-on
880 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
882 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
884 g_peripherals.Initialise();
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"));
891 g_Keyboard.Initialize();
893 #if defined(TARGET_DARWIN_OSX)
894 // Configure and possible manually start the helper.
895 XBMCHelper::GetInstance().Configure();
898 CUtil::InitRandomSeed();
900 g_mediaManager.Initialize();
902 m_lastFrameTime = XbmcThreads::SystemClockMillis();
903 m_lastRenderTime = m_lastFrameTime;
907 bool CApplication::CreateGUI()
911 CLog::Log(LOGNOTICE, "Setup SDL");
913 /* Clean up on exit, exit on window close and interrupt */
916 uint32_t sdlFlags = 0;
918 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
919 sdlFlags |= SDL_INIT_VIDEO;
922 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
923 sdlFlags |= SDL_INIT_JOYSTICK;
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);
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);
942 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
943 g_Windowing.EnableSystemScreenSaver(false);
946 if (SDL_Init(sdlFlags) != 0)
948 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
951 #if defined(TARGET_DARWIN)
952 // SDL_Init will install a handler for segfaults, restore the default handler.
953 signal(SIGSEGV, SIG_DFL);
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())
962 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
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()))
971 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
972 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
975 // update the window resolution
976 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
978 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
979 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
981 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
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);
992 if (g_advancedSettings.m_splashImage)
994 CStdString strUserSplash = "special://home/media/Splash.png";
995 if (CFile::Exists(strUserSplash))
997 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
998 m_splash = new CSplash(strUserSplash);
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");
1008 // The key mappings may already have been loaded by a peripheral
1009 CLog::Log(LOGINFO, "load keymapping");
1010 if (!CButtonTranslator::GetInstance().Load())
1013 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1014 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1017 info.strMode.c_str());
1018 g_windowManager.Initialize();
1023 bool CApplication::InitWindow()
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))
1031 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1035 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1036 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1038 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1043 if (!g_Windowing.InitRenderSystem())
1045 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1048 // set GUI res and force the clear of the screen
1049 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1053 bool CApplication::DestroyWindow()
1055 return g_Windowing.DestroyWindow();
1058 bool CApplication::InitDirectoriesLinux()
1061 The following is the directory mapping for Platform Specific Mode:
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.
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.
1074 NOTE: All these root directories are lowercase. Some of the sub-directories
1075 might be mixed case.
1078 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1079 CStdString userName;
1081 userName = getenv("USER");
1085 CStdString userHome;
1087 userHome = getenv("HOME");
1091 CStdString xbmcBinPath, xbmcPath;
1092 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1093 xbmcPath = getenv("XBMC_HOME");
1095 if (xbmcPath.empty())
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")))
1102 /* Attempt to locate arch independent data files. */
1103 CUtil::GetHomePath(xbmcPath);
1104 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1106 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1112 /* Set some environment variables */
1113 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1114 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1116 if (m_bPlatformDirectories)
1118 // map our special drives
1119 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1120 CSpecialProtocol::SetXBMCPath(xbmcPath);
1121 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1122 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
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);
1130 URIUtils::AddSlashAtEnd(strTempPath);
1131 g_advancedSettings.m_logFolder = strTempPath;
1138 URIUtils::AddSlashAtEnd(xbmcPath);
1139 g_advancedSettings.m_logFolder = xbmcPath;
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"));
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);
1153 URIUtils::AddSlashAtEnd(strTempPath);
1154 g_advancedSettings.m_logFolder = strTempPath;
1163 bool CApplication::InitDirectoriesOSX()
1165 #if defined(TARGET_DARWIN)
1166 CStdString userName;
1168 userName = getenv("USER");
1172 CStdString userHome;
1174 userHome = getenv("HOME");
1178 CStdString xbmcPath;
1179 CUtil::GetHomePath(xbmcPath);
1180 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
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);
1188 // setup path to our internal dylibs so loader can find them
1189 CStdString frameworksPath = CUtil::GetFrameworksPath();
1190 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1192 // OSX always runs with m_bPlatformDirectories == true
1193 if (m_bPlatformDirectories)
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");
1202 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1203 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1206 // location for temp files
1207 #if defined(TARGET_DARWIN_IOS)
1208 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1210 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1211 CDirectory::Create(strTempPath);
1212 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1214 CSpecialProtocol::SetTempPath(strTempPath);
1216 // xbmc.log file location
1217 #if defined(TARGET_DARWIN_IOS)
1218 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1220 strTempPath = userHome + "/Library/Logs";
1222 URIUtils::AddSlashAtEnd(strTempPath);
1223 g_advancedSettings.m_logFolder = strTempPath;
1229 URIUtils::AddSlashAtEnd(xbmcPath);
1230 g_advancedSettings.m_logFolder = xbmcPath;
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"));
1237 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1238 CSpecialProtocol::SetTempPath(strTempPath);
1240 URIUtils::AddSlashAtEnd(strTempPath);
1241 g_advancedSettings.m_logFolder = strTempPath;
1250 bool CApplication::InitDirectoriesWin32()
1252 #ifdef TARGET_WINDOWS
1253 CStdString xbmcPath;
1255 CUtil::GetHomePath(xbmcPath);
1256 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1257 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1258 CSpecialProtocol::SetXBMCPath(xbmcPath);
1260 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1262 g_advancedSettings.m_logFolder = strWin32UserFolder;
1263 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1264 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1265 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1267 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1271 // Expand the DLL search path with our directories
1272 CWIN32Util::ExtendDllPath();
1280 void CApplication::CreateUserDirs()
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
1293 bool CApplication::Initialize()
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;
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)
1306 CDirectory::Create("special://xbmc/language");
1307 CDirectory::Create("special://xbmc/addons");
1308 CDirectory::Create("special://xbmc/sounds");
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();
1323 // initialize (and update as needed) our databases
1324 CDatabaseManager::Get().Initialize();
1328 // Init DPMS, before creating the corresponding setting control.
1329 m_dpms = new DPMSSupport();
1330 if (g_windowManager.Initialized())
1332 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
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);
1341 g_windowManager.Add(new CGUIWindowTestPatternGL);
1344 g_windowManager.Add(new CGUIWindowTestPatternDX);
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);
1372 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1373 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
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);
1397 g_windowManager.Add(new CGUIDialogLockSettings);
1399 g_windowManager.Add(new CGUIDialogContentSettings);
1401 g_windowManager.Add(new CGUIDialogPlayEject);
1403 g_windowManager.Add(new CGUIDialogPeripheralManager);
1404 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1406 g_windowManager.Add(new CGUIDialogMediaFilter);
1407 g_windowManager.Add(new CGUIDialogSubtitles);
1409 g_windowManager.Add(new CGUIWindowMusicPlayList);
1410 g_windowManager.Add(new CGUIWindowMusicSongs);
1411 g_windowManager.Add(new CGUIWindowMusicNav);
1412 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
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);
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);
1438 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
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);
1448 /* window id's 3000 - 3100 are reserved for python */
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))
1454 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1458 if (g_advancedSettings.m_splashImage)
1459 SAFE_DELETE(m_splash);
1461 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1462 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1463 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1465 g_passwordManager.CheckStartUpLock();
1468 // check if we should use the login screen
1469 if (CProfilesManager::Get().UsingLoginScreen())
1470 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1474 CJSONRPC::Initialize();
1476 ADDON::CAddonMgr::Get().StartServices(false);
1477 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1479 g_windowManager.ActivateWindow(WINDOW_HOME);
1480 StartPVRManager(true);
1484 StartPVRManager(false);
1485 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1488 CStereoscopicsManager::Get().Initialize();
1492 else //No GUI Created
1495 CJSONRPC::Initialize();
1497 ADDON::CAddonMgr::Get().StartServices(false);
1500 g_sysinfo.Refresh();
1502 CLog::Log(LOGINFO, "removing tempfiles");
1503 CUtil::RemoveTempFiles();
1505 if (!CProfilesManager::Get().UsingLoginScreen())
1511 m_slowTimer.StartZero();
1513 #if defined(HAVE_LIBCRYSTALHD)
1514 CCrystalHD::GetInstance();
1517 CAddonMgr::Get().StartServices(true);
1519 CLog::Log(LOGNOTICE, "initialize done");
1521 m_bInitializing = false;
1523 // reset our screensaver (starts timers etc.)
1526 #ifdef HAS_SDL_JOYSTICK
1527 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1528 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1534 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1540 // the callback will take care of starting/stopping webserver
1541 ret = CSettings::Get().SetBool("services.webserver", bStart);
1544 case ES_AIRPLAYSERVER:
1545 // the callback will take care of starting/stopping airplay
1546 ret = CSettings::Get().SetBool("services.airplay", bStart);
1549 case ES_JSONRPCSERVER:
1550 // the callback will take care of starting/stopping jsonrpc server
1551 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1555 // the callback will take care of starting/stopping upnp server
1556 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1559 case ES_UPNPRENDERER:
1560 // the callback will take care of starting/stopping upnp renderer
1561 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1564 case ES_EVENTSERVER:
1565 // the callback will take care of starting/stopping event server
1566 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1570 // the callback will take care of starting/stopping zeroconf
1571 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1578 CSettings::Get().Save();
1583 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1585 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1586 g_PVRManager.Start(true, bOpenPVRWindow);
1589 void CApplication::StopPVRManager()
1591 CLog::Log(LOGINFO, "stopping PVRManager");
1592 if (g_PVRManager.IsPlaying())
1594 g_PVRManager.Stop();
1595 g_EpgContainer.Stop();
1598 void CApplication::StartServices()
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);
1607 void CApplication::StopServices()
1609 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1611 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1612 CLog::Log(LOGNOTICE, "stop dvd detect media");
1613 m_DetectDVDType.StopThread();
1616 g_peripherals.Clear();
1619 void CApplication::OnSettingChanged(const CSetting *setting)
1621 if (setting == NULL)
1624 const std::string &settingId = setting->GetId();
1625 if (settingId == "lookandfeel.skin" ||
1626 settingId == "lookandfeel.font" ||
1627 settingId == "lookandfeel.skincolors")
1629 // if the skin changes and the current theme is not the default one, reset
1630 // the theme to the default value (which will also change lookandfeel.skincolors
1631 // which in turn will reload the skin. Similarly, if the current skin font is not
1632 // the default, reset it as well.
1633 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1634 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1635 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1636 CSettings::Get().SetString("lookandfeel.font", "Default");
1639 std::string builtin("ReloadSkin");
1640 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1641 builtin += "(confirm)";
1642 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1645 else if (settingId == "lookandfeel.skintheme")
1647 // also set the default color theme
1648 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1649 URIUtils::RemoveExtension(colorTheme);
1650 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1651 colorTheme = "defaults";
1653 // check if we have to change the skin color
1654 // if yes, it will trigger a call to ReloadSkin() in
1655 // it's OnSettingChanged() callback
1656 // if no we have to call ReloadSkin() ourselves
1657 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1658 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1660 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1662 else if (settingId == "lookandfeel.skinzoom")
1664 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1665 g_windowManager.SendThreadMessage(msg);
1667 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1669 // AE is master of audio settings and needs to be informed first
1670 CAEFactory::OnSettingsChange(settingId);
1672 if (settingId == "audiooutput.guisoundmode")
1674 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1676 // this tells player whether to open an audio stream passthrough or PCM
1677 // if this is changed, audio stream has to be reopened
1678 else if (settingId == "audiooutput.passthrough")
1680 CApplicationMessenger::Get().MediaRestart(false);
1683 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1684 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1685 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1686 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1687 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1688 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1689 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1690 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1693 void CApplication::OnSettingAction(const CSetting *setting)
1695 if (setting == NULL)
1698 const std::string &settingId = setting->GetId();
1699 if (settingId == "lookandfeel.skinsettings")
1700 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1701 else if (settingId == "screensaver.preview")
1702 ActivateScreenSaver(true);
1703 else if (settingId == "screensaver.settings")
1706 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1707 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1709 else if (settingId == "videoscreen.guicalibration")
1710 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1711 else if (settingId == "videoscreen.testpattern")
1712 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1715 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1717 if (setting == NULL)
1720 const std::string &settingId = setting->GetId();
1721 if (settingId == "audiooutput.channels")
1723 // check if this is an update from Eden
1724 if (oldSettingId != NULL && oldSettingNode != NULL &&
1725 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1728 CSettingInt* channels = (CSettingInt*)setting;
1729 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1730 ret = channels->SetValue(channels->GetValue() + 1);
1732 // let's just reset the audiodevice settings as well
1733 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1734 CAEFactory::VerifyOutputDevice(audiodevice, false);
1735 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1740 else if (settingId == "screensaver.mode")
1742 CSettingString *screensaverMode = (CSettingString*)setting;
1743 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1744 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1745 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1747 else if (settingId == "scrapers.musicvideosdefault")
1749 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1750 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1752 musicvideoScraper->Reset();
1756 #if defined(HAS_LIBAMCODEC)
1757 else if (settingId == "videoplayer.useamcodec")
1759 // Do not permit amcodec to be used on non-aml platforms.
1760 // The setting will be hidden but the default value is true,
1761 // so change it to false.
1764 CSettingBool *useamcodec = (CSettingBool*)setting;
1765 useamcodec->SetValue(false);
1769 #if defined(TARGET_ANDROID)
1770 else if (settingId == "videoplayer.usemediacodec")
1772 // Do not permit MediaCodec to be used Android platforms that do not have it.
1773 // The setting will be hidden but the default value is true,
1774 // so change it to false.
1775 if (CAndroidFeatures::GetVersion() < 16)
1777 CSettingBool *usemediacodec = (CSettingBool*)setting;
1778 usemediacodec->SetValue(false);
1781 else if (settingId == "videoplayer.usestagefright")
1783 CSettingBool *usestagefright = (CSettingBool*)setting;
1784 usestagefright->SetValue(false);
1791 bool CApplication::OnSettingsSaving() const
1793 // don't save settings when we're busy stopping the application
1794 // a lot of screens try to save settings on deinit and deinit is
1795 // called for every screen when the application is stopping
1802 void CApplication::ReloadSkin(bool confirm/*=false*/)
1804 m_skinReloading = false;
1805 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1807 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1808 g_windowManager.SendMessage(msg);
1810 // Reload the skin, restoring the previously focused control. We need this as
1811 // the window unload will reset all control states.
1813 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1815 iCtrlID = pWindow->GetFocusedControlID();
1817 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1821 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1822 if (pWindow && pWindow->HasSaveLastControl())
1824 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1825 pWindow->OnMessage(msg3);
1829 if (!m_skinReverting && confirm)
1832 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1834 m_skinReverting = true;
1835 if (oldSkin.empty())
1836 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1838 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1842 m_skinReverting = false;
1845 bool CApplication::Load(const TiXmlNode *settings)
1847 if (settings == NULL)
1850 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1851 if (audioElement != NULL)
1853 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1854 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1855 m_volumeLevel = VOLUME_MAXIMUM;
1861 bool CApplication::Save(TiXmlNode *settings) const
1863 if (settings == NULL)
1866 TiXmlElement volumeNode("audio");
1867 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1868 if (audioNode == NULL)
1871 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1872 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1877 bool CApplication::LoadSkin(const CStdString& skinID)
1879 if (m_skinReloading)
1883 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1885 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1891 void CApplication::LoadSkin(const SkinPtr& skin)
1893 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1896 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1897 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1902 if (!skin->HasSkinFile("Home.xml"))
1904 // failed to find home.xml
1905 // fallback to default skin
1906 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1908 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1909 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1910 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1915 bool bPreviousPlayingState=false;
1916 bool bPreviousRenderingState=false;
1917 if (g_application.m_pPlayer->IsPlayingVideo())
1919 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1920 if (bPreviousPlayingState)
1921 g_application.m_pPlayer->Pause();
1922 #ifdef HAS_VIDEO_PLAYBACK
1923 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1925 g_windowManager.ActivateWindow(WINDOW_HOME);
1926 bPreviousRenderingState = true;
1930 // close the music and video overlays (they're re-opened automatically later)
1931 CSingleLock lock(g_graphicsContext);
1933 // save the current window details
1934 int currentWindow = g_windowManager.GetActiveWindow();
1935 vector<int> currentModelessWindows;
1936 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1940 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1942 g_SkinInfo->Start();
1944 CLog::Log(LOGINFO, " load fonts for skin...");
1945 g_graphicsContext.SetMediaDir(skin->Path());
1946 g_directoryCache.ClearSubPaths(skin->Path());
1947 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1949 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1950 CStdString strFontSet;
1951 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1953 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1954 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1955 CSettings::Get().Save();
1958 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1960 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1962 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1964 // load in the skin strings
1965 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1966 URIUtils::AddSlashAtEnd(langPath);
1968 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1970 g_SkinInfo->LoadIncludes();
1973 start = CurrentHostCounter();
1975 CLog::Log(LOGINFO, " load new skin...");
1977 // Load the user windows
1981 end = CurrentHostCounter();
1982 freq = CurrentHostFrequency();
1983 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1985 CLog::Log(LOGINFO, " initialize new skin...");
1986 g_windowManager.AddMsgTarget(this);
1987 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1988 g_windowManager.AddMsgTarget(&g_infoManager);
1989 g_windowManager.AddMsgTarget(&g_fontManager);
1990 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1991 g_windowManager.SetCallback(*this);
1992 g_windowManager.Initialize();
1993 CTextureCache::Get().Initialize();
1994 g_audioManager.Enable(true);
1995 g_audioManager.Load();
1997 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1998 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2000 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2001 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2002 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2003 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2004 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2007 CLog::Log(LOGINFO, " skin loaded...");
2009 // leave the graphics lock
2013 if (currentWindow != WINDOW_INVALID)
2015 g_windowManager.ActivateWindow(currentWindow);
2016 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2018 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2019 if (dialog) dialog->Show();
2023 if (g_application.m_pPlayer->IsPlayingVideo())
2025 if (bPreviousPlayingState)
2026 g_application.m_pPlayer->Pause();
2027 if (bPreviousRenderingState)
2028 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2032 void CApplication::UnloadSkin(bool forReload /* = false */)
2034 m_skinReloading = forReload;
2036 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2038 g_audioManager.Enable(false);
2040 g_windowManager.DeInitialize();
2041 CTextureCache::Get().Deinitialize();
2043 // remove the skin-dependent window
2044 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2046 g_TextureManager.Cleanup();
2047 g_largeTextureManager.CleanupUnusedImages(true);
2049 g_fontManager.Clear();
2051 g_colorManager.Clear();
2053 g_infoManager.Clear();
2055 // The g_SkinInfo boost shared_ptr ought to be reset here
2056 // but there are too many places it's used without checking for NULL
2057 // and as a result a race condition on exit can cause a crash.
2060 bool CApplication::LoadUserWindows()
2062 // Start from wherever home.xml is
2063 std::vector<CStdString> vecSkinPath;
2064 g_SkinInfo->GetSkinPaths(vecSkinPath);
2065 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2067 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2068 CFileItemList items;
2069 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2071 for (int i = 0; i < items.Size(); ++i)
2073 if (items[i]->m_bIsFolder)
2075 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2076 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2078 CXBMCTinyXML xmlDoc;
2079 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2081 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2085 // Root element should be <window>
2086 TiXmlElement* pRootElement = xmlDoc.RootElement();
2087 CStdString strValue = pRootElement->Value();
2088 if (!strValue.Equals("window"))
2090 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2094 // Read the <type> element to get the window type to create
2095 // If no type is specified, create a CGUIWindow as default
2096 CGUIWindow* pWindow = NULL;
2098 if (pRootElement->Attribute("type"))
2099 strType = pRootElement->Attribute("type");
2102 const TiXmlNode *pType = pRootElement->FirstChild("type");
2103 if (pType && pType->FirstChild())
2104 strType = pType->FirstChild()->Value();
2106 int id = WINDOW_INVALID;
2107 if (!pRootElement->Attribute("id", &id))
2109 const TiXmlNode *pType = pRootElement->FirstChild("id");
2110 if (pType && pType->FirstChild())
2111 id = atol(pType->FirstChild()->Value());
2113 CStdString visibleCondition;
2114 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2116 if (strType.Equals("dialog"))
2117 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2118 else if (strType.Equals("submenu"))
2119 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2120 else if (strType.Equals("buttonmenu"))
2121 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2123 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2125 // Check to make sure the pointer isn't still null
2126 if (pWindow == NULL)
2128 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2131 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2136 pWindow->SetVisibleCondition(visibleCondition);
2137 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2138 g_windowManager.AddCustomWindow(pWindow);
2146 bool CApplication::RenderNoPresent()
2150 // DXMERGE: This may have been important?
2151 // g_graphicsContext.AcquireCurrentContext();
2153 g_graphicsContext.Lock();
2155 // dont show GUI when playing full screen video
2156 if (g_graphicsContext.IsFullScreenVideo())
2158 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2159 g_renderManager.Render(true, 0, 255);
2161 // close window overlays
2162 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2163 if (overlay) overlay->Close(true);
2164 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2165 if (overlay) overlay->Close(true);
2169 bool hasRendered = g_windowManager.Render();
2171 g_graphicsContext.Unlock();
2176 float CApplication::GetDimScreenSaverLevel() const
2178 if (!m_bScreenSave || !m_screenSaver ||
2179 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2180 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2181 !m_screenSaver->ID().empty()))
2184 if (!m_screenSaver->GetSetting("level").empty())
2185 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2189 void CApplication::Render()
2191 // do not render if we are stopped or in background
2197 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2199 bool hasRendered = false;
2200 bool limitFrames = false;
2201 unsigned int singleFrameTime = 10; // default limit 100 fps
2205 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2206 // Whether externalplayer is playing and we're unfocused
2207 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2209 m_bPresentFrame = false;
2210 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2212 m_bPresentFrame = g_renderManager.FrameWait(100);
2217 // engage the frame limiter as needed
2218 limitFrames = lowfps || extPlayerActive;
2219 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2220 // perhaps allowing it to be set differently than the UI option??
2221 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2222 limitFrames = true; // not using vsync.
2223 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2224 limitFrames = true; // using vsync, but it isn't working.
2228 if (extPlayerActive)
2230 ResetScreenSaver(); // Prevent screensaver dimming the screen
2231 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2234 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2240 CSingleLock lock(g_graphicsContext);
2241 g_infoManager.UpdateFPS();
2243 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2244 g_Windowing.SetVSync(true);
2245 else if (vsync_mode == VSYNC_ALWAYS)
2246 g_Windowing.SetVSync(true);
2247 else if (vsync_mode != VSYNC_DRIVER)
2248 g_Windowing.SetVSync(false);
2250 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2253 if(!g_Windowing.BeginRender())
2256 g_renderManager.FrameMove();
2258 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2259 if(g_graphicsContext.GetStereoMode())
2261 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2262 if(RenderNoPresent())
2265 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2267 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2268 if(RenderNoPresent())
2271 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2275 if(RenderNoPresent())
2279 g_renderManager.FrameFinish();
2281 g_Windowing.EndRender();
2283 // execute post rendering actions (finalize window closing)
2284 g_windowManager.AfterRender();
2286 // reset our info cache - we do this at the end of Render so that it is
2287 // fresh for the next process(), or after a windowclose animation (where process()
2289 g_infoManager.ResetCache();
2292 unsigned int now = XbmcThreads::SystemClockMillis();
2294 m_lastRenderTime = now;
2296 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2297 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2299 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2300 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2304 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2305 if (limitFrames || !flip)
2308 singleFrameTime = 40; //if not flipping, loop at 25 fps
2310 unsigned int frameTime = now - m_lastFrameTime;
2311 if (frameTime < singleFrameTime)
2312 Sleep(singleFrameTime - frameTime);
2314 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2317 g_graphicsContext.Flip(dirtyRegions);
2318 CTimeUtils::UpdateFrameTime(flip);
2320 g_renderManager.UpdateResolution();
2321 g_renderManager.ManageCaptures();
2324 void CApplication::SetStandAlone(bool value)
2326 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2329 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2330 // The window manager will return true if the event is processed, false otherwise.
2331 // If not already processed, this routine handles global keypresses. It returns
2332 // true if the key has been processed, false otherwise.
2334 bool CApplication::OnKey(const CKey& key)
2337 // Turn the mouse off, as we've just got a keypress from controller or remote
2338 g_Mouse.SetActive(false);
2340 // get the current active window
2341 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2343 // this will be checked for certain keycodes that need
2344 // special handling if the screensaver is active
2345 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2347 // a key has been pressed.
2349 m_idleTimer.StartZero();
2350 bool processKey = AlwaysProcess(action);
2352 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2356 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2357 // do not wake up the screensaver right after switching off the playing device
2358 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2359 ret = CApplicationMessenger::Get().CECToggleState();
2361 ret = CApplicationMessenger::Get().CECStandby();
2362 if (!ret) /* display is switched off */
2368 // allow some keys to be processed while the screensaver is active
2369 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2371 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2375 // change this if we have a dialog up
2376 if (g_windowManager.HasModalDialog())
2378 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2380 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2381 { // fullscreen info dialog - special case
2382 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2384 if (!key.IsAnalogButton())
2385 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2387 if (OnAction(action))
2390 // fallthrough to the main window
2391 iWin = WINDOW_FULLSCREEN_VIDEO;
2393 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2395 // current active window is full screen video.
2396 if (g_application.m_pPlayer->IsInMenu())
2398 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2399 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2401 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2403 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2404 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2406 // if no PVR specific action/mapping is found, fall back to default
2407 if (action.GetID() == 0)
2408 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2412 // in any other case use the fullscreen window section of keymap.xml to map key->action
2413 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2418 // current active window isnt the fullscreen window
2419 // just use corresponding section from keymap.xml
2420 // to map key->action
2422 // first determine if we should use keyboard input directly
2423 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2424 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2427 CGUIControl *control = window->GetFocusedControl();
2430 // If this is an edit control set usekeyboard to true. This causes the
2431 // keypress to be processed directly not through the key mappings.
2432 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2435 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2436 // This causes the keypress to be used for list navigation.
2437 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2443 action = CAction(0); // reset our action
2444 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2446 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2447 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2448 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2449 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2450 action.GetID() == ACTION_MOVE_RIGHT ||
2451 action.GetID() == ACTION_MOVE_UP ||
2452 action.GetID() == ACTION_MOVE_DOWN ||
2453 action.GetID() == ACTION_SELECT_ITEM ||
2454 action.GetID() == ACTION_ENTER ||
2455 action.GetID() == ACTION_PREVIOUS_MENU ||
2456 action.GetID() == ACTION_NAV_BACK))
2458 // the action isn't plain navigation - check for a keyboard-specific keymap
2459 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2460 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2461 action.GetID() == ACTION_BACKSPACE ||
2462 action.GetID() == ACTION_SHIFT ||
2463 action.GetID() == ACTION_SYMBOLS ||
2464 action.GetID() == ACTION_CURSOR_LEFT ||
2465 action.GetID() == ACTION_CURSOR_RIGHT)
2466 action = CAction(0); // don't bother with this action
2469 if (!action.GetID())
2471 // keyboard entry - pass the keys through directly
2472 if (key.GetFromService())
2473 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2476 // Check for paste keypress
2477 #ifdef TARGET_WINDOWS
2478 // In Windows paste is ctrl-V
2479 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2480 #elif defined(TARGET_LINUX)
2481 // In Linux paste is ctrl-V
2482 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2483 #elif defined(TARGET_DARWIN_OSX)
2484 // In OSX paste is cmd-V
2485 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2487 // Placeholder for other operating systems
2490 action = CAction(ACTION_PASTE);
2491 // If the unicode is non-zero the keypress is a non-printing character
2492 else if (key.GetUnicode())
2493 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2494 // The keypress is a non-printing character
2496 action = CAction(key.GetVKey() | KEY_VKEY);
2500 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2502 if (OnAction(action))
2504 // failed to handle the keyboard action, drop down through to standard action
2506 if (key.GetFromService())
2508 if (key.GetButtonCode() != KEY_INVALID)
2509 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2512 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2514 if (!key.IsAnalogButton())
2515 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2517 return ExecuteInputAction(action);
2520 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2521 // This needs to return true if it processed the appcommand or false if it didn't
2522 bool CApplication::OnAppCommand(const CAction &action)
2524 // Reset the screen saver
2527 // If we were currently in the screen saver wake up and don't process the appcommand
2528 if (WakeUpScreenSaverAndDPMS())
2531 // The action ID is the APPCOMMAND code. We need to retrieve the action
2532 // associated with this appcommand from the mapping table.
2533 uint32_t appcmd = action.GetID();
2534 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2535 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2536 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2538 // If we couldn't find an action return false to indicate we have not
2539 // handled this appcommand
2540 if (!appcmdaction.GetID())
2542 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2546 // Process the appcommand
2547 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2548 OnAction(appcmdaction);
2550 // Always return true regardless of whether the action succeeded or not.
2551 // This stops Windows handling the appcommand itself.
2555 bool CApplication::OnAction(const CAction &action)
2557 // special case for switching between GUI & fullscreen mode.
2558 if (action.GetID() == ACTION_SHOW_GUI)
2559 { // Switch to fullscreen mode if we can
2560 if (SwitchToFullScreen())
2562 m_navigationTimer.StartZero();
2567 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2569 g_graphicsContext.ToggleFullScreenRoot();
2573 if (action.IsMouse())
2574 g_Mouse.SetActive(true);
2577 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2579 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2581 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2583 CGUIDialogVideoBookmarks::OnAddBookmark();
2586 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2587 // playing or ACTION_PLAYER_PLAY if we are not playing.
2588 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2590 if (m_pPlayer->IsPlaying())
2591 return OnAction(CAction(ACTION_PAUSE));
2593 return OnAction(CAction(ACTION_PLAYER_PLAY));
2596 //if the action would start or stop inertial scrolling
2597 //by gesture - bypass the normal OnAction handler of current window
2598 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2601 // just pass the action to the current window and let it handle it
2602 if (g_windowManager.OnAction(action))
2604 m_navigationTimer.StartZero();
2609 // handle extra global presses
2611 // screenshot : take a screenshot :)
2612 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2614 CScreenShot::TakeScreenshot();
2617 // built in functions : execute the built-in
2618 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2620 CBuiltins::Execute(action.GetName());
2621 m_navigationTimer.StartZero();
2626 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2628 CButtonTranslator::GetInstance().Clear();
2629 CButtonTranslator::GetInstance().Load();
2632 // show info : Shows the current video or song information
2633 if (action.GetID() == ACTION_SHOW_INFO)
2635 g_infoManager.ToggleShowInfo();
2639 // codec info : Shows the current song, video or picture codec information
2640 if (action.GetID() == ACTION_SHOW_CODEC)
2642 g_infoManager.ToggleShowCodec();
2646 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2648 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2651 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2652 char rating = tag->GetRating();
2653 bool needsUpdate(false);
2654 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2656 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2659 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2661 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2667 if (db.Open()) // OpenForWrite() ?
2669 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2672 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2673 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2674 g_windowManager.SendMessage(msg);
2680 // Now check with the playlist player if action can be handled.
2681 // In case of the action PREV_ITEM, we only allow the playlist player to take it if we're less than 3 seconds into playback.
2682 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2684 if (g_playlistPlayer.OnAction(action))
2688 // Now check with the player if action can be handled.
2689 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2690 (g_windowManager.GetActiveWindow() == WINDOW_DIALOG_VIDEO_OSD && (action.GetID() == ACTION_NEXT_ITEM || action.GetID() == ACTION_PREV_ITEM || action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)) ||
2691 action.GetID() == ACTION_STOP)
2693 if (m_pPlayer->OnAction(action))
2695 // Player ignored action; popup the OSD
2696 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2697 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2698 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2701 // stop : stops playing current audio song
2702 if (action.GetID() == ACTION_STOP)
2708 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2709 // If so, we just jump to the start of the track.
2710 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2713 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2717 // forward action to g_PVRManager and break if it was able to handle it
2718 if (g_PVRManager.OnAction(action))
2721 // forward action to graphic context and see if it can handle it
2722 if (CStereoscopicsManager::Get().OnAction(action))
2725 if (m_pPlayer->IsPlaying())
2727 // forward channel switches to the player - he knows what to do
2728 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2730 m_pPlayer->OnAction(action);
2734 // pause : pauses current audio song
2735 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2739 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2741 if (!m_pPlayer->IsPaused())
2742 { // unpaused - set the playspeed back to normal
2743 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2745 g_audioManager.Enable(m_pPlayer->IsPaused());
2748 if (!m_pPlayer->IsPaused())
2750 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2751 // if we are playing at normal speed, then allow play to pause
2752 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2754 if (m_pPlayer->GetPlaySpeed() != 1)
2756 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2764 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2766 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2767 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2769 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2771 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2776 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2778 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2781 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2784 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2786 // calculate the speed based on the amount the button is held down
2787 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2788 // returns 0 -> MAX_FFWD_SPEED
2789 int iSpeed = 1 << iPower;
2790 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2792 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2794 CLog::Log(LOGDEBUG,"Resetting playspeed");
2798 // allow play to unpause
2801 if (action.GetID() == ACTION_PLAYER_PLAY)
2803 // unpause, and set the playspeed back to normal
2805 g_audioManager.Enable(m_pPlayer->IsPaused());
2807 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2812 // record current file
2813 if (action.GetID() == ACTION_RECORD)
2815 if (m_pPlayer->CanRecord())
2816 m_pPlayer->Record(!m_pPlayer->IsRecording());
2819 if (m_playerController->OnAction(action))
2824 if (action.GetID() == ACTION_SWITCH_PLAYER)
2826 if(m_pPlayer->IsPlaying())
2828 VECPLAYERCORES cores;
2829 CFileItem item(*m_itemCurrentFile.get());
2830 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2831 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2832 if(core != EPC_NONE)
2834 g_application.m_eForcedNextPlayer = core;
2835 item.m_lStartOffset = (int)(GetTime() * 75);
2836 PlayFile(item, true);
2841 VECPLAYERCORES cores;
2842 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2843 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2844 if(core != EPC_NONE)
2847 g_application.m_eForcedNextPlayer = core;
2848 PlayFile(item, false);
2853 if (g_peripherals.OnAction(action))
2856 if (action.GetID() == ACTION_MUTE)
2862 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2864 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2865 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2867 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2869 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2870 g_windowManager.SendMessage(msg);
2875 // Check for global volume control
2876 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2878 if (!m_pPlayer->IsPassthrough())
2882 float volume = m_volumeLevel;
2883 // Android has steps based on the max available volume level
2884 #if defined(TARGET_ANDROID)
2885 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2887 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2889 if (action.GetRepeat())
2890 step *= action.GetRepeat() * 50; // 50 fps
2892 if (action.GetID() == ACTION_VOLUME_UP)
2893 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2895 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2896 SetVolume(volume, false);
2898 // show visual feedback of volume change...
2899 ShowVolumeBar(&action);
2902 // Check for global seek control
2903 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2905 if (!m_pPlayer->CanSeek()) return false;
2906 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2909 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2911 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2912 CGUIControlProfiler::Instance().Start();
2915 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2917 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2918 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2919 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2920 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2921 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2927 void CApplication::FrameMove(bool processEvents, bool processGUI)
2933 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2934 float frameTime = m_frameTime.GetElapsedSeconds();
2935 m_frameTime.StartZero();
2936 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2937 if( frameTime > 0.5 ) frameTime = 0.5;
2939 if (processGUI && m_renderGUI)
2941 g_graphicsContext.Lock();
2942 // check if there are notifications to display
2943 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2944 if (toast && toast->DoWork())
2946 if (!toast->IsDialogRunning())
2951 g_graphicsContext.Unlock();
2953 CWinEvents::MessagePump();
2955 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2956 // Read the input from a remote
2957 g_RemoteControl.Update();
2960 // process input actions
2961 ProcessRemote(frameTime);
2962 ProcessGamepad(frameTime);
2963 ProcessEventServer(frameTime);
2964 ProcessPeripherals(frameTime);
2965 if (processGUI && m_renderGUI)
2967 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2968 m_seekHandler->Process();
2971 if (processGUI && m_renderGUI)
2974 g_windowManager.Process(CTimeUtils::GetFrameTime());
2975 g_windowManager.FrameMove();
2979 bool CApplication::ProcessGamepad(float frameTime)
2981 #ifdef HAS_SDL_JOYSTICK
2985 int iWin = GetActiveWindowID();
2987 g_Joystick.Update();
2988 if (g_Joystick.GetButton(bid))
2991 m_idleTimer.StartZero();
2994 if (WakeUpScreenSaverAndDPMS())
2996 g_Joystick.Reset(true);
3001 CStdString actionName;
3003 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3005 CAction action(actionID, 1.0f, 0.0f, actionName);
3007 g_Mouse.SetActive(false);
3008 return ExecuteInputAction(action);
3015 if (g_Joystick.GetAxis(bid))
3017 if (g_Joystick.GetAmount() < 0)
3023 CStdString actionName;
3025 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3028 if (WakeUpScreenSaverAndDPMS())
3033 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3035 g_Mouse.SetActive(false);
3036 return ExecuteInputAction(action);
3040 g_Joystick.ResetAxis(abs(bid));
3044 if (g_Joystick.GetHat(bid, position))
3047 m_idleTimer.StartZero();
3050 if (WakeUpScreenSaverAndDPMS())
3057 CStdString actionName;
3060 bid = position<<16|bid;
3062 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3064 CAction action(actionID, 1.0f, 0.0f, actionName);
3066 g_Mouse.SetActive(false);
3067 return ExecuteInputAction(action);
3074 bool CApplication::ProcessRemote(float frameTime)
3076 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3077 if (g_RemoteControl.GetButton())
3079 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3080 g_RemoteControl.Reset();
3087 bool CApplication::ProcessPeripherals(float frameTime)
3090 if (g_peripherals.GetNextKeypress(frameTime, key))
3095 bool CApplication::ProcessMouse()
3099 if (!g_Mouse.IsActive() || !m_AppFocused)
3102 // Get the mouse command ID
3103 uint32_t mousecommand = g_Mouse.GetAction();
3104 if (mousecommand == ACTION_NOOP)
3107 // Reset the screensaver and idle timers
3108 m_idleTimer.StartZero();
3110 if (WakeUpScreenSaverAndDPMS())
3113 // Retrieve the corresponding action
3114 int iWin = GetActiveWindowID();
3115 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3116 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3118 // Deactivate mouse if non-mouse action
3119 if (!mouseaction.IsMouse())
3120 g_Mouse.SetActive(false);
3122 // Consume ACTION_NOOP.
3123 // Some views or dialogs gets closed after any ACTION and
3124 // a sensitive mouse might cause problems.
3125 if (mouseaction.GetID() == ACTION_NOOP)
3128 // If we couldn't find an action return false to indicate we have not
3129 // handled this mouse action
3130 if (!mouseaction.GetID())
3132 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3136 // Log mouse actions except for move and noop
3137 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3138 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3140 // The action might not be a mouse action. For example wheel moves might
3141 // be mapped to volume up/down in mouse.xml. In this case we do not want
3142 // the mouse position saved in the action.
3143 if (!mouseaction.IsMouse())
3144 return OnAction(mouseaction);
3146 // This is a mouse action so we need to record the mouse position
3147 return OnAction(CAction(mouseaction.GetID(),
3148 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3149 (float)g_Mouse.GetX(),
3150 (float)g_Mouse.GetY(),
3151 (float)g_Mouse.GetDX(),
3152 (float)g_Mouse.GetDY(),
3153 mouseaction.GetName()));
3156 bool CApplication::ProcessEventServer(float frameTime)
3158 #ifdef HAS_EVENT_SERVER
3159 CEventServer* es = CEventServer::GetInstance();
3160 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3163 // process any queued up actions
3164 if (es->ExecuteNextAction())
3166 // reset idle timers
3167 m_idleTimer.StartZero();
3169 WakeUpScreenSaverAndDPMS();
3172 // now handle any buttons or axis
3173 std::string joystickName;
3174 bool isAxis = false;
3175 float fAmount = 0.0;
3177 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3178 // when the action exits XBMC
3179 es = CEventServer::GetInstance();
3180 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3182 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3186 if (joystickName.length() > 0)
3190 if (fabs(fAmount) >= 0.08)
3191 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3193 m_lastAxisMap[joystickName].erase(wKeyID);
3196 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3201 if (wKeyID & ES_FLAG_UNICODE)
3203 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3207 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3208 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3209 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3210 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3211 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3212 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3213 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3214 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3215 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3216 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3217 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3218 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3219 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3220 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3221 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3222 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3223 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3224 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3225 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3226 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3229 key.SetFromService(true);
3234 if (m_lastAxisMap.size() > 0)
3236 // Process all the stored axis.
3237 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3239 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3240 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3246 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3248 XBMC_Event newEvent;
3249 newEvent.type = XBMC_MOUSEMOTION;
3250 newEvent.motion.xrel = 0;
3251 newEvent.motion.yrel = 0;
3252 newEvent.motion.state = 0;
3253 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3254 newEvent.motion.x = (uint16_t)pos.x;
3255 newEvent.motion.y = (uint16_t)pos.y;
3256 OnEvent(newEvent); // had to call this to update g_Mouse position
3257 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3264 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3266 #if defined(HAS_EVENT_SERVER)
3267 m_idleTimer.StartZero();
3269 // Make sure to reset screen saver, mouse.
3271 if (WakeUpScreenSaverAndDPMS())
3274 #ifdef HAS_SDL_JOYSTICK
3277 g_Mouse.SetActive(false);
3279 int iWin = GetActiveWindowID();
3281 CStdString actionName;
3282 bool fullRange = false;
3284 // Translate using regular joystick translator.
3285 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3286 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3288 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3294 bool CApplication::ExecuteInputAction(const CAction &action)
3296 bool bResult = false;
3298 // play sound before the action unless the button is held,
3299 // where we execute after the action as held actions aren't fired every time.
3300 if(action.GetHoldTime())
3302 bResult = OnAction(action);
3304 g_audioManager.PlayActionSound(action);
3308 g_audioManager.PlayActionSound(action);
3309 bResult = OnAction(action);
3314 int CApplication::GetActiveWindowID(void)
3316 // Get the currently active window
3317 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3319 // If there is a dialog active get the dialog id instead
3320 if (g_windowManager.HasModalDialog())
3321 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3323 // If the window is FullScreenVideo check for special cases
3324 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3326 // check if we're in a DVD menu
3327 if(g_application.m_pPlayer->IsInMenu())
3328 iWin = WINDOW_VIDEO_MENU;
3329 // check for LiveTV and switch to it's virtual window
3330 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3331 iWin = WINDOW_FULLSCREEN_LIVETV;
3334 // Return the window id
3338 bool CApplication::Cleanup()
3342 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3343 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3344 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3345 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3346 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3347 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3348 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3349 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3350 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3351 g_windowManager.Delete(WINDOW_FILES);
3352 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3353 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3354 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3355 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3356 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3357 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3358 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3359 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3360 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3361 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3362 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3363 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3364 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3365 g_windowManager.Delete(WINDOW_DIALOG_OK);
3366 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3367 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3368 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3369 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3370 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3371 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3372 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3373 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3374 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3375 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3376 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3377 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3378 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3379 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3380 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3381 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3382 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3383 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3384 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3385 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3386 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3387 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3388 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3390 /* Delete PVR related windows and dialogs */
3391 g_windowManager.Delete(WINDOW_PVR);
3392 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3393 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3394 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3395 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3396 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3397 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3398 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3399 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3400 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3401 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3402 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3403 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3404 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3406 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3407 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3408 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3409 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3410 g_windowManager.Delete(WINDOW_VISUALISATION);
3411 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3412 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3413 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3414 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3415 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3416 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3417 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3418 g_windowManager.Delete(WINDOW_SCREENSAVER);
3419 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3420 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3421 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3422 g_windowManager.Delete(WINDOW_SLIDESHOW);
3423 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3424 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3426 g_windowManager.Delete(WINDOW_HOME);
3427 g_windowManager.Delete(WINDOW_PROGRAMS);
3428 g_windowManager.Delete(WINDOW_PICTURES);
3429 g_windowManager.Delete(WINDOW_WEATHER);
3431 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3432 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3433 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3434 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3435 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3436 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3437 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3438 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3439 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3440 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3442 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3443 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3445 CAddonMgr::Get().DeInit();
3447 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3448 CLog::Log(LOGNOTICE, "closing down remote control service");
3449 g_RemoteControl.Disconnect();
3452 CLog::Log(LOGNOTICE, "unload sections");
3454 #ifdef HAS_PERFORMANCE_SAMPLE
3455 CLog::Log(LOGNOTICE, "performance statistics");
3456 m_perfStats.DumpStats();
3459 // Shutdown as much as possible of the
3460 // application, to reduce the leaks dumped
3461 // to the vc output window before calling
3462 // _CrtDumpMemoryLeaks(). Most of the leaks
3463 // shown are no real leaks, as parts of the app
3464 // are still allocated.
3466 g_localizeStrings.Clear();
3467 g_LangCodeExpander.Clear();
3468 g_charsetConverter.clear();
3469 g_directoryCache.Clear();
3470 CButtonTranslator::GetInstance().Clear();
3471 #ifdef HAS_EVENT_SERVER
3472 CEventServer::RemoveInstance();
3474 DllLoaderContainer::Clear();
3475 g_playlistPlayer.Clear();
3476 CSettings::Get().Uninitialize();
3477 g_advancedSettings.Clear();
3480 CXHandle::DumpObjectTracker();
3482 #ifdef HAS_DVD_DRIVE
3483 CLibcdio::ReleaseInstance();
3486 #if defined(TARGET_ANDROID)
3487 // enable for all platforms once it's safe
3488 g_sectionLoader.UnloadAll();
3490 #ifdef _CRTDBG_MAP_ALLOC
3491 _CrtDumpMemoryLeaks();
3492 while(1); // execution ends
3502 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3507 void CApplication::Stop(int exitCode)
3511 CVariant vExitCode(exitCode);
3512 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3514 SaveFileState(true);
3516 g_alarmClock.StopThread();
3518 if( m_bSystemScreenSaverEnable )
3519 g_Windowing.EnableSystemScreenSaver(true);
3521 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3522 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3524 // Update the settings information (volume, uptime etc. need saving)
3525 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3527 CLog::Log(LOGNOTICE, "Saving settings");
3528 CSettings::Get().Save();
3531 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3534 m_AppFocused = false;
3535 m_ExitCode = exitCode;
3536 CLog::Log(LOGNOTICE, "stop all");
3538 // cancel any jobs from the jobmanager
3539 CJobManager::GetInstance().CancelJobs();
3541 // stop scanning before we kill the network and so on
3542 if (m_musicInfoScanner->IsScanning())
3543 m_musicInfoScanner->Stop();
3545 if (m_videoInfoScanner->IsScanning())
3546 m_videoInfoScanner->Stop();
3548 CApplicationMessenger::Get().Cleanup();
3550 CLog::Log(LOGNOTICE, "stop player");
3551 m_pPlayer->ClosePlayer();
3553 CAnnouncementManager::Deinitialize();
3559 #if HAS_FILESYTEM_DAAP
3560 CLog::Log(LOGNOTICE, "stop daap clients");
3561 g_DaapClient.Release();
3563 #ifdef HAS_FILESYSTEM_SAP
3564 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3565 g_sapsessions.StopThread();
3568 if(CZeroconfBrowser::IsInstantiated())
3570 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3571 CZeroconfBrowser::GetInstance()->Stop();
3572 CZeroconfBrowser::ReleaseInstance();
3576 CLog::Log(LOGNOTICE, "clean cached files!");
3577 #ifdef HAS_FILESYSTEM_RAR
3578 g_RarManager.ClearCache(true);
3581 #ifdef HAS_FILESYSTEM_SFTP
3582 CSFTPSessionManager::DisconnectAllSessions();
3585 CLog::Log(LOGNOTICE, "unload skin");
3588 #if defined(TARGET_DARWIN_OSX)
3589 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3590 XBMCHelper::GetInstance().Stop();
3593 #if defined(HAVE_LIBCRYSTALHD)
3594 CCrystalHD::RemoveInstance();
3597 g_mediaManager.Stop();
3599 // Stop services before unloading Python
3600 CAddonMgr::Get().StopServices(false);
3602 // stop all remaining scripts; must be done after skin has been unloaded,
3603 // not before some windows still need it when deinitializing during skin
3605 CScriptInvocationManager::Get().Uninitialize();
3607 g_Windowing.DestroyRenderSystem();
3608 g_Windowing.DestroyWindow();
3609 g_Windowing.DestroyWindowSystem();
3611 // shutdown the AudioEngine
3612 CAEFactory::Shutdown();
3613 CAEFactory::UnLoadEngine();
3615 CLog::Log(LOGNOTICE, "stopped");
3619 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3622 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3623 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3630 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3632 //If item is a plugin, expand out now and run ourselves again
3633 if (item.IsPlugin())
3635 CFileItem item_new(item);
3636 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3637 return PlayMedia(item_new, iPlaylist);
3640 if (item.IsSmartPlayList())
3642 CFileItemList items;
3643 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3646 CSmartPlaylist smartpl;
3647 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3648 smartpl.OpenAndReadName(item.GetPath());
3650 playlist.Add(items);
3651 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3654 else if (item.IsPlayList() || item.IsInternetStream())
3656 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3658 //is or could be a playlist
3659 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3660 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3665 if (dlgCache->IsCanceled())
3672 if (iPlaylist != PLAYLIST_NONE)
3675 if (item.HasProperty("playlist_starting_track"))
3676 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3677 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3681 CLog::Log(LOGWARNING, "CApplication::PlayMedia called to play a playlist %s but no idea which playlist to use, playing first item", item.GetPath().c_str());
3682 if(pPlayList->size())
3683 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3688 //nothing special just play
3689 return PlayFile(item, false) == PLAYBACK_OK;
3693 // For playing a multi-file video. Particularly inefficient
3694 // on startup, as we are required to calculate the length
3695 // of each video, so we open + close each one in turn.
3696 // A faster calculation of video time would improve this
3698 // return value: same with PlayFile()
3699 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3701 if (!item.IsStack())
3702 return PLAYBACK_FAIL;
3706 // case 1: stacked ISOs
3707 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3709 CStackDirectory dir;
3710 CFileItemList movieList;
3711 dir.GetDirectory(item.GetPath(), movieList);
3713 // first assume values passed to the stack
3714 int selectedFile = item.m_lStartPartNumber;
3715 int startoffset = item.m_lStartOffset;
3717 // check if we instructed the stack to resume from default
3718 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3723 CStdString path = item.GetPath();
3724 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3725 path = item.GetProperty("original_listitem_url").asString();
3726 if( dbs.GetResumeBookMark(path, bookmark) )
3728 startoffset = (int)(bookmark.timeInSeconds*75);
3729 selectedFile = bookmark.partNumber;
3734 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3737 // make sure that the selected part is within the boundaries
3738 if (selectedFile <= 0)
3740 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3743 else if (selectedFile > movieList.Size())
3745 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3746 selectedFile = movieList.Size();
3749 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3750 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3751 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3752 *m_stackFileItemToUpdate = item;
3753 return PlayFile(*(movieList[selectedFile - 1]));
3755 // case 2: all other stacks
3758 // see if we have the info in the database
3759 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3760 // then these times will be wrong.
3761 // Also, this is really just a hack for the slow load up times we have
3762 // A much better solution is a fast reader of FPS and fileLength
3763 // that we can use on a file to get it's time.
3765 bool haveTimes(false);
3769 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3770 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3775 // calculate the total time of the stack
3776 CStackDirectory dir;
3777 dir.GetDirectory(item.GetPath(), *m_currentStack);
3779 for (int i = 0; i < m_currentStack->Size(); i++)
3782 (*m_currentStack)[i]->m_lEndOffset = times[i];
3786 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3788 m_currentStack->Clear();
3789 return PLAYBACK_FAIL;
3791 totalTime += duration / 1000;
3792 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3793 times.push_back(totalTime);
3797 double seconds = item.m_lStartOffset / 75.0;
3799 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3800 { // have our times now, so update the dB
3804 dbs.SetStackTimes(item.GetPath(), times);
3806 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3808 // can only resume seek here, not dvdstate
3810 CStdString path = item.GetPath();
3811 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3812 path = item.GetProperty("original_listitem_url").asString();
3813 if( dbs.GetResumeBookMark(path, bookmark) )
3814 seconds = bookmark.timeInSeconds;
3822 *m_itemCurrentFile = item;
3823 m_currentStackPosition = 0;
3824 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3828 // work out where to seek to
3829 for (int i = 0; i < m_currentStack->Size(); i++)
3831 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3833 CFileItem item(*(*m_currentStack)[i]);
3834 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3835 item.m_lStartOffset = (long)(seconds - start) * 75;
3836 m_currentStackPosition = i;
3837 return PlayFile(item, true);
3842 return PlayFile(*(*m_currentStack)[0], true);
3844 return PLAYBACK_FAIL;
3847 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3849 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3850 if (item.GetMimeType().empty())
3851 const_cast<CFileItem&>(item).FillInMimeType();
3855 SaveCurrentFileSettings();
3857 OutputDebugString("new file set audiostream:0\n");
3858 // Switch to default options
3859 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3860 // see if we have saved options in the database
3862 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3863 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3865 *m_itemCurrentFile = item;
3866 m_nextPlaylistItem = -1;
3867 m_currentStackPosition = 0;
3868 m_currentStack->Clear();
3871 CUtil::ClearSubtitles();
3874 if (item.IsDiscStub())
3876 #ifdef HAS_DVD_DRIVE
3877 // Display the Play Eject dialog if there is any optical disc drive
3878 if (g_mediaManager.HasOpticalDrive())
3880 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3881 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3882 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3883 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3887 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3892 if (item.IsPlayList())
3893 return PLAYBACK_FAIL;
3895 if (item.IsPlugin())
3896 { // we modify the item so that it becomes a real URL
3897 CFileItem item_new(item);
3898 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3899 return PlayFile(item_new, false);
3900 return PLAYBACK_FAIL;
3904 if (URIUtils::IsUPnP(item.GetPath()))
3906 CFileItem item_new(item);
3907 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3908 return PlayFile(item_new, false);
3909 return PLAYBACK_FAIL;
3913 // if we have a stacked set of files, we need to setup our stack routines for
3914 // "seamless" seeking and total time of the movie etc.
3915 // will recall with restart set to true
3917 return PlayStack(item, bRestart);
3919 //Is TuxBox, this should probably be moved to CTuxBoxFile
3922 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3924 if(g_tuxboxService.IsRunning())
3925 g_tuxboxService.Stop();
3927 PlayBackRet ret = PLAYBACK_FAIL;
3929 if(g_tuxbox.CreateNewItem(item, item_new))
3932 // Make sure it doesn't have a player
3933 // so we actually select one normally
3934 m_pPlayer->ResetPlayer();
3936 // keep the tuxbox:// url as playing url
3937 // and give the new url to the player
3938 ret = PlayFile(item_new, true);
3939 if(ret == PLAYBACK_OK)
3941 if(!g_tuxboxService.IsRunning())
3942 g_tuxboxService.Start();
3948 CPlayerOptions options;
3950 if( item.HasProperty("StartPercent") )
3952 double fallback = 0.0f;
3953 if(item.GetProperty("StartPercent").isString())
3954 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3955 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3958 PLAYERCOREID eNewCore = EPC_NONE;
3961 // have to be set here due to playstack using this for starting the file
3962 options.starttime = item.m_lStartOffset / 75.0;
3963 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3964 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3966 if( m_eForcedNextPlayer != EPC_NONE )
3967 eNewCore = m_eForcedNextPlayer;
3968 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3969 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3971 eNewCore = m_pPlayer->GetCurrentPlayer();
3975 options.starttime = item.m_lStartOffset / 75.0;
3979 // open the d/b and retrieve the bookmarks for the current movie
3982 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3984 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3986 options.starttime = 0.0f;
3988 CStdString path = item.GetPath();
3989 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3990 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3991 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3992 path = item.GetProperty("original_listitem_url").asString();
3993 if(dbs.GetResumeBookMark(path, bookmark))
3995 options.starttime = bookmark.timeInSeconds;
3996 options.state = bookmark.playerState;
3999 override with information from the actual item if available. We do this as the VFS (eg plugins)
4000 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4001 should the playerState be required, it is fetched from the database.
4002 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4004 if (item.IsResumePointSet())
4005 options.starttime = item.GetCurrentResumeTime();
4007 else if (item.HasVideoInfoTag())
4009 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4011 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4014 dbs.GetBookMarkForEpisode(*tag, bookmark);
4015 options.starttime = bookmark.timeInSeconds;
4016 options.state = bookmark.playerState;
4023 if (m_eForcedNextPlayer != EPC_NONE)
4024 eNewCore = m_eForcedNextPlayer;
4026 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4029 // this really aught to be inside !bRestart, but since PlayStack
4030 // uses that to init playback, we have to keep it outside
4031 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4032 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4033 { // playing from a playlist by the looks
4034 // don't switch to fullscreen if we are not playing the first item...
4035 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4037 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4039 // TODO - this will fail if user seeks back to first file in stack
4040 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4041 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4043 options.fullscreen = false;
4044 // reset this so we don't think we are resuming on seek
4045 m_itemCurrentFile->m_lStartOffset = 0;
4048 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4050 // reset VideoStartWindowed as it's a temp setting
4051 CMediaSettings::Get().SetVideoStartWindowed(false);
4054 //We have to stop parsing a cdg before mplayer is deallocated
4055 // WHY do we have to do this????
4057 m_pKaraokeMgr->Stop();
4061 CSingleLock lock(m_playStateMutex);
4062 // tell system we are starting a file
4063 m_bPlaybackStarting = true;
4065 // for playing a new item, previous playing item's callback may already
4066 // pushed some delay message into the threadmessage list, they are not
4067 // expected be processed after or during the new item playback starting.
4068 // so we clean up previous playing item's playback callback delay messages here.
4069 int previousMsgsIgnoredByNewPlaying[] = {
4070 GUI_MSG_PLAYBACK_STARTED,
4071 GUI_MSG_PLAYBACK_ENDED,
4072 GUI_MSG_PLAYBACK_STOPPED,
4073 GUI_MSG_PLAYLIST_CHANGED,
4074 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4075 GUI_MSG_PLAYLISTPLAYER_STARTED,
4076 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4077 GUI_MSG_QUEUE_NEXT_ITEM,
4080 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4082 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4085 // We should restart the player, unless the previous and next tracks are using
4086 // one of the players that allows gapless playback (paplayer, dvdplayer)
4087 m_pPlayer->ClosePlayerGapless(eNewCore);
4089 // now reset play state to starting, since we already stopped the previous playing item if there is.
4090 // and from now there should be no playback callback from previous playing item be called.
4091 m_ePlayState = PLAY_STATE_STARTING;
4093 m_pPlayer->CreatePlayer(eNewCore, *this);
4095 PlayBackRet iResult;
4096 if (m_pPlayer->HasPlayer())
4098 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4099 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4100 * increase performance on low powered systems (Atom/ARM).
4104 CJobManager::GetInstance().PauseJobs();
4107 // don't hold graphicscontext here since player
4108 // may wait on another thread, that requires gfx
4109 CSingleExit ex(g_graphicsContext);
4111 iResult = m_pPlayer->OpenFile(item, options);
4115 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4116 iResult = PLAYBACK_FAIL;
4119 if(iResult == PLAYBACK_OK)
4121 if (m_pPlayer->GetPlaySpeed() != 1)
4123 int iSpeed = m_pPlayer->GetPlaySpeed();
4124 m_pPlayer->m_iPlaySpeed = 1;
4125 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4128 // if player has volume control, set it.
4129 if (m_pPlayer->ControlsVolume())
4131 m_pPlayer->SetVolume(m_volumeLevel);
4132 m_pPlayer->SetMute(m_muted);
4135 if( m_pPlayer->IsPlayingAudio() )
4137 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4138 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4141 #ifdef HAS_VIDEO_PLAYBACK
4142 else if( m_pPlayer->IsPlayingVideo() )
4144 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4145 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4147 // if player didn't manange to switch to fullscreen by itself do it here
4148 if( options.fullscreen && g_renderManager.IsStarted()
4149 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4150 SwitchToFullScreen();
4155 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4156 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4157 g_windowManager.PreviousWindow();
4161 #if !defined(TARGET_POSIX)
4162 g_audioManager.Enable(false);
4165 if (item.HasPVRChannelInfoTag())
4166 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4169 CSingleLock lock(m_playStateMutex);
4170 m_bPlaybackStarting = false;
4172 if (iResult == PLAYBACK_OK)
4174 // play state: none, starting; playing; stopped; ended.
4175 // last 3 states are set by playback callback, they are all ignored during starting,
4176 // but we recorded the state, here we can make up the callback for the state.
4177 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4178 switch (m_ePlayState)
4180 case PLAY_STATE_PLAYING:
4181 OnPlayBackStarted();
4183 // FIXME: it seems no meaning to callback started here if there was an started callback
4184 // before this stopped/ended callback we recorded. if we callback started here
4185 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4186 // which will send OnStop announce at once, so currently, just call stopped/ended.
4187 case PLAY_STATE_ENDED:
4190 case PLAY_STATE_STOPPED:
4191 OnPlayBackStopped();
4193 case PLAY_STATE_STARTING:
4194 // neither started nor stopped/ended callback be called, that means the item still
4195 // not started, we need not make up any callback, just leave this and
4196 // let the player callback do its work.
4202 else if (iResult == PLAYBACK_FAIL)
4204 // we send this if it isn't playlistplayer that is doing this
4205 int next = g_playlistPlayer.GetNextSong();
4206 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4209 OnPlayBackStopped();
4210 m_ePlayState = PLAY_STATE_NONE;
4216 void CApplication::OnPlayBackEnded()
4218 CSingleLock lock(m_playStateMutex);
4219 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4220 m_ePlayState = PLAY_STATE_ENDED;
4221 if(m_bPlaybackStarting)
4224 // informs python script currently running playback has ended
4225 // (does nothing if python is not loaded)
4227 g_pythonParser.OnPlayBackEnded();
4230 CVariant data(CVariant::VariantTypeObject);
4232 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4234 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4235 g_windowManager.SendThreadMessage(msg);
4238 void CApplication::OnPlayBackStarted()
4240 CSingleLock lock(m_playStateMutex);
4241 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4242 m_ePlayState = PLAY_STATE_PLAYING;
4243 if(m_bPlaybackStarting)
4247 // informs python script currently running playback has started
4248 // (does nothing if python is not loaded)
4249 g_pythonParser.OnPlayBackStarted();
4252 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4253 g_windowManager.SendThreadMessage(msg);
4256 void CApplication::OnQueueNextItem()
4258 CSingleLock lock(m_playStateMutex);
4259 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4260 if(m_bPlaybackStarting)
4262 // informs python script currently running that we are requesting the next track
4263 // (does nothing if python is not loaded)
4265 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4268 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4269 g_windowManager.SendThreadMessage(msg);
4272 void CApplication::OnPlayBackStopped()
4274 CSingleLock lock(m_playStateMutex);
4275 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4276 m_ePlayState = PLAY_STATE_STOPPED;
4277 if(m_bPlaybackStarting)
4280 // informs python script currently running playback has ended
4281 // (does nothing if python is not loaded)
4283 g_pythonParser.OnPlayBackStopped();
4286 CVariant data(CVariant::VariantTypeObject);
4287 data["end"] = false;
4288 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4290 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4291 g_windowManager.SendThreadMessage(msg);
4294 void CApplication::OnPlayBackPaused()
4297 g_pythonParser.OnPlayBackPaused();
4301 param["player"]["speed"] = 0;
4302 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4303 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4306 void CApplication::OnPlayBackResumed()
4309 g_pythonParser.OnPlayBackResumed();
4313 param["player"]["speed"] = 1;
4314 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4315 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4318 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4321 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4325 param["player"]["speed"] = iSpeed;
4326 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4327 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4330 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4333 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4337 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4338 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4339 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4340 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4341 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4342 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4345 void CApplication::OnPlayBackSeekChapter(int iChapter)
4348 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4352 bool CApplication::IsPlayingFullScreenVideo() const
4354 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4357 bool CApplication::IsFullScreen()
4359 return IsPlayingFullScreenVideo() ||
4360 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4361 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4364 void CApplication::SaveFileState(bool bForeground /* = false */)
4366 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4371 CSaveFileStateJob job(*m_progressTrackingItem,
4372 *m_stackFileItemToUpdate,
4373 m_progressTrackingVideoResumeBookmark,
4374 m_progressTrackingPlayCountUpdate);
4376 // Run job in the foreground to make sure it finishes
4381 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4382 *m_stackFileItemToUpdate,
4383 m_progressTrackingVideoResumeBookmark,
4384 m_progressTrackingPlayCountUpdate);
4385 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4389 void CApplication::UpdateFileState()
4391 // Did the file change?
4392 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4396 // Reset tracking item
4397 m_progressTrackingItem->Reset();
4401 if (m_pPlayer->IsPlaying())
4403 if (m_progressTrackingItem->GetPath() == "")
4406 *m_progressTrackingItem = CurrentFileItem();
4407 m_progressTrackingPlayCountUpdate = false;
4410 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4411 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4412 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4413 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4415 m_progressTrackingPlayCountUpdate = true;
4418 // Check whether we're *really* playing video else we may race when getting eg. stream details
4419 if (m_pPlayer->IsPlayingVideo())
4421 /* Always update streamdetails, except for DVDs where we only update
4422 streamdetails if title length > 15m (Should yield more correct info) */
4423 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4425 CStreamDetails details;
4426 // Update with stream details from player, if any
4427 if (m_pPlayer->GetStreamDetails(details))
4428 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4430 if (m_progressTrackingItem->IsStack())
4431 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4434 // Update bookmark for save
4435 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4436 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4437 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4439 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4440 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4442 // Delete the bookmark
4443 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4446 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4448 // Update the bookmark
4449 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4450 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4455 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4462 void CApplication::StopPlaying()
4464 int iWin = g_windowManager.GetActiveWindow();
4465 if ( m_pPlayer->IsPlaying() )
4469 m_pKaraokeMgr->Stop();
4472 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4473 g_PVRManager.SaveCurrentChannelSettings();
4475 m_pPlayer->CloseFile();
4477 // turn off visualisation window when stopping
4478 if ((iWin == WINDOW_VISUALISATION
4479 || iWin == WINDOW_FULLSCREEN_VIDEO)
4481 g_windowManager.PreviousWindow();
4483 g_partyModeManager.Disable();
4487 void CApplication::ResetSystemIdleTimer()
4489 // reset system idle timer
4490 m_idleTimer.StartZero();
4493 void CApplication::ResetScreenSaver()
4496 m_shutdownTimer.StartZero();
4498 // screen saver timer is reset only if we're not already in screensaver or
4500 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4501 ResetScreenSaverTimer();
4504 void CApplication::ResetScreenSaverTimer()
4506 m_screenSaverTimer.StartZero();
4509 void CApplication::StopScreenSaverTimer()
4511 m_screenSaverTimer.Stop();
4514 bool CApplication::ToggleDPMS(bool manual)
4516 if (manual || (m_dpmsIsManual == manual))
4520 m_dpmsIsActive = false;
4521 m_dpmsIsManual = false;
4522 return m_dpms->DisablePowerSaving();
4526 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4528 m_dpmsIsActive = true;
4529 m_dpmsIsManual = manual;
4537 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4541 // First reset DPMS, if active
4546 // TODO: if screensaver lock is specified but screensaver is not active
4547 // (DPMS came first), activate screensaver now.
4549 ResetScreenSaverTimer();
4550 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4553 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4557 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4558 CVariant data(bPowerOffKeyPressed);
4559 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4565 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4567 if (m_iScreenSaveLock == 2)
4570 // if Screen saver is active
4571 if (m_bScreenSave && m_screenSaver)
4573 if (m_iScreenSaveLock == 0)
4574 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4575 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4576 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4577 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4579 m_iScreenSaveLock = 2;
4580 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4582 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4584 pWindow->OnMessage(msg);
4586 if (m_iScreenSaveLock == -1)
4588 m_iScreenSaveLock = 0;
4592 // disable screensaver
4593 m_bScreenSave = false;
4594 m_iScreenSaveLock = 0;
4595 ResetScreenSaverTimer();
4597 if (m_screenSaver->ID() == "visualization")
4599 // we can just continue as usual from vis mode
4602 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4604 else if (!m_screenSaver->ID().empty())
4605 { // we're in screensaver window
4606 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4607 g_windowManager.PreviousWindow(); // show the previous window
4608 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4609 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4617 void CApplication::CheckScreenSaverAndDPMS()
4619 if (!m_dpmsIsActive)
4620 g_Windowing.ResetOSScreensaver();
4622 bool maybeScreensaver =
4623 !m_dpmsIsActive && !m_bScreenSave
4624 && !CSettings::Get().GetString("screensaver.mode").empty();
4626 !m_dpmsIsActive && m_dpms->IsSupported()
4627 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4629 // Has the screen saver window become active?
4630 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4632 m_bScreenSave = true;
4633 maybeScreensaver = false;
4636 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4638 WakeUpScreenSaverAndDPMS();
4642 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4644 // See if we need to reset timer.
4645 // * Are we playing a video and it is not paused?
4646 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4647 // * Are we playing some music in fullscreen vis?
4648 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4649 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4651 ResetScreenSaverTimer();
4655 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4657 // DPMS has priority (it makes the screensaver not needed)
4659 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4662 WakeUpScreenSaver();
4664 else if (maybeScreensaver
4665 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4667 ActivateScreenSaver();
4671 // activate the screensaver.
4672 // if forceType is true, we ignore the various conditions that can alter
4673 // the type of screensaver displayed
4674 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4676 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4677 { // just activate the visualisation if user toggled the usemusicvisinstead option
4678 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4682 m_bScreenSave = true;
4684 // Get Screensaver Mode
4685 m_screenSaver.reset();
4686 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4687 m_screenSaver.reset(new CScreenSaver(""));
4689 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4691 // disable screensaver lock from the login screen
4692 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4695 // set to Dim in the case of a dialog on screen or playing video
4696 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4698 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4699 m_screenSaver.reset(new CScreenSaver(""));
4702 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4704 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4706 else if (!m_screenSaver->ID().empty())
4707 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4710 void CApplication::CheckShutdown()
4712 // first check if we should reset the timer
4713 if (m_bInhibitIdleShutdown
4714 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4715 || m_musicInfoScanner->IsScanning()
4716 || m_videoInfoScanner->IsScanning()
4717 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4718 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4720 m_shutdownTimer.StartZero();
4724 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4726 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4727 m_shutdownTimer.Stop();
4730 CApplicationMessenger::Get().Shutdown();
4734 void CApplication::InhibitIdleShutdown(bool inhibit)
4736 m_bInhibitIdleShutdown = inhibit;
4739 bool CApplication::IsIdleShutdownInhibited() const
4741 return m_bInhibitIdleShutdown;
4744 bool CApplication::OnMessage(CGUIMessage& message)
4746 switch ( message.GetMessage() )
4748 case GUI_MSG_NOTIFY_ALL:
4750 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4752 // Update general playlist: Remove DVD playlist items
4753 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4756 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4757 g_windowManager.SendMessage( msg );
4759 // stop the file if it's on dvd (will set the resume point etc)
4760 if (m_itemCurrentFile->IsOnDVD())
4766 case GUI_MSG_PLAYBACK_STARTED:
4768 #ifdef TARGET_DARWIN
4769 DarwinSetScheduling(message.GetMessage());
4771 // reset the seek handler
4772 m_seekHandler->Reset();
4773 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4775 // Update our infoManager with the new details etc.
4776 if (m_nextPlaylistItem >= 0)
4778 // playing an item which is not in the list - player might be stopped already
4780 if (playList.size() <= m_nextPlaylistItem)
4783 // we've started a previously queued item
4784 CFileItemPtr item = playList[m_nextPlaylistItem];
4785 // update the playlist manager
4786 int currentSong = g_playlistPlayer.GetCurrentSong();
4787 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4788 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4789 g_windowManager.SendThreadMessage(msg);
4790 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4791 *m_itemCurrentFile = *item;
4793 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4794 g_partyModeManager.OnSongChange(true);
4797 param["player"]["speed"] = 1;
4798 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4799 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4801 if (m_pPlayer->IsPlayingAudio())
4803 // Start our cdg parser as appropriate
4805 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4807 m_pKaraokeMgr->Stop();
4808 if (m_itemCurrentFile->IsMusicDb())
4810 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4812 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4813 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4816 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4819 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4828 case GUI_MSG_QUEUE_NEXT_ITEM:
4830 // Check to see if our playlist player has a new item for us,
4831 // and if so, we check whether our current player wants the file
4832 int iNext = g_playlistPlayer.GetNextSong();
4833 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4834 if (iNext < 0 || iNext >= playlist.size())
4836 m_pPlayer->OnNothingToQueueNotify();
4837 return true; // nothing to do
4840 // ok, grab the next song
4841 CFileItem file(*playlist[iNext]);
4843 CURL url(file.GetPath());
4844 if (url.GetProtocol() == "plugin")
4845 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4848 if (URIUtils::IsUPnP(file.GetPath()))
4850 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4855 // ok - send the file to the player, if it accepts it
4856 if (m_pPlayer->QueueNextFile(file))
4858 // player accepted the next file
4859 m_nextPlaylistItem = iNext;
4863 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4864 queue the next (if it wants to) and it doesn't keep looping on this song */
4865 g_playlistPlayer.SetCurrentSong(iNext);
4872 case GUI_MSG_PLAYBACK_STOPPED:
4873 case GUI_MSG_PLAYBACK_ENDED:
4874 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4878 m_pKaraokeMgr->Stop();
4880 #ifdef TARGET_DARWIN
4881 DarwinSetScheduling(message.GetMessage());
4883 // first check if we still have items in the stack to play
4884 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4886 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4887 { // just play the next item in the stack
4888 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4893 // In case playback ended due to user eg. skipping over the end, clear
4894 // our resume bookmark here
4895 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4897 // Delete the bookmark
4898 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4901 // reset the current playing file
4902 m_itemCurrentFile->Reset();
4903 g_infoManager.ResetCurrentItem();
4904 m_currentStack->Clear();
4906 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4908 g_playlistPlayer.PlayNext(1, true);
4912 // reset any forced player
4913 m_eForcedNextPlayer = EPC_NONE;
4915 m_pPlayer->ClosePlayer();
4918 m_pPlayer->m_iPlaySpeed = 1;
4921 if (!m_pPlayer->IsPlaying())
4923 g_audioManager.Enable(true);
4926 if (!m_pPlayer->IsPlayingVideo())
4928 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4930 g_windowManager.PreviousWindow();
4934 CSingleLock lock(g_graphicsContext);
4935 // resets to res_desktop or look&feel resolution (including refreshrate)
4936 g_graphicsContext.SetFullScreenVideo(false);
4940 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4942 CSettings::Get().Save(); // save vis settings
4943 WakeUpScreenSaverAndDPMS();
4944 g_windowManager.PreviousWindow();
4947 // DVD ejected while playing in vis ?
4948 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4951 CSettings::Get().Save(); // save vis settings
4952 WakeUpScreenSaverAndDPMS();
4953 g_windowManager.PreviousWindow();
4956 if (IsEnableTestMode())
4957 CApplicationMessenger::Get().Quit();
4962 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4963 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4968 case GUI_MSG_FULLSCREEN:
4969 { // Switch to fullscreen, if we can
4970 SwitchToFullScreen();
4974 case GUI_MSG_EXECUTE:
4975 if (message.GetNumStringParams())
4976 return ExecuteXBMCAction(message.GetStringParam());
4982 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4984 // see if it is a user set string
4986 //We don't know if there is unsecure information in this yet, so we
4987 //postpone any logging
4988 const std::string in_actionStr(actionStr);
4989 CGUIInfoLabel info(actionStr, "");
4990 actionStr = info.GetLabel(0);
4992 // user has asked for something to be executed
4993 if (CBuiltins::HasCommand(actionStr))
4994 CBuiltins::Execute(actionStr);
4997 // try translating the action from our ButtonTranslator
4999 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5001 OnAction(CAction(actionID));
5004 CFileItem item(actionStr, false);
5006 if (item.IsPythonScript())
5007 { // a python script
5008 CScriptInvocationManager::Get().Execute(item.GetPath());
5012 if (item.IsAudio() || item.IsVideo())
5013 { // an audio or video file
5018 //At this point we have given up to translate, so even though
5019 //there may be insecure information, we log it.
5020 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5027 void CApplication::Process()
5031 // dispatch the messages generated by python or other threads to the current window
5032 g_windowManager.DispatchThreadMessages();
5034 // process messages which have to be send to the gui
5035 // (this can only be done after g_windowManager.Render())
5036 CApplicationMessenger::Get().ProcessWindowMessages();
5040 m_loggingIn = false;
5042 // autoexec.py - profile
5043 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5045 if (XFILE::CFile::Exists(strAutoExecPy))
5046 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5048 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5051 // handle any active scripts
5052 CScriptInvocationManager::Get().Process();
5054 // process messages, even if a movie is playing
5055 CApplicationMessenger::Get().ProcessMessages();
5056 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5058 // check how far we are through playing the current item
5059 // and do anything that needs doing (playcount updates etc)
5060 CheckPlayingProgress();
5063 m_pPlayer->DoAudioWork();
5065 // do any processing that isn't needed on each run
5066 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5068 m_slowTimer.Reset();
5072 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5075 // We get called every 500ms
5076 void CApplication::ProcessSlow()
5078 g_powerManager.ProcessEvents();
5080 #if defined(TARGET_DARWIN_OSX)
5081 // There is an issue on OS X that several system services ask the cursor to become visible
5082 // during their startup routines. Given that we can't control this, we hack it in by
5084 if (g_Windowing.IsFullScreen())
5085 { // SDL thinks it's hidden
5090 // Temporarely pause pausable jobs when viewing video/picture
5091 int currentWindow = g_windowManager.GetActiveWindow();
5092 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5094 CJobManager::GetInstance().PauseJobs();
5098 CJobManager::GetInstance().UnPauseJobs();
5101 // Store our file state for use on close()
5104 // Check if we need to activate the screensaver / DPMS.
5105 CheckScreenSaverAndDPMS();
5107 // Check if we need to shutdown (if enabled).
5108 #if defined(TARGET_DARWIN)
5109 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5111 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5117 // check if we should restart the player
5118 CheckDelayedPlayerRestart();
5120 // check if we can unload any unreferenced dlls or sections
5121 if (!m_pPlayer->IsPlayingVideo())
5122 CSectionLoader::UnloadDelayed();
5124 // check for any idle curl connections
5125 g_curlInterface.CheckIdle();
5127 // check for any idle myth sessions
5128 CMythSession::CheckIdle();
5130 #ifdef HAS_FILESYSTEM_HTSP
5131 // check for any idle htsp sessions
5132 HTSP::CHTSPDirectorySession::CheckIdle();
5136 if ( m_pKaraokeMgr )
5137 m_pKaraokeMgr->ProcessSlow();
5140 if (!m_pPlayer->IsPlayingVideo())
5141 g_largeTextureManager.CleanupUnusedImages();
5143 g_TextureManager.FreeUnusedTextures(5000);
5145 #ifdef HAS_DVD_DRIVE
5146 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5147 if (!m_pPlayer->IsPlayingVideo())
5148 m_Autorun->HandleAutorun();
5151 // update upnp server/renderer states
5153 if(UPNP::CUPnP::IsInstantiated())
5154 UPNP::CUPnP::GetInstance()->UpdateState();
5157 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5161 #ifdef HAS_FILESYSTEM_NFS
5162 gNfsConnection.CheckIfIdle();
5165 #ifdef HAS_FILESYSTEM_AFP
5166 gAfpConnection.CheckIfIdle();
5169 #ifdef HAS_FILESYSTEM_SFTP
5170 CSFTPSessionManager::ClearOutIdleSessions();
5173 g_mediaManager.ProcessEvents();
5176 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5177 g_RemoteControl.Initialize();
5180 if (!m_pPlayer->IsPlayingVideo())
5181 CAddonInstaller::Get().UpdateRepos();
5183 CAEFactory::GarbageCollect();
5185 // if we don't render the gui there's no reason to start the screensaver.
5186 // that way the screensaver won't kick in if we maximize the XBMC window
5187 // after the screensaver start time.
5189 ResetScreenSaverTimer();
5192 // Global Idle Time in Seconds
5193 // idle time will be resetet if on any OnKey()
5194 // int return: system Idle time in seconds! 0 is no idle!
5195 int CApplication::GlobalIdleTime()
5197 if(!m_idleTimer.IsRunning())
5200 m_idleTimer.StartZero();
5202 return (int)m_idleTimer.GetElapsedSeconds();
5205 float CApplication::NavigationIdleTime()
5207 if (!m_navigationTimer.IsRunning())
5209 m_navigationTimer.Stop();
5210 m_navigationTimer.StartZero();
5212 return m_navigationTimer.GetElapsedSeconds();
5215 void CApplication::DelayedPlayerRestart()
5217 m_restartPlayerTimer.StartZero();
5220 void CApplication::CheckDelayedPlayerRestart()
5222 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5224 m_restartPlayerTimer.Stop();
5225 m_restartPlayerTimer.Reset();
5230 void CApplication::Restart(bool bSamePosition)
5232 // this function gets called when the user changes a setting (like noninterleaved)
5233 // and which means we gotta close & reopen the current playing file
5235 // first check if we're playing a file
5236 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5239 if( !m_pPlayer->HasPlayer() )
5244 // do we want to return to the current position in the file
5245 if (false == bSamePosition)
5247 // no, then just reopen the file and start at the beginning
5248 PlayFile(*m_itemCurrentFile, true);
5252 // else get current position
5253 double time = GetTime();
5255 // get player state, needed for dvd's
5256 CStdString state = m_pPlayer->GetPlayerState();
5258 // set the requested starttime
5259 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5262 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5263 m_pPlayer->SetPlayerState(state);
5266 const CStdString& CApplication::CurrentFile()
5268 return m_itemCurrentFile->GetPath();
5271 CFileItem& CApplication::CurrentFileItem()
5273 return *m_itemCurrentFile;
5276 CFileItem& CApplication::CurrentUnstackedItem()
5278 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5279 return *(*m_currentStack)[m_currentStackPosition];
5281 return *m_itemCurrentFile;
5284 void CApplication::ShowVolumeBar(const CAction *action)
5286 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5291 volumeBar->OnAction(*action);
5295 bool CApplication::IsMuted() const
5297 if (g_peripherals.IsMuted())
5299 return CAEFactory::IsMuted();
5302 void CApplication::ToggleMute(void)
5310 void CApplication::SetMute(bool mute)
5312 if (m_muted != mute)
5319 void CApplication::Mute()
5321 if (g_peripherals.Mute())
5324 CAEFactory::SetMute(true);
5329 void CApplication::UnMute()
5331 if (g_peripherals.UnMute())
5334 CAEFactory::SetMute(false);
5339 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5341 float hardwareVolume = iValue;
5344 hardwareVolume /= 100.0f;
5346 SetHardwareVolume(hardwareVolume);
5350 void CApplication::SetHardwareVolume(float hardwareVolume)
5352 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5353 m_volumeLevel = hardwareVolume;
5355 CAEFactory::SetVolume(hardwareVolume);
5358 float CApplication::GetVolume(bool percentage /* = true */) const
5362 // converts the hardware volume to a percentage
5363 return m_volumeLevel * 100.0f;
5366 return m_volumeLevel;
5369 void CApplication::VolumeChanged() const
5371 CVariant data(CVariant::VariantTypeObject);
5372 data["volume"] = GetVolume();
5373 data["muted"] = m_muted;
5374 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5376 // if player has volume control, set it.
5377 if (m_pPlayer->ControlsVolume())
5379 m_pPlayer->SetVolume(m_volumeLevel);
5380 m_pPlayer->SetMute(m_muted);
5384 int CApplication::GetSubtitleDelay() const
5386 // converts subtitle delay to a percentage
5387 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5390 int CApplication::GetAudioDelay() const
5392 // converts audio delay to a percentage
5393 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5396 // Returns the total time in seconds of the current media. Fractional
5397 // portions of a second are possible - but not necessarily supported by the
5398 // player class. This returns a double to be consistent with GetTime() and
5400 double CApplication::GetTotalTime() const
5404 if (m_pPlayer->IsPlaying())
5406 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5407 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5409 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5415 void CApplication::StopShutdownTimer()
5417 if (m_shutdownTimer.IsRunning())
5418 m_shutdownTimer.Stop();
5421 void CApplication::ResetShutdownTimers()
5423 // reset system shutdown timer
5424 m_shutdownTimer.StartZero();
5426 // delete custom shutdown timer
5427 if (g_alarmClock.HasAlarm("shutdowntimer"))
5428 g_alarmClock.Stop("shutdowntimer", true);
5431 // Returns the current time in seconds of the currently playing media.
5432 // Fractional portions of a second are possible. This returns a double to
5433 // be consistent with GetTotalTime() and SeekTime().
5434 double CApplication::GetTime() const
5438 if (m_pPlayer->IsPlaying())
5440 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5442 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5443 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5446 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5452 // Sets the current position of the currently playing media to the specified
5453 // time in seconds. Fractional portions of a second are valid. The passed
5454 // time is the time offset from the beginning of the file as opposed to a
5455 // delta from the current position. This method accepts a double to be
5456 // consistent with GetTime() and GetTotalTime().
5457 void CApplication::SeekTime( double dTime )
5459 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5461 if (!m_pPlayer->CanSeek()) return;
5462 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5464 // find the item in the stack we are seeking to, and load the new
5465 // file if necessary, and calculate the correct seek within the new
5466 // file. Otherwise, just fall through to the usual routine if the
5467 // time is higher than our total time.
5468 for (int i = 0; i < m_currentStack->Size(); i++)
5470 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5472 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5473 if (m_currentStackPosition == i)
5474 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5476 { // seeking to a new file
5477 m_currentStackPosition = i;
5478 CFileItem item(*(*m_currentStack)[i]);
5479 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5480 // don't just call "PlayFile" here, as we are quite likely called from the
5481 // player thread, so we won't be able to delete ourselves.
5482 CApplicationMessenger::Get().PlayFile(item, true);
5488 // convert to milliseconds and perform seek
5489 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5493 float CApplication::GetPercentage() const
5495 if (m_pPlayer->IsPlaying())
5497 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5499 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5500 if (tag.GetDuration() > 0)
5501 return (float)(GetTime() / tag.GetDuration() * 100);
5504 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5506 double totalTime = GetTotalTime();
5507 if (totalTime > 0.0f)
5508 return (float)(GetTime() / totalTime * 100);
5511 return m_pPlayer->GetPercentage();
5516 float CApplication::GetCachePercentage() const
5518 if (m_pPlayer->IsPlaying())
5520 // Note that the player returns a relative cache percentage and we want an absolute percentage
5521 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5523 float stackedTotalTime = (float) GetTotalTime();
5524 // We need to take into account the stack's total time vs. currently playing file's total time
5525 if (stackedTotalTime > 0.0f)
5526 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5529 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5534 void CApplication::SeekPercentage(float percent)
5536 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5538 if (!m_pPlayer->CanSeek()) return;
5539 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5540 SeekTime(percent * 0.01 * GetTotalTime());
5542 m_pPlayer->SeekPercentage(percent);
5546 // SwitchToFullScreen() returns true if a switch is made, else returns false
5547 bool CApplication::SwitchToFullScreen()
5549 // if playing from the video info window, close it first!
5550 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5552 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5553 if (pDialog) pDialog->Close(true);
5556 // don't switch if there is a dialog on screen or the slideshow is active
5557 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5560 // See if we're playing a video, and are in GUI mode
5561 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5563 // then switch to fullscreen mode
5564 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5567 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5568 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5569 { // then switch to visualisation
5570 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5576 void CApplication::Minimize()
5578 g_Windowing.Minimize();
5581 PLAYERCOREID CApplication::GetCurrentPlayer()
5583 return m_pPlayer->GetCurrentPlayer();
5586 void CApplication::UpdateLibraries()
5588 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5590 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5594 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5596 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5601 bool CApplication::IsVideoScanning() const
5603 return m_videoInfoScanner->IsScanning();
5606 bool CApplication::IsMusicScanning() const
5608 return m_musicInfoScanner->IsScanning();
5611 void CApplication::StopVideoScan()
5613 if (m_videoInfoScanner->IsScanning())
5614 m_videoInfoScanner->Stop();
5617 void CApplication::StopMusicScan()
5619 if (m_musicInfoScanner->IsScanning())
5620 m_musicInfoScanner->Stop();
5623 void CApplication::StartVideoCleanup()
5625 if (m_videoInfoScanner->IsScanning())
5628 m_videoInfoScanner->CleanDatabase();
5631 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5633 if (m_videoInfoScanner->IsScanning())
5636 m_videoInfoScanner->ShowDialog(true);
5638 m_videoInfoScanner->Start(strDirectory,scanAll);
5641 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5643 if (m_musicInfoScanner->IsScanning())
5647 { // setup default flags
5648 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5649 flags |= CMusicInfoScanner::SCAN_ONLINE;
5650 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5651 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5654 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5655 m_musicInfoScanner->ShowDialog(true);
5657 m_musicInfoScanner->Start(strDirectory, flags);
5660 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5663 if (m_musicInfoScanner->IsScanning())
5666 m_musicInfoScanner->ShowDialog(true);
5668 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5671 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5674 if (m_musicInfoScanner->IsScanning())
5677 m_musicInfoScanner->ShowDialog(true);
5679 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5682 void CApplication::CheckPlayingProgress()
5684 // check if we haven't rewound past the start of the file
5685 if (m_pPlayer->IsPlaying())
5687 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5697 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5699 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5700 g_application.SeekTime(0);
5706 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5708 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5710 // initial exit conditions
5711 // no songs in playlist just return
5712 if (playlist.size() == 0)
5716 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5719 // setup correct playlist
5720 g_playlistPlayer.ClearPlaylist(iPlaylist);
5722 // if the playlist contains an internet stream, this file will be used
5723 // to generate a thumbnail for musicplayer.cover
5724 g_application.m_strPlayListFile = strPlayList;
5726 // add the items to the playlist player
5727 g_playlistPlayer.Add(iPlaylist, playlist);
5729 // if we have a playlist
5730 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5733 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5734 g_playlistPlayer.Reset();
5735 g_playlistPlayer.Play(track);
5741 void CApplication::SaveCurrentFileSettings()
5743 // don't store settings for PVR in video database
5744 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5746 // save video settings
5747 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5751 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5755 else if (m_itemCurrentFile->IsPVRChannel())
5757 g_PVRManager.SaveCurrentChannelSettings();
5761 bool CApplication::AlwaysProcess(const CAction& action)
5763 // check if this button is mapped to a built-in function
5764 if (!action.GetName().empty())
5766 CStdString builtInFunction;
5767 vector<CStdString> params;
5768 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5769 StringUtils::ToLower(builtInFunction);
5771 // should this button be handled normally or just cancel the screensaver?
5772 if ( builtInFunction.Equals("powerdown")
5773 || builtInFunction.Equals("reboot")
5774 || builtInFunction.Equals("restart")
5775 || builtInFunction.Equals("restartapp")
5776 || builtInFunction.Equals("suspend")
5777 || builtInFunction.Equals("hibernate")
5778 || builtInFunction.Equals("quit")
5779 || builtInFunction.Equals("shutdown"))
5788 bool CApplication::IsCurrentThread() const
5790 return CThread::IsCurrentThread(m_threadID);
5793 void CApplication::SetRenderGUI(bool renderGUI)
5795 if (renderGUI && ! m_renderGUI)
5796 g_windowManager.MarkDirty();
5797 m_renderGUI = renderGUI;
5800 CNetwork& CApplication::getNetwork()
5804 #ifdef HAS_PERFORMANCE_SAMPLE
5805 CPerformanceStats &CApplication::GetPerformanceStats()
5811 bool CApplication::SetLanguage(const CStdString &strLanguage)
5813 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5814 CStdString strNewLanguage = strLanguage;
5815 if (strNewLanguage != strPreviousLanguage)
5817 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5818 if (!g_langInfo.Load(strLangInfoPath))
5821 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5823 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5824 CStdString strFontSet;
5825 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5826 strNewLanguage = strFontSet;
5828 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5830 CSettings::Get().SetString("locale.language", strNewLanguage);
5832 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5835 // also tell our weather and skin to reload as these are localized
5836 g_weatherManager.Refresh();
5837 g_PVRManager.LocalizationChanged();
5844 void CApplication::CloseNetworkShares()
5846 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5848 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5852 #ifdef HAS_FILESYSTEM_NFS
5853 gNfsConnection.Deinit();
5856 #ifdef HAS_FILESYSTEM_AFP
5857 gAfpConnection.Deinit();
5860 #ifdef HAS_FILESYSTEM_SFTP
5861 CSFTPSessionManager::DisconnectAllSessions();