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 "interfaces/json-rpc/InputOperations.h"
143 #include <dbus/dbus.h>
146 #include "interfaces/http-api/XBMChttp.h"
149 #include "interfaces/json-rpc/JSONRPC.h"
150 #include "network/TCPServer.h"
153 #include "network/AirPlayServer.h"
156 #include "network/AirTunesServer.h"
158 #if defined(HAVE_LIBCRYSTALHD)
159 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
161 #include "interfaces/AnnouncementManager.h"
162 #include "peripherals/Peripherals.h"
164 #include "peripherals/devices/PeripheralCecAdapter.h"
166 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
167 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
170 #include "guilib/GUIWindowManager.h"
171 #include "windows/GUIWindowHome.h"
172 #include "guilib/GUIStandardWindow.h"
173 #include "settings/GUIWindowSettings.h"
174 #include "windows/GUIWindowFileManager.h"
175 #include "settings/GUIWindowSettingsCategory.h"
176 #include "music/windows/GUIWindowMusicPlaylist.h"
177 #include "music/windows/GUIWindowMusicSongs.h"
178 #include "music/windows/GUIWindowMusicNav.h"
179 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
180 #include "video/windows/GUIWindowVideoPlaylist.h"
181 #include "music/dialogs/GUIDialogMusicInfo.h"
182 #include "video/dialogs/GUIDialogVideoInfo.h"
183 #include "video/windows/GUIWindowVideoNav.h"
184 #include "settings/GUIWindowSettingsProfile.h"
186 #include "rendering/gl/GUIWindowTestPatternGL.h"
189 #include "rendering/dx/GUIWindowTestPatternDX.h"
191 #include "settings/GUIWindowSettingsScreenCalibration.h"
192 #include "programs/GUIWindowPrograms.h"
193 #include "pictures/GUIWindowPictures.h"
194 #include "windows/GUIWindowWeather.h"
195 #include "windows/GUIWindowLoginScreen.h"
196 #include "addons/GUIWindowAddonBrowser.h"
197 #include "music/windows/GUIWindowVisualisation.h"
198 #include "windows/GUIWindowDebugInfo.h"
199 #include "windows/GUIWindowPointer.h"
200 #include "windows/GUIWindowSystemInfo.h"
201 #include "windows/GUIWindowScreensaver.h"
202 #include "windows/GUIWindowScreensaverDim.h"
203 #include "pictures/GUIWindowSlideShow.h"
204 #include "windows/GUIWindowStartup.h"
205 #include "video/windows/GUIWindowFullScreen.h"
206 #include "video/dialogs/GUIDialogVideoOSD.h"
207 #include "music/dialogs/GUIDialogMusicOverlay.h"
208 #include "video/dialogs/GUIDialogVideoOverlay.h"
211 #include "music/dialogs/GUIDialogMusicOSD.h"
212 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
213 #include "dialogs/GUIDialogTextViewer.h"
214 #include "network/GUIDialogNetworkSetup.h"
215 #include "dialogs/GUIDialogMediaSource.h"
216 #include "video/dialogs/GUIDialogVideoSettings.h"
217 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
218 #include "video/dialogs/GUIDialogVideoBookmarks.h"
219 #include "settings/GUIDialogProfileSettings.h"
220 #include "settings/GUIDialogLockSettings.h"
221 #include "settings/GUIDialogContentSettings.h"
222 #include "video/dialogs/GUIDialogVideoScan.h"
223 #include "dialogs/GUIDialogBusy.h"
224 #include "dialogs/GUIDialogKeyboard.h"
225 #include "dialogs/GUIDialogYesNo.h"
226 #include "dialogs/GUIDialogOK.h"
227 #include "dialogs/GUIDialogProgress.h"
228 #include "dialogs/GUIDialogSelect.h"
229 #include "dialogs/GUIDialogSeekBar.h"
230 #include "dialogs/GUIDialogKaiToast.h"
231 #include "dialogs/GUIDialogVolumeBar.h"
232 #include "dialogs/GUIDialogMuteBug.h"
233 #include "video/dialogs/GUIDialogFileStacking.h"
234 #include "dialogs/GUIDialogNumeric.h"
235 #include "dialogs/GUIDialogGamepad.h"
236 #include "dialogs/GUIDialogSubMenu.h"
237 #include "dialogs/GUIDialogFavourites.h"
238 #include "dialogs/GUIDialogButtonMenu.h"
239 #include "dialogs/GUIDialogContextMenu.h"
240 #include "music/dialogs/GUIDialogMusicScan.h"
241 #include "dialogs/GUIDialogPlayerControls.h"
242 #include "music/dialogs/GUIDialogSongInfo.h"
243 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
244 #include "dialogs/GUIDialogSmartPlaylistRule.h"
245 #include "pictures/GUIDialogPictureInfo.h"
246 #include "addons/GUIDialogAddonSettings.h"
247 #include "addons/GUIDialogAddonInfo.h"
248 #ifdef HAS_LINUX_NETWORK
249 #include "network/GUIDialogAccessPoints.h"
251 #include "video/dialogs/GUIDialogFullScreenInfo.h"
252 #include "video/dialogs/GUIDialogTeletext.h"
253 #include "dialogs/GUIDialogSlider.h"
254 #include "guilib/GUIControlFactory.h"
255 #include "dialogs/GUIDialogCache.h"
256 #include "dialogs/GUIDialogPlayEject.h"
257 #include "utils/XMLUtils.h"
258 #include "addons/AddonInstaller.h"
260 #ifdef HAS_PERFORMANCE_SAMPLE
261 #include "utils/PerformanceSample.h"
263 #define MEASURE_FUNCTION
267 #include <SDL/SDL_mixer.h>
271 #include "win32util.h"
274 #include "windowing/X11/XRandR.h"
277 #ifdef TARGET_DARWIN_OSX
278 #include "CocoaInterface.h"
279 #include "XBMCHelper.h"
282 #include "DarwinUtils.h"
287 #include <cdio/logging.h>
291 #include "linux/HALManager.h"
294 #include "storage/MediaManager.h"
295 #include "utils/JobManager.h"
296 #include "utils/SaveFileStateJob.h"
297 #include "utils/AlarmClock.h"
304 #include "input/linux/LIRC.h"
306 #ifdef HAS_IRSERVERSUITE
307 #include "input/windows/IRServerSuite.h"
311 using namespace ADDON;
312 using namespace XFILE;
314 using namespace MEDIA_DETECT;
316 using namespace PLAYLIST;
317 using namespace VIDEO;
318 using namespace MUSIC_INFO;
319 #ifdef HAS_EVENT_SERVER
320 using namespace EVENTSERVER;
323 using namespace JSONRPC;
325 using namespace ANNOUNCEMENT;
326 using namespace PERIPHERALS;
328 using namespace XbmcThreads;
330 // uncomment this if you want to use release libs in the debug build.
331 // Atm this saves you 7 mb of memory
332 #define USE_RELEASE_LIBS
334 #define MAX_FFWD_SPEED 5
336 //extern IDirectSoundRenderer* m_pAudioDecoder;
337 CApplication::CApplication(void)
339 #ifdef HAS_WEB_SERVER
340 , m_WebServer(*new CWebServer)
342 , m_itemCurrentFile(new CFileItem)
343 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
344 , m_progressTrackingItem(new CFileItem)
347 m_bScreenSave = false;
349 m_dpmsIsActive = false;
350 m_dpmsIsManual = false;
351 m_iScreenSaveLock = 0;
352 m_bInitializing = true;
353 m_eForcedNextPlayer = EPC_NONE;
354 m_strPlayListFile = "";
355 m_nextPlaylistItem = -1;
356 m_bPlaybackStarting = false;
357 m_skinReloading = false;
363 //true while we in IsPaused mode! Workaround for OnPaused, which must be add. after v2.0
366 /* for now always keep this around */
368 m_pKaraokeMgr = new CKaraokeLyricsManager();
370 m_currentStack = new CFileItemList;
374 m_bPresentFrame = false;
375 m_bPlatformDirectories = true;
377 m_bStandalone = false;
378 m_bEnableLegacyRes = false;
379 m_bSystemScreenSaverEnable = false;
380 m_pInertialScrollingHandler = new CInertialScrollingHandler();
382 m_Autorun = new CAutorun();
386 CApplication::~CApplication(void)
388 #ifdef HAS_WEB_SERVER
391 delete &m_progressTrackingVideoResumeBookmark;
395 delete m_currentStack;
398 delete m_pKaraokeMgr;
402 delete m_pInertialScrollingHandler;
405 bool CApplication::OnEvent(XBMC_Event& newEvent)
407 switch(newEvent.type)
410 if (!g_application.m_bStop)
411 g_application.getApplicationMessenger().Quit();
414 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
417 g_Keyboard.ProcessKeyUp();
419 case XBMC_MOUSEBUTTONDOWN:
420 case XBMC_MOUSEBUTTONUP:
421 case XBMC_MOUSEMOTION:
422 g_Mouse.HandleEvent(newEvent);
423 g_application.ProcessMouse();
425 case XBMC_VIDEORESIZE:
426 if (!g_application.m_bInitializing &&
427 !g_advancedSettings.m_fullScreen)
429 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
430 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
431 g_guiSettings.SetInt("window.width", newEvent.resize.w);
432 g_guiSettings.SetInt("window.height", newEvent.resize.h);
437 #ifdef TARGET_WINDOWS
438 if (g_advancedSettings.m_fullScreen)
440 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
441 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
442 if (newRes != g_graphicsContext.GetVideoResolution())
444 g_guiSettings.SetResolution(newRes);
445 g_graphicsContext.SetVideoResolution(newRes);
451 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
455 g_application.getApplicationMessenger().UserEvent(newEvent.user.code);
457 case XBMC_APPCOMMAND:
458 return g_application.OnAppCommand(newEvent.appcommand.action);
463 // This function does not return!
464 void CApplication::FatalErrorHandler(bool WindowSystemInitialized, bool MapDrives, bool InitNetwork)
466 fprintf(stderr, "Fatal error encountered, aborting\n");
467 fprintf(stderr, "Error log at %sxbmc.log\n", g_settings.m_logFolder.c_str());
471 extern "C" void __stdcall init_emu_environ();
472 extern "C" void __stdcall update_emu_environ();
475 // Utility function used to copy files from the application bundle
476 // over to the user data directory in Application Support/XBMC.
478 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
480 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
481 if (!CFile::Exists(destPath))
483 // need to copy it across
484 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
485 CFile::Cache(srcPath, destPath);
489 void CApplication::Preflight()
492 // call 'dbus_threads_init_default' before any other dbus calls in order to
493 // avoid race conditions with other threads using dbus connections
494 dbus_threads_init_default();
497 // run any platform preflight scripts.
498 #if defined(__APPLE__) && !defined(__arm__)
499 CStdString install_path;
501 CUtil::GetHomePath(install_path);
502 setenv("XBMC_HOME", install_path.c_str(), 0);
503 install_path += "/tools/darwin/runtime/preflight";
504 system(install_path.c_str());
508 bool CApplication::Create()
510 g_settings.Initialize(); //Initialize default AdvancedSettings
512 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
513 g_Windowing.EnableSystemScreenSaver(false);
516 tzset(); // Initialize timezone information variables
519 // Grab a handle to our thread to be used later in identifying the render thread.
520 m_threadID = CThread::GetCurrentThreadId();
523 //floating point precision to 24 bits (faster performance)
524 _controlfp(_PC_24, _MCW_PC);
526 /* install win32 exception translator, win32 exceptions
527 * can now be caught using c++ try catch */
528 win32_exception::install_handler();
532 // only the InitDirectories* for the current platform should return true
533 // putting this before the first log entries saves another ifdef for g_settings.m_logFolder
534 bool inited = InitDirectoriesLinux();
536 inited = InitDirectoriesOSX();
538 inited = InitDirectoriesWin32();
540 // copy required files
541 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
542 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
543 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
544 CopyUserDataIfNeeded("special://masterprofile/", "LCD.xml");
546 if (!CLog::Init(_P(g_settings.m_logFolder).c_str()))
548 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
549 _P(g_settings.m_logFolder).c_str());
553 g_settings.LoadProfiles(PROFILES_FILE);
555 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
556 #if defined(TARGET_DARWIN_OSX)
557 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
558 #elif defined(TARGET_DARWIN_IOS)
559 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
560 #elif defined(__FreeBSD__)
561 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
562 #elif defined(_LINUX)
563 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__);
564 #elif defined(_WIN32)
565 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);
566 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
567 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
568 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
569 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
571 CSpecialProtocol::LogPaths();
573 CStdString executable = CUtil::ResolveExecutablePath();
574 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
575 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network.GetHostName().c_str());
576 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_settings.m_logFolder.c_str());
577 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
579 CStdString strExecutablePath;
580 CUtil::GetHomePath(strExecutablePath);
582 // if we are running from DVD our UserData location will be TDATA
583 if (URIUtils::IsDVD(strExecutablePath))
585 // TODO: Should we copy over any UserData folder from the DVD?
586 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
589 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
590 for (int i=0;i<items.Size();++i)
591 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
593 g_settings.m_logFolder = "special://masterprofile/";
597 g_xrandr.LoadCustomModeLinesToAllOutputs();
600 // Init our DllLoaders emu env
605 CLog::Log(LOGNOTICE, "Setup SDL");
607 /* Clean up on exit, exit on window close and interrupt */
610 uint32_t sdlFlags = 0;
612 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
613 sdlFlags |= SDL_INIT_VIDEO;
617 sdlFlags |= SDL_INIT_AUDIO;
620 #ifdef HAS_SDL_JOYSTICK
621 sdlFlags |= SDL_INIT_JOYSTICK;
624 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
625 //this might bring the monitor out of standby, so we have to disable it explicitly
626 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
627 #if defined(_LINUX) && !defined(__APPLE__)
628 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
634 // for nvidia cards - vsync currently ALWAYS enabled.
635 // the reason is that after screen has been setup changing this env var will make no difference.
636 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
637 setenv("__GL_YIELD", "USLEEP", 0);
641 if (SDL_Init(sdlFlags) != 0)
643 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
646 #if defined(TARGET_DARWIN)
647 // SDL_Init will install a handler for segfaults, restore the default handler.
648 signal(SIGSEGV, SIG_DFL);
652 // for python scripts that check the OS
654 setenv("OS","OS X",true);
655 #elif defined(_LINUX)
656 setenv("OS","Linux",true);
657 #elif defined(_WIN32)
658 SetEnvironmentVariable("OS","win32");
661 // Initialize core peripheral port support. Note: If these parameters
662 // are 0 and NULL, respectively, then the default number and types of
663 // controllers will be initialized.
664 if (!g_Windowing.InitWindowSystem())
666 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
670 g_powerManager.Initialize();
672 CLog::Log(LOGNOTICE, "load settings...");
674 g_guiSettings.Initialize(); // Initialize default Settings - don't move
675 g_powerManager.SetDefaults();
676 if (!g_settings.Load())
677 FatalErrorHandler(true, true, true);
679 CLog::Log(LOGINFO, "creating subdirectories");
680 CLog::Log(LOGINFO, "userdata folder: %s", g_settings.GetProfileUserDataFolder().c_str());
681 CLog::Log(LOGINFO, "recording folder:%s", g_guiSettings.GetString("audiocds.recordingpath",false).c_str());
682 CLog::Log(LOGINFO, "screenshots folder:%s", g_guiSettings.GetString("debug.screenshotpath",false).c_str());
683 CDirectory::Create(g_settings.GetUserDataFolder());
684 CDirectory::Create(g_settings.GetProfileUserDataFolder());
685 g_settings.CreateProfileFolders();
687 update_emu_environ();//apply the GUI settings
689 // initialize our charset converter
690 g_charsetConverter.reset();
692 // Load the langinfo to have user charset <-> utf-8 conversion
693 CStdString strLanguage = g_guiSettings.GetString("locale.language");
694 strLanguage[0] = toupper(strLanguage[0]);
696 CStdString strLangInfoPath;
697 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
699 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
700 g_langInfo.Load(strLangInfoPath);
702 CStdString strLanguagePath;
703 strLanguagePath.Format("special://xbmc/language/%s/strings.xml", strLanguage.c_str());
705 CLog::Log(LOGINFO, "load language file:%s", strLanguagePath.c_str());
706 if (!g_localizeStrings.Load(strLanguagePath))
707 FatalErrorHandler(false, false, true);
709 // start-up Addons Framework
710 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
711 if (!CAddonMgr::Get().Init())
713 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
714 FatalErrorHandler(true, true, true);
717 g_peripherals.Initialise();
719 // Create the Mouse, Keyboard, Remote, and Joystick devices
720 // Initialize after loading settings to get joystick deadzone setting
721 g_Mouse.Initialize();
722 g_Mouse.SetEnabled(g_guiSettings.GetBool("input.enablemouse"));
724 g_Keyboard.Initialize();
725 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
726 g_RemoteControl.Initialize();
728 #ifdef HAS_SDL_JOYSTICK
729 g_Joystick.Initialize();
732 #if defined(__APPLE__) && !defined(__arm__)
733 // Configure and possible manually start the helper.
734 XBMCHelper::GetInstance().Configure();
737 // update the window resolution
738 g_Windowing.SetWindowResolution(g_guiSettings.GetInt("window.width"), g_guiSettings.GetInt("window.height"));
740 if (g_advancedSettings.m_startFullScreen && g_guiSettings.m_LookAndFeelResolution == RES_WINDOW)
741 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
743 if (!g_graphicsContext.IsValidResolution(g_guiSettings.m_LookAndFeelResolution))
745 // Oh uh - doesn't look good for starting in their wanted screenmode
746 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
747 g_guiSettings.m_LookAndFeelResolution = RES_DESKTOP;
751 // force initial window creation to be windowed, if fullscreen, it will switch to it below
752 // fixes the white screen of death if starting fullscreen and switching to windowed.
753 bool bFullScreen = false;
754 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[RES_WINDOW], OnEvent))
756 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
760 bool bFullScreen = g_guiSettings.m_LookAndFeelResolution != RES_WINDOW;
761 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, g_settings.m_ResInfo[g_guiSettings.m_LookAndFeelResolution], OnEvent))
763 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
768 if (!g_Windowing.InitRenderSystem())
770 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
774 // set GUI res and force the clear of the screen
775 g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
777 if (g_advancedSettings.m_splashImage)
779 CStdString strUserSplash = "special://home/media/Splash.png";
780 if (CFile::Exists(strUserSplash))
782 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
783 m_splash = new CSplash(strUserSplash);
787 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
788 m_splash = new CSplash("special://xbmc/media/Splash.png");
793 // The key mappings may already have been loaded by a peripheral
794 CLog::Log(LOGINFO, "load keymapping");
795 if (!CButtonTranslator::GetInstance().Load())
796 FatalErrorHandler(false, false, true);
798 int iResolution = g_graphicsContext.GetVideoResolution();
799 CLog::Log(LOGINFO, "GUI format %ix%i %s",
800 g_settings.m_ResInfo[iResolution].iWidth,
801 g_settings.m_ResInfo[iResolution].iHeight,
802 g_settings.m_ResInfo[iResolution].strMode.c_str());
803 g_windowManager.Initialize();
805 CUtil::InitRandomSeed();
807 g_mediaManager.Initialize();
809 m_lastFrameTime = XbmcThreads::SystemClockMillis();
810 m_lastRenderTime = m_lastFrameTime;
815 bool CApplication::InitDirectoriesLinux()
818 The following is the directory mapping for Platform Specific Mode:
820 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
821 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
822 installations like skins, screensavers, etc.
824 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
825 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
826 mapped to special://home/userdata ($HOME/.xbmc/userdata)
827 special://profile/ => [read-write] current profile's userdata directory.
828 Generally special://masterprofile for the master profile or
829 special://masterprofile/profiles/<profile_name> for other profiles.
831 NOTE: All these root directories are lowercase. Some of the sub-directories
835 #if defined(_LINUX) && !defined(__APPLE__)
838 userName = getenv("USER");
844 userHome = getenv("HOME");
848 CStdString xbmcBinPath, xbmcPath;
849 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
850 xbmcPath = getenv("XBMC_HOME");
852 if (xbmcPath.IsEmpty())
854 xbmcPath = xbmcBinPath;
855 /* Check if xbmc binaries and arch independent data files are being kept in
856 * separate locations. */
857 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
859 /* Attempt to locate arch independent data files. */
860 CUtil::GetHomePath(xbmcPath);
861 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
863 fprintf(stderr, "Unable to find path to XBMC data files!\n");
869 /* Set some environment variables */
870 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
871 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
873 if (m_bPlatformDirectories)
875 // map our special drives
876 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
877 CSpecialProtocol::SetXBMCPath(xbmcPath);
878 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
879 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
881 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
882 CSpecialProtocol::SetTempPath(strTempPath);
884 URIUtils::AddSlashAtEnd(strTempPath);
885 g_settings.m_logFolder = strTempPath;
892 URIUtils::AddSlashAtEnd(xbmcPath);
893 g_settings.m_logFolder = xbmcPath;
895 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
896 CSpecialProtocol::SetXBMCPath(xbmcPath);
897 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
898 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
900 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
901 CSpecialProtocol::SetTempPath(strTempPath);
904 URIUtils::AddSlashAtEnd(strTempPath);
905 g_settings.m_logFolder = strTempPath;
914 bool CApplication::InitDirectoriesOSX()
919 userName = getenv("USER");
925 userHome = getenv("HOME");
930 CUtil::GetHomePath(xbmcPath);
931 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
934 CStdString fontconfigPath;
935 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
936 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
939 // setup path to our internal dylibs so loader can find them
940 CStdString frameworksPath = CUtil::GetFrameworksPath();
941 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
943 // OSX always runs with m_bPlatformDirectories == true
944 if (m_bPlatformDirectories)
946 // map our special drives
947 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
948 CSpecialProtocol::SetXBMCPath(xbmcPath);
950 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
951 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
953 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
954 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
957 // location for temp files
959 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
961 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
962 CDirectory::Create(strTempPath);
963 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
965 CSpecialProtocol::SetTempPath(strTempPath);
967 // xbmc.log file location
969 strTempPath = userHome + "/Library/Preferences";
971 strTempPath = userHome + "/Library/Logs";
973 URIUtils::AddSlashAtEnd(strTempPath);
974 g_settings.m_logFolder = strTempPath;
980 URIUtils::AddSlashAtEnd(xbmcPath);
981 g_settings.m_logFolder = xbmcPath;
983 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
984 CSpecialProtocol::SetXBMCPath(xbmcPath);
985 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
986 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
988 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
989 CSpecialProtocol::SetTempPath(strTempPath);
991 URIUtils::AddSlashAtEnd(strTempPath);
992 g_settings.m_logFolder = strTempPath;
1001 bool CApplication::InitDirectoriesWin32()
1004 CStdString xbmcPath;
1006 CUtil::GetHomePath(xbmcPath);
1007 SetEnvironmentVariable("XBMC_HOME", xbmcPath.c_str());
1008 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1009 CSpecialProtocol::SetXBMCPath(xbmcPath);
1011 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1013 g_settings.m_logFolder = strWin32UserFolder;
1014 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1015 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1016 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1018 SetEnvironmentVariable("XBMC_PROFILE_USERDATA",_P("special://masterprofile/").c_str());
1022 // Expand the DLL search path with our directories
1023 CWIN32Util::ExtendDllPath();
1025 // check for a DVD drive
1027 CWIN32Util::GetDrivesByType(vShare, DVD_DRIVES);
1029 g_mediaManager.SetHasOpticalDrive(true);
1031 // Can be removed once the StorageHandler supports optical media
1032 VECSOURCES::const_iterator it;
1033 for(it=vShare.begin();it!=vShare.end();++it)
1034 if(g_mediaManager.GetDriveStatus(it->strPath) == DRIVE_CLOSED_MEDIA_PRESENT)
1035 g_application.getApplicationMessenger().OpticalMount(it->strPath);
1044 void CApplication::CreateUserDirs()
1046 CDirectory::Create("special://home/");
1047 CDirectory::Create("special://home/addons");
1048 CDirectory::Create("special://home/addons/packages");
1049 CDirectory::Create("special://home/media");
1050 CDirectory::Create("special://home/sounds");
1051 CDirectory::Create("special://home/system");
1052 CDirectory::Create("special://masterprofile/");
1053 CDirectory::Create("special://temp/");
1054 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1057 bool CApplication::Initialize()
1059 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1060 // turn off cdio logging
1061 cdio_loglevel_default = CDIO_LOG_ERROR;
1064 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1065 // must create these here. Ideally this should be using special://home/ and
1066 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1067 if (!m_bPlatformDirectories)
1070 CDirectory::Create("special://xbmc/language");
1071 CDirectory::Create("special://xbmc/addons");
1072 CDirectory::Create("special://xbmc/sounds");
1077 // Init DPMS, before creating the corresponding setting control.
1078 m_dpms = new DPMSSupport();
1079 g_guiSettings.GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1081 g_windowManager.Add(new CGUIWindowHome); // window id = 0
1082 g_windowManager.Add(new CGUIWindowPrograms); // window id = 1
1083 g_windowManager.Add(new CGUIWindowPictures); // window id = 2
1084 g_windowManager.Add(new CGUIWindowFileManager); // window id = 3
1085 g_windowManager.Add(new CGUIWindowSettings); // window id = 4
1086 g_windowManager.Add(new CGUIWindowSystemInfo); // window id = 7
1088 g_windowManager.Add(new CGUIWindowTestPatternGL); // window id = 8
1091 g_windowManager.Add(new CGUIWindowTestPatternDX); // window id = 8
1093 g_windowManager.Add(new CGUIDialogTeletext); // window id =
1094 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11
1095 g_windowManager.Add(new CGUIWindowSettingsCategory); // window id = 12 slideshow:window id 2007
1096 g_windowManager.Add(new CGUIWindowVideoNav); // window id = 36
1097 g_windowManager.Add(new CGUIWindowVideoPlaylist); // window id = 28
1098 g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29
1099 g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34
1100 g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40
1101 g_windowManager.Add(new CGUIWindowScreensaverDim); // window id = 97
1102 g_windowManager.Add(new CGUIWindowDebugInfo); // window id = 98
1103 g_windowManager.Add(new CGUIWindowPointer); // window id = 99
1104 g_windowManager.Add(new CGUIDialogYesNo); // window id = 100
1105 g_windowManager.Add(new CGUIDialogProgress); // window id = 101
1106 g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103
1107 g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104
1108 g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115
1109 g_windowManager.Add(new CGUIDialogSubMenu); // window id = 105
1110 g_windowManager.Add(new CGUIDialogContextMenu); // window id = 106
1111 g_windowManager.Add(new CGUIDialogKaiToast); // window id = 107
1112 g_windowManager.Add(new CGUIDialogNumeric); // window id = 109
1113 g_windowManager.Add(new CGUIDialogGamepad); // window id = 110
1114 g_windowManager.Add(new CGUIDialogButtonMenu); // window id = 111
1115 g_windowManager.Add(new CGUIDialogMusicScan); // window id = 112
1116 g_windowManager.Add(new CGUIDialogMuteBug); // window id = 113
1117 g_windowManager.Add(new CGUIDialogPlayerControls); // window id = 114
1119 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall); // window id 143
1120 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge); // window id 144
1122 g_windowManager.Add(new CGUIDialogSlider); // window id = 145
1123 g_windowManager.Add(new CGUIDialogMusicOSD); // window id = 120
1124 g_windowManager.Add(new CGUIDialogVisualisationPresetList); // window id = 122
1125 g_windowManager.Add(new CGUIDialogVideoSettings); // window id = 123
1126 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings); // window id = 124
1127 g_windowManager.Add(new CGUIDialogVideoBookmarks); // window id = 125
1128 // Don't add the filebrowser dialog - it's created and added when it's needed
1129 g_windowManager.Add(new CGUIDialogNetworkSetup); // window id = 128
1130 g_windowManager.Add(new CGUIDialogMediaSource); // window id = 129
1131 g_windowManager.Add(new CGUIDialogProfileSettings); // window id = 130
1132 g_windowManager.Add(new CGUIDialogVideoScan); // window id = 133
1133 g_windowManager.Add(new CGUIDialogFavourites); // window id = 134
1134 g_windowManager.Add(new CGUIDialogSongInfo); // window id = 135
1135 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor); // window id = 136
1136 g_windowManager.Add(new CGUIDialogSmartPlaylistRule); // window id = 137
1137 g_windowManager.Add(new CGUIDialogBusy); // window id = 138
1138 g_windowManager.Add(new CGUIDialogPictureInfo); // window id = 139
1139 g_windowManager.Add(new CGUIDialogAddonInfo);
1140 g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140
1141 #ifdef HAS_LINUX_NETWORK
1142 g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141
1145 g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131
1147 g_windowManager.Add(new CGUIDialogContentSettings); // window id = 132
1149 g_windowManager.Add(new CGUIDialogPlayEject);
1151 g_windowManager.Add(new CGUIDialogPeripheralManager);
1152 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1154 g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500
1155 g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501
1156 g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502
1157 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor); // window id = 503
1159 g_windowManager.Add(new CGUIDialogSelect); // window id = 2000
1160 g_windowManager.Add(new CGUIDialogMusicInfo); // window id = 2001
1161 g_windowManager.Add(new CGUIDialogOK); // window id = 2002
1162 g_windowManager.Add(new CGUIDialogVideoInfo); // window id = 2003
1163 g_windowManager.Add(new CGUIDialogTextViewer);
1164 g_windowManager.Add(new CGUIWindowFullScreen); // window id = 2005
1165 g_windowManager.Add(new CGUIWindowVisualisation); // window id = 2006
1166 g_windowManager.Add(new CGUIWindowSlideShow); // window id = 2007
1167 g_windowManager.Add(new CGUIDialogFileStacking); // window id = 2008
1169 g_windowManager.Add(new CGUIWindowKaraokeLyrics); // window id = 2009
1172 g_windowManager.Add(new CGUIDialogVideoOSD); // window id = 2901
1173 g_windowManager.Add(new CGUIDialogMusicOverlay); // window id = 2903
1174 g_windowManager.Add(new CGUIDialogVideoOverlay); // window id = 2904
1175 g_windowManager.Add(new CGUIWindowScreensaver); // window id = 2900 Screensaver
1176 g_windowManager.Add(new CGUIWindowWeather); // window id = 2600 WEATHER
1177 g_windowManager.Add(new CGUIWindowStartup); // startup window (id 2999)
1179 /* window id's 3000 - 3100 are reserved for python */
1181 // Make sure we have at least the default skin
1182 if (!LoadSkin(g_guiSettings.GetString("lookandfeel.skin")) && !LoadSkin(DEFAULT_SKIN))
1184 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", DEFAULT_SKIN);
1185 FatalErrorHandler(true, true, true);
1188 if (g_advancedSettings.m_splashImage)
1189 SAFE_DELETE(m_splash);
1191 if (g_guiSettings.GetBool("masterlock.startuplock") &&
1192 g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1193 !g_settings.GetMasterProfile().getLockCode().IsEmpty())
1195 g_passwordManager.CheckStartUpLock();
1198 // check if we should use the login screen
1199 if (g_settings.UsingLoginScreen())
1200 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1204 CJSONRPC::Initialize();
1206 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1209 g_sysinfo.Refresh();
1211 CLog::Log(LOGINFO, "removing tempfiles");
1212 CUtil::RemoveTempFiles();
1215 if (g_settings.m_bMute)
1217 SetVolume(g_settings.m_iPreMuteVolumeLevel);
1222 SetVolume(g_settings.m_nVolumeLevel, false);
1225 // if the user shutoff the xbox during music scan
1226 // restore the settings
1227 if (g_settings.m_bMyMusicIsScanning)
1229 CLog::Log(LOGWARNING,"System rebooted during music scan! ... restoring UseTags and FindRemoteThumbs");
1230 RestoreMusicScanSettings();
1233 if (!g_settings.UsingLoginScreen())
1237 g_pythonParser.m_bLogin = true;
1241 m_slowTimer.StartZero();
1243 #if defined(__APPLE__) && !defined(__arm__)
1244 XBMCHelper::GetInstance().CaptureAllInput();
1246 #if defined(HAVE_LIBCRYSTALHD)
1247 CCrystalHD::GetInstance();
1250 CAddonMgr::Get().StartServices(false);
1252 CLog::Log(LOGNOTICE, "initialize done");
1254 m_bInitializing = false;
1256 // reset our screensaver (starts timers etc.)
1261 bool CApplication::StartWebServer()
1263 #ifdef HAS_WEB_SERVER
1264 if (g_guiSettings.GetBool("services.webserver") && m_network.IsAvailable())
1266 int webPort = atoi(g_guiSettings.GetString("services.webserverport"));
1267 CLog::Log(LOGNOTICE, "Webserver: Starting...");
1269 if (webPort < 1024 && geteuid() != 0)
1271 CLog::Log(LOGERROR, "Cannot start Web Server as port is smaller than 1024 and user is not root");
1276 bool started = false;
1277 if (m_WebServer.Start(webPort, g_guiSettings.GetString("services.webserverusername"), g_guiSettings.GetString("services.webserverpassword")))
1279 std::map<std::string, std::string> txt;
1281 // publish web frontend and API services
1282 #ifdef HAS_WEB_INTERFACE
1283 CZeroconf::GetInstance()->PublishService("servers.webserver", "_http._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1286 CZeroconf::GetInstance()->PublishService("servers.webapi", "_xbmc-web._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1289 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-http", "_xbmc-jsonrpc-h._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), webPort, txt);
1293 if (g_settings.m_HttpApiBroadcastLevel >= 1)
1294 getApplicationMessenger().HttpApi("broadcastlevel; StartUp;1");
1304 void CApplication::StopWebServer()
1306 #ifdef HAS_WEB_SERVER
1307 if (m_WebServer.IsStarted())
1309 CLog::Log(LOGNOTICE, "Webserver: Stopping...");
1311 if(! m_WebServer.IsStarted() )
1313 CLog::Log(LOGNOTICE, "Webserver: Stopped...");
1314 CZeroconf::GetInstance()->RemoveService("servers.webserver");
1315 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-http");
1316 CZeroconf::GetInstance()->RemoveService("servers.webapi");
1318 CLog::Log(LOGWARNING, "Webserver: Failed to stop.");
1323 void CApplication::StartAirplayServer()
1326 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1328 int listenPort = g_advancedSettings.m_airPlayPort;
1329 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1330 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1332 if (CAirPlayServer::StartServer(listenPort, true))
1334 CAirPlayServer::SetCredentials(usePassword, password);
1335 std::map<std::string, std::string> txt;
1336 CNetworkInterface* iface = g_application.getNetwork().GetFirstConnectedInterface();
1339 txt["deviceid"] = iface->GetMacAddress();
1343 txt["deviceid"] = "FF:FF:FF:FF:FF:F2";
1345 txt["features"] = "0x77";
1346 txt["model"] = "AppleTV2,1";
1347 txt["srcvers"] = AIRPLAY_SERVER_VERSION_STR;
1348 CZeroconf::GetInstance()->PublishService("servers.airplay", "_airplay._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), listenPort, txt);
1353 if (g_guiSettings.GetBool("services.airplay") && m_network.IsAvailable())
1355 int listenPort = g_advancedSettings.m_airTunesPort;
1356 CStdString password = g_guiSettings.GetString("services.airplaypassword");
1357 bool usePassword = g_guiSettings.GetBool("services.useairplaypassword");
1359 if (!CAirTunesServer::StartServer(listenPort, true, usePassword, password))
1361 CLog::Log(LOGERROR, "Failed to start AirTunes Server");
1367 void CApplication::StopAirplayServer(bool bWait)
1370 CAirPlayServer::StopServer(bWait);
1371 CZeroconf::GetInstance()->RemoveService("servers.airplay");
1374 CAirTunesServer::StopServer(bWait);
1378 bool CApplication::StartJSONRPCServer()
1381 if (g_guiSettings.GetBool("services.esenabled"))
1383 if (CTCPServer::StartServer(g_advancedSettings.m_jsonTcpPort, g_guiSettings.GetBool("services.esallinterfaces")))
1385 std::map<std::string, std::string> txt;
1386 CZeroconf::GetInstance()->PublishService("servers.jsonrpc-tpc", "_xbmc-jsonrpc._tcp", g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME), g_advancedSettings.m_jsonTcpPort, txt);
1397 void CApplication::StopJSONRPCServer(bool bWait)
1400 CTCPServer::StopServer(bWait);
1401 CZeroconf::GetInstance()->RemoveService("servers.jsonrpc-tcp");
1405 void CApplication::StartUPnP()
1409 StartUPnPRenderer();
1413 void CApplication::StopUPnP(bool bWait)
1416 if (CUPnP::IsInstantiated())
1418 CLog::Log(LOGNOTICE, "stopping upnp");
1419 CUPnP::ReleaseInstance(bWait);
1424 bool CApplication::StartEventServer()
1426 #ifdef HAS_EVENT_SERVER
1427 CEventServer* server = CEventServer::GetInstance();
1430 CLog::Log(LOGERROR, "ES: Out of memory");
1433 if (g_guiSettings.GetBool("services.esenabled"))
1435 CLog::Log(LOGNOTICE, "ES: Starting event server");
1436 server->StartServer();
1443 bool CApplication::StopEventServer(bool bWait, bool promptuser)
1445 #ifdef HAS_EVENT_SERVER
1446 CEventServer* server = CEventServer::GetInstance();
1449 CLog::Log(LOGERROR, "ES: Out of memory");
1454 if (server->GetNumberOfClients() > 0)
1456 bool cancelled = false;
1457 if (!CGUIDialogYesNo::ShowAndGetInput(13140, 13141, 13142, 20022,
1458 -1, -1, cancelled, 10000)
1461 CLog::Log(LOGNOTICE, "ES: Not stopping event server");
1465 CLog::Log(LOGNOTICE, "ES: Stopping event server with confirmation");
1467 CEventServer::GetInstance()->StopServer(true);
1472 CLog::Log(LOGNOTICE, "ES: Stopping event server");
1474 CEventServer::GetInstance()->StopServer(bWait);
1481 void CApplication::RefreshEventServer()
1483 #ifdef HAS_EVENT_SERVER
1484 if (g_guiSettings.GetBool("services.esenabled"))
1486 CEventServer::GetInstance()->RefreshSettings();
1491 void CApplication::StartUPnPRenderer()
1494 if (g_guiSettings.GetBool("services.upnprenderer"))
1496 CLog::Log(LOGNOTICE, "starting upnp renderer");
1497 CUPnP::GetInstance()->StartRenderer();
1502 void CApplication::StopUPnPRenderer()
1505 if (CUPnP::IsInstantiated())
1507 CLog::Log(LOGNOTICE, "stopping upnp renderer");
1508 CUPnP::GetInstance()->StopRenderer();
1513 void CApplication::StartUPnPServer()
1516 if (g_guiSettings.GetBool("services.upnpserver"))
1518 CLog::Log(LOGNOTICE, "starting upnp server");
1519 CUPnP::GetInstance()->StartServer();
1524 void CApplication::StopUPnPServer()
1527 if (CUPnP::IsInstantiated())
1529 CLog::Log(LOGNOTICE, "stopping upnp server");
1530 CUPnP::GetInstance()->StopServer();
1535 void CApplication::StartZeroconf()
1538 //entry in guisetting only present if HAS_ZEROCONF is set
1539 if(g_guiSettings.GetBool("services.zeroconf"))
1541 CLog::Log(LOGNOTICE, "starting zeroconf publishing");
1542 CZeroconf::GetInstance()->Start();
1547 void CApplication::StopZeroconf()
1550 if(CZeroconf::IsInstantiated())
1552 CLog::Log(LOGNOTICE, "stopping zeroconf publishing");
1553 CZeroconf::GetInstance()->Stop();
1558 void CApplication::DimLCDOnPlayback(bool dim)
1564 g_lcd->DisableOnPlayback(IsPlayingVideo(), IsPlayingAudio());
1566 g_lcd->SetBackLight(1);
1571 void CApplication::StartServices()
1573 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1574 // Start Thread for DVD Mediatype detection
1575 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1576 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1579 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1580 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1581 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, g_settings.m_bMyMusicPlaylistShuffle);
1582 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistRepeat ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1583 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, g_settings.m_bMyVideoPlaylistShuffle);
1584 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1587 CLCDFactory factory;
1588 g_lcd = factory.Create();
1591 g_lcd->Initialize();
1596 void CApplication::StopServices()
1598 m_network.NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1600 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1601 CLog::Log(LOGNOTICE, "stop dvd detect media");
1602 m_DetectDVDType.StopThread();
1605 g_peripherals.Clear();
1608 void CApplication::ReloadSkin()
1610 m_skinReloading = false;
1611 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1612 g_windowManager.SendMessage(msg);
1613 // Reload the skin, restoring the previously focused control. We need this as
1614 // the window unload will reset all control states.
1615 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1616 int iCtrlID = pWindow->GetFocusedControlID();
1617 g_application.LoadSkin(g_guiSettings.GetString("lookandfeel.skin"));
1618 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1619 if (pWindow && pWindow->HasSaveLastControl())
1621 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1622 pWindow->OnMessage(msg3);
1626 bool CApplication::LoadSkin(const CStdString& skinID)
1628 if (m_skinReloading)
1632 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1634 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1640 void CApplication::LoadSkin(const SkinPtr& skin)
1644 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", DEFAULT_SKIN);
1645 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1646 LoadSkin(DEFAULT_SKIN);
1650 bool bPreviousPlayingState=false;
1651 bool bPreviousRenderingState=false;
1652 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1654 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1655 if (bPreviousPlayingState)
1656 g_application.m_pPlayer->Pause();
1657 #ifdef HAS_VIDEO_PLAYBACK
1658 if (!g_renderManager.Paused())
1660 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1662 g_windowManager.ActivateWindow(WINDOW_HOME);
1663 bPreviousRenderingState = true;
1668 // close the music and video overlays (they're re-opened automatically later)
1669 CSingleLock lock(g_graphicsContext);
1671 // save the current window details
1672 int currentWindow = g_windowManager.GetActiveWindow();
1673 vector<int> currentModelessWindows;
1674 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1678 CLog::Log(LOGINFO, " load skin from:%s", skin->Path().c_str());
1680 g_SkinInfo->Start();
1682 CLog::Log(LOGINFO, " load fonts for skin...");
1683 g_graphicsContext.SetMediaDir(skin->Path());
1684 g_directoryCache.ClearSubPaths(skin->Path());
1685 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(g_guiSettings.GetString("lookandfeel.font")))
1687 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1688 CStdString strFontSet;
1689 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1691 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1692 g_guiSettings.SetString("lookandfeel.font", strFontSet);
1696 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", g_guiSettings.GetString("locale.language").c_str());
1698 g_colorManager.Load(g_guiSettings.GetString("lookandfeel.skincolors"));
1700 g_fontManager.LoadFonts(g_guiSettings.GetString("lookandfeel.font"));
1702 // load in the skin strings
1703 CStdString langPath, skinEnglishPath;
1704 URIUtils::AddFileToFolder(skin->Path(), "language", langPath);
1705 URIUtils::AddFileToFolder(langPath, g_guiSettings.GetString("locale.language"), langPath);
1706 URIUtils::AddFileToFolder(langPath, "strings.xml", langPath);
1708 URIUtils::AddFileToFolder(skin->Path(), "language", skinEnglishPath);
1709 URIUtils::AddFileToFolder(skinEnglishPath, "English", skinEnglishPath);
1710 URIUtils::AddFileToFolder(skinEnglishPath, "strings.xml", skinEnglishPath);
1712 g_localizeStrings.LoadSkinStrings(langPath, skinEnglishPath);
1714 g_SkinInfo->LoadIncludes();
1717 start = CurrentHostCounter();
1719 CLog::Log(LOGINFO, " load new skin...");
1720 CGUIWindowHome *pHome = (CGUIWindowHome *)g_windowManager.GetWindow(WINDOW_HOME);
1721 if (!pHome || !pHome->Load("Home.xml"))
1723 // failed to load home.xml
1724 // fallback to default skin
1725 if ( strcmpi(skin->ID().c_str(), DEFAULT_SKIN) != 0)
1727 CLog::Log(LOGERROR, "failed to load home.xml for skin:%s, fallback to \"%s\" skin", skin->ID().c_str(), DEFAULT_SKIN);
1728 g_guiSettings.SetString("lookandfeel.skin", DEFAULT_SKIN);
1729 LoadSkin(DEFAULT_SKIN);
1734 // Load the user windows
1738 end = CurrentHostCounter();
1739 freq = CurrentHostFrequency();
1740 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1742 CLog::Log(LOGINFO, " initialize new skin...");
1743 g_windowManager.AddMsgTarget(this);
1744 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1745 g_windowManager.AddMsgTarget(&g_infoManager);
1746 g_windowManager.AddMsgTarget(&g_fontManager);
1747 g_windowManager.SetCallback(*this);
1748 g_windowManager.Initialize();
1749 CTextureCache::Get().Initialize();
1750 g_audioManager.Enable(true);
1751 g_audioManager.Load();
1753 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1754 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1756 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1757 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1758 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1759 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1760 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1763 CLog::Log(LOGINFO, " skin loaded...");
1765 // leave the graphics lock
1769 if (currentWindow != WINDOW_INVALID)
1771 g_windowManager.ActivateWindow(currentWindow);
1772 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1774 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1775 if (dialog) dialog->Show();
1779 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1781 if (bPreviousPlayingState)
1782 g_application.m_pPlayer->Pause();
1783 if (bPreviousRenderingState)
1784 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1788 void CApplication::UnloadSkin(bool forReload /* = false */)
1790 m_skinReloading = forReload;
1792 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1794 g_audioManager.Enable(false);
1796 g_windowManager.DeInitialize();
1797 CTextureCache::Get().Deinitialize();
1799 // remove the skin-dependent window
1800 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1802 g_TextureManager.Cleanup();
1803 g_largeTextureManager.CleanupUnusedImages(true);
1805 g_fontManager.Clear();
1807 g_colorManager.Clear();
1809 g_charsetConverter.reset();
1811 g_infoManager.Clear();
1814 bool CApplication::LoadUserWindows()
1816 // Start from wherever home.xml is
1817 std::vector<CStdString> vecSkinPath;
1818 g_SkinInfo->GetSkinPaths(vecSkinPath);
1819 for (unsigned int i = 0;i < vecSkinPath.size();++i)
1821 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1822 CFileItemList items;
1823 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", false))
1825 for (int i = 0; i < items.Size(); ++i)
1827 if (items[i]->m_bIsFolder)
1829 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1830 if (skinFile.Left(6).CompareNoCase("custom") == 0)
1832 TiXmlDocument xmlDoc;
1833 if (!xmlDoc.LoadFile(items[i]->GetPath()))
1835 CLog::Log(LOGERROR, "unable to load:%s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1839 // Root element should be <window>
1840 TiXmlElement* pRootElement = xmlDoc.RootElement();
1841 CStdString strValue = pRootElement->Value();
1842 if (!strValue.Equals("window"))
1844 CLog::Log(LOGERROR, "file :%s doesnt contain <window>", skinFile.c_str());
1848 // Read the <type> element to get the window type to create
1849 // If no type is specified, create a CGUIWindow as default
1850 CGUIWindow* pWindow = NULL;
1852 if (pRootElement->Attribute("type"))
1853 strType = pRootElement->Attribute("type");
1856 const TiXmlNode *pType = pRootElement->FirstChild("type");
1857 if (pType && pType->FirstChild())
1858 strType = pType->FirstChild()->Value();
1860 int id = WINDOW_INVALID;
1861 if (!pRootElement->Attribute("id", &id))
1863 const TiXmlNode *pType = pRootElement->FirstChild("id");
1864 if (pType && pType->FirstChild())
1865 id = atol(pType->FirstChild()->Value());
1867 CStdString visibleCondition;
1868 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1870 if (strType.Equals("dialog"))
1871 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1872 else if (strType.Equals("submenu"))
1873 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
1874 else if (strType.Equals("buttonmenu"))
1875 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
1877 pWindow = new CGUIStandardWindow(id + WINDOW_HOME, skinFile);
1879 // Check to make sure the pointer isn't still null
1880 if (pWindow == NULL)
1882 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
1885 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
1890 pWindow->SetVisibleCondition(visibleCondition);
1891 g_windowManager.AddCustomWindow(pWindow);
1899 bool CApplication::RenderNoPresent()
1903 // DXMERGE: This may have been important?
1904 // g_graphicsContext.AcquireCurrentContext();
1906 g_graphicsContext.Lock();
1908 // dont show GUI when playing full screen video
1909 if (g_graphicsContext.IsFullScreenVideo())
1911 if (m_bPresentFrame && IsPlaying() && !IsPaused())
1914 g_renderManager.Present();
1917 g_renderManager.RenderUpdate(true);
1919 // close window overlays
1920 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1921 if (overlay) overlay->Close(true);
1922 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1923 if (overlay) overlay->Close(true);
1927 bool hasRendered = g_windowManager.Render();
1929 // if we're recording an audio stream then show blinking REC
1930 if (!g_graphicsContext.IsFullScreenVideo())
1932 if (m_pPlayer && m_pPlayer->IsRecording() )
1934 static int iBlinkRecord = 0;
1936 if (iBlinkRecord > 25)
1938 CGUIFont* pFont = g_fontManager.GetFont("font13");
1939 CGUITextLayout::DrawText(pFont, 60, 50, 0xffff0000, 0, "REC", 0);
1942 if (iBlinkRecord > 50)
1947 g_graphicsContext.Unlock();
1952 float CApplication::GetDimScreenSaverLevel() const
1954 if (!m_bScreenSave || !m_screenSaver ||
1955 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
1956 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
1957 m_screenSaver->ID() != "screensaver.xbmc.builtin.slideshow"))
1960 if (!m_screenSaver->GetSetting("level").IsEmpty())
1961 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
1965 bool CApplication::WaitFrame(unsigned int timeout)
1969 // Wait for all other frames to be presented
1970 CSingleLock lock(m_frameMutex);
1971 //wait until event is set, but modify remaining time
1973 TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
1974 cv.wait(lock,timeout);
1975 done = m_frameCount == 0;
1980 void CApplication::NewFrame()
1982 // We just posted another frame. Keep track and notify.
1984 CSingleLock lock(m_frameMutex);
1988 m_frameCond.notifyAll();
1991 void CApplication::Render()
1993 // do not render if we are stopped
1997 if (!m_AppActive && !m_bStop && (!IsPlayingVideo() || IsPaused()))
2006 int vsync_mode = g_guiSettings.GetInt("videoscreen.vsync");
2008 bool decrement = false;
2009 bool hasRendered = false;
2010 bool limitFrames = false;
2011 unsigned int singleFrameTime = 10; // default limit 100 fps
2015 bool lowfps = m_dpmsIsActive;
2016 // Whether externalplayer is playing and we're unfocused
2017 bool extPlayerActive = m_eCurrentPlayer >= EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
2019 m_bPresentFrame = false;
2020 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused())
2022 CSingleLock lock(m_frameMutex);
2024 TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
2027 m_bPresentFrame = m_frameCount > 0;
2028 decrement = m_bPresentFrame;
2033 // engage the frame limiter as needed
2034 limitFrames = lowfps || extPlayerActive;
2035 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2036 // perhaps allowing it to be set differently than the UI option??
2037 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2038 limitFrames = true; // not using vsync.
2039 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2040 limitFrames = true; // using vsync, but it isn't working.
2044 if (extPlayerActive)
2046 ResetScreenSaver(); // Prevent screensaver dimming the screen
2047 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2050 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2057 CSingleLock lock(g_graphicsContext);
2058 g_infoManager.UpdateFPS();
2060 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2061 g_Windowing.SetVSync(true);
2062 else if (vsync_mode == VSYNC_ALWAYS)
2063 g_Windowing.SetVSync(true);
2064 else if (vsync_mode != VSYNC_DRIVER)
2065 g_Windowing.SetVSync(false);
2067 if(!g_Windowing.BeginRender())
2070 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2071 if (RenderNoPresent())
2074 g_Windowing.EndRender();
2076 g_TextureManager.FreeUnusedTextures();
2078 // reset our info cache - we do this at the end of Render so that it is
2079 // fresh for the next process(), or after a windowclose animation (where process()
2081 g_infoManager.ResetCache();
2085 unsigned int now = XbmcThreads::SystemClockMillis();
2087 m_lastRenderTime = now;
2089 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2090 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2092 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2093 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2097 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2098 if (limitFrames || !flip)
2101 singleFrameTime = 40; //if not flipping, loop at 25 fps
2103 unsigned int frameTime = now - m_lastFrameTime;
2104 if (frameTime < singleFrameTime)
2105 Sleep(singleFrameTime - frameTime);
2107 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2110 g_graphicsContext.Flip(dirtyRegions);
2111 CTimeUtils::UpdateFrameTime(flip);
2113 g_renderManager.UpdateResolution();
2114 g_renderManager.ManageCaptures();
2117 CSingleLock lock(m_frameMutex);
2118 if(m_frameCount > 0 && decrement)
2121 m_frameCond.notifyAll();
2124 void CApplication::SetStandAlone(bool value)
2126 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2129 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2130 // The window manager will return true if the event is processed, false otherwise.
2131 // If not already processed, this routine handles global keypresses. It returns
2132 // true if the key has been processed, false otherwise.
2134 bool CApplication::OnKey(const CKey& key)
2137 // Turn the mouse off, as we've just got a keypress from controller or remote
2138 g_Mouse.SetActive(false);
2140 // get the current active window
2141 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2143 // this will be checked for certain keycodes that need
2144 // special handling if the screensaver is active
2145 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2147 // a key has been pressed.
2149 m_idleTimer.StartZero();
2150 bool processKey = AlwaysProcess(action);
2154 // allow some keys to be processed while the screensaver is active
2155 if (WakeUpScreenSaverAndDPMS() && !processKey)
2157 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2161 // change this if we have a dialog up
2162 if (g_windowManager.HasModalDialog())
2164 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2166 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2167 { // fullscreen info dialog - special case
2168 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2170 if (!key.IsAnalogButton())
2171 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2173 if (OnAction(action))
2176 // fallthrough to the main window
2177 iWin = WINDOW_FULLSCREEN_VIDEO;
2179 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2181 // current active window is full screen video.
2182 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2184 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2185 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2189 // no then use the fullscreen window section of keymap.xml to map key->action
2190 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2195 // current active window isnt the fullscreen window
2196 // just use corresponding section from keymap.xml
2197 // to map key->action
2199 // first determine if we should use keyboard input directly
2200 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2201 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2204 CGUIControl *control = window->GetFocusedControl();
2207 // If this is an edit control set usekeyboard to true. This causes the
2208 // keypress to be processed directly not through the key mappings.
2209 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2212 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2213 // This causes the keypress to be used for list navigation.
2214 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2220 action = CAction(0); // reset our action
2221 if (g_guiSettings.GetBool("input.remoteaskeyboard"))
2223 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2224 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2225 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2226 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2227 action.GetID() == ACTION_MOVE_RIGHT ||
2228 action.GetID() == ACTION_MOVE_UP ||
2229 action.GetID() == ACTION_MOVE_DOWN ||
2230 action.GetID() == ACTION_SELECT_ITEM ||
2231 action.GetID() == ACTION_ENTER ||
2232 action.GetID() == ACTION_PREVIOUS_MENU ||
2233 action.GetID() == ACTION_NAV_BACK))
2235 // the action isn't plain navigation - check for a keyboard-specific keymap
2236 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2237 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2238 action.GetID() == ACTION_BACKSPACE ||
2239 action.GetID() == ACTION_SHIFT ||
2240 action.GetID() == ACTION_SYMBOLS ||
2241 action.GetID() == ACTION_CURSOR_LEFT ||
2242 action.GetID() == ACTION_CURSOR_RIGHT)
2243 action = CAction(0); // don't bother with this action
2246 if (!action.GetID())
2248 // keyboard entry - pass the keys through directly
2249 if (key.GetFromHttpApi())
2250 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2252 { // see if we've got an ascii key
2253 if (key.GetUnicode())
2254 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2256 action = CAction(key.GetVKey() | KEY_VKEY);
2260 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2262 if (OnAction(action))
2264 // failed to handle the keyboard action, drop down through to standard action
2266 if (key.GetFromHttpApi())
2268 if (key.GetButtonCode() != KEY_INVALID)
2269 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2272 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2274 if (!key.IsAnalogButton())
2275 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2277 // Play a sound based on the action
2278 g_audioManager.PlayActionSound(action);
2280 return OnAction(action);
2283 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2284 // This needs to return true if it processed the appcommand or false if it didn't
2285 bool CApplication::OnAppCommand(const CAction &action)
2287 // Reset the screen saver
2290 // If we were currently in the screen saver wake up and don't process the appcommand
2291 if (WakeUpScreenSaverAndDPMS())
2294 // The action ID is the APPCOMMAND code. We need to retrieve the action
2295 // associated with this appcommand from the mapping table.
2296 uint32_t appcmd = action.GetID();
2297 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2298 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2299 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2301 // If we couldn't find an action return false to indicate we have not
2302 // handled this appcommand
2303 if (!appcmdaction.GetID())
2305 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2309 // Process the appcommand
2310 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2311 OnAction(appcmdaction);
2313 // Always return true regardless of whether the action succeeded or not.
2314 // This stops Windows handling the appcommand itself.
2318 bool CApplication::OnAction(const CAction &action)
2321 // Let's tell the outside world about this action, ignoring mouse moves
2322 if (g_settings.m_HttpApiBroadcastLevel>=2 && action.GetID() != ACTION_MOUSE_MOVE)
2325 tmp.Format("%i",action.GetID());
2326 getApplicationMessenger().HttpApi("broadcastlevel; OnAction:"+tmp+";2");
2330 // special case for switching between GUI & fullscreen mode.
2331 if (action.GetID() == ACTION_SHOW_GUI)
2332 { // Switch to fullscreen mode if we can
2333 if (SwitchToFullScreen())
2335 m_navigationTimer.StartZero();
2340 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2342 g_graphicsContext.ToggleFullScreenRoot();
2346 if (action.IsMouse())
2347 g_Mouse.SetActive(true);
2349 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2350 // playing or ACTION_PLAYER_PLAY if we are not playing.
2351 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2354 return OnAction(CAction(ACTION_PAUSE));
2356 return OnAction(CAction(ACTION_PLAYER_PLAY));
2359 //if the action would start or stop inertial scrolling
2360 //by gesture - bypass the normal OnAction handler of current window
2361 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2364 // just pass the action to the current window and let it handle it
2365 if (g_windowManager.OnAction(action))
2367 m_navigationTimer.StartZero();
2372 // handle extra global presses
2374 // screenshot : take a screenshot :)
2375 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2377 CUtil::TakeScreenshot();
2380 // built in functions : execute the built-in
2381 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2383 CBuiltins::Execute(action.GetName());
2384 m_navigationTimer.StartZero();
2389 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2391 CButtonTranslator::GetInstance().Clear();
2392 CButtonTranslator::GetInstance().Load();
2395 // show info : Shows the current video or song information
2396 if (action.GetID() == ACTION_SHOW_INFO)
2398 g_infoManager.ToggleShowInfo();
2402 // codec info : Shows the current song, video or picture codec information
2403 if (action.GetID() == ACTION_SHOW_CODEC)
2405 g_infoManager.ToggleShowCodec();
2409 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2411 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2414 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2415 char rating = tag->GetRating();
2416 bool needsUpdate(false);
2417 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2419 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2422 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2424 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2430 if (db.Open()) // OpenForWrite() ?
2432 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2435 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2436 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2437 g_windowManager.SendMessage(msg);
2443 // stop : stops playing current audio song
2444 if (action.GetID() == ACTION_STOP)
2450 // previous : play previous song from playlist
2451 if (action.GetID() == ACTION_PREV_ITEM)
2453 // first check whether we're within 3 seconds of the start of the track
2454 // if not, we just revert to the start of the track
2455 if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2462 g_playlistPlayer.PlayPrevious();
2467 // next : play next song from playlist
2468 if (action.GetID() == ACTION_NEXT_ITEM)
2470 if (IsPlaying() && m_pPlayer->SkipNext())
2473 g_playlistPlayer.PlayNext();
2480 // pause : pauses current audio song
2481 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2485 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2487 if (!m_pPlayer->IsPaused())
2488 { // unpaused - set the playspeed back to normal
2491 g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2494 if (!m_pPlayer->IsPaused())
2496 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2497 // if we are playing at normal speed, then allow play to pause
2498 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2500 if (m_iPlaySpeed != 1)
2510 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2512 int iPlaySpeed = m_iPlaySpeed;
2513 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2515 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2517 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2522 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2524 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2527 SetPlaySpeed(iPlaySpeed);
2530 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2532 // calculate the speed based on the amount the button is held down
2533 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2534 // returns 0 -> MAX_FFWD_SPEED
2535 int iSpeed = 1 << iPower;
2536 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2538 g_application.SetPlaySpeed(iSpeed);
2540 CLog::Log(LOGDEBUG,"Resetting playspeed");
2544 // allow play to unpause
2547 if (action.GetID() == ACTION_PLAYER_PLAY)
2549 // unpause, and set the playspeed back to normal
2551 g_audioManager.Enable(m_pPlayer->IsPaused() && !g_audioContext.IsPassthroughActive());
2553 g_application.SetPlaySpeed(1);
2558 if (action.GetID() == ACTION_MUTE)
2564 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2566 switch(g_guiSettings.GetInt("audiooutput.mode"))
2568 case AUDIO_ANALOG: g_guiSettings.SetInt("audiooutput.mode", AUDIO_IEC958); break;
2569 case AUDIO_IEC958: g_guiSettings.SetInt("audiooutput.mode", AUDIO_HDMI ); break;
2570 case AUDIO_HDMI : g_guiSettings.SetInt("audiooutput.mode", AUDIO_ANALOG); break;
2573 g_application.Restart();
2574 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2576 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2577 g_windowManager.SendMessage(msg);
2582 // Check for global volume control
2583 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2585 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2587 // increase or decrease the volume
2589 if (g_settings.m_bMute)
2591 volume = (int)((float)g_settings.m_iPreMuteVolumeLevel * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
2595 volume = g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel;
2597 // calculate speed so that a full press will equal 1 second from min to max
2598 float speed = float(VOLUME_MAXIMUM - VOLUME_MINIMUM);
2599 if (action.GetRepeat())
2600 speed *= action.GetRepeat();
2602 speed /= 50; //50 fps
2604 if (action.GetID() == ACTION_VOLUME_UP)
2605 volume += (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2607 volume -= (int)((float)fabs(action.GetAmount()) * action.GetAmount() * speed);
2609 SetVolume(volume, false);
2611 // show visual feedback of volume change...
2612 ShowVolumeBar(&action);
2615 // Check for global seek control
2616 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2618 if (!m_pPlayer->CanSeek()) return false;
2619 CGUIWindow *seekBar = g_windowManager.GetWindow(WINDOW_DIALOG_SEEK_BAR);
2621 seekBar->OnAction(action);
2624 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2626 CGUIControlProfiler::Instance().SetOutputFile(_P("special://home/guiprofiler.xml"));
2627 CGUIControlProfiler::Instance().Start();
2630 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2632 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2633 if (iPlaylist == PLAYLIST_VIDEO)
2634 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2635 else if (iPlaylist == PLAYLIST_MUSIC)
2636 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2642 void CApplication::UpdateLCD()
2645 static unsigned int lTickCount = 0;
2647 if (!g_lcd || !g_guiSettings.GetBool("videoscreen.haslcd"))
2649 unsigned int lTimeOut = 1000;
2650 if ( m_iPlaySpeed != 1)
2652 if ( (XbmcThreads::SystemClockMillis() - lTickCount) >= lTimeOut)
2654 if (g_application.NavigationIdleTime() < 5)
2655 g_lcd->Render(ILCD::LCD_MODE_NAVIGATION);
2656 else if (IsPlayingVideo())
2657 g_lcd->Render(ILCD::LCD_MODE_VIDEO);
2658 else if (IsPlayingAudio())
2659 g_lcd->Render(ILCD::LCD_MODE_MUSIC);
2660 else if (IsInScreenSaver())
2661 g_lcd->Render(ILCD::LCD_MODE_SCREENSAVER);
2663 g_lcd->Render(ILCD::LCD_MODE_GENERAL);
2666 lTickCount = XbmcThreads::SystemClockMillis();
2671 void CApplication::FrameMove(bool processEvents)
2677 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2678 float frameTime = m_frameTime.GetElapsedSeconds();
2679 m_frameTime.StartZero();
2680 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2681 if( frameTime > 0.5 ) frameTime = 0.5;
2683 g_graphicsContext.Lock();
2684 // check if there are notifications to display
2685 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2686 if (toast && toast->DoWork())
2688 if (!toast->IsDialogRunning())
2693 g_graphicsContext.Unlock();
2697 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2698 // Read the input from a remote
2699 g_RemoteControl.Update();
2702 // process input actions
2703 CWinEvents::MessagePump();
2704 ProcessHTTPApiButtons();
2705 ProcessJsonRpcButtons();
2706 ProcessRemote(frameTime);
2707 ProcessGamepad(frameTime);
2708 ProcessEventServer(frameTime);
2709 ProcessPeripherals(frameTime);
2710 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2713 g_windowManager.Process(CTimeUtils::GetFrameTime());
2714 g_windowManager.FrameMove();
2717 bool CApplication::ProcessGamepad(float frameTime)
2719 #ifdef HAS_SDL_JOYSTICK
2722 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2723 if (g_windowManager.HasModalDialog())
2725 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2728 g_Joystick.Update();
2729 if (g_Joystick.GetButton(bid))
2732 m_idleTimer.StartZero();
2735 if (WakeUpScreenSaverAndDPMS())
2737 g_Joystick.Reset(true);
2742 CStdString actionName;
2744 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2746 CAction action(actionID, 1.0f, 0.0f, actionName);
2747 g_audioManager.PlayActionSound(action);
2749 g_Mouse.SetActive(false);
2750 return OnAction(action);
2757 if (g_Joystick.GetAxis(bid))
2759 if (g_Joystick.GetAmount() < 0)
2765 CStdString actionName;
2767 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2770 if (WakeUpScreenSaverAndDPMS())
2775 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2776 g_audioManager.PlayActionSound(action);
2778 g_Mouse.SetActive(false);
2779 return OnAction(action);
2783 g_Joystick.ResetAxis(abs(bid));
2787 if (g_Joystick.GetHat(bid, position))
2790 m_idleTimer.StartZero();
2793 if (WakeUpScreenSaverAndDPMS())
2800 CStdString actionName;
2803 bid = position<<16|bid;
2805 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2807 CAction action(actionID, 1.0f, 0.0f, actionName);
2808 g_audioManager.PlayActionSound(action);
2810 g_Mouse.SetActive(false);
2811 return OnAction(action);
2818 bool CApplication::ProcessRemote(float frameTime)
2820 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2821 if (g_RemoteControl.GetButton())
2823 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2824 g_RemoteControl.Reset();
2831 bool CApplication::ProcessPeripherals(float frameTime)
2834 vector<CPeripheral *> peripherals;
2835 if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC))
2837 for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++)
2839 CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr);
2840 if (cecDevice && cecDevice->GetButton())
2842 CKey key(cecDevice->GetButton(), cecDevice->GetHoldTime());
2843 cecDevice->ResetButton();
2853 bool CApplication::ProcessMouse()
2857 if (!g_Mouse.IsActive() || !m_AppFocused)
2860 // Get the mouse command ID
2861 uint32_t mousecommand = g_Mouse.GetAction();
2862 if (mousecommand == ACTION_NOOP)
2865 // Reset the screensaver and idle timers
2866 m_idleTimer.StartZero();
2868 if (WakeUpScreenSaverAndDPMS())
2871 // Retrieve the corresponding action
2873 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2874 if (g_windowManager.HasModalDialog())
2875 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2877 iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2878 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2880 // If we couldn't find an action return false to indicate we have not
2881 // handled this mouse action
2882 if (!mouseaction.GetID())
2884 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
2888 // Log mouse actions except for move and noop
2889 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
2890 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
2892 // The action might not be a mouse action. For example wheel moves might
2893 // be mapped to volume up/down in mouse.xml. In this case we do not want
2894 // the mouse position saved in the action.
2895 if (!mouseaction.IsMouse())
2896 return OnAction(mouseaction);
2898 // This is a mouse action so we need to record the mouse position
2899 return OnAction(CAction(mouseaction.GetID(),
2900 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
2901 (float)g_Mouse.GetX(),
2902 (float)g_Mouse.GetY(),
2903 (float)g_Mouse.GetDX(),
2904 (float)g_Mouse.GetDY(),
2905 mouseaction.GetName()));
2908 void CApplication::CheckForTitleChange()
2911 if (g_settings.m_HttpApiBroadcastLevel>=1)
2913 if (IsPlayingVideo())
2915 const CVideoInfoTag* tagVal = g_infoManager.GetCurrentMovieTag();
2916 if (m_pXbmcHttp && tagVal && !(tagVal->m_strTitle.IsEmpty()))
2918 CStdString msg=m_pXbmcHttp->GetOpenTag()+"MovieTitle:"+tagVal->m_strTitle+m_pXbmcHttp->GetCloseTag();
2919 if (m_prevMedia!=msg && g_settings.m_HttpApiBroadcastLevel>=1)
2921 getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2926 else if (IsPlayingAudio())
2928 const CMusicInfoTag* tagVal=g_infoManager.GetCurrentSongTag();
2929 if (m_pXbmcHttp && tagVal)
2932 if (!tagVal->GetTitle().IsEmpty())
2933 msg=m_pXbmcHttp->GetOpenTag()+"AudioTitle:"+tagVal->GetTitle()+m_pXbmcHttp->GetCloseTag();
2934 if (!tagVal->GetArtist().IsEmpty())
2935 msg+=m_pXbmcHttp->GetOpenTag()+"AudioArtist:"+tagVal->GetArtist()+m_pXbmcHttp->GetCloseTag();
2936 if (m_prevMedia!=msg)
2938 getApplicationMessenger().HttpApi("broadcastlevel; MediaChanged:"+msg+";1");
2947 bool CApplication::ProcessHTTPApiButtons()
2952 // copy key from webserver, and reset it in case we're called again before
2953 // whatever happens in OnKey()
2954 CKey keyHttp(m_pXbmcHttp->GetKey());
2955 m_pXbmcHttp->ResetKey();
2956 if (keyHttp.GetButtonCode() != KEY_INVALID)
2958 if (keyHttp.GetButtonCode() == KEY_VMOUSE) //virtual mouse
2960 int actionID = ACTION_MOUSE_MOVE;
2961 if (keyHttp.GetLeftTrigger() == 1)
2962 actionID = ACTION_MOUSE_LEFT_CLICK;
2963 else if (keyHttp.GetLeftTrigger() == 2)
2964 actionID = ACTION_MOUSE_RIGHT_CLICK;
2965 else if (keyHttp.GetLeftTrigger() == 3)
2966 actionID = ACTION_MOUSE_MIDDLE_CLICK;
2967 else if (keyHttp.GetRightTrigger() == 1)
2968 actionID = ACTION_MOUSE_DOUBLE_CLICK;
2969 CAction action(actionID, keyHttp.GetLeftThumbX(), keyHttp.GetLeftThumbY());
2981 bool CApplication::ProcessJsonRpcButtons()
2984 CKey tempKey(JSONRPC::CInputOperations::GetKey());
2985 if (tempKey.GetButtonCode() != KEY_INVALID)
2986 return OnKey(tempKey);
2991 bool CApplication::ProcessEventServer(float frameTime)
2993 #ifdef HAS_EVENT_SERVER
2994 CEventServer* es = CEventServer::GetInstance();
2995 if (!es || !es->Running() || es->GetNumberOfClients()==0)
2998 // process any queued up actions
2999 if (es->ExecuteNextAction())
3001 // reset idle timers
3002 m_idleTimer.StartZero();
3004 WakeUpScreenSaverAndDPMS();
3007 // now handle any buttons or axis
3008 std::string joystickName;
3009 bool isAxis = false;
3010 float fAmount = 0.0;
3012 WORD wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3016 if (joystickName.length() > 0)
3020 if (fabs(fAmount) >= 0.08)
3021 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3023 m_lastAxisMap[joystickName].erase(wKeyID);
3026 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
3031 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3032 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3033 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3034 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3035 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3036 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3037 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3038 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3039 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3040 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3041 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3042 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3043 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3044 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3045 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3046 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3047 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3048 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3049 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3050 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3057 if (m_lastAxisMap.size() > 0)
3059 // Process all the stored axis.
3060 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3062 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3063 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3069 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3070 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3076 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount)
3078 #if defined(HAS_EVENT_SERVER)
3079 m_idleTimer.StartZero();
3081 // Make sure to reset screen saver, mouse.
3083 if (WakeUpScreenSaverAndDPMS())
3086 #ifdef HAS_SDL_JOYSTICK
3089 g_Mouse.SetActive(false);
3091 // Figure out what window we're taking the event for.
3092 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3093 if (g_windowManager.HasModalDialog())
3094 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3096 // This code is copied from the OnKey handler, it should be factored out.
3097 if (iWin == WINDOW_FULLSCREEN_VIDEO &&
3098 g_application.m_pPlayer &&
3099 g_application.m_pPlayer->IsInMenu())
3101 // If player is in some sort of menu, (ie DVDMENU) map buttons differently.
3102 iWin = WINDOW_VIDEO_MENU;
3106 CStdString actionName;
3107 bool fullRange = false;
3109 // Translate using regular joystick translator.
3110 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3112 CAction action(actionID, fAmount, 0.0f, actionName);
3113 g_audioManager.PlayActionSound(action);
3114 return OnAction(action);
3118 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3125 bool CApplication::Cleanup()
3129 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3130 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3131 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3132 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3133 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3134 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3135 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3136 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3137 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3138 g_windowManager.Delete(WINDOW_FILES);
3139 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3140 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3141 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3142 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3143 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3144 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3145 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3146 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_SCAN);
3147 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3148 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3149 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3150 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3151 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3152 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3153 g_windowManager.Delete(WINDOW_DIALOG_OK);
3154 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3155 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3156 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3157 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3158 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3159 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3160 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3161 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3162 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3163 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3164 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_SCAN);
3165 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3166 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3167 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3168 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3169 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3170 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3171 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3172 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3173 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3174 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3175 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3177 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3178 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3180 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3182 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3183 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3184 g_windowManager.Delete(WINDOW_VISUALISATION);
3185 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3186 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3187 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3188 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3189 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3190 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3191 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3192 g_windowManager.Delete(WINDOW_SCREENSAVER);
3193 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3194 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3195 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3196 g_windowManager.Delete(WINDOW_SLIDESHOW);
3198 g_windowManager.Delete(WINDOW_HOME);
3199 g_windowManager.Delete(WINDOW_PROGRAMS);
3200 g_windowManager.Delete(WINDOW_PICTURES);
3201 g_windowManager.Delete(WINDOW_WEATHER);
3203 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3204 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3205 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3206 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3207 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3208 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3209 g_windowManager.Remove(WINDOW_SETTINGS_NETWORK);
3210 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3211 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3213 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3214 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3216 CAddonMgr::Get().DeInit();
3218 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3219 CLog::Log(LOGNOTICE, "closing down remote control service");
3220 g_RemoteControl.Disconnect();
3223 CLog::Log(LOGNOTICE, "unload sections");
3225 #ifdef HAS_PERFORMANCE_SAMPLE
3226 CLog::Log(LOGNOTICE, "performance statistics");
3227 m_perfStats.DumpStats();
3230 // Shutdown as much as possible of the
3231 // application, to reduce the leaks dumped
3232 // to the vc output window before calling
3233 // _CrtDumpMemoryLeaks(). Most of the leaks
3234 // shown are no real leaks, as parts of the app
3235 // are still allocated.
3237 g_localizeStrings.Clear();
3238 g_LangCodeExpander.Clear();
3239 g_charsetConverter.clear();
3240 g_directoryCache.Clear();
3241 CButtonTranslator::GetInstance().Clear();
3242 CLastfmScrobbler::RemoveInstance();
3243 CLibrefmScrobbler::RemoveInstance();
3244 CLastFmManager::RemoveInstance();
3245 #ifdef HAS_EVENT_SERVER
3246 CEventServer::RemoveInstance();
3248 DllLoaderContainer::Clear();
3249 g_playlistPlayer.Clear();
3251 g_guiSettings.Clear();
3252 g_advancedSettings.Clear();
3255 CXHandle::DumpObjectTracker();
3258 #ifdef _CRTDBG_MAP_ALLOC
3259 _CrtDumpMemoryLeaks();
3260 while(1); // execution ends
3272 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3277 void CApplication::Stop(int exitCode)
3281 CAnnouncementManager::Announce(System, "xbmc", "OnQuit");
3283 // cancel any jobs from the jobmanager
3284 CJobManager::GetInstance().CancelJobs();
3286 g_alarmClock.StopThread();
3291 if (g_settings.m_HttpApiBroadcastLevel >= 1)
3292 getApplicationMessenger().HttpApi("broadcastlevel; ShutDown;1");
3294 m_pXbmcHttp->shuttingDown = true;
3298 if( m_bSystemScreenSaverEnable )
3299 g_Windowing.EnableSystemScreenSaver(true);
3301 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3302 g_settings.m_iSystemTimeTotalUp = g_settings.m_iSystemTimeTotalUp + (int)(CTimeUtils::GetFrameTime() / 60000);
3304 // Update the settings information (volume, uptime etc. need saving)
3305 if (CFile::Exists(g_settings.GetSettingsFile()))
3307 CLog::Log(LOGNOTICE, "Saving settings");
3311 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3314 m_AppActive = false;
3315 m_AppFocused = false;
3316 m_ExitCode = exitCode;
3317 CLog::Log(LOGNOTICE, "stop all");
3319 // stop scanning before we kill the network and so on
3320 CGUIDialogMusicScan *musicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
3322 musicScan->StopScanning();
3324 CGUIDialogVideoScan *videoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
3326 videoScan->StopScanning();
3328 m_applicationMessenger.Cleanup();
3333 #if defined(__APPLE__) && !defined(__arm__)
3334 XBMCHelper::GetInstance().ReleaseAllInput();
3339 CLog::Log(LOGNOTICE, "stop player");
3344 #if HAS_FILESYTEM_DAAP
3345 CLog::Log(LOGNOTICE, "stop daap clients");
3346 g_DaapClient.Release();
3348 #ifdef HAS_FILESYSTEM_SAP
3349 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3350 g_sapsessions.StopThread();
3353 if(CZeroconfBrowser::IsInstantiated())
3355 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3356 CZeroconfBrowser::GetInstance()->Stop();
3357 CZeroconfBrowser::ReleaseInstance();
3361 CLog::Log(LOGNOTICE, "clean cached files!");
3362 #ifdef HAS_FILESYSTEM_RAR
3363 g_RarManager.ClearCache(true);
3366 #ifdef HAS_FILESYSTEM_SFTP
3367 CSFTPSessionManager::DisconnectAllSessions();
3370 CLog::Log(LOGNOTICE, "unload skin");
3373 #if defined(__APPLE__) && !defined(__arm__)
3374 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3375 XBMCHelper::GetInstance().Stop();
3378 #if defined(HAVE_LIBCRYSTALHD)
3379 CCrystalHD::RemoveInstance();
3382 g_mediaManager.Stop();
3384 // Stop services before unloading Python
3385 CAddonMgr::Get().StopServices(false);
3387 /* Python resource freeing must be done after skin has been unloaded, not before
3388 some windows still need it when deinitializing during skin unloading. */
3390 CLog::Log(LOGNOTICE, "stop python");
3391 g_pythonParser.FreeResources();
3402 g_Windowing.DestroyRenderSystem();
3403 g_Windowing.DestroyWindow();
3404 g_Windowing.DestroyWindowSystem();
3406 CLog::Log(LOGNOTICE, "stopped");
3410 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3413 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3414 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3421 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3423 //If item is a plugin, expand out now and run ourselves again
3424 if (item.IsPlugin())
3426 CFileItem item_new(item);
3427 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3428 return PlayMedia(item_new, iPlaylist);
3431 if (item.IsLastFM())
3433 g_partyModeManager.Disable();
3434 return CLastFmManager::GetInstance()->ChangeStation(item.GetAsUrl());
3436 if (item.IsSmartPlayList())
3438 CFileItemList items;
3439 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3442 CSmartPlaylist smartpl;
3443 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3444 smartpl.OpenAndReadName(item.GetPath());
3446 playlist.Add(items);
3447 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3450 else if (item.IsPlayList() || item.IsInternetStream())
3452 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3454 //is or could be a playlist
3455 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3456 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3461 if (dlgCache->IsCanceled())
3468 if (iPlaylist != PLAYLIST_NONE)
3471 if (item.HasProperty("playlist_starting_track"))
3472 track = item.GetProperty("playlist_starting_track").asInteger();
3473 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3477 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());
3478 if(pPlayList->size())
3479 return PlayFile(*(*pPlayList)[0], false);
3484 //nothing special just play
3485 return PlayFile(item, false);
3489 // For playing a multi-file video. Particularly inefficient
3490 // on startup, as we are required to calculate the length
3491 // of each video, so we open + close each one in turn.
3492 // A faster calculation of video time would improve this
3494 bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3496 if (!item.IsStack())
3499 // see if we have the info in the database
3500 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3501 // then these times will be wrong.
3502 // Also, this is really just a hack for the slow load up times we have
3503 // A much better solution is a fast reader of FPS and fileLength
3504 // that we can use on a file to get it's time.
3506 bool haveTimes(false);
3510 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3511 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3516 // calculate the total time of the stack
3517 CStackDirectory dir;
3518 dir.GetDirectory(item.GetPath(), *m_currentStack);
3520 for (int i = 0; i < m_currentStack->Size(); i++)
3523 (*m_currentStack)[i]->m_lEndOffset = times[i];
3527 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3529 m_currentStack->Clear();
3532 totalTime += duration / 1000;
3533 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3534 times.push_back(totalTime);
3538 double seconds = item.m_lStartOffset / 75.0;
3540 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3541 { // have our times now, so update the dB
3545 dbs.SetStackTimes(item.GetPath(), times);
3547 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3549 // can only resume seek here, not dvdstate
3551 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3552 seconds = bookmark.timeInSeconds;
3560 *m_itemCurrentFile = item;
3561 m_currentStackPosition = 0;
3562 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3566 // work out where to seek to
3567 for (int i = 0; i < m_currentStack->Size(); i++)
3569 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3571 CFileItem item(*(*m_currentStack)[i]);
3572 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3573 item.m_lStartOffset = (long)(seconds - start) * 75;
3574 m_currentStackPosition = i;
3575 return PlayFile(item, true);
3580 return PlayFile(*(*m_currentStack)[0], true);
3583 bool CApplication::PlayFile(const CFileItem& item, bool bRestart)
3587 SaveCurrentFileSettings();
3589 OutputDebugString("new file set audiostream:0\n");
3590 // Switch to default options
3591 g_settings.m_currentVideoSettings = g_settings.m_defaultVideoSettings;
3592 // see if we have saved options in the database
3595 *m_itemCurrentFile = item;
3596 m_nextPlaylistItem = -1;
3597 m_currentStackPosition = 0;
3598 m_currentStack->Clear();
3601 CUtil::ClearSubtitles();
3604 if (item.IsDiscStub())
3606 #ifdef HAS_DVD_DRIVE
3607 // Display the Play Eject dialog
3608 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3609 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3610 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3611 return MEDIA_DETECT::CAutorun::PlayDiscAskResume();
3616 if (item.IsPlayList())
3619 if (item.IsPlugin())
3620 { // we modify the item so that it becomes a real URL
3621 CFileItem item_new(item);
3622 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3623 return PlayFile(item_new, false);
3627 if (URIUtils::IsUPnP(item.GetPath()))
3629 CFileItem item_new(item);
3630 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3631 return PlayFile(item_new, false);
3635 // if we have a stacked set of files, we need to setup our stack routines for
3636 // "seamless" seeking and total time of the movie etc.
3637 // will recall with restart set to true
3639 return PlayStack(item, bRestart);
3641 //Is TuxBox, this should probably be moved to CFileTuxBox
3644 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3646 if(g_tuxboxService.IsRunning())
3647 g_tuxboxService.Stop();
3650 if(g_tuxbox.CreateNewItem(item, item_new))
3653 // Make sure it doesn't have a player
3654 // so we actually select one normally
3655 m_eCurrentPlayer = EPC_NONE;
3657 // keep the tuxbox:// url as playing url
3658 // and give the new url to the player
3659 if(PlayFile(item_new, true))
3661 if(!g_tuxboxService.IsRunning())
3662 g_tuxboxService.Start();
3669 CPlayerOptions options;
3671 if( item.HasProperty("StartPercent") )
3673 options.startpercent = item.GetProperty("StartPercent").asDouble();
3676 PLAYERCOREID eNewCore = EPC_NONE;
3679 // have to be set here due to playstack using this for starting the file
3680 options.starttime = item.m_lStartOffset / 75.0;
3681 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3682 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3684 if( m_eForcedNextPlayer != EPC_NONE )
3685 eNewCore = m_eForcedNextPlayer;
3686 else if( m_eCurrentPlayer == EPC_NONE )
3687 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3689 eNewCore = m_eCurrentPlayer;
3693 options.starttime = item.m_lStartOffset / 75.0;
3697 // open the d/b and retrieve the bookmarks for the current movie
3700 dbs.GetVideoSettings(item.GetPath(), g_settings.m_currentVideoSettings);
3702 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3704 options.starttime = 0.0f;
3706 CStdString path = item.GetPath();
3707 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3708 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3709 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3710 path = item.GetProperty("original_listitem_url").asString();
3711 if(dbs.GetResumeBookMark(path, bookmark))
3713 options.starttime = bookmark.timeInSeconds;
3714 options.state = bookmark.playerState;
3717 else if (item.HasVideoInfoTag())
3719 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3721 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3724 dbs.GetBookMarkForEpisode(*tag, bookmark);
3725 options.starttime = bookmark.timeInSeconds;
3726 options.state = bookmark.playerState;
3733 if (m_eForcedNextPlayer != EPC_NONE)
3734 eNewCore = m_eForcedNextPlayer;
3736 eNewCore = CPlayerCoreFactory::GetDefaultPlayer(item);
3739 // this really aught to be inside !bRestart, but since PlayStack
3740 // uses that to init playback, we have to keep it outside
3741 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3742 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3743 { // playing from a playlist by the looks
3744 // don't switch to fullscreen if we are not playing the first item...
3745 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3747 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3749 // TODO - this will fail if user seeks back to first file in stack
3750 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3751 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3753 options.fullscreen = false;
3754 // reset this so we don't think we are resuming on seek
3755 m_itemCurrentFile->m_lStartOffset = 0;
3758 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !g_settings.m_bStartVideoWindowed;
3760 // reset m_bStartVideoWindowed as it's a temp setting
3761 g_settings.m_bStartVideoWindowed = false;
3762 // reset any forced player
3763 m_eForcedNextPlayer = EPC_NONE;
3766 //We have to stop parsing a cdg before mplayer is deallocated
3767 // WHY do we have to do this????
3769 m_pKaraokeMgr->Stop();
3772 // tell system we are starting a file
3773 m_bPlaybackStarting = true;
3775 // We should restart the player, unless the previous and next tracks are using
3776 // one of the players that allows gapless playback (paplayer, dvdplayer)
3779 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER)) )
3788 m_eCurrentPlayer = eNewCore;
3789 m_pPlayer = CPlayerCoreFactory::CreatePlayer(eNewCore, *this);
3792 // Workaround for bug/quirk in SDL_Mixer on OSX.
3793 // TODO: Remove after GUI Sounds redux
3794 #if defined(__APPLE__)
3795 g_audioManager.Enable(false);
3801 // don't hold graphicscontext here since player
3802 // may wait on another thread, that requires gfx
3803 CSingleExit ex(g_graphicsContext);
3804 bResult = m_pPlayer->OpenFile(item, options);
3808 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3814 if (m_iPlaySpeed != 1)
3816 int iSpeed = m_iPlaySpeed;
3818 SetPlaySpeed(iSpeed);
3821 if( IsPlayingAudio() )
3823 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3824 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
3827 #ifdef HAS_VIDEO_PLAYBACK
3828 if( IsPlayingVideo() )
3830 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
3831 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
3833 // if player didn't manange to switch to fullscreen by itself do it here
3834 if( options.fullscreen && g_renderManager.IsStarted()
3835 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
3836 SwitchToFullScreen();
3838 if (!item.IsDVDImage() && !item.IsDVDFile())
3840 CVideoInfoTag *details = m_itemCurrentFile->GetVideoInfoTag();
3841 // Save information about the stream if we currently have no data
3842 if (!details->HasStreamDetails() ||
3843 details->m_streamDetails.GetVideoDuration() <= 0)
3845 if (m_pPlayer->GetStreamDetails(details->m_streamDetails) && details->HasStreamDetails())
3849 dbs.SetStreamDetailsForFileId(details->m_streamDetails, details->m_iFileId);
3851 CUtil::DeleteVideoDatabaseDirectoryCache();
3858 #if !defined(__APPLE__)
3859 g_audioManager.Enable(false);
3862 m_bPlaybackStarting = false;
3865 // we must have started, otherwise player might send this later
3867 OnPlayBackStarted();
3873 // we send this if it isn't playlistplayer that is doing this
3874 int next = g_playlistPlayer.GetNextSong();
3875 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
3878 OnPlayBackStopped();
3884 void CApplication::OnPlayBackEnded()
3886 if(m_bPlaybackStarting)
3889 // informs python script currently running playback has ended
3890 // (does nothing if python is not loaded)
3892 g_pythonParser.OnPlayBackEnded();
3896 // Let's tell the outside world as well
3897 if (g_settings.m_HttpApiBroadcastLevel>=1)
3898 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackEnded;1");
3901 CAnnouncementManager::Announce(Player, "xbmc", "OnStop");
3903 if (IsPlayingAudio())
3905 CLastfmScrobbler::GetInstance()->SubmitQueue();
3906 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3909 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
3910 g_windowManager.SendThreadMessage(msg);
3913 void CApplication::OnPlayBackStarted()
3915 if(m_bPlaybackStarting)
3919 // informs python script currently running playback has started
3920 // (does nothing if python is not loaded)
3921 g_pythonParser.OnPlayBackStarted();
3925 // Let's tell the outside world as well
3926 if (g_settings.m_HttpApiBroadcastLevel>=1)
3927 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStarted;1");
3930 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
3931 g_windowManager.SendThreadMessage(msg);
3934 void CApplication::OnQueueNextItem()
3936 // informs python script currently running that we are requesting the next track
3937 // (does nothing if python is not loaded)
3939 g_pythonParser.OnQueueNextItem(); // currently unimplemented
3943 // Let's tell the outside world as well
3944 if (g_settings.m_HttpApiBroadcastLevel>=1)
3945 getApplicationMessenger().HttpApi("broadcastlevel; OnQueueNextItem;1");
3948 if(IsPlayingAudio())
3950 CLastfmScrobbler::GetInstance()->SubmitQueue();
3951 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3954 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
3955 g_windowManager.SendThreadMessage(msg);
3958 void CApplication::OnPlayBackStopped()
3960 if(m_bPlaybackStarting)
3963 // informs python script currently running playback has ended
3964 // (does nothing if python is not loaded)
3966 g_pythonParser.OnPlayBackStopped();
3970 // Let's tell the outside world as well
3971 if (g_settings.m_HttpApiBroadcastLevel>=1)
3972 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackStopped;1");
3975 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile);
3977 CLastfmScrobbler::GetInstance()->SubmitQueue();
3978 CLibrefmScrobbler::GetInstance()->SubmitQueue();
3980 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
3981 g_windowManager.SendThreadMessage(msg);
3984 void CApplication::OnPlayBackPaused()
3987 g_pythonParser.OnPlayBackPaused();
3991 // Let's tell the outside world as well
3992 if (g_settings.m_HttpApiBroadcastLevel>=1)
3993 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackPaused;1");
3997 param["player"]["speed"] = 0;
3998 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
3999 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4002 void CApplication::OnPlayBackResumed()
4005 g_pythonParser.OnPlayBackResumed();
4009 // Let's tell the outside world as well
4010 if (g_settings.m_HttpApiBroadcastLevel>=1)
4011 getApplicationMessenger().HttpApi("broadcastlevel; OnPlayBackResumed;1");
4015 param["player"]["speed"] = 1;
4016 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4017 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4020 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4023 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4027 // Let's tell the outside world as well
4028 if (g_settings.m_HttpApiBroadcastLevel>=1)
4031 tmp.Format("broadcastlevel; OnPlayBackSpeedChanged:%i;1",iSpeed);
4032 getApplicationMessenger().HttpApi(tmp);
4037 param["player"]["speed"] = iSpeed;
4038 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4039 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4042 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4045 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4049 // Let's tell the outside world as well
4050 if (g_settings.m_HttpApiBroadcastLevel>=1)
4053 tmp.Format("broadcastlevel; OnPlayBackSeek:%i;1",iTime);
4054 getApplicationMessenger().HttpApi(tmp);
4059 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4060 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4061 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4062 param["player"]["speed"] = GetPlaySpeed();
4063 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4064 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4067 void CApplication::OnPlayBackSeekChapter(int iChapter)
4070 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4074 // Let's tell the outside world as well
4075 if (g_settings.m_HttpApiBroadcastLevel>=1)
4078 tmp.Format("broadcastlevel; OnPlayBackSkeekChapter:%i;1",iChapter);
4079 getApplicationMessenger().HttpApi(tmp);
4084 bool CApplication::IsPlaying() const
4088 if (!m_pPlayer->IsPlaying())
4093 bool CApplication::IsPaused() const
4097 if (!m_pPlayer->IsPlaying())
4099 return m_pPlayer->IsPaused();
4102 bool CApplication::IsPlayingAudio() const
4106 if (!m_pPlayer->IsPlaying())
4108 if (m_pPlayer->HasVideo())
4110 if (m_pPlayer->HasAudio())
4115 bool CApplication::IsPlayingVideo() const
4119 if (!m_pPlayer->IsPlaying())
4121 if (m_pPlayer->HasVideo())
4127 bool CApplication::IsPlayingFullScreenVideo() const
4129 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4132 void CApplication::SaveFileState()
4134 if (!g_settings.GetCurrentProfile().canWriteDatabases())
4136 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4137 m_progressTrackingVideoResumeBookmark,
4138 m_progressTrackingPlayCountUpdate);
4139 CJobManager::GetInstance().AddJob(job, NULL);
4142 void CApplication::UpdateFileState()
4144 // Did the file change?
4145 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4149 // Reset tracking item
4150 m_progressTrackingItem->Reset();
4154 if (IsPlayingVideo() || IsPlayingAudio())
4156 if (m_progressTrackingItem->GetPath() == "")
4159 *m_progressTrackingItem = CurrentFileItem();
4160 m_progressTrackingPlayCountUpdate = false;
4163 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4164 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4165 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4166 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4168 m_progressTrackingPlayCountUpdate = true;
4171 if (m_progressTrackingItem->IsVideo())
4173 if ((m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) && m_pPlayer->GetTotalTime() > 15*60)
4175 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.Reset();
4176 m_pPlayer->GetStreamDetails(m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails);
4178 // Update bookmark for save
4179 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::GetPlayerName(m_eCurrentPlayer);
4180 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4181 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4183 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4184 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4186 // Delete the bookmark
4187 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4190 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4192 // Update the bookmark
4193 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4194 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4199 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4206 void CApplication::StopPlaying()
4208 int iWin = g_windowManager.GetActiveWindow();
4213 m_pKaraokeMgr->Stop();
4217 m_pPlayer->CloseFile();
4219 // turn off visualisation window when stopping
4220 if (iWin == WINDOW_VISUALISATION
4221 || iWin == WINDOW_FULLSCREEN_VIDEO)
4222 g_windowManager.PreviousWindow();
4224 g_partyModeManager.Disable();
4228 void CApplication::ResetSystemIdleTimer()
4230 // reset system idle timer
4231 m_idleTimer.StartZero();
4234 void CApplication::ResetScreenSaver()
4237 m_shutdownTimer.StartZero();
4239 // screen saver timer is reset only if we're not already in screensaver or
4241 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4242 ResetScreenSaverTimer();
4245 void CApplication::ResetScreenSaverTimer()
4247 #if defined(__APPLE__) && !defined(__arm__)
4248 Cocoa_UpdateSystemActivity();
4250 m_screenSaverTimer.StartZero();
4253 void CApplication::StopScreenSaverTimer()
4255 m_screenSaverTimer.Stop();
4258 bool CApplication::ToggleDPMS(bool manual)
4260 if (manual || (m_dpmsIsManual == manual))
4264 m_dpmsIsActive = false;
4265 m_dpmsIsManual = false;
4266 return m_dpms->DisablePowerSaving();
4270 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4272 m_dpmsIsActive = true;
4273 m_dpmsIsManual = manual;
4281 bool CApplication::WakeUpScreenSaverAndDPMS()
4285 // turn on lcd backlight
4286 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4287 g_lcd->SetBackLight(1);
4290 // First reset DPMS, if active
4295 // TODO: if screensaver lock is specified but screensaver is not active
4296 // (DPMS came first), activate screensaver now.
4298 ResetScreenSaverTimer();
4299 return !m_bScreenSave || WakeUpScreenSaver();
4302 return WakeUpScreenSaver();
4305 bool CApplication::WakeUpScreenSaver()
4307 if (m_iScreenSaveLock == 2)
4310 // if Screen saver is active
4311 if (m_bScreenSave && m_screenSaver)
4313 if (m_iScreenSaveLock == 0)
4314 if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4315 (g_settings.UsingLoginScreen() || g_guiSettings.GetBool("masterlock.startuplock")) &&
4316 g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4317 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && m_screenSaver->ID() != "visualization")
4319 m_iScreenSaveLock = 2;
4320 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4321 g_windowManager.GetWindow(WINDOW_SCREENSAVER)->OnMessage(msg);
4323 if (m_iScreenSaveLock == -1)
4325 m_iScreenSaveLock = 0;
4329 // disable screensaver
4330 m_bScreenSave = false;
4331 m_iScreenSaveLock = 0;
4332 ResetScreenSaverTimer();
4334 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated");
4336 if (m_screenSaver->ID() == "visualization")
4338 // we can just continue as usual from vis mode
4341 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4343 else if (!m_screenSaver->ID().IsEmpty())
4344 { // we're in screensaver window
4345 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4346 g_windowManager.PreviousWindow(); // show the previous window
4347 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4348 g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4356 void CApplication::CheckScreenSaverAndDPMS()
4358 if (!m_dpmsIsActive)
4359 g_Windowing.ResetOSScreensaver();
4361 bool maybeScreensaver =
4362 !m_dpmsIsActive && !m_bScreenSave
4363 && !g_guiSettings.GetString("screensaver.mode").IsEmpty();
4365 !m_dpmsIsActive && m_dpms->IsSupported()
4366 && g_guiSettings.GetInt("powermanagement.displaysoff") > 0;
4368 // Has the screen saver window become active?
4369 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4371 m_bScreenSave = true;
4372 maybeScreensaver = false;
4375 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4377 // See if we need to reset timer.
4378 // * Are we playing a video and it is not paused?
4379 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4380 // * Are we playing some music in fullscreen vis?
4381 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4382 && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty()))
4384 ResetScreenSaverTimer();
4388 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4390 // DPMS has priority (it makes the screensaver not needed)
4392 && elapsed > g_guiSettings.GetInt("powermanagement.displaysoff") * 60)
4395 WakeUpScreenSaver();
4397 else if (maybeScreensaver
4398 && elapsed > g_guiSettings.GetInt("screensaver.time") * 60)
4400 ActivateScreenSaver();
4404 // activate the screensaver.
4405 // if forceType is true, we ignore the various conditions that can alter
4406 // the type of screensaver displayed
4407 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4409 m_bScreenSave = true;
4411 // Get Screensaver Mode
4412 m_screenSaver.reset();
4413 if (!CAddonMgr::Get().GetAddon(g_guiSettings.GetString("screensaver.mode"), m_screenSaver))
4414 m_screenSaver.reset(new CScreenSaver(""));
4417 // turn off lcd backlight if requested
4418 if (g_lcd && g_advancedSettings.m_lcdDimOnScreenSave)
4419 g_lcd->SetBackLight(0);
4422 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4424 // disable screensaver lock from the login screen
4425 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4428 // set to Dim in the case of a dialog on screen or playing video
4429 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")))
4431 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4432 m_screenSaver.reset(new CScreenSaver(""));
4434 // Check if we are Playing Audio and Vis instead Screensaver!
4435 else if (IsPlayingAudio() && g_guiSettings.GetBool("screensaver.usemusicvisinstead") && !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty())
4436 { // activate the visualisation
4437 m_screenSaver.reset(new CScreenSaver("visualization"));
4438 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4442 // Picture slideshow
4443 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.slideshow")
4445 // reset our codec info - don't want that on screen
4446 g_infoManager.SetShowCodec(false);
4447 CStdString type = m_screenSaver->GetSetting("type");
4448 CStdString path = m_screenSaver->GetSetting("path");
4449 if (type == "2" && path.IsEmpty())
4452 path = "special://profile/Thumbnails/Video/Fanart";
4454 path = "special://profile/Thumbnails/Music/Fanart";
4455 m_applicationMessenger.PictureSlideShow(path, true, type != "2");
4457 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim")
4459 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4461 else if (!m_screenSaver->ID().IsEmpty())
4462 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4465 void CApplication::CheckShutdown()
4467 CGUIDialogMusicScan *pMusicScan = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
4468 CGUIDialogVideoScan *pVideoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
4470 // first check if we should reset the timer
4471 bool resetTimer = false;
4472 if (IsPlaying() || IsPaused()) // is something playing?
4475 if (pMusicScan && pMusicScan->IsScanning()) // music scanning?
4478 if (pVideoScan && pVideoScan->IsScanning()) // video scanning?
4481 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4486 m_shutdownTimer.StartZero();
4490 if ( m_shutdownTimer.GetElapsedSeconds() > g_guiSettings.GetInt("powermanagement.shutdowntime") * 60 )
4492 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4493 m_shutdownTimer.Stop();
4496 getApplicationMessenger().Shutdown();
4500 bool CApplication::OnMessage(CGUIMessage& message)
4502 switch ( message.GetMessage() )
4504 case GUI_MSG_NOTIFY_ALL:
4506 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4508 // Update general playlist: Remove DVD playlist items
4509 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4512 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4513 g_windowManager.SendMessage( msg );
4515 // stop the file if it's on dvd (will set the resume point etc)
4516 if (m_itemCurrentFile->IsOnDVD())
4522 case GUI_MSG_PLAYBACK_STARTED:
4524 #ifdef TARGET_DARWIN
4525 DarwinSetScheduling(message.GetMessage());
4527 // Update our infoManager with the new details etc.
4528 if (m_nextPlaylistItem >= 0)
4529 { // we've started a previously queued item
4530 CFileItemPtr item = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist())[m_nextPlaylistItem];
4531 // update the playlist manager
4532 int currentSong = g_playlistPlayer.GetCurrentSong();
4533 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4534 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4535 g_windowManager.SendThreadMessage(msg);
4536 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4537 *m_itemCurrentFile = *item;
4539 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4540 CLastFmManager::GetInstance()->OnSongChange(*m_itemCurrentFile);
4541 g_partyModeManager.OnSongChange(true);
4544 param["player"]["speed"] = 1;
4545 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4546 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4548 DimLCDOnPlayback(true);
4550 if (IsPlayingAudio())
4552 // Start our cdg parser as appropriate
4554 if (m_pKaraokeMgr && g_guiSettings.GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4556 m_pKaraokeMgr->Stop();
4557 if (m_itemCurrentFile->IsMusicDb())
4559 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4561 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4562 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4565 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4568 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4571 // Let scrobbler know about the track
4572 const CMusicInfoTag* tag=g_infoManager.GetCurrentSongTag();
4575 CLastfmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4576 CLibrefmScrobbler::GetInstance()->AddSong(*tag, CLastFmManager::GetInstance()->IsRadioEnabled());
4584 case GUI_MSG_QUEUE_NEXT_ITEM:
4586 // Check to see if our playlist player has a new item for us,
4587 // and if so, we check whether our current player wants the file
4588 int iNext = g_playlistPlayer.GetNextSong();
4589 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4590 if (iNext < 0 || iNext >= playlist.size())
4592 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4593 return true; // nothing to do
4595 // ok, grab the next song
4596 CFileItemPtr item = playlist[iNext];
4597 // ok - send the file to the player if it wants it
4598 if (m_pPlayer && m_pPlayer->QueueNextFile(*item))
4599 { // player wants the next file
4600 m_nextPlaylistItem = iNext;
4606 case GUI_MSG_PLAYBACK_STOPPED:
4607 case GUI_MSG_PLAYBACK_ENDED:
4608 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4612 m_pKaraokeMgr->Stop();
4614 #ifdef TARGET_DARWIN
4615 DarwinSetScheduling(message.GetMessage());
4617 // first check if we still have items in the stack to play
4618 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4620 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4621 { // just play the next item in the stack
4622 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4627 // In case playback ended due to user eg. skipping over the end, clear
4628 // our resume bookmark here
4629 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4631 // Delete the bookmark
4632 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4635 // reset the current playing file
4636 m_itemCurrentFile->Reset();
4637 g_infoManager.ResetCurrentItem();
4638 m_currentStack->Clear();
4640 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4642 g_playlistPlayer.PlayNext(1, true);
4647 if (CLastFmManager::GetInstance()->IsRadioEnabled())
4648 CLastFmManager::GetInstance()->StopRadio();
4659 g_audioManager.Enable(true);
4660 DimLCDOnPlayback(false);
4663 if (!IsPlayingVideo() && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4665 g_windowManager.PreviousWindow();
4668 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4670 g_settings.Save(); // save vis settings
4671 WakeUpScreenSaverAndDPMS();
4672 g_windowManager.PreviousWindow();
4675 // DVD ejected while playing in vis ?
4676 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4679 g_settings.Save(); // save vis settings
4680 WakeUpScreenSaverAndDPMS();
4681 g_windowManager.PreviousWindow();
4684 if (IsEnableTestMode()) g_application.getApplicationMessenger().Quit();
4689 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4690 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4695 case GUI_MSG_FULLSCREEN:
4696 { // Switch to fullscreen, if we can
4697 SwitchToFullScreen();
4701 case GUI_MSG_EXECUTE:
4702 if (message.GetNumStringParams())
4703 return ExecuteXBMCAction(message.GetStringParam());
4709 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4711 // see if it is a user set string
4712 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4713 CGUIInfoLabel info(actionStr, "");
4714 actionStr = info.GetLabel(0);
4715 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4717 // user has asked for something to be executed
4718 if (CBuiltins::HasCommand(actionStr))
4719 CBuiltins::Execute(actionStr);
4722 // try translating the action from our ButtonTranslator
4724 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4726 OnAction(CAction(actionID));
4729 CFileItem item(actionStr, false);
4731 if (item.IsPythonScript())
4732 { // a python script
4733 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
4737 if (item.IsAudio() || item.IsVideo())
4738 { // an audio or video file
4747 void CApplication::Process()
4751 // dispatch the messages generated by python or other threads to the current window
4752 g_windowManager.DispatchThreadMessages();
4754 // process messages which have to be send to the gui
4755 // (this can only be done after g_windowManager.Render())
4756 m_applicationMessenger.ProcessWindowMessages();
4759 // process any Python scripts
4760 g_pythonParser.Process();
4763 // process messages, even if a movie is playing
4764 m_applicationMessenger.ProcessMessages();
4765 if (g_application.m_bStop) return; //we're done, everything has been unloaded
4767 // check if we can free unused memory
4769 g_audioManager.FreeUnused();
4772 // check how far we are through playing the current item
4773 // and do anything that needs doing (lastfm submission, playcount updates etc)
4774 CheckPlayingProgress();
4778 m_pPlayer->DoAudioWork();
4780 // do any processing that isn't needed on each run
4781 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4783 m_slowTimer.Reset();
4787 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4790 // We get called every 500ms
4791 void CApplication::ProcessSlow()
4793 g_powerManager.ProcessEvents();
4795 #if defined(__APPLE__) && !defined(__arm__)
4796 // There is an issue on OS X that several system services ask the cursor to become visible
4797 // during their startup routines. Given that we can't control this, we hack it in by
4799 if (g_Windowing.IsFullScreen())
4800 { // SDL thinks it's hidden
4805 // Store our file state for use on close()
4808 if (IsPlayingAudio())
4810 CLastfmScrobbler::GetInstance()->UpdateStatus();
4811 CLibrefmScrobbler::GetInstance()->UpdateStatus();
4814 // Check if we need to activate the screensaver / DPMS.
4815 CheckScreenSaverAndDPMS();
4817 // Check if we need to shutdown (if enabled).
4819 if (g_guiSettings.GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
4821 if (g_guiSettings.GetInt("powermanagement.shutdowntime"))
4827 // check if we should restart the player
4828 CheckDelayedPlayerRestart();
4830 // check if we can unload any unreferenced dlls or sections
4831 if (!IsPlayingVideo())
4832 CSectionLoader::UnloadDelayed();
4834 // check for any idle curl connections
4835 g_curlInterface.CheckIdle();
4837 // check for any idle myth sessions
4838 CMythSession::CheckIdle();
4840 #ifdef HAS_FILESYSTEM_HTSP
4841 // check for any idle htsp sessions
4842 HTSP::CHTSPDirectorySession::CheckIdle();
4846 if ( m_pKaraokeMgr )
4847 m_pKaraokeMgr->ProcessSlow();
4850 // LED - LCD SwitchOn On Paused! m_bIsPaused=TRUE -> LED/LCD is ON!
4851 if(IsPaused() != m_bIsPaused)
4854 DimLCDOnPlayback(m_bIsPaused);
4856 m_bIsPaused = IsPaused();
4859 if (!IsPlayingVideo())
4860 g_largeTextureManager.CleanupUnusedImages();
4862 #ifdef HAS_DVD_DRIVE
4863 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
4864 if (!IsPlayingVideo())
4865 m_Autorun->HandleAutorun();
4868 // update upnp server/renderer states
4869 if(CUPnP::IsInstantiated())
4870 CUPnP::GetInstance()->UpdateState();
4872 //Check to see if current playing Title has changed and whether we should broadcast the fact
4873 CheckForTitleChange();
4875 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
4879 #ifdef HAS_FILESYSTEM_NFS
4880 gNfsConnection.CheckIfIdle();
4883 #ifdef HAS_FILESYSTEM_AFP
4884 gAfpConnection.CheckIfIdle();
4887 #ifdef HAS_FILESYSTEM_SFTP
4888 CSFTPSessionManager::ClearOutIdleSessions();
4891 g_mediaManager.ProcessEvents();
4894 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
4895 g_RemoteControl.Initialize();
4899 // attempt to reinitialize the LCD (e.g. after resuming from sleep)
4900 if (!IsPlayingVideo())
4902 if (g_lcd && !g_lcd->IsConnected())
4905 g_lcd->Initialize();
4910 if (!IsPlayingVideo())
4911 CAddonInstaller::Get().UpdateRepos();
4914 // Global Idle Time in Seconds
4915 // idle time will be resetet if on any OnKey()
4916 // int return: system Idle time in seconds! 0 is no idle!
4917 int CApplication::GlobalIdleTime()
4919 if(!m_idleTimer.IsRunning())
4922 m_idleTimer.StartZero();
4924 return (int)m_idleTimer.GetElapsedSeconds();
4927 float CApplication::NavigationIdleTime()
4929 if (!m_navigationTimer.IsRunning())
4931 m_navigationTimer.Stop();
4932 m_navigationTimer.StartZero();
4934 return m_navigationTimer.GetElapsedSeconds();
4937 void CApplication::DelayedPlayerRestart()
4939 m_restartPlayerTimer.StartZero();
4942 void CApplication::CheckDelayedPlayerRestart()
4944 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
4946 m_restartPlayerTimer.Stop();
4947 m_restartPlayerTimer.Reset();
4952 void CApplication::Restart(bool bSamePosition)
4954 // this function gets called when the user changes a setting (like noninterleaved)
4955 // and which means we gotta close & reopen the current playing file
4957 // first check if we're playing a file
4958 if ( !IsPlayingVideo() && !IsPlayingAudio())
4966 // do we want to return to the current position in the file
4967 if (false == bSamePosition)
4969 // no, then just reopen the file and start at the beginning
4970 PlayFile(*m_itemCurrentFile, true);
4974 // else get current position
4975 double time = GetTime();
4977 // get player state, needed for dvd's
4978 CStdString state = m_pPlayer->GetPlayerState();
4980 // set the requested starttime
4981 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
4984 if ( PlayFile(*m_itemCurrentFile, true) && m_pPlayer )
4985 m_pPlayer->SetPlayerState(state);
4988 const CStdString& CApplication::CurrentFile()
4990 return m_itemCurrentFile->GetPath();
4993 CFileItem& CApplication::CurrentFileItem()
4995 return *m_itemCurrentFile;
4998 void CApplication::ShowVolumeBar(const CAction *action)
5000 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5005 volumeBar->OnAction(*action);
5009 bool CApplication::IsMuted() const
5011 return g_settings.m_bMute;
5014 void CApplication::ToggleMute(void)
5016 if (g_settings.m_bMute)
5022 void CApplication::Mute()
5024 g_settings.m_iPreMuteVolumeLevel = GetVolume();
5026 g_settings.m_bMute = true;
5029 void CApplication::UnMute()
5031 SetVolume(g_settings.m_iPreMuteVolumeLevel);
5032 g_settings.m_iPreMuteVolumeLevel = 0;
5033 g_settings.m_bMute = false;
5036 void CApplication::SetVolume(long iValue, bool isPercentage /* = true */)
5038 // convert the percentage to a mB (milliBell) value (*100 for dB)
5040 iValue = (long)((float)iValue * 0.01f * (VOLUME_MAXIMUM - VOLUME_MINIMUM) + VOLUME_MINIMUM);
5042 SetHardwareVolume(iValue);
5043 #ifndef HAS_SDL_AUDIO
5044 g_audioManager.SetVolume(g_settings.m_nVolumeLevel);
5046 g_audioManager.SetVolume((int)(128.f * (g_settings.m_nVolumeLevel - VOLUME_MINIMUM) / (float)(VOLUME_MAXIMUM - VOLUME_MINIMUM)));
5050 void CApplication::SetHardwareVolume(long hardwareVolume)
5053 if (hardwareVolume >= VOLUME_MAXIMUM) // + VOLUME_DRC_MAXIMUM
5054 hardwareVolume = VOLUME_MAXIMUM;// + VOLUME_DRC_MAXIMUM;
5055 if (hardwareVolume <= VOLUME_MINIMUM)
5056 hardwareVolume = VOLUME_MINIMUM;
5058 // update our settings
5059 if (hardwareVolume > VOLUME_MAXIMUM)
5061 g_settings.m_dynamicRangeCompressionLevel = hardwareVolume - VOLUME_MAXIMUM;
5062 g_settings.m_nVolumeLevel = VOLUME_MAXIMUM;
5066 g_settings.m_dynamicRangeCompressionLevel = 0;
5067 g_settings.m_nVolumeLevel = hardwareVolume;
5070 // and tell our player to update the volume
5073 m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5075 // m_pPlayer->SetDynamicRangeCompression(g_settings.m_dynamicRangeCompressionLevel);
5079 int CApplication::GetVolume() const
5081 // converts the hardware volume (in mB) to a percentage
5082 return int(((float)(g_settings.m_nVolumeLevel + g_settings.m_dynamicRangeCompressionLevel - VOLUME_MINIMUM)) / (VOLUME_MAXIMUM - VOLUME_MINIMUM)*100.0f + 0.5f);
5085 int CApplication::GetSubtitleDelay() const
5087 // converts subtitle delay to a percentage
5088 return int(((float)(g_settings.m_currentVideoSettings.m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5091 int CApplication::GetAudioDelay() const
5093 // converts subtitle delay to a percentage
5094 return int(((float)(g_settings.m_currentVideoSettings.m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5097 void CApplication::SetPlaySpeed(int iSpeed)
5099 if (!IsPlayingAudio() && !IsPlayingVideo())
5101 if (m_iPlaySpeed == iSpeed)
5103 if (!m_pPlayer->CanSeek())
5105 if (m_pPlayer->IsPaused())
5108 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5109 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5112 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5116 m_iPlaySpeed = iSpeed;
5118 m_pPlayer->ToFFRW(m_iPlaySpeed);
5119 if (m_iPlaySpeed == 1)
5121 m_pPlayer->SetVolume(g_settings.m_nVolumeLevel);
5125 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5129 int CApplication::GetPlaySpeed() const
5131 return m_iPlaySpeed;
5134 // Returns the total time in seconds of the current media. Fractional
5135 // portions of a second are possible - but not necessarily supported by the
5136 // player class. This returns a double to be consistent with GetTime() and
5138 double CApplication::GetTotalTime() const
5142 if (IsPlaying() && m_pPlayer)
5144 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5145 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5147 rc = m_pPlayer->GetTotalTime();
5153 void CApplication::StopShutdownTimer()
5155 if (m_shutdownTimer.IsRunning())
5156 m_shutdownTimer.Stop();
5159 void CApplication::ResetShutdownTimers()
5161 // reset system shutdown timer
5162 m_shutdownTimer.StartZero();
5164 // delete custom shutdown timer
5165 if (g_alarmClock.HasAlarm("shutdowntimer"))
5166 g_alarmClock.Stop("shutdowntimer", true);
5169 // Returns the current time in seconds of the currently playing media.
5170 // Fractional portions of a second are possible. This returns a double to
5171 // be consistent with GetTotalTime() and SeekTime().
5172 double CApplication::GetTime() const
5176 if (IsPlaying() && m_pPlayer)
5178 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5180 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5181 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5184 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5190 // Sets the current position of the currently playing media to the specified
5191 // time in seconds. Fractional portions of a second are valid. The passed
5192 // time is the time offset from the beginning of the file as opposed to a
5193 // delta from the current position. This method accepts a double to be
5194 // consistent with GetTime() and GetTotalTime().
5195 void CApplication::SeekTime( double dTime )
5197 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5199 if (!m_pPlayer->CanSeek()) return;
5200 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5202 // find the item in the stack we are seeking to, and load the new
5203 // file if necessary, and calculate the correct seek within the new
5204 // file. Otherwise, just fall through to the usual routine if the
5205 // time is higher than our total time.
5206 for (int i = 0; i < m_currentStack->Size(); i++)
5208 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5210 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5211 if (m_currentStackPosition == i)
5212 m_pPlayer->SeekTime((__int64)((dTime - startOfNewFile) * 1000.0));
5214 { // seeking to a new file
5215 m_currentStackPosition = i;
5216 CFileItem item(*(*m_currentStack)[i]);
5217 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5218 // don't just call "PlayFile" here, as we are quite likely called from the
5219 // player thread, so we won't be able to delete ourselves.
5220 m_applicationMessenger.PlayFile(item, true);
5226 // convert to milliseconds and perform seek
5227 m_pPlayer->SeekTime( static_cast<__int64>( dTime * 1000.0 ) );
5231 float CApplication::GetPercentage() const
5233 if (IsPlaying() && m_pPlayer)
5235 if (IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5237 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5238 if (tag.GetDuration() > 0)
5239 return (float)(GetTime() / tag.GetDuration() * 100);
5242 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5243 return (float)(GetTime() / GetTotalTime() * 100);
5245 return m_pPlayer->GetPercentage();
5250 float CApplication::GetCachePercentage() const
5252 if (IsPlaying() && m_pPlayer)
5253 return m_pPlayer->GetCachePercentage();
5258 void CApplication::SeekPercentage(float percent)
5260 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5262 if (!m_pPlayer->CanSeek()) return;
5263 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5264 SeekTime(percent * 0.01 * GetTotalTime());
5266 m_pPlayer->SeekPercentage(percent);
5270 // SwitchToFullScreen() returns true if a switch is made, else returns false
5271 bool CApplication::SwitchToFullScreen()
5273 // if playing from the video info window, close it first!
5274 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5276 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5277 if (pDialog) pDialog->Close(true);
5280 // don't switch if there is a dialog on screen or the slideshow is active
5281 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5284 // See if we're playing a video, and are in GUI mode
5285 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5287 // Reset frame count so that timing is FPS will be correct.
5289 CSingleLock lock(m_frameMutex);
5293 // then switch to fullscreen mode
5294 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5297 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5298 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5299 { // then switch to visualisation
5300 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5306 void CApplication::Minimize()
5308 g_Windowing.Minimize();
5311 PLAYERCOREID CApplication::GetCurrentPlayer()
5313 return m_eCurrentPlayer;
5316 // when a scan is initiated, save current settings
5317 // and enable tag reading and remote thums
5318 void CApplication::SaveMusicScanSettings()
5320 CLog::Log(LOGINFO,"Music scan has started... Enabling tag reading, and remote thumbs");
5321 g_settings.m_bMyMusicIsScanning = true;
5325 void CApplication::RestoreMusicScanSettings()
5327 g_settings.m_bMyMusicIsScanning = false;
5331 void CApplication::UpdateLibraries()
5333 if (g_guiSettings.GetBool("videolibrary.updateonstartup"))
5335 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5336 CGUIDialogVideoScan *scanner = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
5337 if (scanner && !scanner->IsScanning())
5338 scanner->StartScanning("");
5341 if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
5343 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5344 CGUIDialogMusicScan *scanner = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
5345 if (scanner && !scanner->IsScanning())
5346 scanner->StartScanning("");
5350 void CApplication::CheckPlayingProgress()
5352 // check if we haven't rewound past the start of the file
5355 int iSpeed = g_application.GetPlaySpeed();
5365 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5367 g_application.SetPlaySpeed(1);
5368 g_application.SeekTime(0);
5374 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5376 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5378 // initial exit conditions
5379 // no songs in playlist just return
5380 if (playlist.size() == 0)
5384 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5387 // setup correct playlist
5388 g_playlistPlayer.ClearPlaylist(iPlaylist);
5390 // if the playlist contains an internet stream, this file will be used
5391 // to generate a thumbnail for musicplayer.cover
5392 g_application.m_strPlayListFile = strPlayList;
5394 // add the items to the playlist player
5395 g_playlistPlayer.Add(iPlaylist, playlist);
5397 // if we have a playlist
5398 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5401 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5402 g_playlistPlayer.Reset();
5403 g_playlistPlayer.Play(track);
5409 void CApplication::SaveCurrentFileSettings()
5411 if (m_itemCurrentFile->IsVideo())
5413 // save video settings
5414 if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings)
5418 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), g_settings.m_currentVideoSettings);
5424 bool CApplication::AlwaysProcess(const CAction& action)
5426 // check if this button is mapped to a built-in function
5427 if (!action.GetName().IsEmpty())
5429 CStdString builtInFunction;
5430 vector<CStdString> params;
5431 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5432 builtInFunction.ToLower();
5434 // should this button be handled normally or just cancel the screensaver?
5435 if ( builtInFunction.Equals("powerdown")
5436 || builtInFunction.Equals("reboot")
5437 || builtInFunction.Equals("restart")
5438 || builtInFunction.Equals("restartapp")
5439 || builtInFunction.Equals("suspend")
5440 || builtInFunction.Equals("hibernate")
5441 || builtInFunction.Equals("quit")
5442 || builtInFunction.Equals("shutdown"))
5451 CApplicationMessenger& CApplication::getApplicationMessenger()
5453 return m_applicationMessenger;
5456 bool CApplication::IsCurrentThread() const
5458 return CThread::IsCurrentThread(m_threadID);
5461 bool CApplication::IsPresentFrame()
5463 CSingleLock lock(m_frameMutex);
5464 bool ret = m_bPresentFrame;
5469 #if defined(HAS_LINUX_NETWORK)
5470 CNetworkLinux& CApplication::getNetwork()
5474 #elif defined(HAS_WIN32_NETWORK)
5475 CNetworkWin32& CApplication::getNetwork()
5480 CNetwork& CApplication::getNetwork()
5486 #ifdef HAS_PERFORMANCE_SAMPLE
5487 CPerformanceStats &CApplication::GetPerformanceStats()