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();
601 // Utility function used to copy files from the application bundle
602 // over to the user data directory in Application Support/XBMC.
604 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
606 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
607 if (!CFile::Exists(destPath))
609 // need to copy it across
610 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
611 CFile::Copy(srcPath, destPath);
615 void CApplication::Preflight()
618 // call 'dbus_threads_init_default' before any other dbus calls in order to
619 // avoid race conditions with other threads using dbus connections
620 dbus_threads_init_default();
623 // run any platform preflight scripts.
624 #if defined(TARGET_DARWIN_OSX)
625 CStdString install_path;
627 CUtil::GetHomePath(install_path);
628 setenv("XBMC_HOME", install_path.c_str(), 0);
629 install_path += "/tools/darwin/runtime/preflight";
630 system(install_path.c_str());
634 bool CApplication::Create()
636 #if defined(HAS_LINUX_NETWORK)
637 m_network = new CNetworkLinux();
638 #elif defined(HAS_WIN32_NETWORK)
639 m_network = new CNetworkWin32();
641 m_network = new CNetwork();
646 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
648 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
649 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
653 tzset(); // Initialize timezone information variables
656 // Grab a handle to our thread to be used later in identifying the render thread.
657 m_threadID = CThread::GetCurrentThreadId();
660 //floating point precision to 24 bits (faster performance)
661 _controlfp(_PC_24, _MCW_PC);
663 /* install win32 exception translator, win32 exceptions
664 * can now be caught using c++ try catch */
665 win32_exception::install_handler();
669 // only the InitDirectories* for the current platform should return true
670 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
671 bool inited = InitDirectoriesLinux();
673 inited = InitDirectoriesOSX();
675 inited = InitDirectoriesWin32();
677 // copy required files
678 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
679 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
680 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
682 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
684 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
685 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
689 // Init our DllLoaders emu env
692 CProfilesManager::Get().Load();
694 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
695 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(),
696 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness());
698 std::string buildType;
701 #elif defined(NDEBUG)
702 buildType = "Release";
704 buildType = "Unknown";
706 std::string specialVersion;
707 #if defined(TARGET_DARWIN_IOS_ATV2)
708 specialVersion = " (version for AppleTV2)";
709 #elif defined(TARGET_RASPBERRY_PI)
710 specialVersion = " (version for Raspberry Pi)";
711 //#elif defined(some_ID) // uncomment for special version/fork
712 // specialVersion = " (version for XXXX)";
714 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build%s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), specialVersion.c_str());
715 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(),
716 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersionDecoded().c_str(),
717 g_sysinfo.GetBuildTargetPlatformVersion().c_str());
719 std::string deviceModel(g_sysinfo.GetModelName());
720 if (!g_sysinfo.GetManufacturerName().empty())
721 deviceModel = g_sysinfo.GetManufacturerName() + " " + (deviceModel.empty() ? std::string("device") : deviceModel);
722 if (!deviceModel.empty())
723 CLog::Log(LOGNOTICE, "Running on %s with %s, kernel: %s %s %d-bit version %s", deviceModel.c_str(), g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
724 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
726 CLog::Log(LOGNOTICE, "Running on %s, kernel: %s %s %d-bit version %s", g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
727 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
729 #if defined(TARGET_LINUX)
730 #if USE_STATIC_FFMPEG
731 CLog::Log(LOGNOTICE, "FFmpeg statically linked, version: %s", FFMPEG_VERSION);
732 #else // !USE_STATIC_FFMPEG
733 CLog::Log(LOGNOTICE, "FFmpeg version: %s", FFMPEG_VERSION);
734 #endif // !USE_STATIC_FFMPEG
735 if (!strstr(FFMPEG_VERSION, FFMPEG_VER_SHA))
737 if (strstr(FFMPEG_VERSION, "xbmc"))
738 CLog::Log(LOGNOTICE, "WARNING: unknown ffmpeg-xbmc version detected");
740 CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected");
744 std::string cpuModel(g_cpuInfo.getCPUModel());
745 if (!cpuModel.empty())
746 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
748 CLog::Log(LOGNOTICE, "%d CPU core%s available", g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
749 #if defined(TARGET_WINDOWS)
750 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
751 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
752 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
754 #if defined(TARGET_ANDROID)
756 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
757 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
758 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
762 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
763 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
765 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
767 CSpecialProtocol::LogPaths();
769 CStdString executable = CUtil::ResolveExecutablePath();
770 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
771 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
772 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
773 CRegExp::LogCheckUtf8Support();
774 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
776 CStdString strExecutablePath;
777 CUtil::GetHomePath(strExecutablePath);
780 g_xrandr.LoadCustomModeLinesToAllOutputs();
783 // for python scripts that check the OS
784 #if defined(TARGET_DARWIN)
785 setenv("OS","OS X",true);
786 #elif defined(TARGET_POSIX)
787 setenv("OS","Linux",true);
788 #elif defined(TARGET_WINDOWS)
789 CEnvironment::setenv("OS", "win32");
792 // register ffmpeg lockmanager callback
793 av_lockmgr_register(&ffmpeg_lockmgr_cb);
795 avcodec_register_all();
799 avfilter_register_all();
800 // set avutil callback
801 av_log_set_callback(ff_avutil_log);
803 g_powerManager.Initialize();
805 // Load the AudioEngine before settings as they need to query the engine
806 if (!CAEFactory::LoadEngine())
808 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
812 // Initialize default Settings - don't move
813 CLog::Log(LOGNOTICE, "load settings...");
814 if (!CSettings::Get().Initialize())
817 g_powerManager.SetDefaults();
819 // load the actual values
820 if (!CSettings::Get().Load())
822 CLog::Log(LOGFATAL, "unable to load settings");
825 CSettings::Get().SetLoaded();
827 CLog::Log(LOGINFO, "creating subdirectories");
828 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
829 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
830 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
831 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
832 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
833 CProfilesManager::Get().CreateProfileFolders();
835 update_emu_environ();//apply the GUI settings
837 // Load the langinfo to have user charset <-> utf-8 conversion
838 CStdString strLanguage = CSettings::Get().GetString("locale.language");
839 strLanguage[0] = toupper(strLanguage[0]);
841 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
843 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
844 g_langInfo.Load(strLangInfoPath);
845 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
846 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
848 CStdString strLanguagePath = "special://xbmc/language/";
850 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
851 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
853 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
857 // start the AudioEngine
858 if (!CAEFactory::StartEngine())
860 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
864 // restore AE's previous volume state
865 SetHardwareVolume(m_volumeLevel);
866 CAEFactory::SetMute (m_muted);
867 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
869 // initialize m_replayGainSettings
870 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
871 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
872 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
873 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
875 // initialize the addon database (must be before the addon manager is init'd)
876 CDatabaseManager::Get().Initialize(true);
879 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
882 // start-up Addons Framework
883 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
884 if (!CAddonMgr::Get().Init())
886 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
889 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
890 g_RemoteControl.Initialize();
893 g_peripherals.Initialise();
895 // Create the Mouse, Keyboard, Remote, and Joystick devices
896 // Initialize after loading settings to get joystick deadzone setting
897 g_Mouse.Initialize();
898 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
900 g_Keyboard.Initialize();
902 #if defined(TARGET_DARWIN_OSX)
903 // Configure and possible manually start the helper.
904 XBMCHelper::GetInstance().Configure();
907 CUtil::InitRandomSeed();
909 g_mediaManager.Initialize();
911 m_lastFrameTime = XbmcThreads::SystemClockMillis();
912 m_lastRenderTime = m_lastFrameTime;
916 bool CApplication::CreateGUI()
920 CLog::Log(LOGNOTICE, "Setup SDL");
922 /* Clean up on exit, exit on window close and interrupt */
925 uint32_t sdlFlags = 0;
927 #if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX)
928 sdlFlags |= SDL_INIT_VIDEO;
931 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
932 sdlFlags |= SDL_INIT_JOYSTICK;
935 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
936 //this might bring the monitor out of standby, so we have to disable it explicitly
937 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
938 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
939 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
945 // for nvidia cards - vsync currently ALWAYS enabled.
946 // the reason is that after screen has been setup changing this env var will make no difference.
947 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
948 setenv("__GL_YIELD", "USLEEP", 0);
951 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
952 g_Windowing.EnableSystemScreenSaver(false);
955 if (SDL_Init(sdlFlags) != 0)
957 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
960 #if defined(TARGET_DARWIN)
961 // SDL_Init will install a handler for segfaults, restore the default handler.
962 signal(SIGSEGV, SIG_DFL);
966 // Initialize core peripheral port support. Note: If these parameters
967 // are 0 and NULL, respectively, then the default number and types of
968 // controllers will be initialized.
969 if (!g_Windowing.InitWindowSystem())
971 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
975 // Retrieve the matching resolution based on GUI settings
976 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
977 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
978 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
980 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
981 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
984 // update the window resolution
985 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
987 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
988 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
990 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
992 // Oh uh - doesn't look good for starting in their wanted screenmode
993 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
994 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
1001 if (g_advancedSettings.m_splashImage)
1003 CStdString strUserSplash = "special://home/media/Splash.png";
1004 if (CFile::Exists(strUserSplash))
1006 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
1007 m_splash = new CSplash(strUserSplash);
1011 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1012 m_splash = new CSplash("special://xbmc/media/Splash.png");
1017 // The key mappings may already have been loaded by a peripheral
1018 CLog::Log(LOGINFO, "load keymapping");
1019 if (!CButtonTranslator::GetInstance().Load())
1022 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1023 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1026 info.strMode.c_str());
1027 g_windowManager.Initialize();
1032 bool CApplication::InitWindow()
1034 #ifdef TARGET_DARWIN_OSX
1035 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1036 // fixes the white screen of death if starting fullscreen and switching to windowed.
1037 bool bFullScreen = false;
1038 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1040 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1044 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1045 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1047 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1052 if (!g_Windowing.InitRenderSystem())
1054 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1057 // set GUI res and force the clear of the screen
1058 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1062 bool CApplication::DestroyWindow()
1064 return g_Windowing.DestroyWindow();
1067 bool CApplication::InitDirectoriesLinux()
1070 The following is the directory mapping for Platform Specific Mode:
1072 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1073 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1074 installations like skins, screensavers, etc.
1076 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1077 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1078 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1079 special://profile/ => [read-write] current profile's userdata directory.
1080 Generally special://masterprofile for the master profile or
1081 special://masterprofile/profiles/<profile_name> for other profiles.
1083 NOTE: All these root directories are lowercase. Some of the sub-directories
1084 might be mixed case.
1087 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1088 CStdString userName;
1090 userName = getenv("USER");
1094 CStdString userHome;
1096 userHome = getenv("HOME");
1100 CStdString xbmcBinPath, xbmcPath;
1101 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1102 xbmcPath = getenv("XBMC_HOME");
1104 if (xbmcPath.empty())
1106 xbmcPath = xbmcBinPath;
1107 /* Check if xbmc binaries and arch independent data files are being kept in
1108 * separate locations. */
1109 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1111 /* Attempt to locate arch independent data files. */
1112 CUtil::GetHomePath(xbmcPath);
1113 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1115 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1121 /* Set some environment variables */
1122 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1123 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1125 if (m_bPlatformDirectories)
1127 // map our special drives
1128 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1129 CSpecialProtocol::SetXBMCPath(xbmcPath);
1130 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1131 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1133 CStdString strTempPath = userHome;
1134 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1135 if (getenv("XBMC_TEMP"))
1136 strTempPath = getenv("XBMC_TEMP");
1137 CSpecialProtocol::SetTempPath(strTempPath);
1139 URIUtils::AddSlashAtEnd(strTempPath);
1140 g_advancedSettings.m_logFolder = strTempPath;
1147 URIUtils::AddSlashAtEnd(xbmcPath);
1148 g_advancedSettings.m_logFolder = xbmcPath;
1150 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1151 CSpecialProtocol::SetXBMCPath(xbmcPath);
1152 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1153 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1155 CStdString strTempPath = xbmcPath;
1156 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1157 if (getenv("XBMC_TEMP"))
1158 strTempPath = getenv("XBMC_TEMP");
1159 CSpecialProtocol::SetTempPath(strTempPath);
1162 URIUtils::AddSlashAtEnd(strTempPath);
1163 g_advancedSettings.m_logFolder = strTempPath;
1172 bool CApplication::InitDirectoriesOSX()
1174 #if defined(TARGET_DARWIN)
1175 CStdString userName;
1177 userName = getenv("USER");
1181 CStdString userHome;
1183 userHome = getenv("HOME");
1187 CStdString xbmcPath;
1188 CUtil::GetHomePath(xbmcPath);
1189 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1191 #if defined(TARGET_DARWIN_IOS)
1192 CStdString fontconfigPath;
1193 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1194 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1197 // setup path to our internal dylibs so loader can find them
1198 CStdString frameworksPath = CUtil::GetFrameworksPath();
1199 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1201 // OSX always runs with m_bPlatformDirectories == true
1202 if (m_bPlatformDirectories)
1204 // map our special drives
1205 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1206 CSpecialProtocol::SetXBMCPath(xbmcPath);
1207 #if defined(TARGET_DARWIN_IOS)
1208 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1209 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1211 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1212 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1215 // location for temp files
1216 #if defined(TARGET_DARWIN_IOS)
1217 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1219 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1220 CDirectory::Create(strTempPath);
1221 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1223 CSpecialProtocol::SetTempPath(strTempPath);
1225 // xbmc.log file location
1226 #if defined(TARGET_DARWIN_IOS)
1227 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1229 strTempPath = userHome + "/Library/Logs";
1231 URIUtils::AddSlashAtEnd(strTempPath);
1232 g_advancedSettings.m_logFolder = strTempPath;
1238 URIUtils::AddSlashAtEnd(xbmcPath);
1239 g_advancedSettings.m_logFolder = xbmcPath;
1241 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1242 CSpecialProtocol::SetXBMCPath(xbmcPath);
1243 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1244 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1246 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1247 CSpecialProtocol::SetTempPath(strTempPath);
1249 URIUtils::AddSlashAtEnd(strTempPath);
1250 g_advancedSettings.m_logFolder = strTempPath;
1259 bool CApplication::InitDirectoriesWin32()
1261 #ifdef TARGET_WINDOWS
1262 CStdString xbmcPath;
1264 CUtil::GetHomePath(xbmcPath);
1265 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1266 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1267 CSpecialProtocol::SetXBMCPath(xbmcPath);
1269 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1271 g_advancedSettings.m_logFolder = strWin32UserFolder;
1272 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1273 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1274 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1276 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1280 // Expand the DLL search path with our directories
1281 CWIN32Util::ExtendDllPath();
1289 void CApplication::CreateUserDirs()
1291 CDirectory::Create("special://home/");
1292 CDirectory::Create("special://home/addons");
1293 CDirectory::Create("special://home/addons/packages");
1294 CDirectory::Create("special://home/media");
1295 CDirectory::Create("special://home/sounds");
1296 CDirectory::Create("special://home/system");
1297 CDirectory::Create("special://masterprofile/");
1298 CDirectory::Create("special://temp/");
1299 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1302 bool CApplication::Initialize()
1304 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1305 // turn off cdio logging
1306 cdio_loglevel_default = CDIO_LOG_ERROR;
1309 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1310 // must create these here. Ideally this should be using special://home/ and
1311 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1312 if (!m_bPlatformDirectories)
1315 CDirectory::Create("special://xbmc/language");
1316 CDirectory::Create("special://xbmc/addons");
1317 CDirectory::Create("special://xbmc/sounds");
1320 // Load curl so curl_global_init gets called before any service threads
1321 // are started. Unloading will have no effect as curl is never fully unloaded.
1322 // To quote man curl_global_init:
1323 // "This function is not thread safe. You must not call it when any other
1324 // thread in the program (i.e. a thread sharing the same memory) is running.
1325 // This doesn't just mean no other thread that is using libcurl. Because
1326 // curl_global_init() calls functions of other libraries that are similarly
1327 // thread unsafe, it could conflict with any other thread that
1328 // uses these other libraries."
1329 g_curlInterface.Load();
1330 g_curlInterface.Unload();
1332 // initialize (and update as needed) our databases
1333 CDatabaseManager::Get().Initialize();
1337 // Init DPMS, before creating the corresponding setting control.
1338 m_dpms = new DPMSSupport();
1339 if (g_windowManager.Initialized())
1341 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1343 g_windowManager.Add(new CGUIWindowHome);
1344 g_windowManager.Add(new CGUIWindowPrograms);
1345 g_windowManager.Add(new CGUIWindowPictures);
1346 g_windowManager.Add(new CGUIWindowFileManager);
1347 g_windowManager.Add(new CGUIWindowSettings);
1348 g_windowManager.Add(new CGUIWindowSystemInfo);
1350 g_windowManager.Add(new CGUIWindowTestPatternGL);
1353 g_windowManager.Add(new CGUIWindowTestPatternDX);
1355 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1356 g_windowManager.Add(new CGUIWindowSettingsCategory);
1357 g_windowManager.Add(new CGUIWindowVideoNav);
1358 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1359 g_windowManager.Add(new CGUIWindowLoginScreen);
1360 g_windowManager.Add(new CGUIWindowSettingsProfile);
1361 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1362 g_windowManager.Add(new CGUIWindowAddonBrowser);
1363 g_windowManager.Add(new CGUIWindowScreensaverDim);
1364 g_windowManager.Add(new CGUIWindowDebugInfo);
1365 g_windowManager.Add(new CGUIWindowPointer);
1366 g_windowManager.Add(new CGUIDialogYesNo);
1367 g_windowManager.Add(new CGUIDialogProgress);
1368 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1369 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1370 g_windowManager.Add(new CGUIDialogVolumeBar);
1371 g_windowManager.Add(new CGUIDialogSeekBar);
1372 g_windowManager.Add(new CGUIDialogSubMenu);
1373 g_windowManager.Add(new CGUIDialogContextMenu);
1374 g_windowManager.Add(new CGUIDialogKaiToast);
1375 g_windowManager.Add(new CGUIDialogNumeric);
1376 g_windowManager.Add(new CGUIDialogGamepad);
1377 g_windowManager.Add(new CGUIDialogButtonMenu);
1378 g_windowManager.Add(new CGUIDialogMuteBug);
1379 g_windowManager.Add(new CGUIDialogPlayerControls);
1381 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1382 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1384 g_windowManager.Add(new CGUIDialogSlider);
1385 g_windowManager.Add(new CGUIDialogMusicOSD);
1386 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1387 g_windowManager.Add(new CGUIDialogVideoSettings);
1388 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1389 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1390 // Don't add the filebrowser dialog - it's created and added when it's needed
1391 g_windowManager.Add(new CGUIDialogNetworkSetup);
1392 g_windowManager.Add(new CGUIDialogMediaSource);
1393 g_windowManager.Add(new CGUIDialogProfileSettings);
1394 g_windowManager.Add(new CGUIDialogFavourites);
1395 g_windowManager.Add(new CGUIDialogSongInfo);
1396 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1397 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1398 g_windowManager.Add(new CGUIDialogBusy);
1399 g_windowManager.Add(new CGUIDialogPictureInfo);
1400 g_windowManager.Add(new CGUIDialogAddonInfo);
1401 g_windowManager.Add(new CGUIDialogAddonSettings);
1402 #ifdef HAS_LINUX_NETWORK
1403 g_windowManager.Add(new CGUIDialogAccessPoints);
1406 g_windowManager.Add(new CGUIDialogLockSettings);
1408 g_windowManager.Add(new CGUIDialogContentSettings);
1410 g_windowManager.Add(new CGUIDialogPlayEject);
1412 g_windowManager.Add(new CGUIDialogPeripheralManager);
1413 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1415 g_windowManager.Add(new CGUIDialogMediaFilter);
1416 g_windowManager.Add(new CGUIDialogSubtitles);
1418 g_windowManager.Add(new CGUIWindowMusicPlayList);
1419 g_windowManager.Add(new CGUIWindowMusicSongs);
1420 g_windowManager.Add(new CGUIWindowMusicNav);
1421 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1423 /* Load PVR related Windows and Dialogs */
1424 g_windowManager.Add(new CGUIDialogTeletext);
1425 g_windowManager.Add(new CGUIWindowPVR);
1426 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1427 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1428 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1429 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1430 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1431 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1432 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1433 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1434 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1435 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1437 g_windowManager.Add(new CGUIDialogSelect);
1438 g_windowManager.Add(new CGUIDialogMusicInfo);
1439 g_windowManager.Add(new CGUIDialogOK);
1440 g_windowManager.Add(new CGUIDialogVideoInfo);
1441 g_windowManager.Add(new CGUIDialogTextViewer);
1442 g_windowManager.Add(new CGUIWindowFullScreen);
1443 g_windowManager.Add(new CGUIWindowVisualisation);
1444 g_windowManager.Add(new CGUIWindowSlideShow);
1445 g_windowManager.Add(new CGUIDialogFileStacking);
1447 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1450 g_windowManager.Add(new CGUIDialogVideoOSD);
1451 g_windowManager.Add(new CGUIDialogMusicOverlay);
1452 g_windowManager.Add(new CGUIDialogVideoOverlay);
1453 g_windowManager.Add(new CGUIWindowScreensaver);
1454 g_windowManager.Add(new CGUIWindowWeather);
1455 g_windowManager.Add(new CGUIWindowStartup);
1457 /* window id's 3000 - 3100 are reserved for python */
1459 // Make sure we have at least the default skin
1460 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1461 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1463 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1467 if (g_advancedSettings.m_splashImage)
1468 SAFE_DELETE(m_splash);
1470 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1471 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1472 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1474 g_passwordManager.CheckStartUpLock();
1477 // check if we should use the login screen
1478 if (CProfilesManager::Get().UsingLoginScreen())
1479 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1483 CJSONRPC::Initialize();
1485 ADDON::CAddonMgr::Get().StartServices(false);
1486 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1488 g_windowManager.ActivateWindow(WINDOW_HOME);
1489 StartPVRManager(true);
1493 StartPVRManager(false);
1494 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1497 CStereoscopicsManager::Get().Initialize();
1501 else //No GUI Created
1504 CJSONRPC::Initialize();
1506 ADDON::CAddonMgr::Get().StartServices(false);
1509 g_sysinfo.Refresh();
1511 CLog::Log(LOGINFO, "removing tempfiles");
1512 CUtil::RemoveTempFiles();
1514 if (!CProfilesManager::Get().UsingLoginScreen())
1520 m_slowTimer.StartZero();
1522 #if defined(HAVE_LIBCRYSTALHD)
1523 CCrystalHD::GetInstance();
1526 CAddonMgr::Get().StartServices(true);
1528 CLog::Log(LOGNOTICE, "initialize done");
1530 m_bInitializing = false;
1532 // reset our screensaver (starts timers etc.)
1535 #ifdef HAS_SDL_JOYSTICK
1536 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1537 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1543 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1549 // the callback will take care of starting/stopping webserver
1550 ret = CSettings::Get().SetBool("services.webserver", bStart);
1553 case ES_AIRPLAYSERVER:
1554 // the callback will take care of starting/stopping airplay
1555 ret = CSettings::Get().SetBool("services.airplay", bStart);
1558 case ES_JSONRPCSERVER:
1559 // the callback will take care of starting/stopping jsonrpc server
1560 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1564 // the callback will take care of starting/stopping upnp server
1565 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1568 case ES_UPNPRENDERER:
1569 // the callback will take care of starting/stopping upnp renderer
1570 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1573 case ES_EVENTSERVER:
1574 // the callback will take care of starting/stopping event server
1575 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1579 // the callback will take care of starting/stopping zeroconf
1580 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1587 CSettings::Get().Save();
1592 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1594 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1595 g_PVRManager.Start(true, bOpenPVRWindow);
1598 void CApplication::StopPVRManager()
1600 CLog::Log(LOGINFO, "stopping PVRManager");
1601 if (g_PVRManager.IsPlaying())
1603 g_PVRManager.Stop();
1604 g_EpgContainer.Stop();
1607 void CApplication::StartServices()
1609 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1610 // Start Thread for DVD Mediatype detection
1611 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1612 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1616 void CApplication::StopServices()
1618 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1620 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1621 CLog::Log(LOGNOTICE, "stop dvd detect media");
1622 m_DetectDVDType.StopThread();
1625 g_peripherals.Clear();
1628 void CApplication::OnSettingChanged(const CSetting *setting)
1630 if (setting == NULL)
1633 const std::string &settingId = setting->GetId();
1634 if (settingId == "lookandfeel.skin" ||
1635 settingId == "lookandfeel.font" ||
1636 settingId == "lookandfeel.skincolors")
1638 // if the skin changes and the current theme is not the default one, reset
1639 // the theme to the default value (which will also change lookandfeel.skincolors
1640 // which in turn will reload the skin. Similarly, if the current skin font is not
1641 // the default, reset it as well.
1642 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1643 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1644 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1645 CSettings::Get().SetString("lookandfeel.font", "Default");
1648 std::string builtin("ReloadSkin");
1649 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1650 builtin += "(confirm)";
1651 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1654 else if (settingId == "lookandfeel.skintheme")
1656 // also set the default color theme
1657 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1658 URIUtils::RemoveExtension(colorTheme);
1659 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1660 colorTheme = "defaults";
1662 // check if we have to change the skin color
1663 // if yes, it will trigger a call to ReloadSkin() in
1664 // it's OnSettingChanged() callback
1665 // if no we have to call ReloadSkin() ourselves
1666 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1667 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1669 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1671 else if (settingId == "lookandfeel.skinzoom")
1673 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1674 g_windowManager.SendThreadMessage(msg);
1676 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1678 // AE is master of audio settings and needs to be informed first
1679 CAEFactory::OnSettingsChange(settingId);
1681 if (settingId == "audiooutput.guisoundmode")
1683 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1685 // this tells player whether to open an audio stream passthrough or PCM
1686 // if this is changed, audio stream has to be reopened
1687 else if (settingId == "audiooutput.passthrough")
1689 CApplicationMessenger::Get().MediaRestart(false);
1692 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1693 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1694 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1695 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1696 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1697 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1698 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1699 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1702 void CApplication::OnSettingAction(const CSetting *setting)
1704 if (setting == NULL)
1707 const std::string &settingId = setting->GetId();
1708 if (settingId == "lookandfeel.skinsettings")
1709 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1710 else if (settingId == "screensaver.preview")
1711 ActivateScreenSaver(true);
1712 else if (settingId == "screensaver.settings")
1715 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1716 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1718 else if (settingId == "videoscreen.guicalibration")
1719 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1720 else if (settingId == "videoscreen.testpattern")
1721 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1724 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1726 if (setting == NULL)
1729 const std::string &settingId = setting->GetId();
1730 if (settingId == "audiooutput.channels")
1732 // check if this is an update from Eden
1733 if (oldSettingId != NULL && oldSettingNode != NULL &&
1734 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1737 CSettingInt* channels = (CSettingInt*)setting;
1738 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1739 ret = channels->SetValue(channels->GetValue() + 1);
1741 // let's just reset the audiodevice settings as well
1742 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1743 CAEFactory::VerifyOutputDevice(audiodevice, false);
1744 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1749 else if (settingId == "screensaver.mode")
1751 CSettingString *screensaverMode = (CSettingString*)setting;
1752 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1753 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1754 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1756 else if (settingId == "scrapers.musicvideosdefault")
1758 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1759 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1761 musicvideoScraper->Reset();
1765 #if defined(HAS_LIBAMCODEC)
1766 else if (settingId == "videoplayer.useamcodec")
1768 // Do not permit amcodec to be used on non-aml platforms.
1769 // The setting will be hidden but the default value is true,
1770 // so change it to false.
1773 CSettingBool *useamcodec = (CSettingBool*)setting;
1774 useamcodec->SetValue(false);
1778 #if defined(TARGET_ANDROID)
1779 else if (settingId == "videoplayer.usemediacodec")
1781 // Do not permit MediaCodec to be used Android platforms that do not have it.
1782 // The setting will be hidden but the default value is true,
1783 // so change it to false.
1784 if (CAndroidFeatures::GetVersion() < 16)
1786 CSettingBool *usemediacodec = (CSettingBool*)setting;
1787 usemediacodec->SetValue(false);
1790 else if (settingId == "videoplayer.usestagefright")
1792 CSettingBool *usestagefright = (CSettingBool*)setting;
1793 usestagefright->SetValue(false);
1796 #if defined(TARGET_DARWIN_OSX)
1797 else if (settingId == "audiooutput.audiodevice")
1799 CSettingString *audioDevice = (CSettingString*)setting;
1800 // Gotham and older didn't enumerate audio devices per stream on osx
1801 // add stream0 per default which should be ok for all old settings.
1802 if (!StringUtils::EqualsNoCase(audioDevice->GetValue(), "DARWINOSX:default") &&
1803 StringUtils::FindWords(audioDevice->GetValue().c_str(), ":stream") == std::string::npos)
1805 std::string newSetting = audioDevice->GetValue();
1806 newSetting += ":stream0";
1807 return audioDevice->SetValue(newSetting);
1815 bool CApplication::OnSettingsSaving() const
1817 // don't save settings when we're busy stopping the application
1818 // a lot of screens try to save settings on deinit and deinit is
1819 // called for every screen when the application is stopping
1826 void CApplication::ReloadSkin(bool confirm/*=false*/)
1828 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1830 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1831 g_windowManager.SendMessage(msg);
1833 string newSkin = CSettings::Get().GetString("lookandfeel.skin");
1834 if (LoadSkin(newSkin))
1836 /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
1837 user as to whether they want to keep the current skin. */
1838 if (confirm && !m_skinReverting)
1841 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1843 m_skinReverting = true;
1844 if (oldSkin.empty())
1845 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1847 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1853 // skin failed to load - we revert to the default only if we didn't fail loading the default
1854 string defaultSkin = ((CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1855 if (newSkin != defaultSkin)
1857 m_skinReverting = true;
1858 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1859 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1862 m_skinReverting = false;
1865 bool CApplication::Load(const TiXmlNode *settings)
1867 if (settings == NULL)
1870 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1871 if (audioElement != NULL)
1873 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1874 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1875 m_volumeLevel = VOLUME_MAXIMUM;
1881 bool CApplication::Save(TiXmlNode *settings) const
1883 if (settings == NULL)
1886 TiXmlElement volumeNode("audio");
1887 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1888 if (audioNode == NULL)
1891 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1892 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1897 bool CApplication::LoadSkin(const CStdString& skinID)
1900 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1902 if (LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
1905 CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
1909 bool CApplication::LoadSkin(const SkinPtr& skin)
1915 if (!skin->HasSkinFile("Home.xml"))
1918 bool bPreviousPlayingState=false;
1919 bool bPreviousRenderingState=false;
1920 if (g_application.m_pPlayer->IsPlayingVideo())
1922 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1923 if (bPreviousPlayingState)
1924 g_application.m_pPlayer->Pause();
1925 #ifdef HAS_VIDEO_PLAYBACK
1926 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1928 g_windowManager.ActivateWindow(WINDOW_HOME);
1929 bPreviousRenderingState = true;
1933 // close the music and video overlays (they're re-opened automatically later)
1934 CSingleLock lock(g_graphicsContext);
1936 // save the current window details and focused control
1937 int currentWindow = g_windowManager.GetActiveWindow();
1939 CGUIWindow* pWindow = g_windowManager.GetWindow(currentWindow);
1941 iCtrlID = pWindow->GetFocusedControlID();
1942 vector<int> currentModelessWindows;
1943 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1947 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
1949 g_SkinInfo->Start();
1951 CLog::Log(LOGINFO, " load fonts for skin...");
1952 g_graphicsContext.SetMediaDir(skin->Path());
1953 g_directoryCache.ClearSubPaths(skin->Path());
1955 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1957 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1959 // load in the skin strings
1960 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1961 URIUtils::AddSlashAtEnd(langPath);
1963 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1965 g_SkinInfo->LoadIncludes();
1968 start = CurrentHostCounter();
1970 CLog::Log(LOGINFO, " load new skin...");
1972 // Load the user windows
1976 end = CurrentHostCounter();
1977 freq = CurrentHostFrequency();
1978 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1980 CLog::Log(LOGINFO, " initialize new skin...");
1981 g_windowManager.AddMsgTarget(this);
1982 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1983 g_windowManager.AddMsgTarget(&g_infoManager);
1984 g_windowManager.AddMsgTarget(&g_fontManager);
1985 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1986 g_windowManager.SetCallback(*this);
1987 g_windowManager.Initialize();
1988 CTextureCache::Get().Initialize();
1989 g_audioManager.Enable(true);
1990 g_audioManager.Load();
1992 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1993 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1995 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1996 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1997 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1998 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1999 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2002 CLog::Log(LOGINFO, " skin loaded...");
2004 // leave the graphics lock
2008 if (currentWindow != WINDOW_INVALID)
2010 g_windowManager.ActivateWindow(currentWindow);
2011 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2013 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2014 if (dialog) dialog->Show();
2018 pWindow = g_windowManager.GetWindow(currentWindow);
2019 if (pWindow && pWindow->HasSaveLastControl())
2021 CGUIMessage msg(GUI_MSG_SETFOCUS, currentWindow, iCtrlID, 0);
2022 pWindow->OnMessage(msg);
2027 if (g_application.m_pPlayer->IsPlayingVideo())
2029 if (bPreviousPlayingState)
2030 g_application.m_pPlayer->Pause();
2031 if (bPreviousRenderingState)
2032 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2037 void CApplication::UnloadSkin(bool forReload /* = false */)
2039 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2041 g_audioManager.Enable(false);
2043 g_windowManager.DeInitialize();
2044 CTextureCache::Get().Deinitialize();
2046 // remove the skin-dependent window
2047 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2049 g_TextureManager.Cleanup();
2050 g_largeTextureManager.CleanupUnusedImages(true);
2052 g_fontManager.Clear();
2054 g_colorManager.Clear();
2056 g_infoManager.Clear();
2058 // The g_SkinInfo boost shared_ptr ought to be reset here
2059 // but there are too many places it's used without checking for NULL
2060 // and as a result a race condition on exit can cause a crash.
2063 bool CApplication::LoadUserWindows()
2065 // Start from wherever home.xml is
2066 std::vector<CStdString> vecSkinPath;
2067 g_SkinInfo->GetSkinPaths(vecSkinPath);
2068 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2070 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2071 CFileItemList items;
2072 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2074 for (int i = 0; i < items.Size(); ++i)
2076 if (items[i]->m_bIsFolder)
2078 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2079 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2081 CXBMCTinyXML xmlDoc;
2082 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2084 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2088 // Root element should be <window>
2089 TiXmlElement* pRootElement = xmlDoc.RootElement();
2090 CStdString strValue = pRootElement->Value();
2091 if (!strValue.Equals("window"))
2093 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2097 // Read the <type> element to get the window type to create
2098 // If no type is specified, create a CGUIWindow as default
2099 CGUIWindow* pWindow = NULL;
2101 if (pRootElement->Attribute("type"))
2102 strType = pRootElement->Attribute("type");
2105 const TiXmlNode *pType = pRootElement->FirstChild("type");
2106 if (pType && pType->FirstChild())
2107 strType = pType->FirstChild()->Value();
2109 int id = WINDOW_INVALID;
2110 if (!pRootElement->Attribute("id", &id))
2112 const TiXmlNode *pType = pRootElement->FirstChild("id");
2113 if (pType && pType->FirstChild())
2114 id = atol(pType->FirstChild()->Value());
2116 CStdString visibleCondition;
2117 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2119 if (strType.Equals("dialog"))
2120 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2121 else if (strType.Equals("submenu"))
2122 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2123 else if (strType.Equals("buttonmenu"))
2124 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2126 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2128 // Check to make sure the pointer isn't still null
2129 if (pWindow == NULL)
2131 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2134 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2139 pWindow->SetVisibleCondition(visibleCondition);
2140 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2141 g_windowManager.AddCustomWindow(pWindow);
2149 bool CApplication::RenderNoPresent()
2153 // DXMERGE: This may have been important?
2154 // g_graphicsContext.AcquireCurrentContext();
2156 g_graphicsContext.Lock();
2158 // dont show GUI when playing full screen video
2159 if (g_graphicsContext.IsFullScreenVideo())
2161 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2162 g_renderManager.Render(true, 0, 255);
2164 // close window overlays
2165 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2166 if (overlay) overlay->Close(true);
2167 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2168 if (overlay) overlay->Close(true);
2172 bool hasRendered = g_windowManager.Render();
2174 g_graphicsContext.Unlock();
2179 float CApplication::GetDimScreenSaverLevel() const
2181 if (!m_bScreenSave || !m_screenSaver ||
2182 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2183 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2184 !m_screenSaver->ID().empty()))
2187 if (!m_screenSaver->GetSetting("level").empty())
2188 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2192 void CApplication::Render()
2194 // do not render if we are stopped or in background
2200 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2202 bool hasRendered = false;
2203 bool limitFrames = false;
2204 unsigned int singleFrameTime = 10; // default limit 100 fps
2208 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2209 // Whether externalplayer is playing and we're unfocused
2210 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2212 m_bPresentFrame = false;
2213 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2215 m_bPresentFrame = g_renderManager.FrameWait(100);
2220 // engage the frame limiter as needed
2221 limitFrames = lowfps || extPlayerActive;
2222 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2223 // perhaps allowing it to be set differently than the UI option??
2224 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2225 limitFrames = true; // not using vsync.
2226 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2227 limitFrames = true; // using vsync, but it isn't working.
2231 if (extPlayerActive)
2233 ResetScreenSaver(); // Prevent screensaver dimming the screen
2234 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2237 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2243 CSingleLock lock(g_graphicsContext);
2244 g_infoManager.UpdateFPS();
2246 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2247 g_Windowing.SetVSync(true);
2248 else if (vsync_mode == VSYNC_ALWAYS)
2249 g_Windowing.SetVSync(true);
2250 else if (vsync_mode != VSYNC_DRIVER)
2251 g_Windowing.SetVSync(false);
2253 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2256 if(!g_Windowing.BeginRender())
2259 g_renderManager.FrameMove();
2261 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2262 if(g_graphicsContext.GetStereoMode())
2264 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2265 if(RenderNoPresent())
2268 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2270 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2271 if(RenderNoPresent())
2274 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2278 if(RenderNoPresent())
2282 g_renderManager.FrameFinish();
2284 g_Windowing.EndRender();
2286 // execute post rendering actions (finalize window closing)
2287 g_windowManager.AfterRender();
2289 // reset our info cache - we do this at the end of Render so that it is
2290 // fresh for the next process(), or after a windowclose animation (where process()
2292 g_infoManager.ResetCache();
2295 unsigned int now = XbmcThreads::SystemClockMillis();
2297 m_lastRenderTime = now;
2299 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2300 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2302 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2303 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2307 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2308 if (limitFrames || !flip)
2311 singleFrameTime = 40; //if not flipping, loop at 25 fps
2313 unsigned int frameTime = now - m_lastFrameTime;
2314 if (frameTime < singleFrameTime)
2315 Sleep(singleFrameTime - frameTime);
2317 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2320 g_graphicsContext.Flip(dirtyRegions);
2321 CTimeUtils::UpdateFrameTime(flip);
2323 g_renderManager.UpdateResolution();
2324 g_renderManager.ManageCaptures();
2327 void CApplication::SetStandAlone(bool value)
2329 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2332 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2333 // The window manager will return true if the event is processed, false otherwise.
2334 // If not already processed, this routine handles global keypresses. It returns
2335 // true if the key has been processed, false otherwise.
2337 bool CApplication::OnKey(const CKey& key)
2340 // Turn the mouse off, as we've just got a keypress from controller or remote
2341 g_Mouse.SetActive(false);
2343 // get the current active window
2344 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2346 // this will be checked for certain keycodes that need
2347 // special handling if the screensaver is active
2348 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2350 // a key has been pressed.
2352 m_idleTimer.StartZero();
2353 bool processKey = AlwaysProcess(action);
2355 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2359 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2360 // do not wake up the screensaver right after switching off the playing device
2361 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2362 ret = CApplicationMessenger::Get().CECToggleState();
2364 ret = CApplicationMessenger::Get().CECStandby();
2365 if (!ret) /* display is switched off */
2371 // allow some keys to be processed while the screensaver is active
2372 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2374 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2378 // change this if we have a dialog up
2379 if (g_windowManager.HasModalDialog())
2381 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2383 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2384 { // fullscreen info dialog - special case
2385 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2387 if (!key.IsAnalogButton())
2388 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2390 if (OnAction(action))
2393 // fallthrough to the main window
2394 iWin = WINDOW_FULLSCREEN_VIDEO;
2396 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2398 // current active window is full screen video.
2399 if (g_application.m_pPlayer->IsInMenu())
2401 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2402 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2404 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2406 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2407 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2409 // if no PVR specific action/mapping is found, fall back to default
2410 if (action.GetID() == 0)
2411 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2415 // in any other case use the fullscreen window section of keymap.xml to map key->action
2416 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2421 // current active window isnt the fullscreen window
2422 // just use corresponding section from keymap.xml
2423 // to map key->action
2425 // first determine if we should use keyboard input directly
2426 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2427 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2430 CGUIControl *control = window->GetFocusedControl();
2433 // If this is an edit control set usekeyboard to true. This causes the
2434 // keypress to be processed directly not through the key mappings.
2435 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2438 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2439 // This causes the keypress to be used for list navigation.
2440 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2446 action = CAction(0); // reset our action
2447 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2449 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2450 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2451 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2452 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2453 action.GetID() == ACTION_MOVE_RIGHT ||
2454 action.GetID() == ACTION_MOVE_UP ||
2455 action.GetID() == ACTION_MOVE_DOWN ||
2456 action.GetID() == ACTION_SELECT_ITEM ||
2457 action.GetID() == ACTION_ENTER ||
2458 action.GetID() == ACTION_PREVIOUS_MENU ||
2459 action.GetID() == ACTION_NAV_BACK))
2461 // the action isn't plain navigation - check for a keyboard-specific keymap
2462 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2463 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2464 action.GetID() == ACTION_BACKSPACE ||
2465 action.GetID() == ACTION_SHIFT ||
2466 action.GetID() == ACTION_SYMBOLS ||
2467 action.GetID() == ACTION_CURSOR_LEFT ||
2468 action.GetID() == ACTION_CURSOR_RIGHT)
2469 action = CAction(0); // don't bother with this action
2472 if (!action.GetID())
2474 // keyboard entry - pass the keys through directly
2475 if (key.GetFromService())
2476 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2479 // Check for paste keypress
2480 #ifdef TARGET_WINDOWS
2481 // In Windows paste is ctrl-V
2482 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2483 #elif defined(TARGET_LINUX)
2484 // In Linux paste is ctrl-V
2485 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2486 #elif defined(TARGET_DARWIN_OSX)
2487 // In OSX paste is cmd-V
2488 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2490 // Placeholder for other operating systems
2493 action = CAction(ACTION_PASTE);
2494 // If the unicode is non-zero the keypress is a non-printing character
2495 else if (key.GetUnicode())
2496 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2497 // The keypress is a non-printing character
2499 action = CAction(key.GetVKey() | KEY_VKEY);
2503 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2505 if (OnAction(action))
2507 // failed to handle the keyboard action, drop down through to standard action
2509 if (key.GetFromService())
2511 if (key.GetButtonCode() != KEY_INVALID)
2512 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2515 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2517 if (!key.IsAnalogButton())
2518 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2520 return ExecuteInputAction(action);
2523 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2524 // This needs to return true if it processed the appcommand or false if it didn't
2525 bool CApplication::OnAppCommand(const CAction &action)
2527 // Reset the screen saver
2530 // If we were currently in the screen saver wake up and don't process the appcommand
2531 if (WakeUpScreenSaverAndDPMS())
2534 // The action ID is the APPCOMMAND code. We need to retrieve the action
2535 // associated with this appcommand from the mapping table.
2536 uint32_t appcmd = action.GetID();
2537 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2538 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2539 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2541 // If we couldn't find an action return false to indicate we have not
2542 // handled this appcommand
2543 if (!appcmdaction.GetID())
2545 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2549 // Process the appcommand
2550 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2551 OnAction(appcmdaction);
2553 // Always return true regardless of whether the action succeeded or not.
2554 // This stops Windows handling the appcommand itself.
2558 bool CApplication::OnAction(const CAction &action)
2560 // special case for switching between GUI & fullscreen mode.
2561 if (action.GetID() == ACTION_SHOW_GUI)
2562 { // Switch to fullscreen mode if we can
2563 if (SwitchToFullScreen())
2565 m_navigationTimer.StartZero();
2570 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2572 g_graphicsContext.ToggleFullScreenRoot();
2576 if (action.IsMouse())
2577 g_Mouse.SetActive(true);
2580 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2582 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2584 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2586 CGUIDialogVideoBookmarks::OnAddBookmark();
2589 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2590 // playing or ACTION_PLAYER_PLAY if we are not playing.
2591 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2593 if (m_pPlayer->IsPlaying())
2594 return OnAction(CAction(ACTION_PAUSE));
2596 return OnAction(CAction(ACTION_PLAYER_PLAY));
2599 //if the action would start or stop inertial scrolling
2600 //by gesture - bypass the normal OnAction handler of current window
2601 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2604 // just pass the action to the current window and let it handle it
2605 if (g_windowManager.OnAction(action))
2607 m_navigationTimer.StartZero();
2612 // handle extra global presses
2614 // screenshot : take a screenshot :)
2615 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2617 CScreenShot::TakeScreenshot();
2620 // built in functions : execute the built-in
2621 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2623 CBuiltins::Execute(action.GetName());
2624 m_navigationTimer.StartZero();
2629 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2631 CButtonTranslator::GetInstance().Clear();
2632 CButtonTranslator::GetInstance().Load();
2635 // show info : Shows the current video or song information
2636 if (action.GetID() == ACTION_SHOW_INFO)
2638 g_infoManager.ToggleShowInfo();
2642 // codec info : Shows the current song, video or picture codec information
2643 if (action.GetID() == ACTION_SHOW_CODEC)
2645 g_infoManager.ToggleShowCodec();
2649 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2651 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2654 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2655 char rating = tag->GetRating();
2656 bool needsUpdate(false);
2657 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2659 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2662 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2664 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2670 if (db.Open()) // OpenForWrite() ?
2672 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2675 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2676 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2677 g_windowManager.SendMessage(msg);
2683 // Now check with the playlist player if action can be handled.
2684 // 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.
2685 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2687 if (g_playlistPlayer.OnAction(action))
2691 // Now check with the player if action can be handled.
2692 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2693 (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)) ||
2694 action.GetID() == ACTION_STOP)
2696 if (m_pPlayer->OnAction(action))
2698 // Player ignored action; popup the OSD
2699 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2700 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2701 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2704 // stop : stops playing current audio song
2705 if (action.GetID() == ACTION_STOP)
2711 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2712 // If so, we just jump to the start of the track.
2713 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2716 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2720 // forward action to g_PVRManager and break if it was able to handle it
2721 if (g_PVRManager.OnAction(action))
2724 // forward action to graphic context and see if it can handle it
2725 if (CStereoscopicsManager::Get().OnAction(action))
2728 if (m_pPlayer->IsPlaying())
2730 // forward channel switches to the player - he knows what to do
2731 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2733 m_pPlayer->OnAction(action);
2737 // pause : pauses current audio song
2738 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2742 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2744 if (!m_pPlayer->IsPaused())
2745 { // unpaused - set the playspeed back to normal
2746 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2748 g_audioManager.Enable(m_pPlayer->IsPaused());
2751 if (!m_pPlayer->IsPaused())
2753 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2754 // if we are playing at normal speed, then allow play to pause
2755 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2757 if (m_pPlayer->GetPlaySpeed() != 1)
2759 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2767 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2769 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2770 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2772 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2774 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2779 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2781 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2784 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2787 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2789 // calculate the speed based on the amount the button is held down
2790 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2791 // returns 0 -> MAX_FFWD_SPEED
2792 int iSpeed = 1 << iPower;
2793 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2795 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2797 CLog::Log(LOGDEBUG,"Resetting playspeed");
2801 // allow play to unpause
2804 if (action.GetID() == ACTION_PLAYER_PLAY)
2806 // unpause, and set the playspeed back to normal
2808 g_audioManager.Enable(m_pPlayer->IsPaused());
2810 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2815 // record current file
2816 if (action.GetID() == ACTION_RECORD)
2818 if (m_pPlayer->CanRecord())
2819 m_pPlayer->Record(!m_pPlayer->IsRecording());
2822 if (m_playerController->OnAction(action))
2827 if (action.GetID() == ACTION_SWITCH_PLAYER)
2829 if(m_pPlayer->IsPlaying())
2831 VECPLAYERCORES cores;
2832 CFileItem item(*m_itemCurrentFile.get());
2833 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2834 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2835 if(core != EPC_NONE)
2837 g_application.m_eForcedNextPlayer = core;
2838 item.m_lStartOffset = (int)(GetTime() * 75);
2839 PlayFile(item, true);
2844 VECPLAYERCORES cores;
2845 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2846 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2847 if(core != EPC_NONE)
2850 g_application.m_eForcedNextPlayer = core;
2851 PlayFile(item, false);
2856 if (g_peripherals.OnAction(action))
2859 if (action.GetID() == ACTION_MUTE)
2865 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2867 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2868 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2870 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2872 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2873 g_windowManager.SendMessage(msg);
2878 // Check for global volume control
2879 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2881 if (!m_pPlayer->IsPassthrough())
2885 float volume = m_volumeLevel;
2886 // Android has steps based on the max available volume level
2887 #if defined(TARGET_ANDROID)
2888 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2890 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2892 if (action.GetRepeat())
2893 step *= action.GetRepeat() * 50; // 50 fps
2895 if (action.GetID() == ACTION_VOLUME_UP)
2896 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2898 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2899 SetVolume(volume, false);
2901 // show visual feedback of volume change...
2902 ShowVolumeBar(&action);
2905 // Check for global seek control
2906 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2908 if (!m_pPlayer->CanSeek()) return false;
2909 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2912 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2914 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2915 CGUIControlProfiler::Instance().Start();
2918 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2920 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2921 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2922 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2923 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2924 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2930 void CApplication::FrameMove(bool processEvents, bool processGUI)
2936 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2937 float frameTime = m_frameTime.GetElapsedSeconds();
2938 m_frameTime.StartZero();
2939 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2940 if( frameTime > 0.5 ) frameTime = 0.5;
2942 if (processGUI && m_renderGUI)
2944 g_graphicsContext.Lock();
2945 // check if there are notifications to display
2946 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2947 if (toast && toast->DoWork())
2949 if (!toast->IsDialogRunning())
2954 g_graphicsContext.Unlock();
2956 CWinEvents::MessagePump();
2958 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2959 // Read the input from a remote
2960 g_RemoteControl.Update();
2963 // process input actions
2964 ProcessRemote(frameTime);
2965 ProcessGamepad(frameTime);
2966 ProcessEventServer(frameTime);
2967 ProcessPeripherals(frameTime);
2968 if (processGUI && m_renderGUI)
2970 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2971 m_seekHandler->Process();
2974 if (processGUI && m_renderGUI)
2977 g_windowManager.Process(CTimeUtils::GetFrameTime());
2978 g_windowManager.FrameMove();
2982 bool CApplication::ProcessGamepad(float frameTime)
2984 #ifdef HAS_SDL_JOYSTICK
2988 int iWin = GetActiveWindowID();
2990 g_Joystick.Update();
2991 if (g_Joystick.GetButton(bid))
2994 m_idleTimer.StartZero();
2997 if (WakeUpScreenSaverAndDPMS())
2999 g_Joystick.Reset(true);
3004 CStdString actionName;
3006 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3008 CAction action(actionID, 1.0f, 0.0f, actionName);
3010 g_Mouse.SetActive(false);
3011 return ExecuteInputAction(action);
3018 if (g_Joystick.GetAxis(bid))
3020 if (g_Joystick.GetAmount() < 0)
3026 CStdString actionName;
3028 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3031 if (WakeUpScreenSaverAndDPMS())
3036 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3038 g_Mouse.SetActive(false);
3039 return ExecuteInputAction(action);
3043 g_Joystick.ResetAxis(abs(bid));
3047 if (g_Joystick.GetHat(bid, position))
3050 m_idleTimer.StartZero();
3053 if (WakeUpScreenSaverAndDPMS())
3060 CStdString actionName;
3063 bid = position<<16|bid;
3065 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3067 CAction action(actionID, 1.0f, 0.0f, actionName);
3069 g_Mouse.SetActive(false);
3070 return ExecuteInputAction(action);
3077 bool CApplication::ProcessRemote(float frameTime)
3079 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3080 if (g_RemoteControl.GetButton())
3082 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3083 g_RemoteControl.Reset();
3090 bool CApplication::ProcessPeripherals(float frameTime)
3093 if (g_peripherals.GetNextKeypress(frameTime, key))
3098 bool CApplication::ProcessMouse()
3102 if (!g_Mouse.IsActive() || !m_AppFocused)
3105 // Get the mouse command ID
3106 uint32_t mousecommand = g_Mouse.GetAction();
3107 if (mousecommand == ACTION_NOOP)
3110 // Reset the screensaver and idle timers
3111 m_idleTimer.StartZero();
3113 if (WakeUpScreenSaverAndDPMS())
3116 // Retrieve the corresponding action
3117 int iWin = GetActiveWindowID();
3118 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3119 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3121 // Deactivate mouse if non-mouse action
3122 if (!mouseaction.IsMouse())
3123 g_Mouse.SetActive(false);
3125 // Consume ACTION_NOOP.
3126 // Some views or dialogs gets closed after any ACTION and
3127 // a sensitive mouse might cause problems.
3128 if (mouseaction.GetID() == ACTION_NOOP)
3131 // If we couldn't find an action return false to indicate we have not
3132 // handled this mouse action
3133 if (!mouseaction.GetID())
3135 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3139 // Log mouse actions except for move and noop
3140 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3141 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3143 // The action might not be a mouse action. For example wheel moves might
3144 // be mapped to volume up/down in mouse.xml. In this case we do not want
3145 // the mouse position saved in the action.
3146 if (!mouseaction.IsMouse())
3147 return OnAction(mouseaction);
3149 // This is a mouse action so we need to record the mouse position
3150 return OnAction(CAction(mouseaction.GetID(),
3151 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3152 (float)g_Mouse.GetX(),
3153 (float)g_Mouse.GetY(),
3154 (float)g_Mouse.GetDX(),
3155 (float)g_Mouse.GetDY(),
3156 mouseaction.GetName()));
3159 bool CApplication::ProcessEventServer(float frameTime)
3161 #ifdef HAS_EVENT_SERVER
3162 CEventServer* es = CEventServer::GetInstance();
3163 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3166 // process any queued up actions
3167 if (es->ExecuteNextAction())
3169 // reset idle timers
3170 m_idleTimer.StartZero();
3172 WakeUpScreenSaverAndDPMS();
3175 // now handle any buttons or axis
3176 std::string joystickName;
3177 bool isAxis = false;
3178 float fAmount = 0.0;
3180 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3181 // when the action exits XBMC
3182 es = CEventServer::GetInstance();
3183 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3185 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3189 if (joystickName.length() > 0)
3193 if (fabs(fAmount) >= 0.08)
3194 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3196 m_lastAxisMap[joystickName].erase(wKeyID);
3199 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3204 if (wKeyID & ES_FLAG_UNICODE)
3206 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3210 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3211 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3213 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3214 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3215 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3216 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3217 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3219 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3221 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3222 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3223 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3224 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3225 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3226 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3227 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3228 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3229 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3232 key.SetFromService(true);
3237 if (m_lastAxisMap.size() > 0)
3239 // Process all the stored axis.
3240 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3242 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3243 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3249 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3251 XBMC_Event newEvent;
3252 newEvent.type = XBMC_MOUSEMOTION;
3253 newEvent.motion.xrel = 0;
3254 newEvent.motion.yrel = 0;
3255 newEvent.motion.state = 0;
3256 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3257 newEvent.motion.x = (uint16_t)pos.x;
3258 newEvent.motion.y = (uint16_t)pos.y;
3259 OnEvent(newEvent); // had to call this to update g_Mouse position
3260 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3267 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3269 #if defined(HAS_EVENT_SERVER)
3270 m_idleTimer.StartZero();
3272 // Make sure to reset screen saver, mouse.
3274 if (WakeUpScreenSaverAndDPMS())
3277 #ifdef HAS_SDL_JOYSTICK
3280 g_Mouse.SetActive(false);
3282 int iWin = GetActiveWindowID();
3284 CStdString actionName;
3285 bool fullRange = false;
3287 // Translate using regular joystick translator.
3288 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3289 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3291 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3297 bool CApplication::ExecuteInputAction(const CAction &action)
3299 bool bResult = false;
3301 // play sound before the action unless the button is held,
3302 // where we execute after the action as held actions aren't fired every time.
3303 if(action.GetHoldTime())
3305 bResult = OnAction(action);
3307 g_audioManager.PlayActionSound(action);
3311 g_audioManager.PlayActionSound(action);
3312 bResult = OnAction(action);
3317 int CApplication::GetActiveWindowID(void)
3319 // Get the currently active window
3320 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3322 // If there is a dialog active get the dialog id instead
3323 if (g_windowManager.HasModalDialog())
3324 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3326 // If the window is FullScreenVideo check for special cases
3327 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3329 // check if we're in a DVD menu
3330 if(g_application.m_pPlayer->IsInMenu())
3331 iWin = WINDOW_VIDEO_MENU;
3332 // check for LiveTV and switch to it's virtual window
3333 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3334 iWin = WINDOW_FULLSCREEN_LIVETV;
3337 // Return the window id
3341 bool CApplication::Cleanup()
3345 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3346 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3347 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3348 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3349 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3350 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3351 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3352 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3353 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3354 g_windowManager.Delete(WINDOW_FILES);
3355 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3356 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3357 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3358 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3359 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3360 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3361 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3362 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3363 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3364 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3365 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3366 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3367 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3368 g_windowManager.Delete(WINDOW_DIALOG_OK);
3369 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3370 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3371 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3372 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3373 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3374 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3375 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3376 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3377 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3378 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3379 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3380 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3381 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3382 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3383 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3384 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3385 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3386 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3387 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3388 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3389 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3390 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3391 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3393 /* Delete PVR related windows and dialogs */
3394 g_windowManager.Delete(WINDOW_PVR);
3395 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3396 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3397 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3398 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3399 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3400 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3401 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3402 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3403 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3404 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3405 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3406 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3407 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3409 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3410 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3411 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3412 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3413 g_windowManager.Delete(WINDOW_VISUALISATION);
3414 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3415 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3416 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3417 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3418 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3419 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3420 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3421 g_windowManager.Delete(WINDOW_SCREENSAVER);
3422 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3423 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3424 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3425 g_windowManager.Delete(WINDOW_SLIDESHOW);
3426 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3427 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3429 g_windowManager.Delete(WINDOW_HOME);
3430 g_windowManager.Delete(WINDOW_PROGRAMS);
3431 g_windowManager.Delete(WINDOW_PICTURES);
3432 g_windowManager.Delete(WINDOW_WEATHER);
3434 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3435 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3436 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3437 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3438 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3439 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3440 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3441 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3442 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3443 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3445 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3446 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3448 CAddonMgr::Get().DeInit();
3450 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3451 CLog::Log(LOGNOTICE, "closing down remote control service");
3452 g_RemoteControl.Disconnect();
3455 CLog::Log(LOGNOTICE, "unload sections");
3457 #ifdef HAS_PERFORMANCE_SAMPLE
3458 CLog::Log(LOGNOTICE, "performance statistics");
3459 m_perfStats.DumpStats();
3462 // Shutdown as much as possible of the
3463 // application, to reduce the leaks dumped
3464 // to the vc output window before calling
3465 // _CrtDumpMemoryLeaks(). Most of the leaks
3466 // shown are no real leaks, as parts of the app
3467 // are still allocated.
3469 g_localizeStrings.Clear();
3470 g_LangCodeExpander.Clear();
3471 g_charsetConverter.clear();
3472 g_directoryCache.Clear();
3473 CButtonTranslator::GetInstance().Clear();
3474 #ifdef HAS_EVENT_SERVER
3475 CEventServer::RemoveInstance();
3477 DllLoaderContainer::Clear();
3478 g_playlistPlayer.Clear();
3479 CSettings::Get().Uninitialize();
3480 g_advancedSettings.Clear();
3483 CXHandle::DumpObjectTracker();
3485 #ifdef HAS_DVD_DRIVE
3486 CLibcdio::ReleaseInstance();
3489 #if defined(TARGET_ANDROID)
3490 // enable for all platforms once it's safe
3491 g_sectionLoader.UnloadAll();
3493 #ifdef _CRTDBG_MAP_ALLOC
3494 _CrtDumpMemoryLeaks();
3495 while(1); // execution ends
3505 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3510 void CApplication::Stop(int exitCode)
3514 CVariant vExitCode(exitCode);
3515 CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
3517 SaveFileState(true);
3519 g_alarmClock.StopThread();
3521 if( m_bSystemScreenSaverEnable )
3522 g_Windowing.EnableSystemScreenSaver(true);
3524 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3525 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3527 // Update the settings information (volume, uptime etc. need saving)
3528 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3530 CLog::Log(LOGNOTICE, "Saving settings");
3531 CSettings::Get().Save();
3534 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3537 m_AppFocused = false;
3538 m_ExitCode = exitCode;
3539 CLog::Log(LOGNOTICE, "stop all");
3541 // cancel any jobs from the jobmanager
3542 CJobManager::GetInstance().CancelJobs();
3544 // stop scanning before we kill the network and so on
3545 if (m_musicInfoScanner->IsScanning())
3546 m_musicInfoScanner->Stop();
3548 if (m_videoInfoScanner->IsScanning())
3549 m_videoInfoScanner->Stop();
3551 CApplicationMessenger::Get().Cleanup();
3553 CLog::Log(LOGNOTICE, "stop player");
3554 m_pPlayer->ClosePlayer();
3556 CAnnouncementManager::Get().Deinitialize();
3562 #if HAS_FILESYTEM_DAAP
3563 CLog::Log(LOGNOTICE, "stop daap clients");
3564 g_DaapClient.Release();
3566 #ifdef HAS_FILESYSTEM_SAP
3567 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3568 g_sapsessions.StopThread();
3571 if(CZeroconfBrowser::IsInstantiated())
3573 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3574 CZeroconfBrowser::GetInstance()->Stop();
3575 CZeroconfBrowser::ReleaseInstance();
3579 CLog::Log(LOGNOTICE, "clean cached files!");
3580 #ifdef HAS_FILESYSTEM_RAR
3581 g_RarManager.ClearCache(true);
3584 #ifdef HAS_FILESYSTEM_SFTP
3585 CSFTPSessionManager::DisconnectAllSessions();
3588 CLog::Log(LOGNOTICE, "unload skin");
3591 #if defined(TARGET_DARWIN_OSX)
3592 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3593 XBMCHelper::GetInstance().Stop();
3596 #if defined(HAVE_LIBCRYSTALHD)
3597 CCrystalHD::RemoveInstance();
3600 g_mediaManager.Stop();
3602 // Stop services before unloading Python
3603 CAddonMgr::Get().StopServices(false);
3605 // stop all remaining scripts; must be done after skin has been unloaded,
3606 // not before some windows still need it when deinitializing during skin
3608 CScriptInvocationManager::Get().Uninitialize();
3610 g_Windowing.DestroyRenderSystem();
3611 g_Windowing.DestroyWindow();
3612 g_Windowing.DestroyWindowSystem();
3614 // shutdown the AudioEngine
3615 CAEFactory::Shutdown();
3616 CAEFactory::UnLoadEngine();
3618 // unregister ffmpeg lock manager call back
3619 av_lockmgr_register(NULL);
3621 CLog::Log(LOGNOTICE, "stopped");
3625 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3628 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3629 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3636 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3638 //If item is a plugin, expand out now and run ourselves again
3639 if (item.IsPlugin())
3641 CFileItem item_new(item);
3642 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3643 return PlayMedia(item_new, iPlaylist);
3646 if (item.IsSmartPlayList())
3648 CFileItemList items;
3649 CUtil::GetRecursiveListing(item.GetPath(), items, "", DIR_FLAG_NO_FILE_DIRS);
3652 CSmartPlaylist smartpl;
3653 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3654 smartpl.OpenAndReadName(item.GetURL());
3656 playlist.Add(items);
3657 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3660 else if (item.IsPlayList() || item.IsInternetStream())
3662 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3664 //is or could be a playlist
3665 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3666 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3671 if (dlgCache->IsCanceled())
3678 if (iPlaylist != PLAYLIST_NONE)
3681 if (item.HasProperty("playlist_starting_track"))
3682 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3683 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3687 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());
3688 if(pPlayList->size())
3689 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3694 //nothing special just play
3695 return PlayFile(item, false) == PLAYBACK_OK;
3699 // For playing a multi-file video. Particularly inefficient
3700 // on startup, as we are required to calculate the length
3701 // of each video, so we open + close each one in turn.
3702 // A faster calculation of video time would improve this
3704 // return value: same with PlayFile()
3705 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3707 if (!item.IsStack())
3708 return PLAYBACK_FAIL;
3712 // case 1: stacked ISOs
3713 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3715 CStackDirectory dir;
3716 CFileItemList movieList;
3717 dir.GetDirectory(item.GetURL(), movieList);
3719 // first assume values passed to the stack
3720 int selectedFile = item.m_lStartPartNumber;
3721 int startoffset = item.m_lStartOffset;
3723 // check if we instructed the stack to resume from default
3724 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3729 CStdString path = item.GetPath();
3730 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3731 path = item.GetProperty("original_listitem_url").asString();
3732 if( dbs.GetResumeBookMark(path, bookmark) )
3734 startoffset = (int)(bookmark.timeInSeconds*75);
3735 selectedFile = bookmark.partNumber;
3740 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3743 // make sure that the selected part is within the boundaries
3744 if (selectedFile <= 0)
3746 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3749 else if (selectedFile > movieList.Size())
3751 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3752 selectedFile = movieList.Size();
3755 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3756 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3757 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3758 *m_stackFileItemToUpdate = item;
3759 return PlayFile(*(movieList[selectedFile - 1]));
3761 // case 2: all other stacks
3764 // see if we have the info in the database
3765 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3766 // then these times will be wrong.
3767 // Also, this is really just a hack for the slow load up times we have
3768 // A much better solution is a fast reader of FPS and fileLength
3769 // that we can use on a file to get it's time.
3771 bool haveTimes(false);
3775 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3776 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3781 // calculate the total time of the stack
3782 CStackDirectory dir;
3783 dir.GetDirectory(item.GetURL(), *m_currentStack);
3785 for (int i = 0; i < m_currentStack->Size(); i++)
3788 (*m_currentStack)[i]->m_lEndOffset = times[i];
3792 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3794 m_currentStack->Clear();
3795 return PLAYBACK_FAIL;
3797 totalTime += duration / 1000;
3798 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3799 times.push_back(totalTime);
3803 double seconds = item.m_lStartOffset / 75.0;
3805 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3806 { // have our times now, so update the dB
3810 dbs.SetStackTimes(item.GetPath(), times);
3812 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3814 // can only resume seek here, not dvdstate
3816 CStdString path = item.GetPath();
3817 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3818 path = item.GetProperty("original_listitem_url").asString();
3819 if( dbs.GetResumeBookMark(path, bookmark) )
3820 seconds = bookmark.timeInSeconds;
3828 *m_itemCurrentFile = item;
3829 m_currentStackPosition = 0;
3830 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3834 // work out where to seek to
3835 for (int i = 0; i < m_currentStack->Size(); i++)
3837 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3839 CFileItem item(*(*m_currentStack)[i]);
3840 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3841 item.m_lStartOffset = (long)(seconds - start) * 75;
3842 m_currentStackPosition = i;
3843 return PlayFile(item, true);
3848 return PlayFile(*(*m_currentStack)[0], true);
3850 return PLAYBACK_FAIL;
3853 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3855 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3856 if (item.GetMimeType().empty())
3857 const_cast<CFileItem&>(item).FillInMimeType();
3861 SaveCurrentFileSettings();
3863 OutputDebugString("new file set audiostream:0\n");
3864 // Switch to default options
3865 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3866 // see if we have saved options in the database
3868 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3869 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3871 *m_itemCurrentFile = item;
3872 m_nextPlaylistItem = -1;
3873 m_currentStackPosition = 0;
3874 m_currentStack->Clear();
3877 CUtil::ClearSubtitles();
3880 if (item.IsDiscStub())
3882 #ifdef HAS_DVD_DRIVE
3883 // Display the Play Eject dialog if there is any optical disc drive
3884 if (g_mediaManager.HasOpticalDrive())
3886 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3887 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3888 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3889 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3893 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3898 if (item.IsPlayList())
3899 return PLAYBACK_FAIL;
3901 if (item.IsPlugin())
3902 { // we modify the item so that it becomes a real URL
3903 CFileItem item_new(item);
3904 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3905 return PlayFile(item_new, false);
3906 return PLAYBACK_FAIL;
3910 if (URIUtils::IsUPnP(item.GetPath()))
3912 CFileItem item_new(item);
3913 if (XFILE::CUPnPDirectory::GetResource(item.GetURL(), item_new))
3914 return PlayFile(item_new, false);
3915 return PLAYBACK_FAIL;
3919 // if we have a stacked set of files, we need to setup our stack routines for
3920 // "seamless" seeking and total time of the movie etc.
3921 // will recall with restart set to true
3923 return PlayStack(item, bRestart);
3925 //Is TuxBox, this should probably be moved to CTuxBoxFile
3928 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3930 if(g_tuxboxService.IsRunning())
3931 g_tuxboxService.Stop();
3933 PlayBackRet ret = PLAYBACK_FAIL;
3935 if(g_tuxbox.CreateNewItem(item, item_new))
3938 // Make sure it doesn't have a player
3939 // so we actually select one normally
3940 m_pPlayer->ResetPlayer();
3942 // keep the tuxbox:// url as playing url
3943 // and give the new url to the player
3944 ret = PlayFile(item_new, true);
3945 if(ret == PLAYBACK_OK)
3947 if(!g_tuxboxService.IsRunning())
3948 g_tuxboxService.Start();
3954 CPlayerOptions options;
3956 if( item.HasProperty("StartPercent") )
3958 double fallback = 0.0f;
3959 if(item.GetProperty("StartPercent").isString())
3960 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3961 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3964 PLAYERCOREID eNewCore = EPC_NONE;
3967 // have to be set here due to playstack using this for starting the file
3968 options.starttime = item.m_lStartOffset / 75.0;
3969 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3970 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3972 if( m_eForcedNextPlayer != EPC_NONE )
3973 eNewCore = m_eForcedNextPlayer;
3974 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3975 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3977 eNewCore = m_pPlayer->GetCurrentPlayer();
3981 options.starttime = item.m_lStartOffset / 75.0;
3985 // open the d/b and retrieve the bookmarks for the current movie
3988 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3990 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3992 options.starttime = 0.0f;
3994 CStdString path = item.GetPath();
3995 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3996 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3997 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3998 path = item.GetProperty("original_listitem_url").asString();
3999 if(dbs.GetResumeBookMark(path, bookmark))
4001 options.starttime = bookmark.timeInSeconds;
4002 options.state = bookmark.playerState;
4005 override with information from the actual item if available. We do this as the VFS (eg plugins)
4006 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4007 should the playerState be required, it is fetched from the database.
4008 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4010 if (item.IsResumePointSet())
4011 options.starttime = item.GetCurrentResumeTime();
4013 else if (item.HasVideoInfoTag())
4015 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4017 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4020 dbs.GetBookMarkForEpisode(*tag, bookmark);
4021 options.starttime = bookmark.timeInSeconds;
4022 options.state = bookmark.playerState;
4029 if (m_eForcedNextPlayer != EPC_NONE)
4030 eNewCore = m_eForcedNextPlayer;
4032 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4035 // this really aught to be inside !bRestart, but since PlayStack
4036 // uses that to init playback, we have to keep it outside
4037 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4038 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4039 { // playing from a playlist by the looks
4040 // don't switch to fullscreen if we are not playing the first item...
4041 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4043 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4045 // TODO - this will fail if user seeks back to first file in stack
4046 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4047 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4049 options.fullscreen = false;
4050 // reset this so we don't think we are resuming on seek
4051 m_itemCurrentFile->m_lStartOffset = 0;
4054 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4056 // reset VideoStartWindowed as it's a temp setting
4057 CMediaSettings::Get().SetVideoStartWindowed(false);
4060 //We have to stop parsing a cdg before mplayer is deallocated
4061 // WHY do we have to do this????
4063 m_pKaraokeMgr->Stop();
4067 CSingleLock lock(m_playStateMutex);
4068 // tell system we are starting a file
4069 m_bPlaybackStarting = true;
4071 // for playing a new item, previous playing item's callback may already
4072 // pushed some delay message into the threadmessage list, they are not
4073 // expected be processed after or during the new item playback starting.
4074 // so we clean up previous playing item's playback callback delay messages here.
4075 int previousMsgsIgnoredByNewPlaying[] = {
4076 GUI_MSG_PLAYBACK_STARTED,
4077 GUI_MSG_PLAYBACK_ENDED,
4078 GUI_MSG_PLAYBACK_STOPPED,
4079 GUI_MSG_PLAYLIST_CHANGED,
4080 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4081 GUI_MSG_PLAYLISTPLAYER_STARTED,
4082 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4083 GUI_MSG_QUEUE_NEXT_ITEM,
4086 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4088 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4091 // We should restart the player, unless the previous and next tracks are using
4092 // one of the players that allows gapless playback (paplayer, dvdplayer)
4093 m_pPlayer->ClosePlayerGapless(eNewCore);
4095 // now reset play state to starting, since we already stopped the previous playing item if there is.
4096 // and from now there should be no playback callback from previous playing item be called.
4097 m_ePlayState = PLAY_STATE_STARTING;
4099 m_pPlayer->CreatePlayer(eNewCore, *this);
4101 PlayBackRet iResult;
4102 if (m_pPlayer->HasPlayer())
4104 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4105 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4106 * increase performance on low powered systems (Atom/ARM).
4110 CJobManager::GetInstance().PauseJobs();
4113 // don't hold graphicscontext here since player
4114 // may wait on another thread, that requires gfx
4115 CSingleExit ex(g_graphicsContext);
4117 iResult = m_pPlayer->OpenFile(item, options);
4121 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4122 iResult = PLAYBACK_FAIL;
4125 if(iResult == PLAYBACK_OK)
4127 if (m_pPlayer->GetPlaySpeed() != 1)
4129 int iSpeed = m_pPlayer->GetPlaySpeed();
4130 m_pPlayer->m_iPlaySpeed = 1;
4131 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4134 // if player has volume control, set it.
4135 if (m_pPlayer->ControlsVolume())
4137 m_pPlayer->SetVolume(m_volumeLevel);
4138 m_pPlayer->SetMute(m_muted);
4141 if( m_pPlayer->IsPlayingAudio() )
4143 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4144 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4147 #ifdef HAS_VIDEO_PLAYBACK
4148 else if( m_pPlayer->IsPlayingVideo() )
4150 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4151 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4153 // if player didn't manange to switch to fullscreen by itself do it here
4154 if( options.fullscreen && g_renderManager.IsStarted()
4155 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4156 SwitchToFullScreen();
4161 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4162 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4163 g_windowManager.PreviousWindow();
4167 #if !defined(TARGET_POSIX)
4168 g_audioManager.Enable(false);
4171 if (item.HasPVRChannelInfoTag())
4172 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4175 CSingleLock lock(m_playStateMutex);
4176 m_bPlaybackStarting = false;
4178 if (iResult == PLAYBACK_OK)
4180 // play state: none, starting; playing; stopped; ended.
4181 // last 3 states are set by playback callback, they are all ignored during starting,
4182 // but we recorded the state, here we can make up the callback for the state.
4183 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4184 switch (m_ePlayState)
4186 case PLAY_STATE_PLAYING:
4187 OnPlayBackStarted();
4189 // FIXME: it seems no meaning to callback started here if there was an started callback
4190 // before this stopped/ended callback we recorded. if we callback started here
4191 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4192 // which will send OnStop announce at once, so currently, just call stopped/ended.
4193 case PLAY_STATE_ENDED:
4196 case PLAY_STATE_STOPPED:
4197 OnPlayBackStopped();
4199 case PLAY_STATE_STARTING:
4200 // neither started nor stopped/ended callback be called, that means the item still
4201 // not started, we need not make up any callback, just leave this and
4202 // let the player callback do its work.
4208 else if (iResult == PLAYBACK_FAIL)
4210 // we send this if it isn't playlistplayer that is doing this
4211 int next = g_playlistPlayer.GetNextSong();
4212 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4215 OnPlayBackStopped();
4216 m_ePlayState = PLAY_STATE_NONE;
4222 void CApplication::OnPlayBackEnded()
4224 CSingleLock lock(m_playStateMutex);
4225 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4226 m_ePlayState = PLAY_STATE_ENDED;
4227 if(m_bPlaybackStarting)
4230 // informs python script currently running playback has ended
4231 // (does nothing if python is not loaded)
4233 g_pythonParser.OnPlayBackEnded();
4236 CVariant data(CVariant::VariantTypeObject);
4238 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4240 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4241 g_windowManager.SendThreadMessage(msg);
4244 void CApplication::OnPlayBackStarted()
4246 CSingleLock lock(m_playStateMutex);
4247 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4248 m_ePlayState = PLAY_STATE_PLAYING;
4249 if(m_bPlaybackStarting)
4253 // informs python script currently running playback has started
4254 // (does nothing if python is not loaded)
4255 g_pythonParser.OnPlayBackStarted();
4258 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4259 g_windowManager.SendThreadMessage(msg);
4262 void CApplication::OnQueueNextItem()
4264 CSingleLock lock(m_playStateMutex);
4265 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4266 if(m_bPlaybackStarting)
4268 // informs python script currently running that we are requesting the next track
4269 // (does nothing if python is not loaded)
4271 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4274 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4275 g_windowManager.SendThreadMessage(msg);
4278 void CApplication::OnPlayBackStopped()
4280 CSingleLock lock(m_playStateMutex);
4281 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4282 m_ePlayState = PLAY_STATE_STOPPED;
4283 if(m_bPlaybackStarting)
4286 // informs python script currently running playback has ended
4287 // (does nothing if python is not loaded)
4289 g_pythonParser.OnPlayBackStopped();
4292 CVariant data(CVariant::VariantTypeObject);
4293 data["end"] = false;
4294 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4296 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4297 g_windowManager.SendThreadMessage(msg);
4300 void CApplication::OnPlayBackPaused()
4303 g_pythonParser.OnPlayBackPaused();
4307 param["player"]["speed"] = 0;
4308 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4309 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4312 void CApplication::OnPlayBackResumed()
4315 g_pythonParser.OnPlayBackResumed();
4319 param["player"]["speed"] = 1;
4320 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4321 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4324 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4327 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4331 param["player"]["speed"] = iSpeed;
4332 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4333 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4336 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4339 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4343 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4344 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4345 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4346 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4347 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4348 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4351 void CApplication::OnPlayBackSeekChapter(int iChapter)
4354 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4358 bool CApplication::IsPlayingFullScreenVideo() const
4360 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4363 bool CApplication::IsFullScreen()
4365 return IsPlayingFullScreenVideo() ||
4366 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4367 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4370 void CApplication::SaveFileState(bool bForeground /* = false */)
4372 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4377 CSaveFileStateJob job(*m_progressTrackingItem,
4378 *m_stackFileItemToUpdate,
4379 m_progressTrackingVideoResumeBookmark,
4380 m_progressTrackingPlayCountUpdate);
4382 // Run job in the foreground to make sure it finishes
4387 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4388 *m_stackFileItemToUpdate,
4389 m_progressTrackingVideoResumeBookmark,
4390 m_progressTrackingPlayCountUpdate);
4391 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4395 void CApplication::UpdateFileState()
4397 // Did the file change?
4398 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4402 // Reset tracking item
4403 m_progressTrackingItem->Reset();
4407 if (m_pPlayer->IsPlaying())
4409 if (m_progressTrackingItem->GetPath() == "")
4412 *m_progressTrackingItem = CurrentFileItem();
4413 m_progressTrackingPlayCountUpdate = false;
4416 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4417 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4418 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4419 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4421 m_progressTrackingPlayCountUpdate = true;
4424 // Check whether we're *really* playing video else we may race when getting eg. stream details
4425 if (m_pPlayer->IsPlayingVideo())
4427 /* Always update streamdetails, except for DVDs where we only update
4428 streamdetails if title length > 15m (Should yield more correct info) */
4429 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4431 CStreamDetails details;
4432 // Update with stream details from player, if any
4433 if (m_pPlayer->GetStreamDetails(details))
4434 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4436 if (m_progressTrackingItem->IsStack())
4437 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4440 // Update bookmark for save
4441 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4442 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4443 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4445 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4446 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4448 // Delete the bookmark
4449 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4452 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4454 // Update the bookmark
4455 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4456 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4461 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4468 void CApplication::StopPlaying()
4470 int iWin = g_windowManager.GetActiveWindow();
4471 if ( m_pPlayer->IsPlaying() )
4475 m_pKaraokeMgr->Stop();
4478 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4479 g_PVRManager.SaveCurrentChannelSettings();
4481 m_pPlayer->CloseFile();
4483 // turn off visualisation window when stopping
4484 if ((iWin == WINDOW_VISUALISATION
4485 || iWin == WINDOW_FULLSCREEN_VIDEO)
4487 g_windowManager.PreviousWindow();
4489 g_partyModeManager.Disable();
4493 void CApplication::ResetSystemIdleTimer()
4495 // reset system idle timer
4496 m_idleTimer.StartZero();
4499 void CApplication::ResetScreenSaver()
4502 m_shutdownTimer.StartZero();
4504 // screen saver timer is reset only if we're not already in screensaver or
4506 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4507 ResetScreenSaverTimer();
4510 void CApplication::ResetScreenSaverTimer()
4512 m_screenSaverTimer.StartZero();
4515 void CApplication::StopScreenSaverTimer()
4517 m_screenSaverTimer.Stop();
4520 bool CApplication::ToggleDPMS(bool manual)
4522 if (manual || (m_dpmsIsManual == manual))
4526 m_dpmsIsActive = false;
4527 m_dpmsIsManual = false;
4528 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSDeactivated");
4529 return m_dpms->DisablePowerSaving();
4533 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4535 m_dpmsIsActive = true;
4536 m_dpmsIsManual = manual;
4537 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSActivated");
4545 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4549 // First reset DPMS, if active
4554 // TODO: if screensaver lock is specified but screensaver is not active
4555 // (DPMS came first), activate screensaver now.
4557 ResetScreenSaverTimer();
4558 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4561 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4565 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4566 CVariant data(bPowerOffKeyPressed);
4567 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4573 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4575 if (m_iScreenSaveLock == 2)
4578 // if Screen saver is active
4579 if (m_bScreenSave && m_screenSaver)
4581 if (m_iScreenSaveLock == 0)
4582 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4583 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4584 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4585 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4587 m_iScreenSaveLock = 2;
4588 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4590 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4592 pWindow->OnMessage(msg);
4594 if (m_iScreenSaveLock == -1)
4596 m_iScreenSaveLock = 0;
4600 // disable screensaver
4601 m_bScreenSave = false;
4602 m_iScreenSaveLock = 0;
4603 ResetScreenSaverTimer();
4605 if (m_screenSaver->ID() == "visualization")
4607 // we can just continue as usual from vis mode
4610 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4612 else if (!m_screenSaver->ID().empty())
4613 { // we're in screensaver window
4614 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4615 g_windowManager.PreviousWindow(); // show the previous window
4616 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4617 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4625 void CApplication::CheckScreenSaverAndDPMS()
4627 if (!m_dpmsIsActive)
4628 g_Windowing.ResetOSScreensaver();
4630 bool maybeScreensaver =
4631 !m_dpmsIsActive && !m_bScreenSave
4632 && !CSettings::Get().GetString("screensaver.mode").empty();
4634 !m_dpmsIsActive && m_dpms->IsSupported()
4635 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4637 // Has the screen saver window become active?
4638 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4640 m_bScreenSave = true;
4641 maybeScreensaver = false;
4644 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4646 WakeUpScreenSaverAndDPMS();
4650 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4652 // See if we need to reset timer.
4653 // * Are we playing a video and it is not paused?
4654 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4655 // * Are we playing some music in fullscreen vis?
4656 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4657 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4659 ResetScreenSaverTimer();
4663 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4665 // DPMS has priority (it makes the screensaver not needed)
4667 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4670 WakeUpScreenSaver();
4672 else if (maybeScreensaver
4673 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4675 ActivateScreenSaver();
4679 // activate the screensaver.
4680 // if forceType is true, we ignore the various conditions that can alter
4681 // the type of screensaver displayed
4682 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4684 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4685 { // just activate the visualisation if user toggled the usemusicvisinstead option
4686 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4690 m_bScreenSave = true;
4692 // Get Screensaver Mode
4693 m_screenSaver.reset();
4694 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4695 m_screenSaver.reset(new CScreenSaver(""));
4697 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverActivated");
4699 // disable screensaver lock from the login screen
4700 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4703 // set to Dim in the case of a dialog on screen or playing video
4704 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4706 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4707 m_screenSaver.reset(new CScreenSaver(""));
4710 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4712 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4714 else if (!m_screenSaver->ID().empty())
4715 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4718 void CApplication::CheckShutdown()
4720 // first check if we should reset the timer
4721 if (m_bInhibitIdleShutdown
4722 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4723 || m_musicInfoScanner->IsScanning()
4724 || m_videoInfoScanner->IsScanning()
4725 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4726 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4728 m_shutdownTimer.StartZero();
4732 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4734 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4735 m_shutdownTimer.Stop();
4738 CApplicationMessenger::Get().Shutdown();
4742 void CApplication::InhibitIdleShutdown(bool inhibit)
4744 m_bInhibitIdleShutdown = inhibit;
4747 bool CApplication::IsIdleShutdownInhibited() const
4749 return m_bInhibitIdleShutdown;
4752 bool CApplication::OnMessage(CGUIMessage& message)
4754 switch ( message.GetMessage() )
4756 case GUI_MSG_NOTIFY_ALL:
4758 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4760 // Update general playlist: Remove DVD playlist items
4761 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4764 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4765 g_windowManager.SendMessage( msg );
4767 // stop the file if it's on dvd (will set the resume point etc)
4768 if (m_itemCurrentFile->IsOnDVD())
4774 case GUI_MSG_PLAYBACK_STARTED:
4776 #ifdef TARGET_DARWIN
4777 DarwinSetScheduling(message.GetMessage());
4779 // reset the seek handler
4780 m_seekHandler->Reset();
4781 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4783 // Update our infoManager with the new details etc.
4784 if (m_nextPlaylistItem >= 0)
4786 // playing an item which is not in the list - player might be stopped already
4788 if (playList.size() <= m_nextPlaylistItem)
4791 // we've started a previously queued item
4792 CFileItemPtr item = playList[m_nextPlaylistItem];
4793 // update the playlist manager
4794 int currentSong = g_playlistPlayer.GetCurrentSong();
4795 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4796 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4797 g_windowManager.SendThreadMessage(msg);
4798 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4799 *m_itemCurrentFile = *item;
4801 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4802 g_partyModeManager.OnSongChange(true);
4805 param["player"]["speed"] = 1;
4806 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4807 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4809 if (m_pPlayer->IsPlayingAudio())
4811 // Start our cdg parser as appropriate
4813 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4815 m_pKaraokeMgr->Stop();
4816 if (m_itemCurrentFile->IsMusicDb())
4818 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4820 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4821 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4824 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4827 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4836 case GUI_MSG_QUEUE_NEXT_ITEM:
4838 // Check to see if our playlist player has a new item for us,
4839 // and if so, we check whether our current player wants the file
4840 int iNext = g_playlistPlayer.GetNextSong();
4841 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4842 if (iNext < 0 || iNext >= playlist.size())
4844 m_pPlayer->OnNothingToQueueNotify();
4845 return true; // nothing to do
4848 // ok, grab the next song
4849 CFileItem file(*playlist[iNext]);
4851 CURL url(file.GetPath());
4852 if (url.GetProtocol() == "plugin")
4853 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4856 if (URIUtils::IsUPnP(file.GetPath()))
4858 if (!XFILE::CUPnPDirectory::GetResource(file.GetURL(), file))
4863 // ok - send the file to the player, if it accepts it
4864 if (m_pPlayer->QueueNextFile(file))
4866 // player accepted the next file
4867 m_nextPlaylistItem = iNext;
4871 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4872 queue the next (if it wants to) and it doesn't keep looping on this song */
4873 g_playlistPlayer.SetCurrentSong(iNext);
4880 case GUI_MSG_PLAYBACK_STOPPED:
4881 case GUI_MSG_PLAYBACK_ENDED:
4882 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4886 m_pKaraokeMgr->Stop();
4888 #ifdef TARGET_DARWIN
4889 DarwinSetScheduling(message.GetMessage());
4891 // first check if we still have items in the stack to play
4892 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4894 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4895 { // just play the next item in the stack
4896 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4901 // In case playback ended due to user eg. skipping over the end, clear
4902 // our resume bookmark here
4903 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4905 // Delete the bookmark
4906 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4909 // reset the current playing file
4910 m_itemCurrentFile->Reset();
4911 g_infoManager.ResetCurrentItem();
4912 m_currentStack->Clear();
4914 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4916 g_playlistPlayer.PlayNext(1, true);
4920 // reset any forced player
4921 m_eForcedNextPlayer = EPC_NONE;
4923 m_pPlayer->ClosePlayer();
4926 m_pPlayer->m_iPlaySpeed = 1;
4929 if (!m_pPlayer->IsPlaying())
4931 g_audioManager.Enable(true);
4934 if (!m_pPlayer->IsPlayingVideo())
4936 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4938 g_windowManager.PreviousWindow();
4942 CSingleLock lock(g_graphicsContext);
4943 // resets to res_desktop or look&feel resolution (including refreshrate)
4944 g_graphicsContext.SetFullScreenVideo(false);
4948 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4950 CSettings::Get().Save(); // save vis settings
4951 WakeUpScreenSaverAndDPMS();
4952 g_windowManager.PreviousWindow();
4955 // DVD ejected while playing in vis ?
4956 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4959 CSettings::Get().Save(); // save vis settings
4960 WakeUpScreenSaverAndDPMS();
4961 g_windowManager.PreviousWindow();
4964 if (IsEnableTestMode())
4965 CApplicationMessenger::Get().Quit();
4970 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4971 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4976 case GUI_MSG_FULLSCREEN:
4977 { // Switch to fullscreen, if we can
4978 SwitchToFullScreen();
4982 case GUI_MSG_EXECUTE:
4983 if (message.GetNumStringParams())
4984 return ExecuteXBMCAction(message.GetStringParam());
4990 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4992 // see if it is a user set string
4994 //We don't know if there is unsecure information in this yet, so we
4995 //postpone any logging
4996 const std::string in_actionStr(actionStr);
4997 CGUIInfoLabel info(actionStr, "");
4998 actionStr = info.GetLabel(0);
5000 // user has asked for something to be executed
5001 if (CBuiltins::HasCommand(actionStr))
5002 CBuiltins::Execute(actionStr);
5005 // try translating the action from our ButtonTranslator
5007 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5009 OnAction(CAction(actionID));
5012 CFileItem item(actionStr, false);
5014 if (item.IsPythonScript())
5015 { // a python script
5016 CScriptInvocationManager::Get().Execute(item.GetPath());
5020 if (item.IsAudio() || item.IsVideo())
5021 { // an audio or video file
5026 //At this point we have given up to translate, so even though
5027 //there may be insecure information, we log it.
5028 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5035 void CApplication::Process()
5039 // dispatch the messages generated by python or other threads to the current window
5040 g_windowManager.DispatchThreadMessages();
5042 // process messages which have to be send to the gui
5043 // (this can only be done after g_windowManager.Render())
5044 CApplicationMessenger::Get().ProcessWindowMessages();
5048 m_loggingIn = false;
5050 // autoexec.py - profile
5051 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5053 if (XFILE::CFile::Exists(strAutoExecPy))
5054 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5056 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5059 // handle any active scripts
5060 CScriptInvocationManager::Get().Process();
5062 // process messages, even if a movie is playing
5063 CApplicationMessenger::Get().ProcessMessages();
5064 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5066 // check how far we are through playing the current item
5067 // and do anything that needs doing (playcount updates etc)
5068 CheckPlayingProgress();
5071 m_pPlayer->DoAudioWork();
5073 // do any processing that isn't needed on each run
5074 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5076 m_slowTimer.Reset();
5080 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5083 // We get called every 500ms
5084 void CApplication::ProcessSlow()
5086 g_powerManager.ProcessEvents();
5088 #if defined(TARGET_DARWIN_OSX)
5089 // There is an issue on OS X that several system services ask the cursor to become visible
5090 // during their startup routines. Given that we can't control this, we hack it in by
5092 if (g_Windowing.IsFullScreen())
5093 { // SDL thinks it's hidden
5098 // Temporarely pause pausable jobs when viewing video/picture
5099 int currentWindow = g_windowManager.GetActiveWindow();
5100 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5102 CJobManager::GetInstance().PauseJobs();
5106 CJobManager::GetInstance().UnPauseJobs();
5109 // Store our file state for use on close()
5112 // Check if we need to activate the screensaver / DPMS.
5113 CheckScreenSaverAndDPMS();
5115 // Check if we need to shutdown (if enabled).
5116 #if defined(TARGET_DARWIN)
5117 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5119 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5125 // check if we should restart the player
5126 CheckDelayedPlayerRestart();
5128 // check if we can unload any unreferenced dlls or sections
5129 if (!m_pPlayer->IsPlayingVideo())
5130 CSectionLoader::UnloadDelayed();
5132 // check for any idle curl connections
5133 g_curlInterface.CheckIdle();
5135 // check for any idle myth sessions
5136 CMythSession::CheckIdle();
5138 #ifdef HAS_FILESYSTEM_HTSP
5139 // check for any idle htsp sessions
5140 HTSP::CHTSPDirectorySession::CheckIdle();
5144 if ( m_pKaraokeMgr )
5145 m_pKaraokeMgr->ProcessSlow();
5148 if (!m_pPlayer->IsPlayingVideo())
5149 g_largeTextureManager.CleanupUnusedImages();
5151 g_TextureManager.FreeUnusedTextures(5000);
5153 #ifdef HAS_DVD_DRIVE
5154 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5155 if (!m_pPlayer->IsPlayingVideo())
5156 m_Autorun->HandleAutorun();
5159 // update upnp server/renderer states
5161 if(UPNP::CUPnP::IsInstantiated())
5162 UPNP::CUPnP::GetInstance()->UpdateState();
5165 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5169 #ifdef HAS_FILESYSTEM_NFS
5170 gNfsConnection.CheckIfIdle();
5173 #ifdef HAS_FILESYSTEM_AFP
5174 gAfpConnection.CheckIfIdle();
5177 #ifdef HAS_FILESYSTEM_SFTP
5178 CSFTPSessionManager::ClearOutIdleSessions();
5181 g_mediaManager.ProcessEvents();
5184 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5185 g_RemoteControl.Initialize();
5188 if (!m_pPlayer->IsPlayingVideo() &&
5189 CSettings::Get().GetInt("general.addonupdates") != AUTO_UPDATES_NEVER)
5190 CAddonInstaller::Get().UpdateRepos();
5192 CAEFactory::GarbageCollect();
5194 // if we don't render the gui there's no reason to start the screensaver.
5195 // that way the screensaver won't kick in if we maximize the XBMC window
5196 // after the screensaver start time.
5198 ResetScreenSaverTimer();
5201 // Global Idle Time in Seconds
5202 // idle time will be resetet if on any OnKey()
5203 // int return: system Idle time in seconds! 0 is no idle!
5204 int CApplication::GlobalIdleTime()
5206 if(!m_idleTimer.IsRunning())
5209 m_idleTimer.StartZero();
5211 return (int)m_idleTimer.GetElapsedSeconds();
5214 float CApplication::NavigationIdleTime()
5216 if (!m_navigationTimer.IsRunning())
5218 m_navigationTimer.Stop();
5219 m_navigationTimer.StartZero();
5221 return m_navigationTimer.GetElapsedSeconds();
5224 void CApplication::DelayedPlayerRestart()
5226 m_restartPlayerTimer.StartZero();
5229 void CApplication::CheckDelayedPlayerRestart()
5231 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5233 m_restartPlayerTimer.Stop();
5234 m_restartPlayerTimer.Reset();
5239 void CApplication::Restart(bool bSamePosition)
5241 // this function gets called when the user changes a setting (like noninterleaved)
5242 // and which means we gotta close & reopen the current playing file
5244 // first check if we're playing a file
5245 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5248 if( !m_pPlayer->HasPlayer() )
5253 // do we want to return to the current position in the file
5254 if (false == bSamePosition)
5256 // no, then just reopen the file and start at the beginning
5257 PlayFile(*m_itemCurrentFile, true);
5261 // else get current position
5262 double time = GetTime();
5264 // get player state, needed for dvd's
5265 CStdString state = m_pPlayer->GetPlayerState();
5267 // set the requested starttime
5268 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5271 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5272 m_pPlayer->SetPlayerState(state);
5275 const CStdString& CApplication::CurrentFile()
5277 return m_itemCurrentFile->GetPath();
5280 CFileItem& CApplication::CurrentFileItem()
5282 return *m_itemCurrentFile;
5285 CFileItem& CApplication::CurrentUnstackedItem()
5287 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5288 return *(*m_currentStack)[m_currentStackPosition];
5290 return *m_itemCurrentFile;
5293 void CApplication::ShowVolumeBar(const CAction *action)
5295 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5300 volumeBar->OnAction(*action);
5304 bool CApplication::IsMuted() const
5306 if (g_peripherals.IsMuted())
5308 return CAEFactory::IsMuted();
5311 void CApplication::ToggleMute(void)
5319 void CApplication::SetMute(bool mute)
5321 if (m_muted != mute)
5328 void CApplication::Mute()
5330 if (g_peripherals.Mute())
5333 CAEFactory::SetMute(true);
5338 void CApplication::UnMute()
5340 if (g_peripherals.UnMute())
5343 CAEFactory::SetMute(false);
5348 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5350 float hardwareVolume = iValue;
5353 hardwareVolume /= 100.0f;
5355 SetHardwareVolume(hardwareVolume);
5359 void CApplication::SetHardwareVolume(float hardwareVolume)
5361 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5362 m_volumeLevel = hardwareVolume;
5364 CAEFactory::SetVolume(hardwareVolume);
5367 float CApplication::GetVolume(bool percentage /* = true */) const
5371 // converts the hardware volume to a percentage
5372 return m_volumeLevel * 100.0f;
5375 return m_volumeLevel;
5378 void CApplication::VolumeChanged() const
5380 CVariant data(CVariant::VariantTypeObject);
5381 data["volume"] = GetVolume();
5382 data["muted"] = m_muted;
5383 CAnnouncementManager::Get().Announce(Application, "xbmc", "OnVolumeChanged", data);
5385 // if player has volume control, set it.
5386 if (m_pPlayer->ControlsVolume())
5388 m_pPlayer->SetVolume(m_volumeLevel);
5389 m_pPlayer->SetMute(m_muted);
5393 int CApplication::GetSubtitleDelay() const
5395 // converts subtitle delay to a percentage
5396 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5399 int CApplication::GetAudioDelay() const
5401 // converts audio delay to a percentage
5402 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5405 // Returns the total time in seconds of the current media. Fractional
5406 // portions of a second are possible - but not necessarily supported by the
5407 // player class. This returns a double to be consistent with GetTime() and
5409 double CApplication::GetTotalTime() const
5413 if (m_pPlayer->IsPlaying())
5415 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5416 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5418 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5424 void CApplication::StopShutdownTimer()
5426 if (m_shutdownTimer.IsRunning())
5427 m_shutdownTimer.Stop();
5430 void CApplication::ResetShutdownTimers()
5432 // reset system shutdown timer
5433 m_shutdownTimer.StartZero();
5435 // delete custom shutdown timer
5436 if (g_alarmClock.HasAlarm("shutdowntimer"))
5437 g_alarmClock.Stop("shutdowntimer", true);
5440 // Returns the current time in seconds of the currently playing media.
5441 // Fractional portions of a second are possible. This returns a double to
5442 // be consistent with GetTotalTime() and SeekTime().
5443 double CApplication::GetTime() const
5447 if (m_pPlayer->IsPlaying())
5449 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5451 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5452 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5455 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5461 // Sets the current position of the currently playing media to the specified
5462 // time in seconds. Fractional portions of a second are valid. The passed
5463 // time is the time offset from the beginning of the file as opposed to a
5464 // delta from the current position. This method accepts a double to be
5465 // consistent with GetTime() and GetTotalTime().
5466 void CApplication::SeekTime( double dTime )
5468 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5470 if (!m_pPlayer->CanSeek()) return;
5471 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5473 // find the item in the stack we are seeking to, and load the new
5474 // file if necessary, and calculate the correct seek within the new
5475 // file. Otherwise, just fall through to the usual routine if the
5476 // time is higher than our total time.
5477 for (int i = 0; i < m_currentStack->Size(); i++)
5479 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5481 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5482 if (m_currentStackPosition == i)
5483 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5485 { // seeking to a new file
5486 m_currentStackPosition = i;
5487 CFileItem item(*(*m_currentStack)[i]);
5488 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5489 // don't just call "PlayFile" here, as we are quite likely called from the
5490 // player thread, so we won't be able to delete ourselves.
5491 CApplicationMessenger::Get().PlayFile(item, true);
5497 // convert to milliseconds and perform seek
5498 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5502 float CApplication::GetPercentage() const
5504 if (m_pPlayer->IsPlaying())
5506 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5508 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5509 if (tag.GetDuration() > 0)
5510 return (float)(GetTime() / tag.GetDuration() * 100);
5513 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5515 double totalTime = GetTotalTime();
5516 if (totalTime > 0.0f)
5517 return (float)(GetTime() / totalTime * 100);
5520 return m_pPlayer->GetPercentage();
5525 float CApplication::GetCachePercentage() const
5527 if (m_pPlayer->IsPlaying())
5529 // Note that the player returns a relative cache percentage and we want an absolute percentage
5530 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5532 float stackedTotalTime = (float) GetTotalTime();
5533 // We need to take into account the stack's total time vs. currently playing file's total time
5534 if (stackedTotalTime > 0.0f)
5535 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5538 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5543 void CApplication::SeekPercentage(float percent)
5545 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5547 if (!m_pPlayer->CanSeek()) return;
5548 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5549 SeekTime(percent * 0.01 * GetTotalTime());
5551 m_pPlayer->SeekPercentage(percent);
5555 // SwitchToFullScreen() returns true if a switch is made, else returns false
5556 bool CApplication::SwitchToFullScreen()
5558 // if playing from the video info window, close it first!
5559 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5561 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5562 if (pDialog) pDialog->Close(true);
5565 // don't switch if there is a dialog on screen or the slideshow is active
5566 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5569 // See if we're playing a video, and are in GUI mode
5570 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5572 // then switch to fullscreen mode
5573 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5576 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5577 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5578 { // then switch to visualisation
5579 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5585 void CApplication::Minimize()
5587 g_Windowing.Minimize();
5590 PLAYERCOREID CApplication::GetCurrentPlayer()
5592 return m_pPlayer->GetCurrentPlayer();
5595 void CApplication::UpdateLibraries()
5597 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5599 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5603 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5605 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5610 bool CApplication::IsVideoScanning() const
5612 return m_videoInfoScanner->IsScanning();
5615 bool CApplication::IsMusicScanning() const
5617 return m_musicInfoScanner->IsScanning();
5620 void CApplication::StopVideoScan()
5622 if (m_videoInfoScanner->IsScanning())
5623 m_videoInfoScanner->Stop();
5626 void CApplication::StopMusicScan()
5628 if (m_musicInfoScanner->IsScanning())
5629 m_musicInfoScanner->Stop();
5632 void CApplication::StartVideoCleanup()
5634 if (m_videoInfoScanner->IsScanning())
5637 m_videoInfoScanner->CleanDatabase();
5640 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5642 if (m_videoInfoScanner->IsScanning())
5645 m_videoInfoScanner->ShowDialog(true);
5647 m_videoInfoScanner->Start(strDirectory,scanAll);
5650 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5652 if (m_musicInfoScanner->IsScanning())
5656 { // setup default flags
5657 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5658 flags |= CMusicInfoScanner::SCAN_ONLINE;
5659 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5660 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5663 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5664 m_musicInfoScanner->ShowDialog(true);
5666 m_musicInfoScanner->Start(strDirectory, flags);
5669 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5672 if (m_musicInfoScanner->IsScanning())
5675 m_musicInfoScanner->ShowDialog(true);
5677 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5680 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5683 if (m_musicInfoScanner->IsScanning())
5686 m_musicInfoScanner->ShowDialog(true);
5688 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5691 void CApplication::CheckPlayingProgress()
5693 // check if we haven't rewound past the start of the file
5694 if (m_pPlayer->IsPlaying())
5696 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5706 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5708 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5709 g_application.SeekTime(0);
5715 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5717 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5719 // initial exit conditions
5720 // no songs in playlist just return
5721 if (playlist.size() == 0)
5725 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5728 // setup correct playlist
5729 g_playlistPlayer.ClearPlaylist(iPlaylist);
5731 // if the playlist contains an internet stream, this file will be used
5732 // to generate a thumbnail for musicplayer.cover
5733 g_application.m_strPlayListFile = strPlayList;
5735 // add the items to the playlist player
5736 g_playlistPlayer.Add(iPlaylist, playlist);
5738 // if we have a playlist
5739 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5742 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5743 g_playlistPlayer.Reset();
5744 g_playlistPlayer.Play(track);
5750 void CApplication::SaveCurrentFileSettings()
5752 // don't store settings for PVR in video database
5753 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5755 // save video settings
5756 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5760 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5764 else if (m_itemCurrentFile->IsPVRChannel())
5766 g_PVRManager.SaveCurrentChannelSettings();
5770 bool CApplication::AlwaysProcess(const CAction& action)
5772 // check if this button is mapped to a built-in function
5773 if (!action.GetName().empty())
5775 CStdString builtInFunction;
5776 vector<string> params;
5777 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5778 StringUtils::ToLower(builtInFunction);
5780 // should this button be handled normally or just cancel the screensaver?
5781 if ( builtInFunction.Equals("powerdown")
5782 || builtInFunction.Equals("reboot")
5783 || builtInFunction.Equals("restart")
5784 || builtInFunction.Equals("restartapp")
5785 || builtInFunction.Equals("suspend")
5786 || builtInFunction.Equals("hibernate")
5787 || builtInFunction.Equals("quit")
5788 || builtInFunction.Equals("shutdown"))
5797 bool CApplication::IsCurrentThread() const
5799 return CThread::IsCurrentThread(m_threadID);
5802 void CApplication::SetRenderGUI(bool renderGUI)
5804 if (renderGUI && ! m_renderGUI)
5805 g_windowManager.MarkDirty();
5806 m_renderGUI = renderGUI;
5809 CNetwork& CApplication::getNetwork()
5813 #ifdef HAS_PERFORMANCE_SAMPLE
5814 CPerformanceStats &CApplication::GetPerformanceStats()
5820 bool CApplication::SetLanguage(const CStdString &strLanguage)
5822 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5823 if (strLanguage != strPreviousLanguage)
5825 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
5826 if (!g_langInfo.Load(strLangInfoPath))
5829 CSettings::Get().SetString("locale.language", strLanguage);
5831 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
5834 // also tell our weather and skin to reload as these are localized
5835 g_weatherManager.Refresh();
5836 g_PVRManager.LocalizationChanged();
5843 void CApplication::CloseNetworkShares()
5845 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5847 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5851 #ifdef HAS_FILESYSTEM_NFS
5852 gNfsConnection.Deinit();
5855 #ifdef HAS_FILESYSTEM_AFP
5856 gAfpConnection.Deinit();
5859 #ifdef HAS_FILESYSTEM_SFTP
5860 CSFTPSessionManager::DisconnectAllSessions();