2 * Copyright (C) 2005-2012 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 "threads/SystemClock.h"
23 #include "Application.h"
24 #include "interfaces/Builtins.h"
25 #include "utils/Variant.h"
26 #include "utils/Splash.h"
28 #include "utils/Screenshot.h"
31 #include "guilib/TextureManager.h"
32 #include "cores/dvdplayer/DVDFileInfo.h"
33 #include "cores/AudioEngine/AEFactory.h"
34 #include "cores/AudioEngine/Utils/AEUtil.h"
35 #include "PlayListPlayer.h"
37 #include "video/Bookmark.h"
39 #include "network/WebServer.h"
40 #include "network/httprequesthandler/HTTPImageHandler.h"
41 #include "network/httprequesthandler/HTTPVfsHandler.h"
43 #include "network/httprequesthandler/HTTPJsonRpcHandler.h"
45 #ifdef HAS_WEB_INTERFACE
46 #include "network/httprequesthandler/HTTPWebinterfaceHandler.h"
47 #include "network/httprequesthandler/HTTPWebinterfaceAddonsHandler.h"
51 #include "utils/LCDFactory.h"
53 #include "guilib/GUIControlProfiler.h"
54 #include "utils/LangCodeExpander.h"
55 #include "GUIInfoManager.h"
56 #include "playlists/PlayListFactory.h"
57 #include "guilib/GUIFontManager.h"
58 #include "guilib/GUIColorManager.h"
59 #include "guilib/GUITextLayout.h"
60 #include "addons/Skin.h"
62 #include "interfaces/python/XBPython.h"
64 #include "input/ButtonTranslator.h"
65 #include "guilib/GUIAudioManager.h"
66 #include "network/libscrobbler/lastfmscrobbler.h"
67 #include "network/libscrobbler/librefmscrobbler.h"
68 #include "GUIPassword.h"
69 #include "input/InertialScrollingHandler.h"
70 #include "ApplicationMessenger.h"
71 #include "SectionLoader.h"
72 #include "cores/DllLoader/DllLoaderContainer.h"
73 #include "GUIUserMessages.h"
74 #include "filesystem/DirectoryCache.h"
75 #include "filesystem/StackDirectory.h"
76 #include "filesystem/SpecialProtocol.h"
77 #include "filesystem/DllLibCurl.h"
78 #include "filesystem/MythSession.h"
79 #include "filesystem/PluginDirectory.h"
80 #ifdef HAS_FILESYSTEM_SAP
81 #include "filesystem/SAPDirectory.h"
83 #ifdef HAS_FILESYSTEM_HTSP
84 #include "filesystem/HTSPDirectory.h"
86 #include "utils/TuxBoxUtil.h"
87 #include "utils/SystemInfo.h"
88 #include "utils/TimeUtils.h"
89 #include "GUILargeTextureManager.h"
90 #include "TextureCache.h"
91 #include "music/LastFmManager.h"
92 #include "playlists/SmartPlayList.h"
93 #ifdef HAS_FILESYSTEM_RAR
94 #include "filesystem/RarManager.h"
96 #include "playlists/PlayList.h"
97 #include "windowing/WindowingFactory.h"
98 #include "powermanagement/PowerManager.h"
99 #include "powermanagement/DPMSSupport.h"
100 #include "settings/Settings.h"
101 #include "settings/AdvancedSettings.h"
102 #include "guilib/LocalizeStrings.h"
103 #include "utils/CPUInfo.h"
104 #include "utils/SeekHandler.h"
106 #include "input/KeyboardStat.h"
107 #include "input/XBMC_vkeys.h"
108 #include "input/MouseStat.h"
114 #if defined(FILESYSTEM) && !defined(_LINUX)
115 #include "filesystem/FileDAAP.h"
118 #include "network/upnp/UPnP.h"
119 #include "filesystem/UPnPDirectory.h"
121 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
122 #include "filesystem/SMBDirectory.h"
124 #ifdef HAS_FILESYSTEM_NFS
125 #include "filesystem/NFSFile.h"
127 #ifdef HAS_FILESYSTEM_AFP
128 #include "filesystem/AFPFile.h"
130 #ifdef HAS_FILESYSTEM_SFTP
131 #include "filesystem/SFTPFile.h"
133 #include "PartyModeManager.h"
134 #ifdef HAS_VIDEO_PLAYBACK
135 #include "cores/VideoRenderers/RenderManager.h"
138 #include "music/karaoke/karaokelyricsmanager.h"
139 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
140 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
142 #include "network/Network.h"
143 #include "network/Zeroconf.h"
144 #include "network/ZeroconfBrowser.h"
146 #include "threads/platform/win/Win32Exception.h"
148 #ifdef HAS_EVENT_SERVER
149 #include "network/EventServer.h"
152 #include <dbus/dbus.h>
155 #include "interfaces/json-rpc/JSONRPC.h"
156 #include "network/TCPServer.h"
159 #include "network/AirPlayServer.h"
162 #include "network/AirTunesServer.h"
164 #if defined(HAVE_LIBCRYSTALHD)
165 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
167 #include "interfaces/AnnouncementManager.h"
168 #include "peripherals/Peripherals.h"
169 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
170 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
171 #include "peripherals/devices/PeripheralImon.h"
172 #include "music/infoscanner/MusicInfoScanner.h"
175 #include "guilib/GUIWindowManager.h"
176 #include "windows/GUIWindowHome.h"
177 #include "settings/GUIWindowSettings.h"
178 #include "windows/GUIWindowFileManager.h"
179 #include "settings/GUIWindowSettingsCategory.h"
180 #include "music/windows/GUIWindowMusicPlaylist.h"
181 #include "music/windows/GUIWindowMusicSongs.h"
182 #include "music/windows/GUIWindowMusicNav.h"
183 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
184 #include "video/windows/GUIWindowVideoPlaylist.h"
185 #include "music/dialogs/GUIDialogMusicInfo.h"
186 #include "video/dialogs/GUIDialogVideoInfo.h"
187 #include "video/windows/GUIWindowVideoNav.h"
188 #include "settings/GUIWindowSettingsProfile.h"
190 #include "rendering/gl/GUIWindowTestPatternGL.h"
193 #include "rendering/dx/GUIWindowTestPatternDX.h"
195 #include "settings/GUIWindowSettingsScreenCalibration.h"
196 #include "programs/GUIWindowPrograms.h"
197 #include "pictures/GUIWindowPictures.h"
198 #include "windows/GUIWindowWeather.h"
199 #include "windows/GUIWindowLoginScreen.h"
200 #include "addons/GUIWindowAddonBrowser.h"
201 #include "music/windows/GUIWindowVisualisation.h"
202 #include "windows/GUIWindowDebugInfo.h"
203 #include "windows/GUIWindowPointer.h"
204 #include "windows/GUIWindowSystemInfo.h"
205 #include "windows/GUIWindowScreensaver.h"
206 #include "windows/GUIWindowScreensaverDim.h"
207 #include "pictures/GUIWindowSlideShow.h"
208 #include "windows/GUIWindowStartup.h"
209 #include "video/windows/GUIWindowFullScreen.h"
210 #include "video/dialogs/GUIDialogVideoOSD.h"
211 #include "music/dialogs/GUIDialogMusicOverlay.h"
212 #include "video/dialogs/GUIDialogVideoOverlay.h"
213 #include "video/VideoInfoScanner.h"
216 #include "music/dialogs/GUIDialogMusicOSD.h"
217 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
218 #include "dialogs/GUIDialogTextViewer.h"
219 #include "network/GUIDialogNetworkSetup.h"
220 #include "dialogs/GUIDialogMediaSource.h"
221 #include "video/dialogs/GUIDialogVideoSettings.h"
222 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
223 #include "video/dialogs/GUIDialogVideoBookmarks.h"
224 #include "settings/GUIDialogProfileSettings.h"
225 #include "settings/GUIDialogLockSettings.h"
226 #include "settings/GUIDialogContentSettings.h"
227 #include "dialogs/GUIDialogBusy.h"
228 #include "dialogs/GUIDialogKeyboardGeneric.h"
229 #include "dialogs/GUIDialogYesNo.h"
230 #include "dialogs/GUIDialogOK.h"
231 #include "dialogs/GUIDialogProgress.h"
232 #include "dialogs/GUIDialogExtendedProgressBar.h"
233 #include "dialogs/GUIDialogSelect.h"
234 #include "dialogs/GUIDialogSeekBar.h"
235 #include "dialogs/GUIDialogKaiToast.h"
236 #include "dialogs/GUIDialogVolumeBar.h"
237 #include "dialogs/GUIDialogMuteBug.h"
238 #include "video/dialogs/GUIDialogFileStacking.h"
239 #include "dialogs/GUIDialogNumeric.h"
240 #include "dialogs/GUIDialogGamepad.h"
241 #include "dialogs/GUIDialogSubMenu.h"
242 #include "dialogs/GUIDialogFavourites.h"
243 #include "dialogs/GUIDialogButtonMenu.h"
244 #include "dialogs/GUIDialogContextMenu.h"
245 #include "dialogs/GUIDialogPlayerControls.h"
246 #include "music/dialogs/GUIDialogSongInfo.h"
247 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
248 #include "dialogs/GUIDialogSmartPlaylistRule.h"
249 #include "pictures/GUIDialogPictureInfo.h"
250 #include "addons/GUIDialogAddonSettings.h"
251 #include "addons/GUIDialogAddonInfo.h"
252 #ifdef HAS_LINUX_NETWORK
253 #include "network/GUIDialogAccessPoints.h"
256 /* PVR related include Files */
257 #include "pvr/PVRManager.h"
258 #include "pvr/timers/PVRTimers.h"
259 #include "pvr/windows/GUIWindowPVR.h"
260 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
261 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
262 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
263 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
264 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
265 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
266 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
267 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
268 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
269 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
271 #include "epg/EpgContainer.h"
273 #include "video/dialogs/GUIDialogFullScreenInfo.h"
274 #include "video/dialogs/GUIDialogTeletext.h"
275 #include "dialogs/GUIDialogSlider.h"
276 #include "guilib/GUIControlFactory.h"
277 #include "dialogs/GUIDialogCache.h"
278 #include "dialogs/GUIDialogPlayEject.h"
279 #include "dialogs/GUIDialogMediaFilter.h"
280 #include "utils/XMLUtils.h"
281 #include "addons/AddonInstaller.h"
283 #ifdef HAS_PERFORMANCE_SAMPLE
284 #include "utils/PerformanceSample.h"
286 #define MEASURE_FUNCTION
289 #ifdef TARGET_WINDOWS
291 #include "win32util.h"
294 #include "windowing/X11/XRandR.h"
297 #ifdef TARGET_DARWIN_OSX
298 #include "osx/CocoaInterface.h"
299 #include "osx/XBMCHelper.h"
302 #include "osx/DarwinUtils.h"
307 #include <cdio/logging.h>
311 #include "linux/HALManager.h"
314 #include "storage/MediaManager.h"
315 #include "utils/JobManager.h"
316 #include "utils/SaveFileStateJob.h"
317 #include "utils/AlarmClock.h"
318 #include "utils/StringUtils.h"
319 #include "DatabaseManager.h"
326 #include "input/linux/LIRC.h"
328 #ifdef HAS_IRSERVERSUITE
329 #include "input/windows/IRServerSuite.h"
332 #if defined(TARGET_WINDOWS)
333 #include "input/windows/WINJoystick.h"
334 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
335 #include "input/SDLJoystick.h"
339 using namespace ADDON;
340 using namespace XFILE;
342 using namespace MEDIA_DETECT;
344 using namespace PLAYLIST;
345 using namespace VIDEO;
346 using namespace MUSIC_INFO;
347 #ifdef HAS_EVENT_SERVER
348 using namespace EVENTSERVER;
351 using namespace JSONRPC;
353 using namespace ANNOUNCEMENT;
356 using namespace PERIPHERALS;
358 using namespace XbmcThreads;
360 // uncomment this if you want to use release libs in the debug build.
361 // Atm this saves you 7 mb of memory
362 #define USE_RELEASE_LIBS
364 #define MAX_FFWD_SPEED 5
366 //extern IDirectSoundRenderer* m_pAudioDecoder;
367 CApplication::CApplication(void)
369 #ifdef HAS_WEB_SERVER
370 , m_WebServer(*new CWebServer)
371 , m_httpImageHandler(*new CHTTPImageHandler)
372 , m_httpVfsHandler(*new CHTTPVfsHandler)
374 , m_httpJsonRpcHandler(*new CHTTPJsonRpcHandler)
376 #ifdef HAS_WEB_INTERFACE
377 , m_httpWebinterfaceHandler(*new CHTTPWebinterfaceHandler)
378 , m_httpWebinterfaceAddonsHandler(*new CHTTPWebinterfaceAddonsHandler)
381 , m_itemCurrentFile(new CFileItem)
382 , m_stackFileItemToUpdate(new CFileItem)
383 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
384 , m_progressTrackingItem(new CFileItem)
385 , m_videoInfoScanner(new CVideoInfoScanner)
386 , m_musicInfoScanner(new CMusicInfoScanner)
387 , m_seekHandler(new CSeekHandler)
389 TiXmlBase::SetCondenseWhiteSpace(false);
391 m_bInhibitIdleShutdown = false;
392 m_bScreenSave = false;
394 m_dpmsIsActive = false;
395 m_dpmsIsManual = false;
396 m_iScreenSaveLock = 0;
397 m_bInitializing = true;
398 m_eForcedNextPlayer = EPC_NONE;
399 m_strPlayListFile = "";
400 m_nextPlaylistItem = -1;
401 m_bPlaybackStarting = false;
402 m_skinReloading = false;
408 //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
411 /* for now always keep this around */
413 m_pKaraokeMgr = new CKaraokeLyricsManager();
415 m_currentStack = new CFileItemList;
419 m_bPresentFrame = false;
420 m_bPlatformDirectories = true;
422 m_bStandalone = false;
423 m_bEnableLegacyRes = false;
424 m_bSystemScreenSaverEnable = false;
425 m_pInertialScrollingHandler = new CInertialScrollingHandler();
427 m_Autorun = new CAutorun();
432 m_eCurrentPlayer = EPC_NONE;
433 m_progressTrackingPlayCountUpdate = false;
434 m_currentStackPosition = 0;
436 m_lastRenderTime = 0;
440 CApplication::~CApplication(void)
442 #ifdef HAS_WEB_SERVER
444 delete &m_httpImageHandler;
445 delete &m_httpVfsHandler;
447 delete &m_httpJsonRpcHandler;
449 #ifdef HAS_WEB_INTERFACE
450 delete &m_httpWebinterfaceHandler;
451 delete &m_httpWebinterfaceAddonsHandler;
454 delete m_musicInfoScanner;
455 delete m_videoInfoScanner;
456 delete &m_progressTrackingVideoResumeBookmark;
460 delete m_currentStack;
463 delete m_pKaraokeMgr;
467 delete m_seekHandler;
468 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()
569 g_settings.Initialize(); //Initialize default AdvancedSettings
572 tzset(); // Initialize timezone information variables
575 // Grab a handle to our thread to be used later in identifying the render thread.
576 m_threadID = CThread::GetCurrentThreadId();
579 //floating point precision to 24 bits (faster performance)
580 _controlfp(_PC_24, _MCW_PC);
582 /* install win32 exception translator, win32 exceptions
583 * can now be caught using c++ try catch */
584 win32_exception::install_handler();
588 // only the InitDirectories* for the current platform should return true
589 // putting this before the first log entries saves another ifdef for g_settings.m_logFolder
590 bool inited = InitDirectoriesLinux();
592 inited = InitDirectoriesOSX();
594 inited = InitDirectoriesWin32();
596 // copy required files
597 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
598 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
599 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
600 CopyUserDataIfNeeded("special://masterprofile/", "LCD.xml");
602 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_settings.m_logFolder).c_str()))
604 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
605 CSpecialProtocol::TranslatePath(g_settings.m_logFolder).c_str());
609 // Init our DllLoaders emu env
612 g_settings.LoadProfiles(PROFILES_FILE);
614 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
615 #if defined(TARGET_DARWIN_OSX)
616 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
617 #elif defined(TARGET_DARWIN_IOS)
618 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
619 #elif defined(__FreeBSD__)
620 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
621 #elif defined(_LINUX)
622 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__);
623 #elif defined(_WIN32)
624 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);
626 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
627 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
629 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
631 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
632 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
633 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
634 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
636 CSpecialProtocol::LogPaths();
638 CStdString executable = CUtil::ResolveExecutablePath();
639 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
640 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network.GetHostName().c_str());
641 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str());
642 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
644 CStdString strExecutablePath;
645 CUtil::GetHomePath(strExecutablePath);
647 // if we are running from DVD our UserData location will be TDATA
648 if (URIUtils::IsDVD(strExecutablePath))
650 // TODO: Should we copy over any UserData folder from the DVD?
651 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
654 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
655 for (int i=0;i<items.Size();++i)
656 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
658 g_settings.m_logFolder = "special://masterprofile/";
662 g_xrandr.LoadCustomModeLinesToAllOutputs();
665 // for python scripts that check the OS
666 #if defined(TARGET_DARWIN)
667 setenv("OS","OS X",true);
668 #elif defined(_LINUX)
669 setenv("OS","Linux",true);
670 #elif defined(_WIN32)
671 SetEnvironmentVariable("OS","win32");
674 g_powerManager.Initialize();
676 // Load the AudioEngine before settings as they need to query the engine
677 if (!CAEFactory::LoadEngine())
679 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
683 CLog::Log(LOGNOTICE, "load settings...");
685 g_guiSettings.Initialize(); // Initialize default Settings - don't move
686 g_powerManager.SetDefaults();
687 if (!g_settings.Load())
689 CLog::Log(LOGFATAL, "%s: Failed to reset settings", __FUNCTION__);
693 CLog::Log(LOGINFO, "creating subdirectories");
694 CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
695 CLog::Log(LOGINFO, "recording folder: %s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
696 CLog::Log(LOGINFO, "screenshots folder: %s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
697 CDirectory::Create(g_settings.GetUserDataFolder());
698 CDirectory::Create(g_settings.GetProfileUserDataFolder());
699 g_settings.CreateProfileFolders();
701 update_emu_environ();//apply the GUI settings
703 // initialize our charset converter
704 g_charsetConverter.reset();
706 // Load the langinfo to have user charset <-> utf-8 conversion
707 CStdString strLanguage = g_guiSettings.GetString("locale.language");
708 strLanguage[0] = toupper(strLanguage[0]);
710 CStdString strLangInfoPath;
711 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
713 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
714 g_langInfo.Load(strLangInfoPath);
716 CStdString strLanguagePath = "special://xbmc/language/";
718 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
719 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
721 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
725 // start the AudioEngine
726 if (!CAEFactory::StartEngine())
728 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
732 // restore AE's previous volume state
733 SetHardwareVolume(g_settings.m_fVolumeLevel);
734 CAEFactory::SetMute (g_settings.m_bMute);
735 CAEFactory::SetSoundMode(g_guiSettings.GetInt("audiooutput.guisoundmode"));
737 // initialize the addon database (must be before the addon manager is init'd)
738 CDatabaseManager::Get().Initialize(true);
740 // start-up Addons Framework
741 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
742 if (!CAddonMgr::Get().Init())
744 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
748 g_peripherals.Initialise();
750 // Create the Mouse, Keyboard, Remote, and Joystick devices
751 // Initialize after loading settings to get joystick deadzone setting
752 g_Mouse.Initialize();
753 g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
755 g_Keyboard.Initialize();
756 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
757 g_RemoteControl.Initialize();
760 #if defined(TARGET_DARWIN_OSX)
761 // Configure and possible manually start the helper.
762 XBMCHelper::GetInstance().Configure();
765 CUtil::InitRandomSeed();
767 g_mediaManager.Initialize();
769 m_lastFrameTime = XbmcThreads::SystemClockMillis();
770 m_lastRenderTime = m_lastFrameTime;
774 bool CApplication::CreateGUI()
778 CLog::Log(LOGNOTICE, "Setup SDL");
780 /* Clean up on exit, exit on window close and interrupt */
783 uint32_t sdlFlags = 0;
785 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
786 sdlFlags |= SDL_INIT_VIDEO;
789 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
790 sdlFlags |= SDL_INIT_JOYSTICK;
793 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
794 //this might bring the monitor out of standby, so we have to disable it explicitly
795 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
796 #if defined(_LINUX) && !defined(TARGET_DARWIN)
797 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
803 // for nvidia cards - vsync currently ALWAYS enabled.
804 // the reason is that after screen has been setup changing this env var will make no difference.
805 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
806 setenv("__GL_YIELD", "USLEEP", 0);
809 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
810 g_Windowing.EnableSystemScreenSaver(false);
813 if (SDL_Init(sdlFlags) != 0)
815 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
818 #if defined(TARGET_DARWIN)
819 // SDL_Init will install a handler for segfaults, restore the default handler.
820 signal(SIGSEGV, SIG_DFL);
824 // Initialize core peripheral port support. Note: If these parameters
825 // are 0 and NULL, respectively, then the default number and types of
826 // controllers will be initialized.
827 if (!g_Windowing.InitWindowSystem())
829 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
833 // Retrieve the matching resolution based on GUI settings
834 g_guiSettings.m_LookAndFeelResolution = g_guiSettings.GetResolution();
835 CLog::Log(LOGNOTICE, "Checking resolution %i", g_guiSettings.m_LookAndFeelResolution);
836 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
838 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
839 g_guiSettings.SetResolution(RES_DESKTOP);
842 // update the window resolution
843 g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
845 if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
846 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
848 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
850 // Oh uh - doesn't look good for starting in their wanted screenmode
851 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
852 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
859 if (g_advancedSettings.m_splashImage)
861 CStdString strUserSplash = "special://home/media/Splash.png";
862 if (CFile::Exists(strUserSplash))
864 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
865 m_splash = new CSplash(strUserSplash);
869 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
870 m_splash = new CSplash("special://xbmc/media/Splash.png");
875 // The key mappings may already have been loaded by a peripheral
876 CLog::Log(LOGINFO, "load keymapping");
877 if (!CButtonTranslator::GetInstance().Load())
880 int iResolution = g_graphicsContext.GetVideoResolution();
881 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
882 g_settings.m_ResInfo[iResolution].iWidth,
883 g_settings.m_ResInfo[iResolution].iHeight,
884 g_settings.m_ResInfo[iResolution].strMode.c_str());
885 g_windowManager.Initialize();
890 bool CApplication::InitWindow()
892 #ifdef TARGET_DARWIN_OSX
893 // force initial window creation to be windowed, if fullscreen, it will switch to it below
894 // fixes the white screen of death if starting fullscreen and switching to windowed.
895 bool bFullScreen = false;
896 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
898 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
902 bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
903 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
905 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
910 if (!g_Windowing.InitRenderSystem())
912 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
915 // set GUI res and force the clear of the screen
916 g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
917 g_fontManager.ReloadTTFFonts();
921 bool CApplication::DestroyWindow()
923 g_fontManager.UnloadTTFFonts();
924 return g_Windowing.DestroyWindow();
927 bool CApplication::InitDirectoriesLinux()
930 The following is the directory mapping for Platform Specific Mode:
932 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
933 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
934 installations like skins, screensavers, etc.
936 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
937 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
938 mapped to special://home/userdata ($HOME/.xbmc/userdata)
939 special://profile/ => [read-write] current profile's userdata directory.
940 Generally special://masterprofile for the master profile or
941 special://masterprofile/profiles/<profile_name> for other profiles.
943 NOTE: All these root directories are lowercase. Some of the sub-directories
947 #if defined(_LINUX) && !defined(TARGET_DARWIN)
950 userName = getenv("USER");
956 userHome = getenv("HOME");
960 CStdString xbmcBinPath, xbmcPath;
961 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
962 xbmcPath = getenv("XBMC_HOME");
964 if (xbmcPath.IsEmpty())
966 xbmcPath = xbmcBinPath;
967 /* Check if xbmc binaries and arch independent data files are being kept in
968 * separate locations. */
969 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
971 /* Attempt to locate arch independent data files. */
972 CUtil::GetHomePath(xbmcPath);
973 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
975 fprintf(stderr, "Unable to find path to XBMC data files!\n");
981 /* Set some environment variables */
982 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
983 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
985 if (m_bPlatformDirectories)
987 // map our special drives
988 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
989 CSpecialProtocol::SetXBMCPath(xbmcPath);
990 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
991 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
993 CStdString strTempPath = userHome;
994 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
995 if (getenv("XBMC_TEMP"))
996 strTempPath = getenv("XBMC_TEMP");
997 CSpecialProtocol::SetTempPath(strTempPath);
999 URIUtils::AddSlashAtEnd(strTempPath);
1000 g_settings.m_logFolder = strTempPath;
1007 URIUtils::AddSlashAtEnd(xbmcPath);
1008 g_settings.m_logFolder = xbmcPath;
1010 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1011 CSpecialProtocol::SetXBMCPath(xbmcPath);
1012 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1013 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1015 CStdString strTempPath = xbmcPath;
1016 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1017 if (getenv("XBMC_TEMP"))
1018 strTempPath = getenv("XBMC_TEMP");
1019 CSpecialProtocol::SetTempPath(strTempPath);
1022 URIUtils::AddSlashAtEnd(strTempPath);
1023 g_settings.m_logFolder = strTempPath;
1032 bool CApplication::InitDirectoriesOSX()
1034 #if defined(TARGET_DARWIN)
1035 CStdString userName;
1037 userName = getenv("USER");
1041 CStdString userHome;
1043 userHome = getenv("HOME");
1047 CStdString xbmcPath;
1048 CUtil::GetHomePath(xbmcPath);
1049 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1051 #if defined(TARGET_DARWIN_IOS)
1052 CStdString fontconfigPath;
1053 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1054 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1057 // setup path to our internal dylibs so loader can find them
1058 CStdString frameworksPath = CUtil::GetFrameworksPath();
1059 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1061 // OSX always runs with m_bPlatformDirectories == true
1062 if (m_bPlatformDirectories)
1064 // map our special drives
1065 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1066 CSpecialProtocol::SetXBMCPath(xbmcPath);
1067 #if defined(TARGET_DARWIN_IOS)
1068 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
1069 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
1071 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1072 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1075 // location for temp files
1076 #if defined(TARGET_DARWIN_IOS)
1077 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
1079 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1080 CDirectory::Create(strTempPath);
1081 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1083 CSpecialProtocol::SetTempPath(strTempPath);
1085 // xbmc.log file location
1086 #if defined(TARGET_DARWIN_IOS)
1087 strTempPath = userHome + "/Library/Preferences";
1089 strTempPath = userHome + "/Library/Logs";
1091 URIUtils::AddSlashAtEnd(strTempPath);
1092 g_settings.m_logFolder = strTempPath;
1098 URIUtils::AddSlashAtEnd(xbmcPath);
1099 g_settings.m_logFolder = xbmcPath;
1101 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1102 CSpecialProtocol::SetXBMCPath(xbmcPath);
1103 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1104 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1106 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1107 CSpecialProtocol::SetTempPath(strTempPath);
1109 URIUtils::AddSlashAtEnd(strTempPath);
1110 g_settings.m_logFolder = strTempPath;
1119 bool CApplication::InitDirectoriesWin32()
1122 CStdString xbmcPath;
1124 CUtil::GetHomePath(xbmcPath);
1125 SetEnvironmentVariable("XBMC_HOME", xbmcPath.c_str());
1126 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1127 CSpecialProtocol::SetXBMCPath(xbmcPath);
1129 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1131 g_settings.m_logFolder = strWin32UserFolder;
1132 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1133 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1134 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1136 SetEnvironmentVariable("XBMC_PROFILE_USERDATA",CSpecialProtocol::TranslatePath("special://masterprofile/").c_str());
1140 // Expand the DLL search path with our directories
1141 CWIN32Util::ExtendDllPath();
1149 void CApplication::CreateUserDirs()
1151 CDirectory::Create("special://home/");
1152 CDirectory::Create("special://home/addons");
1153 CDirectory::Create("special://home/addons/packages");
1154 CDirectory::Create("special://home/media");
1155 CDirectory::Create("special://home/sounds");
1156 CDirectory::Create("special://home/system");
1157 CDirectory::Create("special://masterprofile/");
1158 CDirectory::Create("special://temp/");
1159 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1162 bool CApplication::Initialize()
1164 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1165 // turn off cdio logging
1166 cdio_loglevel_default = CDIO_LOG_ERROR;
1169 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1170 // must create these here. Ideally this should be using special://home/ and
1171 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1172 if (!m_bPlatformDirectories)
1175 CDirectory::Create("special://xbmc/language");
1176 CDirectory::Create("special://xbmc/addons");
1177 CDirectory::Create("special://xbmc/sounds");
1180 // Load curl so curl_global_init gets called before any service threads
1181 // are started. Unloading will have no effect as curl is never fully unloaded.
1182 // To quote man curl_global_init:
1183 // "This function is not thread safe. You must not call it when any other
1184 // thread in the program (i.e. a thread sharing the same memory) is running.
1185 // This doesn't just mean no other thread that is using libcurl. Because
1186 // curl_global_init() calls functions of other libraries that are similarly
1187 // thread unsafe, it could conflict with any other thread that
1188 // uses these other libraries."
1189 g_curlInterface.Load();
1190 g_curlInterface.Unload();
1192 // initialize (and update as needed) our databases
1193 CDatabaseManager::Get().Initialize();
1195 #ifdef HAS_WEB_SERVER
1196 CWebServer::RegisterRequestHandler(&m_httpImageHandler);
1197 CWebServer::RegisterRequestHandler(&m_httpVfsHandler);
1199 CWebServer::RegisterRequestHandler(&m_httpJsonRpcHandler);
1201 #ifdef HAS_WEB_INTERFACE
1202 CWebServer::RegisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
1203 CWebServer::RegisterRequestHandler(&m_httpWebinterfaceHandler);
1209 // Init DPMS, before creating the corresponding setting control.
1210 m_dpms = new DPMSSupport();
1211 if (g_windowManager.Initialized())
1213 g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1215 g_windowManager.Add(new CGUIWindowHome);
1216 g_windowManager.Add(new CGUIWindowPrograms);
1217 g_windowManager.Add(new CGUIWindowPictures);
1218 g_windowManager.Add(new CGUIWindowFileManager);
1219 g_windowManager.Add(new CGUIWindowSettings);
1220 g_windowManager.Add(new CGUIWindowSystemInfo);
1222 g_windowManager.Add(new CGUIWindowTestPatternGL);
1225 g_windowManager.Add(new CGUIWindowTestPatternDX);
1227 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1228 g_windowManager.Add(new CGUIWindowSettingsCategory);
1229 g_windowManager.Add(new CGUIWindowVideoNav);
1230 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1231 g_windowManager.Add(new CGUIWindowLoginScreen);
1232 g_windowManager.Add(new CGUIWindowSettingsProfile);
1233 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1234 g_windowManager.Add(new CGUIWindowAddonBrowser);
1235 g_windowManager.Add(new CGUIWindowScreensaverDim);
1236 g_windowManager.Add(new CGUIWindowDebugInfo);
1237 g_windowManager.Add(new CGUIWindowPointer);
1238 g_windowManager.Add(new CGUIDialogYesNo);
1239 g_windowManager.Add(new CGUIDialogProgress);
1240 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1241 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1242 g_windowManager.Add(new CGUIDialogVolumeBar);
1243 g_windowManager.Add(new CGUIDialogSeekBar);
1244 g_windowManager.Add(new CGUIDialogSubMenu);
1245 g_windowManager.Add(new CGUIDialogContextMenu);
1246 g_windowManager.Add(new CGUIDialogKaiToast);
1247 g_windowManager.Add(new CGUIDialogNumeric);
1248 g_windowManager.Add(new CGUIDialogGamepad);
1249 g_windowManager.Add(new CGUIDialogButtonMenu);
1250 g_windowManager.Add(new CGUIDialogMuteBug);
1251 g_windowManager.Add(new CGUIDialogPlayerControls);
1253 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1254 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1256 g_windowManager.Add(new CGUIDialogSlider);
1257 g_windowManager.Add(new CGUIDialogMusicOSD);
1258 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1259 g_windowManager.Add(new CGUIDialogVideoSettings);
1260 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1261 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1262 // Don't add the filebrowser dialog - it's created and added when it's needed
1263 g_windowManager.Add(new CGUIDialogNetworkSetup);
1264 g_windowManager.Add(new CGUIDialogMediaSource);
1265 g_windowManager.Add(new CGUIDialogProfileSettings);
1266 g_windowManager.Add(new CGUIDialogFavourites);
1267 g_windowManager.Add(new CGUIDialogSongInfo);
1268 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1269 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1270 g_windowManager.Add(new CGUIDialogBusy);
1271 g_windowManager.Add(new CGUIDialogPictureInfo);
1272 g_windowManager.Add(new CGUIDialogAddonInfo);
1273 g_windowManager.Add(new CGUIDialogAddonSettings);
1274 #ifdef HAS_LINUX_NETWORK
1275 g_windowManager.Add(new CGUIDialogAccessPoints);
1278 g_windowManager.Add(new CGUIDialogLockSettings);
1280 g_windowManager.Add(new CGUIDialogContentSettings);
1282 g_windowManager.Add(new CGUIDialogPlayEject);
1284 g_windowManager.Add(new CGUIDialogPeripheralManager);
1285 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1287 g_windowManager.Add(new CGUIDialogMediaFilter);
1289 g_windowManager.Add(new CGUIWindowMusicPlayList);
1290 g_windowManager.Add(new CGUIWindowMusicSongs);
1291 g_windowManager.Add(new CGUIWindowMusicNav);
1292 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1294 /* Load PVR related Windows and Dialogs */
1295 g_windowManager.Add(new CGUIDialogTeletext);
1296 g_windowManager.Add(new CGUIWindowPVR);
1297 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1298 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1299 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1300 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1301 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1302 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1303 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1304 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1305 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1306 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1308 g_windowManager.Add(new CGUIDialogSelect);
1309 g_windowManager.Add(new CGUIDialogMusicInfo);
1310 g_windowManager.Add(new CGUIDialogOK);
1311 g_windowManager.Add(new CGUIDialogVideoInfo);
1312 g_windowManager.Add(new CGUIDialogTextViewer);
1313 g_windowManager.Add(new CGUIWindowFullScreen);
1314 g_windowManager.Add(new CGUIWindowVisualisation);
1315 g_windowManager.Add(new CGUIWindowSlideShow);
1316 g_windowManager.Add(new CGUIDialogFileStacking);
1318 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1321 g_windowManager.Add(new CGUIDialogVideoOSD);
1322 g_windowManager.Add(new CGUIDialogMusicOverlay);
1323 g_windowManager.Add(new CGUIDialogVideoOverlay);
1324 g_windowManager.Add(new CGUIWindowScreensaver);
1325 g_windowManager.Add(new CGUIWindowWeather);
1326 g_windowManager.Add(new CGUIWindowStartup);
1328 /* window id's 3000 - 3100 are reserved for python */
1330 // Make sure we have at least the default skin
1331 if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
1333 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
1337 if (g_advancedSettings.m_splashImage)
1338 SAFE_DELETE(m_splash);
1340 if (g_guiSettings.GetBool("masterlock.startuplock") &&
1341 g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1342 !g_settings.GetMasterProfile().getLockCode().IsEmpty())
1344 g_passwordManager.CheckStartUpLock();
1347 // check if we should use the login screen
1348 if (g_settings.UsingLoginScreen())
1349 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1353 CJSONRPC::Initialize();
1355 ADDON::CAddonMgr::Get().StartServices(false);
1357 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1361 else //No GUI Created
1364 CJSONRPC::Initialize();
1366 ADDON::CAddonMgr::Get().StartServices(false);
1369 g_sysinfo.Refresh();
1371 CLog::Log(LOGINFO, "removing tempfiles");
1372 CUtil::RemoveTempFiles();
1374 if (!g_settings.UsingLoginScreen())
1378 g_pythonParser.m_bLogin = true;
1382 m_slowTimer.StartZero();
1384 #if defined(HAVE_LIBCRYSTALHD)
1385 CCrystalHD::GetInstance();
1388 CAddonMgr::Get().StartServices(true);
1390 CLog::Log(LOGNOTICE, "initialize done");
1392 m_bInitializing = false;
1394 // reset our screensaver (starts timers etc.)
1397 #ifdef HAS_SDL_JOYSTICK
1398 g_Joystick.SetEnabled(g_guiSettings.GetBool("input.enablejoystick") &&
1399 (CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 || !g_guiSettings.GetBool("input.disablejoystickwithimon")) );
1405 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1408 bool oldSetting = false;
1413 oldSetting = g_guiSettings.GetBool("services.webserver");
1414 g_guiSettings.SetBool("services.webserver", bStart);
1417 ret = StartWebServer();
1423 g_guiSettings.SetBool("services.webserver", oldSetting);
1426 case ES_AIRPLAYSERVER:
1427 oldSetting = g_guiSettings.GetBool("services.esenabled");
1428 g_guiSettings.SetBool("services.airplay", bStart);
1431 ret = StartAirplayServer();
1433 StopAirplayServer(bWait);
1437 g_guiSettings.SetBool("services.esenabled", oldSetting);
1440 case ES_JSONRPCSERVER:
1441 oldSetting = g_guiSettings.GetBool("services.esenabled");
1442 g_guiSettings.SetBool("services.esenabled", bStart);
1445 ret = StartJSONRPCServer();
1447 StopJSONRPCServer(bWait);
1451 g_guiSettings.SetBool("services.esenabled", oldSetting);
1455 g_guiSettings.SetBool("services.upnpserver", bStart);
1461 case ES_UPNPRENDERER:
1462 g_guiSettings.SetBool("services.upnprenderer", bStart);
1464 StartUPnPRenderer();
1468 case ES_EVENTSERVER:
1469 oldSetting = g_guiSettings.GetBool("services.esenabled");
1470 g_guiSettings.SetBool("services.esenabled", bStart);
1473 ret = StartEventServer();
1475 StopEventServer(bWait, false);
1479 g_guiSettings.SetBool("services.esenabled", oldSetting);
1484 g_guiSettings.SetBool("services.zeroconf", bStart);
1499 bool CApplication::StartWebServer()
1501 #ifdef HAS_WEB_SERVER
1502 if (g_guiSettings.GetBool("services.webserver") && m_network.IsAvailable())
1504 int webPort = atoi(g_guiSettings.GetString("services.webserverport"));
1505 CLog::Log(LOGNOTICE, "Webserver: Starting...");
1507 if (webPort < 1024 && !CUtil::CanBindPrivileged())
1509 CLog::Log(LOGERROR, "Cannot start Web Server on port %i, no permission to bind to ports below 1024", webPort);
1514 bool started = false;
1515 if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")))
1517 std::map<std::string, std::string> txt;
1519 // publish web frontend and API services
1520 #ifdef HAS_WEB_INTERFACE
1521 CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1524 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1535 void CApplication::StopWebServer()
1537 #ifdef HAS_WEB_SERVER
1538 if (m_WebServer.IsStarted())
1540 CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1542 if(! m_WebServer.IsStarted() )
1544 CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1545 CZeroconf::GetInstance()->RemoveService("servers.webserver");
1546 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http");
1547 CZeroconf::GetInstance()->RemoveService("servers.webapi");
1549 CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
1554 bool CApplication::StartAirplayServer()
1558 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1560 int listenPort = g_advancedSettings.m_airPlayPort;
1561 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1562 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1564 if (CAirPlayServer::StartServer(listenPort, true))
1566 CAirPlayServer::SetCredentials(usePassword, password);
1567 std::map<std::string, std::string> txt;
1568 CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
1571 txt["deviceid"] = iface->GetMacAddress();
1575 txt["deviceid"] = "FF:FF:FF:FF:FF:F2";
1577 txt["features"] = "0x77";
1578 txt["model"] = "AppleTV2,1";
1579 txt["srcvers"] = AIRPLAY_SERVER_VERSION_STR;
1580 CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt);
1588 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1590 int listenPort = g_advancedSettings.m_airTunesPort;
1591 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1592 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1594 if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password))
1596 CLog::Log(LOGERROR, "Failed to start AirTunes Server");
1605 void CApplication::StopAirplayServer(bool bWait)
1608 CAirPlayServer::StopServer(bWait);
1609 CZeroconf::GetInstance()->RemoveService("servers.airplay");
1612 CAirTunesServer::StopServer(bWait);
1616 bool CApplication::StartJSONRPCServer()
1619 if (g_guiSettings.GetBool("services.esenabled"))
1621 if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces")))
1623 std::map<std::string, std::string> txt;
1624 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt);
1635 void CApplication::StopJSONRPCServer(bool bWait)
1638 CTCPServer::StopServer(bWait);
1639 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp");
1643 void CApplication::StartUPnP()
1647 StartUPnPRenderer();
1651 void CApplication::StopUPnP(bool bWait)
1654 if (UPNP::CUPnP::IsInstantiated())
1656 CLog::Log(LOGNOTICE, "stopping upnp");
1657 UPNP::CUPnP::ReleaseInstance(bWait);
1662 bool CApplication::StartEventServer()
1664 #ifdef HAS_EVENT_SERVER
1665 CEventServer* server = CEventServer::GetInstance();
1668 CLog::Log(LOGERROR, "ES: Out of memory");
1671 if (g_guiSettings.GetBool("services.esenabled"))
1673 CLog::Log(LOGNOTICE, "ES: Starting event server");
1674 server->StartServer();
1681 bool CApplication::StopEventServer(bool bWait, bool promptuser)
1683 #ifdef HAS_EVENT_SERVER
1684 CEventServer* server = CEventServer::GetInstance();
1687 CLog::Log(LOGERROR, "ES: Out of memory");
1692 if (server->GetNumberOfClients() > 0)
1694 bool cancelled = false;
1695 if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1696 -1, -1, cancelled, 10000)
1699 CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1703 CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1705 CEventServer::GetInstance()->StopServer(true);
1710 CLog::Log(LOGNOTICE, "ES: Stopping event server");
1712 CEventServer::GetInstance()->StopServer(bWait);
1719 void CApplication::RefreshEventServer()
1721 #ifdef HAS_EVENT_SERVER
1722 if (g_guiSettings.GetBool("services.esenabled"))
1724 CEventServer::GetInstance()->RefreshSettings();
1729 void CApplication::StartUPnPRenderer()
1732 if (g_guiSettings.GetBool("services.upnprenderer"))
1734 CLog::Log(LOGNOTICE, "starting upnp renderer");
1735 UPNP::CUPnP::GetInstance()->StartRenderer();
1740 void CApplication::StopUPnPRenderer()
1743 if (UPNP::CUPnP::IsInstantiated())
1745 CLog::Log(LOGNOTICE, "stopping upnp renderer");
1746 UPNP::CUPnP::GetInstance()->StopRenderer();
1751 void CApplication::StartUPnPServer()
1754 if (g_guiSettings.GetBool("services.upnpserver"))
1756 CLog::Log(LOGNOTICE, "starting upnp server");
1757 UPNP::CUPnP::GetInstance()->StartServer();
1762 void CApplication::StopUPnPServer()
1765 if (UPNP::CUPnP::IsInstantiated())
1767 CLog::Log(LOGNOTICE, "stopping upnp server");
1768 UPNP::CUPnP::GetInstance()->StopServer();
1773 void CApplication::StartZeroconf()
1776 //entry in guisetting only present if HAS_ZEROCONF is set
1777 if(g_guiSettings.GetBool("services.zeroconf"))
1779 CLog::Log(LOGNOTICE, "starting zeroconf publishing");
1780 CZeroconf::GetInstance()->Start();
1785 void CApplication::StopZeroconf()
1788 if(CZeroconf::IsInstantiated())
1790 CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
1791 CZeroconf::GetInstance()->Stop();
1796 void CApplication::StartPVRManager()
1798 if (g_guiSettings.GetBool("pvrmanager.enabled"))
1799 g_PVRManager.Start(true);
1802 void CApplication::StopPVRManager()
1804 CLog::Log(LOGINFO, "stopping PVRManager");
1805 if (g_PVRManager.IsPlaying())
1807 g_PVRManager.Stop();
1808 g_EpgContainer.Stop();
1811 void CApplication::DimLCDOnPlayback(bool dim)
1817 g_lcd->DisableOnPlayback(IsPlayingVideo(), IsPlayingAudio());
1819 g_lcd->SetBackLight(1);
1824 void CApplication::StartServices()
1826 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1827 // Start Thread for DVD Mediatype detection
1828 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1829 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1832 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1833 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1834 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistShuffle);
1835 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1836 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistShuffle);
1837 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1840 CLCDFactory factory;
1841 g_lcd = factory.Create();
1844 g_lcd->Initialize();
1849 void CApplication::StopServices()
1851 m_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1853 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1854 CLog::Log(LOGNOTICE, "stop dvd detect media");
1855 m_DetectDVDType.StopThread();
1858 g_peripherals.Clear();
1861 void CApplication::ReloadSkin()
1863 m_skinReloading = false;
1864 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1865 g_windowManager.SendMessage(msg);
1867 // Reload the skin, restoring the previously focused control. We need this as
1868 // the window unload will reset all control states.
1870 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1872 iCtrlID = pWindow->GetFocusedControlID();
1874 g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1878 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1879 if (pWindow && pWindow->HasSaveLastControl())
1881 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1882 pWindow->OnMessage(msg3);
1887 bool CApplication::LoadSkin(const CStdString& skinID)
1889 if (m_skinReloading)
1893 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1895 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1901 void CApplication::LoadSkin(const SkinPtr& skin)
1905 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN);
1906 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1907 LoadSkin(DEFAULT_SKIN);
1912 if (!skin->HasSkinFile("Home.xml"))
1914 // failed to find home.xml
1915 // fallback to default skin
1916 if (strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
1918 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
1919 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1920 LoadSkin(DEFAULT_SKIN);
1921 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1926 bool bPreviousPlayingState=false;
1927 bool bPreviousRenderingState=false;
1928 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1930 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1931 if (bPreviousPlayingState)
1932 g_application.m_pPlayer->Pause();
1933 #ifdef HAS_VIDEO_PLAYBACK
1934 if (!g_renderManager.Paused())
1936 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1938 g_windowManager.ActivateWindow(WINDOW_HOME);
1939 bPreviousRenderingState = true;
1944 // close the music and video overlays (they're re-opened automatically later)
1945 CSingleLock lock(g_graphicsContext);
1947 // save the current window details
1948 int currentWindow = g_windowManager.GetActiveWindow();
1949 vector<int> currentModelessWindows;
1950 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1954 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1956 g_SkinInfo->Start();
1958 CLog::Log(LOGINFO, " load fonts for skin...");
1959 g_graphicsContext.SetMediaDir(skin->Path());
1960 g_directoryCache.ClearSubPaths(skin->Path());
1961 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1963 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1964 CStdString strFontSet;
1965 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1967 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1968 g_guiSettings.SetString("lookandfeel.font", strFontSet);
1972 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1974 g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1976 g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1978 // load in the skin strings
1979 CStdString langPath;
1980 URIUtils::AddFileToFolder(skin->Path(), "language", langPath);
1981 URIUtils::AddSlashAtEnd(langPath);
1983 g_localizeStrings.LoadSkinStrings(langPath, g_guiSettings.GetString("locale.language"));
1985 g_SkinInfo->LoadIncludes();
1988 start = CurrentHostCounter();
1990 CLog::Log(LOGINFO, " load new skin...");
1992 // Load the user windows
1996 end = CurrentHostCounter();
1997 freq = CurrentHostFrequency();
1998 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
2000 CLog::Log(LOGINFO, " initialize new skin...");
2001 g_windowManager.AddMsgTarget(this);
2002 g_windowManager.AddMsgTarget(&g_playlistPlayer);
2003 g_windowManager.AddMsgTarget(&g_infoManager);
2004 g_windowManager.AddMsgTarget(&g_fontManager);
2005 g_windowManager.SetCallback(*this);
2006 g_windowManager.Initialize();
2007 CTextureCache::Get().Initialize();
2008 g_audioManager.Enable(true);
2009 g_audioManager.Load();
2011 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
2012 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2014 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2015 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2016 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2017 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2018 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2021 CLog::Log(LOGINFO, " skin loaded...");
2023 // leave the graphics lock
2027 if (currentWindow != WINDOW_INVALID)
2029 g_windowManager.ActivateWindow(currentWindow);
2030 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2032 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2033 if (dialog) dialog->Show();
2037 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
2039 if (bPreviousPlayingState)
2040 g_application.m_pPlayer->Pause();
2041 if (bPreviousRenderingState)
2042 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2046 void CApplication::UnloadSkin(bool forReload /* = false */)
2048 m_skinReloading = forReload;
2050 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2052 g_audioManager.Enable(false);
2054 g_windowManager.DeInitialize();
2055 CTextureCache::Get().Deinitialize();
2057 // remove the skin-dependent window
2058 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2060 g_TextureManager.Cleanup();
2061 g_largeTextureManager.CleanupUnusedImages(true);
2063 g_fontManager.Clear();
2065 g_colorManager.Clear();
2067 g_charsetConverter.reset();
2069 g_infoManager.Clear();
2072 bool CApplication::LoadUserWindows()
2074 // Start from wherever home.xml is
2075 std::vector<CStdString> vecSkinPath;
2076 g_SkinInfo->GetSkinPaths(vecSkinPath);
2077 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2079 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2080 CFileItemList items;
2081 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2083 for (int i = 0; i < items.Size(); ++i)
2085 if (items[i]->m_bIsFolder)
2087 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2088 if (skinFile.Left(6).CompareNoCase("custom") == 0)
2090 CXBMCTinyXML xmlDoc;
2091 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2093 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2097 // Root element should be <window>
2098 TiXmlElement* pRootElement = xmlDoc.RootElement();
2099 CStdString strValue = pRootElement->Value();
2100 if (!strValue.Equals("window"))
2102 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2106 // Read the <type> element to get the window type to create
2107 // If no type is specified, create a CGUIWindow as default
2108 CGUIWindow* pWindow = NULL;
2110 if (pRootElement->Attribute("type"))
2111 strType = pRootElement->Attribute("type");
2114 const TiXmlNode *pType = pRootElement->FirstChild("type");
2115 if (pType && pType->FirstChild())
2116 strType = pType->FirstChild()->Value();
2118 int id = WINDOW_INVALID;
2119 if (!pRootElement->Attribute("id", &id))
2121 const TiXmlNode *pType = pRootElement->FirstChild("id");
2122 if (pType && pType->FirstChild())
2123 id = atol(pType->FirstChild()->Value());
2125 CStdString visibleCondition;
2126 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2128 if (strType.Equals("dialog"))
2129 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2130 else if (strType.Equals("submenu"))
2131 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2132 else if (strType.Equals("buttonmenu"))
2133 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2135 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2137 // Check to make sure the pointer isn't still null
2138 if (pWindow == NULL)
2140 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2143 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2148 pWindow->SetVisibleCondition(visibleCondition);
2149 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2150 g_windowManager.AddCustomWindow(pWindow);
2158 bool CApplication::RenderNoPresent()
2162 // DXMERGE: This may have been important?
2163 // g_graphicsContext.AcquireCurrentContext();
2165 g_graphicsContext.Lock();
2167 // dont show GUI when playing full screen video
2168 if (g_graphicsContext.IsFullScreenVideo())
2170 if (m_bPresentFrame && IsPlaying() && !IsPaused())
2173 g_renderManager.Present();
2176 g_renderManager.RenderUpdate(true);
2178 // close window overlays
2179 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2180 if (overlay) overlay->Close(true);
2181 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2182 if (overlay) overlay->Close(true);
2186 bool hasRendered = g_windowManager.Render();
2188 g_graphicsContext.Unlock();
2193 float CApplication::GetDimScreenSaverLevel() const
2195 if (!m_bScreenSave || !m_screenSaver ||
2196 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2197 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2198 !m_screenSaver->ID().empty()))
2201 if (!m_screenSaver->GetSetting("level").IsEmpty())
2202 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2206 bool CApplication::WaitFrame(unsigned int timeout)
2210 // Wait for all other frames to be presented
2211 CSingleLock lock(m_frameMutex);
2212 //wait until event is set, but modify remaining time
2214 TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
2215 cv.wait(lock,timeout);
2216 done = m_frameCount == 0;
2221 void CApplication::NewFrame()
2223 // We just posted another frame. Keep track and notify.
2225 CSingleLock lock(m_frameMutex);
2229 m_frameCond.notifyAll();
2232 void CApplication::Render()
2234 // do not render if we are stopped
2238 if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
2247 int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
2249 bool decrement = false;
2250 bool hasRendered = false;
2251 bool limitFrames = false;
2252 unsigned int singleFrameTime = 10; // default limit 100 fps
2256 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2257 // Whether externalplayer is playing and we're unfocused
2258 bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
2260 m_bPresentFrame = false;
2261 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
2263 CSingleLock lock(m_frameMutex);
2265 TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
2268 m_bPresentFrame = m_frameCount > 0;
2269 decrement = m_bPresentFrame;
2274 // engage the frame limiter as needed
2275 limitFrames = lowfps || extPlayerActive;
2276 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2277 // perhaps allowing it to be set differently than the UI option??
2278 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2279 limitFrames = true; // not using vsync.
2280 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2281 limitFrames = true; // using vsync, but it isn't working.
2285 if (extPlayerActive)
2287 ResetScreenSaver(); // Prevent screensaver dimming the screen
2288 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2291 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2298 CSingleLock lock(g_graphicsContext);
2299 g_infoManager.UpdateFPS();
2301 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2302 g_Windowing.SetVSync(true);
2303 else if (vsync_mode == VSYNC_ALWAYS)
2304 g_Windowing.SetVSync(true);
2305 else if (vsync_mode != VSYNC_DRIVER)
2306 g_Windowing.SetVSync(false);
2308 if(!g_Windowing.BeginRender())
2311 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2312 if (RenderNoPresent())
2315 g_Windowing.EndRender();
2317 // reset our info cache - we do this at the end of Render so that it is
2318 // fresh for the next process(), or after a windowclose animation (where process()
2320 g_infoManager.ResetCache();
2323 unsigned int now = XbmcThreads::SystemClockMillis();
2325 m_lastRenderTime = now;
2327 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2328 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2330 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2331 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2335 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2336 if (limitFrames || !flip)
2339 singleFrameTime = 40; //if not flipping, loop at 25 fps
2341 unsigned int frameTime = now - m_lastFrameTime;
2342 if (frameTime < singleFrameTime)
2343 Sleep(singleFrameTime - frameTime);
2345 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2348 g_graphicsContext.Flip(dirtyRegions);
2349 CTimeUtils::UpdateFrameTime(flip);
2351 g_TextureManager.FreeUnusedTextures();
2353 g_renderManager.UpdateResolution();
2354 g_renderManager.ManageCaptures();
2357 CSingleLock lock(m_frameMutex);
2358 if(m_frameCount > 0 && decrement)
2361 m_frameCond.notifyAll();
2364 void CApplication::SetStandAlone(bool value)
2366 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2369 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2370 // The window manager will return true if the event is processed, false otherwise.
2371 // If not already processed, this routine handles global keypresses. It returns
2372 // true if the key has been processed, false otherwise.
2374 bool CApplication::OnKey(const CKey& key)
2377 // Turn the mouse off, as we've just got a keypress from controller or remote
2378 g_Mouse.SetActive(false);
2380 // get the current active window
2381 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2383 // this will be checked for certain keycodes that need
2384 // special handling if the screensaver is active
2385 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2387 // a key has been pressed.
2389 m_idleTimer.StartZero();
2390 bool processKey = AlwaysProcess(action);
2394 // allow some keys to be processed while the screensaver is active
2395 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2397 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2401 // change this if we have a dialog up
2402 if (g_windowManager.HasModalDialog())
2404 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2406 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2407 { // fullscreen info dialog - special case
2408 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2410 if (!key.IsAnalogButton())
2411 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2413 if (OnAction(action))
2416 // fallthrough to the main window
2417 iWin = WINDOW_FULLSCREEN_VIDEO;
2419 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2421 // current active window is full screen video.
2422 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2424 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2425 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2427 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2429 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2430 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2432 // if no PVR specific action/mapping is found, fall back to default
2433 if (action.GetID() == 0)
2434 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2438 // in any other case use the fullscreen window section of keymap.xml to map key->action
2439 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2444 // current active window isnt the fullscreen window
2445 // just use corresponding section from keymap.xml
2446 // to map key->action
2448 // first determine if we should use keyboard input directly
2449 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2450 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2453 CGUIControl *control = window->GetFocusedControl();
2456 // If this is an edit control set usekeyboard to true. This causes the
2457 // keypress to be processed directly not through the key mappings.
2458 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2461 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2462 // This causes the keypress to be used for list navigation.
2463 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2469 action = CAction(0); // reset our action
2470 if (g_guiSettings.GetBool("input.remoteaskeyboard"))
2472 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2473 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2474 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2475 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2476 action.GetID() == ACTION_MOVE_RIGHT ||
2477 action.GetID() == ACTION_MOVE_UP ||
2478 action.GetID() == ACTION_MOVE_DOWN ||
2479 action.GetID() == ACTION_SELECT_ITEM ||
2480 action.GetID() == ACTION_ENTER ||
2481 action.GetID() == ACTION_PREVIOUS_MENU ||
2482 action.GetID() == ACTION_NAV_BACK))
2484 // the action isn't plain navigation - check for a keyboard-specific keymap
2485 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2486 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2487 action.GetID() == ACTION_BACKSPACE ||
2488 action.GetID() == ACTION_SHIFT ||
2489 action.GetID() == ACTION_SYMBOLS ||
2490 action.GetID() == ACTION_CURSOR_LEFT ||
2491 action.GetID() == ACTION_CURSOR_RIGHT)
2492 action = CAction(0); // don't bother with this action
2495 if (!action.GetID())
2497 // keyboard entry - pass the keys through directly
2498 if (key.GetFromService())
2499 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2501 { // see if we've got an ascii key
2502 if (key.GetUnicode())
2503 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2505 action = CAction(key.GetVKey() | KEY_VKEY);
2509 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2511 if (OnAction(action))
2513 // failed to handle the keyboard action, drop down through to standard action
2515 if (key.GetFromService())
2517 if (key.GetButtonCode() != KEY_INVALID)
2518 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2521 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2523 if (!key.IsAnalogButton())
2524 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2526 bool bResult = false;
2528 // play sound before the action unless the button is held,
2529 // where we execute after the action as held actions aren't fired every time.
2530 if(action.GetHoldTime())
2532 bResult = OnAction(action);
2534 g_audioManager.PlayActionSound(action);
2538 g_audioManager.PlayActionSound(action);
2539 bResult = OnAction(action);
2545 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2546 // This needs to return true if it processed the appcommand or false if it didn't
2547 bool CApplication::OnAppCommand(const CAction &action)
2549 // Reset the screen saver
2552 // If we were currently in the screen saver wake up and don't process the appcommand
2553 if (WakeUpScreenSaverAndDPMS())
2556 // The action ID is the APPCOMMAND code. We need to retrieve the action
2557 // associated with this appcommand from the mapping table.
2558 uint32_t appcmd = action.GetID();
2559 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2560 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2561 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2563 // If we couldn't find an action return false to indicate we have not
2564 // handled this appcommand
2565 if (!appcmdaction.GetID())
2567 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2571 // Process the appcommand
2572 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2573 OnAction(appcmdaction);
2575 // Always return true regardless of whether the action succeeded or not.
2576 // This stops Windows handling the appcommand itself.
2580 bool CApplication::OnAction(const CAction &action)
2582 // special case for switching between GUI & fullscreen mode.
2583 if (action.GetID() == ACTION_SHOW_GUI)
2584 { // Switch to fullscreen mode if we can
2585 if (SwitchToFullScreen())
2587 m_navigationTimer.StartZero();
2592 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2594 g_graphicsContext.ToggleFullScreenRoot();
2598 if (action.IsMouse())
2599 g_Mouse.SetActive(true);
2601 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2602 // playing or ACTION_PLAYER_PLAY if we are not playing.
2603 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2606 return OnAction(CAction(ACTION_PAUSE));
2608 return OnAction(CAction(ACTION_PLAYER_PLAY));
2611 //if the action would start or stop inertial scrolling
2612 //by gesture - bypass the normal OnAction handler of current window
2613 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2616 // just pass the action to the current window and let it handle it
2617 if (g_windowManager.OnAction(action))
2619 m_navigationTimer.StartZero();
2624 // handle extra global presses
2626 // screenshot : take a screenshot :)
2627 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2629 CScreenShot::TakeScreenshot();
2632 // built in functions : execute the built-in
2633 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2635 CBuiltins::Execute(action.GetName());
2636 m_navigationTimer.StartZero();
2641 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2643 CButtonTranslator::GetInstance().Clear();
2644 CButtonTranslator::GetInstance().Load();
2647 // show info : Shows the current video or song information
2648 if (action.GetID() == ACTION_SHOW_INFO)
2650 g_infoManager.ToggleShowInfo();
2654 // codec info : Shows the current song, video or picture codec information
2655 if (action.GetID() == ACTION_SHOW_CODEC)
2657 g_infoManager.ToggleShowCodec();
2661 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2663 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2666 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2667 char rating = tag->GetRating();
2668 bool needsUpdate(false);
2669 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2671 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2674 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2676 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2682 if (db.Open()) // OpenForWrite() ?
2684 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2687 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2688 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2689 g_windowManager.SendMessage(msg);
2695 // stop : stops playing current audio song
2696 if (action.GetID() == ACTION_STOP)
2702 // previous : play previous song from playlist
2703 if (action.GetID() == ACTION_PREV_ITEM)
2705 // first check whether we're within 3 seconds of the start of the track
2706 // if not, we just revert to the start of the track
2707 if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2714 g_playlistPlayer.PlayPrevious();
2719 // next : play next song from playlist
2720 if (action.GetID() == ACTION_NEXT_ITEM)
2722 if (IsPlaying() && m_pPlayer->SkipNext())
2728 g_playlistPlayer.PlayNext();
2735 // forward channel switches to the player - he knows what to do
2736 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2738 m_pPlayer->OnAction(action);
2742 // pause : pauses current audio song
2743 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2747 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2749 if (!m_pPlayer->IsPaused())
2750 { // unpaused - set the playspeed back to normal
2753 g_audioManager.Enable(m_pPlayer->IsPaused());
2756 if (!m_pPlayer->IsPaused())
2758 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2759 // if we are playing at normal speed, then allow play to pause
2760 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2762 if (m_iPlaySpeed != 1)
2772 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2774 int iPlaySpeed = m_iPlaySpeed;
2775 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2777 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2779 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2784 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2786 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2789 SetPlaySpeed(iPlaySpeed);
2792 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2794 // calculate the speed based on the amount the button is held down
2795 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2796 // returns 0 -> MAX_FFWD_SPEED
2797 int iSpeed = 1 << iPower;
2798 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2800 g_application.SetPlaySpeed(iSpeed);
2802 CLog::Log(LOGDEBUG,"Resetting playspeed");
2806 // allow play to unpause
2809 if (action.GetID() == ACTION_PLAYER_PLAY)
2811 // unpause, and set the playspeed back to normal
2813 g_audioManager.Enable(m_pPlayer->IsPaused());
2815 g_application.SetPlaySpeed(1);
2821 if (g_peripherals.OnAction(action))
2824 if (action.GetID() == ACTION_MUTE)
2830 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2832 switch(g_guiSettings.GetInt("audiooutput.mode"))
2834 case AUDIO_ANALOG: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958); break;
2835 case AUDIO_IEC958: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); break;
2836 case AUDIO_HDMI : g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG); break;
2839 g_application.Restart();
2840 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2842 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2843 g_windowManager.SendMessage(msg);
2848 // Check for global volume control
2849 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2851 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2853 if (g_settings.m_bMute)
2855 float volume = g_settings.m_fVolumeLevel;
2856 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2857 if (action.GetRepeat())
2858 step *= action.GetRepeat() * 50; // 50 fps
2860 if (action.GetID() == ACTION_VOLUME_UP)
2861 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2863 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2865 SetVolume(volume, false);
2867 // show visual feedback of volume change...
2868 ShowVolumeBar(&action);
2871 // Check for global seek control
2872 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2874 if (!m_pPlayer->CanSeek()) return false;
2875 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2878 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2880 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2881 CGUIControlProfiler::Instance().Start();
2884 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2886 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2887 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2888 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2889 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2890 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2896 void CApplication::UpdateLCD()
2899 static unsigned int lTickCount = 0;
2901 if (!g_lcd || !g_guiSettings.GetBool("videoscreen.haslcd"))
2903 unsigned int lTimeOut = 1000;
2904 if ( m_iPlaySpeed != 1)
2906 if ( (XbmcThreads::SystemClockMillis() - lTickCount) >= lTimeOut)
2908 if (g_application.NavigationIdleTime() < 5)
2909 g_lcd->Render(ILCD::LCD_MODE_NAVIGATION);
2910 else if (g_PVRManager.IsPlayingTV())
2911 g_lcd->Render(ILCD::LCD_MODE_PVRTV);
2912 else if (g_PVRManager.IsPlayingRadio())
2913 g_lcd->Render(ILCD::LCD_MODE_PVRRADIO);
2914 else if (IsPlayingVideo())
2915 g_lcd->Render(ILCD::LCD_MODE_VIDEO);
2916 else if (IsPlayingAudio())
2917 g_lcd->Render(ILCD::LCD_MODE_MUSIC);
2918 else if (IsInScreenSaver())
2919 g_lcd->Render(ILCD::LCD_MODE_SCREENSAVER);
2921 g_lcd->Render(ILCD::LCD_MODE_GENERAL);
2924 lTickCount = XbmcThreads::SystemClockMillis();
2929 void CApplication::FrameMove(bool processEvents, bool processGUI)
2935 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2936 float frameTime = m_frameTime.GetElapsedSeconds();
2937 m_frameTime.StartZero();
2938 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2939 if( frameTime > 0.5 ) frameTime = 0.5;
2941 if (processGUI && m_renderGUI)
2943 g_graphicsContext.Lock();
2944 // check if there are notifications to display
2945 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2946 if (toast && toast->DoWork())
2948 if (!toast->IsDialogRunning())
2953 g_graphicsContext.Unlock();
2954 CWinEvents::MessagePump();
2959 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2960 // Read the input from a remote
2961 g_RemoteControl.Update();
2964 // process input actions
2965 ProcessRemote(frameTime);
2966 ProcessGamepad(frameTime);
2967 ProcessEventServer(frameTime);
2968 ProcessPeripherals(frameTime);
2969 if (processGUI && m_renderGUI)
2971 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2972 m_seekHandler->Process();
2975 if (processGUI && m_renderGUI)
2978 g_windowManager.Process(CTimeUtils::GetFrameTime());
2979 g_windowManager.FrameMove();
2983 bool CApplication::ProcessGamepad(float frameTime)
2985 #ifdef HAS_SDL_JOYSTICK
2989 int iWin = GetActiveWindowID();
2991 g_Joystick.Update();
2992 if (g_Joystick.GetButton(bid))
2995 m_idleTimer.StartZero();
2998 if (WakeUpScreenSaverAndDPMS())
3000 g_Joystick.Reset(true);
3005 CStdString actionName;
3007 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3009 CAction action(actionID, 1.0f, 0.0f, actionName);
3010 g_audioManager.PlayActionSound(action);
3012 g_Mouse.SetActive(false);
3013 return OnAction(action);
3020 if (g_Joystick.GetAxis(bid))
3022 if (g_Joystick.GetAmount() < 0)
3028 CStdString actionName;
3030 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3033 if (WakeUpScreenSaverAndDPMS())
3038 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3039 g_audioManager.PlayActionSound(action);
3041 g_Mouse.SetActive(false);
3042 return OnAction(action);
3046 g_Joystick.ResetAxis(abs(bid));
3050 if (g_Joystick.GetHat(bid, position))
3053 m_idleTimer.StartZero();
3056 if (WakeUpScreenSaverAndDPMS())
3063 CStdString actionName;
3066 bid = position<<16|bid;
3068 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3070 CAction action(actionID, 1.0f, 0.0f, actionName);
3071 g_audioManager.PlayActionSound(action);
3073 g_Mouse.SetActive(false);
3074 return OnAction(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
3122 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3123 if (g_windowManager.HasModalDialog())
3124 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3126 iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3127 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3129 // If we couldn't find an action return false to indicate we have not
3130 // handled this mouse action
3131 if (!mouseaction.GetID())
3133 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3137 // Log mouse actions except for move and noop
3138 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3139 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3141 // The action might not be a mouse action. For example wheel moves might
3142 // be mapped to volume up/down in mouse.xml. In this case we do not want
3143 // the mouse position saved in the action.
3144 if (!mouseaction.IsMouse())
3145 return OnAction(mouseaction);
3147 // This is a mouse action so we need to record the mouse position
3148 return OnAction(CAction(mouseaction.GetID(),
3149 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3150 (float)g_Mouse.GetX(),
3151 (float)g_Mouse.GetY(),
3152 (float)g_Mouse.GetDX(),
3153 (float)g_Mouse.GetDY(),
3154 mouseaction.GetName()));
3157 bool CApplication::ProcessEventServer(float frameTime)
3159 #ifdef HAS_EVENT_SERVER
3160 CEventServer* es = CEventServer::GetInstance();
3161 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3164 // process any queued up actions
3165 if (es->ExecuteNextAction())
3167 // reset idle timers
3168 m_idleTimer.StartZero();
3170 WakeUpScreenSaverAndDPMS();
3173 // now handle any buttons or axis
3174 std::string joystickName;
3175 bool isAxis = false;
3176 float fAmount = 0.0;
3178 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3179 // when the action exits XBMC
3180 es = CEventServer::GetInstance();
3181 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3183 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3187 if (joystickName.length() > 0)
3191 if (fabs(fAmount) >= 0.08)
3192 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3194 m_lastAxisMap[joystickName].erase(wKeyID);
3197 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
3202 if (wKeyID & ES_FLAG_UNICODE)
3204 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3208 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3209 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3210 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3211 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3213 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3214 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3215 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3216 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3217 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3219 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3221 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3222 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3223 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3224 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3225 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3226 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3227 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3230 key.SetFromService(true);
3235 if (m_lastAxisMap.size() > 0)
3237 // Process all the stored axis.
3238 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3240 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3241 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3247 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3248 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3254 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount, unsigned int holdTime /*=0*/)
3256 #if defined(HAS_EVENT_SERVER)
3257 m_idleTimer.StartZero();
3259 // Make sure to reset screen saver, mouse.
3261 if (WakeUpScreenSaverAndDPMS())
3264 #ifdef HAS_SDL_JOYSTICK
3267 g_Mouse.SetActive(false);
3269 int iWin = GetActiveWindowID();
3271 CStdString actionName;
3272 bool fullRange = false;
3274 // Translate using regular joystick translator.
3275 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3277 CAction action(actionID, fAmount, 0.0f, actionName, holdTime);
3278 bool bResult = false;
3280 // play sound before the action unless the button is held,
3281 // where we execute after the action as held actions aren't fired every time.
3282 if(action.GetHoldTime())
3284 bResult = OnAction(action);
3286 g_audioManager.PlayActionSound(action);
3290 g_audioManager.PlayActionSound(action);
3291 bResult = OnAction(action);
3298 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3305 int CApplication::GetActiveWindowID(void)
3307 // Get the currently active window
3308 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3310 // If there is a dialog active get the dialog id instead
3311 if (g_windowManager.HasModalDialog())
3312 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3314 // If the window is FullScreenVideo check if we're in a DVD menu
3315 if (iWin == WINDOW_FULLSCREEN_VIDEO && g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
3316 iWin = WINDOW_VIDEO_MENU;
3318 // Return the window id
3322 bool CApplication::Cleanup()
3326 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3327 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3328 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3329 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3330 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3331 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3332 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3333 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3334 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3335 g_windowManager.Delete(WINDOW_FILES);
3336 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3337 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3338 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3339 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3340 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3341 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3342 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3343 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3344 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3345 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3346 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3347 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3348 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3349 g_windowManager.Delete(WINDOW_DIALOG_OK);
3350 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3351 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3352 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3353 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3354 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3355 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3356 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3357 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3358 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3359 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3360 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3361 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3362 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3363 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3364 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3365 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3366 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3367 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3368 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3369 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3370 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3371 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3373 /* Delete PVR related windows and dialogs */
3374 g_windowManager.Delete(WINDOW_PVR);
3375 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3376 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3377 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3378 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3379 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3380 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3381 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3382 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3383 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3387 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3389 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3390 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3391 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3392 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3393 g_windowManager.Delete(WINDOW_VISUALISATION);
3394 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3395 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3396 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3397 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3398 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3399 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3400 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3401 g_windowManager.Delete(WINDOW_SCREENSAVER);
3402 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3403 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3404 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3405 g_windowManager.Delete(WINDOW_SLIDESHOW);
3406 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3407 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3409 g_windowManager.Delete(WINDOW_HOME);
3410 g_windowManager.Delete(WINDOW_PROGRAMS);
3411 g_windowManager.Delete(WINDOW_PICTURES);
3412 g_windowManager.Delete(WINDOW_WEATHER);
3414 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3415 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3416 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3417 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3418 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3419 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3420 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3421 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3422 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3423 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3425 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3426 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3428 CAddonMgr::Get().DeInit();
3430 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3431 CLog::Log(LOGNOTICE, "closing down remote control service");
3432 g_RemoteControl.Disconnect();
3435 CLog::Log(LOGNOTICE, "unload sections");
3437 #ifdef HAS_PERFORMANCE_SAMPLE
3438 CLog::Log(LOGNOTICE, "performance statistics");
3439 m_perfStats.DumpStats();
3442 // Shutdown as much as possible of the
3443 // application, to reduce the leaks dumped
3444 // to the vc output window before calling
3445 // _CrtDumpMemoryLeaks(). Most of the leaks
3446 // shown are no real leaks, as parts of the app
3447 // are still allocated.
3449 g_localizeStrings.Clear();
3450 g_LangCodeExpander.Clear();
3451 g_charsetConverter.clear();
3452 g_directoryCache.Clear();
3453 CButtonTranslator::GetInstance().Clear();
3454 CLastfmScrobbler::RemoveInstance();
3455 CLibrefmScrobbler::RemoveInstance();
3456 CLastFmManager::RemoveInstance();
3457 #ifdef HAS_EVENT_SERVER
3458 CEventServer::RemoveInstance();
3460 DllLoaderContainer::Clear();
3461 g_playlistPlayer.Clear();
3463 g_guiSettings.Clear();
3464 g_advancedSettings.Clear();
3467 CXHandle::DumpObjectTracker();
3469 #if defined(TARGET_ANDROID)
3470 // enable for all platforms once it's safe
3471 g_sectionLoader.UnloadAll();
3473 #ifdef _CRTDBG_MAP_ALLOC
3474 _CrtDumpMemoryLeaks();
3475 while(1); // execution ends
3481 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3486 void CApplication::Stop(int exitCode)
3490 CVariant vExitCode(exitCode);
3491 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3493 SaveFileState(true);
3495 // cancel any jobs from the jobmanager
3496 CJobManager::GetInstance().CancelJobs();
3498 g_alarmClock.StopThread();
3500 if( m_bSystemScreenSaverEnable )
3501 g_Windowing.EnableSystemScreenSaver(true);
3503 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3504 g_settings.m_iSystemTimeTotalUp = g_settings.m_iSystemTimeTotalUp + (int)(CTimeUtils::GetFrameTime() / 60000);
3506 // Update the settings information (volume, uptime etc. need saving)
3507 if (CFile::Exists(g_settings.GetSettingsFile()))
3509 CLog::Log(LOGNOTICE, "Saving settings");
3513 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3516 m_AppActive = false;
3517 m_AppFocused = false;
3518 m_ExitCode = exitCode;
3519 CLog::Log(LOGNOTICE, "stop all");
3521 // stop scanning before we kill the network and so on
3522 if (m_musicInfoScanner->IsScanning())
3523 m_musicInfoScanner->Stop();
3525 if (m_videoInfoScanner->IsScanning())
3526 m_videoInfoScanner->Stop();
3528 CApplicationMessenger::Get().Cleanup();
3534 #ifdef HAS_WEB_SERVER
3535 CWebServer::UnregisterRequestHandler(&m_httpImageHandler);
3536 CWebServer::UnregisterRequestHandler(&m_httpVfsHandler);
3538 CWebServer::UnregisterRequestHandler(&m_httpJsonRpcHandler);
3540 #ifdef HAS_WEB_INTERFACE
3541 CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceAddonsHandler);
3542 CWebServer::UnregisterRequestHandler(&m_httpWebinterfaceHandler);
3548 CLog::Log(LOGNOTICE, "stop player");
3553 #if HAS_FILESYTEM_DAAP
3554 CLog::Log(LOGNOTICE, "stop daap clients");
3555 g_DaapClient.Release();
3557 #ifdef HAS_FILESYSTEM_SAP
3558 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3559 g_sapsessions.StopThread();
3562 if(CZeroconfBrowser::IsInstantiated())
3564 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3565 CZeroconfBrowser::GetInstance()->Stop();
3566 CZeroconfBrowser::ReleaseInstance();
3570 CLog::Log(LOGNOTICE, "clean cached files!");
3571 #ifdef HAS_FILESYSTEM_RAR
3572 g_RarManager.ClearCache(true);
3575 #ifdef HAS_FILESYSTEM_SFTP
3576 CSFTPSessionManager::DisconnectAllSessions();
3579 CLog::Log(LOGNOTICE, "unload skin");
3582 #if defined(TARGET_DARWIN_OSX)
3583 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3584 XBMCHelper::GetInstance().Stop();
3587 #if defined(HAVE_LIBCRYSTALHD)
3588 CCrystalHD::RemoveInstance();
3591 g_mediaManager.Stop();
3593 // Stop services before unloading Python
3594 CAddonMgr::Get().StopServices(false);
3596 /* Python resource freeing must be done after skin has been unloaded, not before
3597 some windows still need it when deinitializing during skin unloading. */
3599 CLog::Log(LOGNOTICE, "stop python");
3600 g_pythonParser.FreeResources();
3611 g_Windowing.DestroyRenderSystem();
3612 g_Windowing.DestroyWindow();
3613 g_Windowing.DestroyWindowSystem();
3615 // shutdown the AudioEngine
3616 CAEFactory::Shutdown();
3618 CLog::Log(LOGNOTICE, "stopped");
3622 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3625 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3626 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3633 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3635 //If item is a plugin, expand out now and run ourselves again
3636 if (item.IsPlugin())
3638 CFileItem item_new(item);
3639 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3640 return PlayMedia(item_new, iPlaylist);
3643 if (item.IsLastFM())
3645 g_partyModeManager.Disable();
3646 return CLastFmManager::GetInstance()->ChangeStation(item.GetAsUrl());
3648 if (item.IsSmartPlayList())
3650 CFileItemList items;
3651 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3654 CSmartPlaylist smartpl;
3655 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3656 smartpl.OpenAndReadName(item.GetPath());
3658 playlist.Add(items);
3659 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3662 else if (item.IsPlayList() || item.IsInternetStream())
3664 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3666 //is or could be a playlist
3667 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3668 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3673 if (dlgCache->IsCanceled())
3680 if (iPlaylist != PLAYLIST_NONE)
3683 if (item.HasProperty("playlist_starting_track"))
3684 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3685 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3689 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());
3690 if(pPlayList->size())
3691 return PlayFile(*(*pPlayList)[0], false);
3696 //nothing special just play
3697 return PlayFile(item, false);
3701 // For playing a multi-file video. Particularly inefficient
3702 // on startup, as we are required to calculate the length
3703 // of each video, so we open + close each one in turn.
3704 // A faster calculation of video time would improve this
3706 bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3708 if (!item.IsStack())
3713 // case 1: stacked ISOs
3714 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3716 CStackDirectory dir;
3717 CFileItemList movieList;
3718 dir.GetDirectory(item.GetPath(), movieList);
3720 // first assume values passed to the stack
3721 int selectedFile = item.m_lStartPartNumber;
3722 int startoffset = item.m_lStartOffset;
3724 // check if we instructed the stack to resume from default
3725 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3730 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3732 startoffset = (int)(bookmark.timeInSeconds*75);
3733 selectedFile = bookmark.partNumber;
3738 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3741 // make sure that the selected part is within the boundaries
3742 if (selectedFile <= 0)
3744 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3747 else if (selectedFile > movieList.Size())
3749 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3750 selectedFile = movieList.Size();
3753 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3754 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3755 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3756 *m_stackFileItemToUpdate = item;
3757 return PlayFile(*(movieList[selectedFile - 1]));
3759 // case 2: all other stacks
3762 // see if we have the info in the database
3763 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3764 // then these times will be wrong.
3765 // Also, this is really just a hack for the slow load up times we have
3766 // A much better solution is a fast reader of FPS and fileLength
3767 // that we can use on a file to get it's time.
3769 bool haveTimes(false);
3773 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3774 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3779 // calculate the total time of the stack
3780 CStackDirectory dir;
3781 dir.GetDirectory(item.GetPath(), *m_currentStack);
3783 for (int i = 0; i < m_currentStack->Size(); i++)
3786 (*m_currentStack)[i]->m_lEndOffset = times[i];
3790 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3792 m_currentStack->Clear();
3795 totalTime += duration / 1000;
3796 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3797 times.push_back(totalTime);
3801 double seconds = item.m_lStartOffset / 75.0;
3803 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3804 { // have our times now, so update the dB
3808 dbs.SetStackTimes(item.GetPath(), times);
3810 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3812 // can only resume seek here, not dvdstate
3814 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3815 seconds = bookmark.timeInSeconds;
3823 *m_itemCurrentFile = item;
3824 m_currentStackPosition = 0;
3825 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3829 // work out where to seek to
3830 for (int i = 0; i < m_currentStack->Size(); i++)
3832 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3834 CFileItem item(*(*m_currentStack)[i]);
3835 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3836 item.m_lStartOffset = (long)(seconds - start) * 75;
3837 m_currentStackPosition = i;
3838 return PlayFile(item, true);
3843 return PlayFile(*(*m_currentStack)[0], true);
3848 bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
3852 SaveCurrentFileSettings();
3854 OutputDebugString("new file set audiostream:0\n");
3855 // Switch to default options
3856 g_settings.m_currentVideoSettings = g_settings.m_defaultVideoSettings;
3857 // see if we have saved options in the database
3860 *m_itemCurrentFile = item;
3861 m_nextPlaylistItem = -1;
3862 m_currentStackPosition = 0;
3863 m_currentStack->Clear();
3866 CUtil::ClearSubtitles();
3869 if (item.IsDiscStub())
3871 #ifdef HAS_DVD_DRIVE
3872 // Display the Play Eject dialog if there is any optical disc drive
3873 if (g_mediaManager.HasOpticalDrive())
3875 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3876 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3877 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3878 return MEDIA_DETECT::CAutorun::PlayDiscAskResume();
3882 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3887 if (item.IsPlayList())
3890 if (item.IsPlugin())
3891 { // we modify the item so that it becomes a real URL
3892 CFileItem item_new(item);
3893 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3894 return PlayFile(item_new, false);
3899 if (URIUtils::IsUPnP(item.GetPath()))
3901 CFileItem item_new(item);
3902 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3903 return PlayFile(item_new, false);
3908 // if we have a stacked set of files, we need to setup our stack routines for
3909 // "seamless" seeking and total time of the movie etc.
3910 // will recall with restart set to true
3912 return PlayStack(item, bRestart);
3914 //Is TuxBox, this should probably be moved to CTuxBoxFile
3917 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3919 if(g_tuxboxService.IsRunning())
3920 g_tuxboxService.Stop();
3923 if(g_tuxbox.CreateNewItem(item, item_new))
3926 // Make sure it doesn't have a player
3927 // so we actually select one normally
3928 m_eCurrentPlayer = EPC_NONE;
3930 // keep the tuxbox:// url as playing url
3931 // and give the new url to the player
3932 if(PlayFile(item_new, true))
3934 if(!g_tuxboxService.IsRunning())
3935 g_tuxboxService.Start();
3942 CPlayerOptions options;
3944 if( item.HasProperty("StartPercent") )
3946 double fallback = 0.0f;
3947 if(item.GetProperty("StartPercent").isString())
3948 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3949 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3952 PLAYERCOREID eNewCore = EPC_NONE;
3955 // have to be set here due to playstack using this for starting the file
3956 options.starttime = item.m_lStartOffset / 75.0;
3957 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3958 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3960 if( m_eForcedNextPlayer != EPC_NONE )
3961 eNewCore = m_eForcedNextPlayer;
3962 else if( m_eCurrentPlayer == EPC_NONE )
3963 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3965 eNewCore = m_eCurrentPlayer;
3969 options.starttime = item.m_lStartOffset / 75.0;
3973 // open the d/b and retrieve the bookmarks for the current movie
3976 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3978 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3980 options.starttime = 0.0f;
3982 CStdString path = item.GetPath();
3983 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3984 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3985 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3986 path = item.GetProperty("original_listitem_url").asString();
3987 if(dbs.GetResumeBookMark(path, bookmark))
3989 options.starttime = bookmark.timeInSeconds;
3990 options.state = bookmark.playerState;
3993 override with information from the actual item if available. We do this as the VFS (eg plugins)
3994 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3995 should the playerState be required, it is fetched from the database.
3996 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3998 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3999 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
4001 else if (item.HasVideoInfoTag())
4003 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4005 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4008 dbs.GetBookMarkForEpisode(*tag, bookmark);
4009 options.starttime = bookmark.timeInSeconds;
4010 options.state = bookmark.playerState;
4017 if (m_eForcedNextPlayer != EPC_NONE)
4018 eNewCore = m_eForcedNextPlayer;
4020 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
4023 // this really aught to be inside !bRestart, but since PlayStack
4024 // uses that to init playback, we have to keep it outside
4025 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4026 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4027 { // playing from a playlist by the looks
4028 // don't switch to fullscreen if we are not playing the first item...
4029 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4031 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4033 // TODO - this will fail if user seeks back to first file in stack
4034 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4035 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4037 options.fullscreen = false;
4038 // reset this so we don't think we are resuming on seek
4039 m_itemCurrentFile->m_lStartOffset = 0;
4042 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
4044 // reset m_bStartVideoWindowed as it's a temp setting
4045 g_settings.m_bStartVideoWindowed = false;
4046 // reset any forced player
4047 m_eForcedNextPlayer = EPC_NONE;
4050 //We have to stop parsing a cdg before mplayer is deallocated
4051 // WHY do we have to do this????
4053 m_pKaraokeMgr->Stop();
4056 // tell system we are starting a file
4057 m_bPlaybackStarting = true;
4059 // We should restart the player, unless the previous and next tracks are using
4060 // one of the players that allows gapless playback (paplayer, dvdplayer)
4063 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER
4064 #if defined(HAS_OMXPLAYER)
4065 || m_eCurrentPlayer == EPC_OMXPLAYER
4076 m_eCurrentPlayer = eNewCore;
4077 m_pPlayer = CPlayerCoreFactory::CreatePlayer(eNewCore, *this);
4083 // don't hold graphicscontext here since player
4084 // may wait on another thread, that requires gfx
4085 CSingleExit ex(g_graphicsContext);
4086 bResult = m_pPlayer->OpenFile(item, options);
4090 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4096 if (m_iPlaySpeed != 1)
4098 int iSpeed = m_iPlaySpeed;
4100 SetPlaySpeed(iSpeed);
4103 if( IsPlayingAudio() )
4105 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4106 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4109 #ifdef HAS_VIDEO_PLAYBACK
4110 if( IsPlayingVideo() )
4112 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4113 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4115 // if player didn't manange to switch to fullscreen by itself do it here
4116 if( options.fullscreen && g_renderManager.IsStarted()
4117 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4118 SwitchToFullScreen();
4120 if (!item.IsDVDImage() && !item.IsDVDFile())
4122 CVideoInfoTag *details = m_itemCurrentFile->GetVideoInfoTag();
4123 // Save information about the stream if we currently have no data
4124 if (!details->HasStreamDetails() ||
4125 details->m_streamDetails.GetVideoDuration() <= 0)
4127 if (m_pPlayer->GetStreamDetails(details->m_streamDetails) && details->HasStreamDetails())
4131 dbs.SetStreamDetailsForFileId(details->m_streamDetails, details->m_iFileId);
4133 CUtil::DeleteVideoDatabaseDirectoryCache();
4140 #if !defined(TARGET_DARWIN) && !defined(_LINUX)
4141 g_audioManager.Enable(false);
4144 if (item.HasPVRChannelInfoTag())
4145 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4147 m_bPlaybackStarting = false;
4151 // we must have started, otherwise player might send this later
4153 OnPlayBackStarted();
4159 // we send this if it isn't playlistplayer that is doing this
4160 int next = g_playlistPlayer.GetNextSong();
4161 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4164 OnPlayBackStopped();
4170 void CApplication::OnPlayBackEnded()
4172 if(m_bPlaybackStarting)
4175 if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4176 CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
4178 // informs python script currently running playback has ended
4179 // (does nothing if python is not loaded)
4181 g_pythonParser.OnPlayBackEnded();
4184 CVariant data(CVariant::VariantTypeObject);
4186 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4188 if (IsPlayingAudio())
4190 CLastfmScrobbler::GetInstance()->SubmitQueue();
4191 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4194 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4195 g_windowManager.SendThreadMessage(msg);
4198 void CApplication::OnPlayBackStarted()
4200 if(m_bPlaybackStarting)
4203 if (!CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4204 CJobManager::GetInstance().Pause(kJobTypeMediaFlags);
4207 // informs python script currently running playback has started
4208 // (does nothing if python is not loaded)
4209 g_pythonParser.OnPlayBackStarted();
4212 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4213 g_windowManager.SendThreadMessage(msg);
4216 void CApplication::OnQueueNextItem()
4218 // informs python script currently running that we are requesting the next track
4219 // (does nothing if python is not loaded)
4221 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4224 if(IsPlayingAudio())
4226 CLastfmScrobbler::GetInstance()->SubmitQueue();
4227 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4230 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4231 g_windowManager.SendThreadMessage(msg);
4234 void CApplication::OnPlayBackStopped()
4236 if(m_bPlaybackStarting)
4239 if (CJobManager::GetInstance().IsPaused(kJobTypeMediaFlags))
4240 CJobManager::GetInstance().UnPause(kJobTypeMediaFlags);
4242 // informs python script currently running playback has ended
4243 // (does nothing if python is not loaded)
4245 g_pythonParser.OnPlayBackStopped();
4248 CVariant data(CVariant::VariantTypeObject);
4249 data["end"] = false;
4250 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4252 CLastfmScrobbler::GetInstance()->SubmitQueue();
4253 CLibrefmScrobbler::GetInstance()->SubmitQueue();
4255 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4256 g_windowManager.SendThreadMessage(msg);
4259 void CApplication::OnPlayBackPaused()
4262 g_pythonParser.OnPlayBackPaused();
4266 param["player"]["speed"] = 0;
4267 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4268 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4271 void CApplication::OnPlayBackResumed()
4274 g_pythonParser.OnPlayBackResumed();
4278 param["player"]["speed"] = 1;
4279 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4280 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4283 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4286 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4290 param["player"]["speed"] = iSpeed;
4291 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4292 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4295 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4298 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4302 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4303 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4304 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4305 param["player"]["speed"] = GetPlaySpeed();
4306 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4307 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4310 void CApplication::OnPlayBackSeekChapter(int iChapter)
4313 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4317 bool CApplication::IsPlaying() const
4321 if (!m_pPlayer->IsPlaying())
4326 bool CApplication::IsPaused() const
4330 if (!m_pPlayer->IsPlaying())
4332 return m_pPlayer->IsPaused();
4335 bool CApplication::IsPlayingAudio() const
4339 if (!m_pPlayer->IsPlaying())
4341 if (m_pPlayer->HasVideo())
4343 if (m_pPlayer->HasAudio())
4348 bool CApplication::IsPlayingVideo() const
4352 if (!m_pPlayer->IsPlaying())
4354 if (m_pPlayer->HasVideo())
4360 bool CApplication::IsPlayingFullScreenVideo() const
4362 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4365 bool CApplication::IsFullScreen()
4367 return IsPlayingFullScreenVideo() ||
4368 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4369 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4372 void CApplication::SaveFileState(bool bForeground /* = false */)
4374 if (m_progressTrackingItem->IsPVRChannel() || !g_settings.GetCurrentProfile().canWriteDatabases())
4379 CSaveFileStateJob job(*m_progressTrackingItem,
4380 *m_stackFileItemToUpdate,
4381 m_progressTrackingVideoResumeBookmark,
4382 m_progressTrackingPlayCountUpdate);
4384 // Run job in the foreground to make sure it finishes
4389 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4390 *m_stackFileItemToUpdate,
4391 m_progressTrackingVideoResumeBookmark,
4392 m_progressTrackingPlayCountUpdate);
4393 CJobManager::GetInstance().AddJob(job, NULL);
4397 void CApplication::UpdateFileState()
4399 // Did the file change?
4400 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4404 // Reset tracking item
4405 m_progressTrackingItem->Reset();
4409 if (IsPlayingVideo() || IsPlayingAudio())
4411 if (m_progressTrackingItem->GetPath() == "")
4414 *m_progressTrackingItem = CurrentFileItem();
4415 m_progressTrackingPlayCountUpdate = false;
4418 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4419 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4420 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4421 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4423 m_progressTrackingPlayCountUpdate = true;
4426 if (m_progressTrackingItem->IsVideo())
4428 if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60*1000)
4430 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset();
4431 m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails);
4433 // Update bookmark for save
4434 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::GetPlayerName(m_eCurrentPlayer);
4435 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4436 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4438 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4439 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4441 // Delete the bookmark
4442 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4445 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4447 // Update the bookmark
4448 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4449 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4454 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4461 void CApplication::StopPlaying()
4463 int iWin = g_windowManager.GetActiveWindow();
4468 m_pKaraokeMgr->Stop();
4471 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4472 g_PVRManager.SaveCurrentChannelSettings();
4475 m_pPlayer->CloseFile();
4477 // turn off visualisation window when stopping
4478 if (iWin == WINDOW_VISUALISATION
4479 || iWin == WINDOW_FULLSCREEN_VIDEO)
4480 g_windowManager.PreviousWindow();
4482 g_partyModeManager.Disable();
4486 void CApplication::ResetSystemIdleTimer()
4488 // reset system idle timer
4489 m_idleTimer.StartZero();
4492 void CApplication::ResetScreenSaver()
4495 m_shutdownTimer.StartZero();
4497 // screen saver timer is reset only if we're not already in screensaver or
4499 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4500 ResetScreenSaverTimer();
4503 void CApplication::ResetScreenSaverTimer()
4505 m_screenSaverTimer.StartZero();
4508 void CApplication::StopScreenSaverTimer()
4510 m_screenSaverTimer.Stop();
4513 bool CApplication::ToggleDPMS(bool manual)
4515 if (manual || (m_dpmsIsManual == manual))
4519 m_dpmsIsActive = false;
4520 m_dpmsIsManual = false;
4521 return m_dpms->DisablePowerSaving();
4525 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4527 m_dpmsIsActive = true;
4528 m_dpmsIsManual = manual;
4536 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4540 // turn on lcd backlight
4541 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4542 g_lcd->SetBackLight(1);
4545 // First reset DPMS, if active
4550 // TODO: if screensaver lock is specified but screensaver is not active
4551 // (DPMS came first), activate screensaver now.
4553 ResetScreenSaverTimer();
4554 return !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4557 return WakeUpScreenSaver(bPowerOffKeyPressed);
4560 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4562 if (m_iScreenSaveLock == 2)
4565 // if Screen saver is active
4566 if (m_bScreenSave && m_screenSaver)
4568 if (m_iScreenSaveLock == 0)
4569 if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4570 (g_settings.UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) &&
4571 g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4572 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4574 m_iScreenSaveLock = 2;
4575 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4577 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4579 pWindow->OnMessage(msg);
4581 if (m_iScreenSaveLock == -1)
4583 m_iScreenSaveLock = 0;
4587 // disable screensaver
4588 m_bScreenSave = false;
4589 m_iScreenSaveLock = 0;
4590 ResetScreenSaverTimer();
4592 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4593 CVariant data(bPowerOffKeyPressed);
4594 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4596 if (m_screenSaver->ID() == "visualization")
4598 // we can just continue as usual from vis mode
4601 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4603 else if (!m_screenSaver->ID().IsEmpty())
4604 { // we're in screensaver window
4605 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4606 g_windowManager.PreviousWindow(); // show the previous window
4607 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4608 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4616 void CApplication::CheckScreenSaverAndDPMS()
4618 if (!m_dpmsIsActive)
4619 g_Windowing.ResetOSScreensaver();
4621 bool maybeScreensaver =
4622 !m_dpmsIsActive && !m_bScreenSave
4623 && !g_guiSettings.GetString("screensaver.mode").IsEmpty();
4625 !m_dpmsIsActive && m_dpms->IsSupported()
4626 && g_guiSettings.GetInt("powermanagement.displaysoff") > 0;
4628 // Has the screen saver window become active?
4629 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4631 m_bScreenSave = true;
4632 maybeScreensaver = false;
4635 if (m_bScreenSave && IsPlayingVideo() && !m_pPlayer->IsPaused())
4637 WakeUpScreenSaverAndDPMS();
4641 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4643 // See if we need to reset timer.
4644 // * Are we playing a video and it is not paused?
4645 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4646 // * Are we playing some music in fullscreen vis?
4647 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4648 && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()))
4650 ResetScreenSaverTimer();
4654 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4656 // DPMS has priority (it makes the screensaver not needed)
4658 && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60)
4661 WakeUpScreenSaver();
4663 else if (maybeScreensaver
4664 && elapsed > g_guiSettings.GetInt("screensaver.time") * 60)
4666 ActivateScreenSaver();
4670 // activate the screensaver.
4671 // if forceType is true, we ignore the various conditions that can alter
4672 // the type of screensaver displayed
4673 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4675 m_bScreenSave = true;
4677 // Get Screensaver Mode
4678 m_screenSaver.reset();
4679 if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver))
4680 m_screenSaver.reset(new CScreenSaver(""));
4683 // turn off lcd backlight if requested
4684 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4685 g_lcd->SetBackLight(0);
4688 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4690 // disable screensaver lock from the login screen
4691 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4694 // set to Dim in the case of a dialog on screen or playing video
4695 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4697 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4698 m_screenSaver.reset(new CScreenSaver(""));
4700 // Check if we are Playing Audio and Vis instead Screensaver!
4701 else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())
4702 { // activate the visualisation
4703 m_screenSaver.reset(new CScreenSaver("visualization"));
4704 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4708 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4710 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4712 else if (!m_screenSaver->ID().IsEmpty())
4713 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4716 void CApplication::CheckShutdown()
4718 // first check if we should reset the timer
4719 bool resetTimer = m_bInhibitIdleShutdown;
4721 if (IsPlaying() || IsPaused()) // is something playing?
4724 if (m_musicInfoScanner->IsScanning())
4727 if (m_videoInfoScanner->IsScanning())
4730 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4733 if (g_guiSettings.GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4738 m_shutdownTimer.StartZero();
4742 if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 )
4744 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4745 m_shutdownTimer.Stop();
4748 CApplicationMessenger::Get().Shutdown();
4752 void CApplication::InhibitIdleShutdown(bool inhibit)
4754 m_bInhibitIdleShutdown = inhibit;
4757 bool CApplication::IsIdleShutdownInhibited() const
4759 return m_bInhibitIdleShutdown;
4762 bool CApplication::OnMessage(CGUIMessage& message)
4764 switch ( message.GetMessage() )
4766 case GUI_MSG_NOTIFY_ALL:
4768 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4770 // Update general playlist: Remove DVD playlist items
4771 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4774 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4775 g_windowManager.SendMessage( msg );
4777 // stop the file if it's on dvd (will set the resume point etc)
4778 if (m_itemCurrentFile->IsOnDVD())
4784 case GUI_MSG_PLAYBACK_STARTED:
4786 #ifdef TARGET_DARWIN
4787 DarwinSetScheduling(message.GetMessage());
4789 // reset the seek handler
4790 m_seekHandler->Reset();
4792 // Update our infoManager with the new details etc.
4793 if (m_nextPlaylistItem >= 0)
4794 { // we've started a previously queued item
4795 CFileItemPtr item = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist())[m_nextPlaylistItem];
4796 // update the playlist manager
4797 int currentSong = g_playlistPlayer.GetCurrentSong();
4798 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4799 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4800 g_windowManager.SendThreadMessage(msg);
4801 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4802 *m_itemCurrentFile = *item;
4804 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4805 CLastFmManager::GetInstance()->OnSongChange(*m_itemCurrentFile);
4806 g_partyModeManager.OnSongChange(true);
4809 param["player"]["speed"] = 1;
4810 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4811 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4813 DimLCDOnPlayback(true);
4815 if (IsPlayingAudio())
4817 // Start our cdg parser as appropriate
4819 if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4821 m_pKaraokeMgr->Stop();
4822 if (m_itemCurrentFile->IsMusicDb())
4824 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4826 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4827 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4830 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4833 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4836 // Let scrobbler know about the track
4837 const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag();
4840 CLastfmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4841 CLibrefmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4849 case GUI_MSG_QUEUE_NEXT_ITEM:
4851 // Check to see if our playlist player has a new item for us,
4852 // and if so, we check whether our current player wants the file
4853 int iNext = g_playlistPlayer.GetNextSong();
4854 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4855 if (iNext < 0 || iNext >= playlist.size())
4857 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4858 return true; // nothing to do
4861 // ok, grab the next song
4862 CFileItem file(*playlist[iNext]);
4864 CURL url(file.GetPath());
4865 if (url.GetProtocol() == "plugin")
4866 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4869 if (URIUtils::IsUPnP(file.GetPath()))
4871 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4876 // ok - send the file to the player if it wants it
4877 if (m_pPlayer && m_pPlayer->QueueNextFile(file))
4878 { // player wants the next file
4879 m_nextPlaylistItem = iNext;
4885 case GUI_MSG_PLAYBACK_STOPPED:
4886 case GUI_MSG_PLAYBACK_ENDED:
4887 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4891 m_pKaraokeMgr->Stop();
4893 #ifdef TARGET_DARWIN
4894 DarwinSetScheduling(message.GetMessage());
4896 // first check if we still have items in the stack to play
4897 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4899 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4900 { // just play the next item in the stack
4901 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4906 // In case playback ended due to user eg. skipping over the end, clear
4907 // our resume bookmark here
4908 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4910 // Delete the bookmark
4911 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4914 // reset the current playing file
4915 m_itemCurrentFile->Reset();
4916 g_infoManager.ResetCurrentItem();
4917 m_currentStack->Clear();
4919 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4921 g_playlistPlayer.PlayNext(1, true);
4926 if (CLastFmManager::GetInstance()->IsRadioEnabled())
4927 CLastFmManager::GetInstance()->StopRadio();
4938 g_audioManager.Enable(true);
4939 DimLCDOnPlayback(false);
4942 if (!IsPlayingVideo())
4944 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4946 g_windowManager.PreviousWindow();
4950 CSingleLock lock(g_graphicsContext);
4951 // resets to res_desktop or look&feel resolution (including refreshrate)
4952 g_graphicsContext.SetFullScreenVideo(false);
4956 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4958 g_settings.Save(); // save vis settings
4959 WakeUpScreenSaverAndDPMS();
4960 g_windowManager.PreviousWindow();
4963 // DVD ejected while playing in vis ?
4964 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4967 g_settings.Save(); // save vis settings
4968 WakeUpScreenSaverAndDPMS();
4969 g_windowManager.PreviousWindow();
4972 if (IsEnableTestMode())
4973 CApplicationMessenger::Get().Quit();
4978 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4979 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4984 case GUI_MSG_FULLSCREEN:
4985 { // Switch to fullscreen, if we can
4986 SwitchToFullScreen();
4990 case GUI_MSG_EXECUTE:
4991 if (message.GetNumStringParams())
4992 return ExecuteXBMCAction(message.GetStringParam());
4998 bool CApplication::ExecuteXBMCAction(std::string actionStr)
5000 // see if it is a user set string
5001 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
5002 CGUIInfoLabel info(actionStr, "");
5003 actionStr = info.GetLabel(0);
5004 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
5006 // user has asked for something to be executed
5007 if (CBuiltins::HasCommand(actionStr))
5008 CBuiltins::Execute(actionStr);
5011 // try translating the action from our ButtonTranslator
5013 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5015 OnAction(CAction(actionID));
5018 CFileItem item(actionStr, false);
5020 if (item.IsPythonScript())
5021 { // a python script
5022 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
5026 if (item.IsAudio() || item.IsVideo())
5027 { // an audio or video file
5036 void CApplication::Process()
5040 // dispatch the messages generated by python or other threads to the current window
5041 g_windowManager.DispatchThreadMessages();
5043 // process messages which have to be send to the gui
5044 // (this can only be done after g_windowManager.Render())
5045 CApplicationMessenger::Get().ProcessWindowMessages();
5048 // process any Python scripts
5049 g_pythonParser.Process();
5052 // process messages, even if a movie is playing
5053 CApplicationMessenger::Get().ProcessMessages();
5054 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5056 // check how far we are through playing the current item
5057 // and do anything that needs doing (lastfm submission, playcount updates etc)
5058 CheckPlayingProgress();
5062 m_pPlayer->DoAudioWork();
5064 // do any processing that isn't needed on each run
5065 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5067 m_slowTimer.Reset();
5071 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5074 // We get called every 500ms
5075 void CApplication::ProcessSlow()
5077 g_powerManager.ProcessEvents();
5079 #if defined(TARGET_DARWIN_OSX)
5080 // There is an issue on OS X that several system services ask the cursor to become visible
5081 // during their startup routines. Given that we can't control this, we hack it in by
5083 if (g_Windowing.IsFullScreen())
5084 { // SDL thinks it's hidden
5089 // Store our file state for use on close()
5092 if (IsPlayingAudio())
5094 CLastfmScrobbler::GetInstance()->UpdateStatus();
5095 CLibrefmScrobbler::GetInstance()->UpdateStatus();
5098 // Check if we need to activate the screensaver / DPMS.
5099 CheckScreenSaverAndDPMS();
5101 // Check if we need to shutdown (if enabled).
5102 #if defined(TARGET_DARWIN)
5103 if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5105 if (g_guiSettings.GetInt("powermanagement.shutdowntime"))
5111 // check if we should restart the player
5112 CheckDelayedPlayerRestart();
5114 // check if we can unload any unreferenced dlls or sections
5115 if (!IsPlayingVideo())
5116 CSectionLoader::UnloadDelayed();
5118 // check for any idle curl connections
5119 g_curlInterface.CheckIdle();
5121 // check for any idle myth sessions
5122 CMythSession::CheckIdle();
5124 #ifdef HAS_FILESYSTEM_HTSP
5125 // check for any idle htsp sessions
5126 HTSP::CHTSPDirectorySession::CheckIdle();
5130 if ( m_pKaraokeMgr )
5131 m_pKaraokeMgr->ProcessSlow();
5134 // LED - LCD SwitchOn On Paused! m_bIsPaused=TRUE -> LED/LCD is ON!
5135 if(IsPaused() != m_bIsPaused)
5138 DimLCDOnPlayback(m_bIsPaused);
5140 m_bIsPaused = IsPaused();
5143 if (!IsPlayingVideo())
5144 g_largeTextureManager.CleanupUnusedImages();
5146 #ifdef HAS_DVD_DRIVE
5147 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5148 if (!IsPlayingVideo())
5149 m_Autorun->HandleAutorun();
5152 // update upnp server/renderer states
5154 if(UPNP::CUPnP::IsInstantiated())
5155 UPNP::CUPnP::GetInstance()->UpdateState();
5158 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
5162 #ifdef HAS_FILESYSTEM_NFS
5163 gNfsConnection.CheckIfIdle();
5166 #ifdef HAS_FILESYSTEM_AFP
5167 gAfpConnection.CheckIfIdle();
5170 #ifdef HAS_FILESYSTEM_SFTP
5171 CSFTPSessionManager::ClearOutIdleSessions();
5174 g_mediaManager.ProcessEvents();
5177 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5178 g_RemoteControl.Initialize();
5182 // attempt to reinitialize the LCD (e.g. after resuming from sleep)
5183 if (!IsPlayingVideo())
5185 if (g_lcd && !g_lcd->IsConnected())
5188 g_lcd->Initialize();
5193 if (!IsPlayingVideo())
5194 CAddonInstaller::Get().UpdateRepos();
5196 CAEFactory::GarbageCollect();
5199 // Global Idle Time in Seconds
5200 // idle time will be resetet if on any OnKey()
5201 // int return: system Idle time in seconds! 0 is no idle!
5202 int CApplication::GlobalIdleTime()
5204 if(!m_idleTimer.IsRunning())
5207 m_idleTimer.StartZero();
5209 return (int)m_idleTimer.GetElapsedSeconds();
5212 float CApplication::NavigationIdleTime()
5214 if (!m_navigationTimer.IsRunning())
5216 m_navigationTimer.Stop();
5217 m_navigationTimer.StartZero();
5219 return m_navigationTimer.GetElapsedSeconds();
5222 void CApplication::DelayedPlayerRestart()
5224 m_restartPlayerTimer.StartZero();
5227 void CApplication::CheckDelayedPlayerRestart()
5229 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5231 m_restartPlayerTimer.Stop();
5232 m_restartPlayerTimer.Reset();
5237 void CApplication::Restart(bool bSamePosition)
5239 // this function gets called when the user changes a setting (like noninterleaved)
5240 // and which means we gotta close & reopen the current playing file
5242 // first check if we're playing a file
5243 if ( !IsPlayingVideo() && !IsPlayingAudio())
5251 // do we want to return to the current position in the file
5252 if (false == bSamePosition)
5254 // no, then just reopen the file and start at the beginning
5255 PlayFile(*m_itemCurrentFile, true);
5259 // else get current position
5260 double time = GetTime();
5262 // get player state, needed for dvd's
5263 CStdString state = m_pPlayer->GetPlayerState();
5265 // set the requested starttime
5266 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5269 if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer )
5270 m_pPlayer->SetPlayerState(state);
5273 const CStdString& CApplication::CurrentFile()
5275 return m_itemCurrentFile->GetPath();
5278 CFileItem& CApplication::CurrentFileItem()
5280 return *m_itemCurrentFile;
5283 void CApplication::ShowVolumeBar(const CAction *action)
5285 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5290 volumeBar->OnAction(*action);
5294 bool CApplication::IsMuted() const
5296 if (g_peripherals.IsMuted())
5298 return CAEFactory::IsMuted();
5301 void CApplication::ToggleMute(void)
5303 if (g_settings.m_bMute)
5309 void CApplication::Mute()
5311 if (g_peripherals.Mute())
5314 CAEFactory::SetMute(true);
5315 g_settings.m_bMute = true;
5319 void CApplication::UnMute()
5321 if (g_peripherals.UnMute())
5324 CAEFactory::SetMute(false);
5325 g_settings.m_bMute = false;
5329 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5331 float hardwareVolume = iValue;
5334 hardwareVolume /= 100.0f;
5336 SetHardwareVolume(hardwareVolume);
5340 void CApplication::SetHardwareVolume(float hardwareVolume)
5342 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5343 g_settings.m_fVolumeLevel = hardwareVolume;
5346 if (hardwareVolume > VOLUME_MINIMUM)
5348 float dB = CAEUtil::PercentToGain(hardwareVolume);
5349 value = CAEUtil::GainToScale(dB);
5354 CAEFactory::SetVolume(value);
5356 /* for platforms where we do not have AE */
5358 m_pPlayer->SetVolume(g_settings.m_fVolumeLevel);
5361 int CApplication::GetVolume() const
5363 // converts the hardware volume to a percentage
5364 return (int)(g_settings.m_fVolumeLevel * 100.0f);
5367 void CApplication::VolumeChanged() const
5369 CVariant data(CVariant::VariantTypeObject);
5370 data["volume"] = GetVolume();
5371 data["muted"] = g_settings.m_bMute;
5372 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5375 int CApplication::GetSubtitleDelay() const
5377 // converts subtitle delay to a percentage
5378 return int(((float)(g_settings.m_currentVideoSettings.m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5381 int CApplication::GetAudioDelay() const
5383 // converts subtitle delay to a percentage
5384 return int(((float)(g_settings.m_currentVideoSettings.m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5387 void CApplication::SetPlaySpeed(int iSpeed)
5389 if (!IsPlayingAudio() && !IsPlayingVideo())
5391 if (m_iPlaySpeed == iSpeed)
5393 if (!m_pPlayer->CanSeek())
5395 if (m_pPlayer->IsPaused())
5398 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5399 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5402 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5406 m_iPlaySpeed = iSpeed;
5408 m_pPlayer->ToFFRW(m_iPlaySpeed);
5409 if (m_iPlaySpeed == 1)
5411 m_pPlayer->SetVolume(VOLUME_MAXIMUM);
5415 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5419 int CApplication::GetPlaySpeed() const
5421 return m_iPlaySpeed;
5424 // Returns the total time in seconds of the current media. Fractional
5425 // portions of a second are possible - but not necessarily supported by the
5426 // player class. This returns a double to be consistent with GetTime() and
5428 double CApplication::GetTotalTime() const
5432 if (IsPlaying() && m_pPlayer)
5434 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5435 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5437 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5443 void CApplication::StopShutdownTimer()
5445 if (m_shutdownTimer.IsRunning())
5446 m_shutdownTimer.Stop();
5449 void CApplication::ResetShutdownTimers()
5451 // reset system shutdown timer
5452 m_shutdownTimer.StartZero();
5454 // delete custom shutdown timer
5455 if (g_alarmClock.HasAlarm("shutdowntimer"))
5456 g_alarmClock.Stop("shutdowntimer", true);
5459 // Returns the current time in seconds of the currently playing media.
5460 // Fractional portions of a second are possible. This returns a double to
5461 // be consistent with GetTotalTime() and SeekTime().
5462 double CApplication::GetTime() const
5466 if (IsPlaying() && m_pPlayer)
5468 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5470 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5471 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5474 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5480 // Sets the current position of the currently playing media to the specified
5481 // time in seconds. Fractional portions of a second are valid. The passed
5482 // time is the time offset from the beginning of the file as opposed to a
5483 // delta from the current position. This method accepts a double to be
5484 // consistent with GetTime() and GetTotalTime().
5485 void CApplication::SeekTime( double dTime )
5487 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5489 if (!m_pPlayer->CanSeek()) return;
5490 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5492 // find the item in the stack we are seeking to, and load the new
5493 // file if necessary, and calculate the correct seek within the new
5494 // file. Otherwise, just fall through to the usual routine if the
5495 // time is higher than our total time.
5496 for (int i = 0; i < m_currentStack->Size(); i++)
5498 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5500 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5501 if (m_currentStackPosition == i)
5502 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5504 { // seeking to a new file
5505 m_currentStackPosition = i;
5506 CFileItem item(*(*m_currentStack)[i]);
5507 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5508 // don't just call "PlayFile" here, as we are quite likely called from the
5509 // player thread, so we won't be able to delete ourselves.
5510 CApplicationMessenger::Get().PlayFile(item, true);
5516 // convert to milliseconds and perform seek
5517 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5521 float CApplication::GetPercentage() const
5523 if (IsPlaying() && m_pPlayer)
5525 if (m_pPlayer->GetTotalTime() == 0 && IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5527 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5528 if (tag.GetDuration() > 0)
5529 return (float)(GetTime() / tag.GetDuration() * 100);
5532 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5534 double totalTime = GetTotalTime();
5535 if (totalTime > 0.0f)
5536 return (float)(GetTime() / totalTime * 100);
5539 return m_pPlayer->GetPercentage();
5544 float CApplication::GetCachePercentage() const
5546 if (IsPlaying() && m_pPlayer)
5548 // Note that the player returns a relative cache percentage and we want an absolute percentage
5549 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5551 float stackedTotalTime = (float) GetTotalTime();
5552 // We need to take into account the stack's total time vs. currently playing file's total time
5553 if (stackedTotalTime > 0.0f)
5554 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5557 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5562 void CApplication::SeekPercentage(float percent)
5564 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5566 if (!m_pPlayer->CanSeek()) return;
5567 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5568 SeekTime(percent * 0.01 * GetTotalTime());
5570 m_pPlayer->SeekPercentage(percent);
5574 // SwitchToFullScreen() returns true if a switch is made, else returns false
5575 bool CApplication::SwitchToFullScreen()
5577 // if playing from the video info window, close it first!
5578 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5580 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5581 if (pDialog) pDialog->Close(true);
5584 // don't switch if there is a dialog on screen or the slideshow is active
5585 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5588 // See if we're playing a video, and are in GUI mode
5589 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5591 // Reset frame count so that timing is FPS will be correct.
5593 CSingleLock lock(m_frameMutex);
5597 // then switch to fullscreen mode
5598 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5601 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5602 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5603 { // then switch to visualisation
5604 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5610 void CApplication::Minimize()
5612 g_Windowing.Minimize();
5615 PLAYERCOREID CApplication::GetCurrentPlayer()
5617 return m_eCurrentPlayer;
5620 void CApplication::UpdateLibraries()
5622 if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
5624 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5628 if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
5630 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5635 bool CApplication::IsVideoScanning() const
5637 return m_videoInfoScanner->IsScanning();
5640 bool CApplication::IsMusicScanning() const
5642 return m_musicInfoScanner->IsScanning();
5645 void CApplication::StopVideoScan()
5647 if (m_videoInfoScanner->IsScanning())
5648 m_videoInfoScanner->Stop();
5651 void CApplication::StopMusicScan()
5653 if (m_musicInfoScanner->IsScanning())
5654 m_musicInfoScanner->Stop();
5657 void CApplication::StartVideoCleanup()
5659 if (m_videoInfoScanner->IsScanning())
5662 m_videoInfoScanner->CleanDatabase();
5665 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5667 if (m_videoInfoScanner->IsScanning())
5670 m_videoInfoScanner->ShowDialog(true);
5672 m_videoInfoScanner->Start(strDirectory,scanAll);
5675 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5677 if (m_musicInfoScanner->IsScanning())
5681 { // setup default flags
5682 if (g_guiSettings.GetBool("musiclibrary.downloadinfo"))
5683 flags |= CMusicInfoScanner::SCAN_ONLINE;
5684 if (g_guiSettings.GetBool("musiclibrary.backgroundupdate"))
5685 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5688 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5689 m_musicInfoScanner->ShowDialog(true);
5691 m_musicInfoScanner->Start(strDirectory, flags);
5694 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5697 if (m_musicInfoScanner->IsScanning())
5700 m_musicInfoScanner->ShowDialog(true);
5702 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5705 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5708 if (m_musicInfoScanner->IsScanning())
5711 m_musicInfoScanner->ShowDialog(true);
5713 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5716 void CApplication::CheckPlayingProgress()
5718 // check if we haven't rewound past the start of the file
5721 int iSpeed = g_application.GetPlaySpeed();
5731 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5733 g_application.SetPlaySpeed(1);
5734 g_application.SeekTime(0);
5740 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5742 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5744 // initial exit conditions
5745 // no songs in playlist just return
5746 if (playlist.size() == 0)
5750 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5753 // setup correct playlist
5754 g_playlistPlayer.ClearPlaylist(iPlaylist);
5756 // if the playlist contains an internet stream, this file will be used
5757 // to generate a thumbnail for musicplayer.cover
5758 g_application.m_strPlayListFile = strPlayList;
5760 // add the items to the playlist player
5761 g_playlistPlayer.Add(iPlaylist, playlist);
5763 // if we have a playlist
5764 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5767 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5768 g_playlistPlayer.Reset();
5769 g_playlistPlayer.Play(track);
5775 void CApplication::SaveCurrentFileSettings()
5777 // don't store settings for PVR in video database
5778 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5780 // save video settings
5781 if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings)
5785 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), g_settings.m_currentVideoSettings);
5789 else if (m_itemCurrentFile->IsPVRChannel())
5791 g_PVRManager.SaveCurrentChannelSettings();
5795 bool CApplication::AlwaysProcess(const CAction& action)
5797 // check if this button is mapped to a built-in function
5798 if (!action.GetName().IsEmpty())
5800 CStdString builtInFunction;
5801 vector<CStdString> params;
5802 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5803 builtInFunction.ToLower();
5805 // should this button be handled normally or just cancel the screensaver?
5806 if ( builtInFunction.Equals("powerdown")
5807 || builtInFunction.Equals("reboot")
5808 || builtInFunction.Equals("restart")
5809 || builtInFunction.Equals("restartapp")
5810 || builtInFunction.Equals("suspend")
5811 || builtInFunction.Equals("hibernate")
5812 || builtInFunction.Equals("quit")
5813 || builtInFunction.Equals("shutdown"))
5822 bool CApplication::IsCurrentThread() const
5824 return CThread::IsCurrentThread(m_threadID);
5827 bool CApplication::IsPresentFrame()
5829 CSingleLock lock(m_frameMutex);
5830 bool ret = m_bPresentFrame;
5835 void CApplication::SetRenderGUI(bool renderGUI)
5837 if (renderGUI && ! m_renderGUI)
5838 g_windowManager.MarkDirty();
5839 m_renderGUI = renderGUI;
5842 #if defined(HAS_LINUX_NETWORK)
5843 CNetworkLinux& CApplication::getNetwork()
5847 #elif defined(HAS_WIN32_NETWORK)
5848 CNetworkWin32& CApplication::getNetwork()
5853 CNetwork& CApplication::getNetwork()
5859 #ifdef HAS_PERFORMANCE_SAMPLE
5860 CPerformanceStats &CApplication::GetPerformanceStats()