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/GUITextLayout.h"
48 #include "addons/Skin.h"
50 #include "interfaces/python/XBPython.h"
52 #include "input/ButtonTranslator.h"
53 #include "guilib/GUIAudioManager.h"
54 #include "GUIPassword.h"
55 #include "input/InertialScrollingHandler.h"
56 #include "ApplicationMessenger.h"
57 #include "SectionLoader.h"
58 #include "cores/DllLoader/DllLoaderContainer.h"
59 #include "GUIUserMessages.h"
60 #include "filesystem/DirectoryCache.h"
61 #include "filesystem/StackDirectory.h"
62 #include "filesystem/SpecialProtocol.h"
63 #include "filesystem/DllLibCurl.h"
64 #include "filesystem/MythSession.h"
65 #include "filesystem/PluginDirectory.h"
66 #ifdef HAS_FILESYSTEM_SAP
67 #include "filesystem/SAPDirectory.h"
69 #ifdef HAS_FILESYSTEM_HTSP
70 #include "filesystem/HTSPDirectory.h"
72 #include "utils/TuxBoxUtil.h"
73 #include "utils/SystemInfo.h"
74 #include "utils/TimeUtils.h"
75 #include "GUILargeTextureManager.h"
76 #include "TextureCache.h"
77 #include "playlists/SmartPlayList.h"
78 #ifdef HAS_FILESYSTEM_RAR
79 #include "filesystem/RarManager.h"
81 #include "playlists/PlayList.h"
82 #include "profiles/ProfilesManager.h"
83 #include "windowing/WindowingFactory.h"
84 #include "powermanagement/PowerManager.h"
85 #include "powermanagement/DPMSSupport.h"
86 #include "settings/SettingAddon.h"
87 #include "settings/Settings.h"
88 #include "settings/AdvancedSettings.h"
89 #include "settings/DisplaySettings.h"
90 #include "settings/MediaSettings.h"
91 #include "settings/MediaSourceSettings.h"
92 #include "settings/SkinSettings.h"
93 #include "settings/Settings.h"
94 #include "guilib/LocalizeStrings.h"
95 #include "utils/CPUInfo.h"
96 #include "utils/RssManager.h"
97 #include "utils/SeekHandler.h"
98 #include "view/ViewStateSettings.h"
100 #include "input/KeyboardStat.h"
101 #include "input/XBMC_vkeys.h"
102 #include "input/MouseStat.h"
108 #if defined(FILESYSTEM) && !defined(TARGET_POSIX)
109 #include "filesystem/FileDAAP.h"
112 #include "network/upnp/UPnP.h"
113 #include "network/upnp/UPnPSettings.h"
114 #include "filesystem/UPnPDirectory.h"
116 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
117 #include "filesystem/SMBDirectory.h"
119 #ifdef HAS_FILESYSTEM_NFS
120 #include "filesystem/NFSFile.h"
122 #ifdef HAS_FILESYSTEM_AFP
123 #include "filesystem/AFPFile.h"
125 #ifdef HAS_FILESYSTEM_SFTP
126 #include "filesystem/SFTPFile.h"
128 #include "PartyModeManager.h"
129 #ifdef HAS_VIDEO_PLAYBACK
130 #include "cores/VideoRenderers/RenderManager.h"
133 #include "music/karaoke/karaokelyricsmanager.h"
134 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
135 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
137 #include "network/Zeroconf.h"
138 #include "network/ZeroconfBrowser.h"
140 #include "threads/platform/win/Win32Exception.h"
142 #ifdef HAS_EVENT_SERVER
143 #include "network/EventServer.h"
146 #include <dbus/dbus.h>
149 #include "interfaces/json-rpc/JSONRPC.h"
150 #include "network/TCPServer.h"
153 #include "network/AirPlayServer.h"
156 #include "network/AirTunesServer.h"
158 #if defined(HAVE_LIBCRYSTALHD)
159 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
161 #include "interfaces/AnnouncementManager.h"
162 #include "peripherals/Peripherals.h"
163 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
165 #include "peripherals/devices/PeripheralImon.h"
166 #include "music/infoscanner/MusicInfoScanner.h"
169 #include "guilib/GUIWindowManager.h"
170 #include "windows/GUIWindowHome.h"
171 #include "settings/windows/GUIWindowSettings.h"
172 #include "windows/GUIWindowFileManager.h"
173 #include "settings/windows/GUIWindowSettingsCategory.h"
174 #include "music/windows/GUIWindowMusicPlaylist.h"
175 #include "music/windows/GUIWindowMusicSongs.h"
176 #include "music/windows/GUIWindowMusicNav.h"
177 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
178 #include "video/windows/GUIWindowVideoPlaylist.h"
179 #include "music/dialogs/GUIDialogMusicInfo.h"
180 #include "video/dialogs/GUIDialogVideoInfo.h"
181 #include "video/windows/GUIWindowVideoNav.h"
182 #include "profiles/windows/GUIWindowSettingsProfile.h"
184 #include "rendering/gl/GUIWindowTestPatternGL.h"
187 #include "rendering/dx/GUIWindowTestPatternDX.h"
189 #include "settings/windows/GUIWindowSettingsScreenCalibration.h"
190 #include "programs/GUIWindowPrograms.h"
191 #include "pictures/GUIWindowPictures.h"
192 #include "windows/GUIWindowWeather.h"
193 #include "windows/GUIWindowLoginScreen.h"
194 #include "addons/GUIWindowAddonBrowser.h"
195 #include "music/windows/GUIWindowVisualisation.h"
196 #include "windows/GUIWindowDebugInfo.h"
197 #include "windows/GUIWindowPointer.h"
198 #include "windows/GUIWindowSystemInfo.h"
199 #include "windows/GUIWindowScreensaver.h"
200 #include "windows/GUIWindowScreensaverDim.h"
201 #include "pictures/GUIWindowSlideShow.h"
202 #include "windows/GUIWindowStartup.h"
203 #include "video/windows/GUIWindowFullScreen.h"
204 #include "video/dialogs/GUIDialogVideoOSD.h"
205 #include "music/dialogs/GUIDialogMusicOverlay.h"
206 #include "video/dialogs/GUIDialogVideoOverlay.h"
207 #include "video/VideoInfoScanner.h"
208 #include "video/PlayerController.h"
211 #include "music/dialogs/GUIDialogMusicOSD.h"
212 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
213 #include "dialogs/GUIDialogTextViewer.h"
214 #include "network/GUIDialogNetworkSetup.h"
215 #include "dialogs/GUIDialogMediaSource.h"
216 #include "video/dialogs/GUIDialogVideoSettings.h"
217 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
218 #include "video/dialogs/GUIDialogVideoBookmarks.h"
219 #include "profiles/dialogs/GUIDialogProfileSettings.h"
220 #include "profiles/dialogs/GUIDialogLockSettings.h"
221 #include "settings/dialogs/GUIDialogContentSettings.h"
222 #include "dialogs/GUIDialogBusy.h"
223 #include "dialogs/GUIDialogKeyboardGeneric.h"
224 #include "dialogs/GUIDialogYesNo.h"
225 #include "dialogs/GUIDialogOK.h"
226 #include "dialogs/GUIDialogProgress.h"
227 #include "dialogs/GUIDialogExtendedProgressBar.h"
228 #include "dialogs/GUIDialogSelect.h"
229 #include "dialogs/GUIDialogSeekBar.h"
230 #include "dialogs/GUIDialogKaiToast.h"
231 #include "dialogs/GUIDialogVolumeBar.h"
232 #include "dialogs/GUIDialogMuteBug.h"
233 #include "video/dialogs/GUIDialogFileStacking.h"
234 #include "dialogs/GUIDialogNumeric.h"
235 #include "dialogs/GUIDialogGamepad.h"
236 #include "dialogs/GUIDialogSubMenu.h"
237 #include "dialogs/GUIDialogFavourites.h"
238 #include "dialogs/GUIDialogButtonMenu.h"
239 #include "dialogs/GUIDialogContextMenu.h"
240 #include "dialogs/GUIDialogPlayerControls.h"
241 #include "music/dialogs/GUIDialogSongInfo.h"
242 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
243 #include "dialogs/GUIDialogSmartPlaylistRule.h"
244 #include "pictures/GUIDialogPictureInfo.h"
245 #include "addons/GUIDialogAddonSettings.h"
246 #include "addons/GUIDialogAddonInfo.h"
247 #ifdef HAS_LINUX_NETWORK
248 #include "network/GUIDialogAccessPoints.h"
251 /* PVR related include Files */
252 #include "pvr/PVRManager.h"
253 #include "pvr/timers/PVRTimers.h"
254 #include "pvr/windows/GUIWindowPVR.h"
255 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
256 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
257 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
258 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
260 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
261 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
263 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
264 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
266 #include "epg/EpgContainer.h"
268 #include "video/dialogs/GUIDialogFullScreenInfo.h"
269 #include "video/dialogs/GUIDialogTeletext.h"
270 #include "dialogs/GUIDialogSlider.h"
271 #include "guilib/GUIControlFactory.h"
272 #include "dialogs/GUIDialogCache.h"
273 #include "dialogs/GUIDialogPlayEject.h"
274 #include "dialogs/GUIDialogMediaFilter.h"
275 #include "utils/XMLUtils.h"
276 #include "addons/AddonInstaller.h"
278 #ifdef HAS_PERFORMANCE_SAMPLE
279 #include "utils/PerformanceSample.h"
281 #define MEASURE_FUNCTION
284 #ifdef TARGET_WINDOWS
286 #include "win32util.h"
289 #include "windowing/X11/XRandR.h"
292 #ifdef TARGET_DARWIN_OSX
293 #include "osx/CocoaInterface.h"
294 #include "osx/XBMCHelper.h"
297 #include "osx/DarwinUtils.h"
302 #include <cdio/logging.h>
306 #include "linux/HALManager.h"
309 #include "storage/MediaManager.h"
310 #include "utils/JobManager.h"
311 #include "utils/SaveFileStateJob.h"
312 #include "utils/AlarmClock.h"
313 #include "utils/RssReader.h"
314 #include "utils/StringUtils.h"
315 #include "utils/Weather.h"
316 #include "DatabaseManager.h"
318 #include "settings/DisplaySettings.h"
319 #include "settings/MediaSettings.h"
320 #include "settings/SkinSettings.h"
321 #include "view/ViewStateSettings.h"
328 #include "input/linux/LIRC.h"
330 #ifdef HAS_IRSERVERSUITE
331 #include "input/windows/IRServerSuite.h"
334 #if defined(TARGET_WINDOWS)
335 #include "input/windows/WINJoystick.h"
336 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
337 #include "input/SDLJoystick.h"
340 #if defined(TARGET_ANDROID)
341 #include "android/activity/XBMCApp.h"
344 #ifdef TARGET_WINDOWS
345 #include "utils/Environment.h"
349 using namespace ADDON;
350 using namespace XFILE;
352 using namespace MEDIA_DETECT;
354 using namespace PLAYLIST;
355 using namespace VIDEO;
356 using namespace MUSIC_INFO;
357 #ifdef HAS_EVENT_SERVER
358 using namespace EVENTSERVER;
361 using namespace JSONRPC;
363 using namespace ANNOUNCEMENT;
366 using namespace PERIPHERALS;
368 using namespace XbmcThreads;
370 // uncomment this if you want to use release libs in the debug build.
371 // Atm this saves you 7 mb of memory
372 #define USE_RELEASE_LIBS
374 #define MAX_FFWD_SPEED 5
376 //extern IDirectSoundRenderer* m_pAudioDecoder;
377 CApplication::CApplication(void)
379 , m_itemCurrentFile(new CFileItem)
380 , m_stackFileItemToUpdate(new CFileItem)
381 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
382 , m_progressTrackingItem(new CFileItem)
383 , m_videoInfoScanner(new CVideoInfoScanner)
384 , m_musicInfoScanner(new CMusicInfoScanner)
385 , m_seekHandler(new CSeekHandler)
386 , m_playerController(new CPlayerController)
389 TiXmlBase::SetCondenseWhiteSpace(false);
391 m_bInhibitIdleShutdown = false;
392 m_bScreenSave = false;
394 m_dpmsIsActive = false;
395 m_dpmsIsManual = false;
396 m_iScreenSaveLock = 0;
397 m_bInitializing = true;
398 m_eForcedNextPlayer = EPC_NONE;
399 m_strPlayListFile = "";
400 m_nextPlaylistItem = -1;
402 m_bPlaybackStarting = false;
403 m_ePlayState = PLAY_STATE_NONE;
404 m_skinReloading = false;
410 // we start in frontend
411 m_bInBackground = false;
413 /* for now always keep this around */
415 m_pKaraokeMgr = new CKaraokeLyricsManager();
417 m_currentStack = new CFileItemList;
419 m_bPresentFrame = false;
420 m_bPlatformDirectories = true;
422 m_bStandalone = false;
423 m_bEnableLegacyRes = false;
424 m_bSystemScreenSaverEnable = false;
425 m_pInertialScrollingHandler = new CInertialScrollingHandler();
427 m_Autorun = new CAutorun();
432 m_eCurrentPlayer = EPC_NONE;
433 m_progressTrackingPlayCountUpdate = false;
434 m_currentStackPosition = 0;
436 m_lastRenderTime = 0;
440 m_volumeLevel = 1.0f;
443 CApplication::~CApplication(void)
445 delete m_musicInfoScanner;
446 delete m_videoInfoScanner;
447 delete &m_progressTrackingVideoResumeBookmark;
451 delete m_currentStack;
454 delete m_pKaraokeMgr;
458 delete m_seekHandler;
459 delete m_playerController;
460 delete m_pInertialScrollingHandler;
464 bool CApplication::OnEvent(XBMC_Event& newEvent)
466 switch(newEvent.type)
469 if (!g_application.m_bStop)
470 CApplicationMessenger::Get().Quit();
473 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
476 g_Keyboard.ProcessKeyUp();
478 case XBMC_MOUSEBUTTONDOWN:
479 case XBMC_MOUSEBUTTONUP:
480 case XBMC_MOUSEMOTION:
481 g_Mouse.HandleEvent(newEvent);
482 g_application.ProcessMouse();
484 case XBMC_VIDEORESIZE:
485 if (!g_application.m_bInitializing &&
486 !g_advancedSettings.m_fullScreen)
488 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
489 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
490 CSettings::Get().SetInt("window.width", newEvent.resize.w);
491 CSettings::Get().SetInt("window.height", newEvent.resize.h);
492 CSettings::Get().Save();
496 #ifdef TARGET_WINDOWS
497 if (g_advancedSettings.m_fullScreen)
499 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
500 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
501 if (newRes != g_graphicsContext.GetVideoResolution())
502 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
507 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
511 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
513 case XBMC_APPCOMMAND:
514 return g_application.OnAppCommand(newEvent.appcommand.action);
517 int windowId = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
519 if (newEvent.touch.action == ACTION_TOUCH_TAP)
520 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
521 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
524 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
526 actionId = newEvent.touch.action;
527 windowId = WINDOW_INVALID;
529 else if (!CButtonTranslator::GetInstance().TranslateTouchAction(newEvent.touch.action, newEvent.touch.pointers, windowId, actionId) ||
533 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), windowId, false);
534 // Post an unfocus message for touch device after the action.
535 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
537 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
538 CApplicationMessenger::Get().SendGUIMessage(msg);
546 extern "C" void __stdcall init_emu_environ();
547 extern "C" void __stdcall update_emu_environ();
550 // Utility function used to copy files from the application bundle
551 // over to the user data directory in Application Support/XBMC.
553 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
555 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
556 if (!CFile::Exists(destPath))
558 // need to copy it across
559 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
560 CFile::Cache(srcPath, destPath);
564 void CApplication::Preflight()
567 // call 'dbus_threads_init_default' before any other dbus calls in order to
568 // avoid race conditions with other threads using dbus connections
569 dbus_threads_init_default();
572 // run any platform preflight scripts.
573 #if defined(TARGET_DARWIN_OSX)
574 CStdString install_path;
576 CUtil::GetHomePath(install_path);
577 setenv("XBMC_HOME", install_path.c_str(), 0);
578 install_path += "/tools/darwin/runtime/preflight";
579 system(install_path.c_str());
583 bool CApplication::Create()
585 #if defined(HAS_LINUX_NETWORK)
586 m_network = new CNetworkLinux();
587 #elif defined(HAS_WIN32_NETWORK)
588 m_network = new CNetworkWin32();
590 m_network = new CNetwork();
595 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
597 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
598 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
602 tzset(); // Initialize timezone information variables
605 // Grab a handle to our thread to be used later in identifying the render thread.
606 m_threadID = CThread::GetCurrentThreadId();
609 //floating point precision to 24 bits (faster performance)
610 _controlfp(_PC_24, _MCW_PC);
612 /* install win32 exception translator, win32 exceptions
613 * can now be caught using c++ try catch */
614 win32_exception::install_handler();
618 // only the InitDirectories* for the current platform should return true
619 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
620 bool inited = InitDirectoriesLinux();
622 inited = InitDirectoriesOSX();
624 inited = InitDirectoriesWin32();
626 // copy required files
627 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
628 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
629 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
631 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
633 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
634 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
638 // Init our DllLoaders emu env
641 CProfilesManager::Get().Load();
643 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
644 #if defined(TARGET_DARWIN_OSX)
645 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
646 #elif defined(TARGET_DARWIN_IOS)
647 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
648 #elif defined(TARGET_FREEBSD)
649 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
650 #elif defined(TARGET_POSIX)
651 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Linux (%s, %s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
652 #elif defined(TARGET_WINDOWS)
653 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: %s. Built on %s (compiler %i)", g_infoManager.GetVersion().c_str(), g_sysinfo.GetKernelVersion().c_str(), __DATE__, _MSC_VER);
654 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
655 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
656 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
657 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
660 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
661 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
663 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
665 CSpecialProtocol::LogPaths();
667 CStdString executable = CUtil::ResolveExecutablePath();
668 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
669 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
670 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
671 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
673 CStdString strExecutablePath;
674 CUtil::GetHomePath(strExecutablePath);
676 // if we are running from DVD our UserData location will be TDATA
677 if (URIUtils::IsDVD(strExecutablePath))
679 // TODO: Should we copy over any UserData folder from the DVD?
680 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
683 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
684 for (int i=0;i<items.Size();++i)
685 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
687 g_advancedSettings.m_logFolder = "special://masterprofile/";
691 g_xrandr.LoadCustomModeLinesToAllOutputs();
694 // for python scripts that check the OS
695 #if defined(TARGET_DARWIN)
696 setenv("OS","OS X",true);
697 #elif defined(TARGET_POSIX)
698 setenv("OS","Linux",true);
699 #elif defined(TARGET_WINDOWS)
700 CEnvironment::setenv("OS", "win32");
703 g_powerManager.Initialize();
705 // Load the AudioEngine before settings as they need to query the engine
706 if (!CAEFactory::LoadEngine())
708 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
712 // Initialize default Settings - don't move
713 CLog::Log(LOGNOTICE, "load settings...");
714 if (!CSettings::Get().Initialize())
717 g_powerManager.SetDefaults();
719 // load the actual values
720 if (!CSettings::Get().Load())
722 CLog::Log(LOGFATAL, "unable to load settings");
725 CSettings::Get().SetLoaded();
727 CLog::Log(LOGINFO, "creating subdirectories");
728 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
729 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
730 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
731 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
732 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
733 CProfilesManager::Get().CreateProfileFolders();
735 update_emu_environ();//apply the GUI settings
737 // initialize our charset converter
738 g_charsetConverter.reset();
740 // Load the langinfo to have user charset <-> utf-8 conversion
741 CStdString strLanguage = CSettings::Get().GetString("locale.language");
742 strLanguage[0] = toupper(strLanguage[0]);
744 CStdString strLangInfoPath;
745 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
747 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
748 g_langInfo.Load(strLangInfoPath);
750 CStdString strLanguagePath = "special://xbmc/language/";
752 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
753 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
755 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
759 // start the AudioEngine
760 if (!CAEFactory::StartEngine())
762 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
766 // restore AE's previous volume state
767 SetHardwareVolume(m_volumeLevel);
768 CAEFactory::SetMute (m_muted);
769 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
771 // initialize m_replayGainSettings
772 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
773 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
774 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
775 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
777 // initialize the addon database (must be before the addon manager is init'd)
778 CDatabaseManager::Get().Initialize(true);
780 // start-up Addons Framework
781 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
782 if (!CAddonMgr::Get().Init())
784 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
788 // set logging from debug add-on
790 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
792 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
794 g_peripherals.Initialise();
796 // Create the Mouse, Keyboard, Remote, and Joystick devices
797 // Initialize after loading settings to get joystick deadzone setting
798 g_Mouse.Initialize();
799 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
801 g_Keyboard.Initialize();
802 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
803 g_RemoteControl.Initialize();
806 #if defined(TARGET_DARWIN_OSX)
807 // Configure and possible manually start the helper.
808 XBMCHelper::GetInstance().Configure();
811 CUtil::InitRandomSeed();
813 g_mediaManager.Initialize();
815 m_lastFrameTime = XbmcThreads::SystemClockMillis();
816 m_lastRenderTime = m_lastFrameTime;
820 bool CApplication::CreateGUI()
824 CLog::Log(LOGNOTICE, "Setup SDL");
826 /* Clean up on exit, exit on window close and interrupt */
829 uint32_t sdlFlags = 0;
831 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
832 sdlFlags |= SDL_INIT_VIDEO;
835 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
836 sdlFlags |= SDL_INIT_JOYSTICK;
839 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
840 //this might bring the monitor out of standby, so we have to disable it explicitly
841 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
842 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
843 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
849 // for nvidia cards - vsync currently ALWAYS enabled.
850 // the reason is that after screen has been setup changing this env var will make no difference.
851 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
852 setenv("__GL_YIELD", "USLEEP", 0);
855 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
856 g_Windowing.EnableSystemScreenSaver(false);
859 if (SDL_Init(sdlFlags) != 0)
861 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
864 #if defined(TARGET_DARWIN)
865 // SDL_Init will install a handler for segfaults, restore the default handler.
866 signal(SIGSEGV, SIG_DFL);
870 // Initialize core peripheral port support. Note: If these parameters
871 // are 0 and NULL, respectively, then the default number and types of
872 // controllers will be initialized.
873 if (!g_Windowing.InitWindowSystem())
875 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
879 // Retrieve the matching resolution based on GUI settings
880 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
881 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
882 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
884 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
885 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
888 // update the window resolution
889 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
891 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
892 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
894 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
896 // Oh uh - doesn't look good for starting in their wanted screenmode
897 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
898 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
905 if (g_advancedSettings.m_splashImage)
907 CStdString strUserSplash = "special://home/media/Splash.png";
908 if (CFile::Exists(strUserSplash))
910 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
911 m_splash = new CSplash(strUserSplash);
915 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
916 m_splash = new CSplash("special://xbmc/media/Splash.png");
921 // The key mappings may already have been loaded by a peripheral
922 CLog::Log(LOGINFO, "load keymapping");
923 if (!CButtonTranslator::GetInstance().Load())
926 int iResolution = g_graphicsContext.GetVideoResolution();
927 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
928 CDisplaySettings::Get().GetResolutionInfo(iResolution).iWidth,
929 CDisplaySettings::Get().GetResolutionInfo(iResolution).iHeight,
930 CDisplaySettings::Get().GetResolutionInfo(iResolution).strMode.c_str());
931 g_windowManager.Initialize();
936 bool CApplication::InitWindow()
938 #ifdef TARGET_DARWIN_OSX
939 // force initial window creation to be windowed, if fullscreen, it will switch to it below
940 // fixes the white screen of death if starting fullscreen and switching to windowed.
941 bool bFullScreen = false;
942 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
944 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
948 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
949 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
951 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
956 if (!g_Windowing.InitRenderSystem())
958 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
961 // set GUI res and force the clear of the screen
962 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
963 g_fontManager.ReloadTTFFonts();
967 bool CApplication::DestroyWindow()
969 g_fontManager.UnloadTTFFonts();
970 return g_Windowing.DestroyWindow();
973 bool CApplication::InitDirectoriesLinux()
976 The following is the directory mapping for Platform Specific Mode:
978 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
979 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
980 installations like skins, screensavers, etc.
982 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
983 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
984 mapped to special://home/userdata ($HOME/.xbmc/userdata)
985 special://profile/ => [read-write] current profile's userdata directory.
986 Generally special://masterprofile for the master profile or
987 special://masterprofile/profiles/<profile_name> for other profiles.
989 NOTE: All these root directories are lowercase. Some of the sub-directories
993 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
996 userName = getenv("USER");
1000 CStdString userHome;
1002 userHome = getenv("HOME");
1006 CStdString xbmcBinPath, xbmcPath;
1007 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1008 xbmcPath = getenv("XBMC_HOME");
1010 if (xbmcPath.IsEmpty())
1012 xbmcPath = xbmcBinPath;
1013 /* Check if xbmc binaries and arch independent data files are being kept in
1014 * separate locations. */
1015 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1017 /* Attempt to locate arch independent data files. */
1018 CUtil::GetHomePath(xbmcPath);
1019 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1021 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1027 /* Set some environment variables */
1028 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1029 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1031 if (m_bPlatformDirectories)
1033 // map our special drives
1034 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1035 CSpecialProtocol::SetXBMCPath(xbmcPath);
1036 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1037 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1039 CStdString strTempPath = userHome;
1040 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1041 if (getenv("XBMC_TEMP"))
1042 strTempPath = getenv("XBMC_TEMP");
1043 CSpecialProtocol::SetTempPath(strTempPath);
1045 URIUtils::AddSlashAtEnd(strTempPath);
1046 g_advancedSettings.m_logFolder = strTempPath;
1053 URIUtils::AddSlashAtEnd(xbmcPath);
1054 g_advancedSettings.m_logFolder = xbmcPath;
1056 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1057 CSpecialProtocol::SetXBMCPath(xbmcPath);
1058 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1059 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1061 CStdString strTempPath = xbmcPath;
1062 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1063 if (getenv("XBMC_TEMP"))
1064 strTempPath = getenv("XBMC_TEMP");
1065 CSpecialProtocol::SetTempPath(strTempPath);
1068 URIUtils::AddSlashAtEnd(strTempPath);
1069 g_advancedSettings.m_logFolder = strTempPath;
1078 bool CApplication::InitDirectoriesOSX()
1080 #if defined(TARGET_DARWIN)
1081 CStdString userName;
1083 userName = getenv("USER");
1087 CStdString userHome;
1089 userHome = getenv("HOME");
1093 CStdString xbmcPath;
1094 CUtil::GetHomePath(xbmcPath);
1095 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1097 #if defined(TARGET_DARWIN_IOS)
1098 CStdString fontconfigPath;
1099 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1100 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1103 // setup path to our internal dylibs so loader can find them
1104 CStdString frameworksPath = CUtil::GetFrameworksPath();
1105 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1107 // OSX always runs with m_bPlatformDirectories == true
1108 if (m_bPlatformDirectories)
1110 // map our special drives
1111 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1112 CSpecialProtocol::SetXBMCPath(xbmcPath);
1113 #if defined(TARGET_DARWIN_IOS)
1114 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
1115 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
1117 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1118 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1121 // location for temp files
1122 #if defined(TARGET_DARWIN_IOS)
1123 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
1125 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1126 CDirectory::Create(strTempPath);
1127 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1129 CSpecialProtocol::SetTempPath(strTempPath);
1131 // xbmc.log file location
1132 #if defined(TARGET_DARWIN_IOS)
1133 strTempPath = userHome + "/Library/Preferences";
1135 strTempPath = userHome + "/Library/Logs";
1137 URIUtils::AddSlashAtEnd(strTempPath);
1138 g_advancedSettings.m_logFolder = strTempPath;
1144 URIUtils::AddSlashAtEnd(xbmcPath);
1145 g_advancedSettings.m_logFolder = xbmcPath;
1147 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1148 CSpecialProtocol::SetXBMCPath(xbmcPath);
1149 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1150 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1152 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1153 CSpecialProtocol::SetTempPath(strTempPath);
1155 URIUtils::AddSlashAtEnd(strTempPath);
1156 g_advancedSettings.m_logFolder = strTempPath;
1165 bool CApplication::InitDirectoriesWin32()
1167 #ifdef TARGET_WINDOWS
1168 CStdString xbmcPath;
1170 CUtil::GetHomePath(xbmcPath);
1171 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1172 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1173 CSpecialProtocol::SetXBMCPath(xbmcPath);
1175 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1177 g_advancedSettings.m_logFolder = strWin32UserFolder;
1178 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1179 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1180 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1182 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1186 // Expand the DLL search path with our directories
1187 CWIN32Util::ExtendDllPath();
1195 void CApplication::CreateUserDirs()
1197 CDirectory::Create("special://home/");
1198 CDirectory::Create("special://home/addons");
1199 CDirectory::Create("special://home/addons/packages");
1200 CDirectory::Create("special://home/media");
1201 CDirectory::Create("special://home/sounds");
1202 CDirectory::Create("special://home/system");
1203 CDirectory::Create("special://masterprofile/");
1204 CDirectory::Create("special://temp/");
1205 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1208 bool CApplication::Initialize()
1210 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1211 // turn off cdio logging
1212 cdio_loglevel_default = CDIO_LOG_ERROR;
1215 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1216 // must create these here. Ideally this should be using special://home/ and
1217 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1218 if (!m_bPlatformDirectories)
1221 CDirectory::Create("special://xbmc/language");
1222 CDirectory::Create("special://xbmc/addons");
1223 CDirectory::Create("special://xbmc/sounds");
1226 // Load curl so curl_global_init gets called before any service threads
1227 // are started. Unloading will have no effect as curl is never fully unloaded.
1228 // To quote man curl_global_init:
1229 // "This function is not thread safe. You must not call it when any other
1230 // thread in the program (i.e. a thread sharing the same memory) is running.
1231 // This doesn't just mean no other thread that is using libcurl. Because
1232 // curl_global_init() calls functions of other libraries that are similarly
1233 // thread unsafe, it could conflict with any other thread that
1234 // uses these other libraries."
1235 g_curlInterface.Load();
1236 g_curlInterface.Unload();
1238 // initialize (and update as needed) our databases
1239 CDatabaseManager::Get().Initialize();
1243 // Init DPMS, before creating the corresponding setting control.
1244 m_dpms = new DPMSSupport();
1245 if (g_windowManager.Initialized())
1247 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1249 g_windowManager.Add(new CGUIWindowHome);
1250 g_windowManager.Add(new CGUIWindowPrograms);
1251 g_windowManager.Add(new CGUIWindowPictures);
1252 g_windowManager.Add(new CGUIWindowFileManager);
1253 g_windowManager.Add(new CGUIWindowSettings);
1254 g_windowManager.Add(new CGUIWindowSystemInfo);
1256 g_windowManager.Add(new CGUIWindowTestPatternGL);
1259 g_windowManager.Add(new CGUIWindowTestPatternDX);
1261 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1262 g_windowManager.Add(new CGUIWindowSettingsCategory);
1263 g_windowManager.Add(new CGUIWindowVideoNav);
1264 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1265 g_windowManager.Add(new CGUIWindowLoginScreen);
1266 g_windowManager.Add(new CGUIWindowSettingsProfile);
1267 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1268 g_windowManager.Add(new CGUIWindowAddonBrowser);
1269 g_windowManager.Add(new CGUIWindowScreensaverDim);
1270 g_windowManager.Add(new CGUIWindowDebugInfo);
1271 g_windowManager.Add(new CGUIWindowPointer);
1272 g_windowManager.Add(new CGUIDialogYesNo);
1273 g_windowManager.Add(new CGUIDialogProgress);
1274 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1275 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1276 g_windowManager.Add(new CGUIDialogVolumeBar);
1277 g_windowManager.Add(new CGUIDialogSeekBar);
1278 g_windowManager.Add(new CGUIDialogSubMenu);
1279 g_windowManager.Add(new CGUIDialogContextMenu);
1280 g_windowManager.Add(new CGUIDialogKaiToast);
1281 g_windowManager.Add(new CGUIDialogNumeric);
1282 g_windowManager.Add(new CGUIDialogGamepad);
1283 g_windowManager.Add(new CGUIDialogButtonMenu);
1284 g_windowManager.Add(new CGUIDialogMuteBug);
1285 g_windowManager.Add(new CGUIDialogPlayerControls);
1287 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1288 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1290 g_windowManager.Add(new CGUIDialogSlider);
1291 g_windowManager.Add(new CGUIDialogMusicOSD);
1292 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1293 g_windowManager.Add(new CGUIDialogVideoSettings);
1294 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1295 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1296 // Don't add the filebrowser dialog - it's created and added when it's needed
1297 g_windowManager.Add(new CGUIDialogNetworkSetup);
1298 g_windowManager.Add(new CGUIDialogMediaSource);
1299 g_windowManager.Add(new CGUIDialogProfileSettings);
1300 g_windowManager.Add(new CGUIDialogFavourites);
1301 g_windowManager.Add(new CGUIDialogSongInfo);
1302 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1303 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1304 g_windowManager.Add(new CGUIDialogBusy);
1305 g_windowManager.Add(new CGUIDialogPictureInfo);
1306 g_windowManager.Add(new CGUIDialogAddonInfo);
1307 g_windowManager.Add(new CGUIDialogAddonSettings);
1308 #ifdef HAS_LINUX_NETWORK
1309 g_windowManager.Add(new CGUIDialogAccessPoints);
1312 g_windowManager.Add(new CGUIDialogLockSettings);
1314 g_windowManager.Add(new CGUIDialogContentSettings);
1316 g_windowManager.Add(new CGUIDialogPlayEject);
1318 g_windowManager.Add(new CGUIDialogPeripheralManager);
1319 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1321 g_windowManager.Add(new CGUIDialogMediaFilter);
1323 g_windowManager.Add(new CGUIWindowMusicPlayList);
1324 g_windowManager.Add(new CGUIWindowMusicSongs);
1325 g_windowManager.Add(new CGUIWindowMusicNav);
1326 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1328 /* Load PVR related Windows and Dialogs */
1329 g_windowManager.Add(new CGUIDialogTeletext);
1330 g_windowManager.Add(new CGUIWindowPVR);
1331 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1332 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1333 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1334 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1335 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1336 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1337 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1338 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1339 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1340 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1342 g_windowManager.Add(new CGUIDialogSelect);
1343 g_windowManager.Add(new CGUIDialogMusicInfo);
1344 g_windowManager.Add(new CGUIDialogOK);
1345 g_windowManager.Add(new CGUIDialogVideoInfo);
1346 g_windowManager.Add(new CGUIDialogTextViewer);
1347 g_windowManager.Add(new CGUIWindowFullScreen);
1348 g_windowManager.Add(new CGUIWindowVisualisation);
1349 g_windowManager.Add(new CGUIWindowSlideShow);
1350 g_windowManager.Add(new CGUIDialogFileStacking);
1352 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1355 g_windowManager.Add(new CGUIDialogVideoOSD);
1356 g_windowManager.Add(new CGUIDialogMusicOverlay);
1357 g_windowManager.Add(new CGUIDialogVideoOverlay);
1358 g_windowManager.Add(new CGUIWindowScreensaver);
1359 g_windowManager.Add(new CGUIWindowWeather);
1360 g_windowManager.Add(new CGUIWindowStartup);
1362 /* window id's 3000 - 3100 are reserved for python */
1364 // Make sure we have at least the default skin
1365 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1366 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1368 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1372 if (g_advancedSettings.m_splashImage)
1373 SAFE_DELETE(m_splash);
1375 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1376 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1377 !CProfilesManager::Get().GetMasterProfile().getLockCode().IsEmpty())
1379 g_passwordManager.CheckStartUpLock();
1382 // check if we should use the login screen
1383 if (CProfilesManager::Get().UsingLoginScreen())
1384 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1388 CJSONRPC::Initialize();
1390 ADDON::CAddonMgr::Get().StartServices(false);
1391 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1393 g_windowManager.ActivateWindow(WINDOW_HOME);
1394 StartPVRManager(true);
1398 StartPVRManager(false);
1399 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1404 else //No GUI Created
1407 CJSONRPC::Initialize();
1409 ADDON::CAddonMgr::Get().StartServices(false);
1412 g_sysinfo.Refresh();
1414 CLog::Log(LOGINFO, "removing tempfiles");
1415 CUtil::RemoveTempFiles();
1417 if (!CProfilesManager::Get().UsingLoginScreen())
1421 g_pythonParser.m_bLogin = true;
1425 m_slowTimer.StartZero();
1427 #if defined(HAVE_LIBCRYSTALHD)
1428 CCrystalHD::GetInstance();
1431 CAddonMgr::Get().StartServices(true);
1433 CLog::Log(LOGNOTICE, "initialize done");
1435 m_bInitializing = false;
1437 // reset our screensaver (starts timers etc.)
1440 #ifdef HAS_SDL_JOYSTICK
1441 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1442 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1448 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1454 // the callback will take care of starting/stopping webserver
1455 ret = CSettings::Get().SetBool("services.webserver", bStart);
1458 case ES_AIRPLAYSERVER:
1459 // the callback will take care of starting/stopping airplay
1460 ret = CSettings::Get().SetBool("services.airplay", bStart);
1463 case ES_JSONRPCSERVER:
1464 // the callback will take care of starting/stopping jsonrpc server
1465 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1469 // the callback will take care of starting/stopping upnp server
1470 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1473 case ES_UPNPRENDERER:
1474 // the callback will take care of starting/stopping upnp renderer
1475 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1478 case ES_EVENTSERVER:
1479 // the callback will take care of starting/stopping event server
1480 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1484 // the callback will take care of starting/stopping zeroconf
1485 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1492 CSettings::Get().Save();
1497 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1499 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1500 g_PVRManager.Start(true, bOpenPVRWindow);
1503 void CApplication::StopPVRManager()
1505 CLog::Log(LOGINFO, "stopping PVRManager");
1506 if (g_PVRManager.IsPlaying())
1508 g_PVRManager.Stop();
1509 g_EpgContainer.Stop();
1512 void CApplication::StartServices()
1514 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1515 // Start Thread for DVD Mediatype detection
1516 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1517 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1520 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1521 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1522 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1523 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1524 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1525 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1528 void CApplication::StopServices()
1530 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1532 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1533 CLog::Log(LOGNOTICE, "stop dvd detect media");
1534 m_DetectDVDType.StopThread();
1537 g_peripherals.Clear();
1540 void CApplication::OnSettingChanged(const CSetting *setting)
1542 if (setting == NULL)
1545 const std::string &settingId = setting->GetId();
1546 if (settingId == "lookandfeel.skin" ||
1547 settingId == "lookandfeel.font" ||
1548 settingId == "lookandfeel.skincolors")
1550 else if (settingId == "lookandfeel.skintheme")
1552 // also set the default color theme
1553 string colorTheme = URIUtils::ReplaceExtension(((CSettingString*)setting)->GetValue(), ".xml");
1554 if (StringUtils::EqualsNoCase(colorTheme, "Textures.xml"))
1555 colorTheme = "defaults.xml";
1557 // check if we have to change the skin color
1558 // if yes, it will trigger a call to ReloadSkin() in
1559 // it's OnSettingChanged() callback
1560 // if no we have to call ReloadSkin() ourselves
1561 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1562 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1566 else if (settingId == "lookandfeel.skinzoom")
1567 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1568 else if (StringUtils::StartsWith(settingId, "audiooutput."))
1570 if (settingId == "audiooutput.guisoundmode")
1571 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1573 CAEFactory::OnSettingsChange(settingId);
1575 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1576 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1577 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1578 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1579 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1580 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1581 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1582 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1585 void CApplication::OnSettingAction(const CSetting *setting)
1587 if (setting == NULL)
1590 const std::string &settingId = setting->GetId();
1591 if (settingId == "lookandfeel.skinsettings")
1592 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1593 else if (settingId == "screensaver.preview")
1594 ActivateScreenSaver(true);
1595 else if (settingId == "screensaver.settings")
1598 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1599 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1601 else if (settingId == "videoscreen.guicalibration")
1602 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1603 else if (settingId == "videoscreen.testpattern")
1604 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1607 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1609 if (setting == NULL)
1612 const std::string &settingId = setting->GetId();
1613 if (settingId == "audiooutput.channels")
1615 // check if this is an update from Eden
1616 if (oldSettingId != NULL && oldSettingNode != NULL &&
1617 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1620 CSettingInt* channels = (CSettingInt*)setting;
1621 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1622 ret = channels->SetValue(channels->GetValue() + 1);
1624 // let's just reset the audiodevice settings as well
1625 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1626 CAEFactory::VerifyOutputDevice(audiodevice, false);
1627 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1632 else if (settingId == "screensaver.mode")
1634 CSettingString *screensaverMode = (CSettingString*)setting;
1635 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1636 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1637 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1639 else if (settingId == "scrapers.musicvideosdefault")
1641 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1642 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1644 musicvideoScraper->Reset();
1652 bool CApplication::OnSettingsSaving() const
1654 // don't save settings when we're busy stopping the application
1655 // a lot of screens try to save settings on deinit and deinit is
1656 // called for every screen when the application is stopping
1663 void CApplication::ReloadSkin()
1665 m_skinReloading = false;
1666 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1667 g_windowManager.SendMessage(msg);
1669 // Reload the skin, restoring the previously focused control. We need this as
1670 // the window unload will reset all control states.
1672 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1674 iCtrlID = pWindow->GetFocusedControlID();
1676 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1680 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1681 if (pWindow && pWindow->HasSaveLastControl())
1683 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1684 pWindow->OnMessage(msg3);
1689 bool CApplication::Load(const TiXmlNode *settings)
1691 if (settings == NULL)
1694 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1695 if (audioElement != NULL)
1697 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1698 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1699 m_volumeLevel = VOLUME_MAXIMUM;
1705 bool CApplication::Save(TiXmlNode *settings) const
1707 if (settings == NULL)
1710 TiXmlElement volumeNode("audio");
1711 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1712 if (audioNode == NULL)
1715 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1716 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1721 bool CApplication::LoadSkin(const CStdString& skinID)
1723 if (m_skinReloading)
1727 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1729 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1735 void CApplication::LoadSkin(const SkinPtr& skin)
1737 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1740 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1741 CSettings::Get().SetString("lookandfeel.skin", defaultSkin);
1746 if (!skin->HasSkinFile("Home.xml"))
1748 // failed to find home.xml
1749 // fallback to default skin
1750 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1752 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1753 CSettings::Get().SetString("lookandfeel.skin", defaultSkin);
1754 LoadSkin(defaultSkin);
1755 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1760 bool bPreviousPlayingState=false;
1761 bool bPreviousRenderingState=false;
1762 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1764 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1765 if (bPreviousPlayingState)
1766 g_application.m_pPlayer->Pause();
1767 #ifdef HAS_VIDEO_PLAYBACK
1768 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1770 g_windowManager.ActivateWindow(WINDOW_HOME);
1771 bPreviousRenderingState = true;
1775 // close the music and video overlays (they're re-opened automatically later)
1776 CSingleLock lock(g_graphicsContext);
1778 // save the current window details
1779 int currentWindow = g_windowManager.GetActiveWindow();
1780 vector<int> currentModelessWindows;
1781 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1785 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1787 g_SkinInfo->Start();
1789 CLog::Log(LOGINFO, " load fonts for skin...");
1790 g_graphicsContext.SetMediaDir(skin->Path());
1791 g_directoryCache.ClearSubPaths(skin->Path());
1792 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1794 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1795 CStdString strFontSet;
1796 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1798 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1799 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1800 CSettings::Get().Save();
1803 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1805 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1807 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1809 // load in the skin strings
1810 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1811 URIUtils::AddSlashAtEnd(langPath);
1813 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1815 g_SkinInfo->LoadIncludes();
1818 start = CurrentHostCounter();
1820 CLog::Log(LOGINFO, " load new skin...");
1822 // Load the user windows
1826 end = CurrentHostCounter();
1827 freq = CurrentHostFrequency();
1828 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1830 CLog::Log(LOGINFO, " initialize new skin...");
1831 g_windowManager.AddMsgTarget(this);
1832 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1833 g_windowManager.AddMsgTarget(&g_infoManager);
1834 g_windowManager.AddMsgTarget(&g_fontManager);
1835 g_windowManager.SetCallback(*this);
1836 g_windowManager.Initialize();
1837 CTextureCache::Get().Initialize();
1838 g_audioManager.Enable(true);
1839 g_audioManager.Load();
1841 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1842 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1844 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1845 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1846 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1847 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1848 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1851 CLog::Log(LOGINFO, " skin loaded...");
1853 // leave the graphics lock
1857 if (currentWindow != WINDOW_INVALID)
1859 g_windowManager.ActivateWindow(currentWindow);
1860 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1862 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1863 if (dialog) dialog->Show();
1867 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1869 if (bPreviousPlayingState)
1870 g_application.m_pPlayer->Pause();
1871 if (bPreviousRenderingState)
1872 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1876 void CApplication::UnloadSkin(bool forReload /* = false */)
1878 m_skinReloading = forReload;
1880 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1882 g_audioManager.Enable(false);
1884 g_windowManager.DeInitialize();
1885 CTextureCache::Get().Deinitialize();
1887 // remove the skin-dependent window
1888 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1890 g_TextureManager.Cleanup();
1891 g_largeTextureManager.CleanupUnusedImages(true);
1893 g_fontManager.Clear();
1895 g_colorManager.Clear();
1897 g_charsetConverter.reset();
1899 g_infoManager.Clear();
1901 // The g_SkinInfo boost shared_ptr ought to be reset here
1902 // but there are too many places it's used without checking for NULL
1903 // and as a result a race condition on exit can cause a crash.
1906 bool CApplication::LoadUserWindows()
1908 // Start from wherever home.xml is
1909 std::vector<CStdString> vecSkinPath;
1910 g_SkinInfo->GetSkinPaths(vecSkinPath);
1911 for (unsigned int i = 0;i < vecSkinPath.size();++i)
1913 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1914 CFileItemList items;
1915 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
1917 for (int i = 0; i < items.Size(); ++i)
1919 if (items[i]->m_bIsFolder)
1921 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1922 if (skinFile.Left(6).CompareNoCase("custom") == 0)
1924 CXBMCTinyXML xmlDoc;
1925 if (!xmlDoc.LoadFile(items[i]->GetPath()))
1927 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1931 // Root element should be <window>
1932 TiXmlElement* pRootElement = xmlDoc.RootElement();
1933 CStdString strValue = pRootElement->Value();
1934 if (!strValue.Equals("window"))
1936 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
1940 // Read the <type> element to get the window type to create
1941 // If no type is specified, create a CGUIWindow as default
1942 CGUIWindow* pWindow = NULL;
1944 if (pRootElement->Attribute("type"))
1945 strType = pRootElement->Attribute("type");
1948 const TiXmlNode *pType = pRootElement->FirstChild("type");
1949 if (pType && pType->FirstChild())
1950 strType = pType->FirstChild()->Value();
1952 int id = WINDOW_INVALID;
1953 if (!pRootElement->Attribute("id", &id))
1955 const TiXmlNode *pType = pRootElement->FirstChild("id");
1956 if (pType && pType->FirstChild())
1957 id = atol(pType->FirstChild()->Value());
1959 CStdString visibleCondition;
1960 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1962 if (strType.Equals("dialog"))
1963 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1964 else if (strType.Equals("submenu"))
1965 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
1966 else if (strType.Equals("buttonmenu"))
1967 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
1969 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
1971 // Check to make sure the pointer isn't still null
1972 if (pWindow == NULL)
1974 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
1977 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
1982 pWindow->SetVisibleCondition(visibleCondition);
1983 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
1984 g_windowManager.AddCustomWindow(pWindow);
1992 bool CApplication::RenderNoPresent()
1996 // DXMERGE: This may have been important?
1997 // g_graphicsContext.AcquireCurrentContext();
1999 g_graphicsContext.Lock();
2001 // dont show GUI when playing full screen video
2002 if (g_graphicsContext.IsFullScreenVideo())
2004 g_renderManager.Render(true, 0, 255);
2006 // close window overlays
2007 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2008 if (overlay) overlay->Close(true);
2009 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2010 if (overlay) overlay->Close(true);
2014 bool hasRendered = g_windowManager.Render();
2016 g_graphicsContext.Unlock();
2021 float CApplication::GetDimScreenSaverLevel() const
2023 if (!m_bScreenSave || !m_screenSaver ||
2024 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2025 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2026 !m_screenSaver->ID().empty()))
2029 if (!m_screenSaver->GetSetting("level").IsEmpty())
2030 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2034 void CApplication::Render()
2036 // do not render if we are stopped or in background
2037 if (m_bStop || m_bInBackground)
2042 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2044 bool hasRendered = false;
2045 bool limitFrames = false;
2046 unsigned int singleFrameTime = 10; // default limit 100 fps
2050 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2051 // Whether externalplayer is playing and we're unfocused
2052 bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
2054 m_bPresentFrame = false;
2055 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused() && g_renderManager.RendererHandlesPresent())
2057 m_bPresentFrame = g_renderManager.FrameWait(100);
2062 // engage the frame limiter as needed
2063 limitFrames = lowfps || extPlayerActive;
2064 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2065 // perhaps allowing it to be set differently than the UI option??
2066 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2067 limitFrames = true; // not using vsync.
2068 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2069 limitFrames = true; // using vsync, but it isn't working.
2073 if (extPlayerActive)
2075 ResetScreenSaver(); // Prevent screensaver dimming the screen
2076 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2079 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2085 CSingleLock lock(g_graphicsContext);
2086 g_infoManager.UpdateFPS();
2088 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2089 g_Windowing.SetVSync(true);
2090 else if (vsync_mode == VSYNC_ALWAYS)
2091 g_Windowing.SetVSync(true);
2092 else if (vsync_mode != VSYNC_DRIVER)
2093 g_Windowing.SetVSync(false);
2095 if (m_bPresentFrame && IsPlaying() && !IsPaused())
2098 if(!g_Windowing.BeginRender())
2101 g_renderManager.FrameMove();
2103 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2104 if (RenderNoPresent())
2107 g_renderManager.FrameFinish();
2109 g_Windowing.EndRender();
2111 // execute post rendering actions (finalize window closing)
2112 g_windowManager.AfterRender();
2114 // reset our info cache - we do this at the end of Render so that it is
2115 // fresh for the next process(), or after a windowclose animation (where process()
2117 g_infoManager.ResetCache();
2120 unsigned int now = XbmcThreads::SystemClockMillis();
2122 m_lastRenderTime = now;
2124 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2125 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2127 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2128 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2132 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2133 if (limitFrames || !flip)
2136 singleFrameTime = 40; //if not flipping, loop at 25 fps
2138 unsigned int frameTime = now - m_lastFrameTime;
2139 if (frameTime < singleFrameTime)
2140 Sleep(singleFrameTime - frameTime);
2142 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2145 g_graphicsContext.Flip(dirtyRegions);
2146 CTimeUtils::UpdateFrameTime(flip);
2148 g_renderManager.UpdateResolution();
2149 g_renderManager.ManageCaptures();
2152 void CApplication::SetStandAlone(bool value)
2154 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2157 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2158 // The window manager will return true if the event is processed, false otherwise.
2159 // If not already processed, this routine handles global keypresses. It returns
2160 // true if the key has been processed, false otherwise.
2162 bool CApplication::OnKey(const CKey& key)
2165 // Turn the mouse off, as we've just got a keypress from controller or remote
2166 g_Mouse.SetActive(false);
2168 // get the current active window
2169 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2171 // this will be checked for certain keycodes that need
2172 // special handling if the screensaver is active
2173 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2175 // a key has been pressed.
2177 m_idleTimer.StartZero();
2178 bool processKey = AlwaysProcess(action);
2182 // allow some keys to be processed while the screensaver is active
2183 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2185 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2189 // change this if we have a dialog up
2190 if (g_windowManager.HasModalDialog())
2192 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2194 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2195 { // fullscreen info dialog - special case
2196 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2198 if (!key.IsAnalogButton())
2199 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2201 if (OnAction(action))
2204 // fallthrough to the main window
2205 iWin = WINDOW_FULLSCREEN_VIDEO;
2207 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2209 // current active window is full screen video.
2210 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2212 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2213 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2215 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2217 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2218 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2220 // if no PVR specific action/mapping is found, fall back to default
2221 if (action.GetID() == 0)
2222 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2226 // in any other case use the fullscreen window section of keymap.xml to map key->action
2227 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2232 // current active window isnt the fullscreen window
2233 // just use corresponding section from keymap.xml
2234 // to map key->action
2236 // first determine if we should use keyboard input directly
2237 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2238 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2241 CGUIControl *control = window->GetFocusedControl();
2244 // If this is an edit control set usekeyboard to true. This causes the
2245 // keypress to be processed directly not through the key mappings.
2246 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2249 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2250 // This causes the keypress to be used for list navigation.
2251 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2257 action = CAction(0); // reset our action
2258 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2260 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2261 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2262 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2263 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2264 action.GetID() == ACTION_MOVE_RIGHT ||
2265 action.GetID() == ACTION_MOVE_UP ||
2266 action.GetID() == ACTION_MOVE_DOWN ||
2267 action.GetID() == ACTION_SELECT_ITEM ||
2268 action.GetID() == ACTION_ENTER ||
2269 action.GetID() == ACTION_PREVIOUS_MENU ||
2270 action.GetID() == ACTION_NAV_BACK))
2272 // the action isn't plain navigation - check for a keyboard-specific keymap
2273 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2274 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2275 action.GetID() == ACTION_BACKSPACE ||
2276 action.GetID() == ACTION_SHIFT ||
2277 action.GetID() == ACTION_SYMBOLS ||
2278 action.GetID() == ACTION_CURSOR_LEFT ||
2279 action.GetID() == ACTION_CURSOR_RIGHT)
2280 action = CAction(0); // don't bother with this action
2283 if (!action.GetID())
2285 // keyboard entry - pass the keys through directly
2286 if (key.GetFromService())
2287 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2289 { // see if we've got an ascii key
2290 if (key.GetUnicode())
2291 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2293 action = CAction(key.GetVKey() | KEY_VKEY);
2297 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2299 if (OnAction(action))
2301 // failed to handle the keyboard action, drop down through to standard action
2303 if (key.GetFromService())
2305 if (key.GetButtonCode() != KEY_INVALID)
2306 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2309 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2311 if (!key.IsAnalogButton())
2312 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2314 return ExecuteInputAction(action);
2317 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2318 // This needs to return true if it processed the appcommand or false if it didn't
2319 bool CApplication::OnAppCommand(const CAction &action)
2321 // Reset the screen saver
2324 // If we were currently in the screen saver wake up and don't process the appcommand
2325 if (WakeUpScreenSaverAndDPMS())
2328 // The action ID is the APPCOMMAND code. We need to retrieve the action
2329 // associated with this appcommand from the mapping table.
2330 uint32_t appcmd = action.GetID();
2331 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2332 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2333 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2335 // If we couldn't find an action return false to indicate we have not
2336 // handled this appcommand
2337 if (!appcmdaction.GetID())
2339 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2343 // Process the appcommand
2344 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2345 OnAction(appcmdaction);
2347 // Always return true regardless of whether the action succeeded or not.
2348 // This stops Windows handling the appcommand itself.
2352 bool CApplication::OnAction(const CAction &action)
2354 // special case for switching between GUI & fullscreen mode.
2355 if (action.GetID() == ACTION_SHOW_GUI)
2356 { // Switch to fullscreen mode if we can
2357 if (SwitchToFullScreen())
2359 m_navigationTimer.StartZero();
2364 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2366 g_graphicsContext.ToggleFullScreenRoot();
2370 if (action.IsMouse())
2371 g_Mouse.SetActive(true);
2374 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2376 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2378 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2380 CGUIDialogVideoBookmarks::OnAddBookmark();
2383 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2384 // playing or ACTION_PLAYER_PLAY if we are not playing.
2385 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2388 return OnAction(CAction(ACTION_PAUSE));
2390 return OnAction(CAction(ACTION_PLAYER_PLAY));
2393 //if the action would start or stop inertial scrolling
2394 //by gesture - bypass the normal OnAction handler of current window
2395 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2398 // just pass the action to the current window and let it handle it
2399 if (g_windowManager.OnAction(action))
2401 m_navigationTimer.StartZero();
2406 // handle extra global presses
2408 // screenshot : take a screenshot :)
2409 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2411 CScreenShot::TakeScreenshot();
2414 // built in functions : execute the built-in
2415 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2417 CBuiltins::Execute(action.GetName());
2418 m_navigationTimer.StartZero();
2423 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2425 CButtonTranslator::GetInstance().Clear();
2426 CButtonTranslator::GetInstance().Load();
2429 // show info : Shows the current video or song information
2430 if (action.GetID() == ACTION_SHOW_INFO)
2432 g_infoManager.ToggleShowInfo();
2436 // codec info : Shows the current song, video or picture codec information
2437 if (action.GetID() == ACTION_SHOW_CODEC)
2439 g_infoManager.ToggleShowCodec();
2443 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2445 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2448 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2449 char rating = tag->GetRating();
2450 bool needsUpdate(false);
2451 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2453 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2456 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2458 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2464 if (db.Open()) // OpenForWrite() ?
2466 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2469 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2470 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2471 g_windowManager.SendMessage(msg);
2477 // Now check with the playlist player if action can be handled.
2478 // 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.
2479 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3) )
2481 if (g_playlistPlayer.OnAction(action))
2485 // Now check with the player if action can be handled.
2486 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2487 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))
2489 if (m_pPlayer != NULL && m_pPlayer->OnAction(action))
2493 // stop : stops playing current audio song
2494 if (action.GetID() == ACTION_STOP)
2500 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2501 // If so, we just jump to the start of the track.
2502 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer && m_pPlayer->CanSeek())
2509 // forward action to g_PVRManager and break if it was able to handle it
2510 if (g_PVRManager.OnAction(action))
2515 // forward channel switches to the player - he knows what to do
2516 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2518 m_pPlayer->OnAction(action);
2522 // pause : pauses current audio song
2523 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2527 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2529 if (!m_pPlayer->IsPaused())
2530 { // unpaused - set the playspeed back to normal
2533 g_audioManager.Enable(m_pPlayer->IsPaused());
2536 if (!m_pPlayer->IsPaused())
2538 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2539 // if we are playing at normal speed, then allow play to pause
2540 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2542 if (m_iPlaySpeed != 1)
2552 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2554 int iPlaySpeed = m_iPlaySpeed;
2555 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2557 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2559 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2564 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2566 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2569 SetPlaySpeed(iPlaySpeed);
2572 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2574 // calculate the speed based on the amount the button is held down
2575 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2576 // returns 0 -> MAX_FFWD_SPEED
2577 int iSpeed = 1 << iPower;
2578 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2580 g_application.SetPlaySpeed(iSpeed);
2582 CLog::Log(LOGDEBUG,"Resetting playspeed");
2586 // allow play to unpause
2589 if (action.GetID() == ACTION_PLAYER_PLAY)
2591 // unpause, and set the playspeed back to normal
2593 g_audioManager.Enable(m_pPlayer->IsPaused());
2595 g_application.SetPlaySpeed(1);
2600 if (m_playerController->OnAction(action))
2605 if (action.GetID() == ACTION_SWITCH_PLAYER)
2609 VECPLAYERCORES cores;
2610 CFileItem item(*m_itemCurrentFile.get());
2611 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2612 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2613 if(core != EPC_NONE)
2615 g_application.m_eForcedNextPlayer = core;
2616 item.m_lStartOffset = (int)(GetTime() * 75);
2617 PlayFile(item, true);
2622 VECPLAYERCORES cores;
2623 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2624 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2625 if(core != EPC_NONE)
2628 g_application.m_eForcedNextPlayer = core;
2629 PlayFile(item, false);
2634 if (g_peripherals.OnAction(action))
2637 if (action.GetID() == ACTION_MUTE)
2643 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2645 // we are only allowed to SetInt to a value supported in GUISettings, so we keep trying until it sticks
2646 int mode = CSettings::Get().GetInt("audiooutput.mode");
2647 for (int i = 0; i < 3; i++)
2651 CSettings::Get().SetInt("audiooutput.mode", mode);
2652 if (CSettings::Get().GetInt("audiooutput.mode") == mode)
2656 g_application.Restart();
2657 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2659 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2660 g_windowManager.SendMessage(msg);
2665 // Check for global volume control
2666 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2668 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2672 float volume = m_volumeLevel;
2673 // Android has steps based on the max available volume level
2674 #if defined(TARGET_ANDROID)
2675 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2677 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2679 if (action.GetRepeat())
2680 step *= action.GetRepeat() * 50; // 50 fps
2682 if (action.GetID() == ACTION_VOLUME_UP)
2683 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2685 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2686 SetVolume(volume, false);
2688 // show visual feedback of volume change...
2689 ShowVolumeBar(&action);
2692 // Check for global seek control
2693 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2695 if (!m_pPlayer->CanSeek()) return false;
2696 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2699 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2701 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2702 CGUIControlProfiler::Instance().Start();
2705 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2707 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2708 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2709 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2710 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2711 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2717 void CApplication::FrameMove(bool processEvents, bool processGUI)
2723 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2724 float frameTime = m_frameTime.GetElapsedSeconds();
2725 m_frameTime.StartZero();
2726 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2727 if( frameTime > 0.5 ) frameTime = 0.5;
2729 if (processGUI && m_renderGUI)
2731 g_graphicsContext.Lock();
2732 // check if there are notifications to display
2733 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2734 if (toast && toast->DoWork())
2736 if (!toast->IsDialogRunning())
2741 g_graphicsContext.Unlock();
2743 CWinEvents::MessagePump();
2745 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2746 // Read the input from a remote
2747 g_RemoteControl.Update();
2750 // process input actions
2751 ProcessRemote(frameTime);
2752 ProcessGamepad(frameTime);
2753 ProcessEventServer(frameTime);
2754 ProcessPeripherals(frameTime);
2755 if (processGUI && m_renderGUI)
2757 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2758 m_seekHandler->Process();
2761 if (processGUI && m_renderGUI)
2764 g_windowManager.Process(CTimeUtils::GetFrameTime());
2765 g_windowManager.FrameMove();
2769 bool CApplication::ProcessGamepad(float frameTime)
2771 #ifdef HAS_SDL_JOYSTICK
2775 int iWin = GetActiveWindowID();
2777 g_Joystick.Update();
2778 if (g_Joystick.GetButton(bid))
2781 m_idleTimer.StartZero();
2784 if (WakeUpScreenSaverAndDPMS())
2786 g_Joystick.Reset(true);
2791 CStdString actionName;
2793 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2795 CAction action(actionID, 1.0f, 0.0f, actionName);
2797 g_Mouse.SetActive(false);
2798 return ExecuteInputAction(action);
2805 if (g_Joystick.GetAxis(bid))
2807 if (g_Joystick.GetAmount() < 0)
2813 CStdString actionName;
2815 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2818 if (WakeUpScreenSaverAndDPMS())
2823 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2825 g_Mouse.SetActive(false);
2826 return ExecuteInputAction(action);
2830 g_Joystick.ResetAxis(abs(bid));
2834 if (g_Joystick.GetHat(bid, position))
2837 m_idleTimer.StartZero();
2840 if (WakeUpScreenSaverAndDPMS())
2847 CStdString actionName;
2850 bid = position<<16|bid;
2852 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2854 CAction action(actionID, 1.0f, 0.0f, actionName);
2856 g_Mouse.SetActive(false);
2857 return ExecuteInputAction(action);
2864 bool CApplication::ProcessRemote(float frameTime)
2866 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2867 if (g_RemoteControl.GetButton())
2869 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2870 g_RemoteControl.Reset();
2877 bool CApplication::ProcessPeripherals(float frameTime)
2880 if (g_peripherals.GetNextKeypress(frameTime, key))
2885 bool CApplication::ProcessMouse()
2889 if (!g_Mouse.IsActive() || !m_AppFocused)
2892 // Get the mouse command ID
2893 uint32_t mousecommand = g_Mouse.GetAction();
2894 if (mousecommand == ACTION_NOOP)
2897 // Reset the screensaver and idle timers
2898 m_idleTimer.StartZero();
2900 if (WakeUpScreenSaverAndDPMS())
2903 // Retrieve the corresponding action
2904 int iWin = GetActiveWindowID();
2905 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2906 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2908 // Deactivate mouse if non-mouse action
2909 if (!mouseaction.IsMouse())
2910 g_Mouse.SetActive(false);
2912 // Consume ACTION_NOOP.
2913 // Some views or dialogs gets closed after any ACTION and
2914 // a sensitive mouse might cause problems.
2915 if (mouseaction.GetID() == ACTION_NOOP)
2918 // If we couldn't find an action return false to indicate we have not
2919 // handled this mouse action
2920 if (!mouseaction.GetID())
2922 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
2926 // Log mouse actions except for move and noop
2927 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
2928 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
2930 // The action might not be a mouse action. For example wheel moves might
2931 // be mapped to volume up/down in mouse.xml. In this case we do not want
2932 // the mouse position saved in the action.
2933 if (!mouseaction.IsMouse())
2934 return OnAction(mouseaction);
2936 // This is a mouse action so we need to record the mouse position
2937 return OnAction(CAction(mouseaction.GetID(),
2938 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
2939 (float)g_Mouse.GetX(),
2940 (float)g_Mouse.GetY(),
2941 (float)g_Mouse.GetDX(),
2942 (float)g_Mouse.GetDY(),
2943 mouseaction.GetName()));
2946 bool CApplication::ProcessEventServer(float frameTime)
2948 #ifdef HAS_EVENT_SERVER
2949 CEventServer* es = CEventServer::GetInstance();
2950 if (!es || !es->Running() || es->GetNumberOfClients()==0)
2953 // process any queued up actions
2954 if (es->ExecuteNextAction())
2956 // reset idle timers
2957 m_idleTimer.StartZero();
2959 WakeUpScreenSaverAndDPMS();
2962 // now handle any buttons or axis
2963 std::string joystickName;
2964 bool isAxis = false;
2965 float fAmount = 0.0;
2967 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
2968 // when the action exits XBMC
2969 es = CEventServer::GetInstance();
2970 if (!es || !es->Running() || es->GetNumberOfClients()==0)
2972 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
2976 if (joystickName.length() > 0)
2980 if (fabs(fAmount) >= 0.08)
2981 m_lastAxisMap[joystickName][wKeyID] = fAmount;
2983 m_lastAxisMap[joystickName].erase(wKeyID);
2986 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
2991 if (wKeyID & ES_FLAG_UNICODE)
2993 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
2997 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
2998 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
2999 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3000 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3001 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3002 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3003 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3004 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3005 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3006 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3007 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3008 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3009 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3010 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3011 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3012 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3013 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3014 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3015 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3016 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3019 key.SetFromService(true);
3024 if (m_lastAxisMap.size() > 0)
3026 // Process all the stored axis.
3027 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3029 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3030 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3036 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3037 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3043 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount, unsigned int holdTime /*=0*/)
3045 #if defined(HAS_EVENT_SERVER)
3046 m_idleTimer.StartZero();
3048 // Make sure to reset screen saver, mouse.
3050 if (WakeUpScreenSaverAndDPMS())
3053 #ifdef HAS_SDL_JOYSTICK
3056 g_Mouse.SetActive(false);
3058 int iWin = GetActiveWindowID();
3060 CStdString actionName;
3061 bool fullRange = false;
3063 // Translate using regular joystick translator.
3064 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3065 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3067 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3073 bool CApplication::ExecuteInputAction(const CAction &action)
3075 bool bResult = false;
3077 // play sound before the action unless the button is held,
3078 // where we execute after the action as held actions aren't fired every time.
3079 if(action.GetHoldTime())
3081 bResult = OnAction(action);
3083 g_audioManager.PlayActionSound(action);
3087 g_audioManager.PlayActionSound(action);
3088 bResult = OnAction(action);
3093 int CApplication::GetActiveWindowID(void)
3095 // Get the currently active window
3096 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3098 // If there is a dialog active get the dialog id instead
3099 if (g_windowManager.HasModalDialog())
3100 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3102 // If the window is FullScreenVideo check for special cases
3103 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3105 // check if we're in a DVD menu
3106 if(g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
3107 iWin = WINDOW_VIDEO_MENU;
3108 // check for LiveTV and switch to it's virtual window
3109 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3110 iWin = WINDOW_FULLSCREEN_LIVETV;
3113 // Return the window id
3117 bool CApplication::Cleanup()
3121 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3122 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3123 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3124 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3125 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3126 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3127 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3128 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3129 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3130 g_windowManager.Delete(WINDOW_FILES);
3131 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3132 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3133 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3134 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3135 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3136 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3137 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3138 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3139 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3140 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3141 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3142 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3143 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3144 g_windowManager.Delete(WINDOW_DIALOG_OK);
3145 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3146 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3147 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3148 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3149 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3150 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3151 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3152 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3153 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3154 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3155 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3156 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3157 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3158 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3159 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3160 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3161 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3162 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3163 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3164 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3165 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3166 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3168 /* Delete PVR related windows and dialogs */
3169 g_windowManager.Delete(WINDOW_PVR);
3170 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3171 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3172 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3173 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3174 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3175 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3176 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3177 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3178 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3179 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3180 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3181 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3182 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3184 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3185 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3186 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3187 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3188 g_windowManager.Delete(WINDOW_VISUALISATION);
3189 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3190 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3191 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3192 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3193 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3194 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3195 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3196 g_windowManager.Delete(WINDOW_SCREENSAVER);
3197 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3198 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3199 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3200 g_windowManager.Delete(WINDOW_SLIDESHOW);
3201 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3202 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3204 g_windowManager.Delete(WINDOW_HOME);
3205 g_windowManager.Delete(WINDOW_PROGRAMS);
3206 g_windowManager.Delete(WINDOW_PICTURES);
3207 g_windowManager.Delete(WINDOW_WEATHER);
3209 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3210 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3211 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3212 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3213 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3214 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3215 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3216 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3217 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3218 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3220 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3221 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3223 CAddonMgr::Get().DeInit();
3225 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3226 CLog::Log(LOGNOTICE, "closing down remote control service");
3227 g_RemoteControl.Disconnect();
3230 CLog::Log(LOGNOTICE, "unload sections");
3232 #ifdef HAS_PERFORMANCE_SAMPLE
3233 CLog::Log(LOGNOTICE, "performance statistics");
3234 m_perfStats.DumpStats();
3237 // Shutdown as much as possible of the
3238 // application, to reduce the leaks dumped
3239 // to the vc output window before calling
3240 // _CrtDumpMemoryLeaks(). Most of the leaks
3241 // shown are no real leaks, as parts of the app
3242 // are still allocated.
3244 g_localizeStrings.Clear();
3245 g_LangCodeExpander.Clear();
3246 g_charsetConverter.clear();
3247 g_directoryCache.Clear();
3248 CButtonTranslator::GetInstance().Clear();
3249 #ifdef HAS_EVENT_SERVER
3250 CEventServer::RemoveInstance();
3252 DllLoaderContainer::Clear();
3253 g_playlistPlayer.Clear();
3254 CSettings::Get().Uninitialize();
3255 g_advancedSettings.Clear();
3258 CXHandle::DumpObjectTracker();
3260 #ifdef HAS_DVD_DRIVE
3261 CLibcdio::ReleaseInstance();
3264 #if defined(TARGET_ANDROID)
3265 // enable for all platforms once it's safe
3266 g_sectionLoader.UnloadAll();
3268 #ifdef _CRTDBG_MAP_ALLOC
3269 _CrtDumpMemoryLeaks();
3270 while(1); // execution ends
3280 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3285 void CApplication::Stop(int exitCode)
3289 CVariant vExitCode(exitCode);
3290 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3292 SaveFileState(true);
3294 // cancel any jobs from the jobmanager
3295 CJobManager::GetInstance().CancelJobs();
3297 g_alarmClock.StopThread();
3299 if( m_bSystemScreenSaverEnable )
3300 g_Windowing.EnableSystemScreenSaver(true);
3302 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3303 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3305 // Update the settings information (volume, uptime etc. need saving)
3306 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3308 CLog::Log(LOGNOTICE, "Saving settings");
3309 CSettings::Get().Save();
3312 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3315 m_AppFocused = false;
3316 m_ExitCode = exitCode;
3317 CLog::Log(LOGNOTICE, "stop all");
3319 // stop scanning before we kill the network and so on
3320 if (m_musicInfoScanner->IsScanning())
3321 m_musicInfoScanner->Stop();
3323 if (m_videoInfoScanner->IsScanning())
3324 m_videoInfoScanner->Stop();
3326 CApplicationMessenger::Get().Cleanup();
3334 CLog::Log(LOGNOTICE, "stop player");
3336 m_pPlayer->CloseFile();
3340 #if HAS_FILESYTEM_DAAP
3341 CLog::Log(LOGNOTICE, "stop daap clients");
3342 g_DaapClient.Release();
3344 #ifdef HAS_FILESYSTEM_SAP
3345 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3346 g_sapsessions.StopThread();
3349 if(CZeroconfBrowser::IsInstantiated())
3351 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3352 CZeroconfBrowser::GetInstance()->Stop();
3353 CZeroconfBrowser::ReleaseInstance();
3357 CLog::Log(LOGNOTICE, "clean cached files!");
3358 #ifdef HAS_FILESYSTEM_RAR
3359 g_RarManager.ClearCache(true);
3362 #ifdef HAS_FILESYSTEM_SFTP
3363 CSFTPSessionManager::DisconnectAllSessions();
3366 CLog::Log(LOGNOTICE, "unload skin");
3369 #if defined(TARGET_DARWIN_OSX)
3370 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3371 XBMCHelper::GetInstance().Stop();
3374 #if defined(HAVE_LIBCRYSTALHD)
3375 CCrystalHD::RemoveInstance();
3378 g_mediaManager.Stop();
3380 // Stop services before unloading Python
3381 CAddonMgr::Get().StopServices(false);
3383 /* Python resource freeing must be done after skin has been unloaded, not before
3384 some windows still need it when deinitializing during skin unloading. */
3386 CLog::Log(LOGNOTICE, "stop python");
3387 g_pythonParser.FreeResources();
3389 g_Windowing.DestroyRenderSystem();
3390 g_Windowing.DestroyWindow();
3391 g_Windowing.DestroyWindowSystem();
3393 // shutdown the AudioEngine
3394 CAEFactory::Shutdown();
3395 CAEFactory::UnLoadEngine();
3397 CLog::Log(LOGNOTICE, "stopped");
3401 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3404 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3405 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3412 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3414 //If item is a plugin, expand out now and run ourselves again
3415 if (item.IsPlugin())
3417 CFileItem item_new(item);
3418 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3419 return PlayMedia(item_new, iPlaylist);
3422 if (item.IsSmartPlayList())
3424 CFileItemList items;
3425 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3428 CSmartPlaylist smartpl;
3429 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3430 smartpl.OpenAndReadName(item.GetPath());
3432 playlist.Add(items);
3433 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3436 else if (item.IsPlayList() || item.IsInternetStream())
3438 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3440 //is or could be a playlist
3441 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3442 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3447 if (dlgCache->IsCanceled())
3454 if (iPlaylist != PLAYLIST_NONE)
3457 if (item.HasProperty("playlist_starting_track"))
3458 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3459 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3463 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());
3464 if(pPlayList->size())
3465 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3470 //nothing special just play
3471 return PlayFile(item, false) == PLAYBACK_OK;
3475 // For playing a multi-file video. Particularly inefficient
3476 // on startup, as we are required to calculate the length
3477 // of each video, so we open + close each one in turn.
3478 // A faster calculation of video time would improve this
3480 // return value: same with PlayFile()
3481 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3483 if (!item.IsStack())
3484 return PLAYBACK_FAIL;
3488 // case 1: stacked ISOs
3489 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3491 CStackDirectory dir;
3492 CFileItemList movieList;
3493 dir.GetDirectory(item.GetPath(), movieList);
3495 // first assume values passed to the stack
3496 int selectedFile = item.m_lStartPartNumber;
3497 int startoffset = item.m_lStartOffset;
3499 // check if we instructed the stack to resume from default
3500 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3505 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3507 startoffset = (int)(bookmark.timeInSeconds*75);
3508 selectedFile = bookmark.partNumber;
3513 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3516 // make sure that the selected part is within the boundaries
3517 if (selectedFile <= 0)
3519 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3522 else if (selectedFile > movieList.Size())
3524 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3525 selectedFile = movieList.Size();
3528 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3529 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3530 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3531 *m_stackFileItemToUpdate = item;
3532 return PlayFile(*(movieList[selectedFile - 1]));
3534 // case 2: all other stacks
3537 // see if we have the info in the database
3538 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3539 // then these times will be wrong.
3540 // Also, this is really just a hack for the slow load up times we have
3541 // A much better solution is a fast reader of FPS and fileLength
3542 // that we can use on a file to get it's time.
3544 bool haveTimes(false);
3548 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3549 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3554 // calculate the total time of the stack
3555 CStackDirectory dir;
3556 dir.GetDirectory(item.GetPath(), *m_currentStack);
3558 for (int i = 0; i < m_currentStack->Size(); i++)
3561 (*m_currentStack)[i]->m_lEndOffset = times[i];
3565 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3567 m_currentStack->Clear();
3568 return PLAYBACK_FAIL;
3570 totalTime += duration / 1000;
3571 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3572 times.push_back(totalTime);
3576 double seconds = item.m_lStartOffset / 75.0;
3578 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3579 { // have our times now, so update the dB
3583 dbs.SetStackTimes(item.GetPath(), times);
3585 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3587 // can only resume seek here, not dvdstate
3589 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3590 seconds = bookmark.timeInSeconds;
3598 *m_itemCurrentFile = item;
3599 m_currentStackPosition = 0;
3600 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3604 // work out where to seek to
3605 for (int i = 0; i < m_currentStack->Size(); i++)
3607 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3609 CFileItem item(*(*m_currentStack)[i]);
3610 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3611 item.m_lStartOffset = (long)(seconds - start) * 75;
3612 m_currentStackPosition = i;
3613 return PlayFile(item, true);
3618 return PlayFile(*(*m_currentStack)[0], true);
3620 return PLAYBACK_FAIL;
3623 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3625 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3626 if (item.GetMimeType().empty())
3627 const_cast<CFileItem&>(item).FillInMimeType();
3631 SaveCurrentFileSettings();
3633 OutputDebugString("new file set audiostream:0\n");
3634 // Switch to default options
3635 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3636 // see if we have saved options in the database
3639 m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3641 *m_itemCurrentFile = item;
3642 m_nextPlaylistItem = -1;
3643 m_currentStackPosition = 0;
3644 m_currentStack->Clear();
3647 CUtil::ClearSubtitles();
3650 if (item.IsDiscStub())
3652 #ifdef HAS_DVD_DRIVE
3653 // Display the Play Eject dialog if there is any optical disc drive
3654 if (g_mediaManager.HasOpticalDrive())
3656 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3657 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3658 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3659 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3663 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3668 if (item.IsPlayList())
3669 return PLAYBACK_FAIL;
3671 if (item.IsPlugin())
3672 { // we modify the item so that it becomes a real URL
3673 CFileItem item_new(item);
3674 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3675 return PlayFile(item_new, false);
3676 return PLAYBACK_FAIL;
3680 if (URIUtils::IsUPnP(item.GetPath()))
3682 CFileItem item_new(item);
3683 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3684 return PlayFile(item_new, false);
3685 return PLAYBACK_FAIL;
3689 // if we have a stacked set of files, we need to setup our stack routines for
3690 // "seamless" seeking and total time of the movie etc.
3691 // will recall with restart set to true
3693 return PlayStack(item, bRestart);
3695 //Is TuxBox, this should probably be moved to CTuxBoxFile
3698 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3700 if(g_tuxboxService.IsRunning())
3701 g_tuxboxService.Stop();
3703 PlayBackRet ret = PLAYBACK_FAIL;
3705 if(g_tuxbox.CreateNewItem(item, item_new))
3708 // Make sure it doesn't have a player
3709 // so we actually select one normally
3710 m_eCurrentPlayer = EPC_NONE;
3712 // keep the tuxbox:// url as playing url
3713 // and give the new url to the player
3714 ret = PlayFile(item_new, true);
3715 if(ret == PLAYBACK_OK)
3717 if(!g_tuxboxService.IsRunning())
3718 g_tuxboxService.Start();
3724 CPlayerOptions options;
3726 if( item.HasProperty("StartPercent") )
3728 double fallback = 0.0f;
3729 if(item.GetProperty("StartPercent").isString())
3730 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3731 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3734 PLAYERCOREID eNewCore = EPC_NONE;
3737 // have to be set here due to playstack using this for starting the file
3738 options.starttime = item.m_lStartOffset / 75.0;
3739 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3740 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3742 if( m_eForcedNextPlayer != EPC_NONE )
3743 eNewCore = m_eForcedNextPlayer;
3744 else if( m_eCurrentPlayer == EPC_NONE )
3745 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3747 eNewCore = m_eCurrentPlayer;
3751 options.starttime = item.m_lStartOffset / 75.0;
3755 // open the d/b and retrieve the bookmarks for the current movie
3758 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3760 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3762 options.starttime = 0.0f;
3764 CStdString path = item.GetPath();
3765 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3766 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3767 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3768 path = item.GetProperty("original_listitem_url").asString();
3769 if(dbs.GetResumeBookMark(path, bookmark))
3771 options.starttime = bookmark.timeInSeconds;
3772 options.state = bookmark.playerState;
3775 override with information from the actual item if available. We do this as the VFS (eg plugins)
3776 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3777 should the playerState be required, it is fetched from the database.
3778 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3780 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3781 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3783 else if (item.HasVideoInfoTag())
3785 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3787 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3790 dbs.GetBookMarkForEpisode(*tag, bookmark);
3791 options.starttime = bookmark.timeInSeconds;
3792 options.state = bookmark.playerState;
3799 if (m_eForcedNextPlayer != EPC_NONE)
3800 eNewCore = m_eForcedNextPlayer;
3802 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3805 // this really aught to be inside !bRestart, but since PlayStack
3806 // uses that to init playback, we have to keep it outside
3807 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3808 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3809 { // playing from a playlist by the looks
3810 // don't switch to fullscreen if we are not playing the first item...
3811 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3813 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3815 // TODO - this will fail if user seeks back to first file in stack
3816 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3817 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3819 options.fullscreen = false;
3820 // reset this so we don't think we are resuming on seek
3821 m_itemCurrentFile->m_lStartOffset = 0;
3824 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3826 // reset VideoStartWindowed as it's a temp setting
3827 CMediaSettings::Get().SetVideoStartWindowed(false);
3830 //We have to stop parsing a cdg before mplayer is deallocated
3831 // WHY do we have to do this????
3833 m_pKaraokeMgr->Stop();
3837 CSingleLock lock(m_playStateMutex);
3838 // tell system we are starting a file
3839 m_bPlaybackStarting = true;
3841 // for playing a new item, previous playing item's callback may already
3842 // pushed some delay message into the threadmessage list, they are not
3843 // expected be processed after or during the new item playback starting.
3844 // so we clean up previous playing item's playback callback delay messages here.
3845 int previousMsgsIgnoredByNewPlaying[] = {
3846 GUI_MSG_PLAYBACK_STARTED,
3847 GUI_MSG_PLAYBACK_ENDED,
3848 GUI_MSG_PLAYBACK_STOPPED,
3849 GUI_MSG_PLAYLIST_CHANGED,
3850 GUI_MSG_PLAYLISTPLAYER_STOPPED,
3851 GUI_MSG_PLAYLISTPLAYER_STARTED,
3852 GUI_MSG_PLAYLISTPLAYER_CHANGED,
3853 GUI_MSG_QUEUE_NEXT_ITEM,
3856 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
3858 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
3861 // We should restart the player, unless the previous and next tracks are using
3862 // one of the players that allows gapless playback (paplayer, dvdplayer)
3865 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER
3866 #if defined(HAS_OMXPLAYER)
3867 || m_eCurrentPlayer == EPC_OMXPLAYER
3872 m_pPlayer->CloseFile();
3877 // XXX: we had to stop the previous playing item, it was done in dvdplayer::OpenFile.
3878 // but in paplayer::OpenFile, it sometimes just fade in without call CloseFile.
3879 // but if we do not stop it, we can not distingush callbacks from previous
3880 // item and current item, it will confused us then we can not make correct delay
3881 // callback after the starting state.
3883 m_pPlayer->CloseFile();
3887 // now reset play state to starting, since we already stopped the previous playing item if there is.
3888 // and from now there should be no playback callback from previous playing item be called.
3889 m_ePlayState = PLAY_STATE_STARTING;
3893 m_eCurrentPlayer = eNewCore;
3894 m_pPlayer.reset(CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this));
3897 PlayBackRet iResult;
3900 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
3901 * This should speed up player startup for files on internet filesystems (eg. webdav) and
3902 * increase performance on low powered systems (Atom/ARM).
3906 CJobManager::GetInstance().Pause(CJob::PRIORITY_LOW); // Pause any low priority jobs
3909 // don't hold graphicscontext here since player
3910 // may wait on another thread, that requires gfx
3911 CSingleExit ex(g_graphicsContext);
3912 // In busy dialog of OpenFile there's a chance to call another place delete the player
3913 // e.g. another PlayFile call switch player.
3914 // Here we use a holdPlace to keep the player not be deleted during OpenFile call
3915 boost::shared_ptr<IPlayer> holdPlace(m_pPlayer);
3916 // op seq for detect cancel (CloseFile be called or OpenFile be called again) during OpenFile.
3917 unsigned int startingSeq = ++m_iPlayerOPSeq;
3919 iResult = m_pPlayer->OpenFile(item, options) ? PLAYBACK_OK : PLAYBACK_FAIL;
3920 // check whether the OpenFile was canceled by either CloseFile or another OpenFile.
3921 if (m_iPlayerOPSeq != startingSeq)
3922 iResult = PLAYBACK_CANCELED;
3926 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3927 iResult = PLAYBACK_FAIL;
3930 if(iResult == PLAYBACK_OK)
3932 if (m_iPlaySpeed != 1)
3934 int iSpeed = m_iPlaySpeed;
3936 SetPlaySpeed(iSpeed);
3939 // if player has volume control, set it.
3940 if (m_pPlayer && m_pPlayer->ControlsVolume())
3942 m_pPlayer->SetVolume(m_volumeLevel);
3943 m_pPlayer->SetMute(m_muted);
3946 if( IsPlayingAudio() )
3948 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3949 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
3952 #ifdef HAS_VIDEO_PLAYBACK
3953 else if( IsPlayingVideo() )
3955 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
3956 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
3958 // if player didn't manange to switch to fullscreen by itself do it here
3959 if( options.fullscreen && g_renderManager.IsStarted()
3960 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
3961 SwitchToFullScreen();
3966 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
3967 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3968 g_windowManager.PreviousWindow();
3972 #if !defined(TARGET_POSIX)
3973 g_audioManager.Enable(false);
3976 if (item.HasPVRChannelInfoTag())
3977 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
3980 CSingleLock lock(m_playStateMutex);
3981 m_bPlaybackStarting = false;
3983 if (iResult == PLAYBACK_OK)
3985 // play state: none, starting; playing; stopped; ended.
3986 // last 3 states are set by playback callback, they are all ignored during starting,
3987 // but we recorded the state, here we can make up the callback for the state.
3988 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
3989 switch (m_ePlayState)
3991 case PLAY_STATE_PLAYING:
3992 OnPlayBackStarted();
3994 // FIXME: it seems no meaning to callback started here if there was an started callback
3995 // before this stopped/ended callback we recorded. if we callback started here
3996 // first, it will delay send OnPlay announce, but then we callback stopped/ended
3997 // which will send OnStop announce at once, so currently, just call stopped/ended.
3998 case PLAY_STATE_ENDED:
4001 case PLAY_STATE_STOPPED:
4002 OnPlayBackStopped();
4004 case PLAY_STATE_STARTING:
4005 // neither started nor stopped/ended callback be called, that means the item still
4006 // not started, we need not make up any callback, just leave this and
4007 // let the player callback do its work.
4013 else if (iResult == PLAYBACK_FAIL)
4015 // we send this if it isn't playlistplayer that is doing this
4016 int next = g_playlistPlayer.GetNextSong();
4017 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4020 OnPlayBackStopped();
4021 m_ePlayState = PLAY_STATE_NONE;
4027 void CApplication::OnPlayBackEnded()
4029 CSingleLock lock(m_playStateMutex);
4030 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4031 m_ePlayState = PLAY_STATE_ENDED;
4032 if(m_bPlaybackStarting)
4035 // informs python script currently running playback has ended
4036 // (does nothing if python is not loaded)
4038 g_pythonParser.OnPlayBackEnded();
4041 CVariant data(CVariant::VariantTypeObject);
4043 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4045 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4046 g_windowManager.SendThreadMessage(msg);
4049 void CApplication::OnPlayBackStarted()
4051 CSingleLock lock(m_playStateMutex);
4052 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4053 m_ePlayState = PLAY_STATE_PLAYING;
4054 if(m_bPlaybackStarting)
4058 // informs python script currently running playback has started
4059 // (does nothing if python is not loaded)
4060 g_pythonParser.OnPlayBackStarted();
4063 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4064 g_windowManager.SendThreadMessage(msg);
4067 void CApplication::OnQueueNextItem()
4069 CSingleLock lock(m_playStateMutex);
4070 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4071 if(m_bPlaybackStarting)
4073 // informs python script currently running that we are requesting the next track
4074 // (does nothing if python is not loaded)
4076 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4079 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4080 g_windowManager.SendThreadMessage(msg);
4083 void CApplication::OnPlayBackStopped()
4085 CSingleLock lock(m_playStateMutex);
4086 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4087 m_ePlayState = PLAY_STATE_STOPPED;
4088 if(m_bPlaybackStarting)
4091 // informs python script currently running playback has ended
4092 // (does nothing if python is not loaded)
4094 g_pythonParser.OnPlayBackStopped();
4097 CVariant data(CVariant::VariantTypeObject);
4098 data["end"] = false;
4099 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4101 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4102 g_windowManager.SendThreadMessage(msg);
4105 void CApplication::OnPlayBackPaused()
4108 g_pythonParser.OnPlayBackPaused();
4112 param["player"]["speed"] = 0;
4113 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4114 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4117 void CApplication::OnPlayBackResumed()
4120 g_pythonParser.OnPlayBackResumed();
4124 param["player"]["speed"] = 1;
4125 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4126 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4129 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4132 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4136 param["player"]["speed"] = iSpeed;
4137 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4138 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4141 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4144 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4148 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4149 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4150 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4151 param["player"]["speed"] = GetPlaySpeed();
4152 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4153 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4156 void CApplication::OnPlayBackSeekChapter(int iChapter)
4159 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4163 bool CApplication::IsPlaying() const
4167 if (!m_pPlayer->IsPlaying())
4172 bool CApplication::IsPaused() const
4176 if (!m_pPlayer->IsPlaying())
4178 return m_pPlayer->IsPaused();
4181 bool CApplication::IsPlayingAudio() const
4185 if (!m_pPlayer->IsPlaying())
4187 if (m_pPlayer->HasVideo())
4189 if (m_pPlayer->HasAudio())
4194 bool CApplication::IsPlayingVideo() const
4198 if (!m_pPlayer->IsPlaying())
4200 if (m_pPlayer->HasVideo())
4206 bool CApplication::IsPlayingFullScreenVideo() const
4208 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4211 bool CApplication::IsFullScreen()
4213 return IsPlayingFullScreenVideo() ||
4214 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4215 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4218 void CApplication::SaveFileState(bool bForeground /* = false */)
4220 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4225 CSaveFileStateJob job(*m_progressTrackingItem,
4226 *m_stackFileItemToUpdate,
4227 m_progressTrackingVideoResumeBookmark,
4228 m_progressTrackingPlayCountUpdate);
4230 // Run job in the foreground to make sure it finishes
4235 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4236 *m_stackFileItemToUpdate,
4237 m_progressTrackingVideoResumeBookmark,
4238 m_progressTrackingPlayCountUpdate);
4239 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4243 void CApplication::UpdateFileState()
4245 // Did the file change?
4246 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4250 // Reset tracking item
4251 m_progressTrackingItem->Reset();
4257 if (m_progressTrackingItem->GetPath() == "")
4260 *m_progressTrackingItem = CurrentFileItem();
4261 m_progressTrackingPlayCountUpdate = false;
4264 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4265 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4266 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4267 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4269 m_progressTrackingPlayCountUpdate = true;
4272 // Check whether we're *really* playing video else we may race when getting eg. stream details
4273 if (IsPlayingVideo())
4275 /* Always update streamdetails, except for DVDs where we only update
4276 streamdetails if title length > 15m (Should yield more correct info) */
4277 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4279 CStreamDetails details;
4280 // Update with stream details from player, if any
4281 if (m_pPlayer->GetStreamDetails(details))
4282 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4285 // Update bookmark for save
4286 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_eCurrentPlayer);
4287 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4288 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4290 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4291 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4293 // Delete the bookmark
4294 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4297 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4299 // Update the bookmark
4300 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4301 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4306 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4313 void CApplication::StopPlaying()
4315 int iWin = g_windowManager.GetActiveWindow();
4320 m_pKaraokeMgr->Stop();
4323 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4324 g_PVRManager.SaveCurrentChannelSettings();
4329 m_pPlayer->CloseFile();
4332 // turn off visualisation window when stopping
4333 if ((iWin == WINDOW_VISUALISATION
4334 || iWin == WINDOW_FULLSCREEN_VIDEO)
4336 g_windowManager.PreviousWindow();
4338 g_partyModeManager.Disable();
4342 void CApplication::ResetSystemIdleTimer()
4344 // reset system idle timer
4345 m_idleTimer.StartZero();
4348 void CApplication::ResetScreenSaver()
4351 m_shutdownTimer.StartZero();
4353 // screen saver timer is reset only if we're not already in screensaver or
4355 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4356 ResetScreenSaverTimer();
4359 void CApplication::ResetScreenSaverTimer()
4361 m_screenSaverTimer.StartZero();
4364 void CApplication::StopScreenSaverTimer()
4366 m_screenSaverTimer.Stop();
4369 bool CApplication::ToggleDPMS(bool manual)
4371 if (manual || (m_dpmsIsManual == manual))
4375 m_dpmsIsActive = false;
4376 m_dpmsIsManual = false;
4377 return m_dpms->DisablePowerSaving();
4381 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4383 m_dpmsIsActive = true;
4384 m_dpmsIsManual = manual;
4392 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4396 // First reset DPMS, if active
4401 // TODO: if screensaver lock is specified but screensaver is not active
4402 // (DPMS came first), activate screensaver now.
4404 ResetScreenSaverTimer();
4405 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4408 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4412 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4413 CVariant data(bPowerOffKeyPressed);
4414 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4420 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4422 if (m_iScreenSaveLock == 2)
4425 // if Screen saver is active
4426 if (m_bScreenSave && m_screenSaver)
4428 if (m_iScreenSaveLock == 0)
4429 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4430 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4431 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4432 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4434 m_iScreenSaveLock = 2;
4435 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4437 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4439 pWindow->OnMessage(msg);
4441 if (m_iScreenSaveLock == -1)
4443 m_iScreenSaveLock = 0;
4447 // disable screensaver
4448 m_bScreenSave = false;
4449 m_iScreenSaveLock = 0;
4450 ResetScreenSaverTimer();
4452 if (m_screenSaver->ID() == "visualization")
4454 // we can just continue as usual from vis mode
4457 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4459 else if (!m_screenSaver->ID().IsEmpty())
4460 { // we're in screensaver window
4461 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4462 g_windowManager.PreviousWindow(); // show the previous window
4463 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4464 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4472 void CApplication::CheckScreenSaverAndDPMS()
4474 if (m_bInBackground)
4476 if (!m_dpmsIsActive)
4477 g_Windowing.ResetOSScreensaver();
4479 bool maybeScreensaver =
4480 !m_dpmsIsActive && !m_bScreenSave
4481 && !CSettings::Get().GetString("screensaver.mode").empty();
4483 !m_dpmsIsActive && m_dpms->IsSupported()
4484 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4486 // Has the screen saver window become active?
4487 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4489 m_bScreenSave = true;
4490 maybeScreensaver = false;
4493 if (m_bScreenSave && IsPlayingVideo() && !m_pPlayer->IsPaused())
4495 WakeUpScreenSaverAndDPMS();
4499 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4501 // See if we need to reset timer.
4502 // * Are we playing a video and it is not paused?
4503 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4504 // * Are we playing some music in fullscreen vis?
4505 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4506 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4508 ResetScreenSaverTimer();
4512 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4514 // DPMS has priority (it makes the screensaver not needed)
4516 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4519 WakeUpScreenSaver();
4521 else if (maybeScreensaver
4522 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4524 ActivateScreenSaver();
4528 // activate the screensaver.
4529 // if forceType is true, we ignore the various conditions that can alter
4530 // the type of screensaver displayed
4531 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4533 m_bScreenSave = true;
4535 // Get Screensaver Mode
4536 m_screenSaver.reset();
4537 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4538 m_screenSaver.reset(new CScreenSaver(""));
4540 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4542 // disable screensaver lock from the login screen
4543 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4546 // set to Dim in the case of a dialog on screen or playing video
4547 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4549 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4550 m_screenSaver.reset(new CScreenSaver(""));
4552 // Check if we are Playing Audio and Vis instead Screensaver!
4553 else if (IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4554 { // activate the visualisation
4555 m_screenSaver.reset(new CScreenSaver("visualization"));
4556 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4560 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4562 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4564 else if (!m_screenSaver->ID().IsEmpty())
4565 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4568 void CApplication::SetInBackground(bool background)
4572 ResetScreenSaverTimer();
4574 m_bInBackground = background;
4577 void CApplication::CheckShutdown()
4579 // first check if we should reset the timer
4580 bool resetTimer = m_bInhibitIdleShutdown;
4582 if (IsPlaying() || IsPaused()) // is something playing?
4585 if (m_musicInfoScanner->IsScanning())
4588 if (m_videoInfoScanner->IsScanning())
4591 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4594 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4599 m_shutdownTimer.StartZero();
4603 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4605 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4606 m_shutdownTimer.Stop();
4609 CApplicationMessenger::Get().Shutdown();
4613 void CApplication::InhibitIdleShutdown(bool inhibit)
4615 m_bInhibitIdleShutdown = inhibit;
4618 bool CApplication::IsIdleShutdownInhibited() const
4620 return m_bInhibitIdleShutdown;
4623 bool CApplication::OnMessage(CGUIMessage& message)
4625 switch ( message.GetMessage() )
4627 case GUI_MSG_NOTIFY_ALL:
4629 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4631 // Update general playlist: Remove DVD playlist items
4632 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4635 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4636 g_windowManager.SendMessage( msg );
4638 // stop the file if it's on dvd (will set the resume point etc)
4639 if (m_itemCurrentFile->IsOnDVD())
4645 case GUI_MSG_PLAYBACK_STARTED:
4647 #ifdef TARGET_DARWIN
4648 DarwinSetScheduling(message.GetMessage());
4650 // reset the seek handler
4651 m_seekHandler->Reset();
4652 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4654 // Update our infoManager with the new details etc.
4655 if (m_nextPlaylistItem >= 0)
4657 // playing an item which is not in the list - player might be stopped already
4659 if (playList.size() <= m_nextPlaylistItem)
4662 // we've started a previously queued item
4663 CFileItemPtr item = playList[m_nextPlaylistItem];
4664 // update the playlist manager
4665 int currentSong = g_playlistPlayer.GetCurrentSong();
4666 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4667 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4668 g_windowManager.SendThreadMessage(msg);
4669 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4670 *m_itemCurrentFile = *item;
4672 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4673 g_partyModeManager.OnSongChange(true);
4676 param["player"]["speed"] = 1;
4677 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4678 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4680 if (IsPlayingAudio())
4682 // Start our cdg parser as appropriate
4684 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4686 m_pKaraokeMgr->Stop();
4687 if (m_itemCurrentFile->IsMusicDb())
4689 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4691 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4692 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4695 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4698 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4707 case GUI_MSG_QUEUE_NEXT_ITEM:
4709 // Check to see if our playlist player has a new item for us,
4710 // and if so, we check whether our current player wants the file
4711 int iNext = g_playlistPlayer.GetNextSong();
4712 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4713 if (iNext < 0 || iNext >= playlist.size())
4715 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4716 return true; // nothing to do
4719 // ok, grab the next song
4720 CFileItem file(*playlist[iNext]);
4722 CURL url(file.GetPath());
4723 if (url.GetProtocol() == "plugin")
4724 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4727 if (URIUtils::IsUPnP(file.GetPath()))
4729 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4734 // ok - send the file to the player, if it accepts it
4737 if (m_pPlayer->QueueNextFile(file))
4739 // player accepted the next file
4740 m_nextPlaylistItem = iNext;
4744 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4745 queue the next (if it wants to) and it doesn't keep looping on this song */
4746 g_playlistPlayer.SetCurrentSong(iNext);
4754 case GUI_MSG_PLAYBACK_STOPPED:
4755 case GUI_MSG_PLAYBACK_ENDED:
4756 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4760 m_pKaraokeMgr->Stop();
4762 #ifdef TARGET_DARWIN
4763 DarwinSetScheduling(message.GetMessage());
4765 // first check if we still have items in the stack to play
4766 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4768 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4769 { // just play the next item in the stack
4770 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4775 // In case playback ended due to user eg. skipping over the end, clear
4776 // our resume bookmark here
4777 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4779 // Delete the bookmark
4780 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4783 // reset the current playing file
4784 m_itemCurrentFile->Reset();
4785 g_infoManager.ResetCurrentItem();
4786 m_currentStack->Clear();
4788 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4790 g_playlistPlayer.PlayNext(1, true);
4794 // reset any forced player
4795 m_eForcedNextPlayer = EPC_NONE;
4800 m_pPlayer->CloseFile();
4810 g_audioManager.Enable(true);
4813 if (!IsPlayingVideo())
4815 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4817 g_windowManager.PreviousWindow();
4821 CSingleLock lock(g_graphicsContext);
4822 // resets to res_desktop or look&feel resolution (including refreshrate)
4823 g_graphicsContext.SetFullScreenVideo(false);
4827 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4829 CSettings::Get().Save(); // save vis settings
4830 WakeUpScreenSaverAndDPMS();
4831 g_windowManager.PreviousWindow();
4834 // DVD ejected while playing in vis ?
4835 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4838 CSettings::Get().Save(); // save vis settings
4839 WakeUpScreenSaverAndDPMS();
4840 g_windowManager.PreviousWindow();
4843 if (IsEnableTestMode())
4844 CApplicationMessenger::Get().Quit();
4849 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4850 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4855 case GUI_MSG_FULLSCREEN:
4856 { // Switch to fullscreen, if we can
4857 SwitchToFullScreen();
4861 case GUI_MSG_EXECUTE:
4862 if (message.GetNumStringParams())
4863 return ExecuteXBMCAction(message.GetStringParam());
4869 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4871 // see if it is a user set string
4872 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4873 CGUIInfoLabel info(actionStr, "");
4874 actionStr = info.GetLabel(0);
4875 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4877 // user has asked for something to be executed
4878 if (CBuiltins::HasCommand(actionStr))
4879 CBuiltins::Execute(actionStr);
4882 // try translating the action from our ButtonTranslator
4884 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4886 OnAction(CAction(actionID));
4889 CFileItem item(actionStr, false);
4891 if (item.IsPythonScript())
4892 { // a python script
4893 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
4897 if (item.IsAudio() || item.IsVideo())
4898 { // an audio or video file
4907 void CApplication::Process()
4911 // dispatch the messages generated by python or other threads to the current window
4912 g_windowManager.DispatchThreadMessages();
4914 // process messages which have to be send to the gui
4915 // (this can only be done after g_windowManager.Render())
4916 CApplicationMessenger::Get().ProcessWindowMessages();
4919 // process any Python scripts
4920 g_pythonParser.Process();
4923 // process messages, even if a movie is playing
4924 CApplicationMessenger::Get().ProcessMessages();
4925 if (g_application.m_bStop) return; //we're done, everything has been unloaded
4927 // check how far we are through playing the current item
4928 // and do anything that needs doing (playcount updates etc)
4929 CheckPlayingProgress();
4933 m_pPlayer->DoAudioWork();
4935 // do any processing that isn't needed on each run
4936 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4938 m_slowTimer.Reset();
4942 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4945 // We get called every 500ms
4946 void CApplication::ProcessSlow()
4948 g_powerManager.ProcessEvents();
4950 #if defined(TARGET_DARWIN_OSX)
4951 // There is an issue on OS X that several system services ask the cursor to become visible
4952 // during their startup routines. Given that we can't control this, we hack it in by
4954 if (g_Windowing.IsFullScreen())
4955 { // SDL thinks it's hidden
4960 // Resume low priority jobs when current item is not video
4961 if (!CurrentFileItem().IsVideo())
4963 CJobManager::GetInstance().UnPause(CJob::PRIORITY_LOW);
4966 // Store our file state for use on close()
4969 // Check if we need to activate the screensaver / DPMS.
4970 CheckScreenSaverAndDPMS();
4972 // Check if we need to shutdown (if enabled).
4973 #if defined(TARGET_DARWIN)
4974 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
4976 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
4982 // check if we should restart the player
4983 CheckDelayedPlayerRestart();
4985 // check if we can unload any unreferenced dlls or sections
4986 if (!IsPlayingVideo())
4987 CSectionLoader::UnloadDelayed();
4989 // check for any idle curl connections
4990 g_curlInterface.CheckIdle();
4992 // check for any idle myth sessions
4993 CMythSession::CheckIdle();
4995 #ifdef HAS_FILESYSTEM_HTSP
4996 // check for any idle htsp sessions
4997 HTSP::CHTSPDirectorySession::CheckIdle();
5001 if ( m_pKaraokeMgr )
5002 m_pKaraokeMgr->ProcessSlow();
5005 if (!IsPlayingVideo())
5006 g_largeTextureManager.CleanupUnusedImages();
5008 g_TextureManager.FreeUnusedTextures(5000);
5010 #ifdef HAS_DVD_DRIVE
5011 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5012 if (!IsPlayingVideo())
5013 m_Autorun->HandleAutorun();
5016 // update upnp server/renderer states
5018 if(UPNP::CUPnP::IsInstantiated())
5019 UPNP::CUPnP::GetInstance()->UpdateState();
5022 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5026 #ifdef HAS_FILESYSTEM_NFS
5027 gNfsConnection.CheckIfIdle();
5030 #ifdef HAS_FILESYSTEM_AFP
5031 gAfpConnection.CheckIfIdle();
5034 #ifdef HAS_FILESYSTEM_SFTP
5035 CSFTPSessionManager::ClearOutIdleSessions();
5038 g_mediaManager.ProcessEvents();
5041 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5042 g_RemoteControl.Initialize();
5045 if (!IsPlayingVideo())
5046 CAddonInstaller::Get().UpdateRepos();
5048 CAEFactory::GarbageCollect();
5051 // Global Idle Time in Seconds
5052 // idle time will be resetet if on any OnKey()
5053 // int return: system Idle time in seconds! 0 is no idle!
5054 int CApplication::GlobalIdleTime()
5056 if(!m_idleTimer.IsRunning())
5059 m_idleTimer.StartZero();
5061 return (int)m_idleTimer.GetElapsedSeconds();
5064 float CApplication::NavigationIdleTime()
5066 if (!m_navigationTimer.IsRunning())
5068 m_navigationTimer.Stop();
5069 m_navigationTimer.StartZero();
5071 return m_navigationTimer.GetElapsedSeconds();
5074 void CApplication::DelayedPlayerRestart()
5076 m_restartPlayerTimer.StartZero();
5079 void CApplication::CheckDelayedPlayerRestart()
5081 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5083 m_restartPlayerTimer.Stop();
5084 m_restartPlayerTimer.Reset();
5089 void CApplication::Restart(bool bSamePosition)
5091 // this function gets called when the user changes a setting (like noninterleaved)
5092 // and which means we gotta close & reopen the current playing file
5094 // first check if we're playing a file
5095 if ( !IsPlayingVideo() && !IsPlayingAudio())
5103 // do we want to return to the current position in the file
5104 if (false == bSamePosition)
5106 // no, then just reopen the file and start at the beginning
5107 PlayFile(*m_itemCurrentFile, true);
5111 // else get current position
5112 double time = GetTime();
5114 // get player state, needed for dvd's
5115 CStdString state = m_pPlayer->GetPlayerState();
5117 // set the requested starttime
5118 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5121 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK && m_pPlayer )
5122 m_pPlayer->SetPlayerState(state);
5125 const CStdString& CApplication::CurrentFile()
5127 return m_itemCurrentFile->GetPath();
5130 CFileItem& CApplication::CurrentFileItem()
5132 return *m_itemCurrentFile;
5135 void CApplication::ShowVolumeBar(const CAction *action)
5137 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5142 volumeBar->OnAction(*action);
5146 bool CApplication::IsMuted() const
5148 if (g_peripherals.IsMuted())
5150 return CAEFactory::IsMuted();
5153 void CApplication::ToggleMute(void)
5161 void CApplication::SetMute(bool mute)
5163 if (m_muted != mute)
5170 void CApplication::Mute()
5172 if (g_peripherals.Mute())
5175 CAEFactory::SetMute(true);
5180 void CApplication::UnMute()
5182 if (g_peripherals.UnMute())
5185 CAEFactory::SetMute(false);
5190 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5192 float hardwareVolume = iValue;
5195 hardwareVolume /= 100.0f;
5197 SetHardwareVolume(hardwareVolume);
5201 void CApplication::SetHardwareVolume(float hardwareVolume)
5203 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5204 m_volumeLevel = hardwareVolume;
5207 if (hardwareVolume > VOLUME_MINIMUM)
5209 float dB = CAEUtil::PercentToGain(hardwareVolume);
5210 value = CAEUtil::GainToScale(dB);
5215 CAEFactory::SetVolume(value);
5218 float CApplication::GetVolume(bool percentage /* = true */) const
5222 // converts the hardware volume to a percentage
5223 return m_volumeLevel * 100.0f;
5226 return m_volumeLevel;
5229 void CApplication::VolumeChanged() const
5231 CVariant data(CVariant::VariantTypeObject);
5232 data["volume"] = GetVolume();
5233 data["muted"] = m_muted;
5234 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5236 // if player has volume control, set it.
5237 if (m_pPlayer && m_pPlayer->ControlsVolume())
5239 m_pPlayer->SetVolume(m_volumeLevel);
5240 m_pPlayer->SetMute(m_muted);
5244 int CApplication::GetSubtitleDelay() const
5246 // converts subtitle delay to a percentage
5247 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5250 int CApplication::GetAudioDelay() const
5252 // converts audio delay to a percentage
5253 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5256 void CApplication::SetPlaySpeed(int iSpeed)
5258 if (!IsPlayingAudio() && !IsPlayingVideo())
5260 if (m_iPlaySpeed == iSpeed)
5262 if (!m_pPlayer->CanSeek())
5264 if (m_pPlayer->IsPaused())
5267 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5268 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5271 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5275 m_iPlaySpeed = iSpeed;
5277 m_pPlayer->ToFFRW(m_iPlaySpeed);
5279 // if player has volume control, set it.
5280 if (m_pPlayer->ControlsVolume())
5282 if (m_iPlaySpeed == 1)
5284 m_pPlayer->SetVolume(VOLUME_MAXIMUM);
5288 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5290 m_pPlayer->SetMute(m_muted);
5294 int CApplication::GetPlaySpeed() const
5296 return m_iPlaySpeed;
5299 // Returns the total time in seconds of the current media. Fractional
5300 // portions of a second are possible - but not necessarily supported by the
5301 // player class. This returns a double to be consistent with GetTime() and
5303 double CApplication::GetTotalTime() const
5307 if (IsPlaying() && m_pPlayer)
5309 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5310 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5312 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5318 void CApplication::StopShutdownTimer()
5320 if (m_shutdownTimer.IsRunning())
5321 m_shutdownTimer.Stop();
5324 void CApplication::ResetShutdownTimers()
5326 // reset system shutdown timer
5327 m_shutdownTimer.StartZero();
5329 // delete custom shutdown timer
5330 if (g_alarmClock.HasAlarm("shutdowntimer"))
5331 g_alarmClock.Stop("shutdowntimer", true);
5334 // Returns the current time in seconds of the currently playing media.
5335 // Fractional portions of a second are possible. This returns a double to
5336 // be consistent with GetTotalTime() and SeekTime().
5337 double CApplication::GetTime() const
5341 if (IsPlaying() && m_pPlayer)
5343 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5345 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5346 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5349 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5355 // Sets the current position of the currently playing media to the specified
5356 // time in seconds. Fractional portions of a second are valid. The passed
5357 // time is the time offset from the beginning of the file as opposed to a
5358 // delta from the current position. This method accepts a double to be
5359 // consistent with GetTime() and GetTotalTime().
5360 void CApplication::SeekTime( double dTime )
5362 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5364 if (!m_pPlayer->CanSeek()) return;
5365 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5367 // find the item in the stack we are seeking to, and load the new
5368 // file if necessary, and calculate the correct seek within the new
5369 // file. Otherwise, just fall through to the usual routine if the
5370 // time is higher than our total time.
5371 for (int i = 0; i < m_currentStack->Size(); i++)
5373 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5375 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5376 if (m_currentStackPosition == i)
5377 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5379 { // seeking to a new file
5380 m_currentStackPosition = i;
5381 CFileItem item(*(*m_currentStack)[i]);
5382 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5383 // don't just call "PlayFile" here, as we are quite likely called from the
5384 // player thread, so we won't be able to delete ourselves.
5385 CApplicationMessenger::Get().PlayFile(item, true);
5391 // convert to milliseconds and perform seek
5392 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5396 float CApplication::GetPercentage() const
5398 if (IsPlaying() && m_pPlayer)
5400 if (m_pPlayer->GetTotalTime() == 0 && IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5402 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5403 if (tag.GetDuration() > 0)
5404 return (float)(GetTime() / tag.GetDuration() * 100);
5407 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5409 double totalTime = GetTotalTime();
5410 if (totalTime > 0.0f)
5411 return (float)(GetTime() / totalTime * 100);
5414 return m_pPlayer->GetPercentage();
5419 float CApplication::GetCachePercentage() const
5421 if (IsPlaying() && m_pPlayer)
5423 // Note that the player returns a relative cache percentage and we want an absolute percentage
5424 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5426 float stackedTotalTime = (float) GetTotalTime();
5427 // We need to take into account the stack's total time vs. currently playing file's total time
5428 if (stackedTotalTime > 0.0f)
5429 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5432 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5437 void CApplication::SeekPercentage(float percent)
5439 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5441 if (!m_pPlayer->CanSeek()) return;
5442 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5443 SeekTime(percent * 0.01 * GetTotalTime());
5445 m_pPlayer->SeekPercentage(percent);
5449 // SwitchToFullScreen() returns true if a switch is made, else returns false
5450 bool CApplication::SwitchToFullScreen()
5452 // if playing from the video info window, close it first!
5453 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5455 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5456 if (pDialog) pDialog->Close(true);
5459 // don't switch if there is a dialog on screen or the slideshow is active
5460 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5463 // See if we're playing a video, and are in GUI mode
5464 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5466 // then switch to fullscreen mode
5467 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5470 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5471 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5472 { // then switch to visualisation
5473 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5479 void CApplication::Minimize()
5481 g_Windowing.Minimize();
5484 PLAYERCOREID CApplication::GetCurrentPlayer()
5486 return m_eCurrentPlayer;
5489 void CApplication::UpdateLibraries()
5491 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5493 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5497 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5499 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5504 bool CApplication::IsVideoScanning() const
5506 return m_videoInfoScanner->IsScanning();
5509 bool CApplication::IsMusicScanning() const
5511 return m_musicInfoScanner->IsScanning();
5514 void CApplication::StopVideoScan()
5516 if (m_videoInfoScanner->IsScanning())
5517 m_videoInfoScanner->Stop();
5520 void CApplication::StopMusicScan()
5522 if (m_musicInfoScanner->IsScanning())
5523 m_musicInfoScanner->Stop();
5526 void CApplication::StartVideoCleanup()
5528 if (m_videoInfoScanner->IsScanning())
5531 m_videoInfoScanner->CleanDatabase();
5534 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5536 if (m_videoInfoScanner->IsScanning())
5539 m_videoInfoScanner->ShowDialog(true);
5541 m_videoInfoScanner->Start(strDirectory,scanAll);
5544 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5546 if (m_musicInfoScanner->IsScanning())
5550 { // setup default flags
5551 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5552 flags |= CMusicInfoScanner::SCAN_ONLINE;
5553 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5554 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5557 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5558 m_musicInfoScanner->ShowDialog(true);
5560 m_musicInfoScanner->Start(strDirectory, flags);
5563 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5566 if (m_musicInfoScanner->IsScanning())
5569 m_musicInfoScanner->ShowDialog(true);
5571 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5574 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5577 if (m_musicInfoScanner->IsScanning())
5580 m_musicInfoScanner->ShowDialog(true);
5582 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5585 void CApplication::CheckPlayingProgress()
5587 // check if we haven't rewound past the start of the file
5590 int iSpeed = g_application.GetPlaySpeed();
5600 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5602 g_application.SetPlaySpeed(1);
5603 g_application.SeekTime(0);
5609 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5611 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5613 // initial exit conditions
5614 // no songs in playlist just return
5615 if (playlist.size() == 0)
5619 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5622 // setup correct playlist
5623 g_playlistPlayer.ClearPlaylist(iPlaylist);
5625 // if the playlist contains an internet stream, this file will be used
5626 // to generate a thumbnail for musicplayer.cover
5627 g_application.m_strPlayListFile = strPlayList;
5629 // add the items to the playlist player
5630 g_playlistPlayer.Add(iPlaylist, playlist);
5632 // if we have a playlist
5633 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5636 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5637 g_playlistPlayer.Reset();
5638 g_playlistPlayer.Play(track);
5644 void CApplication::SaveCurrentFileSettings()
5646 // don't store settings for PVR in video database
5647 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5649 // save video settings
5650 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5654 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5658 else if (m_itemCurrentFile->IsPVRChannel())
5660 g_PVRManager.SaveCurrentChannelSettings();
5664 bool CApplication::AlwaysProcess(const CAction& action)
5666 // check if this button is mapped to a built-in function
5667 if (!action.GetName().IsEmpty())
5669 CStdString builtInFunction;
5670 vector<CStdString> params;
5671 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5672 builtInFunction.ToLower();
5674 // should this button be handled normally or just cancel the screensaver?
5675 if ( builtInFunction.Equals("powerdown")
5676 || builtInFunction.Equals("reboot")
5677 || builtInFunction.Equals("restart")
5678 || builtInFunction.Equals("restartapp")
5679 || builtInFunction.Equals("suspend")
5680 || builtInFunction.Equals("hibernate")
5681 || builtInFunction.Equals("quit")
5682 || builtInFunction.Equals("shutdown"))
5691 bool CApplication::IsCurrentThread() const
5693 return CThread::IsCurrentThread(m_threadID);
5696 void CApplication::SetRenderGUI(bool renderGUI)
5698 if (renderGUI && ! m_renderGUI)
5699 g_windowManager.MarkDirty();
5700 m_renderGUI = renderGUI;
5703 CNetwork& CApplication::getNetwork()
5707 #ifdef HAS_PERFORMANCE_SAMPLE
5708 CPerformanceStats &CApplication::GetPerformanceStats()
5714 bool CApplication::SetLanguage(const CStdString &strLanguage)
5716 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5717 CStdString strNewLanguage = strLanguage;
5718 if (strNewLanguage != strPreviousLanguage)
5720 CStdString strLangInfoPath;
5721 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5722 if (!g_langInfo.Load(strLangInfoPath))
5725 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5727 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5728 CStdString strFontSet;
5729 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5730 strNewLanguage = strFontSet;
5732 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5734 CSettings::Get().SetString("locale.language", strNewLanguage);
5736 g_charsetConverter.reset();
5738 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5741 // also tell our weather and skin to reload as these are localized
5742 g_weatherManager.Refresh();
5743 g_PVRManager.LocalizationChanged();