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/StereoscopicsManager.h"
48 #include "guilib/GUITextLayout.h"
49 #include "addons/Skin.h"
50 #include "interfaces/generic/ScriptInvocationManager.h"
52 #include "interfaces/python/XBPython.h"
54 #include "input/ButtonTranslator.h"
55 #include "guilib/GUIAudioManager.h"
56 #include "GUIPassword.h"
57 #include "input/InertialScrollingHandler.h"
58 #include "ApplicationMessenger.h"
59 #include "SectionLoader.h"
60 #include "cores/DllLoader/DllLoaderContainer.h"
61 #include "GUIUserMessages.h"
62 #include "filesystem/DirectoryCache.h"
63 #include "filesystem/StackDirectory.h"
64 #include "filesystem/SpecialProtocol.h"
65 #include "filesystem/DllLibCurl.h"
66 #include "filesystem/MythSession.h"
67 #include "filesystem/PluginDirectory.h"
68 #ifdef HAS_FILESYSTEM_SAP
69 #include "filesystem/SAPDirectory.h"
71 #ifdef HAS_FILESYSTEM_HTSP
72 #include "filesystem/HTSPDirectory.h"
74 #include "utils/TuxBoxUtil.h"
75 #include "utils/SystemInfo.h"
76 #include "utils/TimeUtils.h"
77 #include "GUILargeTextureManager.h"
78 #include "TextureCache.h"
79 #include "playlists/SmartPlayList.h"
80 #ifdef HAS_FILESYSTEM_RAR
81 #include "filesystem/RarManager.h"
83 #include "playlists/PlayList.h"
84 #include "profiles/ProfilesManager.h"
85 #include "windowing/WindowingFactory.h"
86 #include "powermanagement/PowerManager.h"
87 #include "powermanagement/DPMSSupport.h"
88 #include "settings/SettingAddon.h"
89 #include "settings/Settings.h"
90 #include "settings/AdvancedSettings.h"
91 #include "settings/DisplaySettings.h"
92 #include "settings/MediaSettings.h"
93 #include "settings/MediaSourceSettings.h"
94 #include "settings/SkinSettings.h"
95 #include "guilib/LocalizeStrings.h"
96 #include "utils/CPUInfo.h"
97 #include "utils/RssManager.h"
98 #include "utils/SeekHandler.h"
99 #include "view/ViewStateSettings.h"
101 #include "input/KeyboardStat.h"
102 #include "input/XBMC_vkeys.h"
103 #include "input/MouseStat.h"
109 #if defined(FILESYSTEM) && !defined(TARGET_POSIX)
110 #include "filesystem/FileDAAP.h"
113 #include "network/upnp/UPnP.h"
114 #include "network/upnp/UPnPSettings.h"
115 #include "filesystem/UPnPDirectory.h"
117 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
118 #include "filesystem/SMBDirectory.h"
120 #ifdef HAS_FILESYSTEM_NFS
121 #include "filesystem/NFSFile.h"
123 #ifdef HAS_FILESYSTEM_AFP
124 #include "filesystem/AFPFile.h"
126 #ifdef HAS_FILESYSTEM_SFTP
127 #include "filesystem/SFTPFile.h"
129 #include "PartyModeManager.h"
130 #ifdef HAS_VIDEO_PLAYBACK
131 #include "cores/VideoRenderers/RenderManager.h"
134 #include "music/karaoke/karaokelyricsmanager.h"
135 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
136 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
138 #include "network/Zeroconf.h"
139 #include "network/ZeroconfBrowser.h"
141 #include "threads/platform/win/Win32Exception.h"
143 #ifdef HAS_EVENT_SERVER
144 #include "network/EventServer.h"
147 #include <dbus/dbus.h>
150 #include "interfaces/json-rpc/JSONRPC.h"
151 #include "network/TCPServer.h"
154 #include "network/AirPlayServer.h"
157 #include "network/AirTunesServer.h"
159 #if defined(HAVE_LIBCRYSTALHD)
160 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
162 #include "interfaces/AnnouncementManager.h"
163 #include "peripherals/Peripherals.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
165 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
166 #include "peripherals/devices/PeripheralImon.h"
167 #include "music/infoscanner/MusicInfoScanner.h"
170 #include "guilib/GUIWindowManager.h"
171 #include "windows/GUIWindowHome.h"
172 #include "settings/windows/GUIWindowSettings.h"
173 #include "windows/GUIWindowFileManager.h"
174 #include "settings/windows/GUIWindowSettingsCategory.h"
175 #include "music/windows/GUIWindowMusicPlaylist.h"
176 #include "music/windows/GUIWindowMusicSongs.h"
177 #include "music/windows/GUIWindowMusicNav.h"
178 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
179 #include "video/windows/GUIWindowVideoPlaylist.h"
180 #include "music/dialogs/GUIDialogMusicInfo.h"
181 #include "video/dialogs/GUIDialogVideoInfo.h"
182 #include "video/windows/GUIWindowVideoNav.h"
183 #include "profiles/windows/GUIWindowSettingsProfile.h"
185 #include "rendering/gl/GUIWindowTestPatternGL.h"
188 #include "rendering/dx/GUIWindowTestPatternDX.h"
190 #include "settings/windows/GUIWindowSettingsScreenCalibration.h"
191 #include "programs/GUIWindowPrograms.h"
192 #include "pictures/GUIWindowPictures.h"
193 #include "windows/GUIWindowWeather.h"
194 #include "windows/GUIWindowLoginScreen.h"
195 #include "addons/GUIWindowAddonBrowser.h"
196 #include "music/windows/GUIWindowVisualisation.h"
197 #include "windows/GUIWindowDebugInfo.h"
198 #include "windows/GUIWindowPointer.h"
199 #include "windows/GUIWindowSystemInfo.h"
200 #include "windows/GUIWindowScreensaver.h"
201 #include "windows/GUIWindowScreensaverDim.h"
202 #include "pictures/GUIWindowSlideShow.h"
203 #include "windows/GUIWindowStartup.h"
204 #include "video/windows/GUIWindowFullScreen.h"
205 #include "video/dialogs/GUIDialogVideoOSD.h"
206 #include "music/dialogs/GUIDialogMusicOverlay.h"
207 #include "video/dialogs/GUIDialogVideoOverlay.h"
208 #include "video/VideoInfoScanner.h"
209 #include "video/PlayerController.h"
212 #include "music/dialogs/GUIDialogMusicOSD.h"
213 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
214 #include "dialogs/GUIDialogTextViewer.h"
215 #include "network/GUIDialogNetworkSetup.h"
216 #include "dialogs/GUIDialogMediaSource.h"
217 #include "video/dialogs/GUIDialogVideoSettings.h"
218 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
219 #include "video/dialogs/GUIDialogVideoBookmarks.h"
220 #include "profiles/dialogs/GUIDialogProfileSettings.h"
221 #include "profiles/dialogs/GUIDialogLockSettings.h"
222 #include "settings/dialogs/GUIDialogContentSettings.h"
223 #include "dialogs/GUIDialogBusy.h"
224 #include "dialogs/GUIDialogKeyboardGeneric.h"
225 #include "dialogs/GUIDialogYesNo.h"
226 #include "dialogs/GUIDialogOK.h"
227 #include "dialogs/GUIDialogProgress.h"
228 #include "dialogs/GUIDialogExtendedProgressBar.h"
229 #include "dialogs/GUIDialogSelect.h"
230 #include "dialogs/GUIDialogSeekBar.h"
231 #include "dialogs/GUIDialogKaiToast.h"
232 #include "dialogs/GUIDialogVolumeBar.h"
233 #include "dialogs/GUIDialogMuteBug.h"
234 #include "video/dialogs/GUIDialogFileStacking.h"
235 #include "dialogs/GUIDialogNumeric.h"
236 #include "dialogs/GUIDialogGamepad.h"
237 #include "dialogs/GUIDialogSubMenu.h"
238 #include "dialogs/GUIDialogFavourites.h"
239 #include "dialogs/GUIDialogButtonMenu.h"
240 #include "dialogs/GUIDialogContextMenu.h"
241 #include "dialogs/GUIDialogPlayerControls.h"
242 #include "music/dialogs/GUIDialogSongInfo.h"
243 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
244 #include "dialogs/GUIDialogSmartPlaylistRule.h"
245 #include "pictures/GUIDialogPictureInfo.h"
246 #include "addons/GUIDialogAddonSettings.h"
247 #include "addons/GUIDialogAddonInfo.h"
248 #ifdef HAS_LINUX_NETWORK
249 #include "network/GUIDialogAccessPoints.h"
252 /* PVR related include Files */
253 #include "pvr/PVRManager.h"
254 #include "pvr/timers/PVRTimers.h"
255 #include "pvr/windows/GUIWindowPVR.h"
256 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
257 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
258 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
260 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
261 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
263 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
264 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
265 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
267 #include "epg/EpgContainer.h"
269 #include "video/dialogs/GUIDialogFullScreenInfo.h"
270 #include "video/dialogs/GUIDialogTeletext.h"
271 #include "dialogs/GUIDialogSlider.h"
272 #include "guilib/GUIControlFactory.h"
273 #include "dialogs/GUIDialogCache.h"
274 #include "dialogs/GUIDialogPlayEject.h"
275 #include "dialogs/GUIDialogMediaFilter.h"
276 #include "video/dialogs/GUIDialogSubtitles.h"
277 #include "utils/XMLUtils.h"
278 #include "addons/AddonInstaller.h"
280 #ifdef HAS_PERFORMANCE_SAMPLE
281 #include "utils/PerformanceSample.h"
283 #define MEASURE_FUNCTION
286 #ifdef TARGET_WINDOWS
288 #include "win32util.h"
291 #include "windowing/X11/XRandR.h"
294 #ifdef TARGET_DARWIN_OSX
295 #include "osx/CocoaInterface.h"
296 #include "osx/XBMCHelper.h"
299 #include "osx/DarwinUtils.h"
304 #include <cdio/logging.h>
308 #include "linux/HALManager.h"
311 #include "storage/MediaManager.h"
312 #include "utils/JobManager.h"
313 #include "utils/SaveFileStateJob.h"
314 #include "utils/AlarmClock.h"
315 #include "utils/RssReader.h"
316 #include "utils/StringUtils.h"
317 #include "utils/Weather.h"
318 #include "DatabaseManager.h"
325 #include "input/linux/LIRC.h"
327 #ifdef HAS_IRSERVERSUITE
328 #include "input/windows/IRServerSuite.h"
331 #if defined(TARGET_WINDOWS)
332 #include "input/windows/WINJoystick.h"
333 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
334 #include "input/SDLJoystick.h"
337 #if defined(TARGET_ANDROID)
338 #include "android/activity/XBMCApp.h"
339 #include "android/activity/AndroidFeatures.h"
340 #include "android/jni/Build.h"
343 #ifdef TARGET_WINDOWS
344 #include "utils/Environment.h"
347 #if defined(HAS_LIBAMCODEC)
348 #include "utils/AMLUtils.h"
351 #include "cores/FFmpeg.h"
354 using namespace ADDON;
355 using namespace XFILE;
357 using namespace MEDIA_DETECT;
359 using namespace PLAYLIST;
360 using namespace VIDEO;
361 using namespace MUSIC_INFO;
362 #ifdef HAS_EVENT_SERVER
363 using namespace EVENTSERVER;
366 using namespace JSONRPC;
368 using namespace ANNOUNCEMENT;
371 using namespace PERIPHERALS;
373 using namespace XbmcThreads;
375 // uncomment this if you want to use release libs in the debug build.
376 // Atm this saves you 7 mb of memory
377 #define USE_RELEASE_LIBS
379 #define MAX_FFWD_SPEED 5
381 //extern IDirectSoundRenderer* m_pAudioDecoder;
382 CApplication::CApplication(void)
383 : m_pPlayer(new CApplicationPlayer)
384 , m_itemCurrentFile(new CFileItem)
385 , m_stackFileItemToUpdate(new CFileItem)
386 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
387 , m_progressTrackingItem(new CFileItem)
388 , m_videoInfoScanner(new CVideoInfoScanner)
389 , m_musicInfoScanner(new CMusicInfoScanner)
390 , m_seekHandler(new CSeekHandler)
391 , m_playerController(new CPlayerController)
394 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;
405 m_bPlaybackStarting = false;
406 m_ePlayState = PLAY_STATE_NONE;
407 m_skinReverting = false;
415 /* for now always keep this around */
417 m_pKaraokeMgr = new CKaraokeLyricsManager();
419 m_currentStack = new CFileItemList;
421 m_bPresentFrame = false;
422 m_bPlatformDirectories = true;
424 m_bStandalone = false;
425 m_bEnableLegacyRes = false;
426 m_bSystemScreenSaverEnable = false;
427 m_pInertialScrollingHandler = new CInertialScrollingHandler();
429 m_Autorun = new CAutorun();
434 m_progressTrackingPlayCountUpdate = false;
435 m_currentStackPosition = 0;
437 m_lastRenderTime = 0;
441 m_volumeLevel = 1.0f;
444 CApplication::~CApplication(void)
446 delete m_musicInfoScanner;
447 delete m_videoInfoScanner;
448 delete &m_progressTrackingVideoResumeBookmark;
452 delete m_currentStack;
455 delete m_pKaraokeMgr;
459 delete m_seekHandler;
460 delete m_playerController;
461 delete m_pInertialScrollingHandler;
465 bool CApplication::OnEvent(XBMC_Event& newEvent)
467 switch(newEvent.type)
470 if (!g_application.m_bStop)
471 CApplicationMessenger::Get().Quit();
474 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
477 g_Keyboard.ProcessKeyUp();
479 case XBMC_MOUSEBUTTONDOWN:
480 case XBMC_MOUSEBUTTONUP:
481 case XBMC_MOUSEMOTION:
482 g_Mouse.HandleEvent(newEvent);
483 g_application.ProcessMouse();
485 case XBMC_VIDEORESIZE:
486 if (!g_application.m_bInitializing &&
487 !g_advancedSettings.m_fullScreen)
489 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
490 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
491 CSettings::Get().SetInt("window.width", newEvent.resize.w);
492 CSettings::Get().SetInt("window.height", newEvent.resize.h);
493 CSettings::Get().Save();
497 #ifdef TARGET_WINDOWS
498 if (g_advancedSettings.m_fullScreen)
500 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
501 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
502 if (newRes != g_graphicsContext.GetVideoResolution())
503 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
508 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
512 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
514 case XBMC_APPCOMMAND:
515 return g_application.OnAppCommand(newEvent.appcommand.action);
518 if (newEvent.touch.action == ACTION_TOUCH_TAP)
519 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
520 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
523 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
524 actionId = newEvent.touch.action;
527 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
528 // change this if we have a dialog up
529 if (g_windowManager.HasModalDialog())
531 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
533 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
534 { // fullscreen info dialog - special case
535 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
537 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
541 if (iWin == WINDOW_FULLSCREEN_VIDEO)
543 // current active window is full screen video.
544 if (g_application.m_pPlayer->IsInMenu())
546 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
547 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_VIDEO_MENU, newEvent.touch.action, newEvent.touch.pointers, actionId);
549 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
551 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
552 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
554 // if no PVR specific action/mapping is found, fall back to default
556 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
560 // in any other case use the fullscreen window section of keymap.xml to map key->action
561 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
564 else // iWin != WINDOW_FULLSCREEN_VIDEO
565 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
572 if ((actionId >= ACTION_TOUCH_TAP && actionId <= ACTION_GESTURE_END)
573 || (actionId >= ACTION_MOUSE_START && actionId <= ACTION_MOUSE_END) )
574 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
576 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
578 // Post an unfocus message for touch device after the action.
579 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
581 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
582 CApplicationMessenger::Get().SendGUIMessage(msg);
587 // Reset the screensaver
588 g_application.ResetScreenSaver();
589 g_application.WakeUpScreenSaverAndDPMS();
590 // Send a mouse motion event with no dx,dy for getting the current guiitem selected
591 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, static_cast<float>(newEvent.focus.x), static_cast<float>(newEvent.focus.y), 0, 0));
597 extern "C" void __stdcall init_emu_environ();
598 extern "C" void __stdcall update_emu_environ();
599 extern "C" void __stdcall cleanup_emu_environ();
602 // Utility function used to copy files from the application bundle
603 // over to the user data directory in Application Support/XBMC.
605 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
607 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
608 if (!CFile::Exists(destPath))
610 // need to copy it across
611 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
612 CFile::Copy(srcPath, destPath);
616 void CApplication::Preflight()
619 // call 'dbus_threads_init_default' before any other dbus calls in order to
620 // avoid race conditions with other threads using dbus connections
621 dbus_threads_init_default();
624 // run any platform preflight scripts.
625 #if defined(TARGET_DARWIN_OSX)
626 CStdString install_path;
628 CUtil::GetHomePath(install_path);
629 setenv("XBMC_HOME", install_path.c_str(), 0);
630 install_path += "/tools/darwin/runtime/preflight";
631 system(install_path.c_str());
635 bool CApplication::Create()
637 #if defined(HAS_LINUX_NETWORK)
638 m_network = new CNetworkLinux();
639 #elif defined(HAS_WIN32_NETWORK)
640 m_network = new CNetworkWin32();
642 m_network = new CNetwork();
647 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
649 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
650 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
654 tzset(); // Initialize timezone information variables
657 // Grab a handle to our thread to be used later in identifying the render thread.
658 m_threadID = CThread::GetCurrentThreadId();
661 //floating point precision to 24 bits (faster performance)
662 _controlfp(_PC_24, _MCW_PC);
664 /* install win32 exception translator, win32 exceptions
665 * can now be caught using c++ try catch */
666 win32_exception::install_handler();
670 // only the InitDirectories* for the current platform should return true
671 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
672 bool inited = InitDirectoriesLinux();
674 inited = InitDirectoriesOSX();
676 inited = InitDirectoriesWin32();
678 // copy required files
679 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
680 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
681 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
683 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
685 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
686 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
690 // Init our DllLoaders emu env
693 CProfilesManager::Get().Load();
695 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
696 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(),
697 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness());
699 std::string buildType;
702 #elif defined(NDEBUG)
703 buildType = "Release";
705 buildType = "Unknown";
707 std::string specialVersion;
708 #if defined(TARGET_DARWIN_IOS_ATV2)
709 specialVersion = " (version for AppleTV2)";
710 #elif defined(TARGET_RASPBERRY_PI)
711 specialVersion = " (version for Raspberry Pi)";
712 //#elif defined(some_ID) // uncomment for special version/fork
713 // specialVersion = " (version for XXXX)";
715 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build%s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), specialVersion.c_str());
716 CLog::Log(LOGNOTICE, "XBMC compiled " __DATE__ " by %s for %s %s %d-bit %s (%s)", g_sysinfo.GetUsedCompilerNameAndVer().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(),
717 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersionDecoded().c_str(),
718 g_sysinfo.GetBuildTargetPlatformVersion().c_str());
720 std::string deviceModel(g_sysinfo.GetModelName());
721 if (!g_sysinfo.GetManufacturerName().empty())
722 deviceModel = g_sysinfo.GetManufacturerName() + " " + (deviceModel.empty() ? std::string("device") : deviceModel);
723 if (!deviceModel.empty())
724 CLog::Log(LOGNOTICE, "Running on %s with %s, kernel: %s %s %d-bit version %s", deviceModel.c_str(), g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
725 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
727 CLog::Log(LOGNOTICE, "Running on %s, kernel: %s %s %d-bit version %s", g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
728 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
730 #if defined(TARGET_LINUX)
731 #if USE_STATIC_FFMPEG
732 CLog::Log(LOGNOTICE, "FFmpeg statically linked, version: %s", FFMPEG_VERSION);
733 #else // !USE_STATIC_FFMPEG
734 CLog::Log(LOGNOTICE, "FFmpeg version: %s", FFMPEG_VERSION);
735 #endif // !USE_STATIC_FFMPEG
736 if (!strstr(FFMPEG_VERSION, FFMPEG_VER_SHA))
738 if (strstr(FFMPEG_VERSION, "xbmc"))
739 CLog::Log(LOGNOTICE, "WARNING: unknown ffmpeg-xbmc version detected");
741 CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected");
745 std::string cpuModel(g_cpuInfo.getCPUModel());
746 if (!cpuModel.empty())
747 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
749 CLog::Log(LOGNOTICE, "%d CPU core%s available", g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
750 #if defined(TARGET_WINDOWS)
751 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
752 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
753 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
755 #if defined(TARGET_ANDROID)
757 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
758 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
759 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
763 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
764 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
766 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
768 CSpecialProtocol::LogPaths();
770 CStdString executable = CUtil::ResolveExecutablePath();
771 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
772 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
773 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
774 CRegExp::LogCheckUtf8Support();
775 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
777 CStdString strExecutablePath;
778 CUtil::GetHomePath(strExecutablePath);
781 g_xrandr.LoadCustomModeLinesToAllOutputs();
784 // for python scripts that check the OS
785 #if defined(TARGET_DARWIN)
786 setenv("OS","OS X",true);
787 #elif defined(TARGET_POSIX)
788 setenv("OS","Linux",true);
789 #elif defined(TARGET_WINDOWS)
790 CEnvironment::setenv("OS", "win32");
793 // register ffmpeg lockmanager callback
794 av_lockmgr_register(&ffmpeg_lockmgr_cb);
796 avcodec_register_all();
800 avfilter_register_all();
801 // set avutil callback
802 av_log_set_callback(ff_avutil_log);
804 g_powerManager.Initialize();
806 // Load the AudioEngine before settings as they need to query the engine
807 if (!CAEFactory::LoadEngine())
809 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
813 // Initialize default Settings - don't move
814 CLog::Log(LOGNOTICE, "load settings...");
815 if (!CSettings::Get().Initialize())
818 g_powerManager.SetDefaults();
820 // load the actual values
821 if (!CSettings::Get().Load())
823 CLog::Log(LOGFATAL, "unable to load settings");
826 CSettings::Get().SetLoaded();
828 CLog::Log(LOGINFO, "creating subdirectories");
829 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
830 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
831 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
832 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
833 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
834 CProfilesManager::Get().CreateProfileFolders();
836 update_emu_environ();//apply the GUI settings
838 // Load the langinfo to have user charset <-> utf-8 conversion
839 CStdString strLanguage = CSettings::Get().GetString("locale.language");
840 strLanguage[0] = toupper(strLanguage[0]);
842 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
844 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
845 g_langInfo.Load(strLangInfoPath);
846 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
847 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
849 CStdString strLanguagePath = "special://xbmc/language/";
851 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
852 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
854 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
858 // start the AudioEngine
859 if (!CAEFactory::StartEngine())
861 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
865 // restore AE's previous volume state
866 SetHardwareVolume(m_volumeLevel);
867 CAEFactory::SetMute (m_muted);
868 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
870 // initialize m_replayGainSettings
871 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
872 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
873 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
874 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
876 // initialize the addon database (must be before the addon manager is init'd)
877 CDatabaseManager::Get().Initialize(true);
880 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
883 // start-up Addons Framework
884 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
885 if (!CAddonMgr::Get().Init())
887 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
890 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
891 g_RemoteControl.Initialize();
894 g_peripherals.Initialise();
896 // Create the Mouse, Keyboard, Remote, and Joystick devices
897 // Initialize after loading settings to get joystick deadzone setting
898 g_Mouse.Initialize();
899 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
901 g_Keyboard.Initialize();
903 #if defined(TARGET_DARWIN_OSX)
904 // Configure and possible manually start the helper.
905 XBMCHelper::GetInstance().Configure();
908 CUtil::InitRandomSeed();
910 g_mediaManager.Initialize();
912 m_lastFrameTime = XbmcThreads::SystemClockMillis();
913 m_lastRenderTime = m_lastFrameTime;
917 bool CApplication::CreateGUI()
921 CLog::Log(LOGNOTICE, "Setup SDL");
923 /* Clean up on exit, exit on window close and interrupt */
926 uint32_t sdlFlags = 0;
928 #if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX)
929 sdlFlags |= SDL_INIT_VIDEO;
932 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
933 sdlFlags |= SDL_INIT_JOYSTICK;
936 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
937 //this might bring the monitor out of standby, so we have to disable it explicitly
938 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
939 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
940 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
946 // for nvidia cards - vsync currently ALWAYS enabled.
947 // the reason is that after screen has been setup changing this env var will make no difference.
948 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
949 setenv("__GL_YIELD", "USLEEP", 0);
952 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
953 g_Windowing.EnableSystemScreenSaver(false);
956 if (SDL_Init(sdlFlags) != 0)
958 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
961 #if defined(TARGET_DARWIN)
962 // SDL_Init will install a handler for segfaults, restore the default handler.
963 signal(SIGSEGV, SIG_DFL);
967 // Initialize core peripheral port support. Note: If these parameters
968 // are 0 and NULL, respectively, then the default number and types of
969 // controllers will be initialized.
970 if (!g_Windowing.InitWindowSystem())
972 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
976 // Retrieve the matching resolution based on GUI settings
977 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
978 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
979 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
981 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
982 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
985 // update the window resolution
986 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
988 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
989 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
991 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
993 // Oh uh - doesn't look good for starting in their wanted screenmode
994 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
995 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
1002 if (g_advancedSettings.m_splashImage)
1004 CStdString strUserSplash = "special://home/media/Splash.png";
1005 if (CFile::Exists(strUserSplash))
1007 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
1008 m_splash = new CSplash(strUserSplash);
1012 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1013 m_splash = new CSplash("special://xbmc/media/Splash.png");
1018 // The key mappings may already have been loaded by a peripheral
1019 CLog::Log(LOGINFO, "load keymapping");
1020 if (!CButtonTranslator::GetInstance().Load())
1023 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1024 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1027 info.strMode.c_str());
1028 g_windowManager.Initialize();
1033 bool CApplication::InitWindow()
1035 #ifdef TARGET_DARWIN_OSX
1036 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1037 // fixes the white screen of death if starting fullscreen and switching to windowed.
1038 bool bFullScreen = false;
1039 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1041 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1045 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1046 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1048 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1053 if (!g_Windowing.InitRenderSystem())
1055 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1058 // set GUI res and force the clear of the screen
1059 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1063 bool CApplication::DestroyWindow()
1065 return g_Windowing.DestroyWindow();
1068 bool CApplication::InitDirectoriesLinux()
1071 The following is the directory mapping for Platform Specific Mode:
1073 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1074 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1075 installations like skins, screensavers, etc.
1077 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1078 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1079 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1080 special://profile/ => [read-write] current profile's userdata directory.
1081 Generally special://masterprofile for the master profile or
1082 special://masterprofile/profiles/<profile_name> for other profiles.
1084 NOTE: All these root directories are lowercase. Some of the sub-directories
1085 might be mixed case.
1088 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1089 CStdString userName;
1091 userName = getenv("USER");
1095 CStdString userHome;
1097 userHome = getenv("HOME");
1101 CStdString xbmcBinPath, xbmcPath;
1102 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1103 xbmcPath = getenv("XBMC_HOME");
1105 if (xbmcPath.empty())
1107 xbmcPath = xbmcBinPath;
1108 /* Check if xbmc binaries and arch independent data files are being kept in
1109 * separate locations. */
1110 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1112 /* Attempt to locate arch independent data files. */
1113 CUtil::GetHomePath(xbmcPath);
1114 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1116 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1122 /* Set some environment variables */
1123 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1124 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1126 if (m_bPlatformDirectories)
1128 // map our special drives
1129 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1130 CSpecialProtocol::SetXBMCPath(xbmcPath);
1131 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1132 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1134 CStdString strTempPath = userHome;
1135 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1136 if (getenv("XBMC_TEMP"))
1137 strTempPath = getenv("XBMC_TEMP");
1138 CSpecialProtocol::SetTempPath(strTempPath);
1140 URIUtils::AddSlashAtEnd(strTempPath);
1141 g_advancedSettings.m_logFolder = strTempPath;
1148 URIUtils::AddSlashAtEnd(xbmcPath);
1149 g_advancedSettings.m_logFolder = xbmcPath;
1151 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1152 CSpecialProtocol::SetXBMCPath(xbmcPath);
1153 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1154 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1156 CStdString strTempPath = xbmcPath;
1157 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1158 if (getenv("XBMC_TEMP"))
1159 strTempPath = getenv("XBMC_TEMP");
1160 CSpecialProtocol::SetTempPath(strTempPath);
1163 URIUtils::AddSlashAtEnd(strTempPath);
1164 g_advancedSettings.m_logFolder = strTempPath;
1173 bool CApplication::InitDirectoriesOSX()
1175 #if defined(TARGET_DARWIN)
1176 CStdString userName;
1178 userName = getenv("USER");
1182 CStdString userHome;
1184 userHome = getenv("HOME");
1188 CStdString xbmcPath;
1189 CUtil::GetHomePath(xbmcPath);
1190 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1192 #if defined(TARGET_DARWIN_IOS)
1193 CStdString fontconfigPath;
1194 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1195 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1198 // setup path to our internal dylibs so loader can find them
1199 CStdString frameworksPath = CUtil::GetFrameworksPath();
1200 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1202 // OSX always runs with m_bPlatformDirectories == true
1203 if (m_bPlatformDirectories)
1205 // map our special drives
1206 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1207 CSpecialProtocol::SetXBMCPath(xbmcPath);
1208 #if defined(TARGET_DARWIN_IOS)
1209 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1210 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1212 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1213 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1216 // location for temp files
1217 #if defined(TARGET_DARWIN_IOS)
1218 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1220 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1221 CDirectory::Create(strTempPath);
1222 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1224 CSpecialProtocol::SetTempPath(strTempPath);
1226 // xbmc.log file location
1227 #if defined(TARGET_DARWIN_IOS)
1228 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1230 strTempPath = userHome + "/Library/Logs";
1232 URIUtils::AddSlashAtEnd(strTempPath);
1233 g_advancedSettings.m_logFolder = strTempPath;
1239 URIUtils::AddSlashAtEnd(xbmcPath);
1240 g_advancedSettings.m_logFolder = xbmcPath;
1242 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1243 CSpecialProtocol::SetXBMCPath(xbmcPath);
1244 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1245 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1247 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1248 CSpecialProtocol::SetTempPath(strTempPath);
1250 URIUtils::AddSlashAtEnd(strTempPath);
1251 g_advancedSettings.m_logFolder = strTempPath;
1260 bool CApplication::InitDirectoriesWin32()
1262 #ifdef TARGET_WINDOWS
1263 CStdString xbmcPath;
1265 CUtil::GetHomePath(xbmcPath);
1266 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1267 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1268 CSpecialProtocol::SetXBMCPath(xbmcPath);
1270 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1272 g_advancedSettings.m_logFolder = strWin32UserFolder;
1273 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1274 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1275 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1277 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1281 // Expand the DLL search path with our directories
1282 CWIN32Util::ExtendDllPath();
1290 void CApplication::CreateUserDirs()
1292 CDirectory::Create("special://home/");
1293 CDirectory::Create("special://home/addons");
1294 CDirectory::Create("special://home/addons/packages");
1295 CDirectory::Create("special://home/media");
1296 CDirectory::Create("special://home/sounds");
1297 CDirectory::Create("special://home/system");
1298 CDirectory::Create("special://masterprofile/");
1299 CDirectory::Create("special://temp/");
1300 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1303 bool CApplication::Initialize()
1305 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1306 // turn off cdio logging
1307 cdio_loglevel_default = CDIO_LOG_ERROR;
1310 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1311 // must create these here. Ideally this should be using special://home/ and
1312 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1313 if (!m_bPlatformDirectories)
1316 CDirectory::Create("special://xbmc/language");
1317 CDirectory::Create("special://xbmc/addons");
1318 CDirectory::Create("special://xbmc/sounds");
1321 // Load curl so curl_global_init gets called before any service threads
1322 // are started. Unloading will have no effect as curl is never fully unloaded.
1323 // To quote man curl_global_init:
1324 // "This function is not thread safe. You must not call it when any other
1325 // thread in the program (i.e. a thread sharing the same memory) is running.
1326 // This doesn't just mean no other thread that is using libcurl. Because
1327 // curl_global_init() calls functions of other libraries that are similarly
1328 // thread unsafe, it could conflict with any other thread that
1329 // uses these other libraries."
1330 g_curlInterface.Load();
1331 g_curlInterface.Unload();
1333 // initialize (and update as needed) our databases
1334 CDatabaseManager::Get().Initialize();
1338 // Init DPMS, before creating the corresponding setting control.
1339 m_dpms = new DPMSSupport();
1340 if (g_windowManager.Initialized())
1342 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1344 g_windowManager.Add(new CGUIWindowHome);
1345 g_windowManager.Add(new CGUIWindowPrograms);
1346 g_windowManager.Add(new CGUIWindowPictures);
1347 g_windowManager.Add(new CGUIWindowFileManager);
1348 g_windowManager.Add(new CGUIWindowSettings);
1349 g_windowManager.Add(new CGUIWindowSystemInfo);
1351 g_windowManager.Add(new CGUIWindowTestPatternGL);
1354 g_windowManager.Add(new CGUIWindowTestPatternDX);
1356 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1357 g_windowManager.Add(new CGUIWindowSettingsCategory);
1358 g_windowManager.Add(new CGUIWindowVideoNav);
1359 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1360 g_windowManager.Add(new CGUIWindowLoginScreen);
1361 g_windowManager.Add(new CGUIWindowSettingsProfile);
1362 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1363 g_windowManager.Add(new CGUIWindowAddonBrowser);
1364 g_windowManager.Add(new CGUIWindowScreensaverDim);
1365 g_windowManager.Add(new CGUIWindowDebugInfo);
1366 g_windowManager.Add(new CGUIWindowPointer);
1367 g_windowManager.Add(new CGUIDialogYesNo);
1368 g_windowManager.Add(new CGUIDialogProgress);
1369 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1370 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1371 g_windowManager.Add(new CGUIDialogVolumeBar);
1372 g_windowManager.Add(new CGUIDialogSeekBar);
1373 g_windowManager.Add(new CGUIDialogSubMenu);
1374 g_windowManager.Add(new CGUIDialogContextMenu);
1375 g_windowManager.Add(new CGUIDialogKaiToast);
1376 g_windowManager.Add(new CGUIDialogNumeric);
1377 g_windowManager.Add(new CGUIDialogGamepad);
1378 g_windowManager.Add(new CGUIDialogButtonMenu);
1379 g_windowManager.Add(new CGUIDialogMuteBug);
1380 g_windowManager.Add(new CGUIDialogPlayerControls);
1382 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1383 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1385 g_windowManager.Add(new CGUIDialogSlider);
1386 g_windowManager.Add(new CGUIDialogMusicOSD);
1387 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1388 g_windowManager.Add(new CGUIDialogVideoSettings);
1389 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1390 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1391 // Don't add the filebrowser dialog - it's created and added when it's needed
1392 g_windowManager.Add(new CGUIDialogNetworkSetup);
1393 g_windowManager.Add(new CGUIDialogMediaSource);
1394 g_windowManager.Add(new CGUIDialogProfileSettings);
1395 g_windowManager.Add(new CGUIDialogFavourites);
1396 g_windowManager.Add(new CGUIDialogSongInfo);
1397 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1398 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1399 g_windowManager.Add(new CGUIDialogBusy);
1400 g_windowManager.Add(new CGUIDialogPictureInfo);
1401 g_windowManager.Add(new CGUIDialogAddonInfo);
1402 g_windowManager.Add(new CGUIDialogAddonSettings);
1403 #ifdef HAS_LINUX_NETWORK
1404 g_windowManager.Add(new CGUIDialogAccessPoints);
1407 g_windowManager.Add(new CGUIDialogLockSettings);
1409 g_windowManager.Add(new CGUIDialogContentSettings);
1411 g_windowManager.Add(new CGUIDialogPlayEject);
1413 g_windowManager.Add(new CGUIDialogPeripheralManager);
1414 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1416 g_windowManager.Add(new CGUIDialogMediaFilter);
1417 g_windowManager.Add(new CGUIDialogSubtitles);
1419 g_windowManager.Add(new CGUIWindowMusicPlayList);
1420 g_windowManager.Add(new CGUIWindowMusicSongs);
1421 g_windowManager.Add(new CGUIWindowMusicNav);
1422 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1424 /* Load PVR related Windows and Dialogs */
1425 g_windowManager.Add(new CGUIDialogTeletext);
1426 g_windowManager.Add(new CGUIWindowPVR);
1427 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1428 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1429 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1430 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1431 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1432 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1433 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1434 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1435 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1436 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1438 g_windowManager.Add(new CGUIDialogSelect);
1439 g_windowManager.Add(new CGUIDialogMusicInfo);
1440 g_windowManager.Add(new CGUIDialogOK);
1441 g_windowManager.Add(new CGUIDialogVideoInfo);
1442 g_windowManager.Add(new CGUIDialogTextViewer);
1443 g_windowManager.Add(new CGUIWindowFullScreen);
1444 g_windowManager.Add(new CGUIWindowVisualisation);
1445 g_windowManager.Add(new CGUIWindowSlideShow);
1446 g_windowManager.Add(new CGUIDialogFileStacking);
1448 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1451 g_windowManager.Add(new CGUIDialogVideoOSD);
1452 g_windowManager.Add(new CGUIDialogMusicOverlay);
1453 g_windowManager.Add(new CGUIDialogVideoOverlay);
1454 g_windowManager.Add(new CGUIWindowScreensaver);
1455 g_windowManager.Add(new CGUIWindowWeather);
1456 g_windowManager.Add(new CGUIWindowStartup);
1458 /* window id's 3000 - 3100 are reserved for python */
1460 // Make sure we have at least the default skin
1461 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1462 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1464 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1468 if (g_advancedSettings.m_splashImage)
1469 SAFE_DELETE(m_splash);
1471 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1472 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1473 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1475 g_passwordManager.CheckStartUpLock();
1478 // check if we should use the login screen
1479 if (CProfilesManager::Get().UsingLoginScreen())
1480 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1484 CJSONRPC::Initialize();
1486 ADDON::CAddonMgr::Get().StartServices(false);
1487 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1489 g_windowManager.ActivateWindow(WINDOW_HOME);
1490 StartPVRManager(true);
1494 StartPVRManager(false);
1495 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1498 CStereoscopicsManager::Get().Initialize();
1502 else //No GUI Created
1505 CJSONRPC::Initialize();
1507 ADDON::CAddonMgr::Get().StartServices(false);
1510 g_sysinfo.Refresh();
1512 CLog::Log(LOGINFO, "removing tempfiles");
1513 CUtil::RemoveTempFiles();
1515 if (!CProfilesManager::Get().UsingLoginScreen())
1521 m_slowTimer.StartZero();
1523 #if defined(HAVE_LIBCRYSTALHD)
1524 CCrystalHD::GetInstance();
1527 CAddonMgr::Get().StartServices(true);
1529 CLog::Log(LOGNOTICE, "initialize done");
1531 m_bInitializing = false;
1533 // reset our screensaver (starts timers etc.)
1536 #ifdef HAS_SDL_JOYSTICK
1537 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1538 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1544 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1550 // the callback will take care of starting/stopping webserver
1551 ret = CSettings::Get().SetBool("services.webserver", bStart);
1554 case ES_AIRPLAYSERVER:
1555 // the callback will take care of starting/stopping airplay
1556 ret = CSettings::Get().SetBool("services.airplay", bStart);
1559 case ES_JSONRPCSERVER:
1560 // the callback will take care of starting/stopping jsonrpc server
1561 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1565 // the callback will take care of starting/stopping upnp server
1566 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1569 case ES_UPNPRENDERER:
1570 // the callback will take care of starting/stopping upnp renderer
1571 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1574 case ES_EVENTSERVER:
1575 // the callback will take care of starting/stopping event server
1576 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1580 // the callback will take care of starting/stopping zeroconf
1581 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1588 CSettings::Get().Save();
1593 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1595 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1596 g_PVRManager.Start(true, bOpenPVRWindow);
1599 void CApplication::StopPVRManager()
1601 CLog::Log(LOGINFO, "stopping PVRManager");
1602 if (g_PVRManager.IsPlaying())
1604 g_PVRManager.Stop();
1605 g_EpgContainer.Stop();
1608 void CApplication::StartServices()
1610 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1611 // Start Thread for DVD Mediatype detection
1612 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1613 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1617 void CApplication::StopServices()
1619 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1621 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1622 CLog::Log(LOGNOTICE, "stop dvd detect media");
1623 m_DetectDVDType.StopThread();
1626 g_peripherals.Clear();
1629 void CApplication::OnSettingChanged(const CSetting *setting)
1631 if (setting == NULL)
1634 const std::string &settingId = setting->GetId();
1635 if (settingId == "lookandfeel.skin" ||
1636 settingId == "lookandfeel.font" ||
1637 settingId == "lookandfeel.skincolors")
1639 // if the skin changes and the current theme is not the default one, reset
1640 // the theme to the default value (which will also change lookandfeel.skincolors
1641 // which in turn will reload the skin. Similarly, if the current skin font is not
1642 // the default, reset it as well.
1643 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1644 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1645 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1646 CSettings::Get().SetString("lookandfeel.font", "Default");
1649 std::string builtin("ReloadSkin");
1650 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1651 builtin += "(confirm)";
1652 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1655 else if (settingId == "lookandfeel.skintheme")
1657 // also set the default color theme
1658 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1659 URIUtils::RemoveExtension(colorTheme);
1660 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1661 colorTheme = "defaults";
1663 // check if we have to change the skin color
1664 // if yes, it will trigger a call to ReloadSkin() in
1665 // it's OnSettingChanged() callback
1666 // if no we have to call ReloadSkin() ourselves
1667 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1668 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1670 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1672 else if (settingId == "lookandfeel.skinzoom")
1674 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1675 g_windowManager.SendThreadMessage(msg);
1677 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1679 // AE is master of audio settings and needs to be informed first
1680 CAEFactory::OnSettingsChange(settingId);
1682 if (settingId == "audiooutput.guisoundmode")
1684 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1686 // this tells player whether to open an audio stream passthrough or PCM
1687 // if this is changed, audio stream has to be reopened
1688 else if (settingId == "audiooutput.passthrough")
1690 CApplicationMessenger::Get().MediaRestart(false);
1693 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1694 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1695 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1696 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1697 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1698 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1699 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1700 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1703 void CApplication::OnSettingAction(const CSetting *setting)
1705 if (setting == NULL)
1708 const std::string &settingId = setting->GetId();
1709 if (settingId == "lookandfeel.skinsettings")
1710 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1711 else if (settingId == "screensaver.preview")
1712 ActivateScreenSaver(true);
1713 else if (settingId == "screensaver.settings")
1716 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1717 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1719 else if (settingId == "videoscreen.guicalibration")
1720 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1721 else if (settingId == "videoscreen.testpattern")
1722 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1725 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1727 if (setting == NULL)
1730 const std::string &settingId = setting->GetId();
1731 if (settingId == "audiooutput.channels")
1733 // check if this is an update from Eden
1734 if (oldSettingId != NULL && oldSettingNode != NULL &&
1735 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1738 CSettingInt* channels = (CSettingInt*)setting;
1739 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1740 ret = channels->SetValue(channels->GetValue() + 1);
1742 // let's just reset the audiodevice settings as well
1743 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1744 CAEFactory::VerifyOutputDevice(audiodevice, false);
1745 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1750 else if (settingId == "screensaver.mode")
1752 CSettingString *screensaverMode = (CSettingString*)setting;
1753 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1754 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1755 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1757 else if (settingId == "scrapers.musicvideosdefault")
1759 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1760 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1762 musicvideoScraper->Reset();
1766 #if defined(HAS_LIBAMCODEC)
1767 else if (settingId == "videoplayer.useamcodec")
1769 // Do not permit amcodec to be used on non-aml platforms.
1770 // The setting will be hidden but the default value is true,
1771 // so change it to false.
1774 CSettingBool *useamcodec = (CSettingBool*)setting;
1775 useamcodec->SetValue(false);
1779 #if defined(TARGET_ANDROID)
1780 else if (settingId == "videoplayer.usemediacodec")
1782 // Do not permit MediaCodec to be used Android platforms that do not have it.
1783 // The setting will be hidden but the default value is true,
1784 // so change it to false.
1785 if (CAndroidFeatures::GetVersion() < 16)
1787 CSettingBool *usemediacodec = (CSettingBool*)setting;
1788 usemediacodec->SetValue(false);
1791 else if (settingId == "videoplayer.usestagefright")
1793 CSettingBool *usestagefright = (CSettingBool*)setting;
1794 usestagefright->SetValue(false);
1801 bool CApplication::OnSettingsSaving() const
1803 // don't save settings when we're busy stopping the application
1804 // a lot of screens try to save settings on deinit and deinit is
1805 // called for every screen when the application is stopping
1812 void CApplication::ReloadSkin(bool confirm/*=false*/)
1814 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1816 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1817 g_windowManager.SendMessage(msg);
1819 string newSkin = CSettings::Get().GetString("lookandfeel.skin");
1820 if (LoadSkin(newSkin))
1822 /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
1823 user as to whether they want to keep the current skin. */
1824 if (confirm && !m_skinReverting)
1827 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1829 m_skinReverting = true;
1830 if (oldSkin.empty())
1831 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1833 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1839 // skin failed to load - we revert to the default only if we didn't fail loading the default
1840 string defaultSkin = ((CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1841 if (newSkin != defaultSkin)
1843 m_skinReverting = true;
1844 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1845 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1848 m_skinReverting = false;
1851 bool CApplication::Load(const TiXmlNode *settings)
1853 if (settings == NULL)
1856 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1857 if (audioElement != NULL)
1859 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1860 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1861 m_volumeLevel = VOLUME_MAXIMUM;
1867 bool CApplication::Save(TiXmlNode *settings) const
1869 if (settings == NULL)
1872 TiXmlElement volumeNode("audio");
1873 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1874 if (audioNode == NULL)
1877 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1878 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1883 bool CApplication::LoadSkin(const CStdString& skinID)
1886 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1888 if (LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
1891 CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
1895 bool CApplication::LoadSkin(const SkinPtr& skin)
1901 if (!skin->HasSkinFile("Home.xml"))
1904 bool bPreviousPlayingState=false;
1905 bool bPreviousRenderingState=false;
1906 if (g_application.m_pPlayer->IsPlayingVideo())
1908 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1909 if (bPreviousPlayingState)
1910 g_application.m_pPlayer->Pause();
1911 #ifdef HAS_VIDEO_PLAYBACK
1912 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1914 g_windowManager.ActivateWindow(WINDOW_HOME);
1915 bPreviousRenderingState = true;
1919 // close the music and video overlays (they're re-opened automatically later)
1920 CSingleLock lock(g_graphicsContext);
1922 // save the current window details and focused control
1923 int currentWindow = g_windowManager.GetActiveWindow();
1925 CGUIWindow* pWindow = g_windowManager.GetWindow(currentWindow);
1927 iCtrlID = pWindow->GetFocusedControlID();
1928 vector<int> currentModelessWindows;
1929 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1933 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
1935 g_SkinInfo->Start();
1937 CLog::Log(LOGINFO, " load fonts for skin...");
1938 g_graphicsContext.SetMediaDir(skin->Path());
1939 g_directoryCache.ClearSubPaths(skin->Path());
1941 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1943 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1945 // load in the skin strings
1946 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1947 URIUtils::AddSlashAtEnd(langPath);
1949 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1951 g_SkinInfo->LoadIncludes();
1954 start = CurrentHostCounter();
1956 CLog::Log(LOGINFO, " load new skin...");
1958 // Load the user windows
1962 end = CurrentHostCounter();
1963 freq = CurrentHostFrequency();
1964 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1966 CLog::Log(LOGINFO, " initialize new skin...");
1967 g_windowManager.AddMsgTarget(this);
1968 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1969 g_windowManager.AddMsgTarget(&g_infoManager);
1970 g_windowManager.AddMsgTarget(&g_fontManager);
1971 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1972 g_windowManager.SetCallback(*this);
1973 g_windowManager.Initialize();
1974 CTextureCache::Get().Initialize();
1975 g_audioManager.Enable(true);
1976 g_audioManager.Load();
1978 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1979 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1981 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1982 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1983 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1984 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1985 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1988 CLog::Log(LOGINFO, " skin loaded...");
1990 // leave the graphics lock
1994 if (currentWindow != WINDOW_INVALID)
1996 g_windowManager.ActivateWindow(currentWindow);
1997 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1999 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2000 if (dialog) dialog->Show();
2004 pWindow = g_windowManager.GetWindow(currentWindow);
2005 if (pWindow && pWindow->HasSaveLastControl())
2007 CGUIMessage msg(GUI_MSG_SETFOCUS, currentWindow, iCtrlID, 0);
2008 pWindow->OnMessage(msg);
2013 if (g_application.m_pPlayer->IsPlayingVideo())
2015 if (bPreviousPlayingState)
2016 g_application.m_pPlayer->Pause();
2017 if (bPreviousRenderingState)
2018 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2023 void CApplication::UnloadSkin(bool forReload /* = false */)
2025 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2027 g_audioManager.Enable(false);
2029 g_windowManager.DeInitialize();
2030 CTextureCache::Get().Deinitialize();
2032 // remove the skin-dependent window
2033 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2035 g_TextureManager.Cleanup();
2036 g_largeTextureManager.CleanupUnusedImages(true);
2038 g_fontManager.Clear();
2040 g_colorManager.Clear();
2042 g_infoManager.Clear();
2044 // The g_SkinInfo boost shared_ptr ought to be reset here
2045 // but there are too many places it's used without checking for NULL
2046 // and as a result a race condition on exit can cause a crash.
2049 bool CApplication::LoadUserWindows()
2051 // Start from wherever home.xml is
2052 std::vector<CStdString> vecSkinPath;
2053 g_SkinInfo->GetSkinPaths(vecSkinPath);
2054 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2056 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2057 CFileItemList items;
2058 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2060 for (int i = 0; i < items.Size(); ++i)
2062 if (items[i]->m_bIsFolder)
2064 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2065 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2067 CXBMCTinyXML xmlDoc;
2068 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2070 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2074 // Root element should be <window>
2075 TiXmlElement* pRootElement = xmlDoc.RootElement();
2076 CStdString strValue = pRootElement->Value();
2077 if (!strValue.Equals("window"))
2079 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2083 // Read the <type> element to get the window type to create
2084 // If no type is specified, create a CGUIWindow as default
2085 CGUIWindow* pWindow = NULL;
2087 if (pRootElement->Attribute("type"))
2088 strType = pRootElement->Attribute("type");
2091 const TiXmlNode *pType = pRootElement->FirstChild("type");
2092 if (pType && pType->FirstChild())
2093 strType = pType->FirstChild()->Value();
2095 int id = WINDOW_INVALID;
2096 if (!pRootElement->Attribute("id", &id))
2098 const TiXmlNode *pType = pRootElement->FirstChild("id");
2099 if (pType && pType->FirstChild())
2100 id = atol(pType->FirstChild()->Value());
2102 CStdString visibleCondition;
2103 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2105 if (strType.Equals("dialog"))
2106 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2107 else if (strType.Equals("submenu"))
2108 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2109 else if (strType.Equals("buttonmenu"))
2110 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2112 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2114 // Check to make sure the pointer isn't still null
2115 if (pWindow == NULL)
2117 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2120 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2125 pWindow->SetVisibleCondition(visibleCondition);
2126 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2127 g_windowManager.AddCustomWindow(pWindow);
2135 bool CApplication::RenderNoPresent()
2139 // DXMERGE: This may have been important?
2140 // g_graphicsContext.AcquireCurrentContext();
2142 g_graphicsContext.Lock();
2144 // dont show GUI when playing full screen video
2145 if (g_graphicsContext.IsFullScreenVideo())
2147 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2148 g_renderManager.Render(true, 0, 255);
2150 // close window overlays
2151 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2152 if (overlay) overlay->Close(true);
2153 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2154 if (overlay) overlay->Close(true);
2158 bool hasRendered = g_windowManager.Render();
2160 g_graphicsContext.Unlock();
2165 float CApplication::GetDimScreenSaverLevel() const
2167 if (!m_bScreenSave || !m_screenSaver ||
2168 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2169 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2170 !m_screenSaver->ID().empty()))
2173 if (!m_screenSaver->GetSetting("level").empty())
2174 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2178 void CApplication::Render()
2180 // do not render if we are stopped or in background
2186 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2188 bool hasRendered = false;
2189 bool limitFrames = false;
2190 unsigned int singleFrameTime = 10; // default limit 100 fps
2194 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2195 // Whether externalplayer is playing and we're unfocused
2196 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2198 m_bPresentFrame = false;
2199 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2201 m_bPresentFrame = g_renderManager.FrameWait(100);
2206 // engage the frame limiter as needed
2207 limitFrames = lowfps || extPlayerActive;
2208 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2209 // perhaps allowing it to be set differently than the UI option??
2210 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2211 limitFrames = true; // not using vsync.
2212 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2213 limitFrames = true; // using vsync, but it isn't working.
2217 if (extPlayerActive)
2219 ResetScreenSaver(); // Prevent screensaver dimming the screen
2220 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2223 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2229 CSingleLock lock(g_graphicsContext);
2230 g_infoManager.UpdateFPS();
2232 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2233 g_Windowing.SetVSync(true);
2234 else if (vsync_mode == VSYNC_ALWAYS)
2235 g_Windowing.SetVSync(true);
2236 else if (vsync_mode != VSYNC_DRIVER)
2237 g_Windowing.SetVSync(false);
2239 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2242 if(!g_Windowing.BeginRender())
2245 g_renderManager.FrameMove();
2247 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2248 if(g_graphicsContext.GetStereoMode())
2250 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2251 if(RenderNoPresent())
2254 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2256 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2257 if(RenderNoPresent())
2260 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2264 if(RenderNoPresent())
2268 g_renderManager.FrameFinish();
2270 g_Windowing.EndRender();
2272 // execute post rendering actions (finalize window closing)
2273 g_windowManager.AfterRender();
2275 // reset our info cache - we do this at the end of Render so that it is
2276 // fresh for the next process(), or after a windowclose animation (where process()
2278 g_infoManager.ResetCache();
2281 unsigned int now = XbmcThreads::SystemClockMillis();
2283 m_lastRenderTime = now;
2285 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2286 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2288 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2289 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2293 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2294 if (limitFrames || !flip)
2297 singleFrameTime = 40; //if not flipping, loop at 25 fps
2299 unsigned int frameTime = now - m_lastFrameTime;
2300 if (frameTime < singleFrameTime)
2301 Sleep(singleFrameTime - frameTime);
2303 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2306 g_graphicsContext.Flip(dirtyRegions);
2307 CTimeUtils::UpdateFrameTime(flip);
2309 g_renderManager.UpdateResolution();
2310 g_renderManager.ManageCaptures();
2313 void CApplication::SetStandAlone(bool value)
2315 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2318 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2319 // The window manager will return true if the event is processed, false otherwise.
2320 // If not already processed, this routine handles global keypresses. It returns
2321 // true if the key has been processed, false otherwise.
2323 bool CApplication::OnKey(const CKey& key)
2326 // Turn the mouse off, as we've just got a keypress from controller or remote
2327 g_Mouse.SetActive(false);
2329 // get the current active window
2330 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2332 // this will be checked for certain keycodes that need
2333 // special handling if the screensaver is active
2334 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2336 // a key has been pressed.
2338 m_idleTimer.StartZero();
2339 bool processKey = AlwaysProcess(action);
2341 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2345 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2346 // do not wake up the screensaver right after switching off the playing device
2347 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2348 ret = CApplicationMessenger::Get().CECToggleState();
2350 ret = CApplicationMessenger::Get().CECStandby();
2351 if (!ret) /* display is switched off */
2357 // allow some keys to be processed while the screensaver is active
2358 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2360 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2364 // change this if we have a dialog up
2365 if (g_windowManager.HasModalDialog())
2367 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2369 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2370 { // fullscreen info dialog - special case
2371 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2373 if (!key.IsAnalogButton())
2374 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2376 if (OnAction(action))
2379 // fallthrough to the main window
2380 iWin = WINDOW_FULLSCREEN_VIDEO;
2382 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2384 // current active window is full screen video.
2385 if (g_application.m_pPlayer->IsInMenu())
2387 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2388 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2390 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2392 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2393 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2395 // if no PVR specific action/mapping is found, fall back to default
2396 if (action.GetID() == 0)
2397 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2401 // in any other case use the fullscreen window section of keymap.xml to map key->action
2402 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2407 // current active window isnt the fullscreen window
2408 // just use corresponding section from keymap.xml
2409 // to map key->action
2411 // first determine if we should use keyboard input directly
2412 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2413 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2416 CGUIControl *control = window->GetFocusedControl();
2419 // If this is an edit control set usekeyboard to true. This causes the
2420 // keypress to be processed directly not through the key mappings.
2421 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2424 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2425 // This causes the keypress to be used for list navigation.
2426 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2432 action = CAction(0); // reset our action
2433 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2435 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2436 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2437 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2438 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2439 action.GetID() == ACTION_MOVE_RIGHT ||
2440 action.GetID() == ACTION_MOVE_UP ||
2441 action.GetID() == ACTION_MOVE_DOWN ||
2442 action.GetID() == ACTION_SELECT_ITEM ||
2443 action.GetID() == ACTION_ENTER ||
2444 action.GetID() == ACTION_PREVIOUS_MENU ||
2445 action.GetID() == ACTION_NAV_BACK))
2447 // the action isn't plain navigation - check for a keyboard-specific keymap
2448 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2449 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2450 action.GetID() == ACTION_BACKSPACE ||
2451 action.GetID() == ACTION_SHIFT ||
2452 action.GetID() == ACTION_SYMBOLS ||
2453 action.GetID() == ACTION_CURSOR_LEFT ||
2454 action.GetID() == ACTION_CURSOR_RIGHT)
2455 action = CAction(0); // don't bother with this action
2458 if (!action.GetID())
2460 // keyboard entry - pass the keys through directly
2461 if (key.GetFromService())
2462 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2465 // Check for paste keypress
2466 #ifdef TARGET_WINDOWS
2467 // In Windows paste is ctrl-V
2468 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2469 #elif defined(TARGET_LINUX)
2470 // In Linux paste is ctrl-V
2471 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2472 #elif defined(TARGET_DARWIN_OSX)
2473 // In OSX paste is cmd-V
2474 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2476 // Placeholder for other operating systems
2479 action = CAction(ACTION_PASTE);
2480 // If the unicode is non-zero the keypress is a non-printing character
2481 else if (key.GetUnicode())
2482 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2483 // The keypress is a non-printing character
2485 action = CAction(key.GetVKey() | KEY_VKEY);
2489 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2491 if (OnAction(action))
2493 // failed to handle the keyboard action, drop down through to standard action
2495 if (key.GetFromService())
2497 if (key.GetButtonCode() != KEY_INVALID)
2498 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2501 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2503 if (!key.IsAnalogButton())
2504 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2506 return ExecuteInputAction(action);
2509 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2510 // This needs to return true if it processed the appcommand or false if it didn't
2511 bool CApplication::OnAppCommand(const CAction &action)
2513 // Reset the screen saver
2516 // If we were currently in the screen saver wake up and don't process the appcommand
2517 if (WakeUpScreenSaverAndDPMS())
2520 // The action ID is the APPCOMMAND code. We need to retrieve the action
2521 // associated with this appcommand from the mapping table.
2522 uint32_t appcmd = action.GetID();
2523 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2524 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2525 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2527 // If we couldn't find an action return false to indicate we have not
2528 // handled this appcommand
2529 if (!appcmdaction.GetID())
2531 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2535 // Process the appcommand
2536 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2537 OnAction(appcmdaction);
2539 // Always return true regardless of whether the action succeeded or not.
2540 // This stops Windows handling the appcommand itself.
2544 bool CApplication::OnAction(const CAction &action)
2546 // special case for switching between GUI & fullscreen mode.
2547 if (action.GetID() == ACTION_SHOW_GUI)
2548 { // Switch to fullscreen mode if we can
2549 if (SwitchToFullScreen())
2551 m_navigationTimer.StartZero();
2556 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2558 g_graphicsContext.ToggleFullScreenRoot();
2562 if (action.IsMouse())
2563 g_Mouse.SetActive(true);
2566 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2568 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2570 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2572 CGUIDialogVideoBookmarks::OnAddBookmark();
2575 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2576 // playing or ACTION_PLAYER_PLAY if we are not playing.
2577 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2579 if (m_pPlayer->IsPlaying())
2580 return OnAction(CAction(ACTION_PAUSE));
2582 return OnAction(CAction(ACTION_PLAYER_PLAY));
2585 //if the action would start or stop inertial scrolling
2586 //by gesture - bypass the normal OnAction handler of current window
2587 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2590 // just pass the action to the current window and let it handle it
2591 if (g_windowManager.OnAction(action))
2593 m_navigationTimer.StartZero();
2598 // handle extra global presses
2600 // screenshot : take a screenshot :)
2601 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2603 CScreenShot::TakeScreenshot();
2606 // built in functions : execute the built-in
2607 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2609 CBuiltins::Execute(action.GetName());
2610 m_navigationTimer.StartZero();
2615 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2617 CButtonTranslator::GetInstance().Clear();
2618 CButtonTranslator::GetInstance().Load();
2621 // show info : Shows the current video or song information
2622 if (action.GetID() == ACTION_SHOW_INFO)
2624 g_infoManager.ToggleShowInfo();
2628 // codec info : Shows the current song, video or picture codec information
2629 if (action.GetID() == ACTION_SHOW_CODEC)
2631 g_infoManager.ToggleShowCodec();
2635 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2637 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2640 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2641 char rating = tag->GetRating();
2642 bool needsUpdate(false);
2643 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2645 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2648 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2650 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2656 if (db.Open()) // OpenForWrite() ?
2658 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2661 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2662 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2663 g_windowManager.SendMessage(msg);
2669 // Now check with the playlist player if action can be handled.
2670 // In case of the action PREV_ITEM, we only allow the playlist player to take it if we're less than 3 seconds into playback.
2671 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2673 if (g_playlistPlayer.OnAction(action))
2677 // Now check with the player if action can be handled.
2678 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2679 (g_windowManager.GetActiveWindow() == WINDOW_DIALOG_VIDEO_OSD && (action.GetID() == ACTION_NEXT_ITEM || action.GetID() == ACTION_PREV_ITEM || action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)) ||
2680 action.GetID() == ACTION_STOP)
2682 if (m_pPlayer->OnAction(action))
2684 // Player ignored action; popup the OSD
2685 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2686 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2687 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2690 // stop : stops playing current audio song
2691 if (action.GetID() == ACTION_STOP)
2697 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2698 // If so, we just jump to the start of the track.
2699 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2702 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2706 // forward action to g_PVRManager and break if it was able to handle it
2707 if (g_PVRManager.OnAction(action))
2710 // forward action to graphic context and see if it can handle it
2711 if (CStereoscopicsManager::Get().OnAction(action))
2714 if (m_pPlayer->IsPlaying())
2716 // forward channel switches to the player - he knows what to do
2717 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2719 m_pPlayer->OnAction(action);
2723 // pause : pauses current audio song
2724 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2728 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2730 if (!m_pPlayer->IsPaused())
2731 { // unpaused - set the playspeed back to normal
2732 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2734 g_audioManager.Enable(m_pPlayer->IsPaused());
2737 if (!m_pPlayer->IsPaused())
2739 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2740 // if we are playing at normal speed, then allow play to pause
2741 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2743 if (m_pPlayer->GetPlaySpeed() != 1)
2745 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2753 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2755 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2756 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2758 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2760 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2765 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2767 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2770 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2773 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2775 // calculate the speed based on the amount the button is held down
2776 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2777 // returns 0 -> MAX_FFWD_SPEED
2778 int iSpeed = 1 << iPower;
2779 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2781 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2783 CLog::Log(LOGDEBUG,"Resetting playspeed");
2787 // allow play to unpause
2790 if (action.GetID() == ACTION_PLAYER_PLAY)
2792 // unpause, and set the playspeed back to normal
2794 g_audioManager.Enable(m_pPlayer->IsPaused());
2796 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2801 // record current file
2802 if (action.GetID() == ACTION_RECORD)
2804 if (m_pPlayer->CanRecord())
2805 m_pPlayer->Record(!m_pPlayer->IsRecording());
2808 if (m_playerController->OnAction(action))
2813 if (action.GetID() == ACTION_SWITCH_PLAYER)
2815 if(m_pPlayer->IsPlaying())
2817 VECPLAYERCORES cores;
2818 CFileItem item(*m_itemCurrentFile.get());
2819 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2820 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2821 if(core != EPC_NONE)
2823 g_application.m_eForcedNextPlayer = core;
2824 item.m_lStartOffset = (int)(GetTime() * 75);
2825 PlayFile(item, true);
2830 VECPLAYERCORES cores;
2831 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2832 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2833 if(core != EPC_NONE)
2836 g_application.m_eForcedNextPlayer = core;
2837 PlayFile(item, false);
2842 if (g_peripherals.OnAction(action))
2845 if (action.GetID() == ACTION_MUTE)
2851 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2853 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2854 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2856 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2858 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2859 g_windowManager.SendMessage(msg);
2864 // Check for global volume control
2865 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2867 if (!m_pPlayer->IsPassthrough())
2871 float volume = m_volumeLevel;
2872 // Android has steps based on the max available volume level
2873 #if defined(TARGET_ANDROID)
2874 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2876 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2878 if (action.GetRepeat())
2879 step *= action.GetRepeat() * 50; // 50 fps
2881 if (action.GetID() == ACTION_VOLUME_UP)
2882 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2884 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2885 SetVolume(volume, false);
2887 // show visual feedback of volume change...
2888 ShowVolumeBar(&action);
2891 // Check for global seek control
2892 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2894 if (!m_pPlayer->CanSeek()) return false;
2895 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2898 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2900 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2901 CGUIControlProfiler::Instance().Start();
2904 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2906 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2907 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2908 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2909 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2910 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2916 void CApplication::FrameMove(bool processEvents, bool processGUI)
2922 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2923 float frameTime = m_frameTime.GetElapsedSeconds();
2924 m_frameTime.StartZero();
2925 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2926 if( frameTime > 0.5 ) frameTime = 0.5;
2928 if (processGUI && m_renderGUI)
2930 g_graphicsContext.Lock();
2931 // check if there are notifications to display
2932 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2933 if (toast && toast->DoWork())
2935 if (!toast->IsDialogRunning())
2940 g_graphicsContext.Unlock();
2942 CWinEvents::MessagePump();
2944 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2945 // Read the input from a remote
2946 g_RemoteControl.Update();
2949 // process input actions
2950 ProcessRemote(frameTime);
2951 ProcessGamepad(frameTime);
2952 ProcessEventServer(frameTime);
2953 ProcessPeripherals(frameTime);
2954 if (processGUI && m_renderGUI)
2956 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2957 m_seekHandler->Process();
2960 if (processGUI && m_renderGUI)
2963 g_windowManager.Process(CTimeUtils::GetFrameTime());
2964 g_windowManager.FrameMove();
2968 bool CApplication::ProcessGamepad(float frameTime)
2970 #ifdef HAS_SDL_JOYSTICK
2974 int iWin = GetActiveWindowID();
2976 g_Joystick.Update();
2977 if (g_Joystick.GetButton(bid))
2980 m_idleTimer.StartZero();
2983 if (WakeUpScreenSaverAndDPMS())
2985 g_Joystick.Reset(true);
2990 CStdString actionName;
2992 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2994 CAction action(actionID, 1.0f, 0.0f, actionName);
2996 g_Mouse.SetActive(false);
2997 return ExecuteInputAction(action);
3004 if (g_Joystick.GetAxis(bid))
3006 if (g_Joystick.GetAmount() < 0)
3012 CStdString actionName;
3014 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3017 if (WakeUpScreenSaverAndDPMS())
3022 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3024 g_Mouse.SetActive(false);
3025 return ExecuteInputAction(action);
3029 g_Joystick.ResetAxis(abs(bid));
3033 if (g_Joystick.GetHat(bid, position))
3036 m_idleTimer.StartZero();
3039 if (WakeUpScreenSaverAndDPMS())
3046 CStdString actionName;
3049 bid = position<<16|bid;
3051 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3053 CAction action(actionID, 1.0f, 0.0f, actionName);
3055 g_Mouse.SetActive(false);
3056 return ExecuteInputAction(action);
3063 bool CApplication::ProcessRemote(float frameTime)
3065 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3066 if (g_RemoteControl.GetButton())
3068 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3069 g_RemoteControl.Reset();
3076 bool CApplication::ProcessPeripherals(float frameTime)
3079 if (g_peripherals.GetNextKeypress(frameTime, key))
3084 bool CApplication::ProcessMouse()
3088 if (!g_Mouse.IsActive() || !m_AppFocused)
3091 // Get the mouse command ID
3092 uint32_t mousecommand = g_Mouse.GetAction();
3093 if (mousecommand == ACTION_NOOP)
3096 // Reset the screensaver and idle timers
3097 m_idleTimer.StartZero();
3099 if (WakeUpScreenSaverAndDPMS())
3102 // Retrieve the corresponding action
3103 int iWin = GetActiveWindowID();
3104 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3105 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3107 // Deactivate mouse if non-mouse action
3108 if (!mouseaction.IsMouse())
3109 g_Mouse.SetActive(false);
3111 // Consume ACTION_NOOP.
3112 // Some views or dialogs gets closed after any ACTION and
3113 // a sensitive mouse might cause problems.
3114 if (mouseaction.GetID() == ACTION_NOOP)
3117 // If we couldn't find an action return false to indicate we have not
3118 // handled this mouse action
3119 if (!mouseaction.GetID())
3121 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3125 // Log mouse actions except for move and noop
3126 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3127 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3129 // The action might not be a mouse action. For example wheel moves might
3130 // be mapped to volume up/down in mouse.xml. In this case we do not want
3131 // the mouse position saved in the action.
3132 if (!mouseaction.IsMouse())
3133 return OnAction(mouseaction);
3135 // This is a mouse action so we need to record the mouse position
3136 return OnAction(CAction(mouseaction.GetID(),
3137 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3138 (float)g_Mouse.GetX(),
3139 (float)g_Mouse.GetY(),
3140 (float)g_Mouse.GetDX(),
3141 (float)g_Mouse.GetDY(),
3142 mouseaction.GetName()));
3145 bool CApplication::ProcessEventServer(float frameTime)
3147 #ifdef HAS_EVENT_SERVER
3148 CEventServer* es = CEventServer::GetInstance();
3149 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3152 // process any queued up actions
3153 if (es->ExecuteNextAction())
3155 // reset idle timers
3156 m_idleTimer.StartZero();
3158 WakeUpScreenSaverAndDPMS();
3161 // now handle any buttons or axis
3162 std::string joystickName;
3163 bool isAxis = false;
3164 float fAmount = 0.0;
3166 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3167 // when the action exits XBMC
3168 es = CEventServer::GetInstance();
3169 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3171 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3175 if (joystickName.length() > 0)
3179 if (fabs(fAmount) >= 0.08)
3180 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3182 m_lastAxisMap[joystickName].erase(wKeyID);
3185 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3190 if (wKeyID & ES_FLAG_UNICODE)
3192 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3196 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3197 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3198 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3199 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3200 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3201 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3202 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3203 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3204 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3205 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3206 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3207 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3208 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3209 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3210 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3211 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3213 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3214 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3215 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3218 key.SetFromService(true);
3223 if (m_lastAxisMap.size() > 0)
3225 // Process all the stored axis.
3226 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3228 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3229 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3235 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3237 XBMC_Event newEvent;
3238 newEvent.type = XBMC_MOUSEMOTION;
3239 newEvent.motion.xrel = 0;
3240 newEvent.motion.yrel = 0;
3241 newEvent.motion.state = 0;
3242 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3243 newEvent.motion.x = (uint16_t)pos.x;
3244 newEvent.motion.y = (uint16_t)pos.y;
3245 OnEvent(newEvent); // had to call this to update g_Mouse position
3246 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3253 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3255 #if defined(HAS_EVENT_SERVER)
3256 m_idleTimer.StartZero();
3258 // Make sure to reset screen saver, mouse.
3260 if (WakeUpScreenSaverAndDPMS())
3263 #ifdef HAS_SDL_JOYSTICK
3266 g_Mouse.SetActive(false);
3268 int iWin = GetActiveWindowID();
3270 CStdString actionName;
3271 bool fullRange = false;
3273 // Translate using regular joystick translator.
3274 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3275 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3277 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3283 bool CApplication::ExecuteInputAction(const CAction &action)
3285 bool bResult = false;
3287 // play sound before the action unless the button is held,
3288 // where we execute after the action as held actions aren't fired every time.
3289 if(action.GetHoldTime())
3291 bResult = OnAction(action);
3293 g_audioManager.PlayActionSound(action);
3297 g_audioManager.PlayActionSound(action);
3298 bResult = OnAction(action);
3303 int CApplication::GetActiveWindowID(void)
3305 // Get the currently active window
3306 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3308 // If there is a dialog active get the dialog id instead
3309 if (g_windowManager.HasModalDialog())
3310 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3312 // If the window is FullScreenVideo check for special cases
3313 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3315 // check if we're in a DVD menu
3316 if(g_application.m_pPlayer->IsInMenu())
3317 iWin = WINDOW_VIDEO_MENU;
3318 // check for LiveTV and switch to it's virtual window
3319 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3320 iWin = WINDOW_FULLSCREEN_LIVETV;
3323 // Return the window id
3327 bool CApplication::Cleanup()
3331 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3332 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3333 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3334 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3335 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3336 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3337 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3338 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3339 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3340 g_windowManager.Delete(WINDOW_FILES);
3341 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3342 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3343 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3344 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3345 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3346 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3347 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3348 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3349 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3350 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3351 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3352 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3353 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3354 g_windowManager.Delete(WINDOW_DIALOG_OK);
3355 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3356 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3357 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3358 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3359 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3360 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3361 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3362 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3363 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3364 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3365 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3366 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3367 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3368 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3369 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3370 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3371 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3372 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3373 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3374 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3375 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3376 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3377 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3379 /* Delete PVR related windows and dialogs */
3380 g_windowManager.Delete(WINDOW_PVR);
3381 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3382 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3383 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3387 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3388 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3389 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3390 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3391 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3392 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3393 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3395 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3396 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3397 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3398 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3399 g_windowManager.Delete(WINDOW_VISUALISATION);
3400 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3401 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3402 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3403 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3404 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3405 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3406 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3407 g_windowManager.Delete(WINDOW_SCREENSAVER);
3408 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3409 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3410 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3411 g_windowManager.Delete(WINDOW_SLIDESHOW);
3412 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3413 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3415 g_windowManager.Delete(WINDOW_HOME);
3416 g_windowManager.Delete(WINDOW_PROGRAMS);
3417 g_windowManager.Delete(WINDOW_PICTURES);
3418 g_windowManager.Delete(WINDOW_WEATHER);
3420 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3421 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3422 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3423 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3424 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3425 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3426 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3427 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3428 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3429 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3431 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3432 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3434 CAddonMgr::Get().DeInit();
3436 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3437 CLog::Log(LOGNOTICE, "closing down remote control service");
3438 g_RemoteControl.Disconnect();
3441 CLog::Log(LOGNOTICE, "unload sections");
3443 #ifdef HAS_PERFORMANCE_SAMPLE
3444 CLog::Log(LOGNOTICE, "performance statistics");
3445 m_perfStats.DumpStats();
3448 // Shutdown as much as possible of the
3449 // application, to reduce the leaks dumped
3450 // to the vc output window before calling
3451 // _CrtDumpMemoryLeaks(). Most of the leaks
3452 // shown are no real leaks, as parts of the app
3453 // are still allocated.
3455 g_localizeStrings.Clear();
3456 g_LangCodeExpander.Clear();
3457 g_charsetConverter.clear();
3458 g_directoryCache.Clear();
3459 CButtonTranslator::GetInstance().Clear();
3460 #ifdef HAS_EVENT_SERVER
3461 CEventServer::RemoveInstance();
3463 DllLoaderContainer::Clear();
3464 g_playlistPlayer.Clear();
3465 CSettings::Get().Uninitialize();
3466 g_advancedSettings.Clear();
3469 CXHandle::DumpObjectTracker();
3471 #ifdef HAS_DVD_DRIVE
3472 CLibcdio::ReleaseInstance();
3475 #if defined(TARGET_ANDROID)
3476 // enable for all platforms once it's safe
3477 g_sectionLoader.UnloadAll();
3479 #ifdef _CRTDBG_MAP_ALLOC
3480 _CrtDumpMemoryLeaks();
3481 while(1); // execution ends
3491 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3496 void CApplication::Stop(int exitCode)
3500 CVariant vExitCode(exitCode);
3501 CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
3503 SaveFileState(true);
3505 g_alarmClock.StopThread();
3507 if( m_bSystemScreenSaverEnable )
3508 g_Windowing.EnableSystemScreenSaver(true);
3510 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3511 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3513 // Update the settings information (volume, uptime etc. need saving)
3514 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3516 CLog::Log(LOGNOTICE, "Saving settings");
3517 CSettings::Get().Save();
3520 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3523 m_AppFocused = false;
3524 m_ExitCode = exitCode;
3525 CLog::Log(LOGNOTICE, "stop all");
3527 // cancel any jobs from the jobmanager
3528 CJobManager::GetInstance().CancelJobs();
3530 // stop scanning before we kill the network and so on
3531 if (m_musicInfoScanner->IsScanning())
3532 m_musicInfoScanner->Stop();
3534 if (m_videoInfoScanner->IsScanning())
3535 m_videoInfoScanner->Stop();
3537 CApplicationMessenger::Get().Cleanup();
3539 CLog::Log(LOGNOTICE, "stop player");
3540 m_pPlayer->ClosePlayer();
3542 CAnnouncementManager::Get().Deinitialize();
3548 #if HAS_FILESYTEM_DAAP
3549 CLog::Log(LOGNOTICE, "stop daap clients");
3550 g_DaapClient.Release();
3552 #ifdef HAS_FILESYSTEM_SAP
3553 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3554 g_sapsessions.StopThread();
3557 if(CZeroconfBrowser::IsInstantiated())
3559 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3560 CZeroconfBrowser::GetInstance()->Stop();
3561 CZeroconfBrowser::ReleaseInstance();
3565 CLog::Log(LOGNOTICE, "clean cached files!");
3566 #ifdef HAS_FILESYSTEM_RAR
3567 g_RarManager.ClearCache(true);
3570 #ifdef HAS_FILESYSTEM_SFTP
3571 CSFTPSessionManager::DisconnectAllSessions();
3574 CLog::Log(LOGNOTICE, "unload skin");
3577 #if defined(TARGET_DARWIN_OSX)
3578 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3579 XBMCHelper::GetInstance().Stop();
3582 #if defined(HAVE_LIBCRYSTALHD)
3583 CCrystalHD::RemoveInstance();
3586 g_mediaManager.Stop();
3588 // Stop services before unloading Python
3589 CAddonMgr::Get().StopServices(false);
3591 // stop all remaining scripts; must be done after skin has been unloaded,
3592 // not before some windows still need it when deinitializing during skin
3594 CScriptInvocationManager::Get().Uninitialize();
3596 g_Windowing.DestroyRenderSystem();
3597 g_Windowing.DestroyWindow();
3598 g_Windowing.DestroyWindowSystem();
3600 // shutdown the AudioEngine
3601 CAEFactory::Shutdown();
3602 CAEFactory::UnLoadEngine();
3604 // unregister ffmpeg lock manager call back
3605 av_lockmgr_register(NULL);
3607 CLog::Log(LOGNOTICE, "stopped");
3611 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3614 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3615 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3617 cleanup_emu_environ();
3623 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3625 //If item is a plugin, expand out now and run ourselves again
3626 if (item.IsPlugin())
3628 CFileItem item_new(item);
3629 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3630 return PlayMedia(item_new, iPlaylist);
3633 if (item.IsSmartPlayList())
3635 CFileItemList items;
3636 CUtil::GetRecursiveListing(item.GetPath(), items, "", DIR_FLAG_NO_FILE_DIRS);
3639 CSmartPlaylist smartpl;
3640 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3641 smartpl.OpenAndReadName(item.GetURL());
3643 playlist.Add(items);
3644 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3647 else if (item.IsPlayList() || item.IsInternetStream())
3649 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3651 //is or could be a playlist
3652 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3653 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3658 if (dlgCache->IsCanceled())
3665 if (iPlaylist != PLAYLIST_NONE)
3668 if (item.HasProperty("playlist_starting_track"))
3669 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3670 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3674 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());
3675 if(pPlayList->size())
3676 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3681 //nothing special just play
3682 return PlayFile(item, false) == PLAYBACK_OK;
3686 // For playing a multi-file video. Particularly inefficient
3687 // on startup, as we are required to calculate the length
3688 // of each video, so we open + close each one in turn.
3689 // A faster calculation of video time would improve this
3691 // return value: same with PlayFile()
3692 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3694 if (!item.IsStack())
3695 return PLAYBACK_FAIL;
3699 // case 1: stacked ISOs
3700 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3702 CStackDirectory dir;
3703 CFileItemList movieList;
3704 dir.GetDirectory(item.GetURL(), movieList);
3706 // first assume values passed to the stack
3707 int selectedFile = item.m_lStartPartNumber;
3708 int startoffset = item.m_lStartOffset;
3710 // check if we instructed the stack to resume from default
3711 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3716 CStdString path = item.GetPath();
3717 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3718 path = item.GetProperty("original_listitem_url").asString();
3719 if( dbs.GetResumeBookMark(path, bookmark) )
3721 startoffset = (int)(bookmark.timeInSeconds*75);
3722 selectedFile = bookmark.partNumber;
3727 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3730 // make sure that the selected part is within the boundaries
3731 if (selectedFile <= 0)
3733 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3736 else if (selectedFile > movieList.Size())
3738 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3739 selectedFile = movieList.Size();
3742 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3743 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3744 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3745 *m_stackFileItemToUpdate = item;
3746 return PlayFile(*(movieList[selectedFile - 1]));
3748 // case 2: all other stacks
3751 // see if we have the info in the database
3752 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3753 // then these times will be wrong.
3754 // Also, this is really just a hack for the slow load up times we have
3755 // A much better solution is a fast reader of FPS and fileLength
3756 // that we can use on a file to get it's time.
3758 bool haveTimes(false);
3762 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3763 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3768 // calculate the total time of the stack
3769 CStackDirectory dir;
3770 dir.GetDirectory(item.GetURL(), *m_currentStack);
3772 for (int i = 0; i < m_currentStack->Size(); i++)
3775 (*m_currentStack)[i]->m_lEndOffset = times[i];
3779 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3781 m_currentStack->Clear();
3782 return PLAYBACK_FAIL;
3784 totalTime += duration / 1000;
3785 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3786 times.push_back(totalTime);
3790 double seconds = item.m_lStartOffset / 75.0;
3792 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3793 { // have our times now, so update the dB
3797 dbs.SetStackTimes(item.GetPath(), times);
3799 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3801 // can only resume seek here, not dvdstate
3803 CStdString path = item.GetPath();
3804 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3805 path = item.GetProperty("original_listitem_url").asString();
3806 if( dbs.GetResumeBookMark(path, bookmark) )
3807 seconds = bookmark.timeInSeconds;
3815 *m_itemCurrentFile = item;
3816 m_currentStackPosition = 0;
3817 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3821 // work out where to seek to
3822 for (int i = 0; i < m_currentStack->Size(); i++)
3824 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3826 CFileItem item(*(*m_currentStack)[i]);
3827 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3828 item.m_lStartOffset = (long)(seconds - start) * 75;
3829 m_currentStackPosition = i;
3830 return PlayFile(item, true);
3835 return PlayFile(*(*m_currentStack)[0], true);
3837 return PLAYBACK_FAIL;
3840 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3842 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3843 if (item.GetMimeType().empty())
3844 const_cast<CFileItem&>(item).FillInMimeType();
3848 SaveCurrentFileSettings();
3850 OutputDebugString("new file set audiostream:0\n");
3851 // Switch to default options
3852 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3853 // see if we have saved options in the database
3855 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3856 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3858 *m_itemCurrentFile = item;
3859 m_nextPlaylistItem = -1;
3860 m_currentStackPosition = 0;
3861 m_currentStack->Clear();
3864 CUtil::ClearSubtitles();
3867 if (item.IsDiscStub())
3869 #ifdef HAS_DVD_DRIVE
3870 // Display the Play Eject dialog if there is any optical disc drive
3871 if (g_mediaManager.HasOpticalDrive())
3873 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3874 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3875 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3876 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3880 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3885 if (item.IsPlayList())
3886 return PLAYBACK_FAIL;
3888 if (item.IsPlugin())
3889 { // we modify the item so that it becomes a real URL
3890 CFileItem item_new(item);
3891 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3892 return PlayFile(item_new, false);
3893 return PLAYBACK_FAIL;
3897 if (URIUtils::IsUPnP(item.GetPath()))
3899 CFileItem item_new(item);
3900 if (XFILE::CUPnPDirectory::GetResource(item.GetURL(), item_new))
3901 return PlayFile(item_new, false);
3902 return PLAYBACK_FAIL;
3906 // if we have a stacked set of files, we need to setup our stack routines for
3907 // "seamless" seeking and total time of the movie etc.
3908 // will recall with restart set to true
3910 return PlayStack(item, bRestart);
3912 //Is TuxBox, this should probably be moved to CTuxBoxFile
3915 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3917 if(g_tuxboxService.IsRunning())
3918 g_tuxboxService.Stop();
3920 PlayBackRet ret = PLAYBACK_FAIL;
3922 if(g_tuxbox.CreateNewItem(item, item_new))
3925 // Make sure it doesn't have a player
3926 // so we actually select one normally
3927 m_pPlayer->ResetPlayer();
3929 // keep the tuxbox:// url as playing url
3930 // and give the new url to the player
3931 ret = PlayFile(item_new, true);
3932 if(ret == PLAYBACK_OK)
3934 if(!g_tuxboxService.IsRunning())
3935 g_tuxboxService.Start();
3941 CPlayerOptions options;
3943 if( item.HasProperty("StartPercent") )
3945 double fallback = 0.0f;
3946 if(item.GetProperty("StartPercent").isString())
3947 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3948 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3951 PLAYERCOREID eNewCore = EPC_NONE;
3954 // have to be set here due to playstack using this for starting the file
3955 options.starttime = item.m_lStartOffset / 75.0;
3956 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3957 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3959 if( m_eForcedNextPlayer != EPC_NONE )
3960 eNewCore = m_eForcedNextPlayer;
3961 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3962 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3964 eNewCore = m_pPlayer->GetCurrentPlayer();
3968 options.starttime = item.m_lStartOffset / 75.0;
3972 // open the d/b and retrieve the bookmarks for the current movie
3975 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3977 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3979 options.starttime = 0.0f;
3981 CStdString path = item.GetPath();
3982 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3983 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3984 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3985 path = item.GetProperty("original_listitem_url").asString();
3986 if(dbs.GetResumeBookMark(path, bookmark))
3988 options.starttime = bookmark.timeInSeconds;
3989 options.state = bookmark.playerState;
3992 override with information from the actual item if available. We do this as the VFS (eg plugins)
3993 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3994 should the playerState be required, it is fetched from the database.
3995 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3997 if (item.IsResumePointSet())
3998 options.starttime = item.GetCurrentResumeTime();
4000 else if (item.HasVideoInfoTag())
4002 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4004 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4007 dbs.GetBookMarkForEpisode(*tag, bookmark);
4008 options.starttime = bookmark.timeInSeconds;
4009 options.state = bookmark.playerState;
4016 if (m_eForcedNextPlayer != EPC_NONE)
4017 eNewCore = m_eForcedNextPlayer;
4019 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4022 // this really aught to be inside !bRestart, but since PlayStack
4023 // uses that to init playback, we have to keep it outside
4024 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4025 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4026 { // playing from a playlist by the looks
4027 // don't switch to fullscreen if we are not playing the first item...
4028 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4030 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4032 // TODO - this will fail if user seeks back to first file in stack
4033 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4034 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4036 options.fullscreen = false;
4037 // reset this so we don't think we are resuming on seek
4038 m_itemCurrentFile->m_lStartOffset = 0;
4041 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4043 // reset VideoStartWindowed as it's a temp setting
4044 CMediaSettings::Get().SetVideoStartWindowed(false);
4047 //We have to stop parsing a cdg before mplayer is deallocated
4048 // WHY do we have to do this????
4050 m_pKaraokeMgr->Stop();
4054 CSingleLock lock(m_playStateMutex);
4055 // tell system we are starting a file
4056 m_bPlaybackStarting = true;
4058 // for playing a new item, previous playing item's callback may already
4059 // pushed some delay message into the threadmessage list, they are not
4060 // expected be processed after or during the new item playback starting.
4061 // so we clean up previous playing item's playback callback delay messages here.
4062 int previousMsgsIgnoredByNewPlaying[] = {
4063 GUI_MSG_PLAYBACK_STARTED,
4064 GUI_MSG_PLAYBACK_ENDED,
4065 GUI_MSG_PLAYBACK_STOPPED,
4066 GUI_MSG_PLAYLIST_CHANGED,
4067 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4068 GUI_MSG_PLAYLISTPLAYER_STARTED,
4069 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4070 GUI_MSG_QUEUE_NEXT_ITEM,
4073 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4075 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4078 // We should restart the player, unless the previous and next tracks are using
4079 // one of the players that allows gapless playback (paplayer, dvdplayer)
4080 m_pPlayer->ClosePlayerGapless(eNewCore);
4082 // now reset play state to starting, since we already stopped the previous playing item if there is.
4083 // and from now there should be no playback callback from previous playing item be called.
4084 m_ePlayState = PLAY_STATE_STARTING;
4086 m_pPlayer->CreatePlayer(eNewCore, *this);
4088 PlayBackRet iResult;
4089 if (m_pPlayer->HasPlayer())
4091 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4092 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4093 * increase performance on low powered systems (Atom/ARM).
4097 CJobManager::GetInstance().PauseJobs();
4100 // don't hold graphicscontext here since player
4101 // may wait on another thread, that requires gfx
4102 CSingleExit ex(g_graphicsContext);
4104 iResult = m_pPlayer->OpenFile(item, options);
4108 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4109 iResult = PLAYBACK_FAIL;
4112 if(iResult == PLAYBACK_OK)
4114 if (m_pPlayer->GetPlaySpeed() != 1)
4116 int iSpeed = m_pPlayer->GetPlaySpeed();
4117 m_pPlayer->m_iPlaySpeed = 1;
4118 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4121 // if player has volume control, set it.
4122 if (m_pPlayer->ControlsVolume())
4124 m_pPlayer->SetVolume(m_volumeLevel);
4125 m_pPlayer->SetMute(m_muted);
4128 if( m_pPlayer->IsPlayingAudio() )
4130 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4131 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4134 #ifdef HAS_VIDEO_PLAYBACK
4135 else if( m_pPlayer->IsPlayingVideo() )
4137 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4138 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4140 // if player didn't manange to switch to fullscreen by itself do it here
4141 if( options.fullscreen && g_renderManager.IsStarted()
4142 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4143 SwitchToFullScreen();
4148 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4149 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4150 g_windowManager.PreviousWindow();
4154 #if !defined(TARGET_POSIX)
4155 g_audioManager.Enable(false);
4158 if (item.HasPVRChannelInfoTag())
4159 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4162 CSingleLock lock(m_playStateMutex);
4163 m_bPlaybackStarting = false;
4165 if (iResult == PLAYBACK_OK)
4167 // play state: none, starting; playing; stopped; ended.
4168 // last 3 states are set by playback callback, they are all ignored during starting,
4169 // but we recorded the state, here we can make up the callback for the state.
4170 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4171 switch (m_ePlayState)
4173 case PLAY_STATE_PLAYING:
4174 OnPlayBackStarted();
4176 // FIXME: it seems no meaning to callback started here if there was an started callback
4177 // before this stopped/ended callback we recorded. if we callback started here
4178 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4179 // which will send OnStop announce at once, so currently, just call stopped/ended.
4180 case PLAY_STATE_ENDED:
4183 case PLAY_STATE_STOPPED:
4184 OnPlayBackStopped();
4186 case PLAY_STATE_STARTING:
4187 // neither started nor stopped/ended callback be called, that means the item still
4188 // not started, we need not make up any callback, just leave this and
4189 // let the player callback do its work.
4195 else if (iResult == PLAYBACK_FAIL)
4197 // we send this if it isn't playlistplayer that is doing this
4198 int next = g_playlistPlayer.GetNextSong();
4199 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4202 OnPlayBackStopped();
4203 m_ePlayState = PLAY_STATE_NONE;
4209 void CApplication::OnPlayBackEnded()
4211 CSingleLock lock(m_playStateMutex);
4212 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4213 m_ePlayState = PLAY_STATE_ENDED;
4214 if(m_bPlaybackStarting)
4217 // informs python script currently running playback has ended
4218 // (does nothing if python is not loaded)
4220 g_pythonParser.OnPlayBackEnded();
4223 CVariant data(CVariant::VariantTypeObject);
4225 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4227 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4228 g_windowManager.SendThreadMessage(msg);
4231 void CApplication::OnPlayBackStarted()
4233 CSingleLock lock(m_playStateMutex);
4234 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4235 m_ePlayState = PLAY_STATE_PLAYING;
4236 if(m_bPlaybackStarting)
4240 // informs python script currently running playback has started
4241 // (does nothing if python is not loaded)
4242 g_pythonParser.OnPlayBackStarted();
4245 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4246 g_windowManager.SendThreadMessage(msg);
4249 void CApplication::OnQueueNextItem()
4251 CSingleLock lock(m_playStateMutex);
4252 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4253 if(m_bPlaybackStarting)
4255 // informs python script currently running that we are requesting the next track
4256 // (does nothing if python is not loaded)
4258 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4261 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4262 g_windowManager.SendThreadMessage(msg);
4265 void CApplication::OnPlayBackStopped()
4267 CSingleLock lock(m_playStateMutex);
4268 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4269 m_ePlayState = PLAY_STATE_STOPPED;
4270 if(m_bPlaybackStarting)
4273 // informs python script currently running playback has ended
4274 // (does nothing if python is not loaded)
4276 g_pythonParser.OnPlayBackStopped();
4279 CVariant data(CVariant::VariantTypeObject);
4280 data["end"] = false;
4281 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4283 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4284 g_windowManager.SendThreadMessage(msg);
4287 void CApplication::OnPlayBackPaused()
4290 g_pythonParser.OnPlayBackPaused();
4294 param["player"]["speed"] = 0;
4295 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4296 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4299 void CApplication::OnPlayBackResumed()
4302 g_pythonParser.OnPlayBackResumed();
4306 param["player"]["speed"] = 1;
4307 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4308 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4311 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4314 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4318 param["player"]["speed"] = iSpeed;
4319 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4320 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4323 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4326 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4330 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4331 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4332 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4333 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4334 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4335 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4338 void CApplication::OnPlayBackSeekChapter(int iChapter)
4341 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4345 bool CApplication::IsPlayingFullScreenVideo() const
4347 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4350 bool CApplication::IsFullScreen()
4352 return IsPlayingFullScreenVideo() ||
4353 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4354 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4357 void CApplication::SaveFileState(bool bForeground /* = false */)
4359 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4364 CSaveFileStateJob job(*m_progressTrackingItem,
4365 *m_stackFileItemToUpdate,
4366 m_progressTrackingVideoResumeBookmark,
4367 m_progressTrackingPlayCountUpdate);
4369 // Run job in the foreground to make sure it finishes
4374 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4375 *m_stackFileItemToUpdate,
4376 m_progressTrackingVideoResumeBookmark,
4377 m_progressTrackingPlayCountUpdate);
4378 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4382 void CApplication::UpdateFileState()
4384 // Did the file change?
4385 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4389 // Reset tracking item
4390 m_progressTrackingItem->Reset();
4394 if (m_pPlayer->IsPlaying())
4396 if (m_progressTrackingItem->GetPath() == "")
4399 *m_progressTrackingItem = CurrentFileItem();
4400 m_progressTrackingPlayCountUpdate = false;
4403 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4404 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4405 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4406 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4408 m_progressTrackingPlayCountUpdate = true;
4411 // Check whether we're *really* playing video else we may race when getting eg. stream details
4412 if (m_pPlayer->IsPlayingVideo())
4414 /* Always update streamdetails, except for DVDs where we only update
4415 streamdetails if title length > 15m (Should yield more correct info) */
4416 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4418 CStreamDetails details;
4419 // Update with stream details from player, if any
4420 if (m_pPlayer->GetStreamDetails(details))
4421 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4423 if (m_progressTrackingItem->IsStack())
4424 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4427 // Update bookmark for save
4428 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4429 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4430 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4432 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4433 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4435 // Delete the bookmark
4436 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4439 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4441 // Update the bookmark
4442 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4443 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4448 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4455 void CApplication::StopPlaying()
4457 int iWin = g_windowManager.GetActiveWindow();
4458 if ( m_pPlayer->IsPlaying() )
4462 m_pKaraokeMgr->Stop();
4465 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4466 g_PVRManager.SaveCurrentChannelSettings();
4468 m_pPlayer->CloseFile();
4470 // turn off visualisation window when stopping
4471 if ((iWin == WINDOW_VISUALISATION
4472 || iWin == WINDOW_FULLSCREEN_VIDEO)
4474 g_windowManager.PreviousWindow();
4476 g_partyModeManager.Disable();
4480 void CApplication::ResetSystemIdleTimer()
4482 // reset system idle timer
4483 m_idleTimer.StartZero();
4486 void CApplication::ResetScreenSaver()
4489 m_shutdownTimer.StartZero();
4491 // screen saver timer is reset only if we're not already in screensaver or
4493 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4494 ResetScreenSaverTimer();
4497 void CApplication::ResetScreenSaverTimer()
4499 m_screenSaverTimer.StartZero();
4502 void CApplication::StopScreenSaverTimer()
4504 m_screenSaverTimer.Stop();
4507 bool CApplication::ToggleDPMS(bool manual)
4509 if (manual || (m_dpmsIsManual == manual))
4513 m_dpmsIsActive = false;
4514 m_dpmsIsManual = false;
4515 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSDeactivated");
4516 return m_dpms->DisablePowerSaving();
4520 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4522 m_dpmsIsActive = true;
4523 m_dpmsIsManual = manual;
4524 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSActivated");
4532 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4536 // First reset DPMS, if active
4541 // TODO: if screensaver lock is specified but screensaver is not active
4542 // (DPMS came first), activate screensaver now.
4544 ResetScreenSaverTimer();
4545 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4548 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4552 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4553 CVariant data(bPowerOffKeyPressed);
4554 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4560 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4562 if (m_iScreenSaveLock == 2)
4565 // if Screen saver is active
4566 if (m_bScreenSave && m_screenSaver)
4568 if (m_iScreenSaveLock == 0)
4569 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4570 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4571 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4572 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4574 m_iScreenSaveLock = 2;
4575 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4577 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4579 pWindow->OnMessage(msg);
4581 if (m_iScreenSaveLock == -1)
4583 m_iScreenSaveLock = 0;
4587 // disable screensaver
4588 m_bScreenSave = false;
4589 m_iScreenSaveLock = 0;
4590 ResetScreenSaverTimer();
4592 if (m_screenSaver->ID() == "visualization")
4594 // we can just continue as usual from vis mode
4597 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4599 else if (!m_screenSaver->ID().empty())
4600 { // we're in screensaver window
4601 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4602 g_windowManager.PreviousWindow(); // show the previous window
4603 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4604 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4612 void CApplication::CheckScreenSaverAndDPMS()
4614 if (!m_dpmsIsActive)
4615 g_Windowing.ResetOSScreensaver();
4617 bool maybeScreensaver =
4618 !m_dpmsIsActive && !m_bScreenSave
4619 && !CSettings::Get().GetString("screensaver.mode").empty();
4621 !m_dpmsIsActive && m_dpms->IsSupported()
4622 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4624 // Has the screen saver window become active?
4625 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4627 m_bScreenSave = true;
4628 maybeScreensaver = false;
4631 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4633 WakeUpScreenSaverAndDPMS();
4637 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4639 // See if we need to reset timer.
4640 // * Are we playing a video and it is not paused?
4641 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4642 // * Are we playing some music in fullscreen vis?
4643 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4644 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4646 ResetScreenSaverTimer();
4650 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4652 // DPMS has priority (it makes the screensaver not needed)
4654 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4657 WakeUpScreenSaver();
4659 else if (maybeScreensaver
4660 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4662 ActivateScreenSaver();
4666 // activate the screensaver.
4667 // if forceType is true, we ignore the various conditions that can alter
4668 // the type of screensaver displayed
4669 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4671 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4672 { // just activate the visualisation if user toggled the usemusicvisinstead option
4673 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4677 m_bScreenSave = true;
4679 // Get Screensaver Mode
4680 m_screenSaver.reset();
4681 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4682 m_screenSaver.reset(new CScreenSaver(""));
4684 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverActivated");
4686 // disable screensaver lock from the login screen
4687 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4690 // set to Dim in the case of a dialog on screen or playing video
4691 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4693 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4694 m_screenSaver.reset(new CScreenSaver(""));
4697 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4699 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4701 else if (!m_screenSaver->ID().empty())
4702 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4705 void CApplication::CheckShutdown()
4707 // first check if we should reset the timer
4708 if (m_bInhibitIdleShutdown
4709 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4710 || m_musicInfoScanner->IsScanning()
4711 || m_videoInfoScanner->IsScanning()
4712 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4713 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4715 m_shutdownTimer.StartZero();
4719 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4721 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4722 m_shutdownTimer.Stop();
4725 CApplicationMessenger::Get().Shutdown();
4729 void CApplication::InhibitIdleShutdown(bool inhibit)
4731 m_bInhibitIdleShutdown = inhibit;
4734 bool CApplication::IsIdleShutdownInhibited() const
4736 return m_bInhibitIdleShutdown;
4739 bool CApplication::OnMessage(CGUIMessage& message)
4741 switch ( message.GetMessage() )
4743 case GUI_MSG_NOTIFY_ALL:
4745 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4747 // Update general playlist: Remove DVD playlist items
4748 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4751 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4752 g_windowManager.SendMessage( msg );
4754 // stop the file if it's on dvd (will set the resume point etc)
4755 if (m_itemCurrentFile->IsOnDVD())
4761 case GUI_MSG_PLAYBACK_STARTED:
4763 #ifdef TARGET_DARWIN
4764 DarwinSetScheduling(message.GetMessage());
4766 // reset the seek handler
4767 m_seekHandler->Reset();
4768 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4770 // Update our infoManager with the new details etc.
4771 if (m_nextPlaylistItem >= 0)
4773 // playing an item which is not in the list - player might be stopped already
4775 if (playList.size() <= m_nextPlaylistItem)
4778 // we've started a previously queued item
4779 CFileItemPtr item = playList[m_nextPlaylistItem];
4780 // update the playlist manager
4781 int currentSong = g_playlistPlayer.GetCurrentSong();
4782 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4783 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4784 g_windowManager.SendThreadMessage(msg);
4785 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4786 *m_itemCurrentFile = *item;
4788 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4789 g_partyModeManager.OnSongChange(true);
4792 param["player"]["speed"] = 1;
4793 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4794 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4796 if (m_pPlayer->IsPlayingAudio())
4798 // Start our cdg parser as appropriate
4800 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4802 m_pKaraokeMgr->Stop();
4803 if (m_itemCurrentFile->IsMusicDb())
4805 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4807 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4808 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4811 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4814 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4823 case GUI_MSG_QUEUE_NEXT_ITEM:
4825 // Check to see if our playlist player has a new item for us,
4826 // and if so, we check whether our current player wants the file
4827 int iNext = g_playlistPlayer.GetNextSong();
4828 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4829 if (iNext < 0 || iNext >= playlist.size())
4831 m_pPlayer->OnNothingToQueueNotify();
4832 return true; // nothing to do
4835 // ok, grab the next song
4836 CFileItem file(*playlist[iNext]);
4838 CURL url(file.GetPath());
4839 if (url.GetProtocol() == "plugin")
4840 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4843 if (URIUtils::IsUPnP(file.GetPath()))
4845 if (!XFILE::CUPnPDirectory::GetResource(file.GetURL(), file))
4850 // ok - send the file to the player, if it accepts it
4851 if (m_pPlayer->QueueNextFile(file))
4853 // player accepted the next file
4854 m_nextPlaylistItem = iNext;
4858 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4859 queue the next (if it wants to) and it doesn't keep looping on this song */
4860 g_playlistPlayer.SetCurrentSong(iNext);
4867 case GUI_MSG_PLAYBACK_STOPPED:
4868 case GUI_MSG_PLAYBACK_ENDED:
4869 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4873 m_pKaraokeMgr->Stop();
4875 #ifdef TARGET_DARWIN
4876 DarwinSetScheduling(message.GetMessage());
4878 // first check if we still have items in the stack to play
4879 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4881 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4882 { // just play the next item in the stack
4883 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4888 // In case playback ended due to user eg. skipping over the end, clear
4889 // our resume bookmark here
4890 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4892 // Delete the bookmark
4893 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4896 // reset the current playing file
4897 m_itemCurrentFile->Reset();
4898 g_infoManager.ResetCurrentItem();
4899 m_currentStack->Clear();
4901 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4903 g_playlistPlayer.PlayNext(1, true);
4907 // reset any forced player
4908 m_eForcedNextPlayer = EPC_NONE;
4910 m_pPlayer->ClosePlayer();
4913 m_pPlayer->m_iPlaySpeed = 1;
4916 if (!m_pPlayer->IsPlaying())
4918 g_audioManager.Enable(true);
4921 if (!m_pPlayer->IsPlayingVideo())
4923 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4925 g_windowManager.PreviousWindow();
4929 CSingleLock lock(g_graphicsContext);
4930 // resets to res_desktop or look&feel resolution (including refreshrate)
4931 g_graphicsContext.SetFullScreenVideo(false);
4935 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4937 CSettings::Get().Save(); // save vis settings
4938 WakeUpScreenSaverAndDPMS();
4939 g_windowManager.PreviousWindow();
4942 // DVD ejected while playing in vis ?
4943 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4946 CSettings::Get().Save(); // save vis settings
4947 WakeUpScreenSaverAndDPMS();
4948 g_windowManager.PreviousWindow();
4951 if (IsEnableTestMode())
4952 CApplicationMessenger::Get().Quit();
4957 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4958 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4963 case GUI_MSG_FULLSCREEN:
4964 { // Switch to fullscreen, if we can
4965 SwitchToFullScreen();
4969 case GUI_MSG_EXECUTE:
4970 if (message.GetNumStringParams())
4971 return ExecuteXBMCAction(message.GetStringParam());
4977 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4979 // see if it is a user set string
4981 //We don't know if there is unsecure information in this yet, so we
4982 //postpone any logging
4983 const std::string in_actionStr(actionStr);
4984 CGUIInfoLabel info(actionStr, "");
4985 actionStr = info.GetLabel(0);
4987 // user has asked for something to be executed
4988 if (CBuiltins::HasCommand(actionStr))
4989 CBuiltins::Execute(actionStr);
4992 // try translating the action from our ButtonTranslator
4994 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4996 OnAction(CAction(actionID));
4999 CFileItem item(actionStr, false);
5001 if (item.IsPythonScript())
5002 { // a python script
5003 CScriptInvocationManager::Get().Execute(item.GetPath());
5007 if (item.IsAudio() || item.IsVideo())
5008 { // an audio or video file
5013 //At this point we have given up to translate, so even though
5014 //there may be insecure information, we log it.
5015 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5022 void CApplication::Process()
5026 // dispatch the messages generated by python or other threads to the current window
5027 g_windowManager.DispatchThreadMessages();
5029 // process messages which have to be send to the gui
5030 // (this can only be done after g_windowManager.Render())
5031 CApplicationMessenger::Get().ProcessWindowMessages();
5035 m_loggingIn = false;
5037 // autoexec.py - profile
5038 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5040 if (XFILE::CFile::Exists(strAutoExecPy))
5041 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5043 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5046 // handle any active scripts
5047 CScriptInvocationManager::Get().Process();
5049 // process messages, even if a movie is playing
5050 CApplicationMessenger::Get().ProcessMessages();
5051 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5053 // check how far we are through playing the current item
5054 // and do anything that needs doing (playcount updates etc)
5055 CheckPlayingProgress();
5058 m_pPlayer->DoAudioWork();
5060 // do any processing that isn't needed on each run
5061 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5063 m_slowTimer.Reset();
5067 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5070 // We get called every 500ms
5071 void CApplication::ProcessSlow()
5073 g_powerManager.ProcessEvents();
5075 #if defined(TARGET_DARWIN_OSX)
5076 // There is an issue on OS X that several system services ask the cursor to become visible
5077 // during their startup routines. Given that we can't control this, we hack it in by
5079 if (g_Windowing.IsFullScreen())
5080 { // SDL thinks it's hidden
5085 // Temporarely pause pausable jobs when viewing video/picture
5086 int currentWindow = g_windowManager.GetActiveWindow();
5087 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5089 CJobManager::GetInstance().PauseJobs();
5093 CJobManager::GetInstance().UnPauseJobs();
5096 // Store our file state for use on close()
5099 // Check if we need to activate the screensaver / DPMS.
5100 CheckScreenSaverAndDPMS();
5102 // Check if we need to shutdown (if enabled).
5103 #if defined(TARGET_DARWIN)
5104 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5106 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5112 // check if we should restart the player
5113 CheckDelayedPlayerRestart();
5115 // check if we can unload any unreferenced dlls or sections
5116 if (!m_pPlayer->IsPlayingVideo())
5117 CSectionLoader::UnloadDelayed();
5119 // check for any idle curl connections
5120 g_curlInterface.CheckIdle();
5122 // check for any idle myth sessions
5123 CMythSession::CheckIdle();
5125 #ifdef HAS_FILESYSTEM_HTSP
5126 // check for any idle htsp sessions
5127 HTSP::CHTSPDirectorySession::CheckIdle();
5131 if ( m_pKaraokeMgr )
5132 m_pKaraokeMgr->ProcessSlow();
5135 if (!m_pPlayer->IsPlayingVideo())
5136 g_largeTextureManager.CleanupUnusedImages();
5138 g_TextureManager.FreeUnusedTextures(5000);
5140 #ifdef HAS_DVD_DRIVE
5141 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5142 if (!m_pPlayer->IsPlayingVideo())
5143 m_Autorun->HandleAutorun();
5146 // update upnp server/renderer states
5148 if(UPNP::CUPnP::IsInstantiated())
5149 UPNP::CUPnP::GetInstance()->UpdateState();
5152 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5156 #ifdef HAS_FILESYSTEM_NFS
5157 gNfsConnection.CheckIfIdle();
5160 #ifdef HAS_FILESYSTEM_AFP
5161 gAfpConnection.CheckIfIdle();
5164 #ifdef HAS_FILESYSTEM_SFTP
5165 CSFTPSessionManager::ClearOutIdleSessions();
5168 g_mediaManager.ProcessEvents();
5171 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5172 g_RemoteControl.Initialize();
5175 if (!m_pPlayer->IsPlayingVideo() &&
5176 CSettings::Get().GetInt("general.addonupdates") != AUTO_UPDATES_NEVER)
5177 CAddonInstaller::Get().UpdateRepos();
5179 CAEFactory::GarbageCollect();
5181 // if we don't render the gui there's no reason to start the screensaver.
5182 // that way the screensaver won't kick in if we maximize the XBMC window
5183 // after the screensaver start time.
5185 ResetScreenSaverTimer();
5188 // Global Idle Time in Seconds
5189 // idle time will be resetet if on any OnKey()
5190 // int return: system Idle time in seconds! 0 is no idle!
5191 int CApplication::GlobalIdleTime()
5193 if(!m_idleTimer.IsRunning())
5196 m_idleTimer.StartZero();
5198 return (int)m_idleTimer.GetElapsedSeconds();
5201 float CApplication::NavigationIdleTime()
5203 if (!m_navigationTimer.IsRunning())
5205 m_navigationTimer.Stop();
5206 m_navigationTimer.StartZero();
5208 return m_navigationTimer.GetElapsedSeconds();
5211 void CApplication::DelayedPlayerRestart()
5213 m_restartPlayerTimer.StartZero();
5216 void CApplication::CheckDelayedPlayerRestart()
5218 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5220 m_restartPlayerTimer.Stop();
5221 m_restartPlayerTimer.Reset();
5226 void CApplication::Restart(bool bSamePosition)
5228 // this function gets called when the user changes a setting (like noninterleaved)
5229 // and which means we gotta close & reopen the current playing file
5231 // first check if we're playing a file
5232 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5235 if( !m_pPlayer->HasPlayer() )
5240 // do we want to return to the current position in the file
5241 if (false == bSamePosition)
5243 // no, then just reopen the file and start at the beginning
5244 PlayFile(*m_itemCurrentFile, true);
5248 // else get current position
5249 double time = GetTime();
5251 // get player state, needed for dvd's
5252 CStdString state = m_pPlayer->GetPlayerState();
5254 // set the requested starttime
5255 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5258 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5259 m_pPlayer->SetPlayerState(state);
5262 const CStdString& CApplication::CurrentFile()
5264 return m_itemCurrentFile->GetPath();
5267 CFileItem& CApplication::CurrentFileItem()
5269 return *m_itemCurrentFile;
5272 CFileItem& CApplication::CurrentUnstackedItem()
5274 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5275 return *(*m_currentStack)[m_currentStackPosition];
5277 return *m_itemCurrentFile;
5280 void CApplication::ShowVolumeBar(const CAction *action)
5282 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5287 volumeBar->OnAction(*action);
5291 bool CApplication::IsMuted() const
5293 if (g_peripherals.IsMuted())
5295 return CAEFactory::IsMuted();
5298 void CApplication::ToggleMute(void)
5306 void CApplication::SetMute(bool mute)
5308 if (m_muted != mute)
5315 void CApplication::Mute()
5317 if (g_peripherals.Mute())
5320 CAEFactory::SetMute(true);
5325 void CApplication::UnMute()
5327 if (g_peripherals.UnMute())
5330 CAEFactory::SetMute(false);
5335 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5337 float hardwareVolume = iValue;
5340 hardwareVolume /= 100.0f;
5342 SetHardwareVolume(hardwareVolume);
5346 void CApplication::SetHardwareVolume(float hardwareVolume)
5348 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5349 m_volumeLevel = hardwareVolume;
5351 CAEFactory::SetVolume(hardwareVolume);
5354 float CApplication::GetVolume(bool percentage /* = true */) const
5358 // converts the hardware volume to a percentage
5359 return m_volumeLevel * 100.0f;
5362 return m_volumeLevel;
5365 void CApplication::VolumeChanged() const
5367 CVariant data(CVariant::VariantTypeObject);
5368 data["volume"] = GetVolume();
5369 data["muted"] = m_muted;
5370 CAnnouncementManager::Get().Announce(Application, "xbmc", "OnVolumeChanged", data);
5372 // if player has volume control, set it.
5373 if (m_pPlayer->ControlsVolume())
5375 m_pPlayer->SetVolume(m_volumeLevel);
5376 m_pPlayer->SetMute(m_muted);
5380 int CApplication::GetSubtitleDelay() const
5382 // converts subtitle delay to a percentage
5383 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5386 int CApplication::GetAudioDelay() const
5388 // converts audio delay to a percentage
5389 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5392 // Returns the total time in seconds of the current media. Fractional
5393 // portions of a second are possible - but not necessarily supported by the
5394 // player class. This returns a double to be consistent with GetTime() and
5396 double CApplication::GetTotalTime() const
5400 if (m_pPlayer->IsPlaying())
5402 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5403 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5405 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5411 void CApplication::StopShutdownTimer()
5413 if (m_shutdownTimer.IsRunning())
5414 m_shutdownTimer.Stop();
5417 void CApplication::ResetShutdownTimers()
5419 // reset system shutdown timer
5420 m_shutdownTimer.StartZero();
5422 // delete custom shutdown timer
5423 if (g_alarmClock.HasAlarm("shutdowntimer"))
5424 g_alarmClock.Stop("shutdowntimer", true);
5427 // Returns the current time in seconds of the currently playing media.
5428 // Fractional portions of a second are possible. This returns a double to
5429 // be consistent with GetTotalTime() and SeekTime().
5430 double CApplication::GetTime() const
5434 if (m_pPlayer->IsPlaying())
5436 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5438 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5439 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5442 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5448 // Sets the current position of the currently playing media to the specified
5449 // time in seconds. Fractional portions of a second are valid. The passed
5450 // time is the time offset from the beginning of the file as opposed to a
5451 // delta from the current position. This method accepts a double to be
5452 // consistent with GetTime() and GetTotalTime().
5453 void CApplication::SeekTime( double dTime )
5455 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5457 if (!m_pPlayer->CanSeek()) return;
5458 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5460 // find the item in the stack we are seeking to, and load the new
5461 // file if necessary, and calculate the correct seek within the new
5462 // file. Otherwise, just fall through to the usual routine if the
5463 // time is higher than our total time.
5464 for (int i = 0; i < m_currentStack->Size(); i++)
5466 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5468 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5469 if (m_currentStackPosition == i)
5470 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5472 { // seeking to a new file
5473 m_currentStackPosition = i;
5474 CFileItem item(*(*m_currentStack)[i]);
5475 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5476 // don't just call "PlayFile" here, as we are quite likely called from the
5477 // player thread, so we won't be able to delete ourselves.
5478 CApplicationMessenger::Get().PlayFile(item, true);
5484 // convert to milliseconds and perform seek
5485 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5489 float CApplication::GetPercentage() const
5491 if (m_pPlayer->IsPlaying())
5493 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5495 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5496 if (tag.GetDuration() > 0)
5497 return (float)(GetTime() / tag.GetDuration() * 100);
5500 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5502 double totalTime = GetTotalTime();
5503 if (totalTime > 0.0f)
5504 return (float)(GetTime() / totalTime * 100);
5507 return m_pPlayer->GetPercentage();
5512 float CApplication::GetCachePercentage() const
5514 if (m_pPlayer->IsPlaying())
5516 // Note that the player returns a relative cache percentage and we want an absolute percentage
5517 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5519 float stackedTotalTime = (float) GetTotalTime();
5520 // We need to take into account the stack's total time vs. currently playing file's total time
5521 if (stackedTotalTime > 0.0f)
5522 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5525 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5530 void CApplication::SeekPercentage(float percent)
5532 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5534 if (!m_pPlayer->CanSeek()) return;
5535 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5536 SeekTime(percent * 0.01 * GetTotalTime());
5538 m_pPlayer->SeekPercentage(percent);
5542 // SwitchToFullScreen() returns true if a switch is made, else returns false
5543 bool CApplication::SwitchToFullScreen()
5545 // if playing from the video info window, close it first!
5546 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5548 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5549 if (pDialog) pDialog->Close(true);
5552 // don't switch if there is a dialog on screen or the slideshow is active
5553 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5556 // See if we're playing a video, and are in GUI mode
5557 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5559 // then switch to fullscreen mode
5560 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5563 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5564 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5565 { // then switch to visualisation
5566 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5572 void CApplication::Minimize()
5574 g_Windowing.Minimize();
5577 PLAYERCOREID CApplication::GetCurrentPlayer()
5579 return m_pPlayer->GetCurrentPlayer();
5582 void CApplication::UpdateLibraries()
5584 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5586 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5590 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5592 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5597 bool CApplication::IsVideoScanning() const
5599 return m_videoInfoScanner->IsScanning();
5602 bool CApplication::IsMusicScanning() const
5604 return m_musicInfoScanner->IsScanning();
5607 void CApplication::StopVideoScan()
5609 if (m_videoInfoScanner->IsScanning())
5610 m_videoInfoScanner->Stop();
5613 void CApplication::StopMusicScan()
5615 if (m_musicInfoScanner->IsScanning())
5616 m_musicInfoScanner->Stop();
5619 void CApplication::StartVideoCleanup()
5621 if (m_videoInfoScanner->IsScanning())
5624 m_videoInfoScanner->CleanDatabase();
5627 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5629 if (m_videoInfoScanner->IsScanning())
5632 m_videoInfoScanner->ShowDialog(true);
5634 m_videoInfoScanner->Start(strDirectory,scanAll);
5637 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5639 if (m_musicInfoScanner->IsScanning())
5643 { // setup default flags
5644 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5645 flags |= CMusicInfoScanner::SCAN_ONLINE;
5646 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5647 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5650 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5651 m_musicInfoScanner->ShowDialog(true);
5653 m_musicInfoScanner->Start(strDirectory, flags);
5656 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5659 if (m_musicInfoScanner->IsScanning())
5662 m_musicInfoScanner->ShowDialog(true);
5664 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5667 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5670 if (m_musicInfoScanner->IsScanning())
5673 m_musicInfoScanner->ShowDialog(true);
5675 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5678 void CApplication::CheckPlayingProgress()
5680 // check if we haven't rewound past the start of the file
5681 if (m_pPlayer->IsPlaying())
5683 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5693 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5695 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5696 g_application.SeekTime(0);
5702 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5704 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5706 // initial exit conditions
5707 // no songs in playlist just return
5708 if (playlist.size() == 0)
5712 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5715 // setup correct playlist
5716 g_playlistPlayer.ClearPlaylist(iPlaylist);
5718 // if the playlist contains an internet stream, this file will be used
5719 // to generate a thumbnail for musicplayer.cover
5720 g_application.m_strPlayListFile = strPlayList;
5722 // add the items to the playlist player
5723 g_playlistPlayer.Add(iPlaylist, playlist);
5725 // if we have a playlist
5726 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5729 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5730 g_playlistPlayer.Reset();
5731 g_playlistPlayer.Play(track);
5737 void CApplication::SaveCurrentFileSettings()
5739 // don't store settings for PVR in video database
5740 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5742 // save video settings
5743 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5747 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5751 else if (m_itemCurrentFile->IsPVRChannel())
5753 g_PVRManager.SaveCurrentChannelSettings();
5757 bool CApplication::AlwaysProcess(const CAction& action)
5759 // check if this button is mapped to a built-in function
5760 if (!action.GetName().empty())
5762 CStdString builtInFunction;
5763 vector<string> params;
5764 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5765 StringUtils::ToLower(builtInFunction);
5767 // should this button be handled normally or just cancel the screensaver?
5768 if ( builtInFunction.Equals("powerdown")
5769 || builtInFunction.Equals("reboot")
5770 || builtInFunction.Equals("restart")
5771 || builtInFunction.Equals("restartapp")
5772 || builtInFunction.Equals("suspend")
5773 || builtInFunction.Equals("hibernate")
5774 || builtInFunction.Equals("quit")
5775 || builtInFunction.Equals("shutdown"))
5784 bool CApplication::IsCurrentThread() const
5786 return CThread::IsCurrentThread(m_threadID);
5789 void CApplication::SetRenderGUI(bool renderGUI)
5791 if (renderGUI && ! m_renderGUI)
5792 g_windowManager.MarkDirty();
5793 m_renderGUI = renderGUI;
5796 CNetwork& CApplication::getNetwork()
5800 #ifdef HAS_PERFORMANCE_SAMPLE
5801 CPerformanceStats &CApplication::GetPerformanceStats()
5807 bool CApplication::SetLanguage(const CStdString &strLanguage)
5809 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5810 if (strLanguage != strPreviousLanguage)
5812 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
5813 if (!g_langInfo.Load(strLangInfoPath))
5816 CSettings::Get().SetString("locale.language", strLanguage);
5818 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
5821 // also tell our weather and skin to reload as these are localized
5822 g_weatherManager.Refresh();
5823 g_PVRManager.LocalizationChanged();
5830 void CApplication::CloseNetworkShares()
5832 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5834 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5838 #ifdef HAS_FILESYSTEM_NFS
5839 gNfsConnection.Deinit();
5842 #ifdef HAS_FILESYSTEM_AFP
5843 gAfpConnection.Deinit();
5846 #ifdef HAS_FILESYSTEM_SFTP
5847 CSFTPSessionManager::DisconnectAllSessions();