2 * Copyright (C) 2005-2008 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, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "threads/SystemClock.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
28 #include "input/KeyboardLayoutConfiguration.h"
31 #include "pictures/Picture.h"
32 #include "guilib/TextureManager.h"
33 #include "cores/dvdplayer/DVDFileInfo.h"
34 #include "PlayListPlayer.h"
36 #include "video/Bookmark.h"
38 #include "network/WebServer.h"
41 #include "utils/LCDFactory.h"
43 #include "guilib/GUIControlProfiler.h"
44 #include "utils/LangCodeExpander.h"
45 #include "GUIInfoManager.h"
46 #include "playlists/PlayListFactory.h"
47 #include "guilib/GUIFontManager.h"
48 #include "guilib/GUIColorManager.h"
49 #include "guilib/GUITextLayout.h"
50 #include "addons/Skin.h"
52 #include "interfaces/python/XBPython.h"
54 #include "input/ButtonTranslator.h"
55 #include "guilib/GUIAudioManager.h"
56 #include "network/libscrobbler/lastfmscrobbler.h"
57 #include "network/libscrobbler/librefmscrobbler.h"
58 #include "GUIPassword.h"
59 #include "input/InertialScrollingHandler.h"
60 #include "ApplicationMessenger.h"
61 #include "SectionLoader.h"
62 #include "cores/DllLoader/DllLoaderContainer.h"
63 #include "GUIUserMessages.h"
64 #include "filesystem/DirectoryCache.h"
65 #include "filesystem/StackDirectory.h"
66 #include "filesystem/SpecialProtocol.h"
67 #include "filesystem/DllLibCurl.h"
68 #include "filesystem/MythSession.h"
69 #include "filesystem/PluginDirectory.h"
70 #ifdef HAS_FILESYSTEM_SAP
71 #include "filesystem/SAPDirectory.h"
73 #ifdef HAS_FILESYSTEM_HTSP
74 #include "filesystem/HTSPDirectory.h"
76 #include "utils/TuxBoxUtil.h"
77 #include "utils/SystemInfo.h"
78 #include "utils/TimeUtils.h"
79 #include "GUILargeTextureManager.h"
80 #include "TextureCache.h"
81 #include "music/LastFmManager.h"
82 #include "playlists/SmartPlayList.h"
83 #ifdef HAS_FILESYSTEM_RAR
84 #include "filesystem/RarManager.h"
86 #include "playlists/PlayList.h"
87 #include "windowing/WindowingFactory.h"
88 #include "powermanagement/PowerManager.h"
89 #include "powermanagement/DPMSSupport.h"
90 #include "settings/Settings.h"
91 #include "settings/AdvancedSettings.h"
92 #include "guilib/LocalizeStrings.h"
93 #include "utils/CPUInfo.h"
95 #include "input/KeyboardStat.h"
96 #include "input/XBMC_vkeys.h"
97 #include "input/MouseStat.h"
99 #if defined(FILESYSTEM) && !defined(_LINUX)
100 #include "filesystem/FileDAAP.h"
103 #include "network/UPnP.h"
104 #include "filesystem/UPnPDirectory.h"
106 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
107 #include "filesystem/SMBDirectory.h"
109 #ifdef HAS_FILESYSTEM_NFS
110 #include "filesystem/FileNFS.h"
112 #ifdef HAS_FILESYSTEM_AFP
113 #include "filesystem/FileAFP.h"
115 #ifdef HAS_FILESYSTEM_SFTP
116 #include "filesystem/FileSFTP.h"
118 #include "PartyModeManager.h"
119 #ifdef HAS_VIDEO_PLAYBACK
120 #include "cores/VideoRenderers/RenderManager.h"
123 #include "music/karaoke/karaokelyricsmanager.h"
124 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
125 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
127 #include "guilib/AudioContext.h"
128 #include "guilib/GUIFontTTF.h"
129 #include "network/Network.h"
130 #include "storage/IoSupport.h"
131 #include "network/Zeroconf.h"
132 #include "network/ZeroconfBrowser.h"
134 #include "utils/Win32Exception.h"
136 #ifdef HAS_EVENT_SERVER
137 #include "network/EventServer.h"
140 #include <dbus/dbus.h>
143 #include "interfaces/http-api/XBMChttp.h"
146 #include "interfaces/json-rpc/JSONRPC.h"
147 #include "network/TCPServer.h"
150 #include "network/AirPlayServer.h"
153 #include "network/AirTunesServer.h"
155 #if defined(HAVE_LIBCRYSTALHD)
156 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
158 #include "interfaces/AnnouncementManager.h"
159 #include "peripherals/Peripherals.h"
161 #include "peripherals/devices/PeripheralCecAdapter.h"
163 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
167 #include "guilib/GUIWindowManager.h"
168 #include "windows/GUIWindowHome.h"
169 #include "guilib/GUIStandardWindow.h"
170 #include "settings/GUIWindowSettings.h"
171 #include "windows/GUIWindowFileManager.h"
172 #include "settings/GUIWindowSettingsCategory.h"
173 #include "music/windows/GUIWindowMusicPlaylist.h"
174 #include "music/windows/GUIWindowMusicSongs.h"
175 #include "music/windows/GUIWindowMusicNav.h"
176 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
177 #include "video/windows/GUIWindowVideoPlaylist.h"
178 #include "music/dialogs/GUIDialogMusicInfo.h"
179 #include "video/dialogs/GUIDialogVideoInfo.h"
180 #include "video/windows/GUIWindowVideoNav.h"
181 #include "settings/GUIWindowSettingsProfile.h"
183 #include "rendering/gl/GUIWindowTestPatternGL.h"
186 #include "rendering/dx/GUIWindowTestPatternDX.h"
188 #include "settings/GUIWindowSettingsScreenCalibration.h"
189 #include "programs/GUIWindowPrograms.h"
190 #include "pictures/GUIWindowPictures.h"
191 #include "windows/GUIWindowWeather.h"
192 #include "windows/GUIWindowLoginScreen.h"
193 #include "addons/GUIWindowAddonBrowser.h"
194 #include "music/windows/GUIWindowVisualisation.h"
195 #include "windows/GUIWindowDebugInfo.h"
196 #include "windows/GUIWindowPointer.h"
197 #include "windows/GUIWindowSystemInfo.h"
198 #include "windows/GUIWindowScreensaver.h"
199 #include "windows/GUIWindowScreensaverDim.h"
200 #include "pictures/GUIWindowSlideShow.h"
201 #include "windows/GUIWindowStartup.h"
202 #include "video/windows/GUIWindowFullScreen.h"
203 #include "video/dialogs/GUIDialogVideoOSD.h"
204 #include "music/dialogs/GUIDialogMusicOverlay.h"
205 #include "video/dialogs/GUIDialogVideoOverlay.h"
208 #include "music/dialogs/GUIDialogMusicOSD.h"
209 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
210 #include "dialogs/GUIDialogTextViewer.h"
211 #include "network/GUIDialogNetworkSetup.h"
212 #include "dialogs/GUIDialogMediaSource.h"
213 #include "video/dialogs/GUIDialogVideoSettings.h"
214 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
215 #include "video/dialogs/GUIDialogVideoBookmarks.h"
216 #include "settings/GUIDialogProfileSettings.h"
217 #include "settings/GUIDialogLockSettings.h"
218 #include "settings/GUIDialogContentSettings.h"
219 #include "video/dialogs/GUIDialogVideoScan.h"
220 #include "dialogs/GUIDialogBusy.h"
221 #include "dialogs/GUIDialogKeyboard.h"
222 #include "dialogs/GUIDialogYesNo.h"
223 #include "dialogs/GUIDialogOK.h"
224 #include "dialogs/GUIDialogProgress.h"
225 #include "dialogs/GUIDialogSelect.h"
226 #include "dialogs/GUIDialogSeekBar.h"
227 #include "dialogs/GUIDialogKaiToast.h"
228 #include "dialogs/GUIDialogVolumeBar.h"
229 #include "dialogs/GUIDialogMuteBug.h"
230 #include "video/dialogs/GUIDialogFileStacking.h"
231 #include "dialogs/GUIDialogNumeric.h"
232 #include "dialogs/GUIDialogGamepad.h"
233 #include "dialogs/GUIDialogSubMenu.h"
234 #include "dialogs/GUIDialogFavourites.h"
235 #include "dialogs/GUIDialogButtonMenu.h"
236 #include "dialogs/GUIDialogContextMenu.h"
237 #include "music/dialogs/GUIDialogMusicScan.h"
238 #include "dialogs/GUIDialogPlayerControls.h"
239 #include "music/dialogs/GUIDialogSongInfo.h"
240 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
241 #include "dialogs/GUIDialogSmartPlaylistRule.h"
242 #include "pictures/GUIDialogPictureInfo.h"
243 #include "addons/GUIDialogAddonSettings.h"
244 #include "addons/GUIDialogAddonInfo.h"
245 #ifdef HAS_LINUX_NETWORK
246 #include "network/GUIDialogAccessPoints.h"
248 #include "video/dialogs/GUIDialogFullScreenInfo.h"
249 #include "video/dialogs/GUIDialogTeletext.h"
250 #include "dialogs/GUIDialogSlider.h"
251 #include "guilib/GUIControlFactory.h"
252 #include "dialogs/GUIDialogCache.h"
253 #include "dialogs/GUIDialogPlayEject.h"
254 #include "utils/XMLUtils.h"
255 #include "addons/AddonInstaller.h"
257 #ifdef HAS_PERFORMANCE_SAMPLE
258 #include "utils/PerformanceSample.h"
260 #define MEASURE_FUNCTION
264 #include <SDL/SDL_mixer.h>
268 #include "win32util.h"
271 #include "windowing/X11/XRandR.h"
274 #ifdef TARGET_DARWIN_OSX
275 #include "CocoaInterface.h"
276 #include "XBMCHelper.h"
279 #include "DarwinUtils.h"
284 #include <cdio/logging.h>
288 #include "linux/HALManager.h"
291 #include "storage/MediaManager.h"
292 #include "utils/JobManager.h"
293 #include "utils/SaveFileStateJob.h"
294 #include "utils/AlarmClock.h"
301 #include "input/linux/LIRC.h"
303 #ifdef HAS_IRSERVERSUITE
304 #include "input/windows/IRServerSuite.h"
308 using namespace ADDON;
309 using namespace XFILE;
311 using namespace MEDIA_DETECT;
313 using namespace PLAYLIST;
314 using namespace VIDEO;
315 using namespace MUSIC_INFO;
316 #ifdef HAS_EVENT_SERVER
317 using namespace EVENTSERVER;
320 using namespace JSONRPC;
322 using namespace ANNOUNCEMENT;
323 using namespace PERIPHERALS;
325 using namespace XbmcThreads;
327 // uncomment this if you want to use release libs in the debug build.
328 // Atm this saves you 7 mb of memory
329 #define USE_RELEASE_LIBS
331 #define MAX_FFWD_SPEED 5
333 //extern IDirectSoundRenderer* m_pAudioDecoder;
334 CApplication::CApplication(void) : m_itemCurrentFile(new CFileItem), m_progressTrackingItem(new CFileItem)
335 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
336 , m_WebServer(*new CWebServer)
340 m_bScreenSave = false;
342 m_dpmsIsActive = false;
343 m_dpmsIsManual = false;
344 m_iScreenSaveLock = 0;
345 m_bInitializing = true;
346 m_eForcedNextPlayer = EPC_NONE;
347 m_strPlayListFile = "";
348 m_nextPlaylistItem = -1;
349 m_bPlaybackStarting = false;
350 m_skinReloading = false;
356 //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
359 /* for now always keep this around */
361 m_pKaraokeMgr = new CKaraokeLyricsManager();
363 m_currentStack = new CFileItemList;
367 m_bPresentFrame = false;
368 m_bPlatformDirectories = true;
370 m_bStandalone = false;
371 m_bEnableLegacyRes = false;
372 m_bSystemScreenSaverEnable = false;
373 m_pInertialScrollingHandler = new CInertialScrollingHandler();
374 m_Autorun = new CAutorun();
377 CApplication::~CApplication(void)
380 delete &m_progressTrackingVideoResumeBookmark;
382 delete m_currentStack;
385 delete m_pKaraokeMgr;
389 delete m_pInertialScrollingHandler;
392 bool CApplication::OnEvent(XBMC_Event& newEvent)
394 switch(newEvent.type)
397 if (!g_application.m_bStop)
398 g_application.getApplicationMessenger().Quit();
401 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
404 g_Keyboard.ProcessKeyUp();
406 case XBMC_MOUSEBUTTONDOWN:
407 case XBMC_MOUSEBUTTONUP:
408 case XBMC_MOUSEMOTION:
409 g_Mouse.HandleEvent(newEvent);
410 g_application.ProcessMouse();
412 case XBMC_VIDEORESIZE:
413 if (!g_application.m_bInitializing &&
414 !g_advancedSettings.m_fullScreen)
416 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
417 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
418 g_guiSettings.SetInt("window.width", newEvent.resize.w);
419 g_guiSettings.SetInt("window.height", newEvent.resize.h);
424 g_application.getApplicationMessenger().UserEvent(newEvent.user.code);
426 case XBMC_APPCOMMAND:
427 return g_application.OnAppCommand(newEvent.appcommand.action);
432 // This function does not return!
433 void CApplication::FatalErrorHandler(bool WindowSystemInitialized, bool MapDrives, bool InitNetwork)
435 fprintf(stderr, "Fatal error encountered, aborting\n");
436 fprintf(stderr, "Error log at %sxbmc.log\n", g_settings.m_logFolder.c_str());
440 extern "C" void __stdcall init_emu_environ();
441 extern "C" void __stdcall update_emu_environ();
444 // Utility function used to copy files from the application bundle
445 // over to the user data directory in Application Support/XBMC.
447 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
449 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
450 if (!CFile::Exists(destPath))
452 // need to copy it across
453 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
454 CFile::Cache(srcPath, destPath);
458 void CApplication::Preflight()
461 // call 'dbus_threads_init_default' before any other dbus calls in order to
462 // avoid race conditions with other threads using dbus connections
463 dbus_threads_init_default();
466 // run any platform preflight scripts.
467 #if defined(__APPLE__) && !defined(__arm__)
468 CStdString install_path;
470 CUtil::GetHomePath(install_path);
471 setenv("XBMC_HOME", install_path.c_str(), 0);
472 install_path += "/tools/darwin/runtime/preflight";
473 system(install_path.c_str());
477 bool CApplication::Create()
479 g_settings.Initialize(); //Initialize default AdvancedSettings
481 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
482 g_Windowing.EnableSystemScreenSaver(false);
485 tzset(); // Initialize timezone information variables
488 // Grab a handle to our thread to be used later in identifying the render thread.
489 m_threadID = CThread::GetCurrentThreadId();
492 //floating point precision to 24 bits (faster performance)
493 _controlfp(_PC_24, _MCW_PC);
495 /* install win32 exception translator, win32 exceptions
496 * can now be caught using c++ try catch */
497 win32_exception::install_handler();
501 // only the InitDirectories* for the current platform should return true
502 // putting this before the first log entries saves another ifdef for g_settings.m_logFolder
503 bool inited = InitDirectoriesLinux();
505 inited = InitDirectoriesOSX();
507 inited = InitDirectoriesWin32();
509 // copy required files
510 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
511 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
512 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
513 CopyUserDataIfNeeded("special://masterprofile/", "LCD.xml");
515 if (!CLog::Init(_P(g_settings.m_logFolder).c_str()))
517 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc?\n");
521 g_settings.LoadProfiles(PROFILES_FILE);
523 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
524 #if defined(TARGET_DARWIN_OSX)
525 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
526 #elif defined(TARGET_DARWIN_IOS)
527 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
528 #elif defined(__FreeBSD__)
529 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
530 #elif defined(_LINUX)
531 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__);
532 #elif defined(_WIN32)
533 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);
534 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
535 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
536 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
537 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
539 CSpecialProtocol::LogPaths();
541 CStdString executable = CUtil::ResolveExecutablePath();
542 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
543 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network.GetHostName().c_str());
544 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str());
545 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
547 CStdString strExecutablePath;
548 CUtil::GetHomePath(strExecutablePath);
550 // if we are running from DVD our UserData location will be TDATA
551 if (URIUtils::IsDVD(strExecutablePath))
553 // TODO: Should we copy over any UserData folder from the DVD?
554 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
557 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
558 for (int i=0;i<items.Size();++i)
559 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
561 g_settings.m_logFolder = "special://masterprofile/";
565 g_xrandr.LoadCustomModeLinesToAllOutputs();
568 // Init our DllLoaders emu env
573 CLog::Log(LOGNOTICE, "Setup SDL");
575 /* Clean up on exit, exit on window close and interrupt */
578 uint32_t sdlFlags = 0;
580 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
581 sdlFlags |= SDL_INIT_VIDEO;
585 sdlFlags |= SDL_INIT_AUDIO;
588 #ifdef HAS_SDL_JOYSTICK
589 sdlFlags |= SDL_INIT_JOYSTICK;
592 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
593 //this might bring the monitor out of standby, so we have to disable it explicitly
594 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
595 #if defined(_LINUX) && !defined(__APPLE__)
596 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
602 // for nvidia cards - vsync currently ALWAYS enabled.
603 // the reason is that after screen has been setup changing this env var will make no difference.
604 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
605 setenv("__GL_YIELD", "USLEEP", 0);
609 if (SDL_Init(sdlFlags) != 0)
611 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
614 #if defined(TARGET_DARWIN)
615 // SDL_Init will install a handler for segfaults, restore the default handler.
616 signal(SIGSEGV, SIG_DFL);
620 // for python scripts that check the OS
622 setenv("OS","OS X",true);
623 #elif defined(_LINUX)
624 setenv("OS","Linux",true);
625 #elif defined(_WIN32)
626 SetEnvironmentVariable("OS","win32");
629 // Initialize core peripheral port support. Note: If these parameters
630 // are 0 and NULL, respectively, then the default number and types of
631 // controllers will be initialized.
632 if (!g_Windowing.InitWindowSystem())
634 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
638 g_powerManager.Initialize();
640 CLog::Log(LOGNOTICE, "load settings...");
642 g_guiSettings.Initialize(); // Initialize default Settings - don't move
643 g_powerManager.SetDefaults();
644 if (!g_settings.Load())
645 FatalErrorHandler(true, true, true);
647 CLog::Log(LOGINFO, "creating subdirectories");
648 CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
649 CLog::Log(LOGINFO, "recording folder:%s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
650 CLog::Log(LOGINFO, "screenshots folder:%s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
651 CDirectory::Create(g_settings.GetUserDataFolder());
652 CDirectory::Create(g_settings.GetProfileUserDataFolder());
653 g_settings.CreateProfileFolders();
655 update_emu_environ();//apply the GUI settings
657 // initialize our charset converter
658 g_charsetConverter.reset();
660 // Load the langinfo to have user charset <-> utf-8 conversion
661 CStdString strLanguage = g_guiSettings.GetString("locale.language");
662 strLanguage[0] = toupper(strLanguage[0]);
664 CStdString strLangInfoPath;
665 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
667 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
668 g_langInfo.Load(strLangInfoPath);
670 CStdString strLanguagePath;
671 strLanguagePath.Format("special://xbmc/language/%s/strings.xml", strLanguage.c_str());
673 CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
674 if (!g_localizeStrings.Load(strLanguagePath))
675 FatalErrorHandler(false, false, true);
677 // start-up Addons Framework
678 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
679 if (!CAddonMgr::Get().Init())
681 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
682 FatalErrorHandler(true, true, true);
685 g_peripherals.Initialise();
687 // Create the Mouse, Keyboard, Remote, and Joystick devices
688 // Initialize after loading settings to get joystick deadzone setting
689 g_Mouse.Initialize();
690 g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
692 g_Keyboard.Initialize();
693 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
694 g_RemoteControl.Initialize();
696 #ifdef HAS_SDL_JOYSTICK
697 g_Joystick.Initialize();
700 #if defined(__APPLE__) && !defined(__arm__)
701 // Configure and possible manually start the helper.
702 XBMCHelper::GetInstance().Configure();
705 // update the window resolution
706 g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
708 if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
709 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
711 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
713 // Oh uh - doesn't look good for starting in their wanted screenmode
714 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
715 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
719 // force initial window creation to be windowed, if fullscreen, it will switch to it below
720 // fixes the white screen of death if starting fullscreen and switching to windowed.
721 bool bFullScreen = false;
722 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
724 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
728 bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
729 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
731 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
736 if (!g_Windowing.InitRenderSystem())
738 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
742 // set GUI res and force the clear of the screen
743 g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
745 if (g_advancedSettings.m_splashImage)
747 CStdString strUserSplash = "special://home/media/Splash.png";
748 if (CFile::Exists(strUserSplash))
750 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
751 m_splash = new CSplash(strUserSplash);
755 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
756 m_splash = new CSplash("special://xbmc/media/Splash.png");
761 // The key mappings may already have been loaded by a peripheral
762 CLog::Log(LOGINFO, "load keymapping");
763 if (!CButtonTranslator::GetInstance().Load())
764 FatalErrorHandler(false, false, true);
766 int iResolution = g_graphicsContext.GetVideoResolution();
767 CLog::Log(LOGINFO, "GUI format %ix%i %s",
768 g_settings.m_ResInfo[iResolution].iWidth,
769 g_settings.m_ResInfo[iResolution].iHeight,
770 g_settings.m_ResInfo[iResolution].strMode.c_str());
771 g_windowManager.Initialize();
773 CUtil::InitRandomSeed();
775 g_mediaManager.Initialize();
777 m_lastFrameTime = XbmcThreads::SystemClockMillis();
778 m_lastRenderTime = m_lastFrameTime;
783 bool CApplication::InitDirectoriesLinux()
786 The following is the directory mapping for Platform Specific Mode:
788 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
789 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
790 installations like skins, screensavers, etc.
792 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
793 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
794 mapped to special://home/userdata ($HOME/.xbmc/userdata)
795 special://profile/ => [read-write] current profile's userdata directory.
796 Generally special://masterprofile for the master profile or
797 special://masterprofile/profiles/<profile_name> for other profiles.
799 NOTE: All these root directories are lowercase. Some of the sub-directories
803 #if defined(_LINUX) && !defined(__APPLE__)
806 userName = getenv("USER");
812 userHome = getenv("HOME");
816 CStdString xbmcBinPath, xbmcPath;
817 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
818 xbmcPath = getenv("XBMC_HOME");
820 if (xbmcPath.IsEmpty())
822 xbmcPath = xbmcBinPath;
823 /* Check if xbmc binaries and arch independent data files are being kept in
824 * separate locations. */
825 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
827 /* Attempt to locate arch independent data files. */
828 CUtil::GetHomePath(xbmcPath);
829 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
831 fprintf(stderr, "Unable to find path to XBMC data files!\n");
837 /* Set some environment variables */
838 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
839 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
841 if (m_bPlatformDirectories)
843 // map our special drives
844 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
845 CSpecialProtocol::SetXBMCPath(xbmcPath);
846 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
847 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
849 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
850 CSpecialProtocol::SetTempPath(strTempPath);
852 URIUtils::AddSlashAtEnd(strTempPath);
853 g_settings.m_logFolder = strTempPath;
860 URIUtils::AddSlashAtEnd(xbmcPath);
861 g_settings.m_logFolder = xbmcPath;
863 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
864 CSpecialProtocol::SetXBMCPath(xbmcPath);
865 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
866 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
868 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
869 CSpecialProtocol::SetTempPath(strTempPath);
872 URIUtils::AddSlashAtEnd(strTempPath);
873 g_settings.m_logFolder = strTempPath;
882 bool CApplication::InitDirectoriesOSX()
887 userName = getenv("USER");
893 userHome = getenv("HOME");
898 CUtil::GetHomePath(xbmcPath);
899 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
902 CStdString fontconfigPath;
903 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
904 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
907 // setup path to our internal dylibs so loader can find them
908 CStdString frameworksPath = CUtil::GetFrameworksPath();
909 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
911 // OSX always runs with m_bPlatformDirectories == true
912 if (m_bPlatformDirectories)
914 // map our special drives
915 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
916 CSpecialProtocol::SetXBMCPath(xbmcPath);
918 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
919 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
921 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
922 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
925 // location for temp files
927 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
929 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
930 CDirectory::Create(strTempPath);
931 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
933 CSpecialProtocol::SetTempPath(strTempPath);
935 // xbmc.log file location
937 strTempPath = userHome + "/Library/Preferences";
939 strTempPath = userHome + "/Library/Logs";
941 URIUtils::AddSlashAtEnd(strTempPath);
942 g_settings.m_logFolder = strTempPath;
948 URIUtils::AddSlashAtEnd(xbmcPath);
949 g_settings.m_logFolder = xbmcPath;
951 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
952 CSpecialProtocol::SetXBMCPath(xbmcPath);
953 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
954 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
956 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
957 CSpecialProtocol::SetTempPath(strTempPath);
959 URIUtils::AddSlashAtEnd(strTempPath);
960 g_settings.m_logFolder = strTempPath;
969 bool CApplication::InitDirectoriesWin32()
974 CUtil::GetHomePath(xbmcPath);
975 SetEnvironmentVariable("XBMC_HOME", xbmcPath.c_str());
976 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
977 CSpecialProtocol::SetXBMCPath(xbmcPath);
979 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
981 g_settings.m_logFolder = strWin32UserFolder;
982 CSpecialProtocol::SetHomePath(strWin32UserFolder);
983 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
984 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
986 SetEnvironmentVariable("XBMC_PROFILE_USERDATA",_P("special://masterprofile/").c_str());
990 // Expand the DLL search path with our directories
991 CWIN32Util::ExtendDllPath();
993 // check for a DVD drive
995 CWIN32Util::GetDrivesByType(vShare, DVD_DRIVES);
997 g_mediaManager.SetHasOpticalDrive(true);
999 // Can be removed once the StorageHandler supports optical media
1000 VECSOURCES::const_iterator it;
1001 for(it=vShare.begin();it!=vShare.end();++it)
1002 if(g_mediaManager.GetDriveStatus(it->strPath) == DRIVE_CLOSED_MEDIA_PRESENT)
1003 g_application.getApplicationMessenger().OpticalMount(it->strPath);
1012 void CApplication::CreateUserDirs()
1014 CDirectory::Create("special://home/");
1015 CDirectory::Create("special://home/addons");
1016 CDirectory::Create("special://home/addons/packages");
1017 CDirectory::Create("special://home/media");
1018 CDirectory::Create("special://home/sounds");
1019 CDirectory::Create("special://home/system");
1020 CDirectory::Create("special://masterprofile/");
1021 CDirectory::Create("special://temp/");
1022 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1025 bool CApplication::Initialize()
1027 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1028 // turn off cdio logging
1029 cdio_loglevel_default = CDIO_LOG_ERROR;
1032 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1033 // must create these here. Ideally this should be using special://home/ and
1034 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1035 if (!m_bPlatformDirectories)
1038 CDirectory::Create("special://xbmc/language");
1039 CDirectory::Create("special://xbmc/addons");
1040 CDirectory::Create("special://xbmc/sounds");
1045 // Init DPMS, before creating the corresponding setting control.
1046 m_dpms = new DPMSSupport();
1047 g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1049 g_windowManager.Add(new CGUIWindowHome); // window id = 0
1050 g_windowManager.Add(new CGUIWindowPrograms); // window id = 1
1051 g_windowManager.Add(new CGUIWindowPictures); // window id = 2
1052 g_windowManager.Add(new CGUIWindowFileManager); // window id = 3
1053 g_windowManager.Add(new CGUIWindowSettings); // window id = 4
1054 g_windowManager.Add(new CGUIWindowSystemInfo); // window id = 7
1056 g_windowManager.Add(new CGUIWindowTestPatternGL); // window id = 8
1059 g_windowManager.Add(new CGUIWindowTestPatternDX); // window id = 8
1061 g_windowManager.Add(new CGUIDialogTeletext); // window id =
1062 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
1063 g_windowManager.Add(new CGUIWindowSettingsCategory); // window id = 12 slideshow:window id 2007
1064 g_windowManager.Add(new CGUIWindowVideoNav); // window id = 36
1065 g_windowManager.Add(new CGUIWindowVideoPlaylist); // window id = 28
1066 g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29
1067 g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34
1068 g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40
1069 g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97
1070 g_windowManager.Add(new CGUIWindowDebugInfo); // window id = 98
1071 g_windowManager.Add(new CGUIWindowPointer); // window id = 99
1072 g_windowManager.Add(new CGUIDialogYesNo); // window id = 100
1073 g_windowManager.Add(new CGUIDialogProgress); // window id = 101
1074 g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103
1075 g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104
1076 g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115
1077 g_windowManager.Add(new CGUIDialogSubMenu); // window id = 105
1078 g_windowManager.Add(new CGUIDialogContextMenu); // window id = 106
1079 g_windowManager.Add(new CGUIDialogKaiToast); // window id = 107
1080 g_windowManager.Add(new CGUIDialogNumeric); // window id = 109
1081 g_windowManager.Add(new CGUIDialogGamepad); // window id = 110
1082 g_windowManager.Add(new CGUIDialogButtonMenu); // window id = 111
1083 g_windowManager.Add(new CGUIDialogMusicScan); // window id = 112
1084 g_windowManager.Add(new CGUIDialogMuteBug); // window id = 113
1085 g_windowManager.Add(new CGUIDialogPlayerControls); // window id = 114
1087 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall); // window id 143
1088 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge); // window id 144
1090 g_windowManager.Add(new CGUIDialogSlider); // window id = 145
1091 g_windowManager.Add(new CGUIDialogMusicOSD); // window id = 120
1092 g_windowManager.Add(new CGUIDialogVisualisationPresetList); // window id = 122
1093 g_windowManager.Add(new CGUIDialogVideoSettings); // window id = 123
1094 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings); // window id = 124
1095 g_windowManager.Add(new CGUIDialogVideoBookmarks); // window id = 125
1096 // Don't add the filebrowser dialog - it's created and added when it's needed
1097 g_windowManager.Add(new CGUIDialogNetworkSetup); // window id = 128
1098 g_windowManager.Add(new CGUIDialogMediaSource); // window id = 129
1099 g_windowManager.Add(new CGUIDialogProfileSettings); // window id = 130
1100 g_windowManager.Add(new CGUIDialogVideoScan); // window id = 133
1101 g_windowManager.Add(new CGUIDialogFavourites); // window id = 134
1102 g_windowManager.Add(new CGUIDialogSongInfo); // window id = 135
1103 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor); // window id = 136
1104 g_windowManager.Add(new CGUIDialogSmartPlaylistRule); // window id = 137
1105 g_windowManager.Add(new CGUIDialogBusy); // window id = 138
1106 g_windowManager.Add(new CGUIDialogPictureInfo); // window id = 139
1107 g_windowManager.Add(new CGUIDialogAddonInfo);
1108 g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140
1109 #ifdef HAS_LINUX_NETWORK
1110 g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141
1113 g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131
1115 g_windowManager.Add(new CGUIDialogContentSettings); // window id = 132
1117 g_windowManager.Add(new CGUIDialogPlayEject);
1119 g_windowManager.Add(new CGUIDialogPeripheralManager);
1120 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1122 g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500
1123 g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501
1124 g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502
1125 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor); // window id = 503
1127 g_windowManager.Add(new CGUIDialogSelect); // window id = 2000
1128 g_windowManager.Add(new CGUIDialogMusicInfo); // window id = 2001
1129 g_windowManager.Add(new CGUIDialogOK); // window id = 2002
1130 g_windowManager.Add(new CGUIDialogVideoInfo); // window id = 2003
1131 g_windowManager.Add(new CGUIDialogTextViewer);
1132 g_windowManager.Add(new CGUIWindowFullScreen); // window id = 2005
1133 g_windowManager.Add(new CGUIWindowVisualisation); // window id = 2006
1134 g_windowManager.Add(new CGUIWindowSlideShow); // window id = 2007
1135 g_windowManager.Add(new CGUIDialogFileStacking); // window id = 2008
1137 g_windowManager.Add(new CGUIWindowKaraokeLyrics); // window id = 2009
1140 g_windowManager.Add(new CGUIDialogVideoOSD); // window id = 2901
1141 g_windowManager.Add(new CGUIDialogMusicOverlay); // window id = 2903
1142 g_windowManager.Add(new CGUIDialogVideoOverlay); // window id = 2904
1143 g_windowManager.Add(new CGUIWindowScreensaver); // window id = 2900 Screensaver
1144 g_windowManager.Add(new CGUIWindowWeather); // window id = 2600 WEATHER
1145 g_windowManager.Add(new CGUIWindowStartup); // startup window (id 2999)
1147 /* window id's 3000 - 3100 are reserved for python */
1149 // Make sure we have at least the default skin
1150 if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
1152 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
1153 FatalErrorHandler(true, true, true);
1156 if (g_advancedSettings.m_splashImage)
1157 SAFE_DELETE(m_splash);
1159 if (g_guiSettings.GetBool("masterlock.startuplock") &&
1160 g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1161 !g_settings.GetMasterProfile().getLockCode().IsEmpty())
1163 g_passwordManager.CheckStartUpLock();
1166 // check if we should use the login screen
1167 if (g_settings.UsingLoginScreen())
1168 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1172 CJSONRPC::Initialize();
1174 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1177 g_sysinfo.Refresh();
1179 CLog::Log(LOGINFO, "removing tempfiles");
1180 CUtil::RemoveTempFiles();
1183 if (g_settings.m_bMute)
1186 // if the user shutoff the xbox during music scan
1187 // restore the settings
1188 if (g_settings.m_bMyMusicIsScanning)
1190 CLog::Log(LOGWARNING,"System rebooted during music scan! ... restoring UseTags and FindRemoteThumbs");
1191 RestoreMusicScanSettings();
1194 if (!g_settings.UsingLoginScreen())
1198 g_pythonParser.m_bLogin = true;
1202 m_slowTimer.StartZero();
1204 #if defined(__APPLE__) && !defined(__arm__)
1205 XBMCHelper::GetInstance().CaptureAllInput();
1207 #if defined(HAVE_LIBCRYSTALHD)
1208 CCrystalHD::GetInstance();
1211 CAddonMgr::Get().StartServices(false);
1213 CLog::Log(LOGNOTICE, "initialize done");
1215 m_bInitializing = false;
1217 // reset our screensaver (starts timers etc.)
1222 bool CApplication::StartWebServer()
1224 #ifdef HAS_WEB_SERVER
1225 if (g_guiSettings.GetBool("services.webserver") && m_network.IsAvailable())
1227 int webPort = atoi(g_guiSettings.GetString("services.webserverport"));
1228 CLog::Log(LOGNOTICE, "Webserver: Starting...");
1230 if (webPort < 1024 && geteuid() != 0)
1232 CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
1237 bool started = false;
1238 if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")))
1240 std::map<std::string, std::string> txt;
1242 // publish web frontend and API services
1243 #ifdef HAS_WEB_INTERFACE
1244 CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", "XBMC Web Server", webPort, txt);
1247 CZeroconf::GetInstance()->PublishService("servers.webapi", "_xbmc-web._tcp", "XBMC HTTP API", webPort, txt);
1250 CZeroconf::GetInstance()->PublishService("servers.webjsonrpc", "_xbmc-jsonrpc._tcp", "XBMC JSONRPC", webPort, txt);
1254 if (g_settings.m_HttpApiBroadcastLevel >= 1)
1255 getApplicationMessenger().HttpApi("broadcastlevel; StartUp;1");
1265 void CApplication::StopWebServer()
1267 #ifdef HAS_WEB_SERVER
1268 if (m_WebServer.IsStarted())
1270 CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1272 if(! m_WebServer.IsStarted() )
1274 CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1275 CZeroconf::GetInstance()->RemoveService("servers.webserver");
1276 CZeroconf::GetInstance()->RemoveService("servers.webjsonrpc");
1277 CZeroconf::GetInstance()->RemoveService("servers.webapi");
1279 CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
1284 void CApplication::StartAirplayServer()
1287 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1289 int listenPort = g_advancedSettings.m_airPlayPort;
1290 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1291 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1293 if (CAirPlayServer::StartServer(listenPort, true))
1295 CAirPlayServer::SetCredentials(usePassword, password);
1296 std::map<std::string, std::string> txt;
1297 CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
1300 txt["deviceid"] = iface->GetMacAddress();
1304 txt["deviceid"] = "FF:FF:FF:FF:FF:F2";
1306 txt["features"] = "0x77";
1307 txt["model"] = "AppleTV2,1";
1308 txt["srcvers"] = "101.28";
1309 CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt);
1314 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1316 int listenPort = g_advancedSettings.m_airTunesPort;
1317 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1318 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1320 if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password))
1322 CLog::Log(LOGERROR, "Failed to start AirTunes Server");
1328 void CApplication::StopAirplayServer(bool bWait)
1331 CAirPlayServer::StopServer(bWait);
1332 CZeroconf::GetInstance()->RemoveService("servers.airplay");
1335 CAirTunesServer::StopServer(bWait);
1339 bool CApplication::StartJSONRPCServer()
1342 if (g_guiSettings.GetBool("services.esenabled"))
1344 if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces")))
1346 std::map<std::string, std::string> txt;
1347 CZeroconf::GetInstance()->PublishService("servers.jsonrpc", "_xbmc-jsonrpc._tcp", "XBMC JSONRPC", g_advancedSettings.m_jsonTcpPort, txt);
1358 void CApplication::StopJSONRPCServer(bool bWait)
1361 CTCPServer::StopServer(bWait);
1362 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc");
1366 void CApplication::StartUPnP()
1370 StartUPnPRenderer();
1374 void CApplication::StopUPnP(bool bWait)
1377 if (CUPnP::IsInstantiated())
1379 CLog::Log(LOGNOTICE, "stopping upnp");
1380 CUPnP::ReleaseInstance(bWait);
1385 bool CApplication::StartEventServer()
1387 #ifdef HAS_EVENT_SERVER
1388 CEventServer* server = CEventServer::GetInstance();
1391 CLog::Log(LOGERROR, "ES: Out of memory");
1394 if (g_guiSettings.GetBool("services.esenabled"))
1396 CLog::Log(LOGNOTICE, "ES: Starting event server");
1397 server->StartServer();
1404 bool CApplication::StopEventServer(bool bWait, bool promptuser)
1406 #ifdef HAS_EVENT_SERVER
1407 CEventServer* server = CEventServer::GetInstance();
1410 CLog::Log(LOGERROR, "ES: Out of memory");
1415 if (server->GetNumberOfClients() > 0)
1417 bool cancelled = false;
1418 if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1419 -1, -1, cancelled, 10000)
1422 CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1426 CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1428 CEventServer::GetInstance()->StopServer(true);
1433 CLog::Log(LOGNOTICE, "ES: Stopping event server");
1435 CEventServer::GetInstance()->StopServer(bWait);
1442 void CApplication::RefreshEventServer()
1444 #ifdef HAS_EVENT_SERVER
1445 if (g_guiSettings.GetBool("services.esenabled"))
1447 CEventServer::GetInstance()->RefreshSettings();
1452 void CApplication::StartUPnPRenderer()
1455 if (g_guiSettings.GetBool("services.upnprenderer"))
1457 CLog::Log(LOGNOTICE, "starting upnp renderer");
1458 CUPnP::GetInstance()->StartRenderer();
1463 void CApplication::StopUPnPRenderer()
1466 if (CUPnP::IsInstantiated())
1468 CLog::Log(LOGNOTICE, "stopping upnp renderer");
1469 CUPnP::GetInstance()->StopRenderer();
1474 void CApplication::StartUPnPServer()
1477 if (g_guiSettings.GetBool("services.upnpserver"))
1479 CLog::Log(LOGNOTICE, "starting upnp server");
1480 CUPnP::GetInstance()->StartServer();
1485 void CApplication::StopUPnPServer()
1488 if (CUPnP::IsInstantiated())
1490 CLog::Log(LOGNOTICE, "stopping upnp server");
1491 CUPnP::GetInstance()->StopServer();
1496 void CApplication::StartZeroconf()
1499 //entry in guisetting only present if HAS_ZEROCONF is set
1500 if(g_guiSettings.GetBool("services.zeroconf"))
1502 CLog::Log(LOGNOTICE, "starting zeroconf publishing");
1503 CZeroconf::GetInstance()->Start();
1508 void CApplication::StopZeroconf()
1511 if(CZeroconf::IsInstantiated())
1513 CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
1514 CZeroconf::GetInstance()->Stop();
1519 void CApplication::DimLCDOnPlayback(bool dim)
1525 g_lcd->DisableOnPlayback(IsPlayingVideo(), IsPlayingAudio());
1527 g_lcd->SetBackLight(1);
1532 void CApplication::StartServices()
1534 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1535 // Start Thread for DVD Mediatype detection
1536 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1537 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1540 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1541 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1542 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistShuffle);
1543 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1544 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistShuffle);
1545 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1548 CLCDFactory factory;
1549 g_lcd = factory.Create();
1552 g_lcd->Initialize();
1557 void CApplication::StopServices()
1559 m_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1561 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1562 CLog::Log(LOGNOTICE, "stop dvd detect media");
1563 m_DetectDVDType.StopThread();
1566 g_peripherals.Clear();
1569 void CApplication::ReloadSkin()
1571 m_skinReloading = false;
1572 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1573 g_windowManager.SendMessage(msg);
1574 // Reload the skin, restoring the previously focused control. We need this as
1575 // the window unload will reset all control states.
1576 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1577 int iCtrlID = pWindow->GetFocusedControlID();
1578 g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1579 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1580 if (pWindow && pWindow->HasSaveLastControl())
1582 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1583 pWindow->OnMessage(msg3);
1587 bool CApplication::LoadSkin(const CStdString& skinID)
1589 if (m_skinReloading)
1593 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1595 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1601 void CApplication::LoadSkin(const SkinPtr& skin)
1605 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN);
1606 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1607 LoadSkin(DEFAULT_SKIN);
1611 bool bPreviousPlayingState=false;
1612 bool bPreviousRenderingState=false;
1613 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1615 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1616 if (bPreviousPlayingState)
1617 g_application.m_pPlayer->Pause();
1618 #ifdef HAS_VIDEO_PLAYBACK
1619 if (!g_renderManager.Paused())
1621 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1623 g_windowManager.ActivateWindow(WINDOW_HOME);
1624 bPreviousRenderingState = true;
1629 // close the music and video overlays (they're re-opened automatically later)
1630 CSingleLock lock(g_graphicsContext);
1632 // save the current window details
1633 int currentWindow = g_windowManager.GetActiveWindow();
1634 vector<int> currentModelessWindows;
1635 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1639 CLog::Log(LOGINFO, " load skin from:%s", skin->Path().c_str());
1641 g_SkinInfo->Start();
1643 CLog::Log(LOGINFO, " load fonts for skin...");
1644 g_graphicsContext.SetMediaDir(skin->Path());
1645 g_directoryCache.ClearSubPaths(skin->Path());
1646 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1648 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1649 CStdString strFontSet;
1650 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1652 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1653 g_guiSettings.SetString("lookandfeel.font", strFontSet);
1657 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1659 g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1661 g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1663 // load in the skin strings
1664 CStdString langPath, skinEnglishPath;
1665 URIUtils::AddFileToFolder(skin->Path(), "language", langPath);
1666 URIUtils::AddFileToFolder(langPath, g_guiSettings.GetString("locale.language"), langPath);
1667 URIUtils::AddFileToFolder(langPath, "strings.xml", langPath);
1669 URIUtils::AddFileToFolder(skin->Path(), "language", skinEnglishPath);
1670 URIUtils::AddFileToFolder(skinEnglishPath, "English", skinEnglishPath);
1671 URIUtils::AddFileToFolder(skinEnglishPath, "strings.xml", skinEnglishPath);
1673 g_localizeStrings.LoadSkinStrings(langPath, skinEnglishPath);
1675 g_SkinInfo->LoadIncludes();
1678 start = CurrentHostCounter();
1680 CLog::Log(LOGINFO, " load new skin...");
1681 CGUIWindowHome *pHome = (CGUIWindowHome *)g_windowManager.GetWindow(WINDOW_HOME);
1682 if (!pHome || !pHome->Load("Home.xml"))
1684 // failed to load home.xml
1685 // fallback to default skin
1686 if ( strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
1688 CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
1689 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1690 LoadSkin(DEFAULT_SKIN);
1695 // Load the user windows
1699 end = CurrentHostCounter();
1700 freq = CurrentHostFrequency();
1701 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1703 CLog::Log(LOGINFO, " initialize new skin...");
1704 g_windowManager.AddMsgTarget(this);
1705 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1706 g_windowManager.AddMsgTarget(&g_infoManager);
1707 g_windowManager.AddMsgTarget(&g_fontManager);
1708 g_windowManager.SetCallback(*this);
1709 g_windowManager.Initialize();
1710 CTextureCache::Get().Initialize();
1711 g_audioManager.Enable(true);
1712 g_audioManager.Load();
1714 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1715 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1717 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1718 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1719 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1720 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1721 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1724 CLog::Log(LOGINFO, " skin loaded...");
1726 // leave the graphics lock
1730 if (currentWindow != WINDOW_INVALID)
1732 g_windowManager.ActivateWindow(currentWindow);
1733 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1735 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1736 if (dialog) dialog->Show();
1740 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1742 if (bPreviousPlayingState)
1743 g_application.m_pPlayer->Pause();
1744 if (bPreviousRenderingState)
1745 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1749 void CApplication::UnloadSkin(bool forReload /* = false */)
1751 m_skinReloading = forReload;
1753 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1755 g_audioManager.Enable(false);
1757 g_windowManager.DeInitialize();
1758 CTextureCache::Get().Deinitialize();
1760 // remove the skin-dependent window
1761 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1763 g_TextureManager.Cleanup();
1764 g_largeTextureManager.CleanupUnusedImages(true);
1766 g_fontManager.Clear();
1768 g_colorManager.Clear();
1770 g_charsetConverter.reset();
1772 g_infoManager.Clear();
1775 bool CApplication::LoadUserWindows()
1777 // Start from wherever home.xml is
1778 std::vector<CStdString> vecSkinPath;
1779 g_SkinInfo->GetSkinPaths(vecSkinPath);
1780 for (unsigned int i = 0;i < vecSkinPath.size();++i)
1782 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1783 CFileItemList items;
1784 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", false))
1786 for (int i = 0; i < items.Size(); ++i)
1788 if (items[i]->m_bIsFolder)
1790 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1791 if (skinFile.Left(6).CompareNoCase("custom") == 0)
1793 TiXmlDocument xmlDoc;
1794 if (!xmlDoc.LoadFile(items[i]->GetPath()))
1796 CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1800 // Root element should be <window>
1801 TiXmlElement* pRootElement = xmlDoc.RootElement();
1802 CStdString strValue = pRootElement->Value();
1803 if (!strValue.Equals("window"))
1805 CLog::Log(LOGERROR, "file :%s doesnt contain <window>", skinFile.c_str());
1809 // Read the <type> element to get the window type to create
1810 // If no type is specified, create a CGUIWindow as default
1811 CGUIWindow* pWindow = NULL;
1813 if (pRootElement->Attribute("type"))
1814 strType = pRootElement->Attribute("type");
1817 const TiXmlNode *pType = pRootElement->FirstChild("type");
1818 if (pType && pType->FirstChild())
1819 strType = pType->FirstChild()->Value();
1821 int id = WINDOW_INVALID;
1822 if (!pRootElement->Attribute("id", &id))
1824 const TiXmlNode *pType = pRootElement->FirstChild("id");
1825 if (pType && pType->FirstChild())
1826 id = atol(pType->FirstChild()->Value());
1828 CStdString visibleCondition;
1829 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1831 if (strType.Equals("dialog"))
1832 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1833 else if (strType.Equals("submenu"))
1834 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
1835 else if (strType.Equals("buttonmenu"))
1836 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
1838 pWindow = new CGUIStandardWindow(id + WINDOW_HOME, skinFile);
1840 // Check to make sure the pointer isn't still null
1841 if (pWindow == NULL)
1843 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
1846 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
1851 pWindow->SetVisibleCondition(visibleCondition);
1852 g_windowManager.AddCustomWindow(pWindow);
1860 bool CApplication::RenderNoPresent()
1864 // DXMERGE: This may have been important?
1865 // g_graphicsContext.AcquireCurrentContext();
1867 g_graphicsContext.Lock();
1869 // dont show GUI when playing full screen video
1870 if (g_graphicsContext.IsFullScreenVideo())
1872 if (m_bPresentFrame && IsPlaying() && !IsPaused())
1875 g_renderManager.Present();
1878 g_renderManager.RenderUpdate(true);
1880 // close window overlays
1881 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1882 if (overlay) overlay->Close(true);
1883 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1884 if (overlay) overlay->Close(true);
1888 bool hasRendered = g_windowManager.Render();
1890 // if we're recording an audio stream then show blinking REC
1891 if (!g_graphicsContext.IsFullScreenVideo())
1893 if (m_pPlayer && m_pPlayer->IsRecording() )
1895 static int iBlinkRecord = 0;
1897 if (iBlinkRecord > 25)
1899 CGUIFont* pFont = g_fontManager.GetFont("font13");
1900 CGUITextLayout::DrawText(pFont, 60, 50, 0xffff0000, 0, "REC", 0);
1903 if (iBlinkRecord > 50)
1908 g_graphicsContext.Unlock();
1913 float CApplication::GetDimScreenSaverLevel() const
1915 if (!m_bScreenSave || !m_screenSaver ||
1916 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
1917 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
1918 m_screenSaver->ID() != "screensaver.xbmc.builtin.slideshow"))
1921 if (!m_screenSaver->GetSetting("level").IsEmpty())
1922 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
1926 bool CApplication::WaitFrame(unsigned int timeout)
1930 // Wait for all other frames to be presented
1931 CSingleLock lock(m_frameMutex);
1932 //wait until event is set, but modify remaining time
1934 TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
1935 cv.wait(lock,timeout);
1936 done = m_frameCount == 0;
1941 void CApplication::NewFrame()
1943 // We just posted another frame. Keep track and notify.
1945 CSingleLock lock(m_frameMutex);
1949 m_frameCond.notifyAll();
1952 void CApplication::Render()
1954 // do not render if we are stopped
1958 if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
1967 int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
1969 bool decrement = false;
1970 bool hasRendered = false;
1971 bool limitFrames = false;
1972 unsigned int singleFrameTime = 10; // default limit 100 fps
1976 bool lowfps = m_dpmsIsActive;
1977 // Whether externalplayer is playing and we're unfocused
1978 bool extPlayerActive = m_eCurrentPlayer >= EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
1980 m_bPresentFrame = false;
1981 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
1983 CSingleLock lock(m_frameMutex);
1985 TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
1988 m_bPresentFrame = m_frameCount > 0;
1989 decrement = m_bPresentFrame;
1994 // engage the frame limiter as needed
1995 limitFrames = lowfps || extPlayerActive;
1996 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
1997 // perhaps allowing it to be set differently than the UI option??
1998 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
1999 limitFrames = true; // not using vsync.
2000 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2001 limitFrames = true; // using vsync, but it isn't working.
2005 if (extPlayerActive)
2007 ResetScreenSaver(); // Prevent screensaver dimming the screen
2008 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2011 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2018 CSingleLock lock(g_graphicsContext);
2019 g_infoManager.UpdateFPS();
2021 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2022 g_Windowing.SetVSync(true);
2023 else if (vsync_mode == VSYNC_ALWAYS)
2024 g_Windowing.SetVSync(true);
2025 else if (vsync_mode != VSYNC_DRIVER)
2026 g_Windowing.SetVSync(false);
2028 if(!g_Windowing.BeginRender())
2031 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2032 if (RenderNoPresent())
2035 g_Windowing.EndRender();
2037 g_TextureManager.FreeUnusedTextures();
2039 // reset our info cache - we do this at the end of Render so that it is
2040 // fresh for the next process(), or after a windowclose animation (where process()
2042 g_infoManager.ResetCache();
2046 unsigned int now = XbmcThreads::SystemClockMillis();
2048 m_lastRenderTime = now;
2050 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2051 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2053 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2054 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2058 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2059 if (limitFrames || !flip)
2062 singleFrameTime = 40; //if not flipping, loop at 25 fps
2064 unsigned int frameTime = now - m_lastFrameTime;
2065 if (frameTime < singleFrameTime)
2066 Sleep(singleFrameTime - frameTime);
2068 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2071 g_graphicsContext.Flip(dirtyRegions);
2072 CTimeUtils::UpdateFrameTime(flip);
2074 g_renderManager.UpdateResolution();
2075 g_renderManager.ManageCaptures();
2078 CSingleLock lock(m_frameMutex);
2079 if(m_frameCount > 0 && decrement)
2082 m_frameCond.notifyAll();
2085 void CApplication::SetStandAlone(bool value)
2087 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2090 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2091 // The window manager will return true if the event is processed, false otherwise.
2092 // If not already processed, this routine handles global keypresses. It returns
2093 // true if the key has been processed, false otherwise.
2095 bool CApplication::OnKey(const CKey& key)
2098 // Turn the mouse off, as we've just got a keypress from controller or remote
2099 g_Mouse.SetActive(false);
2101 // get the current active window
2102 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2104 // this will be checked for certain keycodes that need
2105 // special handling if the screensaver is active
2106 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2108 // a key has been pressed.
2110 m_idleTimer.StartZero();
2111 bool processKey = AlwaysProcess(action);
2115 // allow some keys to be processed while the screensaver is active
2116 if (WakeUpScreenSaverAndDPMS() && !processKey)
2118 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2122 // change this if we have a dialog up
2123 if (g_windowManager.HasModalDialog())
2125 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2127 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2128 { // fullscreen info dialog - special case
2129 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2131 if (!key.IsAnalogButton())
2132 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2134 if (OnAction(action))
2137 // fallthrough to the main window
2138 iWin = WINDOW_FULLSCREEN_VIDEO;
2140 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2142 // current active window is full screen video.
2143 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2145 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2146 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2150 // no then use the fullscreen window section of keymap.xml to map key->action
2151 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2156 // current active window isnt the fullscreen window
2157 // just use corresponding section from keymap.xml
2158 // to map key->action
2160 // first determine if we should use keyboard input directly
2161 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2162 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2165 CGUIControl *control = window->GetFocusedControl();
2168 // If this is an edit control set usekeyboard to true. This causes the
2169 // keypress to be processed directly not through the key mappings.
2170 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2173 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2174 // This causes the keypress to be used for list navigation.
2175 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2181 action = CAction(0); // reset our action
2182 if (g_guiSettings.GetBool("input.remoteaskeyboard"))
2184 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2185 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2186 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2187 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2188 action.GetID() == ACTION_MOVE_RIGHT ||
2189 action.GetID() == ACTION_MOVE_UP ||
2190 action.GetID() == ACTION_MOVE_DOWN ||
2191 action.GetID() == ACTION_SELECT_ITEM ||
2192 action.GetID() == ACTION_ENTER ||
2193 action.GetID() == ACTION_PREVIOUS_MENU ||
2194 action.GetID() == ACTION_NAV_BACK))
2196 // the action isn't plain navigation - check for a keyboard-specific keymap
2197 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2198 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2199 action.GetID() == ACTION_BACKSPACE ||
2200 action.GetID() == ACTION_SHIFT ||
2201 action.GetID() == ACTION_SYMBOLS ||
2202 action.GetID() == ACTION_CURSOR_LEFT ||
2203 action.GetID() == ACTION_CURSOR_RIGHT)
2204 action = CAction(0); // don't bother with this action
2207 if (!action.GetID())
2209 // keyboard entry - pass the keys through directly
2210 if (key.GetFromHttpApi())
2211 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2213 { // see if we've got an ascii key
2214 if (key.GetUnicode())
2215 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2217 action = CAction(key.GetVKey() | KEY_VKEY);
2221 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2223 if (OnAction(action))
2225 // failed to handle the keyboard action, drop down through to standard action
2227 if (key.GetFromHttpApi())
2229 if (key.GetButtonCode() != KEY_INVALID)
2230 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2233 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2235 if (!key.IsAnalogButton())
2236 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2238 // Play a sound based on the action
2239 g_audioManager.PlayActionSound(action);
2241 return OnAction(action);
2244 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2245 // This needs to return true if it processed the appcommand or false if it didn't
2246 bool CApplication::OnAppCommand(const CAction &action)
2248 // Reset the screen saver
2251 // If we were currently in the screen saver wake up and don't process the appcommand
2252 if (WakeUpScreenSaverAndDPMS())
2255 // The action ID is the APPCOMMAND code. We need to retrieve the action
2256 // associated with this appcommand from the mapping table.
2257 uint32_t appcmd = action.GetID();
2258 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2259 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2260 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2262 // If we couldn't find an action return false to indicate we have not
2263 // handled this appcommand
2264 if (!appcmdaction.GetID())
2266 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2270 // Process the appcommand
2271 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2272 OnAction(appcmdaction);
2274 // Always return true regardless of whether the action succeeded or not.
2275 // This stops Windows handling the appcommand itself.
2279 bool CApplication::OnAction(const CAction &action)
2282 // Let's tell the outside world about this action, ignoring mouse moves
2283 if (g_settings.m_HttpApiBroadcastLevel>=2 && action.GetID() != ACTION_MOUSE_MOVE)
2286 tmp.Format("%i",action.GetID());
2287 getApplicationMessenger().HttpApi("broadcastlevel; OnAction:"+tmp+";2");
2291 // special case for switching between GUI & fullscreen mode.
2292 if (action.GetID() == ACTION_SHOW_GUI)
2293 { // Switch to fullscreen mode if we can
2294 if (SwitchToFullScreen())
2296 m_navigationTimer.StartZero();
2301 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2303 g_graphicsContext.ToggleFullScreenRoot();
2307 if (action.IsMouse())
2308 g_Mouse.SetActive(true);
2310 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2311 // playing or ACTION_PLAYER_PLAY if we are not playing.
2312 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2315 return OnAction(CAction(ACTION_PAUSE));
2317 return OnAction(CAction(ACTION_PLAYER_PLAY));
2320 //if the action would start or stop inertial scrolling
2321 //by gesture - bypass the normal OnAction handler of current window
2322 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2325 // just pass the action to the current window and let it handle it
2326 if (g_windowManager.OnAction(action))
2328 m_navigationTimer.StartZero();
2333 // handle extra global presses
2335 // screenshot : take a screenshot :)
2336 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2338 CUtil::TakeScreenshot();
2341 // built in functions : execute the built-in
2342 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2344 CBuiltins::Execute(action.GetName());
2345 m_navigationTimer.StartZero();
2350 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2352 CButtonTranslator::GetInstance().Clear();
2353 CButtonTranslator::GetInstance().Load();
2356 // show info : Shows the current video or song information
2357 if (action.GetID() == ACTION_SHOW_INFO)
2359 g_infoManager.ToggleShowInfo();
2363 // codec info : Shows the current song, video or picture codec information
2364 if (action.GetID() == ACTION_SHOW_CODEC)
2366 g_infoManager.ToggleShowCodec();
2370 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2372 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2375 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2376 char rating = tag->GetRating();
2377 bool needsUpdate(false);
2378 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2380 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2383 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2385 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2391 if (db.Open()) // OpenForWrite() ?
2393 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2396 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2397 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2398 g_windowManager.SendMessage(msg);
2404 // stop : stops playing current audio song
2405 if (action.GetID() == ACTION_STOP)
2411 // previous : play previous song from playlist
2412 if (action.GetID() == ACTION_PREV_ITEM)
2414 // first check whether we're within 3 seconds of the start of the track
2415 // if not, we just revert to the start of the track
2416 if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2423 g_playlistPlayer.PlayPrevious();
2428 // next : play next song from playlist
2429 if (action.GetID() == ACTION_NEXT_ITEM)
2431 if (IsPlaying() && m_pPlayer->SkipNext())
2434 g_playlistPlayer.PlayNext();
2441 // pause : pauses current audio song
2442 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2446 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2448 if (!m_pPlayer->IsPaused())
2449 { // unpaused - set the playspeed back to normal
2452 g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2455 if (!m_pPlayer->IsPaused())
2457 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2458 // if we are playing at normal speed, then allow play to pause
2459 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2461 if (m_iPlaySpeed != 1)
2471 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2473 int iPlaySpeed = m_iPlaySpeed;
2474 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2476 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2478 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2483 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2485 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2488 SetPlaySpeed(iPlaySpeed);
2491 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2493 // calculate the speed based on the amount the button is held down
2494 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2495 // returns 0 -> MAX_FFWD_SPEED
2496 int iSpeed = 1 << iPower;
2497 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2499 g_application.SetPlaySpeed(iSpeed);
2501 CLog::Log(LOGDEBUG,"Resetting playspeed");
2505 // allow play to unpause
2508 if (action.GetID() == ACTION_PLAYER_PLAY)
2510 // unpause, and set the playspeed back to normal
2512 g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2514 g_application.SetPlaySpeed(1);
2519 if (action.GetID() == ACTION_MUTE)
2525 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2527 switch(g_guiSettings.GetInt("audiooutput.mode"))
2529 case AUDIO_ANALOG: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958); break;
2530 case AUDIO_IEC958: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); break;
2531 case AUDIO_HDMI : g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG); break;
2534 g_application.Restart();
2535 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2537 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2538 g_windowManager.SendMessage(msg);
2543 // Check for global volume control
2544 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2546 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2548 // increase or decrease the volume
2550 if (g_settings.m_bMute)
2552 volume = (int)((float)g_settings.m_iPreMuteVolumeLevel * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
2556 volume = g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel;
2558 // calculate speed so that a full press will equal 1 second from min to max
2559 float speed = float(VOLUME_MAXIMUM - VOLUME_MINIMUM);
2560 if (action.GetRepeat())
2561 speed *= action.GetRepeat();
2563 speed /= 50; //50 fps
2565 if (action.GetID() == ACTION_VOLUME_UP)
2566 volume += (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2568 volume -= (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2570 SetVolume(volume, false);
2572 // show visual feedback of volume change...
2573 ShowVolumeBar(&action);
2576 // Check for global seek control
2577 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2579 if (!m_pPlayer->CanSeek()) return false;
2580 CGUIWindow *seekBar = g_windowManager.GetWindow(WINDOW_DIALOG_SEEK_BAR);
2582 seekBar->OnAction(action);
2585 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2587 CGUIControlProfiler::Instance().SetOutputFile(_P("special://home/guiprofiler.xml"));
2588 CGUIControlProfiler::Instance().Start();
2591 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2593 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2594 if (iPlaylist == PLAYLIST_VIDEO)
2595 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2596 else if (iPlaylist == PLAYLIST_MUSIC)
2597 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2603 void CApplication::UpdateLCD()
2606 static unsigned int lTickCount = 0;
2608 if (!g_lcd || !g_guiSettings.GetBool("videoscreen.haslcd"))
2610 unsigned int lTimeOut = 1000;
2611 if ( m_iPlaySpeed != 1)
2613 if ( (XbmcThreads::SystemClockMillis() - lTickCount) >= lTimeOut)
2615 if (g_application.NavigationIdleTime() < 5)
2616 g_lcd->Render(ILCD::LCD_MODE_NAVIGATION);
2617 else if (IsPlayingVideo())
2618 g_lcd->Render(ILCD::LCD_MODE_VIDEO);
2619 else if (IsPlayingAudio())
2620 g_lcd->Render(ILCD::LCD_MODE_MUSIC);
2621 else if (IsInScreenSaver())
2622 g_lcd->Render(ILCD::LCD_MODE_SCREENSAVER);
2624 g_lcd->Render(ILCD::LCD_MODE_GENERAL);
2627 lTickCount = XbmcThreads::SystemClockMillis();
2632 void CApplication::FrameMove(bool processEvents)
2638 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2639 float frameTime = m_frameTime.GetElapsedSeconds();
2640 m_frameTime.StartZero();
2641 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2642 if( frameTime > 0.5 ) frameTime = 0.5;
2644 g_graphicsContext.Lock();
2645 // check if there are notifications to display
2646 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2647 if (toast && toast->DoWork())
2649 if (!toast->IsDialogRunning())
2654 g_graphicsContext.Unlock();
2658 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2659 // Read the input from a remote
2660 g_RemoteControl.Update();
2663 // process input actions
2664 CWinEvents::MessagePump();
2665 ProcessHTTPApiButtons();
2666 ProcessRemote(frameTime);
2667 ProcessGamepad(frameTime);
2668 ProcessEventServer(frameTime);
2669 ProcessPeripherals(frameTime);
2670 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2673 g_windowManager.Process(CTimeUtils::GetFrameTime());
2674 g_windowManager.FrameMove();
2677 bool CApplication::ProcessGamepad(float frameTime)
2679 #ifdef HAS_SDL_JOYSTICK
2682 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2683 if (g_windowManager.HasModalDialog())
2685 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2688 g_Joystick.Update();
2689 if (g_Joystick.GetButton(bid))
2692 m_idleTimer.StartZero();
2695 if (WakeUpScreenSaverAndDPMS())
2697 g_Joystick.Reset(true);
2702 CStdString actionName;
2704 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2706 CAction action(actionID, 1.0f, 0.0f, actionName);
2707 g_audioManager.PlayActionSound(action);
2709 g_Mouse.SetActive(false);
2710 return OnAction(action);
2717 if (g_Joystick.GetAxis(bid))
2719 if (g_Joystick.GetAmount() < 0)
2725 CStdString actionName;
2727 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2730 if (WakeUpScreenSaverAndDPMS())
2735 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2736 g_audioManager.PlayActionSound(action);
2738 g_Mouse.SetActive(false);
2739 return OnAction(action);
2743 g_Joystick.ResetAxis(abs(bid));
2747 if (g_Joystick.GetHat(bid, position))
2750 m_idleTimer.StartZero();
2753 if (WakeUpScreenSaverAndDPMS())
2760 CStdString actionName;
2763 bid = position<<16|bid;
2765 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2767 CAction action(actionID, 1.0f, 0.0f, actionName);
2768 g_audioManager.PlayActionSound(action);
2770 g_Mouse.SetActive(false);
2771 return OnAction(action);
2778 bool CApplication::ProcessRemote(float frameTime)
2780 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2781 if (g_RemoteControl.GetButton())
2783 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2784 g_RemoteControl.Reset();
2791 bool CApplication::ProcessPeripherals(float frameTime)
2794 vector<CPeripheral *> peripherals;
2795 if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
2797 for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
2799 CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
2800 if (cecDevice && cecDevice->GetButton())
2802 CKey key(cecDevice->GetButton(), cecDevice->GetHoldTime());
2803 cecDevice->ResetButton();
2813 bool CApplication::ProcessMouse()
2817 if (!g_Mouse.IsActive() || !m_AppFocused)
2820 // Get the mouse command ID
2821 uint32_t mousecommand = g_Mouse.GetAction();
2822 if (mousecommand == ACTION_NOOP)
2825 // Reset the screensaver and idle timers
2826 m_idleTimer.StartZero();
2828 if (WakeUpScreenSaverAndDPMS())
2831 // Retrieve the corresponding action
2833 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2834 if (g_windowManager.HasModalDialog())
2835 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2837 iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2838 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2840 // If we couldn't find an action return false to indicate we have not
2841 // handled this mouse action
2842 if (!mouseaction.GetID())
2844 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
2848 // Log mouse actions except for move and noop
2849 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
2850 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
2852 // The action might not be a mouse action. For example wheel moves might
2853 // be mapped to volume up/down in mouse.xml. In this case we do not want
2854 // the mouse position saved in the action.
2855 if (!mouseaction.IsMouse())
2856 return OnAction(mouseaction);
2858 // This is a mouse action so we need to record the mouse position
2859 return OnAction(CAction(mouseaction.GetID(),
2860 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
2861 (float)g_Mouse.GetX(),
2862 (float)g_Mouse.GetY(),
2863 (float)g_Mouse.GetDX(),
2864 (float)g_Mouse.GetDY(),
2865 mouseaction.GetName()));
2868 void CApplication::CheckForTitleChange()
2871 if (g_settings.m_HttpApiBroadcastLevel>=1)
2873 if (IsPlayingVideo())
2875 const CVideoInfoTag* tagVal = g_infoManager.GetCurrentMovieTag();
2876 if (m_pXbmcHttp && tagVal && !(tagVal->m_strTitle.IsEmpty()))
2878 CStdString msg=m_pXbmcHttp->GetOpenTag()+"MovieTitle:"+tagVal->m_strTitle+m_pXbmcHttp->GetCloseTag();
2879 if (m_prevMedia!=msg && g_settings.m_HttpApiBroadcastLevel>=1)
2881 getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2886 else if (IsPlayingAudio())
2888 const CMusicInfoTag* tagVal=g_infoManager.GetCurrentSongTag();
2889 if (m_pXbmcHttp && tagVal)
2892 if (!tagVal->GetTitle().IsEmpty())
2893 msg=m_pXbmcHttp->GetOpenTag()+"AudioTitle:"+tagVal->GetTitle()+m_pXbmcHttp->GetCloseTag();
2894 if (!tagVal->GetArtist().IsEmpty())
2895 msg+=m_pXbmcHttp->GetOpenTag()+"AudioArtist:"+tagVal->GetArtist()+m_pXbmcHttp->GetCloseTag();
2896 if (m_prevMedia!=msg)
2898 getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2907 bool CApplication::ProcessHTTPApiButtons()
2912 // copy key from webserver, and reset it in case we're called again before
2913 // whatever happens in OnKey()
2914 CKey keyHttp(m_pXbmcHttp->GetKey());
2915 m_pXbmcHttp->ResetKey();
2916 if (keyHttp.GetButtonCode() != KEY_INVALID)
2918 if (keyHttp.GetButtonCode() == KEY_VMOUSE) //virtual mouse
2920 int actionID = ACTION_MOUSE_MOVE;
2921 if (keyHttp.GetLeftTrigger() == 1)
2922 actionID = ACTION_MOUSE_LEFT_CLICK;
2923 else if (keyHttp.GetLeftTrigger() == 2)
2924 actionID = ACTION_MOUSE_RIGHT_CLICK;
2925 else if (keyHttp.GetLeftTrigger() == 3)
2926 actionID = ACTION_MOUSE_MIDDLE_CLICK;
2927 else if (keyHttp.GetRightTrigger() == 1)
2928 actionID = ACTION_MOUSE_DOUBLE_CLICK;
2929 CAction action(actionID, keyHttp.GetLeftThumbX(), keyHttp.GetLeftThumbY());
2941 bool CApplication::ProcessEventServer(float frameTime)
2943 #ifdef HAS_EVENT_SERVER
2944 CEventServer* es = CEventServer::GetInstance();
2945 if (!es || !es->Running() || es->GetNumberOfClients()==0)
2948 // process any queued up actions
2949 if (es->ExecuteNextAction())
2951 // reset idle timers
2952 m_idleTimer.StartZero();
2954 WakeUpScreenSaverAndDPMS();
2957 // now handle any buttons or axis
2958 std::string joystickName;
2959 bool isAxis = false;
2960 float fAmount = 0.0;
2962 WORD wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
2966 if (joystickName.length() > 0)
2970 if (fabs(fAmount) >= 0.08)
2971 m_lastAxisMap[joystickName][wKeyID] = fAmount;
2973 m_lastAxisMap[joystickName].erase(wKeyID);
2976 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
2981 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
2982 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
2983 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
2984 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
2985 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
2986 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
2987 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
2988 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
2989 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
2990 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
2991 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
2992 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
2993 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
2994 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
2995 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
2996 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
2997 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
2998 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
2999 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3000 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3007 if (m_lastAxisMap.size() > 0)
3009 // Process all the stored axis.
3010 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3012 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3013 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3019 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3020 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3026 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount)
3028 #if defined(HAS_EVENT_SERVER)
3029 m_idleTimer.StartZero();
3031 // Make sure to reset screen saver, mouse.
3033 if (WakeUpScreenSaverAndDPMS())
3036 #ifdef HAS_SDL_JOYSTICK
3039 g_Mouse.SetActive(false);
3041 // Figure out what window we're taking the event for.
3042 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3043 if (g_windowManager.HasModalDialog())
3044 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3046 // This code is copied from the OnKey handler, it should be factored out.
3047 if (iWin == WINDOW_FULLSCREEN_VIDEO &&
3048 g_application.m_pPlayer &&
3049 g_application.m_pPlayer->IsInMenu())
3051 // If player is in some sort of menu, (ie DVDMENU) map buttons differently.
3052 iWin = WINDOW_VIDEO_MENU;
3056 CStdString actionName;
3057 bool fullRange = false;
3059 // Translate using regular joystick translator.
3060 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3062 CAction action(actionID, fAmount, 0.0f, actionName);
3063 g_audioManager.PlayActionSound(action);
3064 return OnAction(action);
3068 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3075 bool CApplication::Cleanup()
3079 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3080 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3081 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3082 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3083 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3084 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3085 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3086 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3087 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3088 g_windowManager.Delete(WINDOW_FILES);
3089 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3090 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3091 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3092 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3093 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3094 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3095 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3096 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_SCAN);
3097 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3098 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3099 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3100 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3101 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3102 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3103 g_windowManager.Delete(WINDOW_DIALOG_OK);
3104 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3105 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3106 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3107 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3108 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3109 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3110 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3111 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3112 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3113 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3114 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_SCAN);
3115 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3116 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3117 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3118 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3119 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3120 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3121 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3122 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3123 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3124 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3125 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3127 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3128 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3130 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3132 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3133 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3134 g_windowManager.Delete(WINDOW_VISUALISATION);
3135 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3136 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3137 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3138 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3139 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3140 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3141 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3142 g_windowManager.Delete(WINDOW_SCREENSAVER);
3143 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3144 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3145 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3146 g_windowManager.Delete(WINDOW_SLIDESHOW);
3148 g_windowManager.Delete(WINDOW_HOME);
3149 g_windowManager.Delete(WINDOW_PROGRAMS);
3150 g_windowManager.Delete(WINDOW_PICTURES);
3151 g_windowManager.Delete(WINDOW_WEATHER);
3153 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3154 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3155 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3156 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3157 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3158 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3159 g_windowManager.Remove(WINDOW_SETTINGS_NETWORK);
3160 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3161 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3163 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3164 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3166 CAddonMgr::Get().DeInit();
3168 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3169 CLog::Log(LOGNOTICE, "closing down remote control service");
3170 g_RemoteControl.Disconnect();
3173 CLog::Log(LOGNOTICE, "unload sections");
3175 #ifdef HAS_PERFORMANCE_SAMPLE
3176 CLog::Log(LOGNOTICE, "performance statistics");
3177 m_perfStats.DumpStats();
3180 // Shutdown as much as possible of the
3181 // application, to reduce the leaks dumped
3182 // to the vc output window before calling
3183 // _CrtDumpMemoryLeaks(). Most of the leaks
3184 // shown are no real leaks, as parts of the app
3185 // are still allocated.
3187 g_localizeStrings.Clear();
3188 g_LangCodeExpander.Clear();
3189 g_charsetConverter.clear();
3190 g_directoryCache.Clear();
3191 CButtonTranslator::GetInstance().Clear();
3192 CLastfmScrobbler::RemoveInstance();
3193 CLibrefmScrobbler::RemoveInstance();
3194 CLastFmManager::RemoveInstance();
3195 #ifdef HAS_EVENT_SERVER
3196 CEventServer::RemoveInstance();
3198 DllLoaderContainer::Clear();
3199 g_playlistPlayer.Clear();
3201 g_guiSettings.Clear();
3202 g_advancedSettings.Clear();
3205 CXHandle::DumpObjectTracker();
3208 #ifdef _CRTDBG_MAP_ALLOC
3209 _CrtDumpMemoryLeaks();
3210 while(1); // execution ends
3222 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3227 void CApplication::Stop(int exitCode)
3231 CAnnouncementManager::Announce(System, "xbmc", "OnQuit");
3233 // cancel any jobs from the jobmanager
3234 CJobManager::GetInstance().CancelJobs();
3236 g_alarmClock.StopThread();
3241 if (g_settings.m_HttpApiBroadcastLevel >= 1)
3242 getApplicationMessenger().HttpApi("broadcastlevel; ShutDown;1");
3244 m_pXbmcHttp->shuttingDown = true;
3248 if( m_bSystemScreenSaverEnable )
3249 g_Windowing.EnableSystemScreenSaver(true);
3251 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3252 g_settings.m_iSystemTimeTotalUp = g_settings.m_iSystemTimeTotalUp + (int)(CTimeUtils::GetFrameTime() / 60000);
3254 // Update the settings information (volume, uptime etc. need saving)
3255 if (CFile::Exists(g_settings.GetSettingsFile()))
3257 CLog::Log(LOGNOTICE, "Saving settings");
3261 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3264 m_AppActive = false;
3265 m_AppFocused = false;
3266 m_ExitCode = exitCode;
3267 CLog::Log(LOGNOTICE, "stop all");
3269 // stop scanning before we kill the network and so on
3270 CGUIDialogMusicScan *musicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
3272 musicScan->StopScanning();
3274 CGUIDialogVideoScan *videoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
3276 videoScan->StopScanning();
3278 m_applicationMessenger.Cleanup();
3283 #if defined(__APPLE__) && !defined(__arm__)
3284 XBMCHelper::GetInstance().ReleaseAllInput();
3289 CLog::Log(LOGNOTICE, "stop player");
3294 #if HAS_FILESYTEM_DAAP
3295 CLog::Log(LOGNOTICE, "stop daap clients");
3296 g_DaapClient.Release();
3298 #ifdef HAS_FILESYSTEM_SAP
3299 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3300 g_sapsessions.StopThread();
3303 if(CZeroconfBrowser::IsInstantiated())
3305 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3306 CZeroconfBrowser::GetInstance()->Stop();
3307 CZeroconfBrowser::ReleaseInstance();
3311 CLog::Log(LOGNOTICE, "clean cached files!");
3312 #ifdef HAS_FILESYSTEM_RAR
3313 g_RarManager.ClearCache(true);
3316 #ifdef HAS_FILESYSTEM_SFTP
3317 CSFTPSessionManager::DisconnectAllSessions();
3320 CLog::Log(LOGNOTICE, "unload skin");
3323 #if defined(__APPLE__) && !defined(__arm__)
3324 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3325 XBMCHelper::GetInstance().Stop();
3328 #if defined(HAVE_LIBCRYSTALHD)
3329 CCrystalHD::RemoveInstance();
3332 g_mediaManager.Stop();
3334 // Stop services before unloading Python
3335 CAddonMgr::Get().StopServices(false);
3337 /* Python resource freeing must be done after skin has been unloaded, not before
3338 some windows still need it when deinitializing during skin unloading. */
3340 CLog::Log(LOGNOTICE, "stop python");
3341 g_pythonParser.FreeResources();
3352 g_Windowing.DestroyRenderSystem();
3353 g_Windowing.DestroyWindow();
3354 g_Windowing.DestroyWindowSystem();
3356 CLog::Log(LOGNOTICE, "stopped");
3360 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3363 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3364 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3371 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3373 //If item is a plugin, expand out now and run ourselves again
3374 if (item.IsPlugin())
3376 CFileItem item_new(item);
3377 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3378 return PlayMedia(item_new, iPlaylist);
3381 if (item.IsLastFM())
3383 g_partyModeManager.Disable();
3384 return CLastFmManager::GetInstance()->ChangeStation(item.GetAsUrl());
3386 if (item.IsSmartPlayList())
3388 CFileItemList items;
3389 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3392 CSmartPlaylist smartpl;
3393 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3394 smartpl.OpenAndReadName(item.GetPath());
3396 playlist.Add(items);
3397 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3400 else if (item.IsPlayList() || item.IsInternetStream())
3402 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3404 //is or could be a playlist
3405 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3406 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3411 if (dlgCache->IsCanceled())
3418 if (iPlaylist != PLAYLIST_NONE)
3421 if (item.HasProperty("playlist_starting_track"))
3422 track = item.GetProperty("playlist_starting_track").asInteger();
3423 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3427 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());
3428 if(pPlayList->size())
3429 return PlayFile(*(*pPlayList)[0], false);
3434 //nothing special just play
3435 return PlayFile(item, false);
3439 // For playing a multi-file video. Particularly inefficient
3440 // on startup, as we are required to calculate the length
3441 // of each video, so we open + close each one in turn.
3442 // A faster calculation of video time would improve this
3444 bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3446 if (!item.IsStack())
3449 // see if we have the info in the database
3450 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3451 // then these times will be wrong.
3452 // Also, this is really just a hack for the slow load up times we have
3453 // A much better solution is a fast reader of FPS and fileLength
3454 // that we can use on a file to get it's time.
3456 bool haveTimes(false);
3460 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3461 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3466 // calculate the total time of the stack
3467 CStackDirectory dir;
3468 dir.GetDirectory(item.GetPath(), *m_currentStack);
3470 for (int i = 0; i < m_currentStack->Size(); i++)
3473 (*m_currentStack)[i]->m_lEndOffset = times[i];
3477 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3479 m_currentStack->Clear();
3482 totalTime += duration / 1000;
3483 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3484 times.push_back(totalTime);
3488 double seconds = item.m_lStartOffset / 75.0;
3490 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3491 { // have our times now, so update the dB
3495 dbs.SetStackTimes(item.GetPath(), times);
3497 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3499 // can only resume seek here, not dvdstate
3501 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3502 seconds = bookmark.timeInSeconds;
3510 *m_itemCurrentFile = item;
3511 m_currentStackPosition = 0;
3512 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3516 // work out where to seek to
3517 for (int i = 0; i < m_currentStack->Size(); i++)
3519 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3521 CFileItem item(*(*m_currentStack)[i]);
3522 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3523 item.m_lStartOffset = (long)(seconds - start) * 75;
3524 m_currentStackPosition = i;
3525 return PlayFile(item, true);
3530 return PlayFile(*(*m_currentStack)[0], true);
3533 bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
3537 SaveCurrentFileSettings();
3539 OutputDebugString("new file set audiostream:0\n");
3540 // Switch to default options
3541 g_settings.m_currentVideoSettings = g_settings.m_defaultVideoSettings;
3542 // see if we have saved options in the database
3545 *m_itemCurrentFile = item;
3546 m_nextPlaylistItem = -1;
3547 m_currentStackPosition = 0;
3548 m_currentStack->Clear();
3551 CUtil::ClearSubtitles();
3554 if (item.IsDiscStub())
3556 #ifdef HAS_DVD_DRIVE
3557 // Display the Play Eject dialog
3558 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3559 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3560 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3561 return MEDIA_DETECT::CAutorun::PlayDiscAskResume();
3566 if (item.IsPlayList())
3569 if (item.IsPlugin())
3570 { // we modify the item so that it becomes a real URL
3571 CFileItem item_new(item);
3572 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3573 return PlayFile(item_new, false);
3577 if (URIUtils::IsUPnP(item.GetPath()))
3579 CFileItem item_new(item);
3580 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3581 return PlayFile(item_new, false);
3585 // if we have a stacked set of files, we need to setup our stack routines for
3586 // "seamless" seeking and total time of the movie etc.
3587 // will recall with restart set to true
3589 return PlayStack(item, bRestart);
3591 //Is TuxBox, this should probably be moved to CFileTuxBox
3594 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3596 if(g_tuxboxService.IsRunning())
3597 g_tuxboxService.Stop();
3600 if(g_tuxbox.CreateNewItem(item, item_new))
3603 // Make sure it doesn't have a player
3604 // so we actually select one normally
3605 m_eCurrentPlayer = EPC_NONE;
3607 // keep the tuxbox:// url as playing url
3608 // and give the new url to the player
3609 if(PlayFile(item_new, true))
3611 if(!g_tuxboxService.IsRunning())
3612 g_tuxboxService.Start();
3619 CPlayerOptions options;
3621 if( item.HasProperty("StartPercent") )
3623 options.startpercent = item.GetProperty("StartPercent").asDouble();
3626 PLAYERCOREID eNewCore = EPC_NONE;
3629 // have to be set here due to playstack using this for starting the file
3630 options.starttime = item.m_lStartOffset / 75.0;
3631 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3632 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3634 if( m_eForcedNextPlayer != EPC_NONE )
3635 eNewCore = m_eForcedNextPlayer;
3636 else if( m_eCurrentPlayer == EPC_NONE )
3637 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3639 eNewCore = m_eCurrentPlayer;
3643 options.starttime = item.m_lStartOffset / 75.0;
3647 // open the d/b and retrieve the bookmarks for the current movie
3650 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3652 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3654 options.starttime = 0.0f;
3656 CStdString path = item.GetPath();
3657 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3658 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3659 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3660 path = item.GetProperty("original_listitem_url").asString();
3661 if(dbs.GetResumeBookMark(path, bookmark))
3663 options.starttime = bookmark.timeInSeconds;
3664 options.state = bookmark.playerState;
3667 else if (item.HasVideoInfoTag())
3669 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3671 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3674 dbs.GetBookMarkForEpisode(*tag, bookmark);
3675 options.starttime = bookmark.timeInSeconds;
3676 options.state = bookmark.playerState;
3683 if (m_eForcedNextPlayer != EPC_NONE)
3684 eNewCore = m_eForcedNextPlayer;
3686 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3689 // this really aught to be inside !bRestart, but since PlayStack
3690 // uses that to init playback, we have to keep it outside
3691 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3692 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3693 { // playing from a playlist by the looks
3694 // don't switch to fullscreen if we are not playing the first item...
3695 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3697 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3699 // TODO - this will fail if user seeks back to first file in stack
3700 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3701 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3703 options.fullscreen = false;
3704 // reset this so we don't think we are resuming on seek
3705 m_itemCurrentFile->m_lStartOffset = 0;
3708 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3710 // reset m_bStartVideoWindowed as it's a temp setting
3711 g_settings.m_bStartVideoWindowed = false;
3712 // reset any forced player
3713 m_eForcedNextPlayer = EPC_NONE;
3716 //We have to stop parsing a cdg before mplayer is deallocated
3717 // WHY do we have to do this????
3719 m_pKaraokeMgr->Stop();
3722 // tell system we are starting a file
3723 m_bPlaybackStarting = true;
3725 // We should restart the player, unless the previous and next tracks are using
3726 // one of the players that allows gapless playback (paplayer, dvdplayer)
3729 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER)) )
3738 m_eCurrentPlayer = eNewCore;
3739 m_pPlayer = CPlayerCoreFactory::CreatePlayer(eNewCore, *this);
3742 // Workaround for bug/quirk in SDL_Mixer on OSX.
3743 // TODO: Remove after GUI Sounds redux
3744 #if defined(__APPLE__)
3745 g_audioManager.Enable(false);
3751 // don't hold graphicscontext here since player
3752 // may wait on another thread, that requires gfx
3753 CSingleExit ex(g_graphicsContext);
3754 bResult = m_pPlayer->OpenFile(item, options);
3758 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3764 if (m_iPlaySpeed != 1)
3766 int iSpeed = m_iPlaySpeed;
3768 SetPlaySpeed(iSpeed);
3771 if( IsPlayingAudio() )
3773 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3774 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
3777 #ifdef HAS_VIDEO_PLAYBACK
3778 if( IsPlayingVideo() )
3780 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
3781 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
3783 // if player didn't manange to switch to fullscreen by itself do it here
3784 if( options.fullscreen && g_renderManager.IsStarted()
3785 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
3786 SwitchToFullScreen();
3788 if (!item.IsDVDImage() && !item.IsDVDFile())
3790 CVideoInfoTag *details = m_itemCurrentFile->GetVideoInfoTag();
3791 // Save information about the stream if we currently have no data
3792 if (!details->HasStreamDetails() ||
3793 details->m_streamDetails.GetVideoDuration() <= 0)
3795 if (m_pPlayer->GetStreamDetails(details->m_streamDetails) && details->HasStreamDetails())
3799 dbs.SetStreamDetailsForFileId(details->m_streamDetails, details->m_iFileId);
3801 CUtil::DeleteVideoDatabaseDirectoryCache();
3808 #if !defined(__APPLE__)
3809 g_audioManager.Enable(false);
3812 m_bPlaybackStarting = false;
3815 // we must have started, otherwise player might send this later
3817 OnPlayBackStarted();
3823 // we send this if it isn't playlistplayer that is doing this
3824 int next = g_playlistPlayer.GetNextSong();
3825 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
3828 OnPlayBackStopped();
3834 void CApplication::OnPlayBackEnded()
3836 if(m_bPlaybackStarting)
3839 // informs python script currently running playback has ended
3840 // (does nothing if python is not loaded)
3842 g_pythonParser.OnPlayBackEnded();
3846 // Let's tell the outside world as well
3847 if (g_settings.m_HttpApiBroadcastLevel>=1)
3848 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackEnded;1");
3851 CAnnouncementManager::Announce(Player, "xbmc", "OnStop");
3853 if (IsPlayingAudio())
3855 CLastfmScrobbler::GetInstance()->SubmitQueue();
3856 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3859 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
3860 g_windowManager.SendThreadMessage(msg);
3863 void CApplication::OnPlayBackStarted()
3865 if(m_bPlaybackStarting)
3869 // informs python script currently running playback has started
3870 // (does nothing if python is not loaded)
3871 g_pythonParser.OnPlayBackStarted();
3875 // Let's tell the outside world as well
3876 if (g_settings.m_HttpApiBroadcastLevel>=1)
3877 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStarted;1");
3880 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
3881 g_windowManager.SendThreadMessage(msg);
3884 void CApplication::OnQueueNextItem()
3886 // informs python script currently running that we are requesting the next track
3887 // (does nothing if python is not loaded)
3889 g_pythonParser.OnQueueNextItem(); // currently unimplemented
3893 // Let's tell the outside world as well
3894 if (g_settings.m_HttpApiBroadcastLevel>=1)
3895 getApplicationMessenger().HttpApi("broadcastlevel; OnQueueNextItem;1");
3898 if(IsPlayingAudio())
3900 CLastfmScrobbler::GetInstance()->SubmitQueue();
3901 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3904 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
3905 g_windowManager.SendThreadMessage(msg);
3908 void CApplication::OnPlayBackStopped()
3910 if(m_bPlaybackStarting)
3913 // informs python script currently running playback has ended
3914 // (does nothing if python is not loaded)
3916 g_pythonParser.OnPlayBackStopped();
3920 // Let's tell the outside world as well
3921 if (g_settings.m_HttpApiBroadcastLevel>=1)
3922 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStopped;1");
3925 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile);
3927 CLastfmScrobbler::GetInstance()->SubmitQueue();
3928 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3930 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
3931 g_windowManager.SendThreadMessage(msg);
3934 void CApplication::OnPlayBackPaused()
3937 g_pythonParser.OnPlayBackPaused();
3941 // Let's tell the outside world as well
3942 if (g_settings.m_HttpApiBroadcastLevel>=1)
3943 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackPaused;1");
3947 param["player"]["speed"] = 0;
3948 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3949 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
3952 void CApplication::OnPlayBackResumed()
3955 g_pythonParser.OnPlayBackResumed();
3959 // Let's tell the outside world as well
3960 if (g_settings.m_HttpApiBroadcastLevel>=1)
3961 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackResumed;1");
3965 param["player"]["speed"] = 1;
3966 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3967 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
3970 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
3973 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
3977 // Let's tell the outside world as well
3978 if (g_settings.m_HttpApiBroadcastLevel>=1)
3981 tmp.Format("broadcastlevel; OnPlayBackSpeedChanged:%i;1",iSpeed);
3982 getApplicationMessenger().HttpApi(tmp);
3987 param["player"]["speed"] = iSpeed;
3988 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3989 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
3992 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
3995 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
3999 // Let's tell the outside world as well
4000 if (g_settings.m_HttpApiBroadcastLevel>=1)
4003 tmp.Format("broadcastlevel; OnPlayBackSeek:%i;1",iTime);
4004 getApplicationMessenger().HttpApi(tmp);
4009 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4010 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4011 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4012 param["player"]["speed"] = GetPlaySpeed();
4013 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4014 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4017 void CApplication::OnPlayBackSeekChapter(int iChapter)
4020 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4024 // Let's tell the outside world as well
4025 if (g_settings.m_HttpApiBroadcastLevel>=1)
4028 tmp.Format("broadcastlevel; OnPlayBackSkeekChapter:%i;1",iChapter);
4029 getApplicationMessenger().HttpApi(tmp);
4034 bool CApplication::IsPlaying() const
4038 if (!m_pPlayer->IsPlaying())
4043 bool CApplication::IsPaused() const
4047 if (!m_pPlayer->IsPlaying())
4049 return m_pPlayer->IsPaused();
4052 bool CApplication::IsPlayingAudio() const
4056 if (!m_pPlayer->IsPlaying())
4058 if (m_pPlayer->HasVideo())
4060 if (m_pPlayer->HasAudio())
4065 bool CApplication::IsPlayingVideo() const
4069 if (!m_pPlayer->IsPlaying())
4071 if (m_pPlayer->HasVideo())
4077 bool CApplication::IsPlayingFullScreenVideo() const
4079 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4082 void CApplication::SaveFileState()
4084 if (!g_settings.GetCurrentProfile().canWriteDatabases())
4086 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4087 m_progressTrackingVideoResumeBookmark,
4088 m_progressTrackingPlayCountUpdate);
4089 CJobManager::GetInstance().AddJob(job, NULL);
4092 void CApplication::UpdateFileState()
4094 // Did the file change?
4095 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4099 // Reset tracking item
4100 m_progressTrackingItem->Reset();
4104 if (IsPlayingVideo() || IsPlayingAudio())
4106 if (m_progressTrackingItem->GetPath() == "")
4109 *m_progressTrackingItem = CurrentFileItem();
4110 m_progressTrackingPlayCountUpdate = false;
4113 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4114 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4115 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4116 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4118 m_progressTrackingPlayCountUpdate = true;
4121 if (m_progressTrackingItem->IsVideo())
4123 if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60)
4125 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset();
4126 m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails);
4128 // Update bookmark for save
4129 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::GetPlayerName(m_eCurrentPlayer);
4130 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4131 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4133 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4134 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4136 // Delete the bookmark
4137 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4140 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4142 // Update the bookmark
4143 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4144 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4149 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4156 void CApplication::StopPlaying()
4158 int iWin = g_windowManager.GetActiveWindow();
4163 m_pKaraokeMgr->Stop();
4167 m_pPlayer->CloseFile();
4169 // turn off visualisation window when stopping
4170 if (iWin == WINDOW_VISUALISATION
4171 || iWin == WINDOW_FULLSCREEN_VIDEO)
4172 g_windowManager.PreviousWindow();
4174 g_partyModeManager.Disable();
4178 void CApplication::ResetScreenSaver()
4181 m_shutdownTimer.StartZero();
4183 // screen saver timer is reset only if we're not already in screensaver or
4185 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4186 ResetScreenSaverTimer();
4189 void CApplication::ResetScreenSaverTimer()
4191 #if defined(__APPLE__) && !defined(__arm__)
4192 Cocoa_UpdateSystemActivity();
4194 m_screenSaverTimer.StartZero();
4197 void CApplication::StopScreenSaverTimer()
4199 m_screenSaverTimer.Stop();
4202 bool CApplication::ToggleDPMS(bool manual)
4204 if (manual || (m_dpmsIsManual == manual))
4208 m_dpmsIsActive = false;
4209 m_dpmsIsManual = false;
4210 return m_dpms->DisablePowerSaving();
4214 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4216 m_dpmsIsActive = true;
4217 m_dpmsIsManual = manual;
4225 bool CApplication::WakeUpScreenSaverAndDPMS()
4229 // turn on lcd backlight
4230 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4231 g_lcd->SetBackLight(1);
4234 // First reset DPMS, if active
4239 // TODO: if screensaver lock is specified but screensaver is not active
4240 // (DPMS came first), activate screensaver now.
4242 ResetScreenSaverTimer();
4243 return !m_bScreenSave || WakeUpScreenSaver();
4246 return WakeUpScreenSaver();
4249 bool CApplication::WakeUpScreenSaver()
4251 if (m_iScreenSaveLock == 2)
4254 // if Screen saver is active
4255 if (m_bScreenSave && m_screenSaver)
4257 if (m_iScreenSaveLock == 0)
4258 if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4259 (g_settings.UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) &&
4260 g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4261 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && m_screenSaver->ID() != "visualization")
4263 m_iScreenSaveLock = 2;
4264 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4265 g_windowManager.GetWindow(WINDOW_SCREENSAVER)->OnMessage(msg);
4267 if (m_iScreenSaveLock == -1)
4269 m_iScreenSaveLock = 0;
4273 // disable screensaver
4274 m_bScreenSave = false;
4275 m_iScreenSaveLock = 0;
4276 ResetScreenSaverTimer();
4278 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated");
4280 if (m_screenSaver->ID() == "visualization")
4282 // we can just continue as usual from vis mode
4285 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4287 else if (!m_screenSaver->ID().IsEmpty())
4288 { // we're in screensaver window
4289 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4290 g_windowManager.PreviousWindow(); // show the previous window
4291 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4292 g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4300 void CApplication::CheckScreenSaverAndDPMS()
4302 if (!m_dpmsIsActive)
4303 g_Windowing.ResetOSScreensaver();
4305 bool maybeScreensaver =
4306 !m_dpmsIsActive && !m_bScreenSave
4307 && !g_guiSettings.GetString("screensaver.mode").IsEmpty();
4309 !m_dpmsIsActive && m_dpms->IsSupported()
4310 && g_guiSettings.GetInt("powermanagement.displaysoff") > 0;
4312 // Has the screen saver window become active?
4313 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4315 m_bScreenSave = true;
4316 maybeScreensaver = false;
4319 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4321 // See if we need to reset timer.
4322 // * Are we playing a video and it is not paused?
4323 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4324 // * Are we playing some music in fullscreen vis?
4325 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4326 && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()))
4328 ResetScreenSaverTimer();
4332 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4334 // DPMS has priority (it makes the screensaver not needed)
4336 && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60)
4339 WakeUpScreenSaver();
4341 else if (maybeScreensaver
4342 && elapsed > g_guiSettings.GetInt("screensaver.time") * 60)
4344 ActivateScreenSaver();
4348 // activate the screensaver.
4349 // if forceType is true, we ignore the various conditions that can alter
4350 // the type of screensaver displayed
4351 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4353 m_bScreenSave = true;
4355 // Get Screensaver Mode
4356 m_screenSaver.reset();
4357 if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver))
4358 m_screenSaver.reset(new CScreenSaver(""));
4361 // turn off lcd backlight if requested
4362 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4363 g_lcd->SetBackLight(0);
4366 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4368 // disable screensaver lock from the login screen
4369 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4372 // set to Dim in the case of a dialog on screen or playing video
4373 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")))
4375 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4376 m_screenSaver.reset(new CScreenSaver(""));
4378 // Check if we are Playing Audio and Vis instead Screensaver!
4379 else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())
4380 { // activate the visualisation
4381 m_screenSaver.reset(new CScreenSaver("visualization"));
4382 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4386 // Picture slideshow
4387 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.slideshow")
4389 // reset our codec info - don't want that on screen
4390 g_infoManager.SetShowCodec(false);
4391 CStdString type = m_screenSaver->GetSetting("type");
4392 CStdString path = m_screenSaver->GetSetting("path");
4393 if (type == "2" && path.IsEmpty())
4396 path = "special://profile/Thumbnails/Video/Fanart";
4398 path = "special://profile/Thumbnails/Music/Fanart";
4399 m_applicationMessenger.PictureSlideShow(path, true, type != "2");
4401 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim")
4403 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4405 else if (!m_screenSaver->ID().IsEmpty())
4406 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4409 void CApplication::CheckShutdown()
4411 CGUIDialogMusicScan *pMusicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
4412 CGUIDialogVideoScan *pVideoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
4414 // first check if we should reset the timer
4415 bool resetTimer = false;
4416 if (IsPlaying() || IsPaused()) // is something playing?
4419 if (pMusicScan && pMusicScan->IsScanning()) // music scanning?
4422 if (pVideoScan && pVideoScan->IsScanning()) // video scanning?
4425 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4430 m_shutdownTimer.StartZero();
4434 if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 )
4436 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4437 m_shutdownTimer.Stop();
4440 getApplicationMessenger().Shutdown();
4444 bool CApplication::OnMessage(CGUIMessage& message)
4446 switch ( message.GetMessage() )
4448 case GUI_MSG_NOTIFY_ALL:
4450 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4452 // Update general playlist: Remove DVD playlist items
4453 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4456 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4457 g_windowManager.SendMessage( msg );
4459 // stop the file if it's on dvd (will set the resume point etc)
4460 if (m_itemCurrentFile->IsOnDVD())
4466 case GUI_MSG_PLAYBACK_STARTED:
4468 #ifdef TARGET_DARWIN
4469 DarwinSetScheduling(message.GetMessage());
4471 // Update our infoManager with the new details etc.
4472 if (m_nextPlaylistItem >= 0)
4473 { // we've started a previously queued item
4474 CFileItemPtr item = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist())[m_nextPlaylistItem];
4475 // update the playlist manager
4476 int currentSong = g_playlistPlayer.GetCurrentSong();
4477 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4478 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4479 g_windowManager.SendThreadMessage(msg);
4480 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4481 *m_itemCurrentFile = *item;
4483 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4484 CLastFmManager::GetInstance()->OnSongChange(*m_itemCurrentFile);
4485 g_partyModeManager.OnSongChange(true);
4488 param["player"]["speed"] = 1;
4489 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4490 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4492 DimLCDOnPlayback(true);
4494 if (IsPlayingAudio())
4496 // Start our cdg parser as appropriate
4498 if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4500 m_pKaraokeMgr->Stop();
4501 if (m_itemCurrentFile->IsMusicDb())
4503 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4505 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4506 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4509 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4512 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4515 // Let scrobbler know about the track
4516 const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag();
4519 CLastfmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4520 CLibrefmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4528 case GUI_MSG_QUEUE_NEXT_ITEM:
4530 // Check to see if our playlist player has a new item for us,
4531 // and if so, we check whether our current player wants the file
4532 int iNext = g_playlistPlayer.GetNextSong();
4533 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4534 if (iNext < 0 || iNext >= playlist.size())
4536 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4537 return true; // nothing to do
4539 // ok, grab the next song
4540 CFileItemPtr item = playlist[iNext];
4541 // ok - send the file to the player if it wants it
4542 if (m_pPlayer && m_pPlayer->QueueNextFile(*item))
4543 { // player wants the next file
4544 m_nextPlaylistItem = iNext;
4550 case GUI_MSG_PLAYBACK_STOPPED:
4551 case GUI_MSG_PLAYBACK_ENDED:
4552 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4556 m_pKaraokeMgr->Stop();
4558 #ifdef TARGET_DARWIN
4559 DarwinSetScheduling(message.GetMessage());
4561 // first check if we still have items in the stack to play
4562 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4564 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4565 { // just play the next item in the stack
4566 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4571 // In case playback ended due to user eg. skipping over the end, clear
4572 // our resume bookmark here
4573 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4575 // Delete the bookmark
4576 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4579 // reset the current playing file
4580 m_itemCurrentFile->Reset();
4581 g_infoManager.ResetCurrentItem();
4582 m_currentStack->Clear();
4584 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4586 g_playlistPlayer.PlayNext(1, true);
4591 if (CLastFmManager::GetInstance()->IsRadioEnabled())
4592 CLastFmManager::GetInstance()->StopRadio();
4603 g_audioManager.Enable(true);
4604 DimLCDOnPlayback(false);
4607 if (!IsPlayingVideo() && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4609 g_windowManager.PreviousWindow();
4612 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4614 g_settings.Save(); // save vis settings
4615 WakeUpScreenSaverAndDPMS();
4616 g_windowManager.PreviousWindow();
4619 // DVD ejected while playing in vis ?
4620 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4623 g_settings.Save(); // save vis settings
4624 WakeUpScreenSaverAndDPMS();
4625 g_windowManager.PreviousWindow();
4628 if (IsEnableTestMode()) g_application.getApplicationMessenger().Quit();
4633 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4634 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4639 case GUI_MSG_FULLSCREEN:
4640 { // Switch to fullscreen, if we can
4641 SwitchToFullScreen();
4645 case GUI_MSG_EXECUTE:
4646 if (message.GetNumStringParams())
4647 return ExecuteXBMCAction(message.GetStringParam());
4653 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4655 // see if it is a user set string
4656 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4657 CGUIInfoLabel info(actionStr, "");
4658 actionStr = info.GetLabel(0);
4659 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4661 // user has asked for something to be executed
4662 if (CBuiltins::HasCommand(actionStr))
4663 CBuiltins::Execute(actionStr);
4666 // try translating the action from our ButtonTranslator
4668 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4670 OnAction(CAction(actionID));
4673 CFileItem item(actionStr, false);
4675 if (item.IsPythonScript())
4676 { // a python script
4677 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
4681 if (item.IsAudio() || item.IsVideo())
4682 { // an audio or video file
4691 void CApplication::Process()
4695 // dispatch the messages generated by python or other threads to the current window
4696 g_windowManager.DispatchThreadMessages();
4698 // process messages which have to be send to the gui
4699 // (this can only be done after g_windowManager.Render())
4700 m_applicationMessenger.ProcessWindowMessages();
4703 // process any Python scripts
4704 g_pythonParser.Process();
4707 // process messages, even if a movie is playing
4708 m_applicationMessenger.ProcessMessages();
4709 if (g_application.m_bStop) return; //we're done, everything has been unloaded
4711 // check if we can free unused memory
4713 g_audioManager.FreeUnused();
4716 // check how far we are through playing the current item
4717 // and do anything that needs doing (lastfm submission, playcount updates etc)
4718 CheckPlayingProgress();
4722 m_pPlayer->DoAudioWork();
4724 // do any processing that isn't needed on each run
4725 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4727 m_slowTimer.Reset();
4731 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4734 // We get called every 500ms
4735 void CApplication::ProcessSlow()
4737 g_powerManager.ProcessEvents();
4739 #if defined(__APPLE__) && !defined(__arm__)
4740 // There is an issue on OS X that several system services ask the cursor to become visible
4741 // during their startup routines. Given that we can't control this, we hack it in by
4743 if (g_Windowing.IsFullScreen())
4744 { // SDL thinks it's hidden
4749 // Store our file state for use on close()
4752 if (IsPlayingAudio())
4754 CLastfmScrobbler::GetInstance()->UpdateStatus();
4755 CLibrefmScrobbler::GetInstance()->UpdateStatus();
4758 // Check if we need to activate the screensaver / DPMS.
4759 CheckScreenSaverAndDPMS();
4761 // Check if we need to shutdown (if enabled).
4763 if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
4765 if (g_guiSettings.GetInt("powermanagement.shutdowntime"))
4771 // check if we should restart the player
4772 CheckDelayedPlayerRestart();
4774 // check if we can unload any unreferenced dlls or sections
4775 if (!IsPlayingVideo())
4776 CSectionLoader::UnloadDelayed();
4778 // check for any idle curl connections
4779 g_curlInterface.CheckIdle();
4781 // check for any idle myth sessions
4782 CMythSession::CheckIdle();
4784 #ifdef HAS_FILESYSTEM_HTSP
4785 // check for any idle htsp sessions
4786 HTSP::CHTSPDirectorySession::CheckIdle();
4790 if ( m_pKaraokeMgr )
4791 m_pKaraokeMgr->ProcessSlow();
4794 // LED - LCD SwitchOn On Paused! m_bIsPaused=TRUE -> LED/LCD is ON!
4795 if(IsPaused() != m_bIsPaused)
4798 DimLCDOnPlayback(m_bIsPaused);
4800 m_bIsPaused = IsPaused();
4803 if (!IsPlayingVideo())
4804 g_largeTextureManager.CleanupUnusedImages();
4806 #ifdef HAS_DVD_DRIVE
4807 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
4808 if (!IsPlayingVideo())
4809 m_Autorun->HandleAutorun();
4812 // update upnp server/renderer states
4813 if(CUPnP::IsInstantiated())
4814 CUPnP::GetInstance()->UpdateState();
4816 //Check to see if current playing Title has changed and whether we should broadcast the fact
4817 CheckForTitleChange();
4819 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
4823 #ifdef HAS_FILESYSTEM_NFS
4824 gNfsConnection.CheckIfIdle();
4827 #ifdef HAS_FILESYSTEM_AFP
4828 gAfpConnection.CheckIfIdle();
4831 #ifdef HAS_FILESYSTEM_SFTP
4832 CSFTPSessionManager::ClearOutIdleSessions();
4835 g_mediaManager.ProcessEvents();
4838 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
4839 g_RemoteControl.Initialize();
4843 // attempt to reinitialize the LCD (e.g. after resuming from sleep)
4844 if (!IsPlayingVideo())
4846 if (g_lcd && !g_lcd->IsConnected())
4849 g_lcd->Initialize();
4854 if (!IsPlayingVideo())
4855 CAddonInstaller::Get().UpdateRepos();
4858 // Global Idle Time in Seconds
4859 // idle time will be resetet if on any OnKey()
4860 // int return: system Idle time in seconds! 0 is no idle!
4861 int CApplication::GlobalIdleTime()
4863 if(!m_idleTimer.IsRunning())
4866 m_idleTimer.StartZero();
4868 return (int)m_idleTimer.GetElapsedSeconds();
4871 float CApplication::NavigationIdleTime()
4873 if (!m_navigationTimer.IsRunning())
4875 m_navigationTimer.Stop();
4876 m_navigationTimer.StartZero();
4878 return m_navigationTimer.GetElapsedSeconds();
4881 void CApplication::DelayedPlayerRestart()
4883 m_restartPlayerTimer.StartZero();
4886 void CApplication::CheckDelayedPlayerRestart()
4888 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
4890 m_restartPlayerTimer.Stop();
4891 m_restartPlayerTimer.Reset();
4896 void CApplication::Restart(bool bSamePosition)
4898 // this function gets called when the user changes a setting (like noninterleaved)
4899 // and which means we gotta close & reopen the current playing file
4901 // first check if we're playing a file
4902 if ( !IsPlayingVideo() && !IsPlayingAudio())
4910 // do we want to return to the current position in the file
4911 if (false == bSamePosition)
4913 // no, then just reopen the file and start at the beginning
4914 PlayFile(*m_itemCurrentFile, true);
4918 // else get current position
4919 double time = GetTime();
4921 // get player state, needed for dvd's
4922 CStdString state = m_pPlayer->GetPlayerState();
4924 // set the requested starttime
4925 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
4928 if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer )
4929 m_pPlayer->SetPlayerState(state);
4932 const CStdString& CApplication::CurrentFile()
4934 return m_itemCurrentFile->GetPath();
4937 CFileItem& CApplication::CurrentFileItem()
4939 return *m_itemCurrentFile;
4942 void CApplication::ShowVolumeBar(const CAction *action)
4944 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
4949 volumeBar->OnAction(*action);
4953 bool CApplication::IsMuted() const
4955 return g_settings.m_bMute;
4958 void CApplication::ToggleMute(void)
4960 if (g_settings.m_bMute)
4966 void CApplication::Mute()
4968 g_settings.m_iPreMuteVolumeLevel = GetVolume();
4970 g_settings.m_bMute = true;
4973 void CApplication::UnMute()
4975 SetVolume(g_settings.m_iPreMuteVolumeLevel);
4976 g_settings.m_iPreMuteVolumeLevel = 0;
4977 g_settings.m_bMute = false;
4980 void CApplication::SetVolume(long iValue, bool isPercentage /* = true */)
4982 // convert the percentage to a mB (milliBell) value (*100 for dB)
4984 iValue = (long)((float)iValue * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
4986 SetHardwareVolume(iValue);
4987 #ifndef HAS_SDL_AUDIO
4988 g_audioManager.SetVolume(g_settings.m_nVolumeLevel);
4990 g_audioManager.SetVolume((int)(128.f * (g_settings.m_nVolumeLevel - VOLUME_MINIMUM) / (float)(VOLUME_MAXIMUM - VOLUME_MINIMUM)));
4994 void CApplication::SetHardwareVolume(long hardwareVolume)
4997 if (hardwareVolume >= VOLUME_MAXIMUM) // + VOLUME_DRC_MAXIMUM
4998 hardwareVolume = VOLUME_MAXIMUM;// + VOLUME_DRC_MAXIMUM;
4999 if (hardwareVolume <= VOLUME_MINIMUM)
5000 hardwareVolume = VOLUME_MINIMUM;
5002 // update our settings
5003 if (hardwareVolume > VOLUME_MAXIMUM)
5005 g_settings.m_dynamicRangeCompressionLevel = hardwareVolume - VOLUME_MAXIMUM;
5006 g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
5010 g_settings.m_dynamicRangeCompressionLevel = 0;
5011 g_settings.m_nVolumeLevel = hardwareVolume;
5014 // and tell our player to update the volume
5017 m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5019 // m_pPlayer->SetDynamicRangeCompression(g_settings.m_dynamicRangeCompressionLevel);
5023 int CApplication::GetVolume() const
5025 // converts the hardware volume (in mB) to a percentage
5026 return int(((float)(g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel - VOLUME_MINIMUM)) / (VOLUME_MAXIMUM - VOLUME_MINIMUM)*100.0f + 0.5f);
5029 int CApplication::GetSubtitleDelay() const
5031 // converts subtitle delay to a percentage
5032 return int(((float)(g_settings.m_currentVideoSettings.m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5035 int CApplication::GetAudioDelay() const
5037 // converts subtitle delay to a percentage
5038 return int(((float)(g_settings.m_currentVideoSettings.m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5041 void CApplication::SetPlaySpeed(int iSpeed)
5043 if (!IsPlayingAudio() && !IsPlayingVideo())
5045 if (m_iPlaySpeed == iSpeed)
5047 if (!m_pPlayer->CanSeek())
5049 if (m_pPlayer->IsPaused())
5052 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5053 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5056 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5060 m_iPlaySpeed = iSpeed;
5062 m_pPlayer->ToFFRW(m_iPlaySpeed);
5063 if (m_iPlaySpeed == 1)
5065 m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5069 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5073 int CApplication::GetPlaySpeed() const
5075 return m_iPlaySpeed;
5078 // Returns the total time in seconds of the current media. Fractional
5079 // portions of a second are possible - but not necessarily supported by the
5080 // player class. This returns a double to be consistent with GetTime() and
5082 double CApplication::GetTotalTime() const
5086 if (IsPlaying() && m_pPlayer)
5088 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5089 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5091 rc = m_pPlayer->GetTotalTime();
5097 void CApplication::StopShutdownTimer()
5099 if (m_shutdownTimer.IsRunning())
5100 m_shutdownTimer.Stop();
5103 void CApplication::ResetShutdownTimers()
5105 // reset system shutdown timer
5106 m_shutdownTimer.StartZero();
5108 // delete custom shutdown timer
5109 if (g_alarmClock.HasAlarm("shutdowntimer"))
5110 g_alarmClock.Stop("shutdowntimer", true);
5113 // Returns the current time in seconds of the currently playing media.
5114 // Fractional portions of a second are possible. This returns a double to
5115 // be consistent with GetTotalTime() and SeekTime().
5116 double CApplication::GetTime() const
5120 if (IsPlaying() && m_pPlayer)
5122 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5124 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5125 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5128 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5134 // Sets the current position of the currently playing media to the specified
5135 // time in seconds. Fractional portions of a second are valid. The passed
5136 // time is the time offset from the beginning of the file as opposed to a
5137 // delta from the current position. This method accepts a double to be
5138 // consistent with GetTime() and GetTotalTime().
5139 void CApplication::SeekTime( double dTime )
5141 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5143 if (!m_pPlayer->CanSeek()) return;
5144 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5146 // find the item in the stack we are seeking to, and load the new
5147 // file if necessary, and calculate the correct seek within the new
5148 // file. Otherwise, just fall through to the usual routine if the
5149 // time is higher than our total time.
5150 for (int i = 0; i < m_currentStack->Size(); i++)
5152 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5154 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5155 if (m_currentStackPosition == i)
5156 m_pPlayer->SeekTime((__int64)((dTime - startOfNewFile) * 1000.0));
5158 { // seeking to a new file
5159 m_currentStackPosition = i;
5160 CFileItem item(*(*m_currentStack)[i]);
5161 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5162 // don't just call "PlayFile" here, as we are quite likely called from the
5163 // player thread, so we won't be able to delete ourselves.
5164 m_applicationMessenger.PlayFile(item, true);
5170 // convert to milliseconds and perform seek
5171 m_pPlayer->SeekTime( static_cast<__int64>( dTime * 1000.0 ) );
5175 float CApplication::GetPercentage() const
5177 if (IsPlaying() && m_pPlayer)
5179 if (IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5181 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5182 if (tag.GetDuration() > 0)
5183 return (float)(GetTime() / tag.GetDuration() * 100);
5186 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5187 return (float)(GetTime() / GetTotalTime() * 100);
5189 return m_pPlayer->GetPercentage();
5194 float CApplication::GetCachePercentage() const
5196 if (IsPlaying() && m_pPlayer)
5197 return m_pPlayer->GetCachePercentage();
5202 void CApplication::SeekPercentage(float percent)
5204 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5206 if (!m_pPlayer->CanSeek()) return;
5207 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5208 SeekTime(percent * 0.01 * GetTotalTime());
5210 m_pPlayer->SeekPercentage(percent);
5214 // SwitchToFullScreen() returns true if a switch is made, else returns false
5215 bool CApplication::SwitchToFullScreen()
5217 // if playing from the video info window, close it first!
5218 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5220 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5221 if (pDialog) pDialog->Close(true);
5224 // don't switch if there is a dialog on screen or the slideshow is active
5225 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5228 // See if we're playing a video, and are in GUI mode
5229 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5231 // Reset frame count so that timing is FPS will be correct.
5233 CSingleLock lock(m_frameMutex);
5237 // then switch to fullscreen mode
5238 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5241 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5242 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5243 { // then switch to visualisation
5244 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5250 void CApplication::Minimize()
5252 g_Windowing.Minimize();
5255 PLAYERCOREID CApplication::GetCurrentPlayer()
5257 return m_eCurrentPlayer;
5260 // when a scan is initiated, save current settings
5261 // and enable tag reading and remote thums
5262 void CApplication::SaveMusicScanSettings()
5264 CLog::Log(LOGINFO,"Music scan has started... Enabling tag reading, and remote thumbs");
5265 g_settings.m_bMyMusicIsScanning = true;
5269 void CApplication::RestoreMusicScanSettings()
5271 g_settings.m_bMyMusicIsScanning = false;
5275 void CApplication::UpdateLibraries()
5277 if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
5279 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5280 CGUIDialogVideoScan *scanner = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
5281 if (scanner && !scanner->IsScanning())
5282 scanner->StartScanning("");
5285 if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
5287 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5288 CGUIDialogMusicScan *scanner = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
5289 if (scanner && !scanner->IsScanning())
5290 scanner->StartScanning("");
5294 void CApplication::CheckPlayingProgress()
5296 // check if we haven't rewound past the start of the file
5299 int iSpeed = g_application.GetPlaySpeed();
5309 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5311 g_application.SetPlaySpeed(1);
5312 g_application.SeekTime(0);
5318 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5320 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5322 // initial exit conditions
5323 // no songs in playlist just return
5324 if (playlist.size() == 0)
5328 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5331 // setup correct playlist
5332 g_playlistPlayer.ClearPlaylist(iPlaylist);
5334 // if the playlist contains an internet stream, this file will be used
5335 // to generate a thumbnail for musicplayer.cover
5336 g_application.m_strPlayListFile = strPlayList;
5338 // add the items to the playlist player
5339 g_playlistPlayer.Add(iPlaylist, playlist);
5341 // if we have a playlist
5342 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5345 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5346 g_playlistPlayer.Reset();
5347 g_playlistPlayer.Play(track);
5353 void CApplication::SaveCurrentFileSettings()
5355 if (m_itemCurrentFile->IsVideo())
5357 // save video settings
5358 if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings)
5362 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), g_settings.m_currentVideoSettings);
5368 bool CApplication::AlwaysProcess(const CAction& action)
5370 // check if this button is mapped to a built-in function
5371 if (!action.GetName().IsEmpty())
5373 CStdString builtInFunction;
5374 vector<CStdString> params;
5375 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5376 builtInFunction.ToLower();
5378 // should this button be handled normally or just cancel the screensaver?
5379 if ( builtInFunction.Equals("powerdown")
5380 || builtInFunction.Equals("reboot")
5381 || builtInFunction.Equals("restart")
5382 || builtInFunction.Equals("restartapp")
5383 || builtInFunction.Equals("suspend")
5384 || builtInFunction.Equals("hibernate")
5385 || builtInFunction.Equals("quit")
5386 || builtInFunction.Equals("shutdown"))
5395 CApplicationMessenger& CApplication::getApplicationMessenger()
5397 return m_applicationMessenger;
5400 bool CApplication::IsCurrentThread() const
5402 return CThread::IsCurrentThread(m_threadID);
5405 bool CApplication::IsPresentFrame()
5407 CSingleLock lock(m_frameMutex);
5408 bool ret = m_bPresentFrame;
5413 #if defined(HAS_LINUX_NETWORK)
5414 CNetworkLinux& CApplication::getNetwork()
5418 #elif defined(HAS_WIN32_NETWORK)
5419 CNetworkWin32& CApplication::getNetwork()
5424 CNetwork& CApplication::getNetwork()
5430 #ifdef HAS_PERFORMANCE_SAMPLE
5431 CPerformanceStats &CApplication::GetPerformanceStats()