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/dvdplayer/DVDFileInfo.h"
34 #include "cores/AudioEngine/AEFactory.h"
35 #include "cores/AudioEngine/Utils/AEUtil.h"
36 #include "PlayListPlayer.h"
38 #include "video/Bookmark.h"
40 #include "network/WebServer.h"
41 #include "network/httprequesthandler/HTTPImageHandler.h"
42 #include "network/httprequesthandler/HTTPVfsHandler.h"
44 #include "network/httprequesthandler/HTTPJsonRpcHandler.h"
46 #ifdef HAS_WEB_INTERFACE
47 #include "network/httprequesthandler/HTTPWebinterfaceHandler.h"
48 #include "network/httprequesthandler/HTTPWebinterfaceAddonsHandler.h"
51 #include "guilib/GUIControlProfiler.h"
52 #include "utils/LangCodeExpander.h"
53 #include "GUIInfoManager.h"
54 #include "playlists/PlayListFactory.h"
55 #include "guilib/GUIFontManager.h"
56 #include "guilib/GUIColorManager.h"
57 #include "guilib/GUITextLayout.h"
58 #include "addons/Skin.h"
60 #include "interfaces/python/XBPython.h"
62 #include "input/ButtonTranslator.h"
63 #include "guilib/GUIAudioManager.h"
64 #include "network/libscrobbler/lastfmscrobbler.h"
65 #include "network/libscrobbler/librefmscrobbler.h"
66 #include "GUIPassword.h"
67 #include "input/InertialScrollingHandler.h"
68 #include "ApplicationMessenger.h"
69 #include "SectionLoader.h"
70 #include "cores/DllLoader/DllLoaderContainer.h"
71 #include "GUIUserMessages.h"
72 #include "filesystem/DirectoryCache.h"
73 #include "filesystem/StackDirectory.h"
74 #include "filesystem/SpecialProtocol.h"
75 #include "filesystem/DllLibCurl.h"
76 #include "filesystem/MythSession.h"
77 #include "filesystem/PluginDirectory.h"
78 #ifdef HAS_FILESYSTEM_SAP
79 #include "filesystem/SAPDirectory.h"
81 #ifdef HAS_FILESYSTEM_HTSP
82 #include "filesystem/HTSPDirectory.h"
84 #include "utils/TuxBoxUtil.h"
85 #include "utils/SystemInfo.h"
86 #include "utils/TimeUtils.h"
87 #include "GUILargeTextureManager.h"
88 #include "TextureCache.h"
89 #include "music/LastFmManager.h"
90 #include "playlists/SmartPlayList.h"
91 #ifdef HAS_FILESYSTEM_RAR
92 #include "filesystem/RarManager.h"
94 #include "playlists/PlayList.h"
95 #include "windowing/WindowingFactory.h"
96 #include "powermanagement/PowerManager.h"
97 #include "powermanagement/DPMSSupport.h"
98 #include "settings/Settings.h"
99 #include "settings/AdvancedSettings.h"
100 #include "guilib/LocalizeStrings.h"
101 #include "utils/CPUInfo.h"
102 #include "utils/SeekHandler.h"
104 #include "input/KeyboardStat.h"
105 #include "input/XBMC_vkeys.h"
106 #include "input/MouseStat.h"
112 #if defined(FILESYSTEM) && !defined(_LINUX)
113 #include "filesystem/FileDAAP.h"
116 #include "network/upnp/UPnP.h"
117 #include "filesystem/UPnPDirectory.h"
119 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
120 #include "filesystem/SMBDirectory.h"
122 #ifdef HAS_FILESYSTEM_NFS
123 #include "filesystem/NFSFile.h"
125 #ifdef HAS_FILESYSTEM_AFP
126 #include "filesystem/AFPFile.h"
128 #ifdef HAS_FILESYSTEM_SFTP
129 #include "filesystem/SFTPFile.h"
131 #include "PartyModeManager.h"
132 #ifdef HAS_VIDEO_PLAYBACK
133 #include "cores/VideoRenderers/RenderManager.h"
136 #include "music/karaoke/karaokelyricsmanager.h"
137 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
138 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
140 #include "network/Zeroconf.h"
141 #include "network/ZeroconfBrowser.h"
143 #include "threads/platform/win/Win32Exception.h"
145 #ifdef HAS_EVENT_SERVER
146 #include "network/EventServer.h"
149 #include <dbus/dbus.h>
152 #include "interfaces/json-rpc/JSONRPC.h"
153 #include "network/TCPServer.h"
156 #include "network/AirPlayServer.h"
159 #include "network/AirTunesServer.h"
161 #if defined(HAVE_LIBCRYSTALHD)
162 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
164 #include "interfaces/AnnouncementManager.h"
165 #include "peripherals/Peripherals.h"
166 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
167 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
168 #include "peripherals/devices/PeripheralImon.h"
169 #include "music/infoscanner/MusicInfoScanner.h"
172 #include "guilib/GUIWindowManager.h"
173 #include "windows/GUIWindowHome.h"
174 #include "settings/GUIWindowSettings.h"
175 #include "windows/GUIWindowFileManager.h"
176 #include "settings/GUIWindowSettingsCategory.h"
177 #include "music/windows/GUIWindowMusicPlaylist.h"
178 #include "music/windows/GUIWindowMusicSongs.h"
179 #include "music/windows/GUIWindowMusicNav.h"
180 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
181 #include "video/windows/GUIWindowVideoPlaylist.h"
182 #include "music/dialogs/GUIDialogMusicInfo.h"
183 #include "video/dialogs/GUIDialogVideoInfo.h"
184 #include "video/windows/GUIWindowVideoNav.h"
185 #include "settings/GUIWindowSettingsProfile.h"
187 #include "rendering/gl/GUIWindowTestPatternGL.h"
190 #include "rendering/dx/GUIWindowTestPatternDX.h"
192 #include "settings/GUIWindowSettingsScreenCalibration.h"
193 #include "programs/GUIWindowPrograms.h"
194 #include "pictures/GUIWindowPictures.h"
195 #include "windows/GUIWindowWeather.h"
196 #include "windows/GUIWindowLoginScreen.h"
197 #include "addons/GUIWindowAddonBrowser.h"
198 #include "music/windows/GUIWindowVisualisation.h"
199 #include "windows/GUIWindowDebugInfo.h"
200 #include "windows/GUIWindowPointer.h"
201 #include "windows/GUIWindowSystemInfo.h"
202 #include "windows/GUIWindowScreensaver.h"
203 #include "windows/GUIWindowScreensaverDim.h"
204 #include "pictures/GUIWindowSlideShow.h"
205 #include "windows/GUIWindowStartup.h"
206 #include "video/windows/GUIWindowFullScreen.h"
207 #include "video/dialogs/GUIDialogVideoOSD.h"
208 #include "music/dialogs/GUIDialogMusicOverlay.h"
209 #include "video/dialogs/GUIDialogVideoOverlay.h"
210 #include "video/VideoInfoScanner.h"
213 #include "music/dialogs/GUIDialogMusicOSD.h"
214 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
215 #include "dialogs/GUIDialogTextViewer.h"
216 #include "network/GUIDialogNetworkSetup.h"
217 #include "dialogs/GUIDialogMediaSource.h"
218 #include "video/dialogs/GUIDialogVideoSettings.h"
219 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
220 #include "video/dialogs/GUIDialogVideoBookmarks.h"
221 #include "settings/GUIDialogProfileSettings.h"
222 #include "settings/GUIDialogLockSettings.h"
223 #include "settings/GUIDialogContentSettings.h"
224 #include "dialogs/GUIDialogBusy.h"
225 #include "dialogs/GUIDialogKeyboardGeneric.h"
226 #include "dialogs/GUIDialogYesNo.h"
227 #include "dialogs/GUIDialogOK.h"
228 #include "dialogs/GUIDialogProgress.h"
229 #include "dialogs/GUIDialogExtendedProgressBar.h"
230 #include "dialogs/GUIDialogSelect.h"
231 #include "dialogs/GUIDialogSeekBar.h"
232 #include "dialogs/GUIDialogKaiToast.h"
233 #include "dialogs/GUIDialogVolumeBar.h"
234 #include "dialogs/GUIDialogMuteBug.h"
235 #include "video/dialogs/GUIDialogFileStacking.h"
236 #include "dialogs/GUIDialogNumeric.h"
237 #include "dialogs/GUIDialogGamepad.h"
238 #include "dialogs/GUIDialogSubMenu.h"
239 #include "dialogs/GUIDialogFavourites.h"
240 #include "dialogs/GUIDialogButtonMenu.h"
241 #include "dialogs/GUIDialogContextMenu.h"
242 #include "dialogs/GUIDialogPlayerControls.h"
243 #include "music/dialogs/GUIDialogSongInfo.h"
244 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
245 #include "dialogs/GUIDialogSmartPlaylistRule.h"
246 #include "pictures/GUIDialogPictureInfo.h"
247 #include "addons/GUIDialogAddonSettings.h"
248 #include "addons/GUIDialogAddonInfo.h"
249 #ifdef HAS_LINUX_NETWORK
250 #include "network/GUIDialogAccessPoints.h"
253 /* PVR related include Files */
254 #include "pvr/PVRManager.h"
255 #include "pvr/timers/PVRTimers.h"
256 #include "pvr/windows/GUIWindowPVR.h"
257 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
258 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
260 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
261 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
263 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
264 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
265 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
266 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
268 #include "epg/EpgContainer.h"
270 #include "video/dialogs/GUIDialogFullScreenInfo.h"
271 #include "video/dialogs/GUIDialogTeletext.h"
272 #include "dialogs/GUIDialogSlider.h"
273 #include "guilib/GUIControlFactory.h"
274 #include "dialogs/GUIDialogCache.h"
275 #include "dialogs/GUIDialogPlayEject.h"
276 #include "dialogs/GUIDialogMediaFilter.h"
277 #include "utils/XMLUtils.h"
278 #include "addons/AddonInstaller.h"
280 #ifdef HAS_PERFORMANCE_SAMPLE
281 #include "utils/PerformanceSample.h"
283 #define MEASURE_FUNCTION
286 #ifdef TARGET_WINDOWS
288 #include "win32util.h"
291 #include "windowing/X11/XRandR.h"
294 #ifdef TARGET_DARWIN_OSX
295 #include "osx/CocoaInterface.h"
296 #include "osx/XBMCHelper.h"
299 #include "osx/DarwinUtils.h"
304 #include <cdio/logging.h>
308 #include "linux/HALManager.h"
311 #include "storage/MediaManager.h"
312 #include "utils/JobManager.h"
313 #include "utils/SaveFileStateJob.h"
314 #include "utils/AlarmClock.h"
315 #include "utils/StringUtils.h"
316 #include "DatabaseManager.h"
323 #include "input/linux/LIRC.h"
325 #ifdef HAS_IRSERVERSUITE
326 #include "input/windows/IRServerSuite.h"
329 #if defined(TARGET_WINDOWS)
330 #include "input/windows/WINJoystick.h"
331 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
332 #include "input/SDLJoystick.h"
335 #if defined(TARGET_ANDROID)
336 #include "android/activity/XBMCApp.h"
340 using namespace ADDON;
341 using namespace XFILE;
343 using namespace MEDIA_DETECT;
345 using namespace PLAYLIST;
346 using namespace VIDEO;
347 using namespace MUSIC_INFO;
348 #ifdef HAS_EVENT_SERVER
349 using namespace EVENTSERVER;
352 using namespace JSONRPC;
354 using namespace ANNOUNCEMENT;
357 using namespace PERIPHERALS;
359 using namespace XbmcThreads;
361 // uncomment this if you want to use release libs in the debug build.
362 // Atm this saves you 7 mb of memory
363 #define USE_RELEASE_LIBS
365 #define MAX_FFWD_SPEED 5
367 //extern IDirectSoundRenderer* m_pAudioDecoder;
368 CApplication::CApplication(void)
370 #ifdef HAS_WEB_SERVER
371 , m_WebServer(*new CWebServer)
372 , m_httpImageHandler(*new CHTTPImageHandler)
373 , m_httpVfsHandler(*new CHTTPVfsHandler)
375 , m_httpJsonRpcHandler(*new CHTTPJsonRpcHandler)
377 #ifdef HAS_WEB_INTERFACE
378 , m_httpWebinterfaceHandler(*new CHTTPWebinterfaceHandler)
379 , m_httpWebinterfaceAddonsHandler(*new CHTTPWebinterfaceAddonsHandler)
382 , m_itemCurrentFile(new CFileItem)
383 , m_stackFileItemToUpdate(new CFileItem)
384 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
385 , m_progressTrackingItem(new CFileItem)
386 , m_videoInfoScanner(new CVideoInfoScanner)
387 , m_musicInfoScanner(new CMusicInfoScanner)
388 , m_seekHandler(new CSeekHandler)
391 TiXmlBase::SetCondenseWhiteSpace(false);
393 m_bInhibitIdleShutdown = false;
394 m_bScreenSave = false;
396 m_dpmsIsActive = false;
397 m_dpmsIsManual = false;
398 m_iScreenSaveLock = 0;
399 m_bInitializing = true;
400 m_eForcedNextPlayer = EPC_NONE;
401 m_strPlayListFile = "";
402 m_nextPlaylistItem = -1;
403 m_bPlaybackStarting = false;
404 m_skinReloading = false;
410 /* for now always keep this around */
412 m_pKaraokeMgr = new CKaraokeLyricsManager();
414 m_currentStack = new CFileItemList;
418 m_bPresentFrame = false;
419 m_bPlatformDirectories = true;
421 m_bStandalone = false;
422 m_bEnableLegacyRes = false;
423 m_bSystemScreenSaverEnable = false;
424 m_pInertialScrollingHandler = new CInertialScrollingHandler();
426 m_Autorun = new CAutorun();
431 m_eCurrentPlayer = EPC_NONE;
432 m_progressTrackingPlayCountUpdate = false;
433 m_currentStackPosition = 0;
435 m_lastRenderTime = 0;
439 CApplication::~CApplication(void)
441 #ifdef HAS_WEB_SERVER
443 delete &m_httpImageHandler;
444 delete &m_httpVfsHandler;
446 delete &m_httpJsonRpcHandler;
448 #ifdef HAS_WEB_INTERFACE
449 delete &m_httpWebinterfaceHandler;
450 delete &m_httpWebinterfaceAddonsHandler;
453 delete m_musicInfoScanner;
454 delete m_videoInfoScanner;
455 delete &m_progressTrackingVideoResumeBookmark;
459 delete m_currentStack;
462 delete m_pKaraokeMgr;
466 delete m_seekHandler;
467 delete m_pInertialScrollingHandler;
471 bool CApplication::OnEvent(XBMC_Event& newEvent)
473 switch(newEvent.type)
476 if (!g_application.m_bStop)
477 CApplicationMessenger::Get().Quit();
480 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
483 g_Keyboard.ProcessKeyUp();
485 case XBMC_MOUSEBUTTONDOWN:
486 case XBMC_MOUSEBUTTONUP:
487 case XBMC_MOUSEMOTION:
488 g_Mouse.HandleEvent(newEvent);
489 g_application.ProcessMouse();
491 case XBMC_VIDEORESIZE:
492 if (!g_application.m_bInitializing &&
493 !g_advancedSettings.m_fullScreen)
495 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
496 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
497 g_guiSettings.SetInt("window.width", newEvent.resize.w);
498 g_guiSettings.SetInt("window.height", newEvent.resize.h);
503 #ifdef TARGET_WINDOWS
504 if (g_advancedSettings.m_fullScreen)
506 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
507 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
508 if (newRes != g_graphicsContext.GetVideoResolution())
510 g_guiSettings.SetResolution(newRes);
511 g_graphicsContext.SetVideoResolution(newRes);
517 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
521 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
523 case XBMC_APPCOMMAND:
524 return g_application.OnAppCommand(newEvent.appcommand.action);
529 extern "C" void __stdcall init_emu_environ();
530 extern "C" void __stdcall update_emu_environ();
533 // Utility function used to copy files from the application bundle
534 // over to the user data directory in Application Support/XBMC.
536 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
538 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
539 if (!CFile::Exists(destPath))
541 // need to copy it across
542 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
543 CFile::Cache(srcPath, destPath);
547 void CApplication::Preflight()
550 // call 'dbus_threads_init_default' before any other dbus calls in order to
551 // avoid race conditions with other threads using dbus connections
552 dbus_threads_init_default();
555 // run any platform preflight scripts.
556 #if defined(TARGET_DARWIN_OSX)
557 CStdString install_path;
559 CUtil::GetHomePath(install_path);
560 setenv("XBMC_HOME", install_path.c_str(), 0);
561 install_path += "/tools/darwin/runtime/preflight";
562 system(install_path.c_str());
566 bool CApplication::Create()
568 #if defined(HAS_LINUX_NETWORK)
569 m_network = new CNetworkLinux();
570 #elif defined(HAS_WIN32_NETWORK)
571 m_network = new CNetworkWin32();
573 m_network = new CNetwork();
577 g_settings.Initialize(); //Initialize default AdvancedSettings
580 tzset(); // Initialize timezone information variables
583 // Grab a handle to our thread to be used later in identifying the render thread.
584 m_threadID = CThread::GetCurrentThreadId();
587 //floating point precision to 24 bits (faster performance)
588 _controlfp(_PC_24, _MCW_PC);
590 /* install win32 exception translator, win32 exceptions
591 * can now be caught using c++ try catch */
592 win32_exception::install_handler();
596 // only the InitDirectories* for the current platform should return true
597 // putting this before the first log entries saves another ifdef for g_settings.m_logFolder
598 bool inited = InitDirectoriesLinux();
600 inited = InitDirectoriesOSX();
602 inited = InitDirectoriesWin32();
604 // copy required files
605 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
606 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
607 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
609 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_settings.m_logFolder).c_str()))
611 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
612 CSpecialProtocol::TranslatePath(g_settings.m_logFolder).c_str());
616 // Init our DllLoaders emu env
619 g_settings.LoadProfiles(PROFILES_FILE);
621 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
622 #if defined(TARGET_DARWIN_OSX)
623 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
624 #elif defined(TARGET_DARWIN_IOS)
625 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
626 #elif defined(__FreeBSD__)
627 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
628 #elif defined(_LINUX)
629 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__);
630 #elif defined(_WIN32)
631 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);
632 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
633 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
634 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
635 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
638 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
639 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
641 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
643 CSpecialProtocol::LogPaths();
645 CStdString executable = CUtil::ResolveExecutablePath();
646 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
647 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
648 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str());
649 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
651 CStdString strExecutablePath;
652 CUtil::GetHomePath(strExecutablePath);
654 // if we are running from DVD our UserData location will be TDATA
655 if (URIUtils::IsDVD(strExecutablePath))
657 // TODO: Should we copy over any UserData folder from the DVD?
658 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
661 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
662 for (int i=0;i<items.Size();++i)
663 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
665 g_settings.m_logFolder = "special://masterprofile/";
669 g_xrandr.LoadCustomModeLinesToAllOutputs();
672 // for python scripts that check the OS
673 #if defined(TARGET_DARWIN)
674 setenv("OS","OS X",true);
675 #elif defined(_LINUX)
676 setenv("OS","Linux",true);
677 #elif defined(_WIN32)
678 SetEnvironmentVariable("OS","win32");
681 g_powerManager.Initialize();
683 // Load the AudioEngine before settings as they need to query the engine
684 if (!CAEFactory::LoadEngine())
686 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
690 CLog::Log(LOGNOTICE, "load settings...");
692 g_guiSettings.Initialize(); // Initialize default Settings - don't move
693 g_powerManager.SetDefaults();
694 if (!g_settings.Load())
696 CLog::Log(LOGFATAL, "%s: Failed to reset settings", __FUNCTION__);
700 CLog::Log(LOGINFO, "creating subdirectories");
701 CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
702 CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
703 CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
704 CDirectory::Create(g_settings.GetUserDataFolder());
705 CDirectory::Create(g_settings.GetProfileUserDataFolder());
706 g_settings.CreateProfileFolders();
708 update_emu_environ();//apply the GUI settings
710 // initialize our charset converter
711 g_charsetConverter.reset();
713 // Load the langinfo to have user charset <-> utf-8 conversion
714 CStdString strLanguage = g_guiSettings.GetString("locale.language");
715 strLanguage[0] = toupper(strLanguage[0]);
717 CStdString strLangInfoPath;
718 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
720 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
721 g_langInfo.Load(strLangInfoPath);
723 CStdString strLanguagePath = "special://xbmc/language/";
725 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
726 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
728 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
732 // start the AudioEngine
733 if (!CAEFactory::StartEngine())
735 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
739 // restore AE's previous volume state
740 SetHardwareVolume(g_settings.m_fVolumeLevel);
741 CAEFactory::SetMute (g_settings.m_bMute);
742 CAEFactory::SetSoundMode(g_guiSettings.GetInt("audiooutput.guisoundmode"));
744 // initialize the addon database (must be before the addon manager is init'd)
745 CDatabaseManager::Get().Initialize(true);
747 // start-up Addons Framework
748 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
749 if (!CAddonMgr::Get().Init())
751 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
755 g_peripherals.Initialise();
757 // Create the Mouse, Keyboard, Remote, and Joystick devices
758 // Initialize after loading settings to get joystick deadzone setting
759 g_Mouse.Initialize();
760 g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
762 g_Keyboard.Initialize();
763 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
764 g_RemoteControl.Initialize();
767 #if defined(TARGET_DARWIN_OSX)
768 // Configure and possible manually start the helper.
769 XBMCHelper::GetInstance().Configure();
772 CUtil::InitRandomSeed();
774 g_mediaManager.Initialize();
776 m_lastFrameTime = XbmcThreads::SystemClockMillis();
777 m_lastRenderTime = m_lastFrameTime;
781 bool CApplication::CreateGUI()
785 CLog::Log(LOGNOTICE, "Setup SDL");
787 /* Clean up on exit, exit on window close and interrupt */
790 uint32_t sdlFlags = 0;
792 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
793 sdlFlags |= SDL_INIT_VIDEO;
796 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
797 sdlFlags |= SDL_INIT_JOYSTICK;
800 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
801 //this might bring the monitor out of standby, so we have to disable it explicitly
802 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
803 #if defined(_LINUX) && !defined(TARGET_DARWIN)
804 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
810 // for nvidia cards - vsync currently ALWAYS enabled.
811 // the reason is that after screen has been setup changing this env var will make no difference.
812 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
813 setenv("__GL_YIELD", "USLEEP", 0);
816 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
817 g_Windowing.EnableSystemScreenSaver(false);
820 if (SDL_Init(sdlFlags) != 0)
822 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
825 #if defined(TARGET_DARWIN)
826 // SDL_Init will install a handler for segfaults, restore the default handler.
827 signal(SIGSEGV, SIG_DFL);
831 // Initialize core peripheral port support. Note: If these parameters
832 // are 0 and NULL, respectively, then the default number and types of
833 // controllers will be initialized.
834 if (!g_Windowing.InitWindowSystem())
836 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
840 // Retrieve the matching resolution based on GUI settings
841 g_guiSettings.m_LookAndFeelResolution = g_guiSettings.GetResolution();
842 CLog::Log(LOGNOTICE, "Checking resolution %i", g_guiSettings.m_LookAndFeelResolution);
843 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
845 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
846 g_guiSettings.SetResolution(RES_DESKTOP);
849 // update the window resolution
850 g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
852 if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
853 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
855 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
857 // Oh uh - doesn't look good for starting in their wanted screenmode
858 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
859 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
866 if (g_advancedSettings.m_splashImage)
868 CStdString strUserSplash = "special://home/media/Splash.png";
869 if (CFile::Exists(strUserSplash))
871 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
872 m_splash = new CSplash(strUserSplash);
876 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
877 m_splash = new CSplash("special://xbmc/media/Splash.png");
882 // The key mappings may already have been loaded by a peripheral
883 CLog::Log(LOGINFO, "load keymapping");
884 if (!CButtonTranslator::GetInstance().Load())
887 int iResolution = g_graphicsContext.GetVideoResolution();
888 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
889 g_settings.m_ResInfo[iResolution].iWidth,
890 g_settings.m_ResInfo[iResolution].iHeight,
891 g_settings.m_ResInfo[iResolution].strMode.c_str());
892 g_windowManager.Initialize();
897 bool CApplication::InitWindow()
899 #ifdef TARGET_DARWIN_OSX
900 // force initial window creation to be windowed, if fullscreen, it will switch to it below
901 // fixes the white screen of death if starting fullscreen and switching to windowed.
902 bool bFullScreen = false;
903 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
905 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
909 bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
910 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
912 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
917 if (!g_Windowing.InitRenderSystem())
919 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
922 // set GUI res and force the clear of the screen
923 g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
924 g_fontManager.ReloadTTFFonts();
928 bool CApplication::DestroyWindow()
930 g_fontManager.UnloadTTFFonts();
931 return g_Windowing.DestroyWindow();
934 bool CApplication::InitDirectoriesLinux()
937 The following is the directory mapping for Platform Specific Mode:
939 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
940 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
941 installations like skins, screensavers, etc.
943 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
944 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
945 mapped to special://home/userdata ($HOME/.xbmc/userdata)
946 special://profile/ => [read-write] current profile's userdata directory.
947 Generally special://masterprofile for the master profile or
948 special://masterprofile/profiles/<profile_name> for other profiles.
950 NOTE: All these root directories are lowercase. Some of the sub-directories
954 #if defined(_LINUX) && !defined(TARGET_DARWIN)
957 userName = getenv("USER");
963 userHome = getenv("HOME");
967 CStdString xbmcBinPath, xbmcPath;
968 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
969 xbmcPath = getenv("XBMC_HOME");
971 if (xbmcPath.IsEmpty())
973 xbmcPath = xbmcBinPath;
974 /* Check if xbmc binaries and arch independent data files are being kept in
975 * separate locations. */
976 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
978 /* Attempt to locate arch independent data files. */
979 CUtil::GetHomePath(xbmcPath);
980 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
982 fprintf(stderr, "Unable to find path to XBMC data files!\n");
988 /* Set some environment variables */
989 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
990 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
992 if (m_bPlatformDirectories)
994 // map our special drives
995 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
996 CSpecialProtocol::SetXBMCPath(xbmcPath);
997 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
998 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1000 CStdString strTempPath = userHome;
1001 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1002 if (getenv("XBMC_TEMP"))
1003 strTempPath = getenv("XBMC_TEMP");
1004 CSpecialProtocol::SetTempPath(strTempPath);
1006 URIUtils::AddSlashAtEnd(strTempPath);
1007 g_settings.m_logFolder = strTempPath;
1014 URIUtils::AddSlashAtEnd(xbmcPath);
1015 g_settings.m_logFolder = xbmcPath;
1017 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1018 CSpecialProtocol::SetXBMCPath(xbmcPath);
1019 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1020 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1022 CStdString strTempPath = xbmcPath;
1023 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1024 if (getenv("XBMC_TEMP"))
1025 strTempPath = getenv("XBMC_TEMP");
1026 CSpecialProtocol::SetTempPath(strTempPath);
1029 URIUtils::AddSlashAtEnd(strTempPath);
1030 g_settings.m_logFolder = strTempPath;
1039 bool CApplication::InitDirectoriesOSX()
1041 #if defined(TARGET_DARWIN)
1042 CStdString userName;
1044 userName = getenv("USER");
1048 CStdString userHome;
1050 userHome = getenv("HOME");
1054 CStdString xbmcPath;
1055 CUtil::GetHomePath(xbmcPath);
1056 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1058 #if defined(TARGET_DARWIN_IOS)
1059 CStdString fontconfigPath;
1060 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1061 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1064 // setup path to our internal dylibs so loader can find them
1065 CStdString frameworksPath = CUtil::GetFrameworksPath();
1066 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1068 // OSX always runs with m_bPlatformDirectories == true
1069 if (m_bPlatformDirectories)
1071 // map our special drives
1072 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1073 CSpecialProtocol::SetXBMCPath(xbmcPath);
1074 #if defined(TARGET_DARWIN_IOS)
1075 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
1076 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
1078 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1079 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1082 // location for temp files
1083 #if defined(TARGET_DARWIN_IOS)
1084 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
1086 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1087 CDirectory::Create(strTempPath);
1088 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1090 CSpecialProtocol::SetTempPath(strTempPath);
1092 // xbmc.log file location
1093 #if defined(TARGET_DARWIN_IOS)
1094 strTempPath = userHome + "/Library/Preferences";
1096 strTempPath = userHome + "/Library/Logs";
1098 URIUtils::AddSlashAtEnd(strTempPath);
1099 g_settings.m_logFolder = strTempPath;
1105 URIUtils::AddSlashAtEnd(xbmcPath);
1106 g_settings.m_logFolder = xbmcPath;
1108 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1109 CSpecialProtocol::SetXBMCPath(xbmcPath);
1110 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1111 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1113 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1114 CSpecialProtocol::SetTempPath(strTempPath);
1116 URIUtils::AddSlashAtEnd(strTempPath);
1117 g_settings.m_logFolder = strTempPath;
1126 bool CApplication::InitDirectoriesWin32()
1129 CStdString xbmcPath;
1131 CUtil::GetHomePath(xbmcPath);
1132 SetEnvironmentVariable("XBMC_HOME", xbmcPath.c_str());
1133 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1134 CSpecialProtocol::SetXBMCPath(xbmcPath);
1136 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1138 g_settings.m_logFolder = strWin32UserFolder;
1139 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1140 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1141 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1143 SetEnvironmentVariable("XBMC_PROFILE_USERDATA",CSpecialProtocol::TranslatePath("special://masterprofile/").c_str());
1147 // Expand the DLL search path with our directories
1148 CWIN32Util::ExtendDllPath();
1156 void CApplication::CreateUserDirs()
1158 CDirectory::Create("special://home/");
1159 CDirectory::Create("special://home/addons");
1160 CDirectory::Create("special://home/addons/packages");
1161 CDirectory::Create("special://home/media");
1162 CDirectory::Create("special://home/sounds");
1163 CDirectory::Create("special://home/system");
1164 CDirectory::Create("special://masterprofile/");
1165 CDirectory::Create("special://temp/");
1166 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1169 bool CApplication::Initialize()
1171 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1172 // turn off cdio logging
1173 cdio_loglevel_default = CDIO_LOG_ERROR;
1176 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1177 // must create these here. Ideally this should be using special://home/ and
1178 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1179 if (!m_bPlatformDirectories)
1182 CDirectory::Create("special://xbmc/language");
1183 CDirectory::Create("special://xbmc/addons");
1184 CDirectory::Create("special://xbmc/sounds");
1187 // Load curl so curl_global_init gets called before any service threads
1188 // are started. Unloading will have no effect as curl is never fully unloaded.
1189 // To quote man curl_global_init:
1190 // "This function is not thread safe. You must not call it when any other
1191 // thread in the program (i.e. a thread sharing the same memory) is running.
1192 // This doesn't just mean no other thread that is using libcurl. Because
1193 // curl_global_init() calls functions of other libraries that are similarly
1194 // thread unsafe, it could conflict with any other thread that
1195 // uses these other libraries."
1196 g_curlInterface.Load();
1197 g_curlInterface.Unload();
1199 // initialize (and update as needed) our databases
1200 CDatabaseManager::Get().Initialize();
1202 #ifdef HAS_WEB_SERVER
1203 CWebServer::RegisterRequestHandler(&m_httpImageHandler);
1204 CWebServer::RegisterRequestHandler(&m_httpVfsHandler);
1206 CWebServer::RegisterRequestHandler(&m_httpJsonRpcHandler);
1208 #ifdef HAS_WEB_INTERFACE
1209 CWebServer::RegisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
1210 CWebServer::RegisterRequestHandler(&m_httpWebinterfaceHandler);
1216 // Init DPMS, before creating the corresponding setting control.
1217 m_dpms = new DPMSSupport();
1218 if (g_windowManager.Initialized())
1220 g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1222 g_windowManager.Add(new CGUIWindowHome);
1223 g_windowManager.Add(new CGUIWindowPrograms);
1224 g_windowManager.Add(new CGUIWindowPictures);
1225 g_windowManager.Add(new CGUIWindowFileManager);
1226 g_windowManager.Add(new CGUIWindowSettings);
1227 g_windowManager.Add(new CGUIWindowSystemInfo);
1229 g_windowManager.Add(new CGUIWindowTestPatternGL);
1232 g_windowManager.Add(new CGUIWindowTestPatternDX);
1234 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1235 g_windowManager.Add(new CGUIWindowSettingsCategory);
1236 g_windowManager.Add(new CGUIWindowVideoNav);
1237 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1238 g_windowManager.Add(new CGUIWindowLoginScreen);
1239 g_windowManager.Add(new CGUIWindowSettingsProfile);
1240 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1241 g_windowManager.Add(new CGUIWindowAddonBrowser);
1242 g_windowManager.Add(new CGUIWindowScreensaverDim);
1243 g_windowManager.Add(new CGUIWindowDebugInfo);
1244 g_windowManager.Add(new CGUIWindowPointer);
1245 g_windowManager.Add(new CGUIDialogYesNo);
1246 g_windowManager.Add(new CGUIDialogProgress);
1247 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1248 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1249 g_windowManager.Add(new CGUIDialogVolumeBar);
1250 g_windowManager.Add(new CGUIDialogSeekBar);
1251 g_windowManager.Add(new CGUIDialogSubMenu);
1252 g_windowManager.Add(new CGUIDialogContextMenu);
1253 g_windowManager.Add(new CGUIDialogKaiToast);
1254 g_windowManager.Add(new CGUIDialogNumeric);
1255 g_windowManager.Add(new CGUIDialogGamepad);
1256 g_windowManager.Add(new CGUIDialogButtonMenu);
1257 g_windowManager.Add(new CGUIDialogMuteBug);
1258 g_windowManager.Add(new CGUIDialogPlayerControls);
1260 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1261 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1263 g_windowManager.Add(new CGUIDialogSlider);
1264 g_windowManager.Add(new CGUIDialogMusicOSD);
1265 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1266 g_windowManager.Add(new CGUIDialogVideoSettings);
1267 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1268 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1269 // Don't add the filebrowser dialog - it's created and added when it's needed
1270 g_windowManager.Add(new CGUIDialogNetworkSetup);
1271 g_windowManager.Add(new CGUIDialogMediaSource);
1272 g_windowManager.Add(new CGUIDialogProfileSettings);
1273 g_windowManager.Add(new CGUIDialogFavourites);
1274 g_windowManager.Add(new CGUIDialogSongInfo);
1275 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1276 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1277 g_windowManager.Add(new CGUIDialogBusy);
1278 g_windowManager.Add(new CGUIDialogPictureInfo);
1279 g_windowManager.Add(new CGUIDialogAddonInfo);
1280 g_windowManager.Add(new CGUIDialogAddonSettings);
1281 #ifdef HAS_LINUX_NETWORK
1282 g_windowManager.Add(new CGUIDialogAccessPoints);
1285 g_windowManager.Add(new CGUIDialogLockSettings);
1287 g_windowManager.Add(new CGUIDialogContentSettings);
1289 g_windowManager.Add(new CGUIDialogPlayEject);
1291 g_windowManager.Add(new CGUIDialogPeripheralManager);
1292 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1294 g_windowManager.Add(new CGUIDialogMediaFilter);
1296 g_windowManager.Add(new CGUIWindowMusicPlayList);
1297 g_windowManager.Add(new CGUIWindowMusicSongs);
1298 g_windowManager.Add(new CGUIWindowMusicNav);
1299 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1301 /* Load PVR related Windows and Dialogs */
1302 g_windowManager.Add(new CGUIDialogTeletext);
1303 g_windowManager.Add(new CGUIWindowPVR);
1304 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1305 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1306 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1307 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1308 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1309 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1310 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1311 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1312 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1313 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1315 g_windowManager.Add(new CGUIDialogSelect);
1316 g_windowManager.Add(new CGUIDialogMusicInfo);
1317 g_windowManager.Add(new CGUIDialogOK);
1318 g_windowManager.Add(new CGUIDialogVideoInfo);
1319 g_windowManager.Add(new CGUIDialogTextViewer);
1320 g_windowManager.Add(new CGUIWindowFullScreen);
1321 g_windowManager.Add(new CGUIWindowVisualisation);
1322 g_windowManager.Add(new CGUIWindowSlideShow);
1323 g_windowManager.Add(new CGUIDialogFileStacking);
1325 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1328 g_windowManager.Add(new CGUIDialogVideoOSD);
1329 g_windowManager.Add(new CGUIDialogMusicOverlay);
1330 g_windowManager.Add(new CGUIDialogVideoOverlay);
1331 g_windowManager.Add(new CGUIWindowScreensaver);
1332 g_windowManager.Add(new CGUIWindowWeather);
1333 g_windowManager.Add(new CGUIWindowStartup);
1335 /* window id's 3000 - 3100 are reserved for python */
1337 // Make sure we have at least the default skin
1338 if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
1340 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
1344 if (g_advancedSettings.m_splashImage)
1345 SAFE_DELETE(m_splash);
1347 if (g_guiSettings.GetBool("masterlock.startuplock") &&
1348 g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1349 !g_settings.GetMasterProfile().getLockCode().IsEmpty())
1351 g_passwordManager.CheckStartUpLock();
1354 // check if we should use the login screen
1355 if (g_settings.UsingLoginScreen())
1356 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1360 CJSONRPC::Initialize();
1362 ADDON::CAddonMgr::Get().StartServices(false);
1363 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1365 g_windowManager.ActivateWindow(WINDOW_HOME);
1366 StartPVRManager(true);
1370 StartPVRManager(false);
1371 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1376 else //No GUI Created
1379 CJSONRPC::Initialize();
1381 ADDON::CAddonMgr::Get().StartServices(false);
1384 g_sysinfo.Refresh();
1386 CLog::Log(LOGINFO, "removing tempfiles");
1387 CUtil::RemoveTempFiles();
1389 if (!g_settings.UsingLoginScreen())
1393 g_pythonParser.m_bLogin = true;
1397 m_slowTimer.StartZero();
1399 #if defined(HAVE_LIBCRYSTALHD)
1400 CCrystalHD::GetInstance();
1403 CAddonMgr::Get().StartServices(true);
1405 CLog::Log(LOGNOTICE, "initialize done");
1407 m_bInitializing = false;
1409 // reset our screensaver (starts timers etc.)
1412 #ifdef HAS_SDL_JOYSTICK
1413 g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick") &&
1414 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1420 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1423 bool oldSetting = false;
1428 oldSetting = g_guiSettings.GetBool("services.webserver");
1429 g_guiSettings.SetBool("services.webserver", bStart);
1432 ret = StartWebServer();
1438 g_guiSettings.SetBool("services.webserver", oldSetting);
1441 case ES_AIRPLAYSERVER:
1442 oldSetting = g_guiSettings.GetBool("services.airplay");
1443 g_guiSettings.SetBool("services.airplay", bStart);
1446 ret = StartAirplayServer();
1448 StopAirplayServer(bWait);
1452 g_guiSettings.SetBool("services.airplay", oldSetting);
1455 case ES_JSONRPCSERVER:
1456 oldSetting = g_guiSettings.GetBool("services.esenabled");
1457 g_guiSettings.SetBool("services.esenabled", bStart);
1460 ret = StartJSONRPCServer();
1462 StopJSONRPCServer(bWait);
1466 g_guiSettings.SetBool("services.esenabled", oldSetting);
1470 g_guiSettings.SetBool("services.upnpserver", bStart);
1476 case ES_UPNPRENDERER:
1477 g_guiSettings.SetBool("services.upnprenderer", bStart);
1479 StartUPnPRenderer();
1483 case ES_EVENTSERVER:
1484 oldSetting = g_guiSettings.GetBool("services.esenabled");
1485 g_guiSettings.SetBool("services.esenabled", bStart);
1488 ret = StartEventServer();
1490 StopEventServer(bWait, false);
1494 g_guiSettings.SetBool("services.esenabled", oldSetting);
1499 g_guiSettings.SetBool("services.zeroconf", bStart);
1514 bool CApplication::StartWebServer()
1516 #ifdef HAS_WEB_SERVER
1517 if (g_guiSettings.GetBool("services.webserver") && m_network->IsAvailable())
1519 int webPort = atoi(g_guiSettings.GetString("services.webserverport"));
1520 CLog::Log(LOGNOTICE, "Webserver: Starting...");
1522 if (webPort < 1024 && !CUtil::CanBindPrivileged())
1524 CLog::Log(LOGERROR, "Cannot start Web Server on port %i, no permission to bind to ports below 1024", webPort);
1529 bool started = false;
1530 if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")))
1532 std::vector<std::pair<std::string, std::string> > txt;
1534 // publish web frontend and API services
1535 #ifdef HAS_WEB_INTERFACE
1536 CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1539 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1550 void CApplication::StopWebServer()
1552 #ifdef HAS_WEB_SERVER
1553 if (m_WebServer.IsStarted())
1555 CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1557 if(! m_WebServer.IsStarted() )
1559 CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1560 CZeroconf::GetInstance()->RemoveService("servers.webserver");
1561 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http");
1562 CZeroconf::GetInstance()->RemoveService("servers.webapi");
1564 CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
1569 bool CApplication::StartAirplayServer()
1573 if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable())
1575 int listenPort = g_advancedSettings.m_airPlayPort;
1576 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1577 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1579 if (CAirPlayServer::StartServer(listenPort, true))
1581 CAirPlayServer::SetCredentials(usePassword, password);
1582 std::vector<std::pair<std::string, std::string> > txt;
1583 CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
1586 txt.push_back(std::make_pair("deviceid", iface->GetMacAddress()));
1590 txt.push_back(std::make_pair("deviceid", "FF:FF:FF:FF:FF:F2"));
1592 txt.push_back(std::make_pair("features", "0x77"));
1593 txt.push_back(std::make_pair("model", "AppleTV2,1"));
1594 txt.push_back(std::make_pair("srcvers", AIRPLAY_SERVER_VERSION_STR));
1595 CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt);
1603 if (g_guiSettings.GetBool("services.airplay") && m_network->IsAvailable())
1605 int listenPort = g_advancedSettings.m_airTunesPort;
1606 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1607 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1609 if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password))
1611 CLog::Log(LOGERROR, "Failed to start AirTunes Server");
1620 void CApplication::StopAirplayServer(bool bWait)
1623 CAirPlayServer::StopServer(bWait);
1624 CZeroconf::GetInstance()->RemoveService("servers.airplay");
1627 CAirTunesServer::StopServer(bWait);
1631 bool CApplication::StartJSONRPCServer()
1634 if (g_guiSettings.GetBool("services.esenabled"))
1636 if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces")))
1638 std::vector<std::pair<std::string, std::string> > txt;
1639 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt);
1650 void CApplication::StopJSONRPCServer(bool bWait)
1653 CTCPServer::StopServer(bWait);
1654 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp");
1658 void CApplication::StartUPnP()
1663 StartUPnPRenderer();
1667 void CApplication::StopUPnP(bool bWait)
1670 if (UPNP::CUPnP::IsInstantiated())
1672 CLog::Log(LOGNOTICE, "stopping upnp");
1673 UPNP::CUPnP::ReleaseInstance(bWait);
1678 bool CApplication::StartEventServer()
1680 #ifdef HAS_EVENT_SERVER
1681 CEventServer* server = CEventServer::GetInstance();
1684 CLog::Log(LOGERROR, "ES: Out of memory");
1687 if (g_guiSettings.GetBool("services.esenabled"))
1689 CLog::Log(LOGNOTICE, "ES: Starting event server");
1690 server->StartServer();
1697 bool CApplication::StopEventServer(bool bWait, bool promptuser)
1699 #ifdef HAS_EVENT_SERVER
1700 CEventServer* server = CEventServer::GetInstance();
1703 CLog::Log(LOGERROR, "ES: Out of memory");
1708 if (server->GetNumberOfClients() > 0)
1710 bool cancelled = false;
1711 if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1712 -1, -1, cancelled, 10000)
1715 CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1719 CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1721 CEventServer::GetInstance()->StopServer(true);
1726 CLog::Log(LOGNOTICE, "ES: Stopping event server");
1728 CEventServer::GetInstance()->StopServer(bWait);
1735 void CApplication::RefreshEventServer()
1737 #ifdef HAS_EVENT_SERVER
1738 if (g_guiSettings.GetBool("services.esenabled"))
1740 CEventServer::GetInstance()->RefreshSettings();
1745 void CApplication::StartUPnPClient()
1748 if (g_guiSettings.GetBool("services.upnpcontroller"))
1750 CLog::Log(LOGNOTICE, "starting upnp client");
1751 UPNP::CUPnP::GetInstance()->StartClient();
1756 void CApplication::StopUPnPClient()
1759 if (UPNP::CUPnP::IsInstantiated())
1761 CLog::Log(LOGNOTICE, "stopping upnp client");
1762 UPNP::CUPnP::GetInstance()->StopClient();
1767 void CApplication::StartUPnPRenderer()
1770 if (g_guiSettings.GetBool("services.upnprenderer"))
1772 CLog::Log(LOGNOTICE, "starting upnp renderer");
1773 UPNP::CUPnP::GetInstance()->StartRenderer();
1778 void CApplication::StopUPnPRenderer()
1781 if (UPNP::CUPnP::IsInstantiated())
1783 CLog::Log(LOGNOTICE, "stopping upnp renderer");
1784 UPNP::CUPnP::GetInstance()->StopRenderer();
1789 void CApplication::StartUPnPServer()
1792 if (g_guiSettings.GetBool("services.upnpserver"))
1794 CLog::Log(LOGNOTICE, "starting upnp server");
1795 UPNP::CUPnP::GetInstance()->StartServer();
1800 void CApplication::StopUPnPServer()
1803 if (UPNP::CUPnP::IsInstantiated())
1805 CLog::Log(LOGNOTICE, "stopping upnp server");
1806 UPNP::CUPnP::GetInstance()->StopServer();
1811 void CApplication::StartZeroconf()
1814 //entry in guisetting only present if HAS_ZEROCONF is set
1815 if(g_guiSettings.GetBool("services.zeroconf"))
1817 CLog::Log(LOGNOTICE, "starting zeroconf publishing");
1818 CZeroconf::GetInstance()->Start();
1823 void CApplication::StopZeroconf()
1826 if(CZeroconf::IsInstantiated())
1828 CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
1829 CZeroconf::GetInstance()->Stop();
1834 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1836 if (g_guiSettings.GetBool("pvrmanager.enabled"))
1837 g_PVRManager.Start(true, bOpenPVRWindow);
1840 void CApplication::StopPVRManager()
1842 CLog::Log(LOGINFO, "stopping PVRManager");
1843 if (g_PVRManager.IsPlaying())
1845 g_PVRManager.Stop();
1846 g_EpgContainer.Stop();
1849 void CApplication::StartServices()
1851 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1852 // Start Thread for DVD Mediatype detection
1853 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1854 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1857 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1858 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1859 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistShuffle);
1860 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1861 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistShuffle);
1862 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1865 void CApplication::StopServices()
1867 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1869 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1870 CLog::Log(LOGNOTICE, "stop dvd detect media");
1871 m_DetectDVDType.StopThread();
1874 g_peripherals.Clear();
1877 void CApplication::ReloadSkin()
1879 m_skinReloading = false;
1880 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1881 g_windowManager.SendMessage(msg);
1883 // Reload the skin, restoring the previously focused control. We need this as
1884 // the window unload will reset all control states.
1886 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1888 iCtrlID = pWindow->GetFocusedControlID();
1890 g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1894 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1895 if (pWindow && pWindow->HasSaveLastControl())
1897 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1898 pWindow->OnMessage(msg3);
1903 bool CApplication::LoadSkin(const CStdString& skinID)
1905 if (m_skinReloading)
1909 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1911 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1917 void CApplication::LoadSkin(const SkinPtr& skin)
1921 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN);
1922 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1923 LoadSkin(DEFAULT_SKIN);
1928 if (!skin->HasSkinFile("Home.xml"))
1930 // failed to find home.xml
1931 // fallback to default skin
1932 if (strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
1934 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
1935 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1936 LoadSkin(DEFAULT_SKIN);
1937 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1942 bool bPreviousPlayingState=false;
1943 bool bPreviousRenderingState=false;
1944 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1946 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1947 if (bPreviousPlayingState)
1948 g_application.m_pPlayer->Pause();
1949 #ifdef HAS_VIDEO_PLAYBACK
1950 if (!g_renderManager.Paused())
1952 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1954 g_windowManager.ActivateWindow(WINDOW_HOME);
1955 bPreviousRenderingState = true;
1960 // close the music and video overlays (they're re-opened automatically later)
1961 CSingleLock lock(g_graphicsContext);
1963 // save the current window details
1964 int currentWindow = g_windowManager.GetActiveWindow();
1965 vector<int> currentModelessWindows;
1966 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1970 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1972 g_SkinInfo->Start();
1974 CLog::Log(LOGINFO, " load fonts for skin...");
1975 g_graphicsContext.SetMediaDir(skin->Path());
1976 g_directoryCache.ClearSubPaths(skin->Path());
1977 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1979 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1980 CStdString strFontSet;
1981 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1983 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1984 g_guiSettings.SetString("lookandfeel.font", strFontSet);
1988 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1990 g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1992 g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1994 // load in the skin strings
1995 CStdString langPath;
1996 URIUtils::AddFileToFolder(skin->Path(), "language", langPath);
1997 URIUtils::AddSlashAtEnd(langPath);
1999 g_localizeStrings.LoadSkinStrings(langPath, g_guiSettings.GetString("locale.language"));
2001 g_SkinInfo->LoadIncludes();
2004 start = CurrentHostCounter();
2006 CLog::Log(LOGINFO, " load new skin...");
2008 // Load the user windows
2012 end = CurrentHostCounter();
2013 freq = CurrentHostFrequency();
2014 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
2016 CLog::Log(LOGINFO, " initialize new skin...");
2017 g_windowManager.AddMsgTarget(this);
2018 g_windowManager.AddMsgTarget(&g_playlistPlayer);
2019 g_windowManager.AddMsgTarget(&g_infoManager);
2020 g_windowManager.AddMsgTarget(&g_fontManager);
2021 g_windowManager.SetCallback(*this);
2022 g_windowManager.Initialize();
2023 CTextureCache::Get().Initialize();
2024 g_audioManager.Enable(true);
2025 g_audioManager.Load();
2027 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
2028 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2030 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2031 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2032 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2033 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2034 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2037 CLog::Log(LOGINFO, " skin loaded...");
2039 // leave the graphics lock
2043 if (currentWindow != WINDOW_INVALID)
2045 g_windowManager.ActivateWindow(currentWindow);
2046 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2048 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2049 if (dialog) dialog->Show();
2053 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
2055 if (bPreviousPlayingState)
2056 g_application.m_pPlayer->Pause();
2057 if (bPreviousRenderingState)
2058 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2062 void CApplication::UnloadSkin(bool forReload /* = false */)
2064 m_skinReloading = forReload;
2066 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2068 g_audioManager.Enable(false);
2070 g_windowManager.DeInitialize();
2071 CTextureCache::Get().Deinitialize();
2073 // remove the skin-dependent window
2074 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2076 g_TextureManager.Cleanup();
2077 g_largeTextureManager.CleanupUnusedImages(true);
2079 g_fontManager.Clear();
2081 g_colorManager.Clear();
2083 g_charsetConverter.reset();
2085 g_infoManager.Clear();
2087 // The g_SkinInfo boost shared_ptr ought to be reset here
2088 // but there are too many places it's used without checking for NULL
2089 // and as a result a race condition on exit can cause a crash.
2092 bool CApplication::LoadUserWindows()
2094 // Start from wherever home.xml is
2095 std::vector<CStdString> vecSkinPath;
2096 g_SkinInfo->GetSkinPaths(vecSkinPath);
2097 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2099 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2100 CFileItemList items;
2101 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2103 for (int i = 0; i < items.Size(); ++i)
2105 if (items[i]->m_bIsFolder)
2107 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2108 if (skinFile.Left(6).CompareNoCase("custom") == 0)
2110 CXBMCTinyXML xmlDoc;
2111 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2113 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2117 // Root element should be <window>
2118 TiXmlElement* pRootElement = xmlDoc.RootElement();
2119 CStdString strValue = pRootElement->Value();
2120 if (!strValue.Equals("window"))
2122 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2126 // Read the <type> element to get the window type to create
2127 // If no type is specified, create a CGUIWindow as default
2128 CGUIWindow* pWindow = NULL;
2130 if (pRootElement->Attribute("type"))
2131 strType = pRootElement->Attribute("type");
2134 const TiXmlNode *pType = pRootElement->FirstChild("type");
2135 if (pType && pType->FirstChild())
2136 strType = pType->FirstChild()->Value();
2138 int id = WINDOW_INVALID;
2139 if (!pRootElement->Attribute("id", &id))
2141 const TiXmlNode *pType = pRootElement->FirstChild("id");
2142 if (pType && pType->FirstChild())
2143 id = atol(pType->FirstChild()->Value());
2145 CStdString visibleCondition;
2146 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2148 if (strType.Equals("dialog"))
2149 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2150 else if (strType.Equals("submenu"))
2151 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2152 else if (strType.Equals("buttonmenu"))
2153 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2155 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2157 // Check to make sure the pointer isn't still null
2158 if (pWindow == NULL)
2160 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2163 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2168 pWindow->SetVisibleCondition(visibleCondition);
2169 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2170 g_windowManager.AddCustomWindow(pWindow);
2178 bool CApplication::RenderNoPresent()
2182 // DXMERGE: This may have been important?
2183 // g_graphicsContext.AcquireCurrentContext();
2185 g_graphicsContext.Lock();
2187 // dont show GUI when playing full screen video
2188 if (g_graphicsContext.IsFullScreenVideo())
2190 if (m_bPresentFrame && IsPlaying() && !IsPaused())
2193 g_renderManager.Present();
2196 g_renderManager.RenderUpdate(true);
2198 // close window overlays
2199 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2200 if (overlay) overlay->Close(true);
2201 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2202 if (overlay) overlay->Close(true);
2206 bool hasRendered = g_windowManager.Render();
2208 g_graphicsContext.Unlock();
2213 float CApplication::GetDimScreenSaverLevel() const
2215 if (!m_bScreenSave || !m_screenSaver ||
2216 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2217 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2218 !m_screenSaver->ID().empty()))
2221 if (!m_screenSaver->GetSetting("level").IsEmpty())
2222 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2226 bool CApplication::WaitFrame(unsigned int timeout)
2230 // Wait for all other frames to be presented
2231 CSingleLock lock(m_frameMutex);
2232 //wait until event is set, but modify remaining time
2234 TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
2235 cv.wait(lock,timeout);
2236 done = m_frameCount == 0;
2241 void CApplication::NewFrame()
2243 // We just posted another frame. Keep track and notify.
2245 CSingleLock lock(m_frameMutex);
2249 m_frameCond.notifyAll();
2252 void CApplication::Render()
2254 // do not render if we are stopped
2258 if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
2267 int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
2269 bool decrement = false;
2270 bool hasRendered = false;
2271 bool limitFrames = false;
2272 unsigned int singleFrameTime = 10; // default limit 100 fps
2276 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2277 // Whether externalplayer is playing and we're unfocused
2278 bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
2280 m_bPresentFrame = false;
2281 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
2283 CSingleLock lock(m_frameMutex);
2285 TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
2288 m_bPresentFrame = m_frameCount > 0;
2289 decrement = m_bPresentFrame;
2294 // engage the frame limiter as needed
2295 limitFrames = lowfps || extPlayerActive;
2296 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2297 // perhaps allowing it to be set differently than the UI option??
2298 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2299 limitFrames = true; // not using vsync.
2300 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2301 limitFrames = true; // using vsync, but it isn't working.
2305 if (extPlayerActive)
2307 ResetScreenSaver(); // Prevent screensaver dimming the screen
2308 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2311 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2318 CSingleLock lock(g_graphicsContext);
2319 g_infoManager.UpdateFPS();
2321 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2322 g_Windowing.SetVSync(true);
2323 else if (vsync_mode == VSYNC_ALWAYS)
2324 g_Windowing.SetVSync(true);
2325 else if (vsync_mode != VSYNC_DRIVER)
2326 g_Windowing.SetVSync(false);
2328 if(!g_Windowing.BeginRender())
2331 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2332 if (RenderNoPresent())
2335 g_Windowing.EndRender();
2337 // reset our info cache - we do this at the end of Render so that it is
2338 // fresh for the next process(), or after a windowclose animation (where process()
2340 g_infoManager.ResetCache();
2343 unsigned int now = XbmcThreads::SystemClockMillis();
2345 m_lastRenderTime = now;
2347 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2348 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2350 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2351 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2355 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2356 if (limitFrames || !flip)
2359 singleFrameTime = 40; //if not flipping, loop at 25 fps
2361 unsigned int frameTime = now - m_lastFrameTime;
2362 if (frameTime < singleFrameTime)
2363 Sleep(singleFrameTime - frameTime);
2365 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2368 g_graphicsContext.Flip(dirtyRegions);
2369 CTimeUtils::UpdateFrameTime(flip);
2371 g_TextureManager.FreeUnusedTextures();
2373 g_renderManager.UpdateResolution();
2374 g_renderManager.ManageCaptures();
2377 CSingleLock lock(m_frameMutex);
2378 if(m_frameCount > 0 && decrement)
2381 m_frameCond.notifyAll();
2384 void CApplication::SetStandAlone(bool value)
2386 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2389 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2390 // The window manager will return true if the event is processed, false otherwise.
2391 // If not already processed, this routine handles global keypresses. It returns
2392 // true if the key has been processed, false otherwise.
2394 bool CApplication::OnKey(const CKey& key)
2397 // Turn the mouse off, as we've just got a keypress from controller or remote
2398 g_Mouse.SetActive(false);
2400 // get the current active window
2401 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2403 // this will be checked for certain keycodes that need
2404 // special handling if the screensaver is active
2405 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2407 // a key has been pressed.
2409 m_idleTimer.StartZero();
2410 bool processKey = AlwaysProcess(action);
2414 // allow some keys to be processed while the screensaver is active
2415 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2417 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2421 // change this if we have a dialog up
2422 if (g_windowManager.HasModalDialog())
2424 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2426 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2427 { // fullscreen info dialog - special case
2428 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2430 if (!key.IsAnalogButton())
2431 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2433 if (OnAction(action))
2436 // fallthrough to the main window
2437 iWin = WINDOW_FULLSCREEN_VIDEO;
2439 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2441 // current active window is full screen video.
2442 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2444 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2445 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2447 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2449 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2450 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2452 // if no PVR specific action/mapping is found, fall back to default
2453 if (action.GetID() == 0)
2454 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2458 // in any other case use the fullscreen window section of keymap.xml to map key->action
2459 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2464 // current active window isnt the fullscreen window
2465 // just use corresponding section from keymap.xml
2466 // to map key->action
2468 // first determine if we should use keyboard input directly
2469 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2470 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2473 CGUIControl *control = window->GetFocusedControl();
2476 // If this is an edit control set usekeyboard to true. This causes the
2477 // keypress to be processed directly not through the key mappings.
2478 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2481 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2482 // This causes the keypress to be used for list navigation.
2483 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2489 action = CAction(0); // reset our action
2490 if (g_guiSettings.GetBool("input.remoteaskeyboard"))
2492 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2493 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2494 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2495 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2496 action.GetID() == ACTION_MOVE_RIGHT ||
2497 action.GetID() == ACTION_MOVE_UP ||
2498 action.GetID() == ACTION_MOVE_DOWN ||
2499 action.GetID() == ACTION_SELECT_ITEM ||
2500 action.GetID() == ACTION_ENTER ||
2501 action.GetID() == ACTION_PREVIOUS_MENU ||
2502 action.GetID() == ACTION_NAV_BACK))
2504 // the action isn't plain navigation - check for a keyboard-specific keymap
2505 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2506 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2507 action.GetID() == ACTION_BACKSPACE ||
2508 action.GetID() == ACTION_SHIFT ||
2509 action.GetID() == ACTION_SYMBOLS ||
2510 action.GetID() == ACTION_CURSOR_LEFT ||
2511 action.GetID() == ACTION_CURSOR_RIGHT)
2512 action = CAction(0); // don't bother with this action
2515 if (!action.GetID())
2517 // keyboard entry - pass the keys through directly
2518 if (key.GetFromService())
2519 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2521 { // see if we've got an ascii key
2522 if (key.GetUnicode())
2523 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2525 action = CAction(key.GetVKey() | KEY_VKEY);
2529 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2531 if (OnAction(action))
2533 // failed to handle the keyboard action, drop down through to standard action
2535 if (key.GetFromService())
2537 if (key.GetButtonCode() != KEY_INVALID)
2538 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2541 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2543 if (!key.IsAnalogButton())
2544 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2546 return ExecuteInputAction(action);
2549 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2550 // This needs to return true if it processed the appcommand or false if it didn't
2551 bool CApplication::OnAppCommand(const CAction &action)
2553 // Reset the screen saver
2556 // If we were currently in the screen saver wake up and don't process the appcommand
2557 if (WakeUpScreenSaverAndDPMS())
2560 // The action ID is the APPCOMMAND code. We need to retrieve the action
2561 // associated with this appcommand from the mapping table.
2562 uint32_t appcmd = action.GetID();
2563 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2564 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2565 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2567 // If we couldn't find an action return false to indicate we have not
2568 // handled this appcommand
2569 if (!appcmdaction.GetID())
2571 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2575 // Process the appcommand
2576 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2577 OnAction(appcmdaction);
2579 // Always return true regardless of whether the action succeeded or not.
2580 // This stops Windows handling the appcommand itself.
2584 bool CApplication::OnAction(const CAction &action)
2586 // special case for switching between GUI & fullscreen mode.
2587 if (action.GetID() == ACTION_SHOW_GUI)
2588 { // Switch to fullscreen mode if we can
2589 if (SwitchToFullScreen())
2591 m_navigationTimer.StartZero();
2596 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2598 g_graphicsContext.ToggleFullScreenRoot();
2602 if (action.IsMouse())
2603 g_Mouse.SetActive(true);
2605 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2606 // playing or ACTION_PLAYER_PLAY if we are not playing.
2607 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2610 return OnAction(CAction(ACTION_PAUSE));
2612 return OnAction(CAction(ACTION_PLAYER_PLAY));
2615 //if the action would start or stop inertial scrolling
2616 //by gesture - bypass the normal OnAction handler of current window
2617 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2620 // just pass the action to the current window and let it handle it
2621 if (g_windowManager.OnAction(action))
2623 m_navigationTimer.StartZero();
2628 // handle extra global presses
2630 // screenshot : take a screenshot :)
2631 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2633 CScreenShot::TakeScreenshot();
2636 // built in functions : execute the built-in
2637 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2639 CBuiltins::Execute(action.GetName());
2640 m_navigationTimer.StartZero();
2645 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2647 CButtonTranslator::GetInstance().Clear();
2648 CButtonTranslator::GetInstance().Load();
2651 // show info : Shows the current video or song information
2652 if (action.GetID() == ACTION_SHOW_INFO)
2654 g_infoManager.ToggleShowInfo();
2658 // codec info : Shows the current song, video or picture codec information
2659 if (action.GetID() == ACTION_SHOW_CODEC)
2661 g_infoManager.ToggleShowCodec();
2665 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2667 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2670 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2671 char rating = tag->GetRating();
2672 bool needsUpdate(false);
2673 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2675 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2678 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2680 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2686 if (db.Open()) // OpenForWrite() ?
2688 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2691 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2692 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2693 g_windowManager.SendMessage(msg);
2699 // stop : stops playing current audio song
2700 if (action.GetID() == ACTION_STOP)
2706 // previous : play previous song from playlist
2707 if (action.GetID() == ACTION_PREV_ITEM)
2709 // first check whether we're within 3 seconds of the start of the track
2710 // if not, we just revert to the start of the track
2711 if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2718 g_playlistPlayer.PlayPrevious();
2723 // next : play next song from playlist
2724 if (action.GetID() == ACTION_NEXT_ITEM)
2726 if (IsPlaying() && m_pPlayer->SkipNext())
2732 g_playlistPlayer.PlayNext();
2739 // forward channel switches to the player - he knows what to do
2740 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2742 m_pPlayer->OnAction(action);
2746 // pause : pauses current audio song
2747 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2751 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2753 if (!m_pPlayer->IsPaused())
2754 { // unpaused - set the playspeed back to normal
2757 g_audioManager.Enable(m_pPlayer->IsPaused());
2760 if (!m_pPlayer->IsPaused())
2762 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2763 // if we are playing at normal speed, then allow play to pause
2764 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2766 if (m_iPlaySpeed != 1)
2776 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2778 int iPlaySpeed = m_iPlaySpeed;
2779 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2781 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2783 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2788 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2790 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2793 SetPlaySpeed(iPlaySpeed);
2796 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2798 // calculate the speed based on the amount the button is held down
2799 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2800 // returns 0 -> MAX_FFWD_SPEED
2801 int iSpeed = 1 << iPower;
2802 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2804 g_application.SetPlaySpeed(iSpeed);
2806 CLog::Log(LOGDEBUG,"Resetting playspeed");
2810 // allow play to unpause
2813 if (action.GetID() == ACTION_PLAYER_PLAY)
2815 // unpause, and set the playspeed back to normal
2817 g_audioManager.Enable(m_pPlayer->IsPaused());
2819 g_application.SetPlaySpeed(1);
2826 if (action.GetID() == ACTION_SWITCH_PLAYER)
2830 VECPLAYERCORES cores;
2831 CFileItem item(*m_itemCurrentFile.get());
2832 CPlayerCoreFactory::GetPlayers(item, cores);
2833 PLAYERCOREID core = CPlayerCoreFactory::SelectPlayerDialog(cores);
2834 if(core != EPC_NONE)
2836 g_application.m_eForcedNextPlayer = core;
2837 item.m_lStartOffset = GetTime() * 75;
2838 PlayFile(item, true);
2843 VECPLAYERCORES cores;
2844 CPlayerCoreFactory::GetRemotePlayers(cores);
2845 PLAYERCOREID core = CPlayerCoreFactory::SelectPlayerDialog(cores);
2846 if(core != EPC_NONE)
2849 g_application.m_eForcedNextPlayer = core;
2850 PlayFile(item, false);
2855 if (g_peripherals.OnAction(action))
2858 if (action.GetID() == ACTION_MUTE)
2864 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2866 switch(g_guiSettings.GetInt("audiooutput.mode"))
2868 case AUDIO_ANALOG: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958); break;
2869 case AUDIO_IEC958: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); break;
2870 case AUDIO_HDMI : g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG); break;
2873 g_application.Restart();
2874 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2876 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2877 g_windowManager.SendMessage(msg);
2882 // Check for global volume control
2883 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2885 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2887 if (g_settings.m_bMute)
2889 float volume = g_settings.m_fVolumeLevel;
2890 // Android has steps based on the max available volume level
2891 #if defined(TARGET_ANDROID)
2892 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2894 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2896 if (action.GetRepeat())
2897 step *= action.GetRepeat() * 50; // 50 fps
2899 if (action.GetID() == ACTION_VOLUME_UP)
2900 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2902 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2903 SetVolume(volume, false);
2905 // show visual feedback of volume change...
2906 ShowVolumeBar(&action);
2909 // Check for global seek control
2910 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2912 if (!m_pPlayer->CanSeek()) return false;
2913 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2916 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2918 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2919 CGUIControlProfiler::Instance().Start();
2922 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2924 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2925 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2926 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2927 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2928 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2934 void CApplication::FrameMove(bool processEvents, bool processGUI)
2940 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2941 float frameTime = m_frameTime.GetElapsedSeconds();
2942 m_frameTime.StartZero();
2943 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2944 if( frameTime > 0.5 ) frameTime = 0.5;
2946 if (processGUI && m_renderGUI)
2948 g_graphicsContext.Lock();
2949 // check if there are notifications to display
2950 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2951 if (toast && toast->DoWork())
2953 if (!toast->IsDialogRunning())
2958 g_graphicsContext.Unlock();
2959 CWinEvents::MessagePump();
2962 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2963 // Read the input from a remote
2964 g_RemoteControl.Update();
2967 // process input actions
2968 ProcessRemote(frameTime);
2969 ProcessGamepad(frameTime);
2970 ProcessEventServer(frameTime);
2971 ProcessPeripherals(frameTime);
2972 if (processGUI && m_renderGUI)
2974 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2975 m_seekHandler->Process();
2978 if (processGUI && m_renderGUI)
2981 g_windowManager.Process(CTimeUtils::GetFrameTime());
2982 g_windowManager.FrameMove();
2986 bool CApplication::ProcessGamepad(float frameTime)
2988 #ifdef HAS_SDL_JOYSTICK
2992 int iWin = GetActiveWindowID();
2994 g_Joystick.Update();
2995 if (g_Joystick.GetButton(bid))
2998 m_idleTimer.StartZero();
3001 if (WakeUpScreenSaverAndDPMS())
3003 g_Joystick.Reset(true);
3008 CStdString actionName;
3010 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3012 CAction action(actionID, 1.0f, 0.0f, actionName);
3014 g_Mouse.SetActive(false);
3015 return ExecuteInputAction(action);
3022 if (g_Joystick.GetAxis(bid))
3024 if (g_Joystick.GetAmount() < 0)
3030 CStdString actionName;
3032 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3035 if (WakeUpScreenSaverAndDPMS())
3040 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3042 g_Mouse.SetActive(false);
3043 return ExecuteInputAction(action);
3047 g_Joystick.ResetAxis(abs(bid));
3051 if (g_Joystick.GetHat(bid, position))
3054 m_idleTimer.StartZero();
3057 if (WakeUpScreenSaverAndDPMS())
3064 CStdString actionName;
3067 bid = position<<16|bid;
3069 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3071 CAction action(actionID, 1.0f, 0.0f, actionName);
3073 g_Mouse.SetActive(false);
3074 return ExecuteInputAction(action);
3081 bool CApplication::ProcessRemote(float frameTime)
3083 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3084 if (g_RemoteControl.GetButton())
3086 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3087 g_RemoteControl.Reset();
3094 bool CApplication::ProcessPeripherals(float frameTime)
3097 if (g_peripherals.GetNextKeypress(frameTime, key))
3102 bool CApplication::ProcessMouse()
3106 if (!g_Mouse.IsActive() || !m_AppFocused)
3109 // Get the mouse command ID
3110 uint32_t mousecommand = g_Mouse.GetAction();
3111 if (mousecommand == ACTION_NOOP)
3114 // Reset the screensaver and idle timers
3115 m_idleTimer.StartZero();
3117 if (WakeUpScreenSaverAndDPMS())
3120 // Retrieve the corresponding action
3121 int iWin = GetActiveWindowID();
3122 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3123 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3125 // If we couldn't find an action return false to indicate we have not
3126 // handled this mouse action
3127 if (!mouseaction.GetID())
3129 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3133 // Log mouse actions except for move and noop
3134 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3135 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3137 // The action might not be a mouse action. For example wheel moves might
3138 // be mapped to volume up/down in mouse.xml. In this case we do not want
3139 // the mouse position saved in the action.
3140 if (!mouseaction.IsMouse())
3141 return OnAction(mouseaction);
3143 // This is a mouse action so we need to record the mouse position
3144 return OnAction(CAction(mouseaction.GetID(),
3145 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3146 (float)g_Mouse.GetX(),
3147 (float)g_Mouse.GetY(),
3148 (float)g_Mouse.GetDX(),
3149 (float)g_Mouse.GetDY(),
3150 mouseaction.GetName()));
3153 bool CApplication::ProcessEventServer(float frameTime)
3155 #ifdef HAS_EVENT_SERVER
3156 CEventServer* es = CEventServer::GetInstance();
3157 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3160 // process any queued up actions
3161 if (es->ExecuteNextAction())
3163 // reset idle timers
3164 m_idleTimer.StartZero();
3166 WakeUpScreenSaverAndDPMS();
3169 // now handle any buttons or axis
3170 std::string joystickName;
3171 bool isAxis = false;
3172 float fAmount = 0.0;
3174 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3175 // when the action exits XBMC
3176 es = CEventServer::GetInstance();
3177 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3179 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3183 if (joystickName.length() > 0)
3187 if (fabs(fAmount) >= 0.08)
3188 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3190 m_lastAxisMap[joystickName].erase(wKeyID);
3193 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
3198 if (wKeyID & ES_FLAG_UNICODE)
3200 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3204 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3205 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3206 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3207 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3208 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3209 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3210 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3211 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3213 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3214 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3215 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3216 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3217 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3219 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3221 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3222 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3223 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3226 key.SetFromService(true);
3231 if (m_lastAxisMap.size() > 0)
3233 // Process all the stored axis.
3234 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3236 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3237 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3243 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3244 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3250 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount, unsigned int holdTime /*=0*/)
3252 #if defined(HAS_EVENT_SERVER)
3253 m_idleTimer.StartZero();
3255 // Make sure to reset screen saver, mouse.
3257 if (WakeUpScreenSaverAndDPMS())
3260 #ifdef HAS_SDL_JOYSTICK
3263 g_Mouse.SetActive(false);
3265 int iWin = GetActiveWindowID();
3267 CStdString actionName;
3268 bool fullRange = false;
3270 // Translate using regular joystick translator.
3271 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3272 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3274 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3280 bool CApplication::ExecuteInputAction(CAction action)
3282 bool bResult = false;
3284 // play sound before the action unless the button is held,
3285 // where we execute after the action as held actions aren't fired every time.
3286 if(action.GetHoldTime())
3288 bResult = OnAction(action);
3290 g_audioManager.PlayActionSound(action);
3294 g_audioManager.PlayActionSound(action);
3295 bResult = OnAction(action);
3300 int CApplication::GetActiveWindowID(void)
3302 // Get the currently active window
3303 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3305 // If there is a dialog active get the dialog id instead
3306 if (g_windowManager.HasModalDialog())
3307 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3309 // If the window is FullScreenVideo check for special cases
3310 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3312 // check if we're in a DVD menu
3313 if(g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
3314 iWin = WINDOW_VIDEO_MENU;
3315 // check for LiveTV and switch to it's virtual window
3316 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3317 iWin = WINDOW_FULLSCREEN_LIVETV;
3320 // Return the window id
3324 bool CApplication::Cleanup()
3328 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3329 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3330 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3331 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3332 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3333 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3334 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3335 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3336 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3337 g_windowManager.Delete(WINDOW_FILES);
3338 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3339 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3340 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3341 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3342 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3343 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3344 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3345 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3346 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3347 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3348 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3349 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3350 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3351 g_windowManager.Delete(WINDOW_DIALOG_OK);
3352 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3353 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3354 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3355 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3356 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3357 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3358 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3359 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3360 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3361 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3362 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3363 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3364 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3365 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3366 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3367 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3368 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3369 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3370 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3371 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3372 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3373 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3375 /* Delete PVR related windows and dialogs */
3376 g_windowManager.Delete(WINDOW_PVR);
3377 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3378 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3379 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3380 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3381 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3382 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3383 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3387 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3388 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3389 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3391 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3392 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3393 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3394 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3395 g_windowManager.Delete(WINDOW_VISUALISATION);
3396 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3397 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3398 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3399 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3400 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3401 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3402 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3403 g_windowManager.Delete(WINDOW_SCREENSAVER);
3404 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3405 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3406 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3407 g_windowManager.Delete(WINDOW_SLIDESHOW);
3408 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3409 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3411 g_windowManager.Delete(WINDOW_HOME);
3412 g_windowManager.Delete(WINDOW_PROGRAMS);
3413 g_windowManager.Delete(WINDOW_PICTURES);
3414 g_windowManager.Delete(WINDOW_WEATHER);
3416 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3417 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3418 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3419 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3420 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3421 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3422 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3423 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3424 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3425 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3427 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3428 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3430 CAddonMgr::Get().DeInit();
3432 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3433 CLog::Log(LOGNOTICE, "closing down remote control service");
3434 g_RemoteControl.Disconnect();
3437 CLog::Log(LOGNOTICE, "unload sections");
3439 #ifdef HAS_PERFORMANCE_SAMPLE
3440 CLog::Log(LOGNOTICE, "performance statistics");
3441 m_perfStats.DumpStats();
3444 // Shutdown as much as possible of the
3445 // application, to reduce the leaks dumped
3446 // to the vc output window before calling
3447 // _CrtDumpMemoryLeaks(). Most of the leaks
3448 // shown are no real leaks, as parts of the app
3449 // are still allocated.
3451 g_localizeStrings.Clear();
3452 g_LangCodeExpander.Clear();
3453 g_charsetConverter.clear();
3454 g_directoryCache.Clear();
3455 CButtonTranslator::GetInstance().Clear();
3456 CLastfmScrobbler::RemoveInstance();
3457 CLibrefmScrobbler::RemoveInstance();
3458 CLastFmManager::RemoveInstance();
3459 #ifdef HAS_EVENT_SERVER
3460 CEventServer::RemoveInstance();
3462 DllLoaderContainer::Clear();
3463 g_playlistPlayer.Clear();
3465 g_guiSettings.Clear();
3466 g_advancedSettings.Clear();
3469 CXHandle::DumpObjectTracker();
3471 #ifdef HAS_DVD_DRIVE
3472 CLibcdio::ReleaseInstance();
3475 #if defined(TARGET_ANDROID)
3476 // enable for all platforms once it's safe
3477 g_sectionLoader.UnloadAll();
3479 #ifdef _CRTDBG_MAP_ALLOC
3480 _CrtDumpMemoryLeaks();
3481 while(1); // execution ends
3491 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3496 void CApplication::Stop(int exitCode)
3500 CVariant vExitCode(exitCode);
3501 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3503 SaveFileState(true);
3505 // cancel any jobs from the jobmanager
3506 CJobManager::GetInstance().CancelJobs();
3508 g_alarmClock.StopThread();
3510 if( m_bSystemScreenSaverEnable )
3511 g_Windowing.EnableSystemScreenSaver(true);
3513 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3514 g_settings.m_iSystemTimeTotalUp = g_settings.m_iSystemTimeTotalUp + (int)(CTimeUtils::GetFrameTime() / 60000);
3516 // Update the settings information (volume, uptime etc. need saving)
3517 if (CFile::Exists(g_settings.GetSettingsFile()))
3519 CLog::Log(LOGNOTICE, "Saving settings");
3523 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3526 m_AppActive = false;
3527 m_AppFocused = false;
3528 m_ExitCode = exitCode;
3529 CLog::Log(LOGNOTICE, "stop all");
3531 // stop scanning before we kill the network and so on
3532 if (m_musicInfoScanner->IsScanning())
3533 m_musicInfoScanner->Stop();
3535 if (m_videoInfoScanner->IsScanning())
3536 m_videoInfoScanner->Stop();
3538 CApplicationMessenger::Get().Cleanup();
3544 #ifdef HAS_WEB_SERVER
3545 CWebServer::UnregisterRequestHandler(&m_httpImageHandler);
3546 CWebServer::UnregisterRequestHandler(&m_httpVfsHandler);
3548 CWebServer::UnregisterRequestHandler(&m_httpJsonRpcHandler);
3549 CJSONRPC::Cleanup();
3551 #ifdef HAS_WEB_INTERFACE
3552 CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
3553 CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceHandler);
3559 CLog::Log(LOGNOTICE, "stop player");
3564 #if HAS_FILESYTEM_DAAP
3565 CLog::Log(LOGNOTICE, "stop daap clients");
3566 g_DaapClient.Release();
3568 #ifdef HAS_FILESYSTEM_SAP
3569 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3570 g_sapsessions.StopThread();
3573 if(CZeroconfBrowser::IsInstantiated())
3575 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3576 CZeroconfBrowser::GetInstance()->Stop();
3577 CZeroconfBrowser::ReleaseInstance();
3581 CLog::Log(LOGNOTICE, "clean cached files!");
3582 #ifdef HAS_FILESYSTEM_RAR
3583 g_RarManager.ClearCache(true);
3586 #ifdef HAS_FILESYSTEM_SFTP
3587 CSFTPSessionManager::DisconnectAllSessions();
3590 CLog::Log(LOGNOTICE, "unload skin");
3593 #if defined(TARGET_DARWIN_OSX)
3594 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3595 XBMCHelper::GetInstance().Stop();
3598 #if defined(HAVE_LIBCRYSTALHD)
3599 CCrystalHD::RemoveInstance();
3602 g_mediaManager.Stop();
3604 // Stop services before unloading Python
3605 CAddonMgr::Get().StopServices(false);
3607 /* Python resource freeing must be done after skin has been unloaded, not before
3608 some windows still need it when deinitializing during skin unloading. */
3610 CLog::Log(LOGNOTICE, "stop python");
3611 g_pythonParser.FreeResources();
3613 g_Windowing.DestroyRenderSystem();
3614 g_Windowing.DestroyWindow();
3615 g_Windowing.DestroyWindowSystem();
3617 // shutdown the AudioEngine
3618 CAEFactory::Shutdown();
3619 CAEFactory::UnLoadEngine();
3621 CLog::Log(LOGNOTICE, "stopped");
3625 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3628 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3629 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3636 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3638 //If item is a plugin, expand out now and run ourselves again
3639 if (item.IsPlugin())
3641 CFileItem item_new(item);
3642 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3643 return PlayMedia(item_new, iPlaylist);
3646 if (item.IsLastFM())
3648 g_partyModeManager.Disable();
3649 return CLastFmManager::GetInstance()->ChangeStation(item.GetAsUrl());
3651 if (item.IsSmartPlayList())
3653 CFileItemList items;
3654 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3657 CSmartPlaylist smartpl;
3658 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3659 smartpl.OpenAndReadName(item.GetPath());
3661 playlist.Add(items);
3662 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3665 else if (item.IsPlayList() || item.IsInternetStream())
3667 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3669 //is or could be a playlist
3670 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3671 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3676 if (dlgCache->IsCanceled())
3683 if (iPlaylist != PLAYLIST_NONE)
3686 if (item.HasProperty("playlist_starting_track"))
3687 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3688 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3692 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());
3693 if(pPlayList->size())
3694 return PlayFile(*(*pPlayList)[0], false);
3699 //nothing special just play
3700 return PlayFile(item, false);
3704 // For playing a multi-file video. Particularly inefficient
3705 // on startup, as we are required to calculate the length
3706 // of each video, so we open + close each one in turn.
3707 // A faster calculation of video time would improve this
3709 bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3711 if (!item.IsStack())
3716 // case 1: stacked ISOs
3717 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3719 CStackDirectory dir;
3720 CFileItemList movieList;
3721 dir.GetDirectory(item.GetPath(), movieList);
3723 // first assume values passed to the stack
3724 int selectedFile = item.m_lStartPartNumber;
3725 int startoffset = item.m_lStartOffset;
3727 // check if we instructed the stack to resume from default
3728 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3733 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3735 startoffset = (int)(bookmark.timeInSeconds*75);
3736 selectedFile = bookmark.partNumber;
3741 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3744 // make sure that the selected part is within the boundaries
3745 if (selectedFile <= 0)
3747 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3750 else if (selectedFile > movieList.Size())
3752 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3753 selectedFile = movieList.Size();
3756 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3757 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3758 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3759 *m_stackFileItemToUpdate = item;
3760 return PlayFile(*(movieList[selectedFile - 1]));
3762 // case 2: all other stacks
3765 // see if we have the info in the database
3766 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3767 // then these times will be wrong.
3768 // Also, this is really just a hack for the slow load up times we have
3769 // A much better solution is a fast reader of FPS and fileLength
3770 // that we can use on a file to get it's time.
3772 bool haveTimes(false);
3776 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3777 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3782 // calculate the total time of the stack
3783 CStackDirectory dir;
3784 dir.GetDirectory(item.GetPath(), *m_currentStack);
3786 for (int i = 0; i < m_currentStack->Size(); i++)
3789 (*m_currentStack)[i]->m_lEndOffset = times[i];
3793 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3795 m_currentStack->Clear();
3798 totalTime += duration / 1000;
3799 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3800 times.push_back(totalTime);
3804 double seconds = item.m_lStartOffset / 75.0;
3806 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3807 { // have our times now, so update the dB
3811 dbs.SetStackTimes(item.GetPath(), times);
3813 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3815 // can only resume seek here, not dvdstate
3817 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3818 seconds = bookmark.timeInSeconds;
3826 *m_itemCurrentFile = item;
3827 m_currentStackPosition = 0;
3828 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3832 // work out where to seek to
3833 for (int i = 0; i < m_currentStack->Size(); i++)
3835 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3837 CFileItem item(*(*m_currentStack)[i]);
3838 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3839 item.m_lStartOffset = (long)(seconds - start) * 75;
3840 m_currentStackPosition = i;
3841 return PlayFile(item, true);
3846 return PlayFile(*(*m_currentStack)[0], true);
3851 bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
3855 SaveCurrentFileSettings();
3857 OutputDebugString("new file set audiostream:0\n");
3858 // Switch to default options
3859 g_settings.m_currentVideoSettings = g_settings.m_defaultVideoSettings;
3860 // see if we have saved options in the database
3863 m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3865 *m_itemCurrentFile = item;
3866 m_nextPlaylistItem = -1;
3867 m_currentStackPosition = 0;
3868 m_currentStack->Clear();
3871 CUtil::ClearSubtitles();
3874 if (item.IsDiscStub())
3876 #ifdef HAS_DVD_DRIVE
3877 // Display the Play Eject dialog if there is any optical disc drive
3878 if (g_mediaManager.HasOpticalDrive())
3880 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3881 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3882 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3883 return MEDIA_DETECT::CAutorun::PlayDiscAskResume();
3887 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3892 if (item.IsPlayList())
3895 if (item.IsPlugin())
3896 { // we modify the item so that it becomes a real URL
3897 CFileItem item_new(item);
3898 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3899 return PlayFile(item_new, false);
3904 if (URIUtils::IsUPnP(item.GetPath()))
3906 CFileItem item_new(item);
3907 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3908 return PlayFile(item_new, false);
3913 // if we have a stacked set of files, we need to setup our stack routines for
3914 // "seamless" seeking and total time of the movie etc.
3915 // will recall with restart set to true
3917 return PlayStack(item, bRestart);
3919 //Is TuxBox, this should probably be moved to CTuxBoxFile
3922 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3924 if(g_tuxboxService.IsRunning())
3925 g_tuxboxService.Stop();
3928 if(g_tuxbox.CreateNewItem(item, item_new))
3931 // Make sure it doesn't have a player
3932 // so we actually select one normally
3933 m_eCurrentPlayer = EPC_NONE;
3935 // keep the tuxbox:// url as playing url
3936 // and give the new url to the player
3937 if(PlayFile(item_new, true))
3939 if(!g_tuxboxService.IsRunning())
3940 g_tuxboxService.Start();
3947 CPlayerOptions options;
3949 if( item.HasProperty("StartPercent") )
3951 double fallback = 0.0f;
3952 if(item.GetProperty("StartPercent").isString())
3953 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3954 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3957 PLAYERCOREID eNewCore = EPC_NONE;
3960 // have to be set here due to playstack using this for starting the file
3961 options.starttime = item.m_lStartOffset / 75.0;
3962 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3963 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3965 if( m_eForcedNextPlayer != EPC_NONE )
3966 eNewCore = m_eForcedNextPlayer;
3967 else if( m_eCurrentPlayer == EPC_NONE )
3968 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3970 eNewCore = m_eCurrentPlayer;
3974 options.starttime = item.m_lStartOffset / 75.0;
3978 // open the d/b and retrieve the bookmarks for the current movie
3981 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3983 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3985 options.starttime = 0.0f;
3987 CStdString path = item.GetPath();
3988 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3989 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3990 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3991 path = item.GetProperty("original_listitem_url").asString();
3992 if(dbs.GetResumeBookMark(path, bookmark))
3994 options.starttime = bookmark.timeInSeconds;
3995 options.state = bookmark.playerState;
3998 override with information from the actual item if available. We do this as the VFS (eg plugins)
3999 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4000 should the playerState be required, it is fetched from the database.
4001 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4003 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
4004 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
4006 else if (item.HasVideoInfoTag())
4008 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4010 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4013 dbs.GetBookMarkForEpisode(*tag, bookmark);
4014 options.starttime = bookmark.timeInSeconds;
4015 options.state = bookmark.playerState;
4022 if (m_eForcedNextPlayer != EPC_NONE)
4023 eNewCore = m_eForcedNextPlayer;
4025 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
4028 // this really aught to be inside !bRestart, but since PlayStack
4029 // uses that to init playback, we have to keep it outside
4030 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4031 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4032 { // playing from a playlist by the looks
4033 // don't switch to fullscreen if we are not playing the first item...
4034 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4036 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4038 // TODO - this will fail if user seeks back to first file in stack
4039 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4040 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4042 options.fullscreen = false;
4043 // reset this so we don't think we are resuming on seek
4044 m_itemCurrentFile->m_lStartOffset = 0;
4047 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4049 // reset m_bStartVideoWindowed as it's a temp setting
4050 g_settings.m_bStartVideoWindowed = false;
4053 //We have to stop parsing a cdg before mplayer is deallocated
4054 // WHY do we have to do this????
4056 m_pKaraokeMgr->Stop();
4059 // tell system we are starting a file
4060 m_bPlaybackStarting = true;
4062 // We should restart the player, unless the previous and next tracks are using
4063 // one of the players that allows gapless playback (paplayer, dvdplayer)
4066 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER
4067 #if defined(HAS_OMXPLAYER)
4068 || m_eCurrentPlayer == EPC_OMXPLAYER
4079 m_eCurrentPlayer = eNewCore;
4080 m_pPlayer = CPlayerCoreFactory::CreatePlayer(eNewCore, *this);
4086 // don't hold graphicscontext here since player
4087 // may wait on another thread, that requires gfx
4088 CSingleExit ex(g_graphicsContext);
4089 bResult = m_pPlayer->OpenFile(item, options);
4093 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4099 if (m_iPlaySpeed != 1)
4101 int iSpeed = m_iPlaySpeed;
4103 SetPlaySpeed(iSpeed);
4106 // if player has volume control, set it.
4107 if (m_pPlayer && m_pPlayer->ControlsVolume())
4109 m_pPlayer->SetVolume(g_settings.m_fVolumeLevel);
4110 m_pPlayer->SetMute(g_settings.m_bMute);
4113 if( IsPlayingAudio() )
4115 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4116 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4119 #ifdef HAS_VIDEO_PLAYBACK
4120 else if( IsPlayingVideo() )
4122 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4123 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4125 // if player didn't manange to switch to fullscreen by itself do it here
4126 if( options.fullscreen && g_renderManager.IsStarted()
4127 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4128 SwitchToFullScreen();
4130 if (!item.IsDVDImage() && !item.IsDVDFile())
4132 CVideoInfoTag *details = m_itemCurrentFile->GetVideoInfoTag();
4133 // Save information about the stream if we currently have no data
4134 if (!details->HasStreamDetails() ||
4135 details->m_streamDetails.GetVideoDuration() <= 0)
4137 if (m_pPlayer->GetStreamDetails(details->m_streamDetails) && details->HasStreamDetails())
4141 dbs.SetStreamDetailsForFileId(details->m_streamDetails, details->m_iFileId);
4143 CUtil::DeleteVideoDatabaseDirectoryCache();
4151 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4152 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4153 g_windowManager.PreviousWindow();
4157 #if !defined(TARGET_DARWIN) && !defined(_LINUX)
4158 g_audioManager.Enable(false);
4161 if (item.HasPVRChannelInfoTag())
4162 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4164 m_bPlaybackStarting = false;
4168 // we must have started, otherwise player might send this later
4170 OnPlayBackStarted();
4176 // we send this if it isn't playlistplayer that is doing this
4177 int next = g_playlistPlayer.GetNextSong();
4178 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4181 OnPlayBackStopped();
4187 void CApplication::OnPlayBackEnded()
4189 if(m_bPlaybackStarting)
4192 if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4193 CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
4195 // informs python script currently running playback has ended
4196 // (does nothing if python is not loaded)
4198 g_pythonParser.OnPlayBackEnded();
4201 CVariant data(CVariant::VariantTypeObject);
4203 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4205 if (IsPlayingAudio())
4207 CLastfmScrobbler::GetInstance()->SubmitQueue();
4208 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4211 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4212 g_windowManager.SendThreadMessage(msg);
4215 void CApplication::OnPlayBackStarted()
4217 if(m_bPlaybackStarting)
4220 if (!CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4221 CJobManager::GetInstance().Pause(kJobTypeMediaFlags);
4224 // informs python script currently running playback has started
4225 // (does nothing if python is not loaded)
4226 g_pythonParser.OnPlayBackStarted();
4229 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4230 g_windowManager.SendThreadMessage(msg);
4233 void CApplication::OnQueueNextItem()
4235 // informs python script currently running that we are requesting the next track
4236 // (does nothing if python is not loaded)
4238 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4241 if(IsPlayingAudio())
4243 CLastfmScrobbler::GetInstance()->SubmitQueue();
4244 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4247 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4248 g_windowManager.SendThreadMessage(msg);
4251 void CApplication::OnPlayBackStopped()
4253 if(m_bPlaybackStarting)
4256 if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4257 CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
4259 // informs python script currently running playback has ended
4260 // (does nothing if python is not loaded)
4262 g_pythonParser.OnPlayBackStopped();
4265 CVariant data(CVariant::VariantTypeObject);
4266 data["end"] = false;
4267 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4269 CLastfmScrobbler::GetInstance()->SubmitQueue();
4270 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4272 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4273 g_windowManager.SendThreadMessage(msg);
4276 void CApplication::OnPlayBackPaused()
4279 g_pythonParser.OnPlayBackPaused();
4283 param["player"]["speed"] = 0;
4284 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4285 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4288 void CApplication::OnPlayBackResumed()
4291 g_pythonParser.OnPlayBackResumed();
4295 param["player"]["speed"] = 1;
4296 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4297 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4300 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4303 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4307 param["player"]["speed"] = iSpeed;
4308 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4309 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4312 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4315 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4319 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4320 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4321 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4322 param["player"]["speed"] = GetPlaySpeed();
4323 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4324 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4327 void CApplication::OnPlayBackSeekChapter(int iChapter)
4330 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4334 bool CApplication::IsPlaying() const
4338 if (!m_pPlayer->IsPlaying())
4343 bool CApplication::IsPaused() const
4347 if (!m_pPlayer->IsPlaying())
4349 return m_pPlayer->IsPaused();
4352 bool CApplication::IsPlayingAudio() const
4356 if (!m_pPlayer->IsPlaying())
4358 if (m_pPlayer->HasVideo())
4360 if (m_pPlayer->HasAudio())
4365 bool CApplication::IsPlayingVideo() const
4369 if (!m_pPlayer->IsPlaying())
4371 if (m_pPlayer->HasVideo())
4377 bool CApplication::IsPlayingFullScreenVideo() const
4379 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4382 bool CApplication::IsFullScreen()
4384 return IsPlayingFullScreenVideo() ||
4385 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4386 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4389 void CApplication::SaveFileState(bool bForeground /* = false */)
4391 if (m_progressTrackingItem->IsPVRChannel() || !g_settings.GetCurrentProfile().canWriteDatabases())
4396 CSaveFileStateJob job(*m_progressTrackingItem,
4397 *m_stackFileItemToUpdate,
4398 m_progressTrackingVideoResumeBookmark,
4399 m_progressTrackingPlayCountUpdate);
4401 // Run job in the foreground to make sure it finishes
4406 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4407 *m_stackFileItemToUpdate,
4408 m_progressTrackingVideoResumeBookmark,
4409 m_progressTrackingPlayCountUpdate);
4410 CJobManager::GetInstance().AddJob(job, NULL);
4414 void CApplication::UpdateFileState()
4416 // Did the file change?
4417 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4421 // Reset tracking item
4422 m_progressTrackingItem->Reset();
4428 if (m_progressTrackingItem->GetPath() == "")
4431 *m_progressTrackingItem = CurrentFileItem();
4432 m_progressTrackingPlayCountUpdate = false;
4435 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4436 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4437 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4438 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4440 m_progressTrackingPlayCountUpdate = true;
4443 if (m_progressTrackingItem->IsVideo())
4445 if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60*1000)
4447 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset();
4448 m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails);
4450 // Update bookmark for save
4451 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::GetPlayerName(m_eCurrentPlayer);
4452 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4453 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4455 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4456 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4458 // Delete the bookmark
4459 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4462 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4464 // Update the bookmark
4465 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4466 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4471 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4478 void CApplication::StopPlaying()
4480 int iWin = g_windowManager.GetActiveWindow();
4485 m_pKaraokeMgr->Stop();
4488 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4489 g_PVRManager.SaveCurrentChannelSettings();
4492 m_pPlayer->CloseFile();
4494 // turn off visualisation window when stopping
4495 if ((iWin == WINDOW_VISUALISATION
4496 || iWin == WINDOW_FULLSCREEN_VIDEO)
4498 g_windowManager.PreviousWindow();
4500 g_partyModeManager.Disable();
4504 void CApplication::ResetSystemIdleTimer()
4506 // reset system idle timer
4507 m_idleTimer.StartZero();
4510 void CApplication::ResetScreenSaver()
4513 m_shutdownTimer.StartZero();
4515 // screen saver timer is reset only if we're not already in screensaver or
4517 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4518 ResetScreenSaverTimer();
4521 void CApplication::ResetScreenSaverTimer()
4523 m_screenSaverTimer.StartZero();
4526 void CApplication::StopScreenSaverTimer()
4528 m_screenSaverTimer.Stop();
4531 bool CApplication::ToggleDPMS(bool manual)
4533 if (manual || (m_dpmsIsManual == manual))
4537 m_dpmsIsActive = false;
4538 m_dpmsIsManual = false;
4539 return m_dpms->DisablePowerSaving();
4543 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4545 m_dpmsIsActive = true;
4546 m_dpmsIsManual = manual;
4554 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4558 // First reset DPMS, if active
4563 // TODO: if screensaver lock is specified but screensaver is not active
4564 // (DPMS came first), activate screensaver now.
4566 ResetScreenSaverTimer();
4567 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4570 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4574 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4575 CVariant data(bPowerOffKeyPressed);
4576 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4582 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4584 if (m_iScreenSaveLock == 2)
4587 // if Screen saver is active
4588 if (m_bScreenSave && m_screenSaver)
4590 if (m_iScreenSaveLock == 0)
4591 if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4592 (g_settings.UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) &&
4593 g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4594 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4596 m_iScreenSaveLock = 2;
4597 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4599 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4601 pWindow->OnMessage(msg);
4603 if (m_iScreenSaveLock == -1)
4605 m_iScreenSaveLock = 0;
4609 // disable screensaver
4610 m_bScreenSave = false;
4611 m_iScreenSaveLock = 0;
4612 ResetScreenSaverTimer();
4614 if (m_screenSaver->ID() == "visualization")
4616 // we can just continue as usual from vis mode
4619 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4621 else if (!m_screenSaver->ID().IsEmpty())
4622 { // we're in screensaver window
4623 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4624 g_windowManager.PreviousWindow(); // show the previous window
4625 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4626 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4634 void CApplication::CheckScreenSaverAndDPMS()
4636 if (!m_dpmsIsActive)
4637 g_Windowing.ResetOSScreensaver();
4639 bool maybeScreensaver =
4640 !m_dpmsIsActive && !m_bScreenSave
4641 && !g_guiSettings.GetString("screensaver.mode").IsEmpty();
4643 !m_dpmsIsActive && m_dpms->IsSupported()
4644 && g_guiSettings.GetInt("powermanagement.displaysoff") > 0;
4646 // Has the screen saver window become active?
4647 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4649 m_bScreenSave = true;
4650 maybeScreensaver = false;
4653 if (m_bScreenSave && IsPlayingVideo() && !m_pPlayer->IsPaused())
4655 WakeUpScreenSaverAndDPMS();
4659 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4661 // See if we need to reset timer.
4662 // * Are we playing a video and it is not paused?
4663 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4664 // * Are we playing some music in fullscreen vis?
4665 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4666 && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()))
4668 ResetScreenSaverTimer();
4672 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4674 // DPMS has priority (it makes the screensaver not needed)
4676 && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60)
4679 WakeUpScreenSaver();
4681 else if (maybeScreensaver
4682 && elapsed > g_guiSettings.GetInt("screensaver.time") * 60)
4684 ActivateScreenSaver();
4688 // activate the screensaver.
4689 // if forceType is true, we ignore the various conditions that can alter
4690 // the type of screensaver displayed
4691 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4693 m_bScreenSave = true;
4695 // Get Screensaver Mode
4696 m_screenSaver.reset();
4697 if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver))
4698 m_screenSaver.reset(new CScreenSaver(""));
4700 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4702 // disable screensaver lock from the login screen
4703 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4706 // set to Dim in the case of a dialog on screen or playing video
4707 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4709 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4710 m_screenSaver.reset(new CScreenSaver(""));
4712 // Check if we are Playing Audio and Vis instead Screensaver!
4713 else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())
4714 { // activate the visualisation
4715 m_screenSaver.reset(new CScreenSaver("visualization"));
4716 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4720 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4722 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4724 else if (!m_screenSaver->ID().IsEmpty())
4725 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4728 void CApplication::CheckShutdown()
4730 // first check if we should reset the timer
4731 bool resetTimer = m_bInhibitIdleShutdown;
4733 if (IsPlaying() || IsPaused()) // is something playing?
4736 if (m_musicInfoScanner->IsScanning())
4739 if (m_videoInfoScanner->IsScanning())
4742 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4745 if (g_guiSettings.GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4750 m_shutdownTimer.StartZero();
4754 if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 )
4756 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4757 m_shutdownTimer.Stop();
4760 CApplicationMessenger::Get().Shutdown();
4764 void CApplication::InhibitIdleShutdown(bool inhibit)
4766 m_bInhibitIdleShutdown = inhibit;
4769 bool CApplication::IsIdleShutdownInhibited() const
4771 return m_bInhibitIdleShutdown;
4774 bool CApplication::OnMessage(CGUIMessage& message)
4776 switch ( message.GetMessage() )
4778 case GUI_MSG_NOTIFY_ALL:
4780 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4782 // Update general playlist: Remove DVD playlist items
4783 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4786 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4787 g_windowManager.SendMessage( msg );
4789 // stop the file if it's on dvd (will set the resume point etc)
4790 if (m_itemCurrentFile->IsOnDVD())
4796 case GUI_MSG_PLAYBACK_STARTED:
4798 #ifdef TARGET_DARWIN
4799 DarwinSetScheduling(message.GetMessage());
4801 // reset the seek handler
4802 m_seekHandler->Reset();
4803 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4805 // Update our infoManager with the new details etc.
4806 if (m_nextPlaylistItem >= 0)
4808 // playing an item which is not in the list - player might be stopped already
4810 if (playList.size() <= m_nextPlaylistItem)
4813 // we've started a previously queued item
4814 CFileItemPtr item = playList[m_nextPlaylistItem];
4815 // update the playlist manager
4816 int currentSong = g_playlistPlayer.GetCurrentSong();
4817 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4818 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4819 g_windowManager.SendThreadMessage(msg);
4820 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4821 *m_itemCurrentFile = *item;
4823 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4824 CLastFmManager::GetInstance()->OnSongChange(*m_itemCurrentFile);
4825 g_partyModeManager.OnSongChange(true);
4828 param["player"]["speed"] = 1;
4829 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4830 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4832 if (IsPlayingAudio())
4834 // Start our cdg parser as appropriate
4836 if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4838 m_pKaraokeMgr->Stop();
4839 if (m_itemCurrentFile->IsMusicDb())
4841 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4843 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4844 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4847 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4850 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4853 // Let scrobbler know about the track
4854 const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag();
4857 CLastfmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4858 CLibrefmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4866 case GUI_MSG_QUEUE_NEXT_ITEM:
4868 // Check to see if our playlist player has a new item for us,
4869 // and if so, we check whether our current player wants the file
4870 int iNext = g_playlistPlayer.GetNextSong();
4871 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4872 if (iNext < 0 || iNext >= playlist.size())
4874 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4875 return true; // nothing to do
4878 // ok, grab the next song
4879 CFileItem file(*playlist[iNext]);
4881 CURL url(file.GetPath());
4882 if (url.GetProtocol() == "plugin")
4883 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4886 if (URIUtils::IsUPnP(file.GetPath()))
4888 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4893 // ok - send the file to the player if it wants it
4894 if (m_pPlayer && m_pPlayer->QueueNextFile(file))
4895 { // player wants the next file
4896 m_nextPlaylistItem = iNext;
4902 case GUI_MSG_PLAYBACK_STOPPED:
4903 case GUI_MSG_PLAYBACK_ENDED:
4904 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4908 m_pKaraokeMgr->Stop();
4910 #ifdef TARGET_DARWIN
4911 DarwinSetScheduling(message.GetMessage());
4913 // first check if we still have items in the stack to play
4914 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4916 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4917 { // just play the next item in the stack
4918 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4923 // In case playback ended due to user eg. skipping over the end, clear
4924 // our resume bookmark here
4925 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4927 // Delete the bookmark
4928 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4931 // reset the current playing file
4932 m_itemCurrentFile->Reset();
4933 g_infoManager.ResetCurrentItem();
4934 m_currentStack->Clear();
4936 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4938 g_playlistPlayer.PlayNext(1, true);
4943 if (CLastFmManager::GetInstance()->IsRadioEnabled())
4944 CLastFmManager::GetInstance()->StopRadio();
4946 // reset any forced player
4947 m_eForcedNextPlayer = EPC_NONE;
4958 g_audioManager.Enable(true);
4961 if (!IsPlayingVideo())
4963 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4965 g_windowManager.PreviousWindow();
4969 CSingleLock lock(g_graphicsContext);
4970 // resets to res_desktop or look&feel resolution (including refreshrate)
4971 g_graphicsContext.SetFullScreenVideo(false);
4975 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4977 g_settings.Save(); // save vis settings
4978 WakeUpScreenSaverAndDPMS();
4979 g_windowManager.PreviousWindow();
4982 // DVD ejected while playing in vis ?
4983 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4986 g_settings.Save(); // save vis settings
4987 WakeUpScreenSaverAndDPMS();
4988 g_windowManager.PreviousWindow();
4991 if (IsEnableTestMode())
4992 CApplicationMessenger::Get().Quit();
4997 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4998 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
5003 case GUI_MSG_FULLSCREEN:
5004 { // Switch to fullscreen, if we can
5005 SwitchToFullScreen();
5009 case GUI_MSG_EXECUTE:
5010 if (message.GetNumStringParams())
5011 return ExecuteXBMCAction(message.GetStringParam());
5017 bool CApplication::ExecuteXBMCAction(std::string actionStr)
5019 // see if it is a user set string
5020 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
5021 CGUIInfoLabel info(actionStr, "");
5022 actionStr = info.GetLabel(0);
5023 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
5025 // user has asked for something to be executed
5026 if (CBuiltins::HasCommand(actionStr))
5027 CBuiltins::Execute(actionStr);
5030 // try translating the action from our ButtonTranslator
5032 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5034 OnAction(CAction(actionID));
5037 CFileItem item(actionStr, false);
5039 if (item.IsPythonScript())
5040 { // a python script
5041 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
5045 if (item.IsAudio() || item.IsVideo())
5046 { // an audio or video file
5055 void CApplication::Process()
5059 // dispatch the messages generated by python or other threads to the current window
5060 g_windowManager.DispatchThreadMessages();
5062 // process messages which have to be send to the gui
5063 // (this can only be done after g_windowManager.Render())
5064 CApplicationMessenger::Get().ProcessWindowMessages();
5067 // process any Python scripts
5068 g_pythonParser.Process();
5071 // process messages, even if a movie is playing
5072 CApplicationMessenger::Get().ProcessMessages();
5073 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5075 // check how far we are through playing the current item
5076 // and do anything that needs doing (lastfm submission, playcount updates etc)
5077 CheckPlayingProgress();
5081 m_pPlayer->DoAudioWork();
5083 // do any processing that isn't needed on each run
5084 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5086 m_slowTimer.Reset();
5090 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5093 // We get called every 500ms
5094 void CApplication::ProcessSlow()
5096 g_powerManager.ProcessEvents();
5098 #if defined(TARGET_DARWIN_OSX)
5099 // There is an issue on OS X that several system services ask the cursor to become visible
5100 // during their startup routines. Given that we can't control this, we hack it in by
5102 if (g_Windowing.IsFullScreen())
5103 { // SDL thinks it's hidden
5108 // Store our file state for use on close()
5111 if (IsPlayingAudio())
5113 CLastfmScrobbler::GetInstance()->UpdateStatus();
5114 CLibrefmScrobbler::GetInstance()->UpdateStatus();
5117 // Check if we need to activate the screensaver / DPMS.
5118 CheckScreenSaverAndDPMS();
5120 // Check if we need to shutdown (if enabled).
5121 #if defined(TARGET_DARWIN)
5122 if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5124 if (g_guiSettings.GetInt("powermanagement.shutdowntime"))
5130 // check if we should restart the player
5131 CheckDelayedPlayerRestart();
5133 // check if we can unload any unreferenced dlls or sections
5134 if (!IsPlayingVideo())
5135 CSectionLoader::UnloadDelayed();
5137 // check for any idle curl connections
5138 g_curlInterface.CheckIdle();
5140 // check for any idle myth sessions
5141 CMythSession::CheckIdle();
5143 #ifdef HAS_FILESYSTEM_HTSP
5144 // check for any idle htsp sessions
5145 HTSP::CHTSPDirectorySession::CheckIdle();
5149 if ( m_pKaraokeMgr )
5150 m_pKaraokeMgr->ProcessSlow();
5153 if (!IsPlayingVideo())
5154 g_largeTextureManager.CleanupUnusedImages();
5156 #ifdef HAS_DVD_DRIVE
5157 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5158 if (!IsPlayingVideo())
5159 m_Autorun->HandleAutorun();
5162 // update upnp server/renderer states
5164 if(UPNP::CUPnP::IsInstantiated())
5165 UPNP::CUPnP::GetInstance()->UpdateState();
5168 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
5172 #ifdef HAS_FILESYSTEM_NFS
5173 gNfsConnection.CheckIfIdle();
5176 #ifdef HAS_FILESYSTEM_AFP
5177 gAfpConnection.CheckIfIdle();
5180 #ifdef HAS_FILESYSTEM_SFTP
5181 CSFTPSessionManager::ClearOutIdleSessions();
5184 g_mediaManager.ProcessEvents();
5187 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5188 g_RemoteControl.Initialize();
5191 if (!IsPlayingVideo())
5192 CAddonInstaller::Get().UpdateRepos();
5194 CAEFactory::GarbageCollect();
5197 // Global Idle Time in Seconds
5198 // idle time will be resetet if on any OnKey()
5199 // int return: system Idle time in seconds! 0 is no idle!
5200 int CApplication::GlobalIdleTime()
5202 if(!m_idleTimer.IsRunning())
5205 m_idleTimer.StartZero();
5207 return (int)m_idleTimer.GetElapsedSeconds();
5210 float CApplication::NavigationIdleTime()
5212 if (!m_navigationTimer.IsRunning())
5214 m_navigationTimer.Stop();
5215 m_navigationTimer.StartZero();
5217 return m_navigationTimer.GetElapsedSeconds();
5220 void CApplication::DelayedPlayerRestart()
5222 m_restartPlayerTimer.StartZero();
5225 void CApplication::CheckDelayedPlayerRestart()
5227 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5229 m_restartPlayerTimer.Stop();
5230 m_restartPlayerTimer.Reset();
5235 void CApplication::Restart(bool bSamePosition)
5237 // this function gets called when the user changes a setting (like noninterleaved)
5238 // and which means we gotta close & reopen the current playing file
5240 // first check if we're playing a file
5241 if ( !IsPlayingVideo() && !IsPlayingAudio())
5249 // do we want to return to the current position in the file
5250 if (false == bSamePosition)
5252 // no, then just reopen the file and start at the beginning
5253 PlayFile(*m_itemCurrentFile, true);
5257 // else get current position
5258 double time = GetTime();
5260 // get player state, needed for dvd's
5261 CStdString state = m_pPlayer->GetPlayerState();
5263 // set the requested starttime
5264 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5267 if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer )
5268 m_pPlayer->SetPlayerState(state);
5271 const CStdString& CApplication::CurrentFile()
5273 return m_itemCurrentFile->GetPath();
5276 CFileItem& CApplication::CurrentFileItem()
5278 return *m_itemCurrentFile;
5281 void CApplication::ShowVolumeBar(const CAction *action)
5283 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5288 volumeBar->OnAction(*action);
5292 bool CApplication::IsMuted() const
5294 if (g_peripherals.IsMuted())
5296 return CAEFactory::IsMuted();
5299 void CApplication::ToggleMute(void)
5301 if (g_settings.m_bMute)
5307 void CApplication::Mute()
5309 if (g_peripherals.Mute())
5312 CAEFactory::SetMute(true);
5313 g_settings.m_bMute = true;
5317 void CApplication::UnMute()
5319 if (g_peripherals.UnMute())
5322 CAEFactory::SetMute(false);
5323 g_settings.m_bMute = false;
5327 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5329 float hardwareVolume = iValue;
5332 hardwareVolume /= 100.0f;
5334 SetHardwareVolume(hardwareVolume);
5338 void CApplication::SetHardwareVolume(float hardwareVolume)
5340 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5341 g_settings.m_fVolumeLevel = hardwareVolume;
5344 if (hardwareVolume > VOLUME_MINIMUM)
5346 float dB = CAEUtil::PercentToGain(hardwareVolume);
5347 value = CAEUtil::GainToScale(dB);
5352 CAEFactory::SetVolume(value);
5355 int CApplication::GetVolume() const
5357 // converts the hardware volume to a percentage
5358 return (int)(g_settings.m_fVolumeLevel * 100.0f);
5361 void CApplication::VolumeChanged() const
5363 CVariant data(CVariant::VariantTypeObject);
5364 data["volume"] = GetVolume();
5365 data["muted"] = g_settings.m_bMute;
5366 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5368 // if player has volume control, set it.
5369 if (m_pPlayer && m_pPlayer->ControlsVolume())
5371 m_pPlayer->SetVolume(g_settings.m_fVolumeLevel);
5372 m_pPlayer->SetMute(g_settings.m_bMute);
5376 int CApplication::GetSubtitleDelay() const
5378 // converts subtitle delay to a percentage
5379 return int(((float)(g_settings.m_currentVideoSettings.m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5382 int CApplication::GetAudioDelay() const
5384 // converts subtitle delay to a percentage
5385 return int(((float)(g_settings.m_currentVideoSettings.m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5388 void CApplication::SetPlaySpeed(int iSpeed)
5390 if (!IsPlayingAudio() && !IsPlayingVideo())
5392 if (m_iPlaySpeed == iSpeed)
5394 if (!m_pPlayer->CanSeek())
5396 if (m_pPlayer->IsPaused())
5399 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5400 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5403 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5407 m_iPlaySpeed = iSpeed;
5409 m_pPlayer->ToFFRW(m_iPlaySpeed);
5411 // if player has volume control, set it.
5412 if (m_pPlayer->ControlsVolume())
5414 if (m_iPlaySpeed == 1)
5416 m_pPlayer->SetVolume(VOLUME_MAXIMUM);
5420 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5422 m_pPlayer->SetMute(g_settings.m_bMute);
5426 int CApplication::GetPlaySpeed() const
5428 return m_iPlaySpeed;
5431 // Returns the total time in seconds of the current media. Fractional
5432 // portions of a second are possible - but not necessarily supported by the
5433 // player class. This returns a double to be consistent with GetTime() and
5435 double CApplication::GetTotalTime() const
5439 if (IsPlaying() && m_pPlayer)
5441 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5442 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5444 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5450 void CApplication::StopShutdownTimer()
5452 if (m_shutdownTimer.IsRunning())
5453 m_shutdownTimer.Stop();
5456 void CApplication::ResetShutdownTimers()
5458 // reset system shutdown timer
5459 m_shutdownTimer.StartZero();
5461 // delete custom shutdown timer
5462 if (g_alarmClock.HasAlarm("shutdowntimer"))
5463 g_alarmClock.Stop("shutdowntimer", true);
5466 // Returns the current time in seconds of the currently playing media.
5467 // Fractional portions of a second are possible. This returns a double to
5468 // be consistent with GetTotalTime() and SeekTime().
5469 double CApplication::GetTime() const
5473 if (IsPlaying() && m_pPlayer)
5475 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5477 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5478 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5481 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5487 // Sets the current position of the currently playing media to the specified
5488 // time in seconds. Fractional portions of a second are valid. The passed
5489 // time is the time offset from the beginning of the file as opposed to a
5490 // delta from the current position. This method accepts a double to be
5491 // consistent with GetTime() and GetTotalTime().
5492 void CApplication::SeekTime( double dTime )
5494 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5496 if (!m_pPlayer->CanSeek()) return;
5497 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5499 // find the item in the stack we are seeking to, and load the new
5500 // file if necessary, and calculate the correct seek within the new
5501 // file. Otherwise, just fall through to the usual routine if the
5502 // time is higher than our total time.
5503 for (int i = 0; i < m_currentStack->Size(); i++)
5505 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5507 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5508 if (m_currentStackPosition == i)
5509 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5511 { // seeking to a new file
5512 m_currentStackPosition = i;
5513 CFileItem item(*(*m_currentStack)[i]);
5514 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5515 // don't just call "PlayFile" here, as we are quite likely called from the
5516 // player thread, so we won't be able to delete ourselves.
5517 CApplicationMessenger::Get().PlayFile(item, true);
5523 // convert to milliseconds and perform seek
5524 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5528 float CApplication::GetPercentage() const
5530 if (IsPlaying() && m_pPlayer)
5532 if (m_pPlayer->GetTotalTime() == 0 && IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5534 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5535 if (tag.GetDuration() > 0)
5536 return (float)(GetTime() / tag.GetDuration() * 100);
5539 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5541 double totalTime = GetTotalTime();
5542 if (totalTime > 0.0f)
5543 return (float)(GetTime() / totalTime * 100);
5546 return m_pPlayer->GetPercentage();
5551 float CApplication::GetCachePercentage() const
5553 if (IsPlaying() && m_pPlayer)
5555 // Note that the player returns a relative cache percentage and we want an absolute percentage
5556 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5558 float stackedTotalTime = (float) GetTotalTime();
5559 // We need to take into account the stack's total time vs. currently playing file's total time
5560 if (stackedTotalTime > 0.0f)
5561 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5564 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5569 void CApplication::SeekPercentage(float percent)
5571 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5573 if (!m_pPlayer->CanSeek()) return;
5574 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5575 SeekTime(percent * 0.01 * GetTotalTime());
5577 m_pPlayer->SeekPercentage(percent);
5581 // SwitchToFullScreen() returns true if a switch is made, else returns false
5582 bool CApplication::SwitchToFullScreen()
5584 // if playing from the video info window, close it first!
5585 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5587 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5588 if (pDialog) pDialog->Close(true);
5591 // don't switch if there is a dialog on screen or the slideshow is active
5592 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5595 // See if we're playing a video, and are in GUI mode
5596 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5598 // Reset frame count so that timing is FPS will be correct.
5600 CSingleLock lock(m_frameMutex);
5604 // then switch to fullscreen mode
5605 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5608 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5609 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5610 { // then switch to visualisation
5611 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5617 void CApplication::Minimize()
5619 g_Windowing.Minimize();
5622 PLAYERCOREID CApplication::GetCurrentPlayer()
5624 return m_eCurrentPlayer;
5627 void CApplication::UpdateLibraries()
5629 if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
5631 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5635 if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
5637 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5642 bool CApplication::IsVideoScanning() const
5644 return m_videoInfoScanner->IsScanning();
5647 bool CApplication::IsMusicScanning() const
5649 return m_musicInfoScanner->IsScanning();
5652 void CApplication::StopVideoScan()
5654 if (m_videoInfoScanner->IsScanning())
5655 m_videoInfoScanner->Stop();
5658 void CApplication::StopMusicScan()
5660 if (m_musicInfoScanner->IsScanning())
5661 m_musicInfoScanner->Stop();
5664 void CApplication::StartVideoCleanup()
5666 if (m_videoInfoScanner->IsScanning())
5669 m_videoInfoScanner->CleanDatabase();
5672 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5674 if (m_videoInfoScanner->IsScanning())
5677 m_videoInfoScanner->ShowDialog(true);
5679 m_videoInfoScanner->Start(strDirectory,scanAll);
5682 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5684 if (m_musicInfoScanner->IsScanning())
5688 { // setup default flags
5689 if (g_guiSettings.GetBool("musiclibrary.downloadinfo"))
5690 flags |= CMusicInfoScanner::SCAN_ONLINE;
5691 if (g_guiSettings.GetBool("musiclibrary.backgroundupdate"))
5692 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5695 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5696 m_musicInfoScanner->ShowDialog(true);
5698 m_musicInfoScanner->Start(strDirectory, flags);
5701 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5704 if (m_musicInfoScanner->IsScanning())
5707 m_musicInfoScanner->ShowDialog(true);
5709 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5712 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5715 if (m_musicInfoScanner->IsScanning())
5718 m_musicInfoScanner->ShowDialog(true);
5720 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5723 void CApplication::CheckPlayingProgress()
5725 // check if we haven't rewound past the start of the file
5728 int iSpeed = g_application.GetPlaySpeed();
5738 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5740 g_application.SetPlaySpeed(1);
5741 g_application.SeekTime(0);
5747 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5749 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5751 // initial exit conditions
5752 // no songs in playlist just return
5753 if (playlist.size() == 0)
5757 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5760 // setup correct playlist
5761 g_playlistPlayer.ClearPlaylist(iPlaylist);
5763 // if the playlist contains an internet stream, this file will be used
5764 // to generate a thumbnail for musicplayer.cover
5765 g_application.m_strPlayListFile = strPlayList;
5767 // add the items to the playlist player
5768 g_playlistPlayer.Add(iPlaylist, playlist);
5770 // if we have a playlist
5771 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5774 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5775 g_playlistPlayer.Reset();
5776 g_playlistPlayer.Play(track);
5782 void CApplication::SaveCurrentFileSettings()
5784 // don't store settings for PVR in video database
5785 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5787 // save video settings
5788 if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings)
5792 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), g_settings.m_currentVideoSettings);
5796 else if (m_itemCurrentFile->IsPVRChannel())
5798 g_PVRManager.SaveCurrentChannelSettings();
5802 bool CApplication::AlwaysProcess(const CAction& action)
5804 // check if this button is mapped to a built-in function
5805 if (!action.GetName().IsEmpty())
5807 CStdString builtInFunction;
5808 vector<CStdString> params;
5809 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5810 builtInFunction.ToLower();
5812 // should this button be handled normally or just cancel the screensaver?
5813 if ( builtInFunction.Equals("powerdown")
5814 || builtInFunction.Equals("reboot")
5815 || builtInFunction.Equals("restart")
5816 || builtInFunction.Equals("restartapp")
5817 || builtInFunction.Equals("suspend")
5818 || builtInFunction.Equals("hibernate")
5819 || builtInFunction.Equals("quit")
5820 || builtInFunction.Equals("shutdown"))
5829 bool CApplication::IsCurrentThread() const
5831 return CThread::IsCurrentThread(m_threadID);
5834 bool CApplication::IsPresentFrame()
5836 CSingleLock lock(m_frameMutex);
5837 bool ret = m_bPresentFrame;
5842 void CApplication::SetRenderGUI(bool renderGUI)
5844 if (renderGUI && ! m_renderGUI)
5845 g_windowManager.MarkDirty();
5846 m_renderGUI = renderGUI;
5849 CNetwork& CApplication::getNetwork()
5853 #ifdef HAS_PERFORMANCE_SAMPLE
5854 CPerformanceStats &CApplication::GetPerformanceStats()