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"
342 #ifdef TARGET_WINDOWS
343 #include "utils/Environment.h"
346 #if defined(HAS_LIBAMCODEC)
347 #include "utils/AMLUtils.h"
351 using namespace ADDON;
352 using namespace XFILE;
354 using namespace MEDIA_DETECT;
356 using namespace PLAYLIST;
357 using namespace VIDEO;
358 using namespace MUSIC_INFO;
359 #ifdef HAS_EVENT_SERVER
360 using namespace EVENTSERVER;
363 using namespace JSONRPC;
365 using namespace ANNOUNCEMENT;
368 using namespace PERIPHERALS;
370 using namespace XbmcThreads;
372 // uncomment this if you want to use release libs in the debug build.
373 // Atm this saves you 7 mb of memory
374 #define USE_RELEASE_LIBS
376 #define MAX_FFWD_SPEED 5
378 //extern IDirectSoundRenderer* m_pAudioDecoder;
379 CApplication::CApplication(void)
380 : m_pPlayer(new CApplicationPlayer)
381 , m_itemCurrentFile(new CFileItem)
382 , m_stackFileItemToUpdate(new CFileItem)
383 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
384 , m_progressTrackingItem(new CFileItem)
385 , m_videoInfoScanner(new CVideoInfoScanner)
386 , m_musicInfoScanner(new CMusicInfoScanner)
387 , m_seekHandler(new CSeekHandler)
388 , m_playerController(new CPlayerController)
391 TiXmlBase::SetCondenseWhiteSpace(false);
392 m_bInhibitIdleShutdown = false;
393 m_bScreenSave = false;
395 m_dpmsIsActive = false;
396 m_dpmsIsManual = false;
397 m_iScreenSaveLock = 0;
398 m_bInitializing = true;
399 m_eForcedNextPlayer = EPC_NONE;
400 m_strPlayListFile = "";
401 m_nextPlaylistItem = -1;
402 m_bPlaybackStarting = false;
403 m_ePlayState = PLAY_STATE_NONE;
404 m_skinReloading = false;
405 m_skinReverting = false;
412 // we start in frontend
413 m_bInBackground = false;
415 /* for now always keep this around */
417 m_pKaraokeMgr = new CKaraokeLyricsManager();
419 m_currentStack = new CFileItemList;
421 m_bPresentFrame = false;
422 m_bPlatformDirectories = true;
424 m_bStandalone = false;
425 m_bEnableLegacyRes = false;
426 m_bSystemScreenSaverEnable = false;
427 m_pInertialScrollingHandler = new CInertialScrollingHandler();
429 m_Autorun = new CAutorun();
434 m_progressTrackingPlayCountUpdate = false;
435 m_currentStackPosition = 0;
437 m_lastRenderTime = 0;
441 m_volumeLevel = 1.0f;
444 CApplication::~CApplication(void)
446 delete m_musicInfoScanner;
447 delete m_videoInfoScanner;
448 delete &m_progressTrackingVideoResumeBookmark;
452 delete m_currentStack;
455 delete m_pKaraokeMgr;
459 delete m_seekHandler;
460 delete m_playerController;
461 delete m_pInertialScrollingHandler;
465 bool CApplication::OnEvent(XBMC_Event& newEvent)
467 switch(newEvent.type)
470 if (!g_application.m_bStop)
471 CApplicationMessenger::Get().Quit();
474 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
477 g_Keyboard.ProcessKeyUp();
479 case XBMC_MOUSEBUTTONDOWN:
480 case XBMC_MOUSEBUTTONUP:
481 case XBMC_MOUSEMOTION:
482 g_Mouse.HandleEvent(newEvent);
483 g_application.ProcessMouse();
485 case XBMC_VIDEORESIZE:
486 if (!g_application.m_bInitializing &&
487 !g_advancedSettings.m_fullScreen)
489 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
490 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
491 CSettings::Get().SetInt("window.width", newEvent.resize.w);
492 CSettings::Get().SetInt("window.height", newEvent.resize.h);
493 CSettings::Get().Save();
497 #ifdef TARGET_WINDOWS
498 if (g_advancedSettings.m_fullScreen)
500 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
501 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
502 if (newRes != g_graphicsContext.GetVideoResolution())
503 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
508 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
512 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
514 case XBMC_APPCOMMAND:
515 return g_application.OnAppCommand(newEvent.appcommand.action);
518 int windowId = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
520 if (newEvent.touch.action == ACTION_TOUCH_TAP)
521 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
522 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
525 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
527 actionId = newEvent.touch.action;
528 windowId = WINDOW_INVALID;
530 else if (!CButtonTranslator::GetInstance().TranslateTouchAction(newEvent.touch.action, newEvent.touch.pointers, windowId, actionId) ||
534 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), windowId, false);
535 // Post an unfocus message for touch device after the action.
536 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
538 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
539 CApplicationMessenger::Get().SendGUIMessage(msg);
547 extern "C" void __stdcall init_emu_environ();
548 extern "C" void __stdcall update_emu_environ();
551 // Utility function used to copy files from the application bundle
552 // over to the user data directory in Application Support/XBMC.
554 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
556 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
557 if (!CFile::Exists(destPath))
559 // need to copy it across
560 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
561 CFile::Cache(srcPath, destPath);
565 void CApplication::Preflight()
568 // call 'dbus_threads_init_default' before any other dbus calls in order to
569 // avoid race conditions with other threads using dbus connections
570 dbus_threads_init_default();
573 // run any platform preflight scripts.
574 #if defined(TARGET_DARWIN_OSX)
575 CStdString install_path;
577 CUtil::GetHomePath(install_path);
578 setenv("XBMC_HOME", install_path.c_str(), 0);
579 install_path += "/tools/darwin/runtime/preflight";
580 system(install_path.c_str());
584 bool CApplication::Create()
586 #if defined(HAS_LINUX_NETWORK)
587 m_network = new CNetworkLinux();
588 #elif defined(HAS_WIN32_NETWORK)
589 m_network = new CNetworkWin32();
591 m_network = new CNetwork();
596 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
598 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
599 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
603 tzset(); // Initialize timezone information variables
606 // Grab a handle to our thread to be used later in identifying the render thread.
607 m_threadID = CThread::GetCurrentThreadId();
610 //floating point precision to 24 bits (faster performance)
611 _controlfp(_PC_24, _MCW_PC);
613 /* install win32 exception translator, win32 exceptions
614 * can now be caught using c++ try catch */
615 win32_exception::install_handler();
619 // only the InitDirectories* for the current platform should return true
620 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
621 bool inited = InitDirectoriesLinux();
623 inited = InitDirectoriesOSX();
625 inited = InitDirectoriesWin32();
627 // copy required files
628 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
629 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
630 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
632 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
634 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
635 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
639 // Init our DllLoaders emu env
642 CProfilesManager::Get().Load();
644 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
645 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetCpuFamily().c_str(),
646 g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness());
648 /* Expand macro before stringify */
649 #define STR_MACRO(x) #x
650 #define XSTR_MACRO(x) STR_MACRO(x)
652 std::string compilerStr;
653 #if defined(__clang__)
654 compilerStr = "Clang " XSTR_MACRO(__clang_major__) "." XSTR_MACRO(__clang_minor__) "." XSTR_MACRO(__clang_patchlevel__);
655 #elif defined (__INTEL_COMPILER)
656 compilerStr = "Intel Compiler " XSTR_MACRO(__INTEL_COMPILER);
657 #elif defined (__GNUC__)
659 /* Note: this will not detect GCC + DragonEgg */
660 compilerStr = "llvm-gcc ";
662 compilerStr = "GCC ";
664 compilerStr += XSTR_MACRO(__GNUC__) "." XSTR_MACRO(__GNUC_MINOR__) "." XSTR_MACRO(__GNUC_PATCHLEVEL__);
665 #elif defined (_MSC_VER)
666 compilerStr = "MSVC " XSTR_MACRO(_MSC_FULL_VER);
668 compilerStr = "unknown compiler";
670 std::string buildType;
673 #elif defined(NDEBUG)
674 buildType = "Release";
676 buildType = "Unknown";
678 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(),
679 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersion().c_str());
681 #if defined(TARGET_DARWIN_OSX)
682 CLog::Log(LOGNOTICE, "Running on Darwin OSX %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
683 #elif defined(TARGET_DARWIN_IOS)
684 CLog::Log(LOGNOTICE, "Running on Darwin iOS %d-bit %s%s", g_sysinfo.GetKernelBitness(), g_sysinfo.IsAppleTV2() ? "(AppleTV2) " : "", g_sysinfo.GetUnameVersion().c_str());
685 #elif defined(TARGET_FREEBSD)
686 CLog::Log(LOGNOTICE, "Running on FreeBSD %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
687 #elif defined(TARGET_POSIX)
688 CLog::Log(LOGNOTICE, "Running on Linux %d-bit (%s, %s)", g_sysinfo.GetKernelBitness(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
689 #elif defined(TARGET_WINDOWS)
690 CLog::Log(LOGNOTICE, "Running on %s", g_sysinfo.GetKernelVersion().c_str());
693 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", g_cpuInfo.getCPUModel().c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount()==1) ? "" : "s");
694 #if defined(TARGET_WINDOWS)
695 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
696 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
697 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
700 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
701 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
703 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
705 CSpecialProtocol::LogPaths();
707 CStdString executable = CUtil::ResolveExecutablePath();
708 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
709 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
710 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
711 CRegExp::LogCheckUtf8Support();
712 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
714 CStdString strExecutablePath;
715 CUtil::GetHomePath(strExecutablePath);
718 g_xrandr.LoadCustomModeLinesToAllOutputs();
721 // for python scripts that check the OS
722 #if defined(TARGET_DARWIN)
723 setenv("OS","OS X",true);
724 #elif defined(TARGET_POSIX)
725 setenv("OS","Linux",true);
726 #elif defined(TARGET_WINDOWS)
727 CEnvironment::setenv("OS", "win32");
730 g_powerManager.Initialize();
732 // Load the AudioEngine before settings as they need to query the engine
733 if (!CAEFactory::LoadEngine())
735 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
739 // Initialize default Settings - don't move
740 CLog::Log(LOGNOTICE, "load settings...");
741 if (!CSettings::Get().Initialize())
744 g_powerManager.SetDefaults();
746 // load the actual values
747 if (!CSettings::Get().Load())
749 CLog::Log(LOGFATAL, "unable to load settings");
752 CSettings::Get().SetLoaded();
754 CLog::Log(LOGINFO, "creating subdirectories");
755 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
756 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
757 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
758 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
759 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
760 CProfilesManager::Get().CreateProfileFolders();
762 update_emu_environ();//apply the GUI settings
764 // Load the langinfo to have user charset <-> utf-8 conversion
765 CStdString strLanguage = CSettings::Get().GetString("locale.language");
766 strLanguage[0] = toupper(strLanguage[0]);
768 CStdString strLangInfoPath;
769 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
771 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
772 g_langInfo.Load(strLangInfoPath);
773 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
774 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
776 CStdString strLanguagePath = "special://xbmc/language/";
778 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
779 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
781 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
785 // start the AudioEngine
786 if (!CAEFactory::StartEngine())
788 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
792 // restore AE's previous volume state
793 SetHardwareVolume(m_volumeLevel);
794 CAEFactory::SetMute (m_muted);
795 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
797 // initialize m_replayGainSettings
798 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
799 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
800 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
801 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
803 // initialize the addon database (must be before the addon manager is init'd)
804 CDatabaseManager::Get().Initialize(true);
807 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
810 // start-up Addons Framework
811 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
812 if (!CAddonMgr::Get().Init())
814 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
817 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
818 g_RemoteControl.Initialize();
821 // set logging from debug add-on
823 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
825 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
827 g_peripherals.Initialise();
829 // Create the Mouse, Keyboard, Remote, and Joystick devices
830 // Initialize after loading settings to get joystick deadzone setting
831 g_Mouse.Initialize();
832 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
834 g_Keyboard.Initialize();
836 #if defined(TARGET_DARWIN_OSX)
837 // Configure and possible manually start the helper.
838 XBMCHelper::GetInstance().Configure();
841 CUtil::InitRandomSeed();
843 g_mediaManager.Initialize();
845 m_lastFrameTime = XbmcThreads::SystemClockMillis();
846 m_lastRenderTime = m_lastFrameTime;
850 bool CApplication::CreateGUI()
854 CLog::Log(LOGNOTICE, "Setup SDL");
856 /* Clean up on exit, exit on window close and interrupt */
859 uint32_t sdlFlags = 0;
861 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
862 sdlFlags |= SDL_INIT_VIDEO;
865 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
866 sdlFlags |= SDL_INIT_JOYSTICK;
869 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
870 //this might bring the monitor out of standby, so we have to disable it explicitly
871 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
872 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
873 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
879 // for nvidia cards - vsync currently ALWAYS enabled.
880 // the reason is that after screen has been setup changing this env var will make no difference.
881 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
882 setenv("__GL_YIELD", "USLEEP", 0);
885 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
886 g_Windowing.EnableSystemScreenSaver(false);
889 if (SDL_Init(sdlFlags) != 0)
891 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
894 #if defined(TARGET_DARWIN)
895 // SDL_Init will install a handler for segfaults, restore the default handler.
896 signal(SIGSEGV, SIG_DFL);
900 // Initialize core peripheral port support. Note: If these parameters
901 // are 0 and NULL, respectively, then the default number and types of
902 // controllers will be initialized.
903 if (!g_Windowing.InitWindowSystem())
905 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
909 // Retrieve the matching resolution based on GUI settings
910 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
911 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
912 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
914 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
915 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
918 // update the window resolution
919 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
921 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
922 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
924 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
926 // Oh uh - doesn't look good for starting in their wanted screenmode
927 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
928 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
935 if (g_advancedSettings.m_splashImage)
937 CStdString strUserSplash = "special://home/media/Splash.png";
938 if (CFile::Exists(strUserSplash))
940 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
941 m_splash = new CSplash(strUserSplash);
945 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
946 m_splash = new CSplash("special://xbmc/media/Splash.png");
951 // The key mappings may already have been loaded by a peripheral
952 CLog::Log(LOGINFO, "load keymapping");
953 if (!CButtonTranslator::GetInstance().Load())
956 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
957 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
960 info.strMode.c_str());
961 g_windowManager.Initialize();
966 bool CApplication::InitWindow()
968 #ifdef TARGET_DARWIN_OSX
969 // force initial window creation to be windowed, if fullscreen, it will switch to it below
970 // fixes the white screen of death if starting fullscreen and switching to windowed.
971 bool bFullScreen = false;
972 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
974 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
978 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
979 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
981 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
986 if (!g_Windowing.InitRenderSystem())
988 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
991 // set GUI res and force the clear of the screen
992 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
996 bool CApplication::DestroyWindow()
998 return g_Windowing.DestroyWindow();
1001 bool CApplication::InitDirectoriesLinux()
1004 The following is the directory mapping for Platform Specific Mode:
1006 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1007 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1008 installations like skins, screensavers, etc.
1010 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1011 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1012 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1013 special://profile/ => [read-write] current profile's userdata directory.
1014 Generally special://masterprofile for the master profile or
1015 special://masterprofile/profiles/<profile_name> for other profiles.
1017 NOTE: All these root directories are lowercase. Some of the sub-directories
1018 might be mixed case.
1021 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1022 CStdString userName;
1024 userName = getenv("USER");
1028 CStdString userHome;
1030 userHome = getenv("HOME");
1034 CStdString xbmcBinPath, xbmcPath;
1035 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1036 xbmcPath = getenv("XBMC_HOME");
1038 if (xbmcPath.IsEmpty())
1040 xbmcPath = xbmcBinPath;
1041 /* Check if xbmc binaries and arch independent data files are being kept in
1042 * separate locations. */
1043 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1045 /* Attempt to locate arch independent data files. */
1046 CUtil::GetHomePath(xbmcPath);
1047 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1049 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1055 /* Set some environment variables */
1056 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1057 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1059 if (m_bPlatformDirectories)
1061 // map our special drives
1062 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1063 CSpecialProtocol::SetXBMCPath(xbmcPath);
1064 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1065 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1067 CStdString strTempPath = userHome;
1068 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1069 if (getenv("XBMC_TEMP"))
1070 strTempPath = getenv("XBMC_TEMP");
1071 CSpecialProtocol::SetTempPath(strTempPath);
1073 URIUtils::AddSlashAtEnd(strTempPath);
1074 g_advancedSettings.m_logFolder = strTempPath;
1081 URIUtils::AddSlashAtEnd(xbmcPath);
1082 g_advancedSettings.m_logFolder = xbmcPath;
1084 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1085 CSpecialProtocol::SetXBMCPath(xbmcPath);
1086 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1087 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1089 CStdString strTempPath = xbmcPath;
1090 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1091 if (getenv("XBMC_TEMP"))
1092 strTempPath = getenv("XBMC_TEMP");
1093 CSpecialProtocol::SetTempPath(strTempPath);
1096 URIUtils::AddSlashAtEnd(strTempPath);
1097 g_advancedSettings.m_logFolder = strTempPath;
1106 bool CApplication::InitDirectoriesOSX()
1108 #if defined(TARGET_DARWIN)
1109 CStdString userName;
1111 userName = getenv("USER");
1115 CStdString userHome;
1117 userHome = getenv("HOME");
1121 CStdString xbmcPath;
1122 CUtil::GetHomePath(xbmcPath);
1123 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1125 #if defined(TARGET_DARWIN_IOS)
1126 CStdString fontconfigPath;
1127 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1128 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1131 // setup path to our internal dylibs so loader can find them
1132 CStdString frameworksPath = CUtil::GetFrameworksPath();
1133 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1135 // OSX always runs with m_bPlatformDirectories == true
1136 if (m_bPlatformDirectories)
1138 // map our special drives
1139 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1140 CSpecialProtocol::SetXBMCPath(xbmcPath);
1141 #if defined(TARGET_DARWIN_IOS)
1142 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1143 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1145 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1146 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1149 // location for temp files
1150 #if defined(TARGET_DARWIN_IOS)
1151 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1153 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1154 CDirectory::Create(strTempPath);
1155 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1157 CSpecialProtocol::SetTempPath(strTempPath);
1159 // xbmc.log file location
1160 #if defined(TARGET_DARWIN_IOS)
1161 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1163 strTempPath = userHome + "/Library/Logs";
1165 URIUtils::AddSlashAtEnd(strTempPath);
1166 g_advancedSettings.m_logFolder = strTempPath;
1172 URIUtils::AddSlashAtEnd(xbmcPath);
1173 g_advancedSettings.m_logFolder = xbmcPath;
1175 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1176 CSpecialProtocol::SetXBMCPath(xbmcPath);
1177 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1178 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1180 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1181 CSpecialProtocol::SetTempPath(strTempPath);
1183 URIUtils::AddSlashAtEnd(strTempPath);
1184 g_advancedSettings.m_logFolder = strTempPath;
1193 bool CApplication::InitDirectoriesWin32()
1195 #ifdef TARGET_WINDOWS
1196 CStdString xbmcPath;
1198 CUtil::GetHomePath(xbmcPath);
1199 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1200 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1201 CSpecialProtocol::SetXBMCPath(xbmcPath);
1203 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1205 g_advancedSettings.m_logFolder = strWin32UserFolder;
1206 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1207 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1208 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1210 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1214 // Expand the DLL search path with our directories
1215 CWIN32Util::ExtendDllPath();
1223 void CApplication::CreateUserDirs()
1225 CDirectory::Create("special://home/");
1226 CDirectory::Create("special://home/addons");
1227 CDirectory::Create("special://home/addons/packages");
1228 CDirectory::Create("special://home/media");
1229 CDirectory::Create("special://home/sounds");
1230 CDirectory::Create("special://home/system");
1231 CDirectory::Create("special://masterprofile/");
1232 CDirectory::Create("special://temp/");
1233 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1236 bool CApplication::Initialize()
1238 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1239 // turn off cdio logging
1240 cdio_loglevel_default = CDIO_LOG_ERROR;
1243 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1244 // must create these here. Ideally this should be using special://home/ and
1245 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1246 if (!m_bPlatformDirectories)
1249 CDirectory::Create("special://xbmc/language");
1250 CDirectory::Create("special://xbmc/addons");
1251 CDirectory::Create("special://xbmc/sounds");
1254 // Load curl so curl_global_init gets called before any service threads
1255 // are started. Unloading will have no effect as curl is never fully unloaded.
1256 // To quote man curl_global_init:
1257 // "This function is not thread safe. You must not call it when any other
1258 // thread in the program (i.e. a thread sharing the same memory) is running.
1259 // This doesn't just mean no other thread that is using libcurl. Because
1260 // curl_global_init() calls functions of other libraries that are similarly
1261 // thread unsafe, it could conflict with any other thread that
1262 // uses these other libraries."
1263 g_curlInterface.Load();
1264 g_curlInterface.Unload();
1266 // initialize (and update as needed) our databases
1267 CDatabaseManager::Get().Initialize();
1271 // Init DPMS, before creating the corresponding setting control.
1272 m_dpms = new DPMSSupport();
1273 if (g_windowManager.Initialized())
1275 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1277 g_windowManager.Add(new CGUIWindowHome);
1278 g_windowManager.Add(new CGUIWindowPrograms);
1279 g_windowManager.Add(new CGUIWindowPictures);
1280 g_windowManager.Add(new CGUIWindowFileManager);
1281 g_windowManager.Add(new CGUIWindowSettings);
1282 g_windowManager.Add(new CGUIWindowSystemInfo);
1284 g_windowManager.Add(new CGUIWindowTestPatternGL);
1287 g_windowManager.Add(new CGUIWindowTestPatternDX);
1289 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1290 g_windowManager.Add(new CGUIWindowSettingsCategory);
1291 g_windowManager.Add(new CGUIWindowVideoNav);
1292 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1293 g_windowManager.Add(new CGUIWindowLoginScreen);
1294 g_windowManager.Add(new CGUIWindowSettingsProfile);
1295 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1296 g_windowManager.Add(new CGUIWindowAddonBrowser);
1297 g_windowManager.Add(new CGUIWindowScreensaverDim);
1298 g_windowManager.Add(new CGUIWindowDebugInfo);
1299 g_windowManager.Add(new CGUIWindowPointer);
1300 g_windowManager.Add(new CGUIDialogYesNo);
1301 g_windowManager.Add(new CGUIDialogProgress);
1302 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1303 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1304 g_windowManager.Add(new CGUIDialogVolumeBar);
1305 g_windowManager.Add(new CGUIDialogSeekBar);
1306 g_windowManager.Add(new CGUIDialogSubMenu);
1307 g_windowManager.Add(new CGUIDialogContextMenu);
1308 g_windowManager.Add(new CGUIDialogKaiToast);
1309 g_windowManager.Add(new CGUIDialogNumeric);
1310 g_windowManager.Add(new CGUIDialogGamepad);
1311 g_windowManager.Add(new CGUIDialogButtonMenu);
1312 g_windowManager.Add(new CGUIDialogMuteBug);
1313 g_windowManager.Add(new CGUIDialogPlayerControls);
1315 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1316 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1318 g_windowManager.Add(new CGUIDialogSlider);
1319 g_windowManager.Add(new CGUIDialogMusicOSD);
1320 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1321 g_windowManager.Add(new CGUIDialogVideoSettings);
1322 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1323 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1324 // Don't add the filebrowser dialog - it's created and added when it's needed
1325 g_windowManager.Add(new CGUIDialogNetworkSetup);
1326 g_windowManager.Add(new CGUIDialogMediaSource);
1327 g_windowManager.Add(new CGUIDialogProfileSettings);
1328 g_windowManager.Add(new CGUIDialogFavourites);
1329 g_windowManager.Add(new CGUIDialogSongInfo);
1330 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1331 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1332 g_windowManager.Add(new CGUIDialogBusy);
1333 g_windowManager.Add(new CGUIDialogPictureInfo);
1334 g_windowManager.Add(new CGUIDialogAddonInfo);
1335 g_windowManager.Add(new CGUIDialogAddonSettings);
1336 #ifdef HAS_LINUX_NETWORK
1337 g_windowManager.Add(new CGUIDialogAccessPoints);
1340 g_windowManager.Add(new CGUIDialogLockSettings);
1342 g_windowManager.Add(new CGUIDialogContentSettings);
1344 g_windowManager.Add(new CGUIDialogPlayEject);
1346 g_windowManager.Add(new CGUIDialogPeripheralManager);
1347 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1349 g_windowManager.Add(new CGUIDialogMediaFilter);
1350 g_windowManager.Add(new CGUIDialogSubtitles);
1352 g_windowManager.Add(new CGUIWindowMusicPlayList);
1353 g_windowManager.Add(new CGUIWindowMusicSongs);
1354 g_windowManager.Add(new CGUIWindowMusicNav);
1355 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1357 /* Load PVR related Windows and Dialogs */
1358 g_windowManager.Add(new CGUIDialogTeletext);
1359 g_windowManager.Add(new CGUIWindowPVR);
1360 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1361 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1362 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1363 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1364 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1365 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1366 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1367 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1368 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1369 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1371 g_windowManager.Add(new CGUIDialogSelect);
1372 g_windowManager.Add(new CGUIDialogMusicInfo);
1373 g_windowManager.Add(new CGUIDialogOK);
1374 g_windowManager.Add(new CGUIDialogVideoInfo);
1375 g_windowManager.Add(new CGUIDialogTextViewer);
1376 g_windowManager.Add(new CGUIWindowFullScreen);
1377 g_windowManager.Add(new CGUIWindowVisualisation);
1378 g_windowManager.Add(new CGUIWindowSlideShow);
1379 g_windowManager.Add(new CGUIDialogFileStacking);
1381 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1384 g_windowManager.Add(new CGUIDialogVideoOSD);
1385 g_windowManager.Add(new CGUIDialogMusicOverlay);
1386 g_windowManager.Add(new CGUIDialogVideoOverlay);
1387 g_windowManager.Add(new CGUIWindowScreensaver);
1388 g_windowManager.Add(new CGUIWindowWeather);
1389 g_windowManager.Add(new CGUIWindowStartup);
1391 /* window id's 3000 - 3100 are reserved for python */
1393 // Make sure we have at least the default skin
1394 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1395 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1397 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1401 if (g_advancedSettings.m_splashImage)
1402 SAFE_DELETE(m_splash);
1404 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1405 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1406 !CProfilesManager::Get().GetMasterProfile().getLockCode().IsEmpty())
1408 g_passwordManager.CheckStartUpLock();
1411 // check if we should use the login screen
1412 if (CProfilesManager::Get().UsingLoginScreen())
1413 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1417 CJSONRPC::Initialize();
1419 ADDON::CAddonMgr::Get().StartServices(false);
1420 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1422 g_windowManager.ActivateWindow(WINDOW_HOME);
1423 StartPVRManager(true);
1427 StartPVRManager(false);
1428 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1431 CStereoscopicsManager::Get().Initialize();
1435 else //No GUI Created
1438 CJSONRPC::Initialize();
1440 ADDON::CAddonMgr::Get().StartServices(false);
1443 g_sysinfo.Refresh();
1445 CLog::Log(LOGINFO, "removing tempfiles");
1446 CUtil::RemoveTempFiles();
1448 if (!CProfilesManager::Get().UsingLoginScreen())
1454 m_slowTimer.StartZero();
1456 #if defined(HAVE_LIBCRYSTALHD)
1457 CCrystalHD::GetInstance();
1460 CAddonMgr::Get().StartServices(true);
1462 CLog::Log(LOGNOTICE, "initialize done");
1464 m_bInitializing = false;
1466 // reset our screensaver (starts timers etc.)
1469 #ifdef HAS_SDL_JOYSTICK
1470 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1471 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1477 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1483 // the callback will take care of starting/stopping webserver
1484 ret = CSettings::Get().SetBool("services.webserver", bStart);
1487 case ES_AIRPLAYSERVER:
1488 // the callback will take care of starting/stopping airplay
1489 ret = CSettings::Get().SetBool("services.airplay", bStart);
1492 case ES_JSONRPCSERVER:
1493 // the callback will take care of starting/stopping jsonrpc server
1494 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1498 // the callback will take care of starting/stopping upnp server
1499 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1502 case ES_UPNPRENDERER:
1503 // the callback will take care of starting/stopping upnp renderer
1504 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1507 case ES_EVENTSERVER:
1508 // the callback will take care of starting/stopping event server
1509 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1513 // the callback will take care of starting/stopping zeroconf
1514 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1521 CSettings::Get().Save();
1526 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1528 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1529 g_PVRManager.Start(true, bOpenPVRWindow);
1532 void CApplication::StopPVRManager()
1534 CLog::Log(LOGINFO, "stopping PVRManager");
1535 if (g_PVRManager.IsPlaying())
1537 g_PVRManager.Stop();
1538 g_EpgContainer.Stop();
1541 void CApplication::StartServices()
1543 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1544 // Start Thread for DVD Mediatype detection
1545 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1546 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1549 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1550 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1551 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1552 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1553 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1554 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1557 void CApplication::StopServices()
1559 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1561 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1562 CLog::Log(LOGNOTICE, "stop dvd detect media");
1563 m_DetectDVDType.StopThread();
1566 g_peripherals.Clear();
1569 void CApplication::OnSettingChanged(const CSetting *setting)
1571 if (setting == NULL)
1574 const std::string &settingId = setting->GetId();
1575 if (settingId == "lookandfeel.skin" ||
1576 settingId == "lookandfeel.font" ||
1577 settingId == "lookandfeel.skincolors")
1579 // if the skin changes and the current theme is not the default one, reset
1580 // the theme to the default value (which will also change lookandfeel.skincolors
1581 // which in turn will reload the skin
1582 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1583 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1586 std::string builtin("ReloadSkin");
1587 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1588 builtin += "(confirm)";
1589 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1592 else if (settingId == "lookandfeel.skintheme")
1594 // also set the default color theme
1595 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1596 URIUtils::RemoveExtension(colorTheme);
1597 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1598 colorTheme = "defaults";
1600 // check if we have to change the skin color
1601 // if yes, it will trigger a call to ReloadSkin() in
1602 // it's OnSettingChanged() callback
1603 // if no we have to call ReloadSkin() ourselves
1604 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1605 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1607 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1609 else if (settingId == "lookandfeel.skinzoom")
1610 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1611 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1613 // AE is master of audio settings and needs to be informed first
1614 CAEFactory::OnSettingsChange(settingId);
1616 if (settingId == "audiooutput.guisoundmode")
1618 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1620 // this tells player whether to open an audio stream passthrough or PCM
1621 // if this is changed, audio stream has to be reopened
1622 else if (settingId == "audiooutput.passthrough")
1624 CApplicationMessenger::Get().MediaRestart(false);
1627 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1628 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1629 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1630 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1631 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1632 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1633 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1634 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1637 void CApplication::OnSettingAction(const CSetting *setting)
1639 if (setting == NULL)
1642 const std::string &settingId = setting->GetId();
1643 if (settingId == "lookandfeel.skinsettings")
1644 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1645 else if (settingId == "screensaver.preview")
1646 ActivateScreenSaver(true);
1647 else if (settingId == "screensaver.settings")
1650 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1651 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1653 else if (settingId == "videoscreen.guicalibration")
1654 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1655 else if (settingId == "videoscreen.testpattern")
1656 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1659 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1661 if (setting == NULL)
1664 const std::string &settingId = setting->GetId();
1665 if (settingId == "audiooutput.channels")
1667 // check if this is an update from Eden
1668 if (oldSettingId != NULL && oldSettingNode != NULL &&
1669 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1672 CSettingInt* channels = (CSettingInt*)setting;
1673 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1674 ret = channels->SetValue(channels->GetValue() + 1);
1676 // let's just reset the audiodevice settings as well
1677 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1678 CAEFactory::VerifyOutputDevice(audiodevice, false);
1679 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1684 else if (settingId == "screensaver.mode")
1686 CSettingString *screensaverMode = (CSettingString*)setting;
1687 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1688 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1689 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1691 else if (settingId == "scrapers.musicvideosdefault")
1693 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1694 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1696 musicvideoScraper->Reset();
1700 #if defined(HAS_LIBAMCODEC)
1701 else if (settingId == "videoplayer.useamcodec")
1703 // Do not permit amcodec to be used on non-aml platforms.
1704 // The setting will be hidden but the default value is true,
1705 // so change it to false.
1708 CSettingBool *useamcodec = (CSettingBool*)setting;
1709 useamcodec->SetValue(false);
1713 #if defined(TARGET_ANDROID)
1714 else if (settingId == "videoplayer.usemediacodec")
1716 // Do not permit MediaCodec to be used Android platforms that do not have it.
1717 // The setting will be hidden but the default value is true,
1718 // so change it to false.
1719 if (CAndroidFeatures::GetVersion() < 16)
1721 CSettingBool *usemediacodec = (CSettingBool*)setting;
1722 usemediacodec->SetValue(false);
1725 else if (settingId == "videoplayer.usestagefright")
1727 if (CAndroidFeatures::GetVersion() >= 19)
1729 CSettingBool *usestagefright = (CSettingBool*)setting;
1730 usestagefright->SetValue(false);
1738 bool CApplication::OnSettingsSaving() const
1740 // don't save settings when we're busy stopping the application
1741 // a lot of screens try to save settings on deinit and deinit is
1742 // called for every screen when the application is stopping
1749 void CApplication::ReloadSkin(bool confirm/*=false*/)
1751 m_skinReloading = false;
1752 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1754 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1755 g_windowManager.SendMessage(msg);
1757 // Reload the skin, restoring the previously focused control. We need this as
1758 // the window unload will reset all control states.
1760 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1762 iCtrlID = pWindow->GetFocusedControlID();
1764 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1768 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1769 if (pWindow && pWindow->HasSaveLastControl())
1771 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1772 pWindow->OnMessage(msg3);
1776 if (!m_skinReverting && confirm)
1779 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1781 m_skinReverting = true;
1782 if (oldSkin.empty())
1783 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1785 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1789 m_skinReverting = false;
1792 bool CApplication::Load(const TiXmlNode *settings)
1794 if (settings == NULL)
1797 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1798 if (audioElement != NULL)
1800 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1801 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1802 m_volumeLevel = VOLUME_MAXIMUM;
1808 bool CApplication::Save(TiXmlNode *settings) const
1810 if (settings == NULL)
1813 TiXmlElement volumeNode("audio");
1814 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1815 if (audioNode == NULL)
1818 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1819 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1824 bool CApplication::LoadSkin(const CStdString& skinID)
1826 if (m_skinReloading)
1830 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1832 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1838 void CApplication::LoadSkin(const SkinPtr& skin)
1840 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1843 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1844 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1849 if (!skin->HasSkinFile("Home.xml"))
1851 // failed to find home.xml
1852 // fallback to default skin
1853 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1855 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1856 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1857 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1862 bool bPreviousPlayingState=false;
1863 bool bPreviousRenderingState=false;
1864 if (g_application.m_pPlayer->IsPlayingVideo())
1866 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1867 if (bPreviousPlayingState)
1868 g_application.m_pPlayer->Pause();
1869 #ifdef HAS_VIDEO_PLAYBACK
1870 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1872 g_windowManager.ActivateWindow(WINDOW_HOME);
1873 bPreviousRenderingState = true;
1877 // close the music and video overlays (they're re-opened automatically later)
1878 CSingleLock lock(g_graphicsContext);
1880 // save the current window details
1881 int currentWindow = g_windowManager.GetActiveWindow();
1882 vector<int> currentModelessWindows;
1883 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1887 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1889 g_SkinInfo->Start();
1891 CLog::Log(LOGINFO, " load fonts for skin...");
1892 g_graphicsContext.SetMediaDir(skin->Path());
1893 g_directoryCache.ClearSubPaths(skin->Path());
1894 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1896 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1897 CStdString strFontSet;
1898 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1900 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1901 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1902 CSettings::Get().Save();
1905 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1907 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1909 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1911 // load in the skin strings
1912 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1913 URIUtils::AddSlashAtEnd(langPath);
1915 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1917 g_SkinInfo->LoadIncludes();
1920 start = CurrentHostCounter();
1922 CLog::Log(LOGINFO, " load new skin...");
1924 // Load the user windows
1928 end = CurrentHostCounter();
1929 freq = CurrentHostFrequency();
1930 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1932 CLog::Log(LOGINFO, " initialize new skin...");
1933 g_windowManager.AddMsgTarget(this);
1934 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1935 g_windowManager.AddMsgTarget(&g_infoManager);
1936 g_windowManager.AddMsgTarget(&g_fontManager);
1937 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1938 g_windowManager.SetCallback(*this);
1939 g_windowManager.Initialize();
1940 CTextureCache::Get().Initialize();
1941 g_audioManager.Enable(true);
1942 g_audioManager.Load();
1944 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1945 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1947 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1948 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1949 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1950 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1951 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1954 CLog::Log(LOGINFO, " skin loaded...");
1956 // leave the graphics lock
1960 if (currentWindow != WINDOW_INVALID)
1962 g_windowManager.ActivateWindow(currentWindow);
1963 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1965 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1966 if (dialog) dialog->Show();
1970 if (g_application.m_pPlayer->IsPlayingVideo())
1972 if (bPreviousPlayingState)
1973 g_application.m_pPlayer->Pause();
1974 if (bPreviousRenderingState)
1975 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1979 void CApplication::UnloadSkin(bool forReload /* = false */)
1981 m_skinReloading = forReload;
1983 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1985 g_audioManager.Enable(false);
1987 g_windowManager.DeInitialize();
1988 CTextureCache::Get().Deinitialize();
1990 // remove the skin-dependent window
1991 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1993 g_TextureManager.Cleanup();
1994 g_largeTextureManager.CleanupUnusedImages(true);
1996 g_fontManager.Clear();
1998 g_colorManager.Clear();
2000 g_infoManager.Clear();
2002 // The g_SkinInfo boost shared_ptr ought to be reset here
2003 // but there are too many places it's used without checking for NULL
2004 // and as a result a race condition on exit can cause a crash.
2007 bool CApplication::LoadUserWindows()
2009 // Start from wherever home.xml is
2010 std::vector<CStdString> vecSkinPath;
2011 g_SkinInfo->GetSkinPaths(vecSkinPath);
2012 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2014 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2015 CFileItemList items;
2016 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2018 for (int i = 0; i < items.Size(); ++i)
2020 if (items[i]->m_bIsFolder)
2022 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2023 if (skinFile.Left(6).CompareNoCase("custom") == 0)
2025 CXBMCTinyXML xmlDoc;
2026 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2028 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2032 // Root element should be <window>
2033 TiXmlElement* pRootElement = xmlDoc.RootElement();
2034 CStdString strValue = pRootElement->Value();
2035 if (!strValue.Equals("window"))
2037 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2041 // Read the <type> element to get the window type to create
2042 // If no type is specified, create a CGUIWindow as default
2043 CGUIWindow* pWindow = NULL;
2045 if (pRootElement->Attribute("type"))
2046 strType = pRootElement->Attribute("type");
2049 const TiXmlNode *pType = pRootElement->FirstChild("type");
2050 if (pType && pType->FirstChild())
2051 strType = pType->FirstChild()->Value();
2053 int id = WINDOW_INVALID;
2054 if (!pRootElement->Attribute("id", &id))
2056 const TiXmlNode *pType = pRootElement->FirstChild("id");
2057 if (pType && pType->FirstChild())
2058 id = atol(pType->FirstChild()->Value());
2060 CStdString visibleCondition;
2061 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2063 if (strType.Equals("dialog"))
2064 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2065 else if (strType.Equals("submenu"))
2066 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2067 else if (strType.Equals("buttonmenu"))
2068 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2070 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2072 // Check to make sure the pointer isn't still null
2073 if (pWindow == NULL)
2075 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2078 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2083 pWindow->SetVisibleCondition(visibleCondition);
2084 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2085 g_windowManager.AddCustomWindow(pWindow);
2093 bool CApplication::RenderNoPresent()
2097 // DXMERGE: This may have been important?
2098 // g_graphicsContext.AcquireCurrentContext();
2100 g_graphicsContext.Lock();
2102 // dont show GUI when playing full screen video
2103 if (g_graphicsContext.IsFullScreenVideo())
2105 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2106 g_renderManager.Render(true, 0, 255);
2108 // close window overlays
2109 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2110 if (overlay) overlay->Close(true);
2111 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2112 if (overlay) overlay->Close(true);
2116 bool hasRendered = g_windowManager.Render();
2118 g_graphicsContext.Unlock();
2123 float CApplication::GetDimScreenSaverLevel() const
2125 if (!m_bScreenSave || !m_screenSaver ||
2126 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2127 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2128 !m_screenSaver->ID().empty()))
2131 if (!m_screenSaver->GetSetting("level").IsEmpty())
2132 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2136 void CApplication::Render()
2138 // do not render if we are stopped or in background
2139 if (m_bStop || m_bInBackground)
2144 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2146 bool hasRendered = false;
2147 bool limitFrames = false;
2148 unsigned int singleFrameTime = 10; // default limit 100 fps
2152 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2153 // Whether externalplayer is playing and we're unfocused
2154 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2156 m_bPresentFrame = false;
2157 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2159 m_bPresentFrame = g_renderManager.FrameWait(100);
2164 // engage the frame limiter as needed
2165 limitFrames = lowfps || extPlayerActive;
2166 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2167 // perhaps allowing it to be set differently than the UI option??
2168 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2169 limitFrames = true; // not using vsync.
2170 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2171 limitFrames = true; // using vsync, but it isn't working.
2175 if (extPlayerActive)
2177 ResetScreenSaver(); // Prevent screensaver dimming the screen
2178 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2181 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2187 CSingleLock lock(g_graphicsContext);
2188 g_infoManager.UpdateFPS();
2190 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2191 g_Windowing.SetVSync(true);
2192 else if (vsync_mode == VSYNC_ALWAYS)
2193 g_Windowing.SetVSync(true);
2194 else if (vsync_mode != VSYNC_DRIVER)
2195 g_Windowing.SetVSync(false);
2197 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2200 if(!g_Windowing.BeginRender())
2203 g_renderManager.FrameMove();
2205 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2206 if(g_graphicsContext.GetStereoMode())
2208 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2209 if(RenderNoPresent())
2212 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2214 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2215 if(RenderNoPresent())
2218 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2222 if(RenderNoPresent())
2226 g_renderManager.FrameFinish();
2228 g_Windowing.EndRender();
2230 // execute post rendering actions (finalize window closing)
2231 g_windowManager.AfterRender();
2233 // reset our info cache - we do this at the end of Render so that it is
2234 // fresh for the next process(), or after a windowclose animation (where process()
2236 g_infoManager.ResetCache();
2239 unsigned int now = XbmcThreads::SystemClockMillis();
2241 m_lastRenderTime = now;
2243 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2244 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2246 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2247 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2251 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2252 if (limitFrames || !flip)
2255 singleFrameTime = 40; //if not flipping, loop at 25 fps
2257 unsigned int frameTime = now - m_lastFrameTime;
2258 if (frameTime < singleFrameTime)
2259 Sleep(singleFrameTime - frameTime);
2261 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2264 g_graphicsContext.Flip(dirtyRegions);
2265 CTimeUtils::UpdateFrameTime(flip);
2267 g_renderManager.UpdateResolution();
2268 g_renderManager.ManageCaptures();
2271 void CApplication::SetStandAlone(bool value)
2273 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2276 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2277 // The window manager will return true if the event is processed, false otherwise.
2278 // If not already processed, this routine handles global keypresses. It returns
2279 // true if the key has been processed, false otherwise.
2281 bool CApplication::OnKey(const CKey& key)
2284 // Turn the mouse off, as we've just got a keypress from controller or remote
2285 g_Mouse.SetActive(false);
2287 // get the current active window
2288 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2290 // this will be checked for certain keycodes that need
2291 // special handling if the screensaver is active
2292 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2294 // a key has been pressed.
2296 m_idleTimer.StartZero();
2297 bool processKey = AlwaysProcess(action);
2299 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2303 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2304 // do not wake up the screensaver right after switching off the playing device
2305 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2306 ret = CApplicationMessenger::Get().CECToggleState();
2308 ret = CApplicationMessenger::Get().CECStandby();
2309 if (!ret) /* display is switched off */
2315 // allow some keys to be processed while the screensaver is active
2316 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2318 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2322 // change this if we have a dialog up
2323 if (g_windowManager.HasModalDialog())
2325 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2327 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2328 { // fullscreen info dialog - special case
2329 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2331 if (!key.IsAnalogButton())
2332 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2334 if (OnAction(action))
2337 // fallthrough to the main window
2338 iWin = WINDOW_FULLSCREEN_VIDEO;
2340 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2342 // current active window is full screen video.
2343 if (g_application.m_pPlayer->IsInMenu())
2345 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2346 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2348 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2350 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2351 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2353 // if no PVR specific action/mapping is found, fall back to default
2354 if (action.GetID() == 0)
2355 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2359 // in any other case use the fullscreen window section of keymap.xml to map key->action
2360 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2365 // current active window isnt the fullscreen window
2366 // just use corresponding section from keymap.xml
2367 // to map key->action
2369 // first determine if we should use keyboard input directly
2370 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2371 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2374 CGUIControl *control = window->GetFocusedControl();
2377 // If this is an edit control set usekeyboard to true. This causes the
2378 // keypress to be processed directly not through the key mappings.
2379 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2382 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2383 // This causes the keypress to be used for list navigation.
2384 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2390 action = CAction(0); // reset our action
2391 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2393 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2394 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2395 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2396 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2397 action.GetID() == ACTION_MOVE_RIGHT ||
2398 action.GetID() == ACTION_MOVE_UP ||
2399 action.GetID() == ACTION_MOVE_DOWN ||
2400 action.GetID() == ACTION_SELECT_ITEM ||
2401 action.GetID() == ACTION_ENTER ||
2402 action.GetID() == ACTION_PREVIOUS_MENU ||
2403 action.GetID() == ACTION_NAV_BACK))
2405 // the action isn't plain navigation - check for a keyboard-specific keymap
2406 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2407 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2408 action.GetID() == ACTION_BACKSPACE ||
2409 action.GetID() == ACTION_SHIFT ||
2410 action.GetID() == ACTION_SYMBOLS ||
2411 action.GetID() == ACTION_CURSOR_LEFT ||
2412 action.GetID() == ACTION_CURSOR_RIGHT)
2413 action = CAction(0); // don't bother with this action
2416 if (!action.GetID())
2418 // keyboard entry - pass the keys through directly
2419 if (key.GetFromService())
2420 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2423 // Check for paste keypress
2424 #ifdef TARGET_WINDOWS
2425 // In Windows paste is ctrl-V
2426 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2427 #elif defined(TARGET_LINUX)
2428 // In Linux paste is ctrl-V
2429 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2430 #elif defined(TARGET_DARWIN_OSX)
2431 // In OSX paste is cmd-V
2432 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2434 // Placeholder for other operating systems
2437 action = CAction(ACTION_PASTE);
2438 // If the unicode is non-zero the keypress is a non-printing character
2439 else if (key.GetUnicode())
2440 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2441 // The keypress is a non-printing character
2443 action = CAction(key.GetVKey() | KEY_VKEY);
2447 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2449 if (OnAction(action))
2451 // failed to handle the keyboard action, drop down through to standard action
2453 if (key.GetFromService())
2455 if (key.GetButtonCode() != KEY_INVALID)
2456 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2459 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2461 if (!key.IsAnalogButton())
2462 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2464 return ExecuteInputAction(action);
2467 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2468 // This needs to return true if it processed the appcommand or false if it didn't
2469 bool CApplication::OnAppCommand(const CAction &action)
2471 // Reset the screen saver
2474 // If we were currently in the screen saver wake up and don't process the appcommand
2475 if (WakeUpScreenSaverAndDPMS())
2478 // The action ID is the APPCOMMAND code. We need to retrieve the action
2479 // associated with this appcommand from the mapping table.
2480 uint32_t appcmd = action.GetID();
2481 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2482 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2483 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2485 // If we couldn't find an action return false to indicate we have not
2486 // handled this appcommand
2487 if (!appcmdaction.GetID())
2489 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2493 // Process the appcommand
2494 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2495 OnAction(appcmdaction);
2497 // Always return true regardless of whether the action succeeded or not.
2498 // This stops Windows handling the appcommand itself.
2502 bool CApplication::OnAction(const CAction &action)
2504 // special case for switching between GUI & fullscreen mode.
2505 if (action.GetID() == ACTION_SHOW_GUI)
2506 { // Switch to fullscreen mode if we can
2507 if (SwitchToFullScreen())
2509 m_navigationTimer.StartZero();
2514 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2516 g_graphicsContext.ToggleFullScreenRoot();
2520 if (action.IsMouse())
2521 g_Mouse.SetActive(true);
2524 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2526 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2528 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2530 CGUIDialogVideoBookmarks::OnAddBookmark();
2533 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2534 // playing or ACTION_PLAYER_PLAY if we are not playing.
2535 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2537 if (m_pPlayer->IsPlaying())
2538 return OnAction(CAction(ACTION_PAUSE));
2540 return OnAction(CAction(ACTION_PLAYER_PLAY));
2543 //if the action would start or stop inertial scrolling
2544 //by gesture - bypass the normal OnAction handler of current window
2545 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2548 // just pass the action to the current window and let it handle it
2549 if (g_windowManager.OnAction(action))
2551 m_navigationTimer.StartZero();
2556 // handle extra global presses
2558 // screenshot : take a screenshot :)
2559 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2561 CScreenShot::TakeScreenshot();
2564 // built in functions : execute the built-in
2565 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2567 CBuiltins::Execute(action.GetName());
2568 m_navigationTimer.StartZero();
2573 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2575 CButtonTranslator::GetInstance().Clear();
2576 CButtonTranslator::GetInstance().Load();
2579 // show info : Shows the current video or song information
2580 if (action.GetID() == ACTION_SHOW_INFO)
2582 g_infoManager.ToggleShowInfo();
2586 // codec info : Shows the current song, video or picture codec information
2587 if (action.GetID() == ACTION_SHOW_CODEC)
2589 g_infoManager.ToggleShowCodec();
2593 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2595 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2598 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2599 char rating = tag->GetRating();
2600 bool needsUpdate(false);
2601 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2603 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2606 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2608 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2614 if (db.Open()) // OpenForWrite() ?
2616 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2619 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2620 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2621 g_windowManager.SendMessage(msg);
2627 // Now check with the playlist player if action can be handled.
2628 // 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.
2629 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2631 if (g_playlistPlayer.OnAction(action))
2635 // Now check with the player if action can be handled.
2636 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2637 (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)))
2639 if (m_pPlayer->OnAction(action))
2643 // stop : stops playing current audio song
2644 if (action.GetID() == ACTION_STOP)
2650 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2651 // If so, we just jump to the start of the track.
2652 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2655 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2659 // forward action to g_PVRManager and break if it was able to handle it
2660 if (g_PVRManager.OnAction(action))
2663 // forward action to graphic context and see if it can handle it
2664 if (CStereoscopicsManager::Get().OnAction(action))
2667 if (m_pPlayer->IsPlaying())
2669 // forward channel switches to the player - he knows what to do
2670 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2672 m_pPlayer->OnAction(action);
2676 // pause : pauses current audio song
2677 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2681 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2683 if (!m_pPlayer->IsPaused())
2684 { // unpaused - set the playspeed back to normal
2685 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2687 g_audioManager.Enable(m_pPlayer->IsPaused());
2690 if (!m_pPlayer->IsPaused())
2692 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2693 // if we are playing at normal speed, then allow play to pause
2694 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2696 if (m_pPlayer->GetPlaySpeed() != 1)
2698 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2706 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2708 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2709 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2711 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2713 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2718 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2720 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2723 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2726 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2728 // calculate the speed based on the amount the button is held down
2729 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2730 // returns 0 -> MAX_FFWD_SPEED
2731 int iSpeed = 1 << iPower;
2732 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2734 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2736 CLog::Log(LOGDEBUG,"Resetting playspeed");
2740 // allow play to unpause
2743 if (action.GetID() == ACTION_PLAYER_PLAY)
2745 // unpause, and set the playspeed back to normal
2747 g_audioManager.Enable(m_pPlayer->IsPaused());
2749 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2754 if (m_playerController->OnAction(action))
2759 if (action.GetID() == ACTION_SWITCH_PLAYER)
2761 if(m_pPlayer->IsPlaying())
2763 VECPLAYERCORES cores;
2764 CFileItem item(*m_itemCurrentFile.get());
2765 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2766 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2767 if(core != EPC_NONE)
2769 g_application.m_eForcedNextPlayer = core;
2770 item.m_lStartOffset = (int)(GetTime() * 75);
2771 PlayFile(item, true);
2776 VECPLAYERCORES cores;
2777 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2778 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2779 if(core != EPC_NONE)
2782 g_application.m_eForcedNextPlayer = core;
2783 PlayFile(item, false);
2788 if (g_peripherals.OnAction(action))
2791 if (action.GetID() == ACTION_MUTE)
2797 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2799 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2800 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2802 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2804 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2805 g_windowManager.SendMessage(msg);
2810 // Check for global volume control
2811 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2813 if (!m_pPlayer->IsPassthrough())
2817 float volume = m_volumeLevel;
2818 // Android has steps based on the max available volume level
2819 #if defined(TARGET_ANDROID)
2820 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2822 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2824 if (action.GetRepeat())
2825 step *= action.GetRepeat() * 50; // 50 fps
2827 if (action.GetID() == ACTION_VOLUME_UP)
2828 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2830 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2831 SetVolume(volume, false);
2833 // show visual feedback of volume change...
2834 ShowVolumeBar(&action);
2837 // Check for global seek control
2838 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2840 if (!m_pPlayer->CanSeek()) return false;
2841 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2844 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2846 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2847 CGUIControlProfiler::Instance().Start();
2850 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2852 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2853 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2854 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2855 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2856 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2862 void CApplication::FrameMove(bool processEvents, bool processGUI)
2868 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2869 float frameTime = m_frameTime.GetElapsedSeconds();
2870 m_frameTime.StartZero();
2871 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2872 if( frameTime > 0.5 ) frameTime = 0.5;
2874 if (processGUI && m_renderGUI)
2876 g_graphicsContext.Lock();
2877 // check if there are notifications to display
2878 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2879 if (toast && toast->DoWork())
2881 if (!toast->IsDialogRunning())
2886 g_graphicsContext.Unlock();
2888 CWinEvents::MessagePump();
2890 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2891 // Read the input from a remote
2892 g_RemoteControl.Update();
2895 // process input actions
2896 ProcessRemote(frameTime);
2897 ProcessGamepad(frameTime);
2898 ProcessEventServer(frameTime);
2899 ProcessPeripherals(frameTime);
2900 if (processGUI && m_renderGUI)
2902 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2903 m_seekHandler->Process();
2906 if (processGUI && m_renderGUI)
2909 g_windowManager.Process(CTimeUtils::GetFrameTime());
2910 g_windowManager.FrameMove();
2914 bool CApplication::ProcessGamepad(float frameTime)
2916 #ifdef HAS_SDL_JOYSTICK
2920 int iWin = GetActiveWindowID();
2922 g_Joystick.Update();
2923 if (g_Joystick.GetButton(bid))
2926 m_idleTimer.StartZero();
2929 if (WakeUpScreenSaverAndDPMS())
2931 g_Joystick.Reset(true);
2936 CStdString actionName;
2938 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2940 CAction action(actionID, 1.0f, 0.0f, actionName);
2942 g_Mouse.SetActive(false);
2943 return ExecuteInputAction(action);
2950 if (g_Joystick.GetAxis(bid))
2952 if (g_Joystick.GetAmount() < 0)
2958 CStdString actionName;
2960 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2963 if (WakeUpScreenSaverAndDPMS())
2968 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2970 g_Mouse.SetActive(false);
2971 return ExecuteInputAction(action);
2975 g_Joystick.ResetAxis(abs(bid));
2979 if (g_Joystick.GetHat(bid, position))
2982 m_idleTimer.StartZero();
2985 if (WakeUpScreenSaverAndDPMS())
2992 CStdString actionName;
2995 bid = position<<16|bid;
2997 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2999 CAction action(actionID, 1.0f, 0.0f, actionName);
3001 g_Mouse.SetActive(false);
3002 return ExecuteInputAction(action);
3009 bool CApplication::ProcessRemote(float frameTime)
3011 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3012 if (g_RemoteControl.GetButton())
3014 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3015 g_RemoteControl.Reset();
3022 bool CApplication::ProcessPeripherals(float frameTime)
3025 if (g_peripherals.GetNextKeypress(frameTime, key))
3030 bool CApplication::ProcessMouse()
3034 if (!g_Mouse.IsActive() || !m_AppFocused)
3037 // Get the mouse command ID
3038 uint32_t mousecommand = g_Mouse.GetAction();
3039 if (mousecommand == ACTION_NOOP)
3042 // Reset the screensaver and idle timers
3043 m_idleTimer.StartZero();
3045 if (WakeUpScreenSaverAndDPMS())
3048 // Retrieve the corresponding action
3049 int iWin = GetActiveWindowID();
3050 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3051 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3053 // Deactivate mouse if non-mouse action
3054 if (!mouseaction.IsMouse())
3055 g_Mouse.SetActive(false);
3057 // Consume ACTION_NOOP.
3058 // Some views or dialogs gets closed after any ACTION and
3059 // a sensitive mouse might cause problems.
3060 if (mouseaction.GetID() == ACTION_NOOP)
3063 // If we couldn't find an action return false to indicate we have not
3064 // handled this mouse action
3065 if (!mouseaction.GetID())
3067 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3071 // Log mouse actions except for move and noop
3072 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3073 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3075 // The action might not be a mouse action. For example wheel moves might
3076 // be mapped to volume up/down in mouse.xml. In this case we do not want
3077 // the mouse position saved in the action.
3078 if (!mouseaction.IsMouse())
3079 return OnAction(mouseaction);
3081 // This is a mouse action so we need to record the mouse position
3082 return OnAction(CAction(mouseaction.GetID(),
3083 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3084 (float)g_Mouse.GetX(),
3085 (float)g_Mouse.GetY(),
3086 (float)g_Mouse.GetDX(),
3087 (float)g_Mouse.GetDY(),
3088 mouseaction.GetName()));
3091 bool CApplication::ProcessEventServer(float frameTime)
3093 #ifdef HAS_EVENT_SERVER
3094 CEventServer* es = CEventServer::GetInstance();
3095 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3098 // process any queued up actions
3099 if (es->ExecuteNextAction())
3101 // reset idle timers
3102 m_idleTimer.StartZero();
3104 WakeUpScreenSaverAndDPMS();
3107 // now handle any buttons or axis
3108 std::string joystickName;
3109 bool isAxis = false;
3110 float fAmount = 0.0;
3112 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3113 // when the action exits XBMC
3114 es = CEventServer::GetInstance();
3115 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3117 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3121 if (joystickName.length() > 0)
3125 if (fabs(fAmount) >= 0.08)
3126 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3128 m_lastAxisMap[joystickName].erase(wKeyID);
3131 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3136 if (wKeyID & ES_FLAG_UNICODE)
3138 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3142 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3143 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3144 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3145 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3146 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3147 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3148 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3149 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3150 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3151 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3152 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3153 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3154 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3155 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3156 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3157 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3158 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3159 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3160 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3161 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3164 key.SetFromService(true);
3169 if (m_lastAxisMap.size() > 0)
3171 // Process all the stored axis.
3172 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3174 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3175 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3181 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3183 XBMC_Event newEvent;
3184 newEvent.type = XBMC_MOUSEMOTION;
3185 newEvent.motion.xrel = 0;
3186 newEvent.motion.yrel = 0;
3187 newEvent.motion.state = 0;
3188 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3189 newEvent.motion.x = pos.x;
3190 newEvent.motion.y = pos.y;
3191 OnEvent(newEvent); // had to call this to update g_Mouse position
3192 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3199 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3201 #if defined(HAS_EVENT_SERVER)
3202 m_idleTimer.StartZero();
3204 // Make sure to reset screen saver, mouse.
3206 if (WakeUpScreenSaverAndDPMS())
3209 #ifdef HAS_SDL_JOYSTICK
3212 g_Mouse.SetActive(false);
3214 int iWin = GetActiveWindowID();
3216 CStdString actionName;
3217 bool fullRange = false;
3219 // Translate using regular joystick translator.
3220 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3221 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3223 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3229 bool CApplication::ExecuteInputAction(const CAction &action)
3231 bool bResult = false;
3233 // play sound before the action unless the button is held,
3234 // where we execute after the action as held actions aren't fired every time.
3235 if(action.GetHoldTime())
3237 bResult = OnAction(action);
3239 g_audioManager.PlayActionSound(action);
3243 g_audioManager.PlayActionSound(action);
3244 bResult = OnAction(action);
3249 int CApplication::GetActiveWindowID(void)
3251 // Get the currently active window
3252 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3254 // If there is a dialog active get the dialog id instead
3255 if (g_windowManager.HasModalDialog())
3256 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3258 // If the window is FullScreenVideo check for special cases
3259 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3261 // check if we're in a DVD menu
3262 if(g_application.m_pPlayer->IsInMenu())
3263 iWin = WINDOW_VIDEO_MENU;
3264 // check for LiveTV and switch to it's virtual window
3265 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3266 iWin = WINDOW_FULLSCREEN_LIVETV;
3269 // Return the window id
3273 bool CApplication::Cleanup()
3277 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3278 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3279 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3280 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3281 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3282 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3283 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3284 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3285 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3286 g_windowManager.Delete(WINDOW_FILES);
3287 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3288 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3289 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3290 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3291 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3292 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3293 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3294 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3295 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3296 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3297 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3298 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3299 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3300 g_windowManager.Delete(WINDOW_DIALOG_OK);
3301 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3302 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3303 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3304 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3305 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3306 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3307 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3308 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3309 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3310 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3311 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3312 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3313 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3314 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3315 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3316 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3317 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3318 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3319 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3320 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3321 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3322 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3323 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3325 /* Delete PVR related windows and dialogs */
3326 g_windowManager.Delete(WINDOW_PVR);
3327 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3328 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3329 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3330 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3331 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3332 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3333 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3334 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3335 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3336 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3337 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3338 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3339 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3341 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3342 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3343 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3344 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3345 g_windowManager.Delete(WINDOW_VISUALISATION);
3346 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3347 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3348 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3349 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3350 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3351 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3352 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3353 g_windowManager.Delete(WINDOW_SCREENSAVER);
3354 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3355 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3356 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3357 g_windowManager.Delete(WINDOW_SLIDESHOW);
3358 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3359 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3361 g_windowManager.Delete(WINDOW_HOME);
3362 g_windowManager.Delete(WINDOW_PROGRAMS);
3363 g_windowManager.Delete(WINDOW_PICTURES);
3364 g_windowManager.Delete(WINDOW_WEATHER);
3366 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3367 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3368 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3369 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3370 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3371 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3372 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3373 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3374 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3375 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3377 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3378 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3380 CAddonMgr::Get().DeInit();
3382 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3383 CLog::Log(LOGNOTICE, "closing down remote control service");
3384 g_RemoteControl.Disconnect();
3387 CLog::Log(LOGNOTICE, "unload sections");
3389 #ifdef HAS_PERFORMANCE_SAMPLE
3390 CLog::Log(LOGNOTICE, "performance statistics");
3391 m_perfStats.DumpStats();
3394 // Shutdown as much as possible of the
3395 // application, to reduce the leaks dumped
3396 // to the vc output window before calling
3397 // _CrtDumpMemoryLeaks(). Most of the leaks
3398 // shown are no real leaks, as parts of the app
3399 // are still allocated.
3401 g_localizeStrings.Clear();
3402 g_LangCodeExpander.Clear();
3403 g_charsetConverter.clear();
3404 g_directoryCache.Clear();
3405 CButtonTranslator::GetInstance().Clear();
3406 #ifdef HAS_EVENT_SERVER
3407 CEventServer::RemoveInstance();
3409 DllLoaderContainer::Clear();
3410 g_playlistPlayer.Clear();
3411 CSettings::Get().Uninitialize();
3412 g_advancedSettings.Clear();
3415 CXHandle::DumpObjectTracker();
3417 #ifdef HAS_DVD_DRIVE
3418 CLibcdio::ReleaseInstance();
3421 #if defined(TARGET_ANDROID)
3422 // enable for all platforms once it's safe
3423 g_sectionLoader.UnloadAll();
3425 #ifdef _CRTDBG_MAP_ALLOC
3426 _CrtDumpMemoryLeaks();
3427 while(1); // execution ends
3437 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3442 void CApplication::Stop(int exitCode)
3446 CVariant vExitCode(exitCode);
3447 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3449 SaveFileState(true);
3451 g_alarmClock.StopThread();
3453 if( m_bSystemScreenSaverEnable )
3454 g_Windowing.EnableSystemScreenSaver(true);
3456 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3457 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3459 // Update the settings information (volume, uptime etc. need saving)
3460 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3462 CLog::Log(LOGNOTICE, "Saving settings");
3463 CSettings::Get().Save();
3466 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3469 m_AppFocused = false;
3470 m_ExitCode = exitCode;
3471 CLog::Log(LOGNOTICE, "stop all");
3473 // cancel any jobs from the jobmanager
3474 CJobManager::GetInstance().CancelJobs();
3476 // stop scanning before we kill the network and so on
3477 if (m_musicInfoScanner->IsScanning())
3478 m_musicInfoScanner->Stop();
3480 if (m_videoInfoScanner->IsScanning())
3481 m_videoInfoScanner->Stop();
3483 CApplicationMessenger::Get().Cleanup();
3489 CLog::Log(LOGNOTICE, "stop player");
3490 m_pPlayer->ClosePlayer();
3492 #if HAS_FILESYTEM_DAAP
3493 CLog::Log(LOGNOTICE, "stop daap clients");
3494 g_DaapClient.Release();
3496 #ifdef HAS_FILESYSTEM_SAP
3497 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3498 g_sapsessions.StopThread();
3501 if(CZeroconfBrowser::IsInstantiated())
3503 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3504 CZeroconfBrowser::GetInstance()->Stop();
3505 CZeroconfBrowser::ReleaseInstance();
3509 CLog::Log(LOGNOTICE, "clean cached files!");
3510 #ifdef HAS_FILESYSTEM_RAR
3511 g_RarManager.ClearCache(true);
3514 #ifdef HAS_FILESYSTEM_SFTP
3515 CSFTPSessionManager::DisconnectAllSessions();
3518 CLog::Log(LOGNOTICE, "unload skin");
3521 #if defined(TARGET_DARWIN_OSX)
3522 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3523 XBMCHelper::GetInstance().Stop();
3526 #if defined(HAVE_LIBCRYSTALHD)
3527 CCrystalHD::RemoveInstance();
3530 g_mediaManager.Stop();
3532 // Stop services before unloading Python
3533 CAddonMgr::Get().StopServices(false);
3535 // stop all remaining scripts; must be done after skin has been unloaded,
3536 // not before some windows still need it when deinitializing during skin
3538 CScriptInvocationManager::Get().Uninitialize();
3540 g_Windowing.DestroyRenderSystem();
3541 g_Windowing.DestroyWindow();
3542 g_Windowing.DestroyWindowSystem();
3544 // shutdown the AudioEngine
3545 CAEFactory::Shutdown();
3546 CAEFactory::UnLoadEngine();
3548 CLog::Log(LOGNOTICE, "stopped");
3552 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3555 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3556 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3563 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3565 //If item is a plugin, expand out now and run ourselves again
3566 if (item.IsPlugin())
3568 CFileItem item_new(item);
3569 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3570 return PlayMedia(item_new, iPlaylist);
3573 if (item.IsSmartPlayList())
3575 CFileItemList items;
3576 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3579 CSmartPlaylist smartpl;
3580 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3581 smartpl.OpenAndReadName(item.GetPath());
3583 playlist.Add(items);
3584 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3587 else if (item.IsPlayList() || item.IsInternetStream())
3589 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3591 //is or could be a playlist
3592 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3593 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3598 if (dlgCache->IsCanceled())
3605 if (iPlaylist != PLAYLIST_NONE)
3608 if (item.HasProperty("playlist_starting_track"))
3609 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3610 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3614 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());
3615 if(pPlayList->size())
3616 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3621 //nothing special just play
3622 return PlayFile(item, false) == PLAYBACK_OK;
3626 // For playing a multi-file video. Particularly inefficient
3627 // on startup, as we are required to calculate the length
3628 // of each video, so we open + close each one in turn.
3629 // A faster calculation of video time would improve this
3631 // return value: same with PlayFile()
3632 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3634 if (!item.IsStack())
3635 return PLAYBACK_FAIL;
3639 // case 1: stacked ISOs
3640 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3642 CStackDirectory dir;
3643 CFileItemList movieList;
3644 dir.GetDirectory(item.GetPath(), movieList);
3646 // first assume values passed to the stack
3647 int selectedFile = item.m_lStartPartNumber;
3648 int startoffset = item.m_lStartOffset;
3650 // check if we instructed the stack to resume from default
3651 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3656 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3658 startoffset = (int)(bookmark.timeInSeconds*75);
3659 selectedFile = bookmark.partNumber;
3664 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3667 // make sure that the selected part is within the boundaries
3668 if (selectedFile <= 0)
3670 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3673 else if (selectedFile > movieList.Size())
3675 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3676 selectedFile = movieList.Size();
3679 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3680 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3681 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3682 *m_stackFileItemToUpdate = item;
3683 return PlayFile(*(movieList[selectedFile - 1]));
3685 // case 2: all other stacks
3688 // see if we have the info in the database
3689 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3690 // then these times will be wrong.
3691 // Also, this is really just a hack for the slow load up times we have
3692 // A much better solution is a fast reader of FPS and fileLength
3693 // that we can use on a file to get it's time.
3695 bool haveTimes(false);
3699 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3700 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3705 // calculate the total time of the stack
3706 CStackDirectory dir;
3707 dir.GetDirectory(item.GetPath(), *m_currentStack);
3709 for (int i = 0; i < m_currentStack->Size(); i++)
3712 (*m_currentStack)[i]->m_lEndOffset = times[i];
3716 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3718 m_currentStack->Clear();
3719 return PLAYBACK_FAIL;
3721 totalTime += duration / 1000;
3722 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3723 times.push_back(totalTime);
3727 double seconds = item.m_lStartOffset / 75.0;
3729 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3730 { // have our times now, so update the dB
3734 dbs.SetStackTimes(item.GetPath(), times);
3736 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3738 // can only resume seek here, not dvdstate
3740 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3741 seconds = bookmark.timeInSeconds;
3749 *m_itemCurrentFile = item;
3750 m_currentStackPosition = 0;
3751 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3755 // work out where to seek to
3756 for (int i = 0; i < m_currentStack->Size(); i++)
3758 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3760 CFileItem item(*(*m_currentStack)[i]);
3761 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3762 item.m_lStartOffset = (long)(seconds - start) * 75;
3763 m_currentStackPosition = i;
3764 return PlayFile(item, true);
3769 return PlayFile(*(*m_currentStack)[0], true);
3771 return PLAYBACK_FAIL;
3774 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3776 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3777 if (item.GetMimeType().empty())
3778 const_cast<CFileItem&>(item).FillInMimeType();
3782 SaveCurrentFileSettings();
3784 OutputDebugString("new file set audiostream:0\n");
3785 // Switch to default options
3786 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3787 // see if we have saved options in the database
3789 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3790 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3792 *m_itemCurrentFile = item;
3793 m_nextPlaylistItem = -1;
3794 m_currentStackPosition = 0;
3795 m_currentStack->Clear();
3798 CUtil::ClearSubtitles();
3801 if (item.IsDiscStub())
3803 #ifdef HAS_DVD_DRIVE
3804 // Display the Play Eject dialog if there is any optical disc drive
3805 if (g_mediaManager.HasOpticalDrive())
3807 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3808 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3809 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3810 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3814 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3819 if (item.IsPlayList())
3820 return PLAYBACK_FAIL;
3822 if (item.IsPlugin())
3823 { // we modify the item so that it becomes a real URL
3824 CFileItem item_new(item);
3825 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3826 return PlayFile(item_new, false);
3827 return PLAYBACK_FAIL;
3831 if (URIUtils::IsUPnP(item.GetPath()))
3833 CFileItem item_new(item);
3834 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3835 return PlayFile(item_new, false);
3836 return PLAYBACK_FAIL;
3840 // if we have a stacked set of files, we need to setup our stack routines for
3841 // "seamless" seeking and total time of the movie etc.
3842 // will recall with restart set to true
3844 return PlayStack(item, bRestart);
3846 //Is TuxBox, this should probably be moved to CTuxBoxFile
3849 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3851 if(g_tuxboxService.IsRunning())
3852 g_tuxboxService.Stop();
3854 PlayBackRet ret = PLAYBACK_FAIL;
3856 if(g_tuxbox.CreateNewItem(item, item_new))
3859 // Make sure it doesn't have a player
3860 // so we actually select one normally
3861 m_pPlayer->ResetPlayer();
3863 // keep the tuxbox:// url as playing url
3864 // and give the new url to the player
3865 ret = PlayFile(item_new, true);
3866 if(ret == PLAYBACK_OK)
3868 if(!g_tuxboxService.IsRunning())
3869 g_tuxboxService.Start();
3875 CPlayerOptions options;
3877 if( item.HasProperty("StartPercent") )
3879 double fallback = 0.0f;
3880 if(item.GetProperty("StartPercent").isString())
3881 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3882 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3885 PLAYERCOREID eNewCore = EPC_NONE;
3888 // have to be set here due to playstack using this for starting the file
3889 options.starttime = item.m_lStartOffset / 75.0;
3890 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3891 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3893 if( m_eForcedNextPlayer != EPC_NONE )
3894 eNewCore = m_eForcedNextPlayer;
3895 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3896 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3898 eNewCore = m_pPlayer->GetCurrentPlayer();
3902 options.starttime = item.m_lStartOffset / 75.0;
3906 // open the d/b and retrieve the bookmarks for the current movie
3909 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3911 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3913 options.starttime = 0.0f;
3915 CStdString path = item.GetPath();
3916 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3917 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3918 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3919 path = item.GetProperty("original_listitem_url").asString();
3920 if(dbs.GetResumeBookMark(path, bookmark))
3922 options.starttime = bookmark.timeInSeconds;
3923 options.state = bookmark.playerState;
3926 override with information from the actual item if available. We do this as the VFS (eg plugins)
3927 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3928 should the playerState be required, it is fetched from the database.
3929 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3931 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3932 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3934 else if (item.HasVideoInfoTag())
3936 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3938 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3941 dbs.GetBookMarkForEpisode(*tag, bookmark);
3942 options.starttime = bookmark.timeInSeconds;
3943 options.state = bookmark.playerState;
3950 if (m_eForcedNextPlayer != EPC_NONE)
3951 eNewCore = m_eForcedNextPlayer;
3953 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3956 // this really aught to be inside !bRestart, but since PlayStack
3957 // uses that to init playback, we have to keep it outside
3958 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3959 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3960 { // playing from a playlist by the looks
3961 // don't switch to fullscreen if we are not playing the first item...
3962 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3964 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3966 // TODO - this will fail if user seeks back to first file in stack
3967 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3968 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3970 options.fullscreen = false;
3971 // reset this so we don't think we are resuming on seek
3972 m_itemCurrentFile->m_lStartOffset = 0;
3975 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3977 // reset VideoStartWindowed as it's a temp setting
3978 CMediaSettings::Get().SetVideoStartWindowed(false);
3981 //We have to stop parsing a cdg before mplayer is deallocated
3982 // WHY do we have to do this????
3984 m_pKaraokeMgr->Stop();
3988 CSingleLock lock(m_playStateMutex);
3989 // tell system we are starting a file
3990 m_bPlaybackStarting = true;
3992 // for playing a new item, previous playing item's callback may already
3993 // pushed some delay message into the threadmessage list, they are not
3994 // expected be processed after or during the new item playback starting.
3995 // so we clean up previous playing item's playback callback delay messages here.
3996 int previousMsgsIgnoredByNewPlaying[] = {
3997 GUI_MSG_PLAYBACK_STARTED,
3998 GUI_MSG_PLAYBACK_ENDED,
3999 GUI_MSG_PLAYBACK_STOPPED,
4000 GUI_MSG_PLAYLIST_CHANGED,
4001 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4002 GUI_MSG_PLAYLISTPLAYER_STARTED,
4003 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4004 GUI_MSG_QUEUE_NEXT_ITEM,
4007 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4009 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4012 // We should restart the player, unless the previous and next tracks are using
4013 // one of the players that allows gapless playback (paplayer, dvdplayer)
4014 m_pPlayer->ClosePlayerGapless(eNewCore);
4016 // now reset play state to starting, since we already stopped the previous playing item if there is.
4017 // and from now there should be no playback callback from previous playing item be called.
4018 m_ePlayState = PLAY_STATE_STARTING;
4020 m_pPlayer->CreatePlayer(eNewCore, *this);
4022 PlayBackRet iResult;
4023 if (m_pPlayer->HasPlayer())
4025 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4026 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4027 * increase performance on low powered systems (Atom/ARM).
4031 CJobManager::GetInstance().PauseJobs();
4034 // don't hold graphicscontext here since player
4035 // may wait on another thread, that requires gfx
4036 CSingleExit ex(g_graphicsContext);
4038 iResult = m_pPlayer->OpenFile(item, options);
4042 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4043 iResult = PLAYBACK_FAIL;
4046 if(iResult == PLAYBACK_OK)
4048 if (m_pPlayer->GetPlaySpeed() != 1)
4050 int iSpeed = m_pPlayer->GetPlaySpeed();
4051 m_pPlayer->m_iPlaySpeed = 1;
4052 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4055 // if player has volume control, set it.
4056 if (m_pPlayer->ControlsVolume())
4058 m_pPlayer->SetVolume(m_volumeLevel);
4059 m_pPlayer->SetMute(m_muted);
4062 if( m_pPlayer->IsPlayingAudio() )
4064 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4065 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4068 #ifdef HAS_VIDEO_PLAYBACK
4069 else if( m_pPlayer->IsPlayingVideo() )
4071 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4072 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4074 // if player didn't manange to switch to fullscreen by itself do it here
4075 if( options.fullscreen && g_renderManager.IsStarted()
4076 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4077 SwitchToFullScreen();
4082 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4083 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4084 g_windowManager.PreviousWindow();
4088 #if !defined(TARGET_POSIX)
4089 g_audioManager.Enable(false);
4092 if (item.HasPVRChannelInfoTag())
4093 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4096 CSingleLock lock(m_playStateMutex);
4097 m_bPlaybackStarting = false;
4099 if (iResult == PLAYBACK_OK)
4101 // play state: none, starting; playing; stopped; ended.
4102 // last 3 states are set by playback callback, they are all ignored during starting,
4103 // but we recorded the state, here we can make up the callback for the state.
4104 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4105 switch (m_ePlayState)
4107 case PLAY_STATE_PLAYING:
4108 OnPlayBackStarted();
4110 // FIXME: it seems no meaning to callback started here if there was an started callback
4111 // before this stopped/ended callback we recorded. if we callback started here
4112 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4113 // which will send OnStop announce at once, so currently, just call stopped/ended.
4114 case PLAY_STATE_ENDED:
4117 case PLAY_STATE_STOPPED:
4118 OnPlayBackStopped();
4120 case PLAY_STATE_STARTING:
4121 // neither started nor stopped/ended callback be called, that means the item still
4122 // not started, we need not make up any callback, just leave this and
4123 // let the player callback do its work.
4129 else if (iResult == PLAYBACK_FAIL)
4131 // we send this if it isn't playlistplayer that is doing this
4132 int next = g_playlistPlayer.GetNextSong();
4133 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4136 OnPlayBackStopped();
4137 m_ePlayState = PLAY_STATE_NONE;
4143 void CApplication::OnPlayBackEnded()
4145 CSingleLock lock(m_playStateMutex);
4146 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4147 m_ePlayState = PLAY_STATE_ENDED;
4148 if(m_bPlaybackStarting)
4151 // informs python script currently running playback has ended
4152 // (does nothing if python is not loaded)
4154 g_pythonParser.OnPlayBackEnded();
4157 CVariant data(CVariant::VariantTypeObject);
4159 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4161 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4162 g_windowManager.SendThreadMessage(msg);
4165 void CApplication::OnPlayBackStarted()
4167 CSingleLock lock(m_playStateMutex);
4168 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4169 m_ePlayState = PLAY_STATE_PLAYING;
4170 if(m_bPlaybackStarting)
4174 // informs python script currently running playback has started
4175 // (does nothing if python is not loaded)
4176 g_pythonParser.OnPlayBackStarted();
4179 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4180 g_windowManager.SendThreadMessage(msg);
4183 void CApplication::OnQueueNextItem()
4185 CSingleLock lock(m_playStateMutex);
4186 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4187 if(m_bPlaybackStarting)
4189 // informs python script currently running that we are requesting the next track
4190 // (does nothing if python is not loaded)
4192 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4195 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4196 g_windowManager.SendThreadMessage(msg);
4199 void CApplication::OnPlayBackStopped()
4201 CSingleLock lock(m_playStateMutex);
4202 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4203 m_ePlayState = PLAY_STATE_STOPPED;
4204 if(m_bPlaybackStarting)
4207 // informs python script currently running playback has ended
4208 // (does nothing if python is not loaded)
4210 g_pythonParser.OnPlayBackStopped();
4213 CVariant data(CVariant::VariantTypeObject);
4214 data["end"] = false;
4215 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4217 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4218 g_windowManager.SendThreadMessage(msg);
4221 void CApplication::OnPlayBackPaused()
4224 g_pythonParser.OnPlayBackPaused();
4228 param["player"]["speed"] = 0;
4229 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4230 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4233 void CApplication::OnPlayBackResumed()
4236 g_pythonParser.OnPlayBackResumed();
4240 param["player"]["speed"] = 1;
4241 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4242 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4245 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4248 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4252 param["player"]["speed"] = iSpeed;
4253 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4254 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4257 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4260 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4264 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4265 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4266 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4267 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4268 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4269 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4272 void CApplication::OnPlayBackSeekChapter(int iChapter)
4275 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4279 bool CApplication::IsPlayingFullScreenVideo() const
4281 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4284 bool CApplication::IsFullScreen()
4286 return IsPlayingFullScreenVideo() ||
4287 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4288 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4291 void CApplication::SaveFileState(bool bForeground /* = false */)
4293 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4298 CSaveFileStateJob job(*m_progressTrackingItem,
4299 *m_stackFileItemToUpdate,
4300 m_progressTrackingVideoResumeBookmark,
4301 m_progressTrackingPlayCountUpdate);
4303 // Run job in the foreground to make sure it finishes
4308 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4309 *m_stackFileItemToUpdate,
4310 m_progressTrackingVideoResumeBookmark,
4311 m_progressTrackingPlayCountUpdate);
4312 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4316 void CApplication::UpdateFileState()
4318 // Did the file change?
4319 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4323 // Reset tracking item
4324 m_progressTrackingItem->Reset();
4328 if (m_pPlayer->IsPlaying())
4330 if (m_progressTrackingItem->GetPath() == "")
4333 *m_progressTrackingItem = CurrentFileItem();
4334 m_progressTrackingPlayCountUpdate = false;
4337 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4338 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4339 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4340 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4342 m_progressTrackingPlayCountUpdate = true;
4345 // Check whether we're *really* playing video else we may race when getting eg. stream details
4346 if (m_pPlayer->IsPlayingVideo())
4348 /* Always update streamdetails, except for DVDs where we only update
4349 streamdetails if title length > 15m (Should yield more correct info) */
4350 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4352 CStreamDetails details;
4353 // Update with stream details from player, if any
4354 if (m_pPlayer->GetStreamDetails(details))
4355 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4358 // Update bookmark for save
4359 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4360 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4361 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4363 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4364 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4366 // Delete the bookmark
4367 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4370 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4372 // Update the bookmark
4373 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4374 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4379 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4386 void CApplication::StopPlaying()
4388 int iWin = g_windowManager.GetActiveWindow();
4389 if ( m_pPlayer->IsPlaying() )
4393 m_pKaraokeMgr->Stop();
4396 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4397 g_PVRManager.SaveCurrentChannelSettings();
4399 m_pPlayer->CloseFile();
4401 // turn off visualisation window when stopping
4402 if ((iWin == WINDOW_VISUALISATION
4403 || iWin == WINDOW_FULLSCREEN_VIDEO)
4405 g_windowManager.PreviousWindow();
4407 g_partyModeManager.Disable();
4411 void CApplication::ResetSystemIdleTimer()
4413 // reset system idle timer
4414 m_idleTimer.StartZero();
4417 void CApplication::ResetScreenSaver()
4420 m_shutdownTimer.StartZero();
4422 // screen saver timer is reset only if we're not already in screensaver or
4424 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4425 ResetScreenSaverTimer();
4428 void CApplication::ResetScreenSaverTimer()
4430 m_screenSaverTimer.StartZero();
4433 void CApplication::StopScreenSaverTimer()
4435 m_screenSaverTimer.Stop();
4438 bool CApplication::ToggleDPMS(bool manual)
4440 if (manual || (m_dpmsIsManual == manual))
4444 m_dpmsIsActive = false;
4445 m_dpmsIsManual = false;
4446 return m_dpms->DisablePowerSaving();
4450 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4452 m_dpmsIsActive = true;
4453 m_dpmsIsManual = manual;
4461 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4465 // First reset DPMS, if active
4470 // TODO: if screensaver lock is specified but screensaver is not active
4471 // (DPMS came first), activate screensaver now.
4473 ResetScreenSaverTimer();
4474 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4477 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4481 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4482 CVariant data(bPowerOffKeyPressed);
4483 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4489 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4491 if (m_iScreenSaveLock == 2)
4494 // if Screen saver is active
4495 if (m_bScreenSave && m_screenSaver)
4497 if (m_iScreenSaveLock == 0)
4498 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4499 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4500 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4501 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4503 m_iScreenSaveLock = 2;
4504 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4506 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4508 pWindow->OnMessage(msg);
4510 if (m_iScreenSaveLock == -1)
4512 m_iScreenSaveLock = 0;
4516 // disable screensaver
4517 m_bScreenSave = false;
4518 m_iScreenSaveLock = 0;
4519 ResetScreenSaverTimer();
4521 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4523 else if (!m_screenSaver->ID().IsEmpty())
4524 { // we're in screensaver window
4525 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER
4526 || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4527 g_windowManager.PreviousWindow(); // show the previous window
4529 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4530 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4538 void CApplication::CheckScreenSaverAndDPMS()
4540 if (m_bInBackground)
4542 if (!m_dpmsIsActive)
4543 g_Windowing.ResetOSScreensaver();
4545 bool maybeScreensaver =
4546 !m_dpmsIsActive && !m_bScreenSave
4547 && !CSettings::Get().GetString("screensaver.mode").empty();
4549 !m_dpmsIsActive && m_dpms->IsSupported()
4550 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4552 // Has the screen saver window become active?
4553 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4555 m_bScreenSave = true;
4556 maybeScreensaver = false;
4559 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4561 WakeUpScreenSaverAndDPMS();
4565 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4567 // See if we need to reset timer.
4568 // * Are we playing a video and it is not paused?
4569 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4570 // * Are we playing some music in fullscreen vis?
4571 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4572 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4574 ResetScreenSaverTimer();
4578 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4580 // DPMS has priority (it makes the screensaver not needed)
4582 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4585 WakeUpScreenSaver();
4587 else if (maybeScreensaver
4588 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4590 ActivateScreenSaver();
4594 // activate the screensaver.
4595 // if forceType is true, we ignore the various conditions that can alter
4596 // the type of screensaver displayed
4597 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4599 m_bScreenSave = true;
4601 // Get Screensaver Mode
4602 m_screenSaver.reset();
4603 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4604 m_screenSaver.reset(new CScreenSaver(""));
4606 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4608 // disable screensaver lock from the login screen
4609 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4612 // set to Dim in the case of a dialog on screen or playing video
4613 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4615 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4616 m_screenSaver.reset(new CScreenSaver(""));
4618 // Check if we are Playing Audio and Vis instead Screensaver!
4619 else if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4620 { // activate the visualisation
4621 m_screenSaver.reset(new CScreenSaver("visualization"));
4622 // prevent music info popup if vis is already running
4623 if (g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
4624 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4628 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4630 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4632 else if (!m_screenSaver->ID().IsEmpty())
4633 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4636 void CApplication::SetInBackground(bool background)
4640 ResetScreenSaverTimer();
4642 m_bInBackground = background;
4645 void CApplication::CheckShutdown()
4647 // first check if we should reset the timer
4648 bool resetTimer = m_bInhibitIdleShutdown;
4650 if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4653 if (m_musicInfoScanner->IsScanning())
4656 if (m_videoInfoScanner->IsScanning())
4659 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4662 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4667 m_shutdownTimer.StartZero();
4671 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4673 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4674 m_shutdownTimer.Stop();
4677 CApplicationMessenger::Get().Shutdown();
4681 void CApplication::InhibitIdleShutdown(bool inhibit)
4683 m_bInhibitIdleShutdown = inhibit;
4686 bool CApplication::IsIdleShutdownInhibited() const
4688 return m_bInhibitIdleShutdown;
4691 bool CApplication::OnMessage(CGUIMessage& message)
4693 switch ( message.GetMessage() )
4695 case GUI_MSG_NOTIFY_ALL:
4697 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4699 // Update general playlist: Remove DVD playlist items
4700 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4703 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4704 g_windowManager.SendMessage( msg );
4706 // stop the file if it's on dvd (will set the resume point etc)
4707 if (m_itemCurrentFile->IsOnDVD())
4713 case GUI_MSG_PLAYBACK_STARTED:
4715 #ifdef TARGET_DARWIN
4716 DarwinSetScheduling(message.GetMessage());
4718 // reset the seek handler
4719 m_seekHandler->Reset();
4720 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4722 // Update our infoManager with the new details etc.
4723 if (m_nextPlaylistItem >= 0)
4725 // playing an item which is not in the list - player might be stopped already
4727 if (playList.size() <= m_nextPlaylistItem)
4730 // we've started a previously queued item
4731 CFileItemPtr item = playList[m_nextPlaylistItem];
4732 // update the playlist manager
4733 int currentSong = g_playlistPlayer.GetCurrentSong();
4734 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4735 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4736 g_windowManager.SendThreadMessage(msg);
4737 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4738 *m_itemCurrentFile = *item;
4740 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4741 g_partyModeManager.OnSongChange(true);
4744 param["player"]["speed"] = 1;
4745 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4746 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4748 if (m_pPlayer->IsPlayingAudio())
4750 // Start our cdg parser as appropriate
4752 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4754 m_pKaraokeMgr->Stop();
4755 if (m_itemCurrentFile->IsMusicDb())
4757 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4759 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4760 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4763 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4766 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4775 case GUI_MSG_QUEUE_NEXT_ITEM:
4777 // Check to see if our playlist player has a new item for us,
4778 // and if so, we check whether our current player wants the file
4779 int iNext = g_playlistPlayer.GetNextSong();
4780 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4781 if (iNext < 0 || iNext >= playlist.size())
4783 m_pPlayer->OnNothingToQueueNotify();
4784 return true; // nothing to do
4787 // ok, grab the next song
4788 CFileItem file(*playlist[iNext]);
4790 CURL url(file.GetPath());
4791 if (url.GetProtocol() == "plugin")
4792 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4795 if (URIUtils::IsUPnP(file.GetPath()))
4797 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4802 // ok - send the file to the player, if it accepts it
4803 if (m_pPlayer->QueueNextFile(file))
4805 // player accepted the next file
4806 m_nextPlaylistItem = iNext;
4810 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4811 queue the next (if it wants to) and it doesn't keep looping on this song */
4812 g_playlistPlayer.SetCurrentSong(iNext);
4819 case GUI_MSG_PLAYBACK_STOPPED:
4820 case GUI_MSG_PLAYBACK_ENDED:
4821 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4825 m_pKaraokeMgr->Stop();
4827 #ifdef TARGET_DARWIN
4828 DarwinSetScheduling(message.GetMessage());
4830 // first check if we still have items in the stack to play
4831 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4833 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4834 { // just play the next item in the stack
4835 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4840 // In case playback ended due to user eg. skipping over the end, clear
4841 // our resume bookmark here
4842 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4844 // Delete the bookmark
4845 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4848 // reset the current playing file
4849 m_itemCurrentFile->Reset();
4850 g_infoManager.ResetCurrentItem();
4851 m_currentStack->Clear();
4853 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4855 g_playlistPlayer.PlayNext(1, true);
4859 // reset any forced player
4860 m_eForcedNextPlayer = EPC_NONE;
4862 m_pPlayer->ClosePlayer();
4865 m_pPlayer->m_iPlaySpeed = 1;
4868 if (!m_pPlayer->IsPlaying())
4870 g_audioManager.Enable(true);
4873 if (!m_pPlayer->IsPlayingVideo())
4875 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4877 g_windowManager.PreviousWindow();
4881 CSingleLock lock(g_graphicsContext);
4882 // resets to res_desktop or look&feel resolution (including refreshrate)
4883 g_graphicsContext.SetFullScreenVideo(false);
4887 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4889 CSettings::Get().Save(); // save vis settings
4890 WakeUpScreenSaverAndDPMS();
4891 g_windowManager.PreviousWindow();
4894 // DVD ejected while playing in vis ?
4895 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4898 CSettings::Get().Save(); // save vis settings
4899 WakeUpScreenSaverAndDPMS();
4900 g_windowManager.PreviousWindow();
4903 if (IsEnableTestMode())
4904 CApplicationMessenger::Get().Quit();
4909 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4910 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4915 case GUI_MSG_FULLSCREEN:
4916 { // Switch to fullscreen, if we can
4917 SwitchToFullScreen();
4921 case GUI_MSG_EXECUTE:
4922 if (message.GetNumStringParams())
4923 return ExecuteXBMCAction(message.GetStringParam());
4929 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4931 // see if it is a user set string
4933 //We don't know if there is unsecure information in this yet, so we
4934 //postpone any logging
4935 const std::string in_actionStr(actionStr);
4936 CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
4937 CGUIInfoLabel info(actionStr, "");
4938 actionStr = info.GetLabel(0);
4940 // user has asked for something to be executed
4941 if (CBuiltins::HasCommand(actionStr))
4942 CBuiltins::Execute(actionStr);
4945 // try translating the action from our ButtonTranslator
4947 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4949 OnAction(CAction(actionID));
4952 CFileItem item(actionStr, false);
4954 if (item.IsPythonScript())
4955 { // a python script
4956 CScriptInvocationManager::Get().Execute(item.GetPath());
4960 if (item.IsAudio() || item.IsVideo())
4961 { // an audio or video file
4966 //At this point we have given up to translate, so even though
4967 //there may be insecure information, we log it.
4968 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
4975 void CApplication::Process()
4979 // dispatch the messages generated by python or other threads to the current window
4980 g_windowManager.DispatchThreadMessages();
4982 // process messages which have to be send to the gui
4983 // (this can only be done after g_windowManager.Render())
4984 CApplicationMessenger::Get().ProcessWindowMessages();
4988 m_loggingIn = false;
4990 // autoexec.py - profile
4991 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
4993 if (XFILE::CFile::Exists(strAutoExecPy))
4994 CScriptInvocationManager::Get().Execute(strAutoExecPy);
4996 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
4999 // handle any active scripts
5000 CScriptInvocationManager::Get().Process();
5002 // process messages, even if a movie is playing
5003 CApplicationMessenger::Get().ProcessMessages();
5004 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5006 // check how far we are through playing the current item
5007 // and do anything that needs doing (playcount updates etc)
5008 CheckPlayingProgress();
5011 m_pPlayer->DoAudioWork();
5013 // do any processing that isn't needed on each run
5014 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5016 m_slowTimer.Reset();
5020 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5023 // We get called every 500ms
5024 void CApplication::ProcessSlow()
5026 g_powerManager.ProcessEvents();
5028 #if defined(TARGET_DARWIN_OSX)
5029 // There is an issue on OS X that several system services ask the cursor to become visible
5030 // during their startup routines. Given that we can't control this, we hack it in by
5032 if (g_Windowing.IsFullScreen())
5033 { // SDL thinks it's hidden
5038 // Temporarely pause pausable jobs when viewing video/picture
5039 int currentWindow = g_windowManager.GetActiveWindow();
5040 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5042 CJobManager::GetInstance().PauseJobs();
5046 CJobManager::GetInstance().UnPauseJobs();
5049 // Store our file state for use on close()
5052 // Check if we need to activate the screensaver / DPMS.
5053 CheckScreenSaverAndDPMS();
5055 // Check if we need to shutdown (if enabled).
5056 #if defined(TARGET_DARWIN)
5057 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5059 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5065 // check if we should restart the player
5066 CheckDelayedPlayerRestart();
5068 // check if we can unload any unreferenced dlls or sections
5069 if (!m_pPlayer->IsPlayingVideo())
5070 CSectionLoader::UnloadDelayed();
5072 // check for any idle curl connections
5073 g_curlInterface.CheckIdle();
5075 // check for any idle myth sessions
5076 CMythSession::CheckIdle();
5078 #ifdef HAS_FILESYSTEM_HTSP
5079 // check for any idle htsp sessions
5080 HTSP::CHTSPDirectorySession::CheckIdle();
5084 if ( m_pKaraokeMgr )
5085 m_pKaraokeMgr->ProcessSlow();
5088 if (!m_pPlayer->IsPlayingVideo())
5089 g_largeTextureManager.CleanupUnusedImages();
5091 g_TextureManager.FreeUnusedTextures(5000);
5093 #ifdef HAS_DVD_DRIVE
5094 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5095 if (!m_pPlayer->IsPlayingVideo())
5096 m_Autorun->HandleAutorun();
5099 // update upnp server/renderer states
5101 if(UPNP::CUPnP::IsInstantiated())
5102 UPNP::CUPnP::GetInstance()->UpdateState();
5105 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5109 #ifdef HAS_FILESYSTEM_NFS
5110 gNfsConnection.CheckIfIdle();
5113 #ifdef HAS_FILESYSTEM_AFP
5114 gAfpConnection.CheckIfIdle();
5117 #ifdef HAS_FILESYSTEM_SFTP
5118 CSFTPSessionManager::ClearOutIdleSessions();
5121 g_mediaManager.ProcessEvents();
5124 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5125 g_RemoteControl.Initialize();
5128 if (!m_pPlayer->IsPlayingVideo())
5129 CAddonInstaller::Get().UpdateRepos();
5131 CAEFactory::GarbageCollect();
5134 // Global Idle Time in Seconds
5135 // idle time will be resetet if on any OnKey()
5136 // int return: system Idle time in seconds! 0 is no idle!
5137 int CApplication::GlobalIdleTime()
5139 if(!m_idleTimer.IsRunning())
5142 m_idleTimer.StartZero();
5144 return (int)m_idleTimer.GetElapsedSeconds();
5147 float CApplication::NavigationIdleTime()
5149 if (!m_navigationTimer.IsRunning())
5151 m_navigationTimer.Stop();
5152 m_navigationTimer.StartZero();
5154 return m_navigationTimer.GetElapsedSeconds();
5157 void CApplication::DelayedPlayerRestart()
5159 m_restartPlayerTimer.StartZero();
5162 void CApplication::CheckDelayedPlayerRestart()
5164 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5166 m_restartPlayerTimer.Stop();
5167 m_restartPlayerTimer.Reset();
5172 void CApplication::Restart(bool bSamePosition)
5174 // this function gets called when the user changes a setting (like noninterleaved)
5175 // and which means we gotta close & reopen the current playing file
5177 // first check if we're playing a file
5178 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5181 if( !m_pPlayer->HasPlayer() )
5186 // do we want to return to the current position in the file
5187 if (false == bSamePosition)
5189 // no, then just reopen the file and start at the beginning
5190 PlayFile(*m_itemCurrentFile, true);
5194 // else get current position
5195 double time = GetTime();
5197 // get player state, needed for dvd's
5198 CStdString state = m_pPlayer->GetPlayerState();
5200 // set the requested starttime
5201 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5204 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5205 m_pPlayer->SetPlayerState(state);
5208 const CStdString& CApplication::CurrentFile()
5210 return m_itemCurrentFile->GetPath();
5213 CFileItem& CApplication::CurrentFileItem()
5215 return *m_itemCurrentFile;
5218 void CApplication::ShowVolumeBar(const CAction *action)
5220 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5225 volumeBar->OnAction(*action);
5229 bool CApplication::IsMuted() const
5231 if (g_peripherals.IsMuted())
5233 return CAEFactory::IsMuted();
5236 void CApplication::ToggleMute(void)
5244 void CApplication::SetMute(bool mute)
5246 if (m_muted != mute)
5253 void CApplication::Mute()
5255 if (g_peripherals.Mute())
5258 CAEFactory::SetMute(true);
5263 void CApplication::UnMute()
5265 if (g_peripherals.UnMute())
5268 CAEFactory::SetMute(false);
5273 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5275 float hardwareVolume = iValue;
5278 hardwareVolume /= 100.0f;
5280 SetHardwareVolume(hardwareVolume);
5284 void CApplication::SetHardwareVolume(float hardwareVolume)
5286 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5287 m_volumeLevel = hardwareVolume;
5290 if (hardwareVolume > VOLUME_MINIMUM)
5292 float dB = CAEUtil::PercentToGain(hardwareVolume);
5293 value = CAEUtil::GainToScale(dB);
5298 CAEFactory::SetVolume(value);
5301 float CApplication::GetVolume(bool percentage /* = true */) const
5305 // converts the hardware volume to a percentage
5306 return m_volumeLevel * 100.0f;
5309 return m_volumeLevel;
5312 void CApplication::VolumeChanged() const
5314 CVariant data(CVariant::VariantTypeObject);
5315 data["volume"] = GetVolume();
5316 data["muted"] = m_muted;
5317 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5319 // if player has volume control, set it.
5320 if (m_pPlayer->ControlsVolume())
5322 m_pPlayer->SetVolume(m_volumeLevel);
5323 m_pPlayer->SetMute(m_muted);
5327 int CApplication::GetSubtitleDelay() const
5329 // converts subtitle delay to a percentage
5330 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5333 int CApplication::GetAudioDelay() const
5335 // converts audio delay to a percentage
5336 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5339 // Returns the total time in seconds of the current media. Fractional
5340 // portions of a second are possible - but not necessarily supported by the
5341 // player class. This returns a double to be consistent with GetTime() and
5343 double CApplication::GetTotalTime() const
5347 if (m_pPlayer->IsPlaying())
5349 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5350 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5352 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5358 void CApplication::StopShutdownTimer()
5360 if (m_shutdownTimer.IsRunning())
5361 m_shutdownTimer.Stop();
5364 void CApplication::ResetShutdownTimers()
5366 // reset system shutdown timer
5367 m_shutdownTimer.StartZero();
5369 // delete custom shutdown timer
5370 if (g_alarmClock.HasAlarm("shutdowntimer"))
5371 g_alarmClock.Stop("shutdowntimer", true);
5374 // Returns the current time in seconds of the currently playing media.
5375 // Fractional portions of a second are possible. This returns a double to
5376 // be consistent with GetTotalTime() and SeekTime().
5377 double CApplication::GetTime() const
5381 if (m_pPlayer->IsPlaying())
5383 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5385 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5386 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5389 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5395 // Sets the current position of the currently playing media to the specified
5396 // time in seconds. Fractional portions of a second are valid. The passed
5397 // time is the time offset from the beginning of the file as opposed to a
5398 // delta from the current position. This method accepts a double to be
5399 // consistent with GetTime() and GetTotalTime().
5400 void CApplication::SeekTime( double dTime )
5402 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5404 if (!m_pPlayer->CanSeek()) return;
5405 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5407 // find the item in the stack we are seeking to, and load the new
5408 // file if necessary, and calculate the correct seek within the new
5409 // file. Otherwise, just fall through to the usual routine if the
5410 // time is higher than our total time.
5411 for (int i = 0; i < m_currentStack->Size(); i++)
5413 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5415 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5416 if (m_currentStackPosition == i)
5417 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5419 { // seeking to a new file
5420 m_currentStackPosition = i;
5421 CFileItem item(*(*m_currentStack)[i]);
5422 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5423 // don't just call "PlayFile" here, as we are quite likely called from the
5424 // player thread, so we won't be able to delete ourselves.
5425 CApplicationMessenger::Get().PlayFile(item, true);
5431 // convert to milliseconds and perform seek
5432 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5436 float CApplication::GetPercentage() const
5438 if (m_pPlayer->IsPlaying())
5440 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5442 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5443 if (tag.GetDuration() > 0)
5444 return (float)(GetTime() / tag.GetDuration() * 100);
5447 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5449 double totalTime = GetTotalTime();
5450 if (totalTime > 0.0f)
5451 return (float)(GetTime() / totalTime * 100);
5454 return m_pPlayer->GetPercentage();
5459 float CApplication::GetCachePercentage() const
5461 if (m_pPlayer->IsPlaying())
5463 // Note that the player returns a relative cache percentage and we want an absolute percentage
5464 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5466 float stackedTotalTime = (float) GetTotalTime();
5467 // We need to take into account the stack's total time vs. currently playing file's total time
5468 if (stackedTotalTime > 0.0f)
5469 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5472 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5477 void CApplication::SeekPercentage(float percent)
5479 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5481 if (!m_pPlayer->CanSeek()) return;
5482 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5483 SeekTime(percent * 0.01 * GetTotalTime());
5485 m_pPlayer->SeekPercentage(percent);
5489 // SwitchToFullScreen() returns true if a switch is made, else returns false
5490 bool CApplication::SwitchToFullScreen()
5492 // if playing from the video info window, close it first!
5493 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5495 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5496 if (pDialog) pDialog->Close(true);
5499 // don't switch if there is a dialog on screen or the slideshow is active
5500 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5503 // See if we're playing a video, and are in GUI mode
5504 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5506 // then switch to fullscreen mode
5507 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5510 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5511 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5512 { // then switch to visualisation
5513 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5519 void CApplication::Minimize()
5521 g_Windowing.Minimize();
5524 PLAYERCOREID CApplication::GetCurrentPlayer()
5526 return m_pPlayer->GetCurrentPlayer();
5529 void CApplication::UpdateLibraries()
5531 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5533 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5537 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5539 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5544 bool CApplication::IsVideoScanning() const
5546 return m_videoInfoScanner->IsScanning();
5549 bool CApplication::IsMusicScanning() const
5551 return m_musicInfoScanner->IsScanning();
5554 void CApplication::StopVideoScan()
5556 if (m_videoInfoScanner->IsScanning())
5557 m_videoInfoScanner->Stop();
5560 void CApplication::StopMusicScan()
5562 if (m_musicInfoScanner->IsScanning())
5563 m_musicInfoScanner->Stop();
5566 void CApplication::StartVideoCleanup()
5568 if (m_videoInfoScanner->IsScanning())
5571 m_videoInfoScanner->CleanDatabase();
5574 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5576 if (m_videoInfoScanner->IsScanning())
5579 m_videoInfoScanner->ShowDialog(true);
5581 m_videoInfoScanner->Start(strDirectory,scanAll);
5584 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5586 if (m_musicInfoScanner->IsScanning())
5590 { // setup default flags
5591 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5592 flags |= CMusicInfoScanner::SCAN_ONLINE;
5593 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5594 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5597 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5598 m_musicInfoScanner->ShowDialog(true);
5600 m_musicInfoScanner->Start(strDirectory, flags);
5603 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5606 if (m_musicInfoScanner->IsScanning())
5609 m_musicInfoScanner->ShowDialog(true);
5611 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5614 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5617 if (m_musicInfoScanner->IsScanning())
5620 m_musicInfoScanner->ShowDialog(true);
5622 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5625 void CApplication::CheckPlayingProgress()
5627 // check if we haven't rewound past the start of the file
5628 if (m_pPlayer->IsPlaying())
5630 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5640 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5642 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5643 g_application.SeekTime(0);
5649 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5651 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5653 // initial exit conditions
5654 // no songs in playlist just return
5655 if (playlist.size() == 0)
5659 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5662 // setup correct playlist
5663 g_playlistPlayer.ClearPlaylist(iPlaylist);
5665 // if the playlist contains an internet stream, this file will be used
5666 // to generate a thumbnail for musicplayer.cover
5667 g_application.m_strPlayListFile = strPlayList;
5669 // add the items to the playlist player
5670 g_playlistPlayer.Add(iPlaylist, playlist);
5672 // if we have a playlist
5673 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5676 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5677 g_playlistPlayer.Reset();
5678 g_playlistPlayer.Play(track);
5684 void CApplication::SaveCurrentFileSettings()
5686 // don't store settings for PVR in video database
5687 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5689 // save video settings
5690 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5694 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5698 else if (m_itemCurrentFile->IsPVRChannel())
5700 g_PVRManager.SaveCurrentChannelSettings();
5704 bool CApplication::AlwaysProcess(const CAction& action)
5706 // check if this button is mapped to a built-in function
5707 if (!action.GetName().IsEmpty())
5709 CStdString builtInFunction;
5710 vector<CStdString> params;
5711 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5712 builtInFunction.ToLower();
5714 // should this button be handled normally or just cancel the screensaver?
5715 if ( builtInFunction.Equals("powerdown")
5716 || builtInFunction.Equals("reboot")
5717 || builtInFunction.Equals("restart")
5718 || builtInFunction.Equals("restartapp")
5719 || builtInFunction.Equals("suspend")
5720 || builtInFunction.Equals("hibernate")
5721 || builtInFunction.Equals("quit")
5722 || builtInFunction.Equals("shutdown"))
5731 bool CApplication::IsCurrentThread() const
5733 return CThread::IsCurrentThread(m_threadID);
5736 void CApplication::SetRenderGUI(bool renderGUI)
5738 if (renderGUI && ! m_renderGUI)
5739 g_windowManager.MarkDirty();
5740 m_renderGUI = renderGUI;
5743 CNetwork& CApplication::getNetwork()
5747 #ifdef HAS_PERFORMANCE_SAMPLE
5748 CPerformanceStats &CApplication::GetPerformanceStats()
5754 bool CApplication::SetLanguage(const CStdString &strLanguage)
5756 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5757 CStdString strNewLanguage = strLanguage;
5758 if (strNewLanguage != strPreviousLanguage)
5760 CStdString strLangInfoPath;
5761 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5762 if (!g_langInfo.Load(strLangInfoPath))
5765 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5767 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5768 CStdString strFontSet;
5769 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5770 strNewLanguage = strFontSet;
5772 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5774 CSettings::Get().SetString("locale.language", strNewLanguage);
5776 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5779 // also tell our weather and skin to reload as these are localized
5780 g_weatherManager.Refresh();
5781 g_PVRManager.LocalizationChanged();
5788 void CApplication::CloseNetworkShares()
5790 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5792 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5796 #ifdef HAS_FILESYSTEM_NFS
5797 gNfsConnection.Deinit();
5800 #ifdef HAS_FILESYSTEM_AFP
5801 gAfpConnection.Deinit();
5804 #ifdef HAS_FILESYSTEM_SFTP
5805 CSFTPSessionManager::DisconnectAllSessions();