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 = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
770 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
771 g_langInfo.Load(strLangInfoPath);
772 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
773 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
775 CStdString strLanguagePath = "special://xbmc/language/";
777 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
778 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
780 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
784 // start the AudioEngine
785 if (!CAEFactory::StartEngine())
787 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
791 // restore AE's previous volume state
792 SetHardwareVolume(m_volumeLevel);
793 CAEFactory::SetMute (m_muted);
794 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
796 // initialize m_replayGainSettings
797 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
798 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
799 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
800 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
802 // initialize the addon database (must be before the addon manager is init'd)
803 CDatabaseManager::Get().Initialize(true);
806 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
809 // start-up Addons Framework
810 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
811 if (!CAddonMgr::Get().Init())
813 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
816 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
817 g_RemoteControl.Initialize();
820 // set logging from debug add-on
822 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
824 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
826 g_peripherals.Initialise();
828 // Create the Mouse, Keyboard, Remote, and Joystick devices
829 // Initialize after loading settings to get joystick deadzone setting
830 g_Mouse.Initialize();
831 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
833 g_Keyboard.Initialize();
835 #if defined(TARGET_DARWIN_OSX)
836 // Configure and possible manually start the helper.
837 XBMCHelper::GetInstance().Configure();
840 CUtil::InitRandomSeed();
842 g_mediaManager.Initialize();
844 m_lastFrameTime = XbmcThreads::SystemClockMillis();
845 m_lastRenderTime = m_lastFrameTime;
849 bool CApplication::CreateGUI()
853 CLog::Log(LOGNOTICE, "Setup SDL");
855 /* Clean up on exit, exit on window close and interrupt */
858 uint32_t sdlFlags = 0;
860 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
861 sdlFlags |= SDL_INIT_VIDEO;
864 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
865 sdlFlags |= SDL_INIT_JOYSTICK;
868 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
869 //this might bring the monitor out of standby, so we have to disable it explicitly
870 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
871 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
872 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
878 // for nvidia cards - vsync currently ALWAYS enabled.
879 // the reason is that after screen has been setup changing this env var will make no difference.
880 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
881 setenv("__GL_YIELD", "USLEEP", 0);
884 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
885 g_Windowing.EnableSystemScreenSaver(false);
888 if (SDL_Init(sdlFlags) != 0)
890 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
893 #if defined(TARGET_DARWIN)
894 // SDL_Init will install a handler for segfaults, restore the default handler.
895 signal(SIGSEGV, SIG_DFL);
899 // Initialize core peripheral port support. Note: If these parameters
900 // are 0 and NULL, respectively, then the default number and types of
901 // controllers will be initialized.
902 if (!g_Windowing.InitWindowSystem())
904 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
908 // Retrieve the matching resolution based on GUI settings
909 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
910 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
911 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
913 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
914 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
917 // update the window resolution
918 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
920 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
921 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
923 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
925 // Oh uh - doesn't look good for starting in their wanted screenmode
926 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
927 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
934 if (g_advancedSettings.m_splashImage)
936 CStdString strUserSplash = "special://home/media/Splash.png";
937 if (CFile::Exists(strUserSplash))
939 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
940 m_splash = new CSplash(strUserSplash);
944 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
945 m_splash = new CSplash("special://xbmc/media/Splash.png");
950 // The key mappings may already have been loaded by a peripheral
951 CLog::Log(LOGINFO, "load keymapping");
952 if (!CButtonTranslator::GetInstance().Load())
955 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
956 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
959 info.strMode.c_str());
960 g_windowManager.Initialize();
965 bool CApplication::InitWindow()
967 #ifdef TARGET_DARWIN_OSX
968 // force initial window creation to be windowed, if fullscreen, it will switch to it below
969 // fixes the white screen of death if starting fullscreen and switching to windowed.
970 bool bFullScreen = false;
971 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
973 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
977 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
978 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
980 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
985 if (!g_Windowing.InitRenderSystem())
987 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
990 // set GUI res and force the clear of the screen
991 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
995 bool CApplication::DestroyWindow()
997 return g_Windowing.DestroyWindow();
1000 bool CApplication::InitDirectoriesLinux()
1003 The following is the directory mapping for Platform Specific Mode:
1005 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1006 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1007 installations like skins, screensavers, etc.
1009 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1010 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1011 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1012 special://profile/ => [read-write] current profile's userdata directory.
1013 Generally special://masterprofile for the master profile or
1014 special://masterprofile/profiles/<profile_name> for other profiles.
1016 NOTE: All these root directories are lowercase. Some of the sub-directories
1017 might be mixed case.
1020 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1021 CStdString userName;
1023 userName = getenv("USER");
1027 CStdString userHome;
1029 userHome = getenv("HOME");
1033 CStdString xbmcBinPath, xbmcPath;
1034 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1035 xbmcPath = getenv("XBMC_HOME");
1037 if (xbmcPath.empty())
1039 xbmcPath = xbmcBinPath;
1040 /* Check if xbmc binaries and arch independent data files are being kept in
1041 * separate locations. */
1042 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1044 /* Attempt to locate arch independent data files. */
1045 CUtil::GetHomePath(xbmcPath);
1046 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1048 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1054 /* Set some environment variables */
1055 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1056 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1058 if (m_bPlatformDirectories)
1060 // map our special drives
1061 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1062 CSpecialProtocol::SetXBMCPath(xbmcPath);
1063 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1064 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1066 CStdString strTempPath = userHome;
1067 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1068 if (getenv("XBMC_TEMP"))
1069 strTempPath = getenv("XBMC_TEMP");
1070 CSpecialProtocol::SetTempPath(strTempPath);
1072 URIUtils::AddSlashAtEnd(strTempPath);
1073 g_advancedSettings.m_logFolder = strTempPath;
1080 URIUtils::AddSlashAtEnd(xbmcPath);
1081 g_advancedSettings.m_logFolder = xbmcPath;
1083 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1084 CSpecialProtocol::SetXBMCPath(xbmcPath);
1085 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1086 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1088 CStdString strTempPath = xbmcPath;
1089 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1090 if (getenv("XBMC_TEMP"))
1091 strTempPath = getenv("XBMC_TEMP");
1092 CSpecialProtocol::SetTempPath(strTempPath);
1095 URIUtils::AddSlashAtEnd(strTempPath);
1096 g_advancedSettings.m_logFolder = strTempPath;
1105 bool CApplication::InitDirectoriesOSX()
1107 #if defined(TARGET_DARWIN)
1108 CStdString userName;
1110 userName = getenv("USER");
1114 CStdString userHome;
1116 userHome = getenv("HOME");
1120 CStdString xbmcPath;
1121 CUtil::GetHomePath(xbmcPath);
1122 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1124 #if defined(TARGET_DARWIN_IOS)
1125 CStdString fontconfigPath;
1126 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1127 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1130 // setup path to our internal dylibs so loader can find them
1131 CStdString frameworksPath = CUtil::GetFrameworksPath();
1132 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1134 // OSX always runs with m_bPlatformDirectories == true
1135 if (m_bPlatformDirectories)
1137 // map our special drives
1138 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1139 CSpecialProtocol::SetXBMCPath(xbmcPath);
1140 #if defined(TARGET_DARWIN_IOS)
1141 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1142 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1144 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1145 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1148 // location for temp files
1149 #if defined(TARGET_DARWIN_IOS)
1150 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1152 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1153 CDirectory::Create(strTempPath);
1154 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1156 CSpecialProtocol::SetTempPath(strTempPath);
1158 // xbmc.log file location
1159 #if defined(TARGET_DARWIN_IOS)
1160 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1162 strTempPath = userHome + "/Library/Logs";
1164 URIUtils::AddSlashAtEnd(strTempPath);
1165 g_advancedSettings.m_logFolder = strTempPath;
1171 URIUtils::AddSlashAtEnd(xbmcPath);
1172 g_advancedSettings.m_logFolder = xbmcPath;
1174 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1175 CSpecialProtocol::SetXBMCPath(xbmcPath);
1176 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1177 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1179 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1180 CSpecialProtocol::SetTempPath(strTempPath);
1182 URIUtils::AddSlashAtEnd(strTempPath);
1183 g_advancedSettings.m_logFolder = strTempPath;
1192 bool CApplication::InitDirectoriesWin32()
1194 #ifdef TARGET_WINDOWS
1195 CStdString xbmcPath;
1197 CUtil::GetHomePath(xbmcPath);
1198 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1199 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1200 CSpecialProtocol::SetXBMCPath(xbmcPath);
1202 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1204 g_advancedSettings.m_logFolder = strWin32UserFolder;
1205 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1206 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1207 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1209 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1213 // Expand the DLL search path with our directories
1214 CWIN32Util::ExtendDllPath();
1222 void CApplication::CreateUserDirs()
1224 CDirectory::Create("special://home/");
1225 CDirectory::Create("special://home/addons");
1226 CDirectory::Create("special://home/addons/packages");
1227 CDirectory::Create("special://home/media");
1228 CDirectory::Create("special://home/sounds");
1229 CDirectory::Create("special://home/system");
1230 CDirectory::Create("special://masterprofile/");
1231 CDirectory::Create("special://temp/");
1232 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1235 bool CApplication::Initialize()
1237 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1238 // turn off cdio logging
1239 cdio_loglevel_default = CDIO_LOG_ERROR;
1242 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1243 // must create these here. Ideally this should be using special://home/ and
1244 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1245 if (!m_bPlatformDirectories)
1248 CDirectory::Create("special://xbmc/language");
1249 CDirectory::Create("special://xbmc/addons");
1250 CDirectory::Create("special://xbmc/sounds");
1253 // Load curl so curl_global_init gets called before any service threads
1254 // are started. Unloading will have no effect as curl is never fully unloaded.
1255 // To quote man curl_global_init:
1256 // "This function is not thread safe. You must not call it when any other
1257 // thread in the program (i.e. a thread sharing the same memory) is running.
1258 // This doesn't just mean no other thread that is using libcurl. Because
1259 // curl_global_init() calls functions of other libraries that are similarly
1260 // thread unsafe, it could conflict with any other thread that
1261 // uses these other libraries."
1262 g_curlInterface.Load();
1263 g_curlInterface.Unload();
1265 // initialize (and update as needed) our databases
1266 CDatabaseManager::Get().Initialize();
1270 // Init DPMS, before creating the corresponding setting control.
1271 m_dpms = new DPMSSupport();
1272 if (g_windowManager.Initialized())
1274 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1276 g_windowManager.Add(new CGUIWindowHome);
1277 g_windowManager.Add(new CGUIWindowPrograms);
1278 g_windowManager.Add(new CGUIWindowPictures);
1279 g_windowManager.Add(new CGUIWindowFileManager);
1280 g_windowManager.Add(new CGUIWindowSettings);
1281 g_windowManager.Add(new CGUIWindowSystemInfo);
1283 g_windowManager.Add(new CGUIWindowTestPatternGL);
1286 g_windowManager.Add(new CGUIWindowTestPatternDX);
1288 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1289 g_windowManager.Add(new CGUIWindowSettingsCategory);
1290 g_windowManager.Add(new CGUIWindowVideoNav);
1291 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1292 g_windowManager.Add(new CGUIWindowLoginScreen);
1293 g_windowManager.Add(new CGUIWindowSettingsProfile);
1294 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1295 g_windowManager.Add(new CGUIWindowAddonBrowser);
1296 g_windowManager.Add(new CGUIWindowScreensaverDim);
1297 g_windowManager.Add(new CGUIWindowDebugInfo);
1298 g_windowManager.Add(new CGUIWindowPointer);
1299 g_windowManager.Add(new CGUIDialogYesNo);
1300 g_windowManager.Add(new CGUIDialogProgress);
1301 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1302 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1303 g_windowManager.Add(new CGUIDialogVolumeBar);
1304 g_windowManager.Add(new CGUIDialogSeekBar);
1305 g_windowManager.Add(new CGUIDialogSubMenu);
1306 g_windowManager.Add(new CGUIDialogContextMenu);
1307 g_windowManager.Add(new CGUIDialogKaiToast);
1308 g_windowManager.Add(new CGUIDialogNumeric);
1309 g_windowManager.Add(new CGUIDialogGamepad);
1310 g_windowManager.Add(new CGUIDialogButtonMenu);
1311 g_windowManager.Add(new CGUIDialogMuteBug);
1312 g_windowManager.Add(new CGUIDialogPlayerControls);
1314 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1315 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1317 g_windowManager.Add(new CGUIDialogSlider);
1318 g_windowManager.Add(new CGUIDialogMusicOSD);
1319 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1320 g_windowManager.Add(new CGUIDialogVideoSettings);
1321 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1322 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1323 // Don't add the filebrowser dialog - it's created and added when it's needed
1324 g_windowManager.Add(new CGUIDialogNetworkSetup);
1325 g_windowManager.Add(new CGUIDialogMediaSource);
1326 g_windowManager.Add(new CGUIDialogProfileSettings);
1327 g_windowManager.Add(new CGUIDialogFavourites);
1328 g_windowManager.Add(new CGUIDialogSongInfo);
1329 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1330 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1331 g_windowManager.Add(new CGUIDialogBusy);
1332 g_windowManager.Add(new CGUIDialogPictureInfo);
1333 g_windowManager.Add(new CGUIDialogAddonInfo);
1334 g_windowManager.Add(new CGUIDialogAddonSettings);
1335 #ifdef HAS_LINUX_NETWORK
1336 g_windowManager.Add(new CGUIDialogAccessPoints);
1339 g_windowManager.Add(new CGUIDialogLockSettings);
1341 g_windowManager.Add(new CGUIDialogContentSettings);
1343 g_windowManager.Add(new CGUIDialogPlayEject);
1345 g_windowManager.Add(new CGUIDialogPeripheralManager);
1346 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1348 g_windowManager.Add(new CGUIDialogMediaFilter);
1349 g_windowManager.Add(new CGUIDialogSubtitles);
1351 g_windowManager.Add(new CGUIWindowMusicPlayList);
1352 g_windowManager.Add(new CGUIWindowMusicSongs);
1353 g_windowManager.Add(new CGUIWindowMusicNav);
1354 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1356 /* Load PVR related Windows and Dialogs */
1357 g_windowManager.Add(new CGUIDialogTeletext);
1358 g_windowManager.Add(new CGUIWindowPVR);
1359 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1360 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1361 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1362 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1363 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1364 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1365 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1366 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1367 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1368 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1370 g_windowManager.Add(new CGUIDialogSelect);
1371 g_windowManager.Add(new CGUIDialogMusicInfo);
1372 g_windowManager.Add(new CGUIDialogOK);
1373 g_windowManager.Add(new CGUIDialogVideoInfo);
1374 g_windowManager.Add(new CGUIDialogTextViewer);
1375 g_windowManager.Add(new CGUIWindowFullScreen);
1376 g_windowManager.Add(new CGUIWindowVisualisation);
1377 g_windowManager.Add(new CGUIWindowSlideShow);
1378 g_windowManager.Add(new CGUIDialogFileStacking);
1380 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1383 g_windowManager.Add(new CGUIDialogVideoOSD);
1384 g_windowManager.Add(new CGUIDialogMusicOverlay);
1385 g_windowManager.Add(new CGUIDialogVideoOverlay);
1386 g_windowManager.Add(new CGUIWindowScreensaver);
1387 g_windowManager.Add(new CGUIWindowWeather);
1388 g_windowManager.Add(new CGUIWindowStartup);
1390 /* window id's 3000 - 3100 are reserved for python */
1392 // Make sure we have at least the default skin
1393 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1394 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1396 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1400 if (g_advancedSettings.m_splashImage)
1401 SAFE_DELETE(m_splash);
1403 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1404 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1405 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1407 g_passwordManager.CheckStartUpLock();
1410 // check if we should use the login screen
1411 if (CProfilesManager::Get().UsingLoginScreen())
1412 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1416 CJSONRPC::Initialize();
1418 ADDON::CAddonMgr::Get().StartServices(false);
1419 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1421 g_windowManager.ActivateWindow(WINDOW_HOME);
1422 StartPVRManager(true);
1426 StartPVRManager(false);
1427 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1430 CStereoscopicsManager::Get().Initialize();
1434 else //No GUI Created
1437 CJSONRPC::Initialize();
1439 ADDON::CAddonMgr::Get().StartServices(false);
1442 g_sysinfo.Refresh();
1444 CLog::Log(LOGINFO, "removing tempfiles");
1445 CUtil::RemoveTempFiles();
1447 if (!CProfilesManager::Get().UsingLoginScreen())
1453 m_slowTimer.StartZero();
1455 #if defined(HAVE_LIBCRYSTALHD)
1456 CCrystalHD::GetInstance();
1459 CAddonMgr::Get().StartServices(true);
1461 CLog::Log(LOGNOTICE, "initialize done");
1463 m_bInitializing = false;
1465 // reset our screensaver (starts timers etc.)
1468 #ifdef HAS_SDL_JOYSTICK
1469 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1470 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1476 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1482 // the callback will take care of starting/stopping webserver
1483 ret = CSettings::Get().SetBool("services.webserver", bStart);
1486 case ES_AIRPLAYSERVER:
1487 // the callback will take care of starting/stopping airplay
1488 ret = CSettings::Get().SetBool("services.airplay", bStart);
1491 case ES_JSONRPCSERVER:
1492 // the callback will take care of starting/stopping jsonrpc server
1493 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1497 // the callback will take care of starting/stopping upnp server
1498 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1501 case ES_UPNPRENDERER:
1502 // the callback will take care of starting/stopping upnp renderer
1503 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1506 case ES_EVENTSERVER:
1507 // the callback will take care of starting/stopping event server
1508 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1512 // the callback will take care of starting/stopping zeroconf
1513 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1520 CSettings::Get().Save();
1525 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1527 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1528 g_PVRManager.Start(true, bOpenPVRWindow);
1531 void CApplication::StopPVRManager()
1533 CLog::Log(LOGINFO, "stopping PVRManager");
1534 if (g_PVRManager.IsPlaying())
1536 g_PVRManager.Stop();
1537 g_EpgContainer.Stop();
1540 void CApplication::StartServices()
1542 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1543 // Start Thread for DVD Mediatype detection
1544 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1545 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1548 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1549 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1550 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1551 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1552 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1553 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1556 void CApplication::StopServices()
1558 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1560 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1561 CLog::Log(LOGNOTICE, "stop dvd detect media");
1562 m_DetectDVDType.StopThread();
1565 g_peripherals.Clear();
1568 void CApplication::OnSettingChanged(const CSetting *setting)
1570 if (setting == NULL)
1573 const std::string &settingId = setting->GetId();
1574 if (settingId == "lookandfeel.skin" ||
1575 settingId == "lookandfeel.font" ||
1576 settingId == "lookandfeel.skincolors")
1578 // if the skin changes and the current theme is not the default one, reset
1579 // the theme to the default value (which will also change lookandfeel.skincolors
1580 // which in turn will reload the skin
1581 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1582 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1585 std::string builtin("ReloadSkin");
1586 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1587 builtin += "(confirm)";
1588 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1591 else if (settingId == "lookandfeel.skintheme")
1593 // also set the default color theme
1594 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1595 URIUtils::RemoveExtension(colorTheme);
1596 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1597 colorTheme = "defaults";
1599 // check if we have to change the skin color
1600 // if yes, it will trigger a call to ReloadSkin() in
1601 // it's OnSettingChanged() callback
1602 // if no we have to call ReloadSkin() ourselves
1603 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1604 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1606 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1608 else if (settingId == "lookandfeel.skinzoom")
1609 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1610 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1612 // AE is master of audio settings and needs to be informed first
1613 CAEFactory::OnSettingsChange(settingId);
1615 if (settingId == "audiooutput.guisoundmode")
1617 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1619 // this tells player whether to open an audio stream passthrough or PCM
1620 // if this is changed, audio stream has to be reopened
1621 else if (settingId == "audiooutput.passthrough")
1623 CApplicationMessenger::Get().MediaRestart(false);
1626 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1627 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1628 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1629 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1630 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1631 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1632 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1633 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1636 void CApplication::OnSettingAction(const CSetting *setting)
1638 if (setting == NULL)
1641 const std::string &settingId = setting->GetId();
1642 if (settingId == "lookandfeel.skinsettings")
1643 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1644 else if (settingId == "screensaver.preview")
1645 ActivateScreenSaver(true);
1646 else if (settingId == "screensaver.settings")
1649 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1650 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1652 else if (settingId == "videoscreen.guicalibration")
1653 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1654 else if (settingId == "videoscreen.testpattern")
1655 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1658 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1660 if (setting == NULL)
1663 const std::string &settingId = setting->GetId();
1664 if (settingId == "audiooutput.channels")
1666 // check if this is an update from Eden
1667 if (oldSettingId != NULL && oldSettingNode != NULL &&
1668 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1671 CSettingInt* channels = (CSettingInt*)setting;
1672 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1673 ret = channels->SetValue(channels->GetValue() + 1);
1675 // let's just reset the audiodevice settings as well
1676 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1677 CAEFactory::VerifyOutputDevice(audiodevice, false);
1678 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1683 else if (settingId == "screensaver.mode")
1685 CSettingString *screensaverMode = (CSettingString*)setting;
1686 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1687 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1688 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1690 else if (settingId == "scrapers.musicvideosdefault")
1692 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1693 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1695 musicvideoScraper->Reset();
1699 #if defined(HAS_LIBAMCODEC)
1700 else if (settingId == "videoplayer.useamcodec")
1702 // Do not permit amcodec to be used on non-aml platforms.
1703 // The setting will be hidden but the default value is true,
1704 // so change it to false.
1707 CSettingBool *useamcodec = (CSettingBool*)setting;
1708 useamcodec->SetValue(false);
1712 #if defined(TARGET_ANDROID)
1713 else if (settingId == "videoplayer.usemediacodec")
1715 // Do not permit MediaCodec to be used Android platforms that do not have it.
1716 // The setting will be hidden but the default value is true,
1717 // so change it to false.
1718 if (CAndroidFeatures::GetVersion() < 16)
1720 CSettingBool *usemediacodec = (CSettingBool*)setting;
1721 usemediacodec->SetValue(false);
1724 else if (settingId == "videoplayer.usestagefright")
1726 CSettingBool *usestagefright = (CSettingBool*)setting;
1727 usestagefright->SetValue(false);
1734 bool CApplication::OnSettingsSaving() const
1736 // don't save settings when we're busy stopping the application
1737 // a lot of screens try to save settings on deinit and deinit is
1738 // called for every screen when the application is stopping
1745 void CApplication::ReloadSkin(bool confirm/*=false*/)
1747 m_skinReloading = false;
1748 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1750 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1751 g_windowManager.SendMessage(msg);
1753 // Reload the skin, restoring the previously focused control. We need this as
1754 // the window unload will reset all control states.
1756 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1758 iCtrlID = pWindow->GetFocusedControlID();
1760 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1764 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1765 if (pWindow && pWindow->HasSaveLastControl())
1767 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1768 pWindow->OnMessage(msg3);
1772 if (!m_skinReverting && confirm)
1775 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1777 m_skinReverting = true;
1778 if (oldSkin.empty())
1779 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1781 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1785 m_skinReverting = false;
1788 bool CApplication::Load(const TiXmlNode *settings)
1790 if (settings == NULL)
1793 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1794 if (audioElement != NULL)
1796 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1797 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1798 m_volumeLevel = VOLUME_MAXIMUM;
1804 bool CApplication::Save(TiXmlNode *settings) const
1806 if (settings == NULL)
1809 TiXmlElement volumeNode("audio");
1810 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1811 if (audioNode == NULL)
1814 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1815 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1820 bool CApplication::LoadSkin(const CStdString& skinID)
1822 if (m_skinReloading)
1826 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1828 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1834 void CApplication::LoadSkin(const SkinPtr& skin)
1836 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1839 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1840 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1845 if (!skin->HasSkinFile("Home.xml"))
1847 // failed to find home.xml
1848 // fallback to default skin
1849 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1851 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1852 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1853 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1858 bool bPreviousPlayingState=false;
1859 bool bPreviousRenderingState=false;
1860 if (g_application.m_pPlayer->IsPlayingVideo())
1862 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1863 if (bPreviousPlayingState)
1864 g_application.m_pPlayer->Pause();
1865 #ifdef HAS_VIDEO_PLAYBACK
1866 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1868 g_windowManager.ActivateWindow(WINDOW_HOME);
1869 bPreviousRenderingState = true;
1873 // close the music and video overlays (they're re-opened automatically later)
1874 CSingleLock lock(g_graphicsContext);
1876 // save the current window details
1877 int currentWindow = g_windowManager.GetActiveWindow();
1878 vector<int> currentModelessWindows;
1879 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1883 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1885 g_SkinInfo->Start();
1887 CLog::Log(LOGINFO, " load fonts for skin...");
1888 g_graphicsContext.SetMediaDir(skin->Path());
1889 g_directoryCache.ClearSubPaths(skin->Path());
1890 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1892 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1893 CStdString strFontSet;
1894 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1896 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1897 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1898 CSettings::Get().Save();
1901 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1903 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1905 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1907 // load in the skin strings
1908 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1909 URIUtils::AddSlashAtEnd(langPath);
1911 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1913 g_SkinInfo->LoadIncludes();
1916 start = CurrentHostCounter();
1918 CLog::Log(LOGINFO, " load new skin...");
1920 // Load the user windows
1924 end = CurrentHostCounter();
1925 freq = CurrentHostFrequency();
1926 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1928 CLog::Log(LOGINFO, " initialize new skin...");
1929 g_windowManager.AddMsgTarget(this);
1930 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1931 g_windowManager.AddMsgTarget(&g_infoManager);
1932 g_windowManager.AddMsgTarget(&g_fontManager);
1933 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1934 g_windowManager.SetCallback(*this);
1935 g_windowManager.Initialize();
1936 CTextureCache::Get().Initialize();
1937 g_audioManager.Enable(true);
1938 g_audioManager.Load();
1940 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1941 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1943 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1944 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1945 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1946 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1947 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1950 CLog::Log(LOGINFO, " skin loaded...");
1952 // leave the graphics lock
1956 if (currentWindow != WINDOW_INVALID)
1958 g_windowManager.ActivateWindow(currentWindow);
1959 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1961 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1962 if (dialog) dialog->Show();
1966 if (g_application.m_pPlayer->IsPlayingVideo())
1968 if (bPreviousPlayingState)
1969 g_application.m_pPlayer->Pause();
1970 if (bPreviousRenderingState)
1971 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1975 void CApplication::UnloadSkin(bool forReload /* = false */)
1977 m_skinReloading = forReload;
1979 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1981 g_audioManager.Enable(false);
1983 g_windowManager.DeInitialize();
1984 CTextureCache::Get().Deinitialize();
1986 // remove the skin-dependent window
1987 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1989 g_TextureManager.Cleanup();
1990 g_largeTextureManager.CleanupUnusedImages(true);
1992 g_fontManager.Clear();
1994 g_colorManager.Clear();
1996 g_infoManager.Clear();
1998 // The g_SkinInfo boost shared_ptr ought to be reset here
1999 // but there are too many places it's used without checking for NULL
2000 // and as a result a race condition on exit can cause a crash.
2003 bool CApplication::LoadUserWindows()
2005 // Start from wherever home.xml is
2006 std::vector<CStdString> vecSkinPath;
2007 g_SkinInfo->GetSkinPaths(vecSkinPath);
2008 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2010 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2011 CFileItemList items;
2012 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2014 for (int i = 0; i < items.Size(); ++i)
2016 if (items[i]->m_bIsFolder)
2018 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2019 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2021 CXBMCTinyXML xmlDoc;
2022 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2024 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2028 // Root element should be <window>
2029 TiXmlElement* pRootElement = xmlDoc.RootElement();
2030 CStdString strValue = pRootElement->Value();
2031 if (!strValue.Equals("window"))
2033 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2037 // Read the <type> element to get the window type to create
2038 // If no type is specified, create a CGUIWindow as default
2039 CGUIWindow* pWindow = NULL;
2041 if (pRootElement->Attribute("type"))
2042 strType = pRootElement->Attribute("type");
2045 const TiXmlNode *pType = pRootElement->FirstChild("type");
2046 if (pType && pType->FirstChild())
2047 strType = pType->FirstChild()->Value();
2049 int id = WINDOW_INVALID;
2050 if (!pRootElement->Attribute("id", &id))
2052 const TiXmlNode *pType = pRootElement->FirstChild("id");
2053 if (pType && pType->FirstChild())
2054 id = atol(pType->FirstChild()->Value());
2056 CStdString visibleCondition;
2057 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2059 if (strType.Equals("dialog"))
2060 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2061 else if (strType.Equals("submenu"))
2062 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2063 else if (strType.Equals("buttonmenu"))
2064 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2066 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2068 // Check to make sure the pointer isn't still null
2069 if (pWindow == NULL)
2071 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2074 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2079 pWindow->SetVisibleCondition(visibleCondition);
2080 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2081 g_windowManager.AddCustomWindow(pWindow);
2089 bool CApplication::RenderNoPresent()
2093 // DXMERGE: This may have been important?
2094 // g_graphicsContext.AcquireCurrentContext();
2096 g_graphicsContext.Lock();
2098 // dont show GUI when playing full screen video
2099 if (g_graphicsContext.IsFullScreenVideo())
2101 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2102 g_renderManager.Render(true, 0, 255);
2104 // close window overlays
2105 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2106 if (overlay) overlay->Close(true);
2107 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2108 if (overlay) overlay->Close(true);
2112 bool hasRendered = g_windowManager.Render();
2114 g_graphicsContext.Unlock();
2119 float CApplication::GetDimScreenSaverLevel() const
2121 if (!m_bScreenSave || !m_screenSaver ||
2122 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2123 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2124 !m_screenSaver->ID().empty()))
2127 if (!m_screenSaver->GetSetting("level").empty())
2128 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2132 void CApplication::Render()
2134 // do not render if we are stopped or in background
2135 if (m_bStop || m_bInBackground)
2140 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2142 bool hasRendered = false;
2143 bool limitFrames = false;
2144 unsigned int singleFrameTime = 10; // default limit 100 fps
2148 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2149 // Whether externalplayer is playing and we're unfocused
2150 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2152 m_bPresentFrame = false;
2153 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2155 m_bPresentFrame = g_renderManager.FrameWait(100);
2160 // engage the frame limiter as needed
2161 limitFrames = lowfps || extPlayerActive;
2162 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2163 // perhaps allowing it to be set differently than the UI option??
2164 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2165 limitFrames = true; // not using vsync.
2166 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2167 limitFrames = true; // using vsync, but it isn't working.
2171 if (extPlayerActive)
2173 ResetScreenSaver(); // Prevent screensaver dimming the screen
2174 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2177 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2183 CSingleLock lock(g_graphicsContext);
2184 g_infoManager.UpdateFPS();
2186 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2187 g_Windowing.SetVSync(true);
2188 else if (vsync_mode == VSYNC_ALWAYS)
2189 g_Windowing.SetVSync(true);
2190 else if (vsync_mode != VSYNC_DRIVER)
2191 g_Windowing.SetVSync(false);
2193 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2196 if(!g_Windowing.BeginRender())
2199 g_renderManager.FrameMove();
2201 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2202 if(g_graphicsContext.GetStereoMode())
2204 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2205 if(RenderNoPresent())
2208 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2210 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2211 if(RenderNoPresent())
2214 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2218 if(RenderNoPresent())
2222 g_renderManager.FrameFinish();
2224 g_Windowing.EndRender();
2226 // execute post rendering actions (finalize window closing)
2227 g_windowManager.AfterRender();
2229 // reset our info cache - we do this at the end of Render so that it is
2230 // fresh for the next process(), or after a windowclose animation (where process()
2232 g_infoManager.ResetCache();
2235 unsigned int now = XbmcThreads::SystemClockMillis();
2237 m_lastRenderTime = now;
2239 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2240 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2242 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2243 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2247 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2248 if (limitFrames || !flip)
2251 singleFrameTime = 40; //if not flipping, loop at 25 fps
2253 unsigned int frameTime = now - m_lastFrameTime;
2254 if (frameTime < singleFrameTime)
2255 Sleep(singleFrameTime - frameTime);
2257 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2260 g_graphicsContext.Flip(dirtyRegions);
2261 CTimeUtils::UpdateFrameTime(flip);
2263 g_renderManager.UpdateResolution();
2264 g_renderManager.ManageCaptures();
2267 void CApplication::SetStandAlone(bool value)
2269 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2272 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2273 // The window manager will return true if the event is processed, false otherwise.
2274 // If not already processed, this routine handles global keypresses. It returns
2275 // true if the key has been processed, false otherwise.
2277 bool CApplication::OnKey(const CKey& key)
2280 // Turn the mouse off, as we've just got a keypress from controller or remote
2281 g_Mouse.SetActive(false);
2283 // get the current active window
2284 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2286 // this will be checked for certain keycodes that need
2287 // special handling if the screensaver is active
2288 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2290 // a key has been pressed.
2292 m_idleTimer.StartZero();
2293 bool processKey = AlwaysProcess(action);
2295 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2299 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2300 // do not wake up the screensaver right after switching off the playing device
2301 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2302 ret = CApplicationMessenger::Get().CECToggleState();
2304 ret = CApplicationMessenger::Get().CECStandby();
2305 if (!ret) /* display is switched off */
2311 // allow some keys to be processed while the screensaver is active
2312 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2314 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2318 // change this if we have a dialog up
2319 if (g_windowManager.HasModalDialog())
2321 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2323 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2324 { // fullscreen info dialog - special case
2325 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2327 if (!key.IsAnalogButton())
2328 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2330 if (OnAction(action))
2333 // fallthrough to the main window
2334 iWin = WINDOW_FULLSCREEN_VIDEO;
2336 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2338 // current active window is full screen video.
2339 if (g_application.m_pPlayer->IsInMenu())
2341 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2342 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2344 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2346 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2347 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2349 // if no PVR specific action/mapping is found, fall back to default
2350 if (action.GetID() == 0)
2351 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2355 // in any other case use the fullscreen window section of keymap.xml to map key->action
2356 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2361 // current active window isnt the fullscreen window
2362 // just use corresponding section from keymap.xml
2363 // to map key->action
2365 // first determine if we should use keyboard input directly
2366 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2367 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2370 CGUIControl *control = window->GetFocusedControl();
2373 // If this is an edit control set usekeyboard to true. This causes the
2374 // keypress to be processed directly not through the key mappings.
2375 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2378 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2379 // This causes the keypress to be used for list navigation.
2380 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2386 action = CAction(0); // reset our action
2387 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2389 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2390 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2391 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2392 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2393 action.GetID() == ACTION_MOVE_RIGHT ||
2394 action.GetID() == ACTION_MOVE_UP ||
2395 action.GetID() == ACTION_MOVE_DOWN ||
2396 action.GetID() == ACTION_SELECT_ITEM ||
2397 action.GetID() == ACTION_ENTER ||
2398 action.GetID() == ACTION_PREVIOUS_MENU ||
2399 action.GetID() == ACTION_NAV_BACK))
2401 // the action isn't plain navigation - check for a keyboard-specific keymap
2402 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2403 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2404 action.GetID() == ACTION_BACKSPACE ||
2405 action.GetID() == ACTION_SHIFT ||
2406 action.GetID() == ACTION_SYMBOLS ||
2407 action.GetID() == ACTION_CURSOR_LEFT ||
2408 action.GetID() == ACTION_CURSOR_RIGHT)
2409 action = CAction(0); // don't bother with this action
2412 if (!action.GetID())
2414 // keyboard entry - pass the keys through directly
2415 if (key.GetFromService())
2416 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2419 // Check for paste keypress
2420 #ifdef TARGET_WINDOWS
2421 // In Windows paste is ctrl-V
2422 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2423 #elif defined(TARGET_LINUX)
2424 // In Linux paste is ctrl-V
2425 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2426 #elif defined(TARGET_DARWIN_OSX)
2427 // In OSX paste is cmd-V
2428 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2430 // Placeholder for other operating systems
2433 action = CAction(ACTION_PASTE);
2434 // If the unicode is non-zero the keypress is a non-printing character
2435 else if (key.GetUnicode())
2436 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2437 // The keypress is a non-printing character
2439 action = CAction(key.GetVKey() | KEY_VKEY);
2443 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2445 if (OnAction(action))
2447 // failed to handle the keyboard action, drop down through to standard action
2449 if (key.GetFromService())
2451 if (key.GetButtonCode() != KEY_INVALID)
2452 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2455 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2457 if (!key.IsAnalogButton())
2458 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2460 return ExecuteInputAction(action);
2463 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2464 // This needs to return true if it processed the appcommand or false if it didn't
2465 bool CApplication::OnAppCommand(const CAction &action)
2467 // Reset the screen saver
2470 // If we were currently in the screen saver wake up and don't process the appcommand
2471 if (WakeUpScreenSaverAndDPMS())
2474 // The action ID is the APPCOMMAND code. We need to retrieve the action
2475 // associated with this appcommand from the mapping table.
2476 uint32_t appcmd = action.GetID();
2477 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2478 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2479 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2481 // If we couldn't find an action return false to indicate we have not
2482 // handled this appcommand
2483 if (!appcmdaction.GetID())
2485 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2489 // Process the appcommand
2490 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2491 OnAction(appcmdaction);
2493 // Always return true regardless of whether the action succeeded or not.
2494 // This stops Windows handling the appcommand itself.
2498 bool CApplication::OnAction(const CAction &action)
2500 // special case for switching between GUI & fullscreen mode.
2501 if (action.GetID() == ACTION_SHOW_GUI)
2502 { // Switch to fullscreen mode if we can
2503 if (SwitchToFullScreen())
2505 m_navigationTimer.StartZero();
2510 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2512 g_graphicsContext.ToggleFullScreenRoot();
2516 if (action.IsMouse())
2517 g_Mouse.SetActive(true);
2520 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2522 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2524 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2526 CGUIDialogVideoBookmarks::OnAddBookmark();
2529 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2530 // playing or ACTION_PLAYER_PLAY if we are not playing.
2531 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2533 if (m_pPlayer->IsPlaying())
2534 return OnAction(CAction(ACTION_PAUSE));
2536 return OnAction(CAction(ACTION_PLAYER_PLAY));
2539 //if the action would start or stop inertial scrolling
2540 //by gesture - bypass the normal OnAction handler of current window
2541 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2544 // just pass the action to the current window and let it handle it
2545 if (g_windowManager.OnAction(action))
2547 m_navigationTimer.StartZero();
2552 // handle extra global presses
2554 // screenshot : take a screenshot :)
2555 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2557 CScreenShot::TakeScreenshot();
2560 // built in functions : execute the built-in
2561 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2563 CBuiltins::Execute(action.GetName());
2564 m_navigationTimer.StartZero();
2569 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2571 CButtonTranslator::GetInstance().Clear();
2572 CButtonTranslator::GetInstance().Load();
2575 // show info : Shows the current video or song information
2576 if (action.GetID() == ACTION_SHOW_INFO)
2578 g_infoManager.ToggleShowInfo();
2582 // codec info : Shows the current song, video or picture codec information
2583 if (action.GetID() == ACTION_SHOW_CODEC)
2585 g_infoManager.ToggleShowCodec();
2589 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2591 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2594 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2595 char rating = tag->GetRating();
2596 bool needsUpdate(false);
2597 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2599 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2602 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2604 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2610 if (db.Open()) // OpenForWrite() ?
2612 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2615 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2616 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2617 g_windowManager.SendMessage(msg);
2623 // Now check with the playlist player if action can be handled.
2624 // 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.
2625 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2627 if (g_playlistPlayer.OnAction(action))
2631 // Now check with the player if action can be handled.
2632 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2633 (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)) ||
2634 action.GetID() == ACTION_STOP)
2636 if (m_pPlayer->OnAction(action))
2640 // stop : stops playing current audio song
2641 if (action.GetID() == ACTION_STOP)
2647 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2648 // If so, we just jump to the start of the track.
2649 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2652 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2656 // forward action to g_PVRManager and break if it was able to handle it
2657 if (g_PVRManager.OnAction(action))
2660 // forward action to graphic context and see if it can handle it
2661 if (CStereoscopicsManager::Get().OnAction(action))
2664 if (m_pPlayer->IsPlaying())
2666 // forward channel switches to the player - he knows what to do
2667 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2669 m_pPlayer->OnAction(action);
2673 // pause : pauses current audio song
2674 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2678 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2680 if (!m_pPlayer->IsPaused())
2681 { // unpaused - set the playspeed back to normal
2682 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2684 g_audioManager.Enable(m_pPlayer->IsPaused());
2687 if (!m_pPlayer->IsPaused())
2689 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2690 // if we are playing at normal speed, then allow play to pause
2691 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2693 if (m_pPlayer->GetPlaySpeed() != 1)
2695 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2703 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2705 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2706 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2708 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2710 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2715 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2717 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2720 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2723 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2725 // calculate the speed based on the amount the button is held down
2726 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2727 // returns 0 -> MAX_FFWD_SPEED
2728 int iSpeed = 1 << iPower;
2729 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2731 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2733 CLog::Log(LOGDEBUG,"Resetting playspeed");
2737 // allow play to unpause
2740 if (action.GetID() == ACTION_PLAYER_PLAY)
2742 // unpause, and set the playspeed back to normal
2744 g_audioManager.Enable(m_pPlayer->IsPaused());
2746 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2751 if (m_playerController->OnAction(action))
2756 if (action.GetID() == ACTION_SWITCH_PLAYER)
2758 if(m_pPlayer->IsPlaying())
2760 VECPLAYERCORES cores;
2761 CFileItem item(*m_itemCurrentFile.get());
2762 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2763 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2764 if(core != EPC_NONE)
2766 g_application.m_eForcedNextPlayer = core;
2767 item.m_lStartOffset = (int)(GetTime() * 75);
2768 PlayFile(item, true);
2773 VECPLAYERCORES cores;
2774 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2775 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2776 if(core != EPC_NONE)
2779 g_application.m_eForcedNextPlayer = core;
2780 PlayFile(item, false);
2785 if (g_peripherals.OnAction(action))
2788 if (action.GetID() == ACTION_MUTE)
2794 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2796 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2797 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2799 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2801 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2802 g_windowManager.SendMessage(msg);
2807 // Check for global volume control
2808 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2810 if (!m_pPlayer->IsPassthrough())
2814 float volume = m_volumeLevel;
2815 // Android has steps based on the max available volume level
2816 #if defined(TARGET_ANDROID)
2817 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2819 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2821 if (action.GetRepeat())
2822 step *= action.GetRepeat() * 50; // 50 fps
2824 if (action.GetID() == ACTION_VOLUME_UP)
2825 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2827 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2828 SetVolume(volume, false);
2830 // show visual feedback of volume change...
2831 ShowVolumeBar(&action);
2834 // Check for global seek control
2835 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2837 if (!m_pPlayer->CanSeek()) return false;
2838 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2841 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2843 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2844 CGUIControlProfiler::Instance().Start();
2847 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2849 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2850 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2851 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2852 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2853 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2859 void CApplication::FrameMove(bool processEvents, bool processGUI)
2865 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2866 float frameTime = m_frameTime.GetElapsedSeconds();
2867 m_frameTime.StartZero();
2868 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2869 if( frameTime > 0.5 ) frameTime = 0.5;
2871 if (processGUI && m_renderGUI)
2873 g_graphicsContext.Lock();
2874 // check if there are notifications to display
2875 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2876 if (toast && toast->DoWork())
2878 if (!toast->IsDialogRunning())
2883 g_graphicsContext.Unlock();
2885 CWinEvents::MessagePump();
2887 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2888 // Read the input from a remote
2889 g_RemoteControl.Update();
2892 // process input actions
2893 ProcessRemote(frameTime);
2894 ProcessGamepad(frameTime);
2895 ProcessEventServer(frameTime);
2896 ProcessPeripherals(frameTime);
2897 if (processGUI && m_renderGUI)
2899 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2900 m_seekHandler->Process();
2903 if (processGUI && m_renderGUI)
2906 g_windowManager.Process(CTimeUtils::GetFrameTime());
2907 g_windowManager.FrameMove();
2911 bool CApplication::ProcessGamepad(float frameTime)
2913 #ifdef HAS_SDL_JOYSTICK
2917 int iWin = GetActiveWindowID();
2919 g_Joystick.Update();
2920 if (g_Joystick.GetButton(bid))
2923 m_idleTimer.StartZero();
2926 if (WakeUpScreenSaverAndDPMS())
2928 g_Joystick.Reset(true);
2933 CStdString actionName;
2935 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2937 CAction action(actionID, 1.0f, 0.0f, actionName);
2939 g_Mouse.SetActive(false);
2940 return ExecuteInputAction(action);
2947 if (g_Joystick.GetAxis(bid))
2949 if (g_Joystick.GetAmount() < 0)
2955 CStdString actionName;
2957 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2960 if (WakeUpScreenSaverAndDPMS())
2965 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2967 g_Mouse.SetActive(false);
2968 return ExecuteInputAction(action);
2972 g_Joystick.ResetAxis(abs(bid));
2976 if (g_Joystick.GetHat(bid, position))
2979 m_idleTimer.StartZero();
2982 if (WakeUpScreenSaverAndDPMS())
2989 CStdString actionName;
2992 bid = position<<16|bid;
2994 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2996 CAction action(actionID, 1.0f, 0.0f, actionName);
2998 g_Mouse.SetActive(false);
2999 return ExecuteInputAction(action);
3006 bool CApplication::ProcessRemote(float frameTime)
3008 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3009 if (g_RemoteControl.GetButton())
3011 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3012 g_RemoteControl.Reset();
3019 bool CApplication::ProcessPeripherals(float frameTime)
3022 if (g_peripherals.GetNextKeypress(frameTime, key))
3027 bool CApplication::ProcessMouse()
3031 if (!g_Mouse.IsActive() || !m_AppFocused)
3034 // Get the mouse command ID
3035 uint32_t mousecommand = g_Mouse.GetAction();
3036 if (mousecommand == ACTION_NOOP)
3039 // Reset the screensaver and idle timers
3040 m_idleTimer.StartZero();
3042 if (WakeUpScreenSaverAndDPMS())
3045 // Retrieve the corresponding action
3046 int iWin = GetActiveWindowID();
3047 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3048 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3050 // Deactivate mouse if non-mouse action
3051 if (!mouseaction.IsMouse())
3052 g_Mouse.SetActive(false);
3054 // Consume ACTION_NOOP.
3055 // Some views or dialogs gets closed after any ACTION and
3056 // a sensitive mouse might cause problems.
3057 if (mouseaction.GetID() == ACTION_NOOP)
3060 // If we couldn't find an action return false to indicate we have not
3061 // handled this mouse action
3062 if (!mouseaction.GetID())
3064 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3068 // Log mouse actions except for move and noop
3069 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3070 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3072 // The action might not be a mouse action. For example wheel moves might
3073 // be mapped to volume up/down in mouse.xml. In this case we do not want
3074 // the mouse position saved in the action.
3075 if (!mouseaction.IsMouse())
3076 return OnAction(mouseaction);
3078 // This is a mouse action so we need to record the mouse position
3079 return OnAction(CAction(mouseaction.GetID(),
3080 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3081 (float)g_Mouse.GetX(),
3082 (float)g_Mouse.GetY(),
3083 (float)g_Mouse.GetDX(),
3084 (float)g_Mouse.GetDY(),
3085 mouseaction.GetName()));
3088 bool CApplication::ProcessEventServer(float frameTime)
3090 #ifdef HAS_EVENT_SERVER
3091 CEventServer* es = CEventServer::GetInstance();
3092 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3095 // process any queued up actions
3096 if (es->ExecuteNextAction())
3098 // reset idle timers
3099 m_idleTimer.StartZero();
3101 WakeUpScreenSaverAndDPMS();
3104 // now handle any buttons or axis
3105 std::string joystickName;
3106 bool isAxis = false;
3107 float fAmount = 0.0;
3109 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3110 // when the action exits XBMC
3111 es = CEventServer::GetInstance();
3112 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3114 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3118 if (joystickName.length() > 0)
3122 if (fabs(fAmount) >= 0.08)
3123 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3125 m_lastAxisMap[joystickName].erase(wKeyID);
3128 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3133 if (wKeyID & ES_FLAG_UNICODE)
3135 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3139 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3140 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3141 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3142 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3143 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3144 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3145 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3146 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3147 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3148 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3149 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3150 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3151 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3152 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3153 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3154 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3155 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3156 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3157 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3158 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3161 key.SetFromService(true);
3166 if (m_lastAxisMap.size() > 0)
3168 // Process all the stored axis.
3169 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3171 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3172 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3178 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3180 XBMC_Event newEvent;
3181 newEvent.type = XBMC_MOUSEMOTION;
3182 newEvent.motion.xrel = 0;
3183 newEvent.motion.yrel = 0;
3184 newEvent.motion.state = 0;
3185 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3186 newEvent.motion.x = (uint16_t)pos.x;
3187 newEvent.motion.y = (uint16_t)pos.y;
3188 OnEvent(newEvent); // had to call this to update g_Mouse position
3189 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3196 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3198 #if defined(HAS_EVENT_SERVER)
3199 m_idleTimer.StartZero();
3201 // Make sure to reset screen saver, mouse.
3203 if (WakeUpScreenSaverAndDPMS())
3206 #ifdef HAS_SDL_JOYSTICK
3209 g_Mouse.SetActive(false);
3211 int iWin = GetActiveWindowID();
3213 CStdString actionName;
3214 bool fullRange = false;
3216 // Translate using regular joystick translator.
3217 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3218 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3220 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3226 bool CApplication::ExecuteInputAction(const CAction &action)
3228 bool bResult = false;
3230 // play sound before the action unless the button is held,
3231 // where we execute after the action as held actions aren't fired every time.
3232 if(action.GetHoldTime())
3234 bResult = OnAction(action);
3236 g_audioManager.PlayActionSound(action);
3240 g_audioManager.PlayActionSound(action);
3241 bResult = OnAction(action);
3246 int CApplication::GetActiveWindowID(void)
3248 // Get the currently active window
3249 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3251 // If there is a dialog active get the dialog id instead
3252 if (g_windowManager.HasModalDialog())
3253 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3255 // If the window is FullScreenVideo check for special cases
3256 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3258 // check if we're in a DVD menu
3259 if(g_application.m_pPlayer->IsInMenu())
3260 iWin = WINDOW_VIDEO_MENU;
3261 // check for LiveTV and switch to it's virtual window
3262 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3263 iWin = WINDOW_FULLSCREEN_LIVETV;
3266 // Return the window id
3270 bool CApplication::Cleanup()
3274 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3275 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3276 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3277 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3278 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3279 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3280 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3281 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3282 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3283 g_windowManager.Delete(WINDOW_FILES);
3284 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3285 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3286 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3287 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3288 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3289 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3290 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3291 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3292 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3293 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3294 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3295 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3296 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3297 g_windowManager.Delete(WINDOW_DIALOG_OK);
3298 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3299 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3300 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3301 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3302 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3303 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3304 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3305 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3306 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3307 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3308 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3309 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3310 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3311 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3312 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3313 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3314 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3315 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3316 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3317 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3318 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3319 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3320 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3322 /* Delete PVR related windows and dialogs */
3323 g_windowManager.Delete(WINDOW_PVR);
3324 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3325 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3326 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3327 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3328 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3329 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3330 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3331 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3332 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3333 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3334 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3335 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3336 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3338 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3339 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3340 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3341 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3342 g_windowManager.Delete(WINDOW_VISUALISATION);
3343 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3344 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3345 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3346 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3347 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3348 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3349 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3350 g_windowManager.Delete(WINDOW_SCREENSAVER);
3351 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3352 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3353 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3354 g_windowManager.Delete(WINDOW_SLIDESHOW);
3355 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3356 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3358 g_windowManager.Delete(WINDOW_HOME);
3359 g_windowManager.Delete(WINDOW_PROGRAMS);
3360 g_windowManager.Delete(WINDOW_PICTURES);
3361 g_windowManager.Delete(WINDOW_WEATHER);
3363 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3364 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3365 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3366 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3367 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3368 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3369 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3370 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3371 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3372 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3374 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3375 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3377 CAddonMgr::Get().DeInit();
3379 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3380 CLog::Log(LOGNOTICE, "closing down remote control service");
3381 g_RemoteControl.Disconnect();
3384 CLog::Log(LOGNOTICE, "unload sections");
3386 #ifdef HAS_PERFORMANCE_SAMPLE
3387 CLog::Log(LOGNOTICE, "performance statistics");
3388 m_perfStats.DumpStats();
3391 // Shutdown as much as possible of the
3392 // application, to reduce the leaks dumped
3393 // to the vc output window before calling
3394 // _CrtDumpMemoryLeaks(). Most of the leaks
3395 // shown are no real leaks, as parts of the app
3396 // are still allocated.
3398 g_localizeStrings.Clear();
3399 g_LangCodeExpander.Clear();
3400 g_charsetConverter.clear();
3401 g_directoryCache.Clear();
3402 CButtonTranslator::GetInstance().Clear();
3403 #ifdef HAS_EVENT_SERVER
3404 CEventServer::RemoveInstance();
3406 DllLoaderContainer::Clear();
3407 g_playlistPlayer.Clear();
3408 CSettings::Get().Uninitialize();
3409 g_advancedSettings.Clear();
3412 CXHandle::DumpObjectTracker();
3414 #ifdef HAS_DVD_DRIVE
3415 CLibcdio::ReleaseInstance();
3418 #if defined(TARGET_ANDROID)
3419 // enable for all platforms once it's safe
3420 g_sectionLoader.UnloadAll();
3422 #ifdef _CRTDBG_MAP_ALLOC
3423 _CrtDumpMemoryLeaks();
3424 while(1); // execution ends
3434 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3439 void CApplication::Stop(int exitCode)
3443 CVariant vExitCode(exitCode);
3444 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3446 SaveFileState(true);
3448 g_alarmClock.StopThread();
3450 if( m_bSystemScreenSaverEnable )
3451 g_Windowing.EnableSystemScreenSaver(true);
3453 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3454 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3456 // Update the settings information (volume, uptime etc. need saving)
3457 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3459 CLog::Log(LOGNOTICE, "Saving settings");
3460 CSettings::Get().Save();
3463 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3466 m_AppFocused = false;
3467 m_ExitCode = exitCode;
3468 CLog::Log(LOGNOTICE, "stop all");
3470 // cancel any jobs from the jobmanager
3471 CJobManager::GetInstance().CancelJobs();
3473 // stop scanning before we kill the network and so on
3474 if (m_musicInfoScanner->IsScanning())
3475 m_musicInfoScanner->Stop();
3477 if (m_videoInfoScanner->IsScanning())
3478 m_videoInfoScanner->Stop();
3480 CApplicationMessenger::Get().Cleanup();
3482 CLog::Log(LOGNOTICE, "stop player");
3483 m_pPlayer->ClosePlayer();
3489 #if HAS_FILESYTEM_DAAP
3490 CLog::Log(LOGNOTICE, "stop daap clients");
3491 g_DaapClient.Release();
3493 #ifdef HAS_FILESYSTEM_SAP
3494 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3495 g_sapsessions.StopThread();
3498 if(CZeroconfBrowser::IsInstantiated())
3500 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3501 CZeroconfBrowser::GetInstance()->Stop();
3502 CZeroconfBrowser::ReleaseInstance();
3506 CLog::Log(LOGNOTICE, "clean cached files!");
3507 #ifdef HAS_FILESYSTEM_RAR
3508 g_RarManager.ClearCache(true);
3511 #ifdef HAS_FILESYSTEM_SFTP
3512 CSFTPSessionManager::DisconnectAllSessions();
3515 CLog::Log(LOGNOTICE, "unload skin");
3518 #if defined(TARGET_DARWIN_OSX)
3519 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3520 XBMCHelper::GetInstance().Stop();
3523 #if defined(HAVE_LIBCRYSTALHD)
3524 CCrystalHD::RemoveInstance();
3527 g_mediaManager.Stop();
3529 // Stop services before unloading Python
3530 CAddonMgr::Get().StopServices(false);
3532 // stop all remaining scripts; must be done after skin has been unloaded,
3533 // not before some windows still need it when deinitializing during skin
3535 CScriptInvocationManager::Get().Uninitialize();
3537 g_Windowing.DestroyRenderSystem();
3538 g_Windowing.DestroyWindow();
3539 g_Windowing.DestroyWindowSystem();
3541 // shutdown the AudioEngine
3542 CAEFactory::Shutdown();
3543 CAEFactory::UnLoadEngine();
3545 CLog::Log(LOGNOTICE, "stopped");
3549 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3552 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3553 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3560 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3562 //If item is a plugin, expand out now and run ourselves again
3563 if (item.IsPlugin())
3565 CFileItem item_new(item);
3566 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3567 return PlayMedia(item_new, iPlaylist);
3570 if (item.IsSmartPlayList())
3572 CFileItemList items;
3573 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3576 CSmartPlaylist smartpl;
3577 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3578 smartpl.OpenAndReadName(item.GetPath());
3580 playlist.Add(items);
3581 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3584 else if (item.IsPlayList() || item.IsInternetStream())
3586 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3588 //is or could be a playlist
3589 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3590 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3595 if (dlgCache->IsCanceled())
3602 if (iPlaylist != PLAYLIST_NONE)
3605 if (item.HasProperty("playlist_starting_track"))
3606 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3607 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3611 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());
3612 if(pPlayList->size())
3613 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3618 //nothing special just play
3619 return PlayFile(item, false) == PLAYBACK_OK;
3623 // For playing a multi-file video. Particularly inefficient
3624 // on startup, as we are required to calculate the length
3625 // of each video, so we open + close each one in turn.
3626 // A faster calculation of video time would improve this
3628 // return value: same with PlayFile()
3629 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3631 if (!item.IsStack())
3632 return PLAYBACK_FAIL;
3636 // case 1: stacked ISOs
3637 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3639 CStackDirectory dir;
3640 CFileItemList movieList;
3641 dir.GetDirectory(item.GetPath(), movieList);
3643 // first assume values passed to the stack
3644 int selectedFile = item.m_lStartPartNumber;
3645 int startoffset = item.m_lStartOffset;
3647 // check if we instructed the stack to resume from default
3648 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3653 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3655 startoffset = (int)(bookmark.timeInSeconds*75);
3656 selectedFile = bookmark.partNumber;
3661 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3664 // make sure that the selected part is within the boundaries
3665 if (selectedFile <= 0)
3667 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3670 else if (selectedFile > movieList.Size())
3672 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3673 selectedFile = movieList.Size();
3676 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3677 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3678 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3679 *m_stackFileItemToUpdate = item;
3680 return PlayFile(*(movieList[selectedFile - 1]));
3682 // case 2: all other stacks
3685 // see if we have the info in the database
3686 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3687 // then these times will be wrong.
3688 // Also, this is really just a hack for the slow load up times we have
3689 // A much better solution is a fast reader of FPS and fileLength
3690 // that we can use on a file to get it's time.
3692 bool haveTimes(false);
3696 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3697 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3702 // calculate the total time of the stack
3703 CStackDirectory dir;
3704 dir.GetDirectory(item.GetPath(), *m_currentStack);
3706 for (int i = 0; i < m_currentStack->Size(); i++)
3709 (*m_currentStack)[i]->m_lEndOffset = times[i];
3713 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3715 m_currentStack->Clear();
3716 return PLAYBACK_FAIL;
3718 totalTime += duration / 1000;
3719 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3720 times.push_back(totalTime);
3724 double seconds = item.m_lStartOffset / 75.0;
3726 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3727 { // have our times now, so update the dB
3731 dbs.SetStackTimes(item.GetPath(), times);
3733 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3735 // can only resume seek here, not dvdstate
3737 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3738 seconds = bookmark.timeInSeconds;
3746 *m_itemCurrentFile = item;
3747 m_currentStackPosition = 0;
3748 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3752 // work out where to seek to
3753 for (int i = 0; i < m_currentStack->Size(); i++)
3755 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3757 CFileItem item(*(*m_currentStack)[i]);
3758 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3759 item.m_lStartOffset = (long)(seconds - start) * 75;
3760 m_currentStackPosition = i;
3761 return PlayFile(item, true);
3766 return PlayFile(*(*m_currentStack)[0], true);
3768 return PLAYBACK_FAIL;
3771 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3773 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3774 if (item.GetMimeType().empty())
3775 const_cast<CFileItem&>(item).FillInMimeType();
3779 SaveCurrentFileSettings();
3781 OutputDebugString("new file set audiostream:0\n");
3782 // Switch to default options
3783 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3784 // see if we have saved options in the database
3786 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3787 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3789 *m_itemCurrentFile = item;
3790 m_nextPlaylistItem = -1;
3791 m_currentStackPosition = 0;
3792 m_currentStack->Clear();
3795 CUtil::ClearSubtitles();
3798 if (item.IsDiscStub())
3800 #ifdef HAS_DVD_DRIVE
3801 // Display the Play Eject dialog if there is any optical disc drive
3802 if (g_mediaManager.HasOpticalDrive())
3804 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3805 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3806 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3807 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3811 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3816 if (item.IsPlayList())
3817 return PLAYBACK_FAIL;
3819 if (item.IsPlugin())
3820 { // we modify the item so that it becomes a real URL
3821 CFileItem item_new(item);
3822 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3823 return PlayFile(item_new, false);
3824 return PLAYBACK_FAIL;
3828 if (URIUtils::IsUPnP(item.GetPath()))
3830 CFileItem item_new(item);
3831 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3832 return PlayFile(item_new, false);
3833 return PLAYBACK_FAIL;
3837 // if we have a stacked set of files, we need to setup our stack routines for
3838 // "seamless" seeking and total time of the movie etc.
3839 // will recall with restart set to true
3841 return PlayStack(item, bRestart);
3843 //Is TuxBox, this should probably be moved to CTuxBoxFile
3846 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3848 if(g_tuxboxService.IsRunning())
3849 g_tuxboxService.Stop();
3851 PlayBackRet ret = PLAYBACK_FAIL;
3853 if(g_tuxbox.CreateNewItem(item, item_new))
3856 // Make sure it doesn't have a player
3857 // so we actually select one normally
3858 m_pPlayer->ResetPlayer();
3860 // keep the tuxbox:// url as playing url
3861 // and give the new url to the player
3862 ret = PlayFile(item_new, true);
3863 if(ret == PLAYBACK_OK)
3865 if(!g_tuxboxService.IsRunning())
3866 g_tuxboxService.Start();
3872 CPlayerOptions options;
3874 if( item.HasProperty("StartPercent") )
3876 double fallback = 0.0f;
3877 if(item.GetProperty("StartPercent").isString())
3878 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3879 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3882 PLAYERCOREID eNewCore = EPC_NONE;
3885 // have to be set here due to playstack using this for starting the file
3886 options.starttime = item.m_lStartOffset / 75.0;
3887 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3888 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3890 if( m_eForcedNextPlayer != EPC_NONE )
3891 eNewCore = m_eForcedNextPlayer;
3892 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3893 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3895 eNewCore = m_pPlayer->GetCurrentPlayer();
3899 options.starttime = item.m_lStartOffset / 75.0;
3903 // open the d/b and retrieve the bookmarks for the current movie
3906 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3908 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3910 options.starttime = 0.0f;
3912 CStdString path = item.GetPath();
3913 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3914 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3915 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3916 path = item.GetProperty("original_listitem_url").asString();
3917 if(dbs.GetResumeBookMark(path, bookmark))
3919 options.starttime = bookmark.timeInSeconds;
3920 options.state = bookmark.playerState;
3923 override with information from the actual item if available. We do this as the VFS (eg plugins)
3924 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3925 should the playerState be required, it is fetched from the database.
3926 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3928 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3929 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3931 else if (item.HasVideoInfoTag())
3933 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3935 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3938 dbs.GetBookMarkForEpisode(*tag, bookmark);
3939 options.starttime = bookmark.timeInSeconds;
3940 options.state = bookmark.playerState;
3947 if (m_eForcedNextPlayer != EPC_NONE)
3948 eNewCore = m_eForcedNextPlayer;
3950 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3953 // this really aught to be inside !bRestart, but since PlayStack
3954 // uses that to init playback, we have to keep it outside
3955 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3956 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3957 { // playing from a playlist by the looks
3958 // don't switch to fullscreen if we are not playing the first item...
3959 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3961 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3963 // TODO - this will fail if user seeks back to first file in stack
3964 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3965 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3967 options.fullscreen = false;
3968 // reset this so we don't think we are resuming on seek
3969 m_itemCurrentFile->m_lStartOffset = 0;
3972 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3974 // reset VideoStartWindowed as it's a temp setting
3975 CMediaSettings::Get().SetVideoStartWindowed(false);
3978 //We have to stop parsing a cdg before mplayer is deallocated
3979 // WHY do we have to do this????
3981 m_pKaraokeMgr->Stop();
3985 CSingleLock lock(m_playStateMutex);
3986 // tell system we are starting a file
3987 m_bPlaybackStarting = true;
3989 // for playing a new item, previous playing item's callback may already
3990 // pushed some delay message into the threadmessage list, they are not
3991 // expected be processed after or during the new item playback starting.
3992 // so we clean up previous playing item's playback callback delay messages here.
3993 int previousMsgsIgnoredByNewPlaying[] = {
3994 GUI_MSG_PLAYBACK_STARTED,
3995 GUI_MSG_PLAYBACK_ENDED,
3996 GUI_MSG_PLAYBACK_STOPPED,
3997 GUI_MSG_PLAYLIST_CHANGED,
3998 GUI_MSG_PLAYLISTPLAYER_STOPPED,
3999 GUI_MSG_PLAYLISTPLAYER_STARTED,
4000 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4001 GUI_MSG_QUEUE_NEXT_ITEM,
4004 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4006 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4009 // We should restart the player, unless the previous and next tracks are using
4010 // one of the players that allows gapless playback (paplayer, dvdplayer)
4011 m_pPlayer->ClosePlayerGapless(eNewCore);
4013 // now reset play state to starting, since we already stopped the previous playing item if there is.
4014 // and from now there should be no playback callback from previous playing item be called.
4015 m_ePlayState = PLAY_STATE_STARTING;
4017 m_pPlayer->CreatePlayer(eNewCore, *this);
4019 PlayBackRet iResult;
4020 if (m_pPlayer->HasPlayer())
4022 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4023 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4024 * increase performance on low powered systems (Atom/ARM).
4028 CJobManager::GetInstance().PauseJobs();
4031 // don't hold graphicscontext here since player
4032 // may wait on another thread, that requires gfx
4033 CSingleExit ex(g_graphicsContext);
4035 iResult = m_pPlayer->OpenFile(item, options);
4039 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4040 iResult = PLAYBACK_FAIL;
4043 if(iResult == PLAYBACK_OK)
4045 if (m_pPlayer->GetPlaySpeed() != 1)
4047 int iSpeed = m_pPlayer->GetPlaySpeed();
4048 m_pPlayer->m_iPlaySpeed = 1;
4049 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4052 // if player has volume control, set it.
4053 if (m_pPlayer->ControlsVolume())
4055 m_pPlayer->SetVolume(m_volumeLevel);
4056 m_pPlayer->SetMute(m_muted);
4059 if( m_pPlayer->IsPlayingAudio() )
4061 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4062 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4065 #ifdef HAS_VIDEO_PLAYBACK
4066 else if( m_pPlayer->IsPlayingVideo() )
4068 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4069 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4071 // if player didn't manange to switch to fullscreen by itself do it here
4072 if( options.fullscreen && g_renderManager.IsStarted()
4073 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4074 SwitchToFullScreen();
4079 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4080 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4081 g_windowManager.PreviousWindow();
4085 #if !defined(TARGET_POSIX)
4086 g_audioManager.Enable(false);
4089 if (item.HasPVRChannelInfoTag())
4090 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4093 CSingleLock lock(m_playStateMutex);
4094 m_bPlaybackStarting = false;
4096 if (iResult == PLAYBACK_OK)
4098 // play state: none, starting; playing; stopped; ended.
4099 // last 3 states are set by playback callback, they are all ignored during starting,
4100 // but we recorded the state, here we can make up the callback for the state.
4101 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4102 switch (m_ePlayState)
4104 case PLAY_STATE_PLAYING:
4105 OnPlayBackStarted();
4107 // FIXME: it seems no meaning to callback started here if there was an started callback
4108 // before this stopped/ended callback we recorded. if we callback started here
4109 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4110 // which will send OnStop announce at once, so currently, just call stopped/ended.
4111 case PLAY_STATE_ENDED:
4114 case PLAY_STATE_STOPPED:
4115 OnPlayBackStopped();
4117 case PLAY_STATE_STARTING:
4118 // neither started nor stopped/ended callback be called, that means the item still
4119 // not started, we need not make up any callback, just leave this and
4120 // let the player callback do its work.
4126 else if (iResult == PLAYBACK_FAIL)
4128 // we send this if it isn't playlistplayer that is doing this
4129 int next = g_playlistPlayer.GetNextSong();
4130 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4133 OnPlayBackStopped();
4134 m_ePlayState = PLAY_STATE_NONE;
4140 void CApplication::OnPlayBackEnded()
4142 CSingleLock lock(m_playStateMutex);
4143 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4144 m_ePlayState = PLAY_STATE_ENDED;
4145 if(m_bPlaybackStarting)
4148 // informs python script currently running playback has ended
4149 // (does nothing if python is not loaded)
4151 g_pythonParser.OnPlayBackEnded();
4154 CVariant data(CVariant::VariantTypeObject);
4156 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4158 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4159 g_windowManager.SendThreadMessage(msg);
4162 void CApplication::OnPlayBackStarted()
4164 CSingleLock lock(m_playStateMutex);
4165 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4166 m_ePlayState = PLAY_STATE_PLAYING;
4167 if(m_bPlaybackStarting)
4171 // informs python script currently running playback has started
4172 // (does nothing if python is not loaded)
4173 g_pythonParser.OnPlayBackStarted();
4176 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4177 g_windowManager.SendThreadMessage(msg);
4180 void CApplication::OnQueueNextItem()
4182 CSingleLock lock(m_playStateMutex);
4183 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4184 if(m_bPlaybackStarting)
4186 // informs python script currently running that we are requesting the next track
4187 // (does nothing if python is not loaded)
4189 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4192 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4193 g_windowManager.SendThreadMessage(msg);
4196 void CApplication::OnPlayBackStopped()
4198 CSingleLock lock(m_playStateMutex);
4199 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4200 m_ePlayState = PLAY_STATE_STOPPED;
4201 if(m_bPlaybackStarting)
4204 // informs python script currently running playback has ended
4205 // (does nothing if python is not loaded)
4207 g_pythonParser.OnPlayBackStopped();
4210 CVariant data(CVariant::VariantTypeObject);
4211 data["end"] = false;
4212 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4214 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4215 g_windowManager.SendThreadMessage(msg);
4218 void CApplication::OnPlayBackPaused()
4221 g_pythonParser.OnPlayBackPaused();
4225 param["player"]["speed"] = 0;
4226 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4227 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4230 void CApplication::OnPlayBackResumed()
4233 g_pythonParser.OnPlayBackResumed();
4237 param["player"]["speed"] = 1;
4238 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4239 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4242 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4245 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4249 param["player"]["speed"] = iSpeed;
4250 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4251 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4254 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4257 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4261 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4262 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4263 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4264 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4265 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4266 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4269 void CApplication::OnPlayBackSeekChapter(int iChapter)
4272 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4276 bool CApplication::IsPlayingFullScreenVideo() const
4278 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4281 bool CApplication::IsFullScreen()
4283 return IsPlayingFullScreenVideo() ||
4284 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4285 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4288 void CApplication::SaveFileState(bool bForeground /* = false */)
4290 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4295 CSaveFileStateJob job(*m_progressTrackingItem,
4296 *m_stackFileItemToUpdate,
4297 m_progressTrackingVideoResumeBookmark,
4298 m_progressTrackingPlayCountUpdate);
4300 // Run job in the foreground to make sure it finishes
4305 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4306 *m_stackFileItemToUpdate,
4307 m_progressTrackingVideoResumeBookmark,
4308 m_progressTrackingPlayCountUpdate);
4309 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4313 void CApplication::UpdateFileState()
4315 // Did the file change?
4316 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4320 // Reset tracking item
4321 m_progressTrackingItem->Reset();
4325 if (m_pPlayer->IsPlaying())
4327 if (m_progressTrackingItem->GetPath() == "")
4330 *m_progressTrackingItem = CurrentFileItem();
4331 m_progressTrackingPlayCountUpdate = false;
4334 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4335 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4336 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4337 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4339 m_progressTrackingPlayCountUpdate = true;
4342 // Check whether we're *really* playing video else we may race when getting eg. stream details
4343 if (m_pPlayer->IsPlayingVideo())
4345 /* Always update streamdetails, except for DVDs where we only update
4346 streamdetails if title length > 15m (Should yield more correct info) */
4347 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4349 CStreamDetails details;
4350 // Update with stream details from player, if any
4351 if (m_pPlayer->GetStreamDetails(details))
4352 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4354 if (m_progressTrackingItem->IsStack())
4355 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
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.clear();
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() == "visualization")
4523 // we can just continue as usual from vis mode
4526 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4528 else if (!m_screenSaver->ID().empty())
4529 { // we're in screensaver window
4530 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4531 g_windowManager.PreviousWindow(); // show the previous window
4532 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4533 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4541 void CApplication::CheckScreenSaverAndDPMS()
4543 if (m_bInBackground)
4545 if (!m_dpmsIsActive)
4546 g_Windowing.ResetOSScreensaver();
4548 bool maybeScreensaver =
4549 !m_dpmsIsActive && !m_bScreenSave
4550 && !CSettings::Get().GetString("screensaver.mode").empty();
4552 !m_dpmsIsActive && m_dpms->IsSupported()
4553 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4555 // Has the screen saver window become active?
4556 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4558 m_bScreenSave = true;
4559 maybeScreensaver = false;
4562 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4564 WakeUpScreenSaverAndDPMS();
4568 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4570 // See if we need to reset timer.
4571 // * Are we playing a video and it is not paused?
4572 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4573 // * Are we playing some music in fullscreen vis?
4574 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4575 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4577 ResetScreenSaverTimer();
4581 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4583 // DPMS has priority (it makes the screensaver not needed)
4585 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4588 WakeUpScreenSaver();
4590 else if (maybeScreensaver
4591 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4593 ActivateScreenSaver();
4597 // activate the screensaver.
4598 // if forceType is true, we ignore the various conditions that can alter
4599 // the type of screensaver displayed
4600 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4602 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4603 { // just activate the visualisation if user toggled the usemusicvisinstead option
4604 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4608 m_bScreenSave = true;
4610 // Get Screensaver Mode
4611 m_screenSaver.reset();
4612 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4613 m_screenSaver.reset(new CScreenSaver(""));
4615 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4617 // disable screensaver lock from the login screen
4618 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4621 // set to Dim in the case of a dialog on screen or playing video
4622 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4624 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4625 m_screenSaver.reset(new CScreenSaver(""));
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().empty())
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();
5135 // Global Idle Time in Seconds
5136 // idle time will be resetet if on any OnKey()
5137 // int return: system Idle time in seconds! 0 is no idle!
5138 int CApplication::GlobalIdleTime()
5140 if(!m_idleTimer.IsRunning())
5143 m_idleTimer.StartZero();
5145 return (int)m_idleTimer.GetElapsedSeconds();
5148 float CApplication::NavigationIdleTime()
5150 if (!m_navigationTimer.IsRunning())
5152 m_navigationTimer.Stop();
5153 m_navigationTimer.StartZero();
5155 return m_navigationTimer.GetElapsedSeconds();
5158 void CApplication::DelayedPlayerRestart()
5160 m_restartPlayerTimer.StartZero();
5163 void CApplication::CheckDelayedPlayerRestart()
5165 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5167 m_restartPlayerTimer.Stop();
5168 m_restartPlayerTimer.Reset();
5173 void CApplication::Restart(bool bSamePosition)
5175 // this function gets called when the user changes a setting (like noninterleaved)
5176 // and which means we gotta close & reopen the current playing file
5178 // first check if we're playing a file
5179 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5182 if( !m_pPlayer->HasPlayer() )
5187 // do we want to return to the current position in the file
5188 if (false == bSamePosition)
5190 // no, then just reopen the file and start at the beginning
5191 PlayFile(*m_itemCurrentFile, true);
5195 // else get current position
5196 double time = GetTime();
5198 // get player state, needed for dvd's
5199 CStdString state = m_pPlayer->GetPlayerState();
5201 // set the requested starttime
5202 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5205 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5206 m_pPlayer->SetPlayerState(state);
5209 const CStdString& CApplication::CurrentFile()
5211 return m_itemCurrentFile->GetPath();
5214 CFileItem& CApplication::CurrentFileItem()
5216 return *m_itemCurrentFile;
5219 void CApplication::ShowVolumeBar(const CAction *action)
5221 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5226 volumeBar->OnAction(*action);
5230 bool CApplication::IsMuted() const
5232 if (g_peripherals.IsMuted())
5234 return CAEFactory::IsMuted();
5237 void CApplication::ToggleMute(void)
5245 void CApplication::SetMute(bool mute)
5247 if (m_muted != mute)
5254 void CApplication::Mute()
5256 if (g_peripherals.Mute())
5259 CAEFactory::SetMute(true);
5264 void CApplication::UnMute()
5266 if (g_peripherals.UnMute())
5269 CAEFactory::SetMute(false);
5274 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5276 float hardwareVolume = iValue;
5279 hardwareVolume /= 100.0f;
5281 SetHardwareVolume(hardwareVolume);
5285 void CApplication::SetHardwareVolume(float hardwareVolume)
5287 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5288 m_volumeLevel = hardwareVolume;
5291 if (hardwareVolume > VOLUME_MINIMUM)
5293 float dB = CAEUtil::PercentToGain(hardwareVolume);
5294 value = CAEUtil::GainToScale(dB);
5299 CAEFactory::SetVolume(value);
5302 float CApplication::GetVolume(bool percentage /* = true */) const
5306 // converts the hardware volume to a percentage
5307 return m_volumeLevel * 100.0f;
5310 return m_volumeLevel;
5313 void CApplication::VolumeChanged() const
5315 CVariant data(CVariant::VariantTypeObject);
5316 data["volume"] = GetVolume();
5317 data["muted"] = m_muted;
5318 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5320 // if player has volume control, set it.
5321 if (m_pPlayer->ControlsVolume())
5323 m_pPlayer->SetVolume(m_volumeLevel);
5324 m_pPlayer->SetMute(m_muted);
5328 int CApplication::GetSubtitleDelay() const
5330 // converts subtitle delay to a percentage
5331 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5334 int CApplication::GetAudioDelay() const
5336 // converts audio delay to a percentage
5337 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5340 // Returns the total time in seconds of the current media. Fractional
5341 // portions of a second are possible - but not necessarily supported by the
5342 // player class. This returns a double to be consistent with GetTime() and
5344 double CApplication::GetTotalTime() const
5348 if (m_pPlayer->IsPlaying())
5350 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5351 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5353 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5359 void CApplication::StopShutdownTimer()
5361 if (m_shutdownTimer.IsRunning())
5362 m_shutdownTimer.Stop();
5365 void CApplication::ResetShutdownTimers()
5367 // reset system shutdown timer
5368 m_shutdownTimer.StartZero();
5370 // delete custom shutdown timer
5371 if (g_alarmClock.HasAlarm("shutdowntimer"))
5372 g_alarmClock.Stop("shutdowntimer", true);
5375 // Returns the current time in seconds of the currently playing media.
5376 // Fractional portions of a second are possible. This returns a double to
5377 // be consistent with GetTotalTime() and SeekTime().
5378 double CApplication::GetTime() const
5382 if (m_pPlayer->IsPlaying())
5384 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5386 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5387 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5390 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5396 // Sets the current position of the currently playing media to the specified
5397 // time in seconds. Fractional portions of a second are valid. The passed
5398 // time is the time offset from the beginning of the file as opposed to a
5399 // delta from the current position. This method accepts a double to be
5400 // consistent with GetTime() and GetTotalTime().
5401 void CApplication::SeekTime( double dTime )
5403 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5405 if (!m_pPlayer->CanSeek()) return;
5406 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5408 // find the item in the stack we are seeking to, and load the new
5409 // file if necessary, and calculate the correct seek within the new
5410 // file. Otherwise, just fall through to the usual routine if the
5411 // time is higher than our total time.
5412 for (int i = 0; i < m_currentStack->Size(); i++)
5414 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5416 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5417 if (m_currentStackPosition == i)
5418 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5420 { // seeking to a new file
5421 m_currentStackPosition = i;
5422 CFileItem item(*(*m_currentStack)[i]);
5423 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5424 // don't just call "PlayFile" here, as we are quite likely called from the
5425 // player thread, so we won't be able to delete ourselves.
5426 CApplicationMessenger::Get().PlayFile(item, true);
5432 // convert to milliseconds and perform seek
5433 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5437 float CApplication::GetPercentage() const
5439 if (m_pPlayer->IsPlaying())
5441 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5443 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5444 if (tag.GetDuration() > 0)
5445 return (float)(GetTime() / tag.GetDuration() * 100);
5448 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5450 double totalTime = GetTotalTime();
5451 if (totalTime > 0.0f)
5452 return (float)(GetTime() / totalTime * 100);
5455 return m_pPlayer->GetPercentage();
5460 float CApplication::GetCachePercentage() const
5462 if (m_pPlayer->IsPlaying())
5464 // Note that the player returns a relative cache percentage and we want an absolute percentage
5465 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5467 float stackedTotalTime = (float) GetTotalTime();
5468 // We need to take into account the stack's total time vs. currently playing file's total time
5469 if (stackedTotalTime > 0.0f)
5470 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5473 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5478 void CApplication::SeekPercentage(float percent)
5480 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5482 if (!m_pPlayer->CanSeek()) return;
5483 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5484 SeekTime(percent * 0.01 * GetTotalTime());
5486 m_pPlayer->SeekPercentage(percent);
5490 // SwitchToFullScreen() returns true if a switch is made, else returns false
5491 bool CApplication::SwitchToFullScreen()
5493 // if playing from the video info window, close it first!
5494 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5496 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5497 if (pDialog) pDialog->Close(true);
5500 // don't switch if there is a dialog on screen or the slideshow is active
5501 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5504 // See if we're playing a video, and are in GUI mode
5505 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5507 // then switch to fullscreen mode
5508 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5511 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5512 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5513 { // then switch to visualisation
5514 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5520 void CApplication::Minimize()
5522 g_Windowing.Minimize();
5525 PLAYERCOREID CApplication::GetCurrentPlayer()
5527 return m_pPlayer->GetCurrentPlayer();
5530 void CApplication::UpdateLibraries()
5532 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5534 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5538 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5540 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5545 bool CApplication::IsVideoScanning() const
5547 return m_videoInfoScanner->IsScanning();
5550 bool CApplication::IsMusicScanning() const
5552 return m_musicInfoScanner->IsScanning();
5555 void CApplication::StopVideoScan()
5557 if (m_videoInfoScanner->IsScanning())
5558 m_videoInfoScanner->Stop();
5561 void CApplication::StopMusicScan()
5563 if (m_musicInfoScanner->IsScanning())
5564 m_musicInfoScanner->Stop();
5567 void CApplication::StartVideoCleanup()
5569 if (m_videoInfoScanner->IsScanning())
5572 m_videoInfoScanner->CleanDatabase();
5575 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5577 if (m_videoInfoScanner->IsScanning())
5580 m_videoInfoScanner->ShowDialog(true);
5582 m_videoInfoScanner->Start(strDirectory,scanAll);
5585 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5587 if (m_musicInfoScanner->IsScanning())
5591 { // setup default flags
5592 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5593 flags |= CMusicInfoScanner::SCAN_ONLINE;
5594 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5595 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5598 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5599 m_musicInfoScanner->ShowDialog(true);
5601 m_musicInfoScanner->Start(strDirectory, flags);
5604 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5607 if (m_musicInfoScanner->IsScanning())
5610 m_musicInfoScanner->ShowDialog(true);
5612 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5615 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5618 if (m_musicInfoScanner->IsScanning())
5621 m_musicInfoScanner->ShowDialog(true);
5623 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5626 void CApplication::CheckPlayingProgress()
5628 // check if we haven't rewound past the start of the file
5629 if (m_pPlayer->IsPlaying())
5631 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5641 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5643 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5644 g_application.SeekTime(0);
5650 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5652 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5654 // initial exit conditions
5655 // no songs in playlist just return
5656 if (playlist.size() == 0)
5660 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5663 // setup correct playlist
5664 g_playlistPlayer.ClearPlaylist(iPlaylist);
5666 // if the playlist contains an internet stream, this file will be used
5667 // to generate a thumbnail for musicplayer.cover
5668 g_application.m_strPlayListFile = strPlayList;
5670 // add the items to the playlist player
5671 g_playlistPlayer.Add(iPlaylist, playlist);
5673 // if we have a playlist
5674 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5677 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5678 g_playlistPlayer.Reset();
5679 g_playlistPlayer.Play(track);
5685 void CApplication::SaveCurrentFileSettings()
5687 // don't store settings for PVR in video database
5688 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5690 // save video settings
5691 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5695 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5699 else if (m_itemCurrentFile->IsPVRChannel())
5701 g_PVRManager.SaveCurrentChannelSettings();
5705 bool CApplication::AlwaysProcess(const CAction& action)
5707 // check if this button is mapped to a built-in function
5708 if (!action.GetName().empty())
5710 CStdString builtInFunction;
5711 vector<CStdString> params;
5712 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5713 StringUtils::ToLower(builtInFunction);
5715 // should this button be handled normally or just cancel the screensaver?
5716 if ( builtInFunction.Equals("powerdown")
5717 || builtInFunction.Equals("reboot")
5718 || builtInFunction.Equals("restart")
5719 || builtInFunction.Equals("restartapp")
5720 || builtInFunction.Equals("suspend")
5721 || builtInFunction.Equals("hibernate")
5722 || builtInFunction.Equals("quit")
5723 || builtInFunction.Equals("shutdown"))
5732 bool CApplication::IsCurrentThread() const
5734 return CThread::IsCurrentThread(m_threadID);
5737 void CApplication::SetRenderGUI(bool renderGUI)
5739 if (renderGUI && ! m_renderGUI)
5740 g_windowManager.MarkDirty();
5741 m_renderGUI = renderGUI;
5744 CNetwork& CApplication::getNetwork()
5748 #ifdef HAS_PERFORMANCE_SAMPLE
5749 CPerformanceStats &CApplication::GetPerformanceStats()
5755 bool CApplication::SetLanguage(const CStdString &strLanguage)
5757 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5758 CStdString strNewLanguage = strLanguage;
5759 if (strNewLanguage != strPreviousLanguage)
5761 CStdString strLangInfoPath = StringUtils::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();