2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "network/Network.h"
22 #include "threads/SystemClock.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
29 #include "utils/Screenshot.h"
32 #include "guilib/TextureManager.h"
33 #include "cores/IPlayer.h"
34 #include "cores/dvdplayer/DVDFileInfo.h"
35 #include "cores/AudioEngine/AEFactory.h"
36 #include "cores/AudioEngine/Utils/AEUtil.h"
37 #include "PlayListPlayer.h"
39 #include "video/Bookmark.h"
40 #include "network/NetworkServices.h"
41 #include "guilib/GUIControlProfiler.h"
42 #include "utils/LangCodeExpander.h"
43 #include "GUIInfoManager.h"
44 #include "playlists/PlayListFactory.h"
45 #include "guilib/GUIFontManager.h"
46 #include "guilib/GUIColorManager.h"
47 #include "guilib/GUITextLayout.h"
48 #include "addons/Skin.h"
50 #include "interfaces/python/XBPython.h"
52 #include "input/ButtonTranslator.h"
53 #include "guilib/GUIAudioManager.h"
54 #include "GUIPassword.h"
55 #include "input/InertialScrollingHandler.h"
56 #include "ApplicationMessenger.h"
57 #include "SectionLoader.h"
58 #include "cores/DllLoader/DllLoaderContainer.h"
59 #include "GUIUserMessages.h"
60 #include "filesystem/DirectoryCache.h"
61 #include "filesystem/StackDirectory.h"
62 #include "filesystem/SpecialProtocol.h"
63 #include "filesystem/DllLibCurl.h"
64 #include "filesystem/MythSession.h"
65 #include "filesystem/PluginDirectory.h"
66 #ifdef HAS_FILESYSTEM_SAP
67 #include "filesystem/SAPDirectory.h"
69 #ifdef HAS_FILESYSTEM_HTSP
70 #include "filesystem/HTSPDirectory.h"
72 #include "utils/TuxBoxUtil.h"
73 #include "utils/SystemInfo.h"
74 #include "utils/TimeUtils.h"
75 #include "GUILargeTextureManager.h"
76 #include "TextureCache.h"
77 #include "playlists/SmartPlayList.h"
78 #ifdef HAS_FILESYSTEM_RAR
79 #include "filesystem/RarManager.h"
81 #include "playlists/PlayList.h"
82 #include "profiles/ProfilesManager.h"
83 #include "windowing/WindowingFactory.h"
84 #include "powermanagement/PowerManager.h"
85 #include "powermanagement/DPMSSupport.h"
86 #include "settings/SettingAddon.h"
87 #include "settings/Settings.h"
88 #include "settings/AdvancedSettings.h"
89 #include "settings/DisplaySettings.h"
90 #include "settings/MediaSettings.h"
91 #include "settings/MediaSourceSettings.h"
92 #include "settings/SkinSettings.h"
93 #include "settings/Settings.h"
94 #include "guilib/LocalizeStrings.h"
95 #include "utils/CPUInfo.h"
96 #include "utils/RssManager.h"
97 #include "utils/SeekHandler.h"
98 #include "view/ViewStateSettings.h"
100 #include "input/KeyboardStat.h"
101 #include "input/XBMC_vkeys.h"
102 #include "input/MouseStat.h"
108 #if defined(FILESYSTEM) && !defined(_LINUX)
109 #include "filesystem/FileDAAP.h"
112 #include "network/upnp/UPnP.h"
113 #include "network/upnp/UPnPSettings.h"
114 #include "filesystem/UPnPDirectory.h"
116 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
117 #include "filesystem/SMBDirectory.h"
119 #ifdef HAS_FILESYSTEM_NFS
120 #include "filesystem/NFSFile.h"
122 #ifdef HAS_FILESYSTEM_AFP
123 #include "filesystem/AFPFile.h"
125 #ifdef HAS_FILESYSTEM_SFTP
126 #include "filesystem/SFTPFile.h"
128 #include "PartyModeManager.h"
129 #ifdef HAS_VIDEO_PLAYBACK
130 #include "cores/VideoRenderers/RenderManager.h"
133 #include "music/karaoke/karaokelyricsmanager.h"
134 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
135 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
137 #include "network/Zeroconf.h"
138 #include "network/ZeroconfBrowser.h"
140 #include "threads/platform/win/Win32Exception.h"
142 #ifdef HAS_EVENT_SERVER
143 #include "network/EventServer.h"
146 #include <dbus/dbus.h>
149 #include "interfaces/json-rpc/JSONRPC.h"
150 #include "network/TCPServer.h"
153 #include "network/AirPlayServer.h"
156 #include "network/AirTunesServer.h"
158 #if defined(HAVE_LIBCRYSTALHD)
159 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
161 #include "interfaces/AnnouncementManager.h"
162 #include "peripherals/Peripherals.h"
163 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
165 #include "peripherals/devices/PeripheralImon.h"
166 #include "music/infoscanner/MusicInfoScanner.h"
169 #include "guilib/GUIWindowManager.h"
170 #include "windows/GUIWindowHome.h"
171 #include "settings/windows/GUIWindowSettings.h"
172 #include "windows/GUIWindowFileManager.h"
173 #include "settings/windows/GUIWindowSettingsCategory.h"
174 #include "music/windows/GUIWindowMusicPlaylist.h"
175 #include "music/windows/GUIWindowMusicSongs.h"
176 #include "music/windows/GUIWindowMusicNav.h"
177 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
178 #include "video/windows/GUIWindowVideoPlaylist.h"
179 #include "music/dialogs/GUIDialogMusicInfo.h"
180 #include "video/dialogs/GUIDialogVideoInfo.h"
181 #include "video/windows/GUIWindowVideoNav.h"
182 #include "profiles/windows/GUIWindowSettingsProfile.h"
184 #include "rendering/gl/GUIWindowTestPatternGL.h"
187 #include "rendering/dx/GUIWindowTestPatternDX.h"
189 #include "settings/windows/GUIWindowSettingsScreenCalibration.h"
190 #include "programs/GUIWindowPrograms.h"
191 #include "pictures/GUIWindowPictures.h"
192 #include "windows/GUIWindowWeather.h"
193 #include "windows/GUIWindowLoginScreen.h"
194 #include "addons/GUIWindowAddonBrowser.h"
195 #include "music/windows/GUIWindowVisualisation.h"
196 #include "windows/GUIWindowDebugInfo.h"
197 #include "windows/GUIWindowPointer.h"
198 #include "windows/GUIWindowSystemInfo.h"
199 #include "windows/GUIWindowScreensaver.h"
200 #include "windows/GUIWindowScreensaverDim.h"
201 #include "pictures/GUIWindowSlideShow.h"
202 #include "windows/GUIWindowStartup.h"
203 #include "video/windows/GUIWindowFullScreen.h"
204 #include "video/dialogs/GUIDialogVideoOSD.h"
205 #include "music/dialogs/GUIDialogMusicOverlay.h"
206 #include "video/dialogs/GUIDialogVideoOverlay.h"
207 #include "video/VideoInfoScanner.h"
208 #include "video/PlayerController.h"
211 #include "music/dialogs/GUIDialogMusicOSD.h"
212 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
213 #include "dialogs/GUIDialogTextViewer.h"
214 #include "network/GUIDialogNetworkSetup.h"
215 #include "dialogs/GUIDialogMediaSource.h"
216 #include "video/dialogs/GUIDialogVideoSettings.h"
217 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
218 #include "video/dialogs/GUIDialogVideoBookmarks.h"
219 #include "profiles/dialogs/GUIDialogProfileSettings.h"
220 #include "profiles/dialogs/GUIDialogLockSettings.h"
221 #include "settings/dialogs/GUIDialogContentSettings.h"
222 #include "dialogs/GUIDialogBusy.h"
223 #include "dialogs/GUIDialogKeyboardGeneric.h"
224 #include "dialogs/GUIDialogYesNo.h"
225 #include "dialogs/GUIDialogOK.h"
226 #include "dialogs/GUIDialogProgress.h"
227 #include "dialogs/GUIDialogExtendedProgressBar.h"
228 #include "dialogs/GUIDialogSelect.h"
229 #include "dialogs/GUIDialogSeekBar.h"
230 #include "dialogs/GUIDialogKaiToast.h"
231 #include "dialogs/GUIDialogVolumeBar.h"
232 #include "dialogs/GUIDialogMuteBug.h"
233 #include "video/dialogs/GUIDialogFileStacking.h"
234 #include "dialogs/GUIDialogNumeric.h"
235 #include "dialogs/GUIDialogGamepad.h"
236 #include "dialogs/GUIDialogSubMenu.h"
237 #include "dialogs/GUIDialogFavourites.h"
238 #include "dialogs/GUIDialogButtonMenu.h"
239 #include "dialogs/GUIDialogContextMenu.h"
240 #include "dialogs/GUIDialogPlayerControls.h"
241 #include "music/dialogs/GUIDialogSongInfo.h"
242 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
243 #include "dialogs/GUIDialogSmartPlaylistRule.h"
244 #include "pictures/GUIDialogPictureInfo.h"
245 #include "addons/GUIDialogAddonSettings.h"
246 #include "addons/GUIDialogAddonInfo.h"
247 #ifdef HAS_LINUX_NETWORK
248 #include "network/GUIDialogAccessPoints.h"
251 /* PVR related include Files */
252 #include "pvr/PVRManager.h"
253 #include "pvr/timers/PVRTimers.h"
254 #include "pvr/windows/GUIWindowPVR.h"
255 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
256 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
257 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
258 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
260 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
261 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
263 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
264 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
266 #include "epg/EpgContainer.h"
268 #include "video/dialogs/GUIDialogFullScreenInfo.h"
269 #include "video/dialogs/GUIDialogTeletext.h"
270 #include "dialogs/GUIDialogSlider.h"
271 #include "guilib/GUIControlFactory.h"
272 #include "dialogs/GUIDialogCache.h"
273 #include "dialogs/GUIDialogPlayEject.h"
274 #include "dialogs/GUIDialogMediaFilter.h"
275 #include "utils/XMLUtils.h"
276 #include "addons/AddonInstaller.h"
278 #ifdef HAS_PERFORMANCE_SAMPLE
279 #include "utils/PerformanceSample.h"
281 #define MEASURE_FUNCTION
284 #ifdef TARGET_WINDOWS
286 #include "win32util.h"
289 #include "windowing/X11/XRandR.h"
292 #ifdef TARGET_DARWIN_OSX
293 #include "osx/CocoaInterface.h"
294 #include "osx/XBMCHelper.h"
297 #include "osx/DarwinUtils.h"
302 #include <cdio/logging.h>
306 #include "linux/HALManager.h"
309 #include "storage/MediaManager.h"
310 #include "utils/JobManager.h"
311 #include "utils/SaveFileStateJob.h"
312 #include "utils/AlarmClock.h"
313 #include "utils/RssReader.h"
314 #include "utils/StringUtils.h"
315 #include "utils/Weather.h"
316 #include "DatabaseManager.h"
318 #include "settings/DisplaySettings.h"
319 #include "settings/MediaSettings.h"
320 #include "settings/SkinSettings.h"
321 #include "view/ViewStateSettings.h"
328 #include "input/linux/LIRC.h"
330 #ifdef HAS_IRSERVERSUITE
331 #include "input/windows/IRServerSuite.h"
334 #if defined(TARGET_WINDOWS)
335 #include "input/windows/WINJoystick.h"
336 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
337 #include "input/SDLJoystick.h"
340 #if defined(TARGET_ANDROID)
341 #include "android/activity/XBMCApp.h"
345 #include "linux/LinuxTimezone.h"
348 #ifdef TARGET_WINDOWS
349 #include "utils/Environment.h"
353 using namespace ADDON;
354 using namespace XFILE;
356 using namespace MEDIA_DETECT;
358 using namespace PLAYLIST;
359 using namespace VIDEO;
360 using namespace MUSIC_INFO;
361 #ifdef HAS_EVENT_SERVER
362 using namespace EVENTSERVER;
365 using namespace JSONRPC;
367 using namespace ANNOUNCEMENT;
370 using namespace PERIPHERALS;
372 using namespace XbmcThreads;
374 // uncomment this if you want to use release libs in the debug build.
375 // Atm this saves you 7 mb of memory
376 #define USE_RELEASE_LIBS
378 #define MAX_FFWD_SPEED 5
380 //extern IDirectSoundRenderer* m_pAudioDecoder;
381 CApplication::CApplication(void)
383 , m_itemCurrentFile(new CFileItem)
384 , m_stackFileItemToUpdate(new CFileItem)
385 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
386 , m_progressTrackingItem(new CFileItem)
387 , m_videoInfoScanner(new CVideoInfoScanner)
388 , m_musicInfoScanner(new CMusicInfoScanner)
389 , m_seekHandler(new CSeekHandler)
390 , m_playerController(new CPlayerController)
393 TiXmlBase::SetCondenseWhiteSpace(false);
395 m_bInhibitIdleShutdown = false;
396 m_bScreenSave = false;
398 m_dpmsIsActive = false;
399 m_dpmsIsManual = false;
400 m_iScreenSaveLock = 0;
401 m_bInitializing = true;
402 m_eForcedNextPlayer = EPC_NONE;
403 m_strPlayListFile = "";
404 m_nextPlaylistItem = -1;
406 m_bPlaybackStarting = false;
407 m_ePlayState = PLAY_STATE_NONE;
408 m_skinReloading = false;
414 // we start in frontend
415 m_bInBackground = false;
417 /* for now always keep this around */
419 m_pKaraokeMgr = new CKaraokeLyricsManager();
421 m_currentStack = new CFileItemList;
425 m_bPresentFrame = false;
426 m_bPlatformDirectories = true;
428 m_bStandalone = false;
429 m_bEnableLegacyRes = false;
430 m_bSystemScreenSaverEnable = false;
431 m_pInertialScrollingHandler = new CInertialScrollingHandler();
433 m_Autorun = new CAutorun();
438 m_eCurrentPlayer = EPC_NONE;
439 m_progressTrackingPlayCountUpdate = false;
440 m_currentStackPosition = 0;
442 m_lastRenderTime = 0;
446 m_volumeLevel = 1.0f;
449 CApplication::~CApplication(void)
451 delete m_musicInfoScanner;
452 delete m_videoInfoScanner;
453 delete &m_progressTrackingVideoResumeBookmark;
457 delete m_currentStack;
460 delete m_pKaraokeMgr;
464 delete m_seekHandler;
465 delete m_playerController;
466 delete m_pInertialScrollingHandler;
470 bool CApplication::OnEvent(XBMC_Event& newEvent)
472 switch(newEvent.type)
475 if (!g_application.m_bStop)
476 CApplicationMessenger::Get().Quit();
479 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
482 g_Keyboard.ProcessKeyUp();
484 case XBMC_MOUSEBUTTONDOWN:
485 case XBMC_MOUSEBUTTONUP:
486 case XBMC_MOUSEMOTION:
487 g_Mouse.HandleEvent(newEvent);
488 g_application.ProcessMouse();
490 case XBMC_VIDEORESIZE:
491 if (!g_application.m_bInitializing &&
492 !g_advancedSettings.m_fullScreen)
494 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
495 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
496 CSettings::Get().SetInt("window.width", newEvent.resize.w);
497 CSettings::Get().SetInt("window.height", newEvent.resize.h);
498 CSettings::Get().Save();
502 #ifdef TARGET_WINDOWS
503 if (g_advancedSettings.m_fullScreen)
505 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
506 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
507 if (newRes != g_graphicsContext.GetVideoResolution())
508 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
513 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
517 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
519 case XBMC_APPCOMMAND:
520 return g_application.OnAppCommand(newEvent.appcommand.action);
523 int windowId = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
525 if (newEvent.touch.action == ACTION_TOUCH_TAP)
526 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
527 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
530 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
532 actionId = newEvent.touch.action;
533 windowId = WINDOW_INVALID;
535 else if (!CButtonTranslator::GetInstance().TranslateTouchAction(newEvent.touch.action, newEvent.touch.pointers, windowId, actionId) ||
539 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), windowId, false);
540 // Post an unfocus message for touch device after the action.
541 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
543 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
544 CApplicationMessenger::Get().SendGUIMessage(msg);
552 extern "C" void __stdcall init_emu_environ();
553 extern "C" void __stdcall update_emu_environ();
556 // Utility function used to copy files from the application bundle
557 // over to the user data directory in Application Support/XBMC.
559 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
561 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
562 if (!CFile::Exists(destPath))
564 // need to copy it across
565 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
566 CFile::Cache(srcPath, destPath);
570 void CApplication::Preflight()
573 // call 'dbus_threads_init_default' before any other dbus calls in order to
574 // avoid race conditions with other threads using dbus connections
575 dbus_threads_init_default();
578 // run any platform preflight scripts.
579 #if defined(TARGET_DARWIN_OSX)
580 CStdString install_path;
582 CUtil::GetHomePath(install_path);
583 setenv("XBMC_HOME", install_path.c_str(), 0);
584 install_path += "/tools/darwin/runtime/preflight";
585 system(install_path.c_str());
589 bool CApplication::Create()
591 #if defined(HAS_LINUX_NETWORK)
592 m_network = new CNetworkLinux();
593 #elif defined(HAS_WIN32_NETWORK)
594 m_network = new CNetworkWin32();
596 m_network = new CNetwork();
601 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
603 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
604 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
608 tzset(); // Initialize timezone information variables
611 // Grab a handle to our thread to be used later in identifying the render thread.
612 m_threadID = CThread::GetCurrentThreadId();
615 //floating point precision to 24 bits (faster performance)
616 _controlfp(_PC_24, _MCW_PC);
618 /* install win32 exception translator, win32 exceptions
619 * can now be caught using c++ try catch */
620 win32_exception::install_handler();
624 // only the InitDirectories* for the current platform should return true
625 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
626 bool inited = InitDirectoriesLinux();
628 inited = InitDirectoriesOSX();
630 inited = InitDirectoriesWin32();
632 // copy required files
633 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
634 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
635 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
637 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
639 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
640 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
644 // Init our DllLoaders emu env
647 CProfilesManager::Get().Load();
649 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
650 #if defined(TARGET_DARWIN_OSX)
651 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin OSX (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
652 #elif defined(TARGET_DARWIN_IOS)
653 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: Darwin iOS (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
654 #elif defined(__FreeBSD__)
655 CLog::Log(LOGNOTICE, "Starting XBMC (%s), Platform: FreeBSD (%s). Built on %s", g_infoManager.GetVersion().c_str(), g_sysinfo.GetUnameVersion().c_str(), __DATE__);
656 #elif defined(_LINUX)
657 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__);
658 #elif defined(_WIN32)
659 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);
660 CLog::Log(LOGNOTICE, g_cpuInfo.getCPUModel().c_str());
661 CLog::Log(LOGNOTICE, CWIN32Util::GetResInfoString());
662 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
663 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
666 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
667 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
669 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
671 CSpecialProtocol::LogPaths();
673 CStdString executable = CUtil::ResolveExecutablePath();
674 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
675 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
676 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
677 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
679 CStdString strExecutablePath;
680 CUtil::GetHomePath(strExecutablePath);
682 // if we are running from DVD our UserData location will be TDATA
683 if (URIUtils::IsDVD(strExecutablePath))
685 // TODO: Should we copy over any UserData folder from the DVD?
686 if (!CFile::Exists("special://masterprofile/guisettings.xml")) // first run - cache userdata folder
689 CUtil::GetRecursiveListing("special://xbmc/userdata",items,"");
690 for (int i=0;i<items.Size();++i)
691 CFile::Cache(items[i]->GetPath(),"special://masterprofile/"+URIUtils::GetFileName(items[i]->GetPath()));
693 g_advancedSettings.m_logFolder = "special://masterprofile/";
697 g_xrandr.LoadCustomModeLinesToAllOutputs();
700 // for python scripts that check the OS
701 #if defined(TARGET_DARWIN)
702 setenv("OS","OS X",true);
703 #elif defined(_LINUX)
704 setenv("OS","Linux",true);
705 #elif defined(_WIN32)
706 CEnvironment::setenv("OS", "win32");
709 g_powerManager.Initialize();
711 // Load the AudioEngine before settings as they need to query the engine
712 if (!CAEFactory::LoadEngine())
714 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
718 // Initialize default Settings - don't move
719 CLog::Log(LOGNOTICE, "load settings...");
720 if (!CSettings::Get().Initialize())
723 g_powerManager.SetDefaults();
725 // load the actual values
726 if (!CSettings::Get().Load())
728 CLog::Log(LOGFATAL, "unable to load settings");
731 CSettings::Get().SetLoaded();
733 CLog::Log(LOGINFO, "creating subdirectories");
734 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
735 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
736 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
737 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
738 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
739 CProfilesManager::Get().CreateProfileFolders();
741 update_emu_environ();//apply the GUI settings
743 // initialize our charset converter
744 g_charsetConverter.reset();
746 // Load the langinfo to have user charset <-> utf-8 conversion
747 CStdString strLanguage = CSettings::Get().GetString("locale.language");
748 strLanguage[0] = toupper(strLanguage[0]);
750 CStdString strLangInfoPath;
751 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
753 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
754 g_langInfo.Load(strLangInfoPath);
756 CStdString strLanguagePath = "special://xbmc/language/";
758 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
759 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
761 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
765 // start the AudioEngine
766 if (!CAEFactory::StartEngine())
768 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
772 // restore AE's previous volume state
773 SetHardwareVolume(m_volumeLevel);
774 CAEFactory::SetMute (m_muted);
775 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
777 // initialize m_replayGainSettings
778 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
779 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
780 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
781 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
783 // initialize the addon database (must be before the addon manager is init'd)
784 CDatabaseManager::Get().Initialize(true);
786 // start-up Addons Framework
787 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
788 if (!CAddonMgr::Get().Init())
790 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
794 // set logging from debug add-on
796 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
798 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
800 g_peripherals.Initialise();
802 // Create the Mouse, Keyboard, Remote, and Joystick devices
803 // Initialize after loading settings to get joystick deadzone setting
804 g_Mouse.Initialize();
805 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
807 g_Keyboard.Initialize();
808 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
809 g_RemoteControl.Initialize();
812 #if defined(TARGET_DARWIN_OSX)
813 // Configure and possible manually start the helper.
814 XBMCHelper::GetInstance().Configure();
817 CUtil::InitRandomSeed();
819 g_mediaManager.Initialize();
821 m_lastFrameTime = XbmcThreads::SystemClockMillis();
822 m_lastRenderTime = m_lastFrameTime;
826 bool CApplication::CreateGUI()
830 CLog::Log(LOGNOTICE, "Setup SDL");
832 /* Clean up on exit, exit on window close and interrupt */
835 uint32_t sdlFlags = 0;
837 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
838 sdlFlags |= SDL_INIT_VIDEO;
841 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
842 sdlFlags |= SDL_INIT_JOYSTICK;
845 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
846 //this might bring the monitor out of standby, so we have to disable it explicitly
847 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
848 #if defined(_LINUX) && !defined(TARGET_DARWIN)
849 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
855 // for nvidia cards - vsync currently ALWAYS enabled.
856 // the reason is that after screen has been setup changing this env var will make no difference.
857 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
858 setenv("__GL_YIELD", "USLEEP", 0);
861 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
862 g_Windowing.EnableSystemScreenSaver(false);
865 if (SDL_Init(sdlFlags) != 0)
867 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
870 #if defined(TARGET_DARWIN)
871 // SDL_Init will install a handler for segfaults, restore the default handler.
872 signal(SIGSEGV, SIG_DFL);
876 // Initialize core peripheral port support. Note: If these parameters
877 // are 0 and NULL, respectively, then the default number and types of
878 // controllers will be initialized.
879 if (!g_Windowing.InitWindowSystem())
881 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
885 // Retrieve the matching resolution based on GUI settings
886 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
887 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
888 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
890 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
891 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
894 // update the window resolution
895 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
897 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
898 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
900 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
902 // Oh uh - doesn't look good for starting in their wanted screenmode
903 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
904 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
911 if (g_advancedSettings.m_splashImage)
913 CStdString strUserSplash = "special://home/media/Splash.png";
914 if (CFile::Exists(strUserSplash))
916 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
917 m_splash = new CSplash(strUserSplash);
921 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
922 m_splash = new CSplash("special://xbmc/media/Splash.png");
927 // The key mappings may already have been loaded by a peripheral
928 CLog::Log(LOGINFO, "load keymapping");
929 if (!CButtonTranslator::GetInstance().Load())
932 int iResolution = g_graphicsContext.GetVideoResolution();
933 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
934 CDisplaySettings::Get().GetResolutionInfo(iResolution).iWidth,
935 CDisplaySettings::Get().GetResolutionInfo(iResolution).iHeight,
936 CDisplaySettings::Get().GetResolutionInfo(iResolution).strMode.c_str());
937 g_windowManager.Initialize();
942 bool CApplication::InitWindow()
944 #ifdef TARGET_DARWIN_OSX
945 // force initial window creation to be windowed, if fullscreen, it will switch to it below
946 // fixes the white screen of death if starting fullscreen and switching to windowed.
947 bool bFullScreen = false;
948 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
950 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
954 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
955 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
957 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
962 if (!g_Windowing.InitRenderSystem())
964 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
967 // set GUI res and force the clear of the screen
968 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
969 g_fontManager.ReloadTTFFonts();
973 bool CApplication::DestroyWindow()
975 g_fontManager.UnloadTTFFonts();
976 return g_Windowing.DestroyWindow();
979 bool CApplication::InitDirectoriesLinux()
982 The following is the directory mapping for Platform Specific Mode:
984 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
985 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
986 installations like skins, screensavers, etc.
988 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
989 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
990 mapped to special://home/userdata ($HOME/.xbmc/userdata)
991 special://profile/ => [read-write] current profile's userdata directory.
992 Generally special://masterprofile for the master profile or
993 special://masterprofile/profiles/<profile_name> for other profiles.
995 NOTE: All these root directories are lowercase. Some of the sub-directories
999 #if defined(_LINUX) && !defined(TARGET_DARWIN)
1000 CStdString userName;
1002 userName = getenv("USER");
1006 CStdString userHome;
1008 userHome = getenv("HOME");
1012 CStdString xbmcBinPath, xbmcPath;
1013 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1014 xbmcPath = getenv("XBMC_HOME");
1016 if (xbmcPath.IsEmpty())
1018 xbmcPath = xbmcBinPath;
1019 /* Check if xbmc binaries and arch independent data files are being kept in
1020 * separate locations. */
1021 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1023 /* Attempt to locate arch independent data files. */
1024 CUtil::GetHomePath(xbmcPath);
1025 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1027 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1033 /* Set some environment variables */
1034 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1035 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1037 if (m_bPlatformDirectories)
1039 // map our special drives
1040 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1041 CSpecialProtocol::SetXBMCPath(xbmcPath);
1042 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1043 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1045 CStdString strTempPath = userHome;
1046 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1047 if (getenv("XBMC_TEMP"))
1048 strTempPath = getenv("XBMC_TEMP");
1049 CSpecialProtocol::SetTempPath(strTempPath);
1051 URIUtils::AddSlashAtEnd(strTempPath);
1052 g_advancedSettings.m_logFolder = strTempPath;
1059 URIUtils::AddSlashAtEnd(xbmcPath);
1060 g_advancedSettings.m_logFolder = xbmcPath;
1062 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1063 CSpecialProtocol::SetXBMCPath(xbmcPath);
1064 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1065 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1067 CStdString strTempPath = xbmcPath;
1068 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1069 if (getenv("XBMC_TEMP"))
1070 strTempPath = getenv("XBMC_TEMP");
1071 CSpecialProtocol::SetTempPath(strTempPath);
1074 URIUtils::AddSlashAtEnd(strTempPath);
1075 g_advancedSettings.m_logFolder = strTempPath;
1084 bool CApplication::InitDirectoriesOSX()
1086 #if defined(TARGET_DARWIN)
1087 CStdString userName;
1089 userName = getenv("USER");
1093 CStdString userHome;
1095 userHome = getenv("HOME");
1099 CStdString xbmcPath;
1100 CUtil::GetHomePath(xbmcPath);
1101 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1103 #if defined(TARGET_DARWIN_IOS)
1104 CStdString fontconfigPath;
1105 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1106 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1109 // setup path to our internal dylibs so loader can find them
1110 CStdString frameworksPath = CUtil::GetFrameworksPath();
1111 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1113 // OSX always runs with m_bPlatformDirectories == true
1114 if (m_bPlatformDirectories)
1116 // map our special drives
1117 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1118 CSpecialProtocol::SetXBMCPath(xbmcPath);
1119 #if defined(TARGET_DARWIN_IOS)
1120 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
1121 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
1123 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1124 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1127 // location for temp files
1128 #if defined(TARGET_DARWIN_IOS)
1129 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
1131 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1132 CDirectory::Create(strTempPath);
1133 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1135 CSpecialProtocol::SetTempPath(strTempPath);
1137 // xbmc.log file location
1138 #if defined(TARGET_DARWIN_IOS)
1139 strTempPath = userHome + "/Library/Preferences";
1141 strTempPath = userHome + "/Library/Logs";
1143 URIUtils::AddSlashAtEnd(strTempPath);
1144 g_advancedSettings.m_logFolder = strTempPath;
1150 URIUtils::AddSlashAtEnd(xbmcPath);
1151 g_advancedSettings.m_logFolder = xbmcPath;
1153 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1154 CSpecialProtocol::SetXBMCPath(xbmcPath);
1155 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1156 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1158 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1159 CSpecialProtocol::SetTempPath(strTempPath);
1161 URIUtils::AddSlashAtEnd(strTempPath);
1162 g_advancedSettings.m_logFolder = strTempPath;
1171 bool CApplication::InitDirectoriesWin32()
1174 CStdString xbmcPath;
1176 CUtil::GetHomePath(xbmcPath);
1177 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1178 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1179 CSpecialProtocol::SetXBMCPath(xbmcPath);
1181 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1183 g_advancedSettings.m_logFolder = strWin32UserFolder;
1184 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1185 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1186 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1188 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1192 // Expand the DLL search path with our directories
1193 CWIN32Util::ExtendDllPath();
1201 void CApplication::CreateUserDirs()
1203 CDirectory::Create("special://home/");
1204 CDirectory::Create("special://home/addons");
1205 CDirectory::Create("special://home/addons/packages");
1206 CDirectory::Create("special://home/media");
1207 CDirectory::Create("special://home/sounds");
1208 CDirectory::Create("special://home/system");
1209 CDirectory::Create("special://masterprofile/");
1210 CDirectory::Create("special://temp/");
1211 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1214 bool CApplication::Initialize()
1216 #if defined(HAS_DVD_DRIVE) && !defined(_WIN32) // somehow this throws an "unresolved external symbol" on win32
1217 // turn off cdio logging
1218 cdio_loglevel_default = CDIO_LOG_ERROR;
1221 #ifdef _LINUX // TODO: Win32 has no special://home/ mapping by default, so we
1222 // must create these here. Ideally this should be using special://home/ and
1223 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1224 if (!m_bPlatformDirectories)
1227 CDirectory::Create("special://xbmc/language");
1228 CDirectory::Create("special://xbmc/addons");
1229 CDirectory::Create("special://xbmc/sounds");
1232 // Load curl so curl_global_init gets called before any service threads
1233 // are started. Unloading will have no effect as curl is never fully unloaded.
1234 // To quote man curl_global_init:
1235 // "This function is not thread safe. You must not call it when any other
1236 // thread in the program (i.e. a thread sharing the same memory) is running.
1237 // This doesn't just mean no other thread that is using libcurl. Because
1238 // curl_global_init() calls functions of other libraries that are similarly
1239 // thread unsafe, it could conflict with any other thread that
1240 // uses these other libraries."
1241 g_curlInterface.Load();
1242 g_curlInterface.Unload();
1244 // initialize (and update as needed) our databases
1245 CDatabaseManager::Get().Initialize();
1249 // Init DPMS, before creating the corresponding setting control.
1250 m_dpms = new DPMSSupport();
1251 if (g_windowManager.Initialized())
1253 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetVisible(m_dpms->IsSupported());
1255 g_windowManager.Add(new CGUIWindowHome);
1256 g_windowManager.Add(new CGUIWindowPrograms);
1257 g_windowManager.Add(new CGUIWindowPictures);
1258 g_windowManager.Add(new CGUIWindowFileManager);
1259 g_windowManager.Add(new CGUIWindowSettings);
1260 g_windowManager.Add(new CGUIWindowSystemInfo);
1262 g_windowManager.Add(new CGUIWindowTestPatternGL);
1265 g_windowManager.Add(new CGUIWindowTestPatternDX);
1267 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1268 g_windowManager.Add(new CGUIWindowSettingsCategory);
1269 g_windowManager.Add(new CGUIWindowVideoNav);
1270 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1271 g_windowManager.Add(new CGUIWindowLoginScreen);
1272 g_windowManager.Add(new CGUIWindowSettingsProfile);
1273 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1274 g_windowManager.Add(new CGUIWindowAddonBrowser);
1275 g_windowManager.Add(new CGUIWindowScreensaverDim);
1276 g_windowManager.Add(new CGUIWindowDebugInfo);
1277 g_windowManager.Add(new CGUIWindowPointer);
1278 g_windowManager.Add(new CGUIDialogYesNo);
1279 g_windowManager.Add(new CGUIDialogProgress);
1280 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1281 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1282 g_windowManager.Add(new CGUIDialogVolumeBar);
1283 g_windowManager.Add(new CGUIDialogSeekBar);
1284 g_windowManager.Add(new CGUIDialogSubMenu);
1285 g_windowManager.Add(new CGUIDialogContextMenu);
1286 g_windowManager.Add(new CGUIDialogKaiToast);
1287 g_windowManager.Add(new CGUIDialogNumeric);
1288 g_windowManager.Add(new CGUIDialogGamepad);
1289 g_windowManager.Add(new CGUIDialogButtonMenu);
1290 g_windowManager.Add(new CGUIDialogMuteBug);
1291 g_windowManager.Add(new CGUIDialogPlayerControls);
1293 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1294 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1296 g_windowManager.Add(new CGUIDialogSlider);
1297 g_windowManager.Add(new CGUIDialogMusicOSD);
1298 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1299 g_windowManager.Add(new CGUIDialogVideoSettings);
1300 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1301 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1302 // Don't add the filebrowser dialog - it's created and added when it's needed
1303 g_windowManager.Add(new CGUIDialogNetworkSetup);
1304 g_windowManager.Add(new CGUIDialogMediaSource);
1305 g_windowManager.Add(new CGUIDialogProfileSettings);
1306 g_windowManager.Add(new CGUIDialogFavourites);
1307 g_windowManager.Add(new CGUIDialogSongInfo);
1308 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1309 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1310 g_windowManager.Add(new CGUIDialogBusy);
1311 g_windowManager.Add(new CGUIDialogPictureInfo);
1312 g_windowManager.Add(new CGUIDialogAddonInfo);
1313 g_windowManager.Add(new CGUIDialogAddonSettings);
1314 #ifdef HAS_LINUX_NETWORK
1315 g_windowManager.Add(new CGUIDialogAccessPoints);
1318 g_windowManager.Add(new CGUIDialogLockSettings);
1320 g_windowManager.Add(new CGUIDialogContentSettings);
1322 g_windowManager.Add(new CGUIDialogPlayEject);
1324 g_windowManager.Add(new CGUIDialogPeripheralManager);
1325 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1327 g_windowManager.Add(new CGUIDialogMediaFilter);
1329 g_windowManager.Add(new CGUIWindowMusicPlayList);
1330 g_windowManager.Add(new CGUIWindowMusicSongs);
1331 g_windowManager.Add(new CGUIWindowMusicNav);
1332 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1334 /* Load PVR related Windows and Dialogs */
1335 g_windowManager.Add(new CGUIDialogTeletext);
1336 g_windowManager.Add(new CGUIWindowPVR);
1337 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1338 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1339 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1340 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1341 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1342 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1343 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1344 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1345 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1346 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1348 g_windowManager.Add(new CGUIDialogSelect);
1349 g_windowManager.Add(new CGUIDialogMusicInfo);
1350 g_windowManager.Add(new CGUIDialogOK);
1351 g_windowManager.Add(new CGUIDialogVideoInfo);
1352 g_windowManager.Add(new CGUIDialogTextViewer);
1353 g_windowManager.Add(new CGUIWindowFullScreen);
1354 g_windowManager.Add(new CGUIWindowVisualisation);
1355 g_windowManager.Add(new CGUIWindowSlideShow);
1356 g_windowManager.Add(new CGUIDialogFileStacking);
1358 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1361 g_windowManager.Add(new CGUIDialogVideoOSD);
1362 g_windowManager.Add(new CGUIDialogMusicOverlay);
1363 g_windowManager.Add(new CGUIDialogVideoOverlay);
1364 g_windowManager.Add(new CGUIWindowScreensaver);
1365 g_windowManager.Add(new CGUIWindowWeather);
1366 g_windowManager.Add(new CGUIWindowStartup);
1368 /* window id's 3000 - 3100 are reserved for python */
1370 // Make sure we have at least the default skin
1371 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1372 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1374 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1378 if (g_advancedSettings.m_splashImage)
1379 SAFE_DELETE(m_splash);
1381 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1382 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1383 !CProfilesManager::Get().GetMasterProfile().getLockCode().IsEmpty())
1385 g_passwordManager.CheckStartUpLock();
1388 // check if we should use the login screen
1389 if (CProfilesManager::Get().UsingLoginScreen())
1390 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1394 CJSONRPC::Initialize();
1396 ADDON::CAddonMgr::Get().StartServices(false);
1397 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1399 g_windowManager.ActivateWindow(WINDOW_HOME);
1400 StartPVRManager(true);
1404 StartPVRManager(false);
1405 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1410 else //No GUI Created
1413 CJSONRPC::Initialize();
1415 ADDON::CAddonMgr::Get().StartServices(false);
1418 g_sysinfo.Refresh();
1420 CLog::Log(LOGINFO, "removing tempfiles");
1421 CUtil::RemoveTempFiles();
1423 if (!CProfilesManager::Get().UsingLoginScreen())
1427 g_pythonParser.m_bLogin = true;
1431 m_slowTimer.StartZero();
1433 #if defined(HAVE_LIBCRYSTALHD)
1434 CCrystalHD::GetInstance();
1437 CAddonMgr::Get().StartServices(true);
1439 CLog::Log(LOGNOTICE, "initialize done");
1441 m_bInitializing = false;
1443 // reset our screensaver (starts timers etc.)
1446 #ifdef HAS_SDL_JOYSTICK
1447 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1448 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1454 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1460 // the callback will take care of starting/stopping webserver
1461 ret = CSettings::Get().SetBool("services.webserver", bStart);
1464 case ES_AIRPLAYSERVER:
1465 // the callback will take care of starting/stopping airplay
1466 ret = CSettings::Get().SetBool("services.airplay", bStart);
1469 case ES_JSONRPCSERVER:
1470 // the callback will take care of starting/stopping jsonrpc server
1471 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1475 // the callback will take care of starting/stopping upnp server
1476 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1479 case ES_UPNPRENDERER:
1480 // the callback will take care of starting/stopping upnp renderer
1481 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1484 case ES_EVENTSERVER:
1485 // the callback will take care of starting/stopping event server
1486 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1490 // the callback will take care of starting/stopping zeroconf
1491 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1498 CSettings::Get().Save();
1503 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1505 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1506 g_PVRManager.Start(true, bOpenPVRWindow);
1509 void CApplication::StopPVRManager()
1511 CLog::Log(LOGINFO, "stopping PVRManager");
1512 if (g_PVRManager.IsPlaying())
1514 g_PVRManager.Stop();
1515 g_EpgContainer.Stop();
1518 void CApplication::StartServices()
1520 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1521 // Start Thread for DVD Mediatype detection
1522 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1523 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1526 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1527 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1528 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1529 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1530 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1531 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1534 void CApplication::StopServices()
1536 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1538 #if !defined(_WIN32) && defined(HAS_DVD_DRIVE)
1539 CLog::Log(LOGNOTICE, "stop dvd detect media");
1540 m_DetectDVDType.StopThread();
1543 g_peripherals.Clear();
1546 void CApplication::OnSettingChanged(const CSetting *setting)
1548 if (setting == NULL)
1551 const std::string &settingId = setting->GetId();
1552 if (settingId == "lookandfeel.skin" ||
1553 settingId == "lookandfeel.font" ||
1554 settingId == "lookandfeel.skincolors")
1556 else if (settingId == "lookandfeel.skintheme")
1558 // also set the default color theme
1559 string colorTheme = URIUtils::ReplaceExtension(((CSettingString*)setting)->GetValue(), ".xml");
1560 if (StringUtils::EqualsNoCase(colorTheme, "Textures.xml"))
1561 colorTheme = "defaults.xml";
1563 // check if we have to change the skin color
1564 // if yes, it will trigger a call to ReloadSkin() in
1565 // it's OnSettingChanged() callback
1566 // if no we have to call ReloadSkin() ourselves
1567 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1568 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1572 else if (settingId == "lookandfeel.skinzoom")
1573 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1574 else if (StringUtils::StartsWith(settingId, "audiooutput."))
1576 if (settingId == "audiooutput.guisoundmode")
1577 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1579 CAEFactory::OnSettingsChange(settingId);
1581 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1582 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1583 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1584 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1585 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1586 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1587 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1588 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1591 void CApplication::OnSettingAction(const CSetting *setting)
1593 if (setting == NULL)
1596 const std::string &settingId = setting->GetId();
1597 if (settingId == "lookandfeel.skinsettings")
1598 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1599 else if (settingId == "screensaver.preview")
1600 ActivateScreenSaver(true);
1601 else if (settingId == "screensaver.settings")
1604 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1605 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1607 else if (settingId == "videoscreen.guicalibration")
1608 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1609 else if (settingId == "videoscreen.testpattern")
1610 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1613 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1615 if (setting == NULL)
1618 const std::string &settingId = setting->GetId();
1619 if (settingId == "audiooutput.channels")
1621 // check if this is an update from Eden
1622 if (oldSettingId != NULL && oldSettingNode != NULL &&
1623 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1626 CSettingInt* channels = (CSettingInt*)setting;
1627 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1628 ret = channels->SetValue(channels->GetValue() + 1);
1630 // let's just reset the audiodevice settings as well
1631 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1632 CAEFactory::VerifyOutputDevice(audiodevice, false);
1633 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1638 else if (settingId == "screensaver.mode")
1640 CSettingString *screensaverMode = (CSettingString*)setting;
1641 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1642 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1643 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1645 else if (settingId == "scrapers.musicvideosdefault")
1647 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1648 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1650 musicvideoScraper->Reset();
1658 bool CApplication::OnSettingsSaving() const
1660 // don't save settings when we're busy stopping the application
1661 // a lot of screens try to save settings on deinit and deinit is
1662 // called for every screen when the application is stopping
1669 void CApplication::ReloadSkin()
1671 m_skinReloading = false;
1672 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1673 g_windowManager.SendMessage(msg);
1675 // Reload the skin, restoring the previously focused control. We need this as
1676 // the window unload will reset all control states.
1678 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1680 iCtrlID = pWindow->GetFocusedControlID();
1682 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1686 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1687 if (pWindow && pWindow->HasSaveLastControl())
1689 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1690 pWindow->OnMessage(msg3);
1695 bool CApplication::Load(const TiXmlNode *settings)
1697 if (settings == NULL)
1700 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1701 if (audioElement != NULL)
1703 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1704 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1705 m_volumeLevel = VOLUME_MAXIMUM;
1711 bool CApplication::Save(TiXmlNode *settings) const
1713 if (settings == NULL)
1716 TiXmlElement volumeNode("audio");
1717 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1718 if (audioNode == NULL)
1721 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1722 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1727 bool CApplication::LoadSkin(const CStdString& skinID)
1729 if (m_skinReloading)
1733 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1735 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1741 void CApplication::LoadSkin(const SkinPtr& skin)
1743 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1746 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1747 CSettings::Get().SetString("lookandfeel.skin", defaultSkin);
1752 if (!skin->HasSkinFile("Home.xml"))
1754 // failed to find home.xml
1755 // fallback to default skin
1756 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1758 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1759 CSettings::Get().SetString("lookandfeel.skin", defaultSkin);
1760 LoadSkin(defaultSkin);
1761 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1766 bool bPreviousPlayingState=false;
1767 bool bPreviousRenderingState=false;
1768 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1770 bPreviousPlayingState = !g_application.m_pPlayer->IsPaused();
1771 if (bPreviousPlayingState)
1772 g_application.m_pPlayer->Pause();
1773 #ifdef HAS_VIDEO_PLAYBACK
1774 if (!g_renderManager.Paused())
1776 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1778 g_windowManager.ActivateWindow(WINDOW_HOME);
1779 bPreviousRenderingState = true;
1784 // close the music and video overlays (they're re-opened automatically later)
1785 CSingleLock lock(g_graphicsContext);
1787 // save the current window details
1788 int currentWindow = g_windowManager.GetActiveWindow();
1789 vector<int> currentModelessWindows;
1790 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1794 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1796 g_SkinInfo->Start();
1798 CLog::Log(LOGINFO, " load fonts for skin...");
1799 g_graphicsContext.SetMediaDir(skin->Path());
1800 g_directoryCache.ClearSubPaths(skin->Path());
1801 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1803 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1804 CStdString strFontSet;
1805 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1807 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1808 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1809 CSettings::Get().Save();
1812 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1814 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1816 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1818 // load in the skin strings
1819 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1820 URIUtils::AddSlashAtEnd(langPath);
1822 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1824 g_SkinInfo->LoadIncludes();
1827 start = CurrentHostCounter();
1829 CLog::Log(LOGINFO, " load new skin...");
1831 // Load the user windows
1835 end = CurrentHostCounter();
1836 freq = CurrentHostFrequency();
1837 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1839 CLog::Log(LOGINFO, " initialize new skin...");
1840 g_windowManager.AddMsgTarget(this);
1841 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1842 g_windowManager.AddMsgTarget(&g_infoManager);
1843 g_windowManager.AddMsgTarget(&g_fontManager);
1844 g_windowManager.SetCallback(*this);
1845 g_windowManager.Initialize();
1846 CTextureCache::Get().Initialize();
1847 g_audioManager.Enable(true);
1848 g_audioManager.Load();
1850 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1851 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1853 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1854 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1855 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1856 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1857 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1860 CLog::Log(LOGINFO, " skin loaded...");
1862 // leave the graphics lock
1866 if (currentWindow != WINDOW_INVALID)
1868 g_windowManager.ActivateWindow(currentWindow);
1869 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1871 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1872 if (dialog) dialog->Show();
1876 if (g_application.m_pPlayer && g_application.IsPlayingVideo())
1878 if (bPreviousPlayingState)
1879 g_application.m_pPlayer->Pause();
1880 if (bPreviousRenderingState)
1881 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1885 void CApplication::UnloadSkin(bool forReload /* = false */)
1887 m_skinReloading = forReload;
1889 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1891 g_audioManager.Enable(false);
1893 g_windowManager.DeInitialize();
1894 CTextureCache::Get().Deinitialize();
1896 // remove the skin-dependent window
1897 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1899 g_TextureManager.Cleanup();
1900 g_largeTextureManager.CleanupUnusedImages(true);
1902 g_fontManager.Clear();
1904 g_colorManager.Clear();
1906 g_charsetConverter.reset();
1908 g_infoManager.Clear();
1910 // The g_SkinInfo boost shared_ptr ought to be reset here
1911 // but there are too many places it's used without checking for NULL
1912 // and as a result a race condition on exit can cause a crash.
1915 bool CApplication::LoadUserWindows()
1917 // Start from wherever home.xml is
1918 std::vector<CStdString> vecSkinPath;
1919 g_SkinInfo->GetSkinPaths(vecSkinPath);
1920 for (unsigned int i = 0;i < vecSkinPath.size();++i)
1922 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1923 CFileItemList items;
1924 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
1926 for (int i = 0; i < items.Size(); ++i)
1928 if (items[i]->m_bIsFolder)
1930 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1931 if (skinFile.Left(6).CompareNoCase("custom") == 0)
1933 CXBMCTinyXML xmlDoc;
1934 if (!xmlDoc.LoadFile(items[i]->GetPath()))
1936 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1940 // Root element should be <window>
1941 TiXmlElement* pRootElement = xmlDoc.RootElement();
1942 CStdString strValue = pRootElement->Value();
1943 if (!strValue.Equals("window"))
1945 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
1949 // Read the <type> element to get the window type to create
1950 // If no type is specified, create a CGUIWindow as default
1951 CGUIWindow* pWindow = NULL;
1953 if (pRootElement->Attribute("type"))
1954 strType = pRootElement->Attribute("type");
1957 const TiXmlNode *pType = pRootElement->FirstChild("type");
1958 if (pType && pType->FirstChild())
1959 strType = pType->FirstChild()->Value();
1961 int id = WINDOW_INVALID;
1962 if (!pRootElement->Attribute("id", &id))
1964 const TiXmlNode *pType = pRootElement->FirstChild("id");
1965 if (pType && pType->FirstChild())
1966 id = atol(pType->FirstChild()->Value());
1968 CStdString visibleCondition;
1969 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1971 if (strType.Equals("dialog"))
1972 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1973 else if (strType.Equals("submenu"))
1974 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
1975 else if (strType.Equals("buttonmenu"))
1976 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
1978 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
1980 // Check to make sure the pointer isn't still null
1981 if (pWindow == NULL)
1983 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
1986 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
1991 pWindow->SetVisibleCondition(visibleCondition);
1992 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
1993 g_windowManager.AddCustomWindow(pWindow);
2001 bool CApplication::RenderNoPresent()
2005 // DXMERGE: This may have been important?
2006 // g_graphicsContext.AcquireCurrentContext();
2008 g_graphicsContext.Lock();
2010 // dont show GUI when playing full screen video
2011 if (g_graphicsContext.IsFullScreenVideo())
2013 if (m_bPresentFrame && IsPlaying() && !IsPaused())
2016 g_renderManager.Present();
2019 g_renderManager.RenderUpdate(true);
2021 // close window overlays
2022 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2023 if (overlay) overlay->Close(true);
2024 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2025 if (overlay) overlay->Close(true);
2029 bool hasRendered = g_windowManager.Render();
2031 g_graphicsContext.Unlock();
2036 float CApplication::GetDimScreenSaverLevel() const
2038 if (!m_bScreenSave || !m_screenSaver ||
2039 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2040 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2041 !m_screenSaver->ID().empty()))
2044 if (!m_screenSaver->GetSetting("level").IsEmpty())
2045 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2049 bool CApplication::WaitFrame(unsigned int timeout)
2053 // Wait for all other frames to be presented
2054 CSingleLock lock(m_frameMutex);
2055 //wait until event is set, but modify remaining time
2057 TightConditionVariable<InversePredicate<int&> > cv(m_frameCond, InversePredicate<int&>(m_frameCount));
2058 cv.wait(lock,timeout);
2059 done = m_frameCount == 0;
2064 void CApplication::NewFrame()
2066 // We just posted another frame. Keep track and notify.
2068 CSingleLock lock(m_frameMutex);
2072 m_frameCond.notifyAll();
2075 void CApplication::Render()
2077 // do not render if we are stopped or in background
2078 if (m_bStop || m_bInBackground)
2083 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2085 bool decrement = false;
2086 bool hasRendered = false;
2087 bool limitFrames = false;
2088 unsigned int singleFrameTime = 10; // default limit 100 fps
2092 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2093 // Whether externalplayer is playing and we're unfocused
2094 bool extPlayerActive = m_eCurrentPlayer == EPC_EXTPLAYER && IsPlaying() && !m_AppFocused;
2096 m_bPresentFrame = false;
2097 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !IsPaused() && g_renderManager.RendererHandlesPresent())
2099 CSingleLock lock(m_frameMutex);
2101 TightConditionVariable<int&> cv(m_frameCond,m_frameCount);
2104 m_bPresentFrame = m_frameCount > 0;
2105 decrement = m_bPresentFrame;
2110 // engage the frame limiter as needed
2111 limitFrames = lowfps || extPlayerActive;
2112 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2113 // perhaps allowing it to be set differently than the UI option??
2114 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2115 limitFrames = true; // not using vsync.
2116 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2117 limitFrames = true; // using vsync, but it isn't working.
2121 if (extPlayerActive)
2123 ResetScreenSaver(); // Prevent screensaver dimming the screen
2124 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2127 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2134 CSingleLock lock(g_graphicsContext);
2135 g_infoManager.UpdateFPS();
2137 if (g_graphicsContext.IsFullScreenVideo() && IsPlaying() && vsync_mode == VSYNC_VIDEO)
2138 g_Windowing.SetVSync(true);
2139 else if (vsync_mode == VSYNC_ALWAYS)
2140 g_Windowing.SetVSync(true);
2141 else if (vsync_mode != VSYNC_DRIVER)
2142 g_Windowing.SetVSync(false);
2144 if(!g_Windowing.BeginRender())
2147 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2148 if (RenderNoPresent())
2151 g_Windowing.EndRender();
2153 // execute post rendering actions (finalize window closing)
2154 g_windowManager.AfterRender();
2156 // reset our info cache - we do this at the end of Render so that it is
2157 // fresh for the next process(), or after a windowclose animation (where process()
2159 g_infoManager.ResetCache();
2162 unsigned int now = XbmcThreads::SystemClockMillis();
2164 m_lastRenderTime = now;
2166 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2167 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2169 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2170 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2174 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2175 if (limitFrames || !flip)
2178 singleFrameTime = 40; //if not flipping, loop at 25 fps
2180 unsigned int frameTime = now - m_lastFrameTime;
2181 if (frameTime < singleFrameTime)
2182 Sleep(singleFrameTime - frameTime);
2184 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2187 g_graphicsContext.Flip(dirtyRegions);
2188 CTimeUtils::UpdateFrameTime(flip);
2190 g_renderManager.UpdateResolution();
2191 g_renderManager.ManageCaptures();
2194 CSingleLock lock(m_frameMutex);
2195 if(m_frameCount > 0 && decrement)
2198 m_frameCond.notifyAll();
2201 void CApplication::SetStandAlone(bool value)
2203 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2206 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2207 // The window manager will return true if the event is processed, false otherwise.
2208 // If not already processed, this routine handles global keypresses. It returns
2209 // true if the key has been processed, false otherwise.
2211 bool CApplication::OnKey(const CKey& key)
2214 // Turn the mouse off, as we've just got a keypress from controller or remote
2215 g_Mouse.SetActive(false);
2217 // get the current active window
2218 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2220 // this will be checked for certain keycodes that need
2221 // special handling if the screensaver is active
2222 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2224 // a key has been pressed.
2226 m_idleTimer.StartZero();
2227 bool processKey = AlwaysProcess(action);
2231 // allow some keys to be processed while the screensaver is active
2232 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2234 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2238 // change this if we have a dialog up
2239 if (g_windowManager.HasModalDialog())
2241 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2243 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2244 { // fullscreen info dialog - special case
2245 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2247 if (!key.IsAnalogButton())
2248 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2250 if (OnAction(action))
2253 // fallthrough to the main window
2254 iWin = WINDOW_FULLSCREEN_VIDEO;
2256 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2258 // current active window is full screen video.
2259 if (g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
2261 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2262 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2264 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2266 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2267 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2269 // if no PVR specific action/mapping is found, fall back to default
2270 if (action.GetID() == 0)
2271 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2275 // in any other case use the fullscreen window section of keymap.xml to map key->action
2276 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2281 // current active window isnt the fullscreen window
2282 // just use corresponding section from keymap.xml
2283 // to map key->action
2285 // first determine if we should use keyboard input directly
2286 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2287 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2290 CGUIControl *control = window->GetFocusedControl();
2293 // If this is an edit control set usekeyboard to true. This causes the
2294 // keypress to be processed directly not through the key mappings.
2295 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2298 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2299 // This causes the keypress to be used for list navigation.
2300 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2306 action = CAction(0); // reset our action
2307 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2309 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2310 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2311 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2312 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2313 action.GetID() == ACTION_MOVE_RIGHT ||
2314 action.GetID() == ACTION_MOVE_UP ||
2315 action.GetID() == ACTION_MOVE_DOWN ||
2316 action.GetID() == ACTION_SELECT_ITEM ||
2317 action.GetID() == ACTION_ENTER ||
2318 action.GetID() == ACTION_PREVIOUS_MENU ||
2319 action.GetID() == ACTION_NAV_BACK))
2321 // the action isn't plain navigation - check for a keyboard-specific keymap
2322 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2323 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2324 action.GetID() == ACTION_BACKSPACE ||
2325 action.GetID() == ACTION_SHIFT ||
2326 action.GetID() == ACTION_SYMBOLS ||
2327 action.GetID() == ACTION_CURSOR_LEFT ||
2328 action.GetID() == ACTION_CURSOR_RIGHT)
2329 action = CAction(0); // don't bother with this action
2332 if (!action.GetID())
2334 // keyboard entry - pass the keys through directly
2335 if (key.GetFromService())
2336 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2338 { // see if we've got an ascii key
2339 if (key.GetUnicode())
2340 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2342 action = CAction(key.GetVKey() | KEY_VKEY);
2346 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %i", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2348 if (OnAction(action))
2350 // failed to handle the keyboard action, drop down through to standard action
2352 if (key.GetFromService())
2354 if (key.GetButtonCode() != KEY_INVALID)
2355 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2358 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2360 if (!key.IsAnalogButton())
2361 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2363 return ExecuteInputAction(action);
2366 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2367 // This needs to return true if it processed the appcommand or false if it didn't
2368 bool CApplication::OnAppCommand(const CAction &action)
2370 // Reset the screen saver
2373 // If we were currently in the screen saver wake up and don't process the appcommand
2374 if (WakeUpScreenSaverAndDPMS())
2377 // The action ID is the APPCOMMAND code. We need to retrieve the action
2378 // associated with this appcommand from the mapping table.
2379 uint32_t appcmd = action.GetID();
2380 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2381 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2382 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2384 // If we couldn't find an action return false to indicate we have not
2385 // handled this appcommand
2386 if (!appcmdaction.GetID())
2388 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2392 // Process the appcommand
2393 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2394 OnAction(appcmdaction);
2396 // Always return true regardless of whether the action succeeded or not.
2397 // This stops Windows handling the appcommand itself.
2401 bool CApplication::OnAction(const CAction &action)
2403 // special case for switching between GUI & fullscreen mode.
2404 if (action.GetID() == ACTION_SHOW_GUI)
2405 { // Switch to fullscreen mode if we can
2406 if (SwitchToFullScreen())
2408 m_navigationTimer.StartZero();
2413 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2415 g_graphicsContext.ToggleFullScreenRoot();
2419 if (action.IsMouse())
2420 g_Mouse.SetActive(true);
2423 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2425 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2427 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2429 CGUIDialogVideoBookmarks::OnAddBookmark();
2432 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2433 // playing or ACTION_PLAYER_PLAY if we are not playing.
2434 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2437 return OnAction(CAction(ACTION_PAUSE));
2439 return OnAction(CAction(ACTION_PLAYER_PLAY));
2442 //if the action would start or stop inertial scrolling
2443 //by gesture - bypass the normal OnAction handler of current window
2444 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2447 // just pass the action to the current window and let it handle it
2448 if (g_windowManager.OnAction(action))
2450 m_navigationTimer.StartZero();
2455 // handle extra global presses
2457 // screenshot : take a screenshot :)
2458 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2460 CScreenShot::TakeScreenshot();
2463 // built in functions : execute the built-in
2464 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2466 CBuiltins::Execute(action.GetName());
2467 m_navigationTimer.StartZero();
2472 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2474 CButtonTranslator::GetInstance().Clear();
2475 CButtonTranslator::GetInstance().Load();
2478 // show info : Shows the current video or song information
2479 if (action.GetID() == ACTION_SHOW_INFO)
2481 g_infoManager.ToggleShowInfo();
2485 // codec info : Shows the current song, video or picture codec information
2486 if (action.GetID() == ACTION_SHOW_CODEC)
2488 g_infoManager.ToggleShowCodec();
2492 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && IsPlayingAudio())
2494 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2497 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2498 char rating = tag->GetRating();
2499 bool needsUpdate(false);
2500 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2502 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2505 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2507 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2513 if (db.Open()) // OpenForWrite() ?
2515 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2518 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2519 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2520 g_windowManager.SendMessage(msg);
2526 // stop : stops playing current audio song
2527 if (action.GetID() == ACTION_STOP)
2533 // previous : play previous song from playlist
2534 if (action.GetID() == ACTION_PREV_ITEM)
2536 // first check whether we're within 3 seconds of the start of the track
2537 // if not, we just revert to the start of the track
2538 if (m_pPlayer && m_pPlayer->CanSeek() && GetTime() > 3)
2545 g_playlistPlayer.PlayPrevious();
2550 // next : play next song from playlist
2551 if (action.GetID() == ACTION_NEXT_ITEM)
2553 if (IsPlaying() && m_pPlayer->SkipNext())
2559 g_playlistPlayer.PlayNext();
2564 // forward action to g_PVRManager and break if it was able to handle it
2565 if (g_PVRManager.OnAction(action))
2570 // forward channel switches to the player - he knows what to do
2571 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2573 m_pPlayer->OnAction(action);
2577 // pause : pauses current audio song
2578 if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1)
2582 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2584 if (!m_pPlayer->IsPaused())
2585 { // unpaused - set the playspeed back to normal
2588 g_audioManager.Enable(m_pPlayer->IsPaused());
2591 if (!m_pPlayer->IsPaused())
2593 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2594 // if we are playing at normal speed, then allow play to pause
2595 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2597 if (m_iPlaySpeed != 1)
2607 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2609 int iPlaySpeed = m_iPlaySpeed;
2610 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2612 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2614 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2619 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2621 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2624 SetPlaySpeed(iPlaySpeed);
2627 else if ((action.GetAmount() || GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2629 // calculate the speed based on the amount the button is held down
2630 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2631 // returns 0 -> MAX_FFWD_SPEED
2632 int iSpeed = 1 << iPower;
2633 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2635 g_application.SetPlaySpeed(iSpeed);
2637 CLog::Log(LOGDEBUG,"Resetting playspeed");
2641 // allow play to unpause
2644 if (action.GetID() == ACTION_PLAYER_PLAY)
2646 // unpause, and set the playspeed back to normal
2648 g_audioManager.Enable(m_pPlayer->IsPaused());
2650 g_application.SetPlaySpeed(1);
2655 if (m_playerController->OnAction(action))
2660 if (action.GetID() == ACTION_SWITCH_PLAYER)
2664 VECPLAYERCORES cores;
2665 CFileItem item(*m_itemCurrentFile.get());
2666 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2667 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2668 if(core != EPC_NONE)
2670 g_application.m_eForcedNextPlayer = core;
2671 item.m_lStartOffset = (int)(GetTime() * 75);
2672 PlayFile(item, true);
2677 VECPLAYERCORES cores;
2678 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2679 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2680 if(core != EPC_NONE)
2683 g_application.m_eForcedNextPlayer = core;
2684 PlayFile(item, false);
2689 if (g_peripherals.OnAction(action))
2692 if (action.GetID() == ACTION_MUTE)
2698 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2700 // we are only allowed to SetInt to a value supported in GUISettings, so we keep trying until it sticks
2701 int mode = CSettings::Get().GetInt("audiooutput.mode");
2702 for (int i = 0; i < 3; i++)
2706 CSettings::Get().SetInt("audiooutput.mode", mode);
2707 if (CSettings::Get().GetInt("audiooutput.mode") == mode)
2711 g_application.Restart();
2712 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2714 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2715 g_windowManager.SendMessage(msg);
2720 // Check for global volume control
2721 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2723 if (!m_pPlayer || !m_pPlayer->IsPassthrough())
2727 float volume = m_volumeLevel;
2728 // Android has steps based on the max available volume level
2729 #if defined(TARGET_ANDROID)
2730 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2732 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2734 if (action.GetRepeat())
2735 step *= action.GetRepeat() * 50; // 50 fps
2737 if (action.GetID() == ACTION_VOLUME_UP)
2738 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2740 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2741 SetVolume(volume, false);
2743 // show visual feedback of volume change...
2744 ShowVolumeBar(&action);
2747 // Check for global seek control
2748 if (IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2750 if (!m_pPlayer->CanSeek()) return false;
2751 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2754 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2756 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2757 CGUIControlProfiler::Instance().Start();
2760 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2762 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2763 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2764 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2765 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2766 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2772 void CApplication::FrameMove(bool processEvents, bool processGUI)
2778 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2779 float frameTime = m_frameTime.GetElapsedSeconds();
2780 m_frameTime.StartZero();
2781 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2782 if( frameTime > 0.5 ) frameTime = 0.5;
2784 if (processGUI && m_renderGUI)
2786 g_graphicsContext.Lock();
2787 // check if there are notifications to display
2788 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2789 if (toast && toast->DoWork())
2791 if (!toast->IsDialogRunning())
2796 g_graphicsContext.Unlock();
2798 CWinEvents::MessagePump();
2800 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2801 // Read the input from a remote
2802 g_RemoteControl.Update();
2805 // process input actions
2806 ProcessRemote(frameTime);
2807 ProcessGamepad(frameTime);
2808 ProcessEventServer(frameTime);
2809 ProcessPeripherals(frameTime);
2810 if (processGUI && m_renderGUI)
2812 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2813 m_seekHandler->Process();
2816 if (processGUI && m_renderGUI)
2819 g_windowManager.Process(CTimeUtils::GetFrameTime());
2820 g_windowManager.FrameMove();
2824 bool CApplication::ProcessGamepad(float frameTime)
2826 #ifdef HAS_SDL_JOYSTICK
2830 int iWin = GetActiveWindowID();
2832 g_Joystick.Update();
2833 if (g_Joystick.GetButton(bid))
2836 m_idleTimer.StartZero();
2839 if (WakeUpScreenSaverAndDPMS())
2841 g_Joystick.Reset(true);
2846 CStdString actionName;
2848 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2850 CAction action(actionID, 1.0f, 0.0f, actionName);
2852 g_Mouse.SetActive(false);
2853 return ExecuteInputAction(action);
2860 if (g_Joystick.GetAxis(bid))
2862 if (g_Joystick.GetAmount() < 0)
2868 CStdString actionName;
2870 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2873 if (WakeUpScreenSaverAndDPMS())
2878 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2880 g_Mouse.SetActive(false);
2881 return ExecuteInputAction(action);
2885 g_Joystick.ResetAxis(abs(bid));
2889 if (g_Joystick.GetHat(bid, position))
2892 m_idleTimer.StartZero();
2895 if (WakeUpScreenSaverAndDPMS())
2902 CStdString actionName;
2905 bid = position<<16|bid;
2907 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2909 CAction action(actionID, 1.0f, 0.0f, actionName);
2911 g_Mouse.SetActive(false);
2912 return ExecuteInputAction(action);
2919 bool CApplication::ProcessRemote(float frameTime)
2921 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2922 if (g_RemoteControl.GetButton())
2924 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2925 g_RemoteControl.Reset();
2932 bool CApplication::ProcessPeripherals(float frameTime)
2935 if (g_peripherals.GetNextKeypress(frameTime, key))
2940 bool CApplication::ProcessMouse()
2944 if (!g_Mouse.IsActive() || !m_AppFocused)
2947 // Get the mouse command ID
2948 uint32_t mousecommand = g_Mouse.GetAction();
2949 if (mousecommand == ACTION_NOOP)
2952 // Reset the screensaver and idle timers
2953 m_idleTimer.StartZero();
2955 if (WakeUpScreenSaverAndDPMS())
2958 // Retrieve the corresponding action
2959 int iWin = GetActiveWindowID();
2960 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2961 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2963 // Deactivate mouse if non-mouse action
2964 if (!mouseaction.IsMouse())
2965 g_Mouse.SetActive(false);
2967 // Consume ACTION_NOOP.
2968 // Some views or dialogs gets closed after any ACTION and
2969 // a sensitive mouse might cause problems.
2970 if (mouseaction.GetID() == ACTION_NOOP)
2973 // If we couldn't find an action return false to indicate we have not
2974 // handled this mouse action
2975 if (!mouseaction.GetID())
2977 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
2981 // Log mouse actions except for move and noop
2982 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
2983 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
2985 // The action might not be a mouse action. For example wheel moves might
2986 // be mapped to volume up/down in mouse.xml. In this case we do not want
2987 // the mouse position saved in the action.
2988 if (!mouseaction.IsMouse())
2989 return OnAction(mouseaction);
2991 // This is a mouse action so we need to record the mouse position
2992 return OnAction(CAction(mouseaction.GetID(),
2993 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
2994 (float)g_Mouse.GetX(),
2995 (float)g_Mouse.GetY(),
2996 (float)g_Mouse.GetDX(),
2997 (float)g_Mouse.GetDY(),
2998 mouseaction.GetName()));
3001 bool CApplication::ProcessEventServer(float frameTime)
3003 #ifdef HAS_EVENT_SERVER
3004 CEventServer* es = CEventServer::GetInstance();
3005 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3008 // process any queued up actions
3009 if (es->ExecuteNextAction())
3011 // reset idle timers
3012 m_idleTimer.StartZero();
3014 WakeUpScreenSaverAndDPMS();
3017 // now handle any buttons or axis
3018 std::string joystickName;
3019 bool isAxis = false;
3020 float fAmount = 0.0;
3022 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3023 // when the action exits XBMC
3024 es = CEventServer::GetInstance();
3025 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3027 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3031 if (joystickName.length() > 0)
3035 if (fabs(fAmount) >= 0.08)
3036 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3038 m_lastAxisMap[joystickName].erase(wKeyID);
3041 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
3046 if (wKeyID & ES_FLAG_UNICODE)
3048 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3052 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3053 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3054 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3055 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3056 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3057 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3058 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3059 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3060 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3061 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3062 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3063 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3064 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3065 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3066 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3067 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3068 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3069 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3070 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3071 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3074 key.SetFromService(true);
3079 if (m_lastAxisMap.size() > 0)
3081 // Process all the stored axis.
3082 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3084 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3085 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3091 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3092 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3098 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount, unsigned int holdTime /*=0*/)
3100 #if defined(HAS_EVENT_SERVER)
3101 m_idleTimer.StartZero();
3103 // Make sure to reset screen saver, mouse.
3105 if (WakeUpScreenSaverAndDPMS())
3108 #ifdef HAS_SDL_JOYSTICK
3111 g_Mouse.SetActive(false);
3113 int iWin = GetActiveWindowID();
3115 CStdString actionName;
3116 bool fullRange = false;
3118 // Translate using regular joystick translator.
3119 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3120 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3122 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3128 bool CApplication::ExecuteInputAction(const CAction &action)
3130 bool bResult = false;
3132 // play sound before the action unless the button is held,
3133 // where we execute after the action as held actions aren't fired every time.
3134 if(action.GetHoldTime())
3136 bResult = OnAction(action);
3138 g_audioManager.PlayActionSound(action);
3142 g_audioManager.PlayActionSound(action);
3143 bResult = OnAction(action);
3148 int CApplication::GetActiveWindowID(void)
3150 // Get the currently active window
3151 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3153 // If there is a dialog active get the dialog id instead
3154 if (g_windowManager.HasModalDialog())
3155 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3157 // If the window is FullScreenVideo check for special cases
3158 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3160 // check if we're in a DVD menu
3161 if(g_application.m_pPlayer && g_application.m_pPlayer->IsInMenu())
3162 iWin = WINDOW_VIDEO_MENU;
3163 // check for LiveTV and switch to it's virtual window
3164 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3165 iWin = WINDOW_FULLSCREEN_LIVETV;
3168 // Return the window id
3172 bool CApplication::Cleanup()
3176 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3177 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3178 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3179 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3180 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3181 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3182 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3183 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3184 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3185 g_windowManager.Delete(WINDOW_FILES);
3186 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3187 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3188 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3189 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3190 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3191 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3192 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3193 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3194 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3195 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3196 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3197 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3198 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3199 g_windowManager.Delete(WINDOW_DIALOG_OK);
3200 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3201 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3202 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3203 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3204 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3205 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3206 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3207 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3208 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3209 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3210 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3211 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3212 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3213 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3214 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3215 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3216 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3217 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3218 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3219 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3220 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3221 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3223 /* Delete PVR related windows and dialogs */
3224 g_windowManager.Delete(WINDOW_PVR);
3225 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3226 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3227 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3228 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3229 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3230 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3231 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3232 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3233 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3234 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3235 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3236 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3237 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3239 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3240 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3241 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3242 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3243 g_windowManager.Delete(WINDOW_VISUALISATION);
3244 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3245 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3246 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3247 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3248 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3249 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3250 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3251 g_windowManager.Delete(WINDOW_SCREENSAVER);
3252 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3253 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3254 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3255 g_windowManager.Delete(WINDOW_SLIDESHOW);
3256 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3257 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3259 g_windowManager.Delete(WINDOW_HOME);
3260 g_windowManager.Delete(WINDOW_PROGRAMS);
3261 g_windowManager.Delete(WINDOW_PICTURES);
3262 g_windowManager.Delete(WINDOW_WEATHER);
3264 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3265 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3266 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3267 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3268 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3269 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3270 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3271 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3272 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3273 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3275 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3276 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3278 CAddonMgr::Get().DeInit();
3280 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3281 CLog::Log(LOGNOTICE, "closing down remote control service");
3282 g_RemoteControl.Disconnect();
3285 CLog::Log(LOGNOTICE, "unload sections");
3287 #ifdef HAS_PERFORMANCE_SAMPLE
3288 CLog::Log(LOGNOTICE, "performance statistics");
3289 m_perfStats.DumpStats();
3292 // Shutdown as much as possible of the
3293 // application, to reduce the leaks dumped
3294 // to the vc output window before calling
3295 // _CrtDumpMemoryLeaks(). Most of the leaks
3296 // shown are no real leaks, as parts of the app
3297 // are still allocated.
3299 g_localizeStrings.Clear();
3300 g_LangCodeExpander.Clear();
3301 g_charsetConverter.clear();
3302 g_directoryCache.Clear();
3303 CButtonTranslator::GetInstance().Clear();
3304 #ifdef HAS_EVENT_SERVER
3305 CEventServer::RemoveInstance();
3307 DllLoaderContainer::Clear();
3308 g_playlistPlayer.Clear();
3309 CSettings::Get().Uninitialize();
3310 g_advancedSettings.Clear();
3313 CXHandle::DumpObjectTracker();
3315 #ifdef HAS_DVD_DRIVE
3316 CLibcdio::ReleaseInstance();
3319 #if defined(TARGET_ANDROID)
3320 // enable for all platforms once it's safe
3321 g_sectionLoader.UnloadAll();
3323 #ifdef _CRTDBG_MAP_ALLOC
3324 _CrtDumpMemoryLeaks();
3325 while(1); // execution ends
3335 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3340 void CApplication::Stop(int exitCode)
3344 CVariant vExitCode(exitCode);
3345 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3347 SaveFileState(true);
3349 // cancel any jobs from the jobmanager
3350 CJobManager::GetInstance().CancelJobs();
3352 g_alarmClock.StopThread();
3354 if( m_bSystemScreenSaverEnable )
3355 g_Windowing.EnableSystemScreenSaver(true);
3357 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3358 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3360 // Update the settings information (volume, uptime etc. need saving)
3361 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3363 CLog::Log(LOGNOTICE, "Saving settings");
3364 CSettings::Get().Save();
3367 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3370 m_AppFocused = false;
3371 m_ExitCode = exitCode;
3372 CLog::Log(LOGNOTICE, "stop all");
3374 // stop scanning before we kill the network and so on
3375 if (m_musicInfoScanner->IsScanning())
3376 m_musicInfoScanner->Stop();
3378 if (m_videoInfoScanner->IsScanning())
3379 m_videoInfoScanner->Stop();
3381 CApplicationMessenger::Get().Cleanup();
3389 CLog::Log(LOGNOTICE, "stop player");
3391 m_pPlayer->CloseFile();
3395 #if HAS_FILESYTEM_DAAP
3396 CLog::Log(LOGNOTICE, "stop daap clients");
3397 g_DaapClient.Release();
3399 #ifdef HAS_FILESYSTEM_SAP
3400 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3401 g_sapsessions.StopThread();
3404 if(CZeroconfBrowser::IsInstantiated())
3406 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3407 CZeroconfBrowser::GetInstance()->Stop();
3408 CZeroconfBrowser::ReleaseInstance();
3412 CLog::Log(LOGNOTICE, "clean cached files!");
3413 #ifdef HAS_FILESYSTEM_RAR
3414 g_RarManager.ClearCache(true);
3417 #ifdef HAS_FILESYSTEM_SFTP
3418 CSFTPSessionManager::DisconnectAllSessions();
3421 CLog::Log(LOGNOTICE, "unload skin");
3424 #if defined(TARGET_DARWIN_OSX)
3425 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3426 XBMCHelper::GetInstance().Stop();
3429 #if defined(HAVE_LIBCRYSTALHD)
3430 CCrystalHD::RemoveInstance();
3433 g_mediaManager.Stop();
3435 // Stop services before unloading Python
3436 CAddonMgr::Get().StopServices(false);
3438 /* Python resource freeing must be done after skin has been unloaded, not before
3439 some windows still need it when deinitializing during skin unloading. */
3441 CLog::Log(LOGNOTICE, "stop python");
3442 g_pythonParser.FreeResources();
3444 g_Windowing.DestroyRenderSystem();
3445 g_Windowing.DestroyWindow();
3446 g_Windowing.DestroyWindowSystem();
3448 // shutdown the AudioEngine
3449 CAEFactory::Shutdown();
3450 CAEFactory::UnLoadEngine();
3452 CLog::Log(LOGNOTICE, "stopped");
3456 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3459 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3460 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3467 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3469 //If item is a plugin, expand out now and run ourselves again
3470 if (item.IsPlugin())
3472 CFileItem item_new(item);
3473 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3474 return PlayMedia(item_new, iPlaylist);
3477 if (item.IsSmartPlayList())
3479 CFileItemList items;
3480 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3483 CSmartPlaylist smartpl;
3484 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3485 smartpl.OpenAndReadName(item.GetPath());
3487 playlist.Add(items);
3488 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3491 else if (item.IsPlayList() || item.IsInternetStream())
3493 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3495 //is or could be a playlist
3496 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3497 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3502 if (dlgCache->IsCanceled())
3509 if (iPlaylist != PLAYLIST_NONE)
3512 if (item.HasProperty("playlist_starting_track"))
3513 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3514 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3518 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());
3519 if(pPlayList->size())
3520 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3525 //nothing special just play
3526 return PlayFile(item, false) == PLAYBACK_OK;
3530 // For playing a multi-file video. Particularly inefficient
3531 // on startup, as we are required to calculate the length
3532 // of each video, so we open + close each one in turn.
3533 // A faster calculation of video time would improve this
3535 // return value: same with PlayFile()
3536 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3538 if (!item.IsStack())
3539 return PLAYBACK_FAIL;
3543 // case 1: stacked ISOs
3544 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3546 CStackDirectory dir;
3547 CFileItemList movieList;
3548 dir.GetDirectory(item.GetPath(), movieList);
3550 // first assume values passed to the stack
3551 int selectedFile = item.m_lStartPartNumber;
3552 int startoffset = item.m_lStartOffset;
3554 // check if we instructed the stack to resume from default
3555 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3560 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3562 startoffset = (int)(bookmark.timeInSeconds*75);
3563 selectedFile = bookmark.partNumber;
3568 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3571 // make sure that the selected part is within the boundaries
3572 if (selectedFile <= 0)
3574 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3577 else if (selectedFile > movieList.Size())
3579 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3580 selectedFile = movieList.Size();
3583 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3584 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3585 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3586 *m_stackFileItemToUpdate = item;
3587 return PlayFile(*(movieList[selectedFile - 1]));
3589 // case 2: all other stacks
3592 // see if we have the info in the database
3593 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3594 // then these times will be wrong.
3595 // Also, this is really just a hack for the slow load up times we have
3596 // A much better solution is a fast reader of FPS and fileLength
3597 // that we can use on a file to get it's time.
3599 bool haveTimes(false);
3603 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3604 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3609 // calculate the total time of the stack
3610 CStackDirectory dir;
3611 dir.GetDirectory(item.GetPath(), *m_currentStack);
3613 for (int i = 0; i < m_currentStack->Size(); i++)
3616 (*m_currentStack)[i]->m_lEndOffset = times[i];
3620 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3622 m_currentStack->Clear();
3623 return PLAYBACK_FAIL;
3625 totalTime += duration / 1000;
3626 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3627 times.push_back(totalTime);
3631 double seconds = item.m_lStartOffset / 75.0;
3633 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3634 { // have our times now, so update the dB
3638 dbs.SetStackTimes(item.GetPath(), times);
3640 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3642 // can only resume seek here, not dvdstate
3644 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3645 seconds = bookmark.timeInSeconds;
3653 *m_itemCurrentFile = item;
3654 m_currentStackPosition = 0;
3655 m_eCurrentPlayer = EPC_NONE; // must be reset on initial play otherwise last player will be used
3659 // work out where to seek to
3660 for (int i = 0; i < m_currentStack->Size(); i++)
3662 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3664 CFileItem item(*(*m_currentStack)[i]);
3665 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3666 item.m_lStartOffset = (long)(seconds - start) * 75;
3667 m_currentStackPosition = i;
3668 return PlayFile(item, true);
3673 return PlayFile(*(*m_currentStack)[0], true);
3675 return PLAYBACK_FAIL;
3678 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3682 SaveCurrentFileSettings();
3684 OutputDebugString("new file set audiostream:0\n");
3685 // Switch to default options
3686 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3687 // see if we have saved options in the database
3690 m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3692 *m_itemCurrentFile = item;
3693 m_nextPlaylistItem = -1;
3694 m_currentStackPosition = 0;
3695 m_currentStack->Clear();
3698 CUtil::ClearSubtitles();
3701 if (item.IsDiscStub())
3703 #ifdef HAS_DVD_DRIVE
3704 // Display the Play Eject dialog if there is any optical disc drive
3705 if (g_mediaManager.HasOpticalDrive())
3707 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3708 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3709 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3710 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3714 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3719 if (item.IsPlayList())
3720 return PLAYBACK_FAIL;
3722 if (item.IsPlugin())
3723 { // we modify the item so that it becomes a real URL
3724 CFileItem item_new(item);
3725 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3726 return PlayFile(item_new, false);
3727 return PLAYBACK_FAIL;
3731 if (URIUtils::IsUPnP(item.GetPath()))
3733 CFileItem item_new(item);
3734 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3735 return PlayFile(item_new, false);
3736 return PLAYBACK_FAIL;
3740 // if we have a stacked set of files, we need to setup our stack routines for
3741 // "seamless" seeking and total time of the movie etc.
3742 // will recall with restart set to true
3744 return PlayStack(item, bRestart);
3746 //Is TuxBox, this should probably be moved to CTuxBoxFile
3749 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3751 if(g_tuxboxService.IsRunning())
3752 g_tuxboxService.Stop();
3754 PlayBackRet ret = PLAYBACK_FAIL;
3756 if(g_tuxbox.CreateNewItem(item, item_new))
3759 // Make sure it doesn't have a player
3760 // so we actually select one normally
3761 m_eCurrentPlayer = EPC_NONE;
3763 // keep the tuxbox:// url as playing url
3764 // and give the new url to the player
3765 ret = PlayFile(item_new, true);
3766 if(ret == PLAYBACK_OK)
3768 if(!g_tuxboxService.IsRunning())
3769 g_tuxboxService.Start();
3775 CPlayerOptions options;
3777 if( item.HasProperty("StartPercent") )
3779 double fallback = 0.0f;
3780 if(item.GetProperty("StartPercent").isString())
3781 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3782 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3785 PLAYERCOREID eNewCore = EPC_NONE;
3788 // have to be set here due to playstack using this for starting the file
3789 options.starttime = item.m_lStartOffset / 75.0;
3790 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3791 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3793 if( m_eForcedNextPlayer != EPC_NONE )
3794 eNewCore = m_eForcedNextPlayer;
3795 else if( m_eCurrentPlayer == EPC_NONE )
3796 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3798 eNewCore = m_eCurrentPlayer;
3802 options.starttime = item.m_lStartOffset / 75.0;
3806 // open the d/b and retrieve the bookmarks for the current movie
3809 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3811 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3813 options.starttime = 0.0f;
3815 CStdString path = item.GetPath();
3816 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3817 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3818 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3819 path = item.GetProperty("original_listitem_url").asString();
3820 if(dbs.GetResumeBookMark(path, bookmark))
3822 options.starttime = bookmark.timeInSeconds;
3823 options.state = bookmark.playerState;
3826 override with information from the actual item if available. We do this as the VFS (eg plugins)
3827 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3828 should the playerState be required, it is fetched from the database.
3829 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3831 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3832 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3834 else if (item.HasVideoInfoTag())
3836 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3838 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3841 dbs.GetBookMarkForEpisode(*tag, bookmark);
3842 options.starttime = bookmark.timeInSeconds;
3843 options.state = bookmark.playerState;
3850 if (m_eForcedNextPlayer != EPC_NONE)
3851 eNewCore = m_eForcedNextPlayer;
3853 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3856 // this really aught to be inside !bRestart, but since PlayStack
3857 // uses that to init playback, we have to keep it outside
3858 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3859 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3860 { // playing from a playlist by the looks
3861 // don't switch to fullscreen if we are not playing the first item...
3862 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3864 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3866 // TODO - this will fail if user seeks back to first file in stack
3867 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3868 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3870 options.fullscreen = false;
3871 // reset this so we don't think we are resuming on seek
3872 m_itemCurrentFile->m_lStartOffset = 0;
3875 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3877 // reset VideoStartWindowed as it's a temp setting
3878 CMediaSettings::Get().SetVideoStartWindowed(false);
3881 //We have to stop parsing a cdg before mplayer is deallocated
3882 // WHY do we have to do this????
3884 m_pKaraokeMgr->Stop();
3888 CSingleLock lock(m_playStateMutex);
3889 // tell system we are starting a file
3890 m_bPlaybackStarting = true;
3892 // for playing a new item, previous playing item's callback may already
3893 // pushed some delay message into the threadmessage list, they are not
3894 // expected be processed after or during the new item playback starting.
3895 // so we clean up previous playing item's playback callback delay messages here.
3896 int previousMsgsIgnoredByNewPlaying[] = {
3897 GUI_MSG_PLAYBACK_STARTED,
3898 GUI_MSG_PLAYBACK_ENDED,
3899 GUI_MSG_PLAYBACK_STOPPED,
3900 GUI_MSG_PLAYLIST_CHANGED,
3901 GUI_MSG_PLAYLISTPLAYER_STOPPED,
3902 GUI_MSG_PLAYLISTPLAYER_STARTED,
3903 GUI_MSG_PLAYLISTPLAYER_CHANGED,
3904 GUI_MSG_QUEUE_NEXT_ITEM,
3907 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
3909 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
3912 // We should restart the player, unless the previous and next tracks are using
3913 // one of the players that allows gapless playback (paplayer, dvdplayer)
3916 if ( !(m_eCurrentPlayer == eNewCore && (m_eCurrentPlayer == EPC_DVDPLAYER || m_eCurrentPlayer == EPC_PAPLAYER
3917 #if defined(HAS_OMXPLAYER)
3918 || m_eCurrentPlayer == EPC_OMXPLAYER
3923 m_pPlayer->CloseFile();
3928 // XXX: we had to stop the previous playing item, it was done in dvdplayer::OpenFile.
3929 // but in paplayer::OpenFile, it sometimes just fade in without call CloseFile.
3930 // but if we do not stop it, we can not distingush callbacks from previous
3931 // item and current item, it will confused us then we can not make correct delay
3932 // callback after the starting state.
3934 m_pPlayer->CloseFile();
3938 // now reset play state to starting, since we already stopped the previous playing item if there is.
3939 // and from now there should be no playback callback from previous playing item be called.
3940 m_ePlayState = PLAY_STATE_STARTING;
3944 m_eCurrentPlayer = eNewCore;
3945 m_pPlayer.reset(CPlayerCoreFactory::Get().CreatePlayer(eNewCore, *this));
3948 PlayBackRet iResult;
3951 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
3952 * This should speed up player startup for files on internet filesystems (eg. webdav) and
3953 * increase performance on low powered systems (Atom/ARM).
3957 CJobManager::GetInstance().Pause(CJob::PRIORITY_LOW); // Pause any low priority jobs
3960 // don't hold graphicscontext here since player
3961 // may wait on another thread, that requires gfx
3962 CSingleExit ex(g_graphicsContext);
3963 // In busy dialog of OpenFile there's a chance to call another place delete the player
3964 // e.g. another PlayFile call switch player.
3965 // Here we use a holdPlace to keep the player not be deleted during OpenFile call
3966 boost::shared_ptr<IPlayer> holdPlace(m_pPlayer);
3967 // op seq for detect cancel (CloseFile be called or OpenFile be called again) during OpenFile.
3968 unsigned int startingSeq = ++m_iPlayerOPSeq;
3970 iResult = m_pPlayer->OpenFile(item, options) ? PLAYBACK_OK : PLAYBACK_FAIL;
3971 // check whether the OpenFile was canceled by either CloseFile or another OpenFile.
3972 if (m_iPlayerOPSeq != startingSeq)
3973 iResult = PLAYBACK_CANCELED;
3977 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3978 iResult = PLAYBACK_FAIL;
3981 if(iResult == PLAYBACK_OK)
3983 if (m_iPlaySpeed != 1)
3985 int iSpeed = m_iPlaySpeed;
3987 SetPlaySpeed(iSpeed);
3990 // if player has volume control, set it.
3991 if (m_pPlayer && m_pPlayer->ControlsVolume())
3993 m_pPlayer->SetVolume(m_volumeLevel);
3994 m_pPlayer->SetMute(m_muted);
3997 if( IsPlayingAudio() )
3999 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4000 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4003 #ifdef HAS_VIDEO_PLAYBACK
4004 else if( IsPlayingVideo() )
4006 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4007 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4009 // if player didn't manange to switch to fullscreen by itself do it here
4010 if( options.fullscreen && g_renderManager.IsStarted()
4011 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4012 SwitchToFullScreen();
4017 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4018 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4019 g_windowManager.PreviousWindow();
4023 #if !defined(TARGET_DARWIN) && !defined(_LINUX)
4024 g_audioManager.Enable(false);
4027 if (item.HasPVRChannelInfoTag())
4028 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4031 CSingleLock lock(m_playStateMutex);
4032 m_bPlaybackStarting = false;
4034 if (iResult == PLAYBACK_OK)
4036 // play state: none, starting; playing; stopped; ended.
4037 // last 3 states are set by playback callback, they are all ignored during starting,
4038 // but we recorded the state, here we can make up the callback for the state.
4039 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4040 switch (m_ePlayState)
4042 case PLAY_STATE_PLAYING:
4043 OnPlayBackStarted();
4045 // FIXME: it seems no meaning to callback started here if there was an started callback
4046 // before this stopped/ended callback we recorded. if we callback started here
4047 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4048 // which will send OnStop announce at once, so currently, just call stopped/ended.
4049 case PLAY_STATE_ENDED:
4052 case PLAY_STATE_STOPPED:
4053 OnPlayBackStopped();
4055 case PLAY_STATE_STARTING:
4056 // neither started nor stopped/ended callback be called, that means the item still
4057 // not started, we need not make up any callback, just leave this and
4058 // let the player callback do its work.
4064 else if (iResult == PLAYBACK_FAIL)
4066 // we send this if it isn't playlistplayer that is doing this
4067 int next = g_playlistPlayer.GetNextSong();
4068 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4071 OnPlayBackStopped();
4072 m_ePlayState = PLAY_STATE_NONE;
4078 void CApplication::OnPlayBackEnded()
4080 CSingleLock lock(m_playStateMutex);
4081 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4082 m_ePlayState = PLAY_STATE_ENDED;
4083 if(m_bPlaybackStarting)
4086 // informs python script currently running playback has ended
4087 // (does nothing if python is not loaded)
4089 g_pythonParser.OnPlayBackEnded();
4092 CVariant data(CVariant::VariantTypeObject);
4094 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4096 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4097 g_windowManager.SendThreadMessage(msg);
4100 void CApplication::OnPlayBackStarted()
4102 CSingleLock lock(m_playStateMutex);
4103 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4104 m_ePlayState = PLAY_STATE_PLAYING;
4105 if(m_bPlaybackStarting)
4109 // informs python script currently running playback has started
4110 // (does nothing if python is not loaded)
4111 g_pythonParser.OnPlayBackStarted();
4114 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4115 g_windowManager.SendThreadMessage(msg);
4118 void CApplication::OnQueueNextItem()
4120 CSingleLock lock(m_playStateMutex);
4121 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4122 if(m_bPlaybackStarting)
4124 // informs python script currently running that we are requesting the next track
4125 // (does nothing if python is not loaded)
4127 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4130 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4131 g_windowManager.SendThreadMessage(msg);
4134 void CApplication::OnPlayBackStopped()
4136 CSingleLock lock(m_playStateMutex);
4137 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4138 m_ePlayState = PLAY_STATE_STOPPED;
4139 if(m_bPlaybackStarting)
4142 // informs python script currently running playback has ended
4143 // (does nothing if python is not loaded)
4145 g_pythonParser.OnPlayBackStopped();
4148 CVariant data(CVariant::VariantTypeObject);
4149 data["end"] = false;
4150 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4152 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4153 g_windowManager.SendThreadMessage(msg);
4156 void CApplication::OnPlayBackPaused()
4159 g_pythonParser.OnPlayBackPaused();
4163 param["player"]["speed"] = 0;
4164 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4165 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4168 void CApplication::OnPlayBackResumed()
4171 g_pythonParser.OnPlayBackResumed();
4175 param["player"]["speed"] = 1;
4176 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4177 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4180 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4183 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4187 param["player"]["speed"] = iSpeed;
4188 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4189 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4192 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4195 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4199 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4200 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4201 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4202 param["player"]["speed"] = GetPlaySpeed();
4203 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4204 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4207 void CApplication::OnPlayBackSeekChapter(int iChapter)
4210 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4214 bool CApplication::IsPlaying() const
4218 if (!m_pPlayer->IsPlaying())
4223 bool CApplication::IsPaused() const
4227 if (!m_pPlayer->IsPlaying())
4229 return m_pPlayer->IsPaused();
4232 bool CApplication::IsPlayingAudio() const
4236 if (!m_pPlayer->IsPlaying())
4238 if (m_pPlayer->HasVideo())
4240 if (m_pPlayer->HasAudio())
4245 bool CApplication::IsPlayingVideo() const
4249 if (!m_pPlayer->IsPlaying())
4251 if (m_pPlayer->HasVideo())
4257 bool CApplication::IsPlayingFullScreenVideo() const
4259 return IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4262 bool CApplication::IsFullScreen()
4264 return IsPlayingFullScreenVideo() ||
4265 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4266 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4269 void CApplication::SaveFileState(bool bForeground /* = false */)
4271 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4276 CSaveFileStateJob job(*m_progressTrackingItem,
4277 *m_stackFileItemToUpdate,
4278 m_progressTrackingVideoResumeBookmark,
4279 m_progressTrackingPlayCountUpdate);
4281 // Run job in the foreground to make sure it finishes
4286 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4287 *m_stackFileItemToUpdate,
4288 m_progressTrackingVideoResumeBookmark,
4289 m_progressTrackingPlayCountUpdate);
4290 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4294 void CApplication::UpdateFileState()
4296 // Did the file change?
4297 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4301 // Reset tracking item
4302 m_progressTrackingItem->Reset();
4308 if (m_progressTrackingItem->GetPath() == "")
4311 *m_progressTrackingItem = CurrentFileItem();
4312 m_progressTrackingPlayCountUpdate = false;
4315 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4316 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4317 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4318 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4320 m_progressTrackingPlayCountUpdate = true;
4323 // Check whether we're *really* playing video else we may race when getting eg. stream details
4324 if (IsPlayingVideo())
4326 /* Always update streamdetails, except for DVDs where we only update
4327 streamdetails if title length > 15m (Should yield more correct info) */
4328 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4330 CStreamDetails details;
4331 // Update with stream details from player, if any
4332 if (m_pPlayer->GetStreamDetails(details))
4333 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4336 // Update bookmark for save
4337 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_eCurrentPlayer);
4338 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4339 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4341 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4342 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4344 // Delete the bookmark
4345 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4348 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4350 // Update the bookmark
4351 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4352 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4357 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4364 void CApplication::StopPlaying()
4366 int iWin = g_windowManager.GetActiveWindow();
4371 m_pKaraokeMgr->Stop();
4374 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4375 g_PVRManager.SaveCurrentChannelSettings();
4380 m_pPlayer->CloseFile();
4383 // turn off visualisation window when stopping
4384 if ((iWin == WINDOW_VISUALISATION
4385 || iWin == WINDOW_FULLSCREEN_VIDEO)
4387 g_windowManager.PreviousWindow();
4389 g_partyModeManager.Disable();
4393 void CApplication::ResetSystemIdleTimer()
4395 // reset system idle timer
4396 m_idleTimer.StartZero();
4399 void CApplication::ResetScreenSaver()
4402 m_shutdownTimer.StartZero();
4404 // screen saver timer is reset only if we're not already in screensaver or
4406 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4407 ResetScreenSaverTimer();
4410 void CApplication::ResetScreenSaverTimer()
4412 m_screenSaverTimer.StartZero();
4415 void CApplication::StopScreenSaverTimer()
4417 m_screenSaverTimer.Stop();
4420 bool CApplication::ToggleDPMS(bool manual)
4422 if (manual || (m_dpmsIsManual == manual))
4426 m_dpmsIsActive = false;
4427 m_dpmsIsManual = false;
4428 return m_dpms->DisablePowerSaving();
4432 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4434 m_dpmsIsActive = true;
4435 m_dpmsIsManual = manual;
4443 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4447 // First reset DPMS, if active
4452 // TODO: if screensaver lock is specified but screensaver is not active
4453 // (DPMS came first), activate screensaver now.
4455 ResetScreenSaverTimer();
4456 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4459 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4463 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4464 CVariant data(bPowerOffKeyPressed);
4465 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4471 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4473 if (m_iScreenSaveLock == 2)
4476 // if Screen saver is active
4477 if (m_bScreenSave && m_screenSaver)
4479 if (m_iScreenSaveLock == 0)
4480 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4481 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4482 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4483 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4485 m_iScreenSaveLock = 2;
4486 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4488 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4490 pWindow->OnMessage(msg);
4492 if (m_iScreenSaveLock == -1)
4494 m_iScreenSaveLock = 0;
4498 // disable screensaver
4499 m_bScreenSave = false;
4500 m_iScreenSaveLock = 0;
4501 ResetScreenSaverTimer();
4503 if (m_screenSaver->ID() == "visualization")
4505 // we can just continue as usual from vis mode
4508 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4510 else if (!m_screenSaver->ID().IsEmpty())
4511 { // we're in screensaver window
4512 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4513 g_windowManager.PreviousWindow(); // show the previous window
4514 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4515 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4523 void CApplication::CheckScreenSaverAndDPMS()
4525 if (m_bInBackground)
4527 if (!m_dpmsIsActive)
4528 g_Windowing.ResetOSScreensaver();
4530 bool maybeScreensaver =
4531 !m_dpmsIsActive && !m_bScreenSave
4532 && !CSettings::Get().GetString("screensaver.mode").empty();
4534 !m_dpmsIsActive && m_dpms->IsSupported()
4535 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4537 // Has the screen saver window become active?
4538 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4540 m_bScreenSave = true;
4541 maybeScreensaver = false;
4544 if (m_bScreenSave && IsPlayingVideo() && !m_pPlayer->IsPaused())
4546 WakeUpScreenSaverAndDPMS();
4550 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4552 // See if we need to reset timer.
4553 // * Are we playing a video and it is not paused?
4554 if ((IsPlayingVideo() && !m_pPlayer->IsPaused())
4555 // * Are we playing some music in fullscreen vis?
4556 || (IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4557 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4559 ResetScreenSaverTimer();
4563 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4565 // DPMS has priority (it makes the screensaver not needed)
4567 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4570 WakeUpScreenSaver();
4572 else if (maybeScreensaver
4573 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4575 ActivateScreenSaver();
4579 // activate the screensaver.
4580 // if forceType is true, we ignore the various conditions that can alter
4581 // the type of screensaver displayed
4582 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4584 m_bScreenSave = true;
4586 // Get Screensaver Mode
4587 m_screenSaver.reset();
4588 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4589 m_screenSaver.reset(new CScreenSaver(""));
4591 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4593 // disable screensaver lock from the login screen
4594 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4597 // set to Dim in the case of a dialog on screen or playing video
4598 if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4600 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4601 m_screenSaver.reset(new CScreenSaver(""));
4603 // Check if we are Playing Audio and Vis instead Screensaver!
4604 else if (IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4605 { // activate the visualisation
4606 m_screenSaver.reset(new CScreenSaver("visualization"));
4607 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4611 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4613 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4615 else if (!m_screenSaver->ID().IsEmpty())
4616 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4619 void CApplication::SetInBackground(bool background)
4623 ResetScreenSaverTimer();
4625 m_bInBackground = background;
4628 void CApplication::CheckShutdown()
4630 // first check if we should reset the timer
4631 bool resetTimer = m_bInhibitIdleShutdown;
4633 if (IsPlaying() || IsPaused()) // is something playing?
4636 if (m_musicInfoScanner->IsScanning())
4639 if (m_videoInfoScanner->IsScanning())
4642 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4645 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4650 m_shutdownTimer.StartZero();
4654 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4656 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4657 m_shutdownTimer.Stop();
4660 CApplicationMessenger::Get().Shutdown();
4664 void CApplication::InhibitIdleShutdown(bool inhibit)
4666 m_bInhibitIdleShutdown = inhibit;
4669 bool CApplication::IsIdleShutdownInhibited() const
4671 return m_bInhibitIdleShutdown;
4674 bool CApplication::OnMessage(CGUIMessage& message)
4676 switch ( message.GetMessage() )
4678 case GUI_MSG_NOTIFY_ALL:
4680 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4682 // Update general playlist: Remove DVD playlist items
4683 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4686 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4687 g_windowManager.SendMessage( msg );
4689 // stop the file if it's on dvd (will set the resume point etc)
4690 if (m_itemCurrentFile->IsOnDVD())
4696 case GUI_MSG_PLAYBACK_STARTED:
4698 #ifdef TARGET_DARWIN
4699 DarwinSetScheduling(message.GetMessage());
4701 // reset the seek handler
4702 m_seekHandler->Reset();
4703 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4705 // Update our infoManager with the new details etc.
4706 if (m_nextPlaylistItem >= 0)
4708 // playing an item which is not in the list - player might be stopped already
4710 if (playList.size() <= m_nextPlaylistItem)
4713 // we've started a previously queued item
4714 CFileItemPtr item = playList[m_nextPlaylistItem];
4715 // update the playlist manager
4716 int currentSong = g_playlistPlayer.GetCurrentSong();
4717 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4718 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4719 g_windowManager.SendThreadMessage(msg);
4720 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4721 *m_itemCurrentFile = *item;
4723 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4724 g_partyModeManager.OnSongChange(true);
4727 param["player"]["speed"] = 1;
4728 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4729 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4731 if (IsPlayingAudio())
4733 // Start our cdg parser as appropriate
4735 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4737 m_pKaraokeMgr->Stop();
4738 if (m_itemCurrentFile->IsMusicDb())
4740 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4742 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4743 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4746 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4749 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4758 case GUI_MSG_QUEUE_NEXT_ITEM:
4760 // Check to see if our playlist player has a new item for us,
4761 // and if so, we check whether our current player wants the file
4762 int iNext = g_playlistPlayer.GetNextSong();
4763 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4764 if (iNext < 0 || iNext >= playlist.size())
4766 if (m_pPlayer) m_pPlayer->OnNothingToQueueNotify();
4767 return true; // nothing to do
4770 // ok, grab the next song
4771 CFileItem file(*playlist[iNext]);
4773 CURL url(file.GetPath());
4774 if (url.GetProtocol() == "plugin")
4775 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4778 if (URIUtils::IsUPnP(file.GetPath()))
4780 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4785 // ok - send the file to the player, if it accepts it
4788 if (m_pPlayer->QueueNextFile(file))
4790 // player accepted the next file
4791 m_nextPlaylistItem = iNext;
4795 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4796 queue the next (if it wants to) and it doesn't keep looping on this song */
4797 g_playlistPlayer.SetCurrentSong(iNext);
4805 case GUI_MSG_PLAYBACK_STOPPED:
4806 case GUI_MSG_PLAYBACK_ENDED:
4807 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4811 m_pKaraokeMgr->Stop();
4813 #ifdef TARGET_DARWIN
4814 DarwinSetScheduling(message.GetMessage());
4816 // first check if we still have items in the stack to play
4817 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4819 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4820 { // just play the next item in the stack
4821 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4826 // In case playback ended due to user eg. skipping over the end, clear
4827 // our resume bookmark here
4828 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4830 // Delete the bookmark
4831 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4834 // reset the current playing file
4835 m_itemCurrentFile->Reset();
4836 g_infoManager.ResetCurrentItem();
4837 m_currentStack->Clear();
4839 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4841 g_playlistPlayer.PlayNext(1, true);
4845 // reset any forced player
4846 m_eForcedNextPlayer = EPC_NONE;
4851 m_pPlayer->CloseFile();
4861 g_audioManager.Enable(true);
4864 if (!IsPlayingVideo())
4866 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4868 g_windowManager.PreviousWindow();
4872 CSingleLock lock(g_graphicsContext);
4873 // resets to res_desktop or look&feel resolution (including refreshrate)
4874 g_graphicsContext.SetFullScreenVideo(false);
4878 if (!IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4880 CSettings::Get().Save(); // save vis settings
4881 WakeUpScreenSaverAndDPMS();
4882 g_windowManager.PreviousWindow();
4885 // DVD ejected while playing in vis ?
4886 if (!IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4889 CSettings::Get().Save(); // save vis settings
4890 WakeUpScreenSaverAndDPMS();
4891 g_windowManager.PreviousWindow();
4894 if (IsEnableTestMode())
4895 CApplicationMessenger::Get().Quit();
4900 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4901 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4906 case GUI_MSG_FULLSCREEN:
4907 { // Switch to fullscreen, if we can
4908 SwitchToFullScreen();
4912 case GUI_MSG_EXECUTE:
4913 if (message.GetNumStringParams())
4914 return ExecuteXBMCAction(message.GetStringParam());
4920 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4922 // see if it is a user set string
4923 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4924 CGUIInfoLabel info(actionStr, "");
4925 actionStr = info.GetLabel(0);
4926 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4928 // user has asked for something to be executed
4929 if (CBuiltins::HasCommand(actionStr))
4930 CBuiltins::Execute(actionStr);
4933 // try translating the action from our ButtonTranslator
4935 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4937 OnAction(CAction(actionID));
4940 CFileItem item(actionStr, false);
4942 if (item.IsPythonScript())
4943 { // a python script
4944 g_pythonParser.evalFile(item.GetPath().c_str(),ADDON::AddonPtr());
4948 if (item.IsAudio() || item.IsVideo())
4949 { // an audio or video file
4958 void CApplication::Process()
4962 // dispatch the messages generated by python or other threads to the current window
4963 g_windowManager.DispatchThreadMessages();
4965 // process messages which have to be send to the gui
4966 // (this can only be done after g_windowManager.Render())
4967 CApplicationMessenger::Get().ProcessWindowMessages();
4970 // process any Python scripts
4971 g_pythonParser.Process();
4974 // process messages, even if a movie is playing
4975 CApplicationMessenger::Get().ProcessMessages();
4976 if (g_application.m_bStop) return; //we're done, everything has been unloaded
4978 // check how far we are through playing the current item
4979 // and do anything that needs doing (playcount updates etc)
4980 CheckPlayingProgress();
4984 m_pPlayer->DoAudioWork();
4986 // do any processing that isn't needed on each run
4987 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4989 m_slowTimer.Reset();
4993 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4996 // We get called every 500ms
4997 void CApplication::ProcessSlow()
4999 g_powerManager.ProcessEvents();
5001 #if defined(TARGET_DARWIN_OSX)
5002 // There is an issue on OS X that several system services ask the cursor to become visible
5003 // during their startup routines. Given that we can't control this, we hack it in by
5005 if (g_Windowing.IsFullScreen())
5006 { // SDL thinks it's hidden
5011 // Resume low priority jobs when current item is not video
5012 if (!CurrentFileItem().IsVideo())
5014 CJobManager::GetInstance().UnPause(CJob::PRIORITY_LOW);
5017 // Store our file state for use on close()
5020 // Check if we need to activate the screensaver / DPMS.
5021 CheckScreenSaverAndDPMS();
5023 // Check if we need to shutdown (if enabled).
5024 #if defined(TARGET_DARWIN)
5025 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5027 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5033 // check if we should restart the player
5034 CheckDelayedPlayerRestart();
5036 // check if we can unload any unreferenced dlls or sections
5037 if (!IsPlayingVideo())
5038 CSectionLoader::UnloadDelayed();
5040 // check for any idle curl connections
5041 g_curlInterface.CheckIdle();
5043 // check for any idle myth sessions
5044 CMythSession::CheckIdle();
5046 #ifdef HAS_FILESYSTEM_HTSP
5047 // check for any idle htsp sessions
5048 HTSP::CHTSPDirectorySession::CheckIdle();
5052 if ( m_pKaraokeMgr )
5053 m_pKaraokeMgr->ProcessSlow();
5056 if (!IsPlayingVideo())
5057 g_largeTextureManager.CleanupUnusedImages();
5059 g_TextureManager.FreeUnusedTextures(5000);
5061 #ifdef HAS_DVD_DRIVE
5062 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5063 if (!IsPlayingVideo())
5064 m_Autorun->HandleAutorun();
5067 // update upnp server/renderer states
5069 if(UPNP::CUPnP::IsInstantiated())
5070 UPNP::CUPnP::GetInstance()->UpdateState();
5073 #if defined(_LINUX) && defined(HAS_FILESYSTEM_SMB)
5077 #ifdef HAS_FILESYSTEM_NFS
5078 gNfsConnection.CheckIfIdle();
5081 #ifdef HAS_FILESYSTEM_AFP
5082 gAfpConnection.CheckIfIdle();
5085 #ifdef HAS_FILESYSTEM_SFTP
5086 CSFTPSessionManager::ClearOutIdleSessions();
5089 g_mediaManager.ProcessEvents();
5092 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5093 g_RemoteControl.Initialize();
5096 if (!IsPlayingVideo())
5097 CAddonInstaller::Get().UpdateRepos();
5099 CAEFactory::GarbageCollect();
5102 // Global Idle Time in Seconds
5103 // idle time will be resetet if on any OnKey()
5104 // int return: system Idle time in seconds! 0 is no idle!
5105 int CApplication::GlobalIdleTime()
5107 if(!m_idleTimer.IsRunning())
5110 m_idleTimer.StartZero();
5112 return (int)m_idleTimer.GetElapsedSeconds();
5115 float CApplication::NavigationIdleTime()
5117 if (!m_navigationTimer.IsRunning())
5119 m_navigationTimer.Stop();
5120 m_navigationTimer.StartZero();
5122 return m_navigationTimer.GetElapsedSeconds();
5125 void CApplication::DelayedPlayerRestart()
5127 m_restartPlayerTimer.StartZero();
5130 void CApplication::CheckDelayedPlayerRestart()
5132 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5134 m_restartPlayerTimer.Stop();
5135 m_restartPlayerTimer.Reset();
5140 void CApplication::Restart(bool bSamePosition)
5142 // this function gets called when the user changes a setting (like noninterleaved)
5143 // and which means we gotta close & reopen the current playing file
5145 // first check if we're playing a file
5146 if ( !IsPlayingVideo() && !IsPlayingAudio())
5154 // do we want to return to the current position in the file
5155 if (false == bSamePosition)
5157 // no, then just reopen the file and start at the beginning
5158 PlayFile(*m_itemCurrentFile, true);
5162 // else get current position
5163 double time = GetTime();
5165 // get player state, needed for dvd's
5166 CStdString state = m_pPlayer->GetPlayerState();
5168 // set the requested starttime
5169 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5172 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK && m_pPlayer )
5173 m_pPlayer->SetPlayerState(state);
5176 const CStdString& CApplication::CurrentFile()
5178 return m_itemCurrentFile->GetPath();
5181 CFileItem& CApplication::CurrentFileItem()
5183 return *m_itemCurrentFile;
5186 void CApplication::ShowVolumeBar(const CAction *action)
5188 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5193 volumeBar->OnAction(*action);
5197 bool CApplication::IsMuted() const
5199 if (g_peripherals.IsMuted())
5201 return CAEFactory::IsMuted();
5204 void CApplication::ToggleMute(void)
5212 void CApplication::SetMute(bool mute)
5214 if (m_muted != mute)
5221 void CApplication::Mute()
5223 if (g_peripherals.Mute())
5226 CAEFactory::SetMute(true);
5231 void CApplication::UnMute()
5233 if (g_peripherals.UnMute())
5236 CAEFactory::SetMute(false);
5241 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5243 float hardwareVolume = iValue;
5246 hardwareVolume /= 100.0f;
5248 SetHardwareVolume(hardwareVolume);
5252 void CApplication::SetHardwareVolume(float hardwareVolume)
5254 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5255 m_volumeLevel = hardwareVolume;
5258 if (hardwareVolume > VOLUME_MINIMUM)
5260 float dB = CAEUtil::PercentToGain(hardwareVolume);
5261 value = CAEUtil::GainToScale(dB);
5266 CAEFactory::SetVolume(value);
5269 float CApplication::GetVolume(bool percentage /* = true */) const
5273 // converts the hardware volume to a percentage
5274 return m_volumeLevel * 100.0f;
5277 return m_volumeLevel;
5280 void CApplication::VolumeChanged() const
5282 CVariant data(CVariant::VariantTypeObject);
5283 data["volume"] = GetVolume();
5284 data["muted"] = m_muted;
5285 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5287 // if player has volume control, set it.
5288 if (m_pPlayer && m_pPlayer->ControlsVolume())
5290 m_pPlayer->SetVolume(m_volumeLevel);
5291 m_pPlayer->SetMute(m_muted);
5295 int CApplication::GetSubtitleDelay() const
5297 // converts subtitle delay to a percentage
5298 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5301 int CApplication::GetAudioDelay() const
5303 // converts audio delay to a percentage
5304 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5307 void CApplication::SetPlaySpeed(int iSpeed)
5309 if (!IsPlayingAudio() && !IsPlayingVideo())
5311 if (m_iPlaySpeed == iSpeed)
5313 if (!m_pPlayer->CanSeek())
5315 if (m_pPlayer->IsPaused())
5318 ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
5319 ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
5322 iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
5326 m_iPlaySpeed = iSpeed;
5328 m_pPlayer->ToFFRW(m_iPlaySpeed);
5330 // if player has volume control, set it.
5331 if (m_pPlayer->ControlsVolume())
5333 if (m_iPlaySpeed == 1)
5335 m_pPlayer->SetVolume(VOLUME_MAXIMUM);
5339 m_pPlayer->SetVolume(VOLUME_MINIMUM);
5341 m_pPlayer->SetMute(m_muted);
5345 int CApplication::GetPlaySpeed() const
5347 return m_iPlaySpeed;
5350 // Returns the total time in seconds of the current media. Fractional
5351 // portions of a second are possible - but not necessarily supported by the
5352 // player class. This returns a double to be consistent with GetTime() and
5354 double CApplication::GetTotalTime() const
5358 if (IsPlaying() && m_pPlayer)
5360 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5361 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5363 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5369 void CApplication::StopShutdownTimer()
5371 if (m_shutdownTimer.IsRunning())
5372 m_shutdownTimer.Stop();
5375 void CApplication::ResetShutdownTimers()
5377 // reset system shutdown timer
5378 m_shutdownTimer.StartZero();
5380 // delete custom shutdown timer
5381 if (g_alarmClock.HasAlarm("shutdowntimer"))
5382 g_alarmClock.Stop("shutdowntimer", true);
5385 // Returns the current time in seconds of the currently playing media.
5386 // Fractional portions of a second are possible. This returns a double to
5387 // be consistent with GetTotalTime() and SeekTime().
5388 double CApplication::GetTime() const
5392 if (IsPlaying() && m_pPlayer)
5394 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5396 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5397 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5400 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5406 // Sets the current position of the currently playing media to the specified
5407 // time in seconds. Fractional portions of a second are valid. The passed
5408 // time is the time offset from the beginning of the file as opposed to a
5409 // delta from the current position. This method accepts a double to be
5410 // consistent with GetTime() and GetTotalTime().
5411 void CApplication::SeekTime( double dTime )
5413 if (IsPlaying() && m_pPlayer && (dTime >= 0.0))
5415 if (!m_pPlayer->CanSeek()) return;
5416 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5418 // find the item in the stack we are seeking to, and load the new
5419 // file if necessary, and calculate the correct seek within the new
5420 // file. Otherwise, just fall through to the usual routine if the
5421 // time is higher than our total time.
5422 for (int i = 0; i < m_currentStack->Size(); i++)
5424 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5426 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5427 if (m_currentStackPosition == i)
5428 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5430 { // seeking to a new file
5431 m_currentStackPosition = i;
5432 CFileItem item(*(*m_currentStack)[i]);
5433 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5434 // don't just call "PlayFile" here, as we are quite likely called from the
5435 // player thread, so we won't be able to delete ourselves.
5436 CApplicationMessenger::Get().PlayFile(item, true);
5442 // convert to milliseconds and perform seek
5443 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5447 float CApplication::GetPercentage() const
5449 if (IsPlaying() && m_pPlayer)
5451 if (m_pPlayer->GetTotalTime() == 0 && IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5453 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5454 if (tag.GetDuration() > 0)
5455 return (float)(GetTime() / tag.GetDuration() * 100);
5458 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5460 double totalTime = GetTotalTime();
5461 if (totalTime > 0.0f)
5462 return (float)(GetTime() / totalTime * 100);
5465 return m_pPlayer->GetPercentage();
5470 float CApplication::GetCachePercentage() const
5472 if (IsPlaying() && m_pPlayer)
5474 // Note that the player returns a relative cache percentage and we want an absolute percentage
5475 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5477 float stackedTotalTime = (float) GetTotalTime();
5478 // We need to take into account the stack's total time vs. currently playing file's total time
5479 if (stackedTotalTime > 0.0f)
5480 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5483 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5488 void CApplication::SeekPercentage(float percent)
5490 if (IsPlaying() && m_pPlayer && (percent >= 0.0))
5492 if (!m_pPlayer->CanSeek()) return;
5493 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5494 SeekTime(percent * 0.01 * GetTotalTime());
5496 m_pPlayer->SeekPercentage(percent);
5500 // SwitchToFullScreen() returns true if a switch is made, else returns false
5501 bool CApplication::SwitchToFullScreen()
5503 // if playing from the video info window, close it first!
5504 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5506 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5507 if (pDialog) pDialog->Close(true);
5510 // don't switch if there is a dialog on screen or the slideshow is active
5511 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5514 // See if we're playing a video, and are in GUI mode
5515 if ( IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5517 // Reset frame count so that timing is FPS will be correct.
5519 CSingleLock lock(m_frameMutex);
5523 // then switch to fullscreen mode
5524 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5527 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5528 if (IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5529 { // then switch to visualisation
5530 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5536 void CApplication::Minimize()
5538 g_Windowing.Minimize();
5541 PLAYERCOREID CApplication::GetCurrentPlayer()
5543 return m_eCurrentPlayer;
5546 void CApplication::UpdateLibraries()
5548 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5550 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5554 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5556 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5561 bool CApplication::IsVideoScanning() const
5563 return m_videoInfoScanner->IsScanning();
5566 bool CApplication::IsMusicScanning() const
5568 return m_musicInfoScanner->IsScanning();
5571 void CApplication::StopVideoScan()
5573 if (m_videoInfoScanner->IsScanning())
5574 m_videoInfoScanner->Stop();
5577 void CApplication::StopMusicScan()
5579 if (m_musicInfoScanner->IsScanning())
5580 m_musicInfoScanner->Stop();
5583 void CApplication::StartVideoCleanup()
5585 if (m_videoInfoScanner->IsScanning())
5588 m_videoInfoScanner->CleanDatabase();
5591 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5593 if (m_videoInfoScanner->IsScanning())
5596 m_videoInfoScanner->ShowDialog(true);
5598 m_videoInfoScanner->Start(strDirectory,scanAll);
5601 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5603 if (m_musicInfoScanner->IsScanning())
5607 { // setup default flags
5608 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5609 flags |= CMusicInfoScanner::SCAN_ONLINE;
5610 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5611 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5614 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5615 m_musicInfoScanner->ShowDialog(true);
5617 m_musicInfoScanner->Start(strDirectory, flags);
5620 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5623 if (m_musicInfoScanner->IsScanning())
5626 m_musicInfoScanner->ShowDialog(true);
5628 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5631 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5634 if (m_musicInfoScanner->IsScanning())
5637 m_musicInfoScanner->ShowDialog(true);
5639 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5642 void CApplication::CheckPlayingProgress()
5644 // check if we haven't rewound past the start of the file
5647 int iSpeed = g_application.GetPlaySpeed();
5657 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5659 g_application.SetPlaySpeed(1);
5660 g_application.SeekTime(0);
5666 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5668 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5670 // initial exit conditions
5671 // no songs in playlist just return
5672 if (playlist.size() == 0)
5676 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5679 // setup correct playlist
5680 g_playlistPlayer.ClearPlaylist(iPlaylist);
5682 // if the playlist contains an internet stream, this file will be used
5683 // to generate a thumbnail for musicplayer.cover
5684 g_application.m_strPlayListFile = strPlayList;
5686 // add the items to the playlist player
5687 g_playlistPlayer.Add(iPlaylist, playlist);
5689 // if we have a playlist
5690 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5693 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5694 g_playlistPlayer.Reset();
5695 g_playlistPlayer.Play(track);
5701 void CApplication::SaveCurrentFileSettings()
5703 // don't store settings for PVR in video database
5704 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5706 // save video settings
5707 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5711 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5715 else if (m_itemCurrentFile->IsPVRChannel())
5717 g_PVRManager.SaveCurrentChannelSettings();
5721 bool CApplication::AlwaysProcess(const CAction& action)
5723 // check if this button is mapped to a built-in function
5724 if (!action.GetName().IsEmpty())
5726 CStdString builtInFunction;
5727 vector<CStdString> params;
5728 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5729 builtInFunction.ToLower();
5731 // should this button be handled normally or just cancel the screensaver?
5732 if ( builtInFunction.Equals("powerdown")
5733 || builtInFunction.Equals("reboot")
5734 || builtInFunction.Equals("restart")
5735 || builtInFunction.Equals("restartapp")
5736 || builtInFunction.Equals("suspend")
5737 || builtInFunction.Equals("hibernate")
5738 || builtInFunction.Equals("quit")
5739 || builtInFunction.Equals("shutdown"))
5748 bool CApplication::IsCurrentThread() const
5750 return CThread::IsCurrentThread(m_threadID);
5753 bool CApplication::IsPresentFrame()
5755 CSingleLock lock(m_frameMutex);
5756 bool ret = m_bPresentFrame;
5761 void CApplication::SetRenderGUI(bool renderGUI)
5763 if (renderGUI && ! m_renderGUI)
5764 g_windowManager.MarkDirty();
5765 m_renderGUI = renderGUI;
5768 CNetwork& CApplication::getNetwork()
5772 #ifdef HAS_PERFORMANCE_SAMPLE
5773 CPerformanceStats &CApplication::GetPerformanceStats()
5779 bool CApplication::SetLanguage(const CStdString &strLanguage)
5781 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5782 CStdString strNewLanguage = strLanguage;
5783 if (strNewLanguage != strPreviousLanguage)
5785 CStdString strLangInfoPath;
5786 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5787 if (!g_langInfo.Load(strLangInfoPath))
5790 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5792 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5793 CStdString strFontSet;
5794 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5795 strNewLanguage = strFontSet;
5797 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5799 CSettings::Get().SetString("locale.language", strNewLanguage);
5801 g_charsetConverter.reset();
5803 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5806 // also tell our weather and skin to reload as these are localized
5807 g_weatherManager.Refresh();
5808 g_PVRManager.LocalizationChanged();