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 == "audiocds.settings")
1721 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("audiocds.encoder"), addon, ADDON_AUDIOENCODER))
1722 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1724 else if (settingId == "videoscreen.guicalibration")
1725 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1726 else if (settingId == "videoscreen.testpattern")
1727 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1730 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1732 if (setting == NULL)
1735 const std::string &settingId = setting->GetId();
1736 if (settingId == "audiooutput.channels")
1738 // check if this is an update from Eden
1739 if (oldSettingId != NULL && oldSettingNode != NULL &&
1740 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1743 CSettingInt* channels = (CSettingInt*)setting;
1744 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1745 ret = channels->SetValue(channels->GetValue() + 1);
1747 // let's just reset the audiodevice settings as well
1748 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1749 CAEFactory::VerifyOutputDevice(audiodevice, false);
1750 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1755 else if (settingId == "screensaver.mode")
1757 CSettingString *screensaverMode = (CSettingString*)setting;
1758 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1759 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1760 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1762 else if (settingId == "scrapers.musicvideosdefault")
1764 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1765 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1767 musicvideoScraper->Reset();
1771 #if defined(HAS_LIBAMCODEC)
1772 else if (settingId == "videoplayer.useamcodec")
1774 // Do not permit amcodec to be used on non-aml platforms.
1775 // The setting will be hidden but the default value is true,
1776 // so change it to false.
1779 CSettingBool *useamcodec = (CSettingBool*)setting;
1780 useamcodec->SetValue(false);
1784 #if defined(TARGET_ANDROID)
1785 else if (settingId == "videoplayer.usemediacodec")
1787 // Do not permit MediaCodec to be used Android platforms that do not have it.
1788 // The setting will be hidden but the default value is true,
1789 // so change it to false.
1790 if (CAndroidFeatures::GetVersion() < 16)
1792 CSettingBool *usemediacodec = (CSettingBool*)setting;
1793 usemediacodec->SetValue(false);
1796 else if (settingId == "videoplayer.usestagefright")
1798 CSettingBool *usestagefright = (CSettingBool*)setting;
1799 usestagefright->SetValue(false);
1802 #if defined(TARGET_DARWIN_OSX)
1803 else if (settingId == "audiooutput.audiodevice")
1805 CSettingString *audioDevice = (CSettingString*)setting;
1806 // Gotham and older didn't enumerate audio devices per stream on osx
1807 // add stream0 per default which should be ok for all old settings.
1808 if (!StringUtils::EqualsNoCase(audioDevice->GetValue(), "DARWINOSX:default") &&
1809 StringUtils::FindWords(audioDevice->GetValue().c_str(), ":stream") == std::string::npos)
1811 std::string newSetting = audioDevice->GetValue();
1812 newSetting += ":stream0";
1813 return audioDevice->SetValue(newSetting);
1821 bool CApplication::OnSettingsSaving() const
1823 // don't save settings when we're busy stopping the application
1824 // a lot of screens try to save settings on deinit and deinit is
1825 // called for every screen when the application is stopping
1832 void CApplication::ReloadSkin(bool confirm/*=false*/)
1834 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1836 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1837 g_windowManager.SendMessage(msg);
1839 string newSkin = CSettings::Get().GetString("lookandfeel.skin");
1840 if (LoadSkin(newSkin))
1842 /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
1843 user as to whether they want to keep the current skin. */
1844 if (confirm && !m_skinReverting)
1847 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1849 m_skinReverting = true;
1850 if (oldSkin.empty())
1851 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1853 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1859 // skin failed to load - we revert to the default only if we didn't fail loading the default
1860 string defaultSkin = ((CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1861 if (newSkin != defaultSkin)
1863 m_skinReverting = true;
1864 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1865 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1868 m_skinReverting = false;
1871 bool CApplication::Load(const TiXmlNode *settings)
1873 if (settings == NULL)
1876 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1877 if (audioElement != NULL)
1879 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1880 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1881 m_volumeLevel = VOLUME_MAXIMUM;
1887 bool CApplication::Save(TiXmlNode *settings) const
1889 if (settings == NULL)
1892 TiXmlElement volumeNode("audio");
1893 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1894 if (audioNode == NULL)
1897 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1898 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1903 bool CApplication::LoadSkin(const CStdString& skinID)
1906 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1908 if (LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
1911 CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
1915 bool CApplication::LoadSkin(const SkinPtr& skin)
1921 if (!skin->HasSkinFile("Home.xml"))
1924 bool bPreviousPlayingState=false;
1925 bool bPreviousRenderingState=false;
1926 if (g_application.m_pPlayer->IsPlayingVideo())
1928 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1929 if (bPreviousPlayingState)
1930 g_application.m_pPlayer->Pause();
1931 #ifdef HAS_VIDEO_PLAYBACK
1932 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1934 g_windowManager.ActivateWindow(WINDOW_HOME);
1935 bPreviousRenderingState = true;
1939 // close the music and video overlays (they're re-opened automatically later)
1940 CSingleLock lock(g_graphicsContext);
1942 // save the current window details and focused control
1943 int currentWindow = g_windowManager.GetActiveWindow();
1945 CGUIWindow* pWindow = g_windowManager.GetWindow(currentWindow);
1947 iCtrlID = pWindow->GetFocusedControlID();
1948 vector<int> currentModelessWindows;
1949 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1953 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
1955 g_SkinInfo->Start();
1957 CLog::Log(LOGINFO, " load fonts for skin...");
1958 g_graphicsContext.SetMediaDir(skin->Path());
1959 g_directoryCache.ClearSubPaths(skin->Path());
1961 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1963 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1965 // load in the skin strings
1966 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1967 URIUtils::AddSlashAtEnd(langPath);
1969 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1971 g_SkinInfo->LoadIncludes();
1974 start = CurrentHostCounter();
1976 CLog::Log(LOGINFO, " load new skin...");
1978 // Load the user windows
1982 end = CurrentHostCounter();
1983 freq = CurrentHostFrequency();
1984 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1986 CLog::Log(LOGINFO, " initialize new skin...");
1987 g_windowManager.AddMsgTarget(this);
1988 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1989 g_windowManager.AddMsgTarget(&g_infoManager);
1990 g_windowManager.AddMsgTarget(&g_fontManager);
1991 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1992 g_windowManager.SetCallback(*this);
1993 g_windowManager.Initialize();
1994 CTextureCache::Get().Initialize();
1995 g_audioManager.Enable(true);
1996 g_audioManager.Load();
1998 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1999 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2001 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2002 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2003 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2004 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2005 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2008 CLog::Log(LOGINFO, " skin loaded...");
2010 // leave the graphics lock
2014 if (currentWindow != WINDOW_INVALID)
2016 g_windowManager.ActivateWindow(currentWindow);
2017 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2019 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2020 if (dialog) dialog->Show();
2024 pWindow = g_windowManager.GetWindow(currentWindow);
2025 if (pWindow && pWindow->HasSaveLastControl())
2027 CGUIMessage msg(GUI_MSG_SETFOCUS, currentWindow, iCtrlID, 0);
2028 pWindow->OnMessage(msg);
2033 if (g_application.m_pPlayer->IsPlayingVideo())
2035 if (bPreviousPlayingState)
2036 g_application.m_pPlayer->Pause();
2037 if (bPreviousRenderingState)
2038 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2043 void CApplication::UnloadSkin(bool forReload /* = false */)
2045 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2047 g_audioManager.Enable(false);
2049 g_windowManager.DeInitialize();
2050 CTextureCache::Get().Deinitialize();
2052 // remove the skin-dependent window
2053 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2055 g_TextureManager.Cleanup();
2056 g_largeTextureManager.CleanupUnusedImages(true);
2058 g_fontManager.Clear();
2060 g_colorManager.Clear();
2062 g_infoManager.Clear();
2064 // The g_SkinInfo boost shared_ptr ought to be reset here
2065 // but there are too many places it's used without checking for NULL
2066 // and as a result a race condition on exit can cause a crash.
2069 bool CApplication::LoadUserWindows()
2071 // Start from wherever home.xml is
2072 std::vector<CStdString> vecSkinPath;
2073 g_SkinInfo->GetSkinPaths(vecSkinPath);
2074 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2076 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2077 CFileItemList items;
2078 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2080 for (int i = 0; i < items.Size(); ++i)
2082 if (items[i]->m_bIsFolder)
2084 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2085 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2087 CXBMCTinyXML xmlDoc;
2088 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2090 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2094 // Root element should be <window>
2095 TiXmlElement* pRootElement = xmlDoc.RootElement();
2096 CStdString strValue = pRootElement->Value();
2097 if (!strValue.Equals("window"))
2099 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2103 // Read the <type> element to get the window type to create
2104 // If no type is specified, create a CGUIWindow as default
2105 CGUIWindow* pWindow = NULL;
2107 if (pRootElement->Attribute("type"))
2108 strType = pRootElement->Attribute("type");
2111 const TiXmlNode *pType = pRootElement->FirstChild("type");
2112 if (pType && pType->FirstChild())
2113 strType = pType->FirstChild()->Value();
2115 int id = WINDOW_INVALID;
2116 if (!pRootElement->Attribute("id", &id))
2118 const TiXmlNode *pType = pRootElement->FirstChild("id");
2119 if (pType && pType->FirstChild())
2120 id = atol(pType->FirstChild()->Value());
2122 CStdString visibleCondition;
2123 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2125 if (strType.Equals("dialog"))
2126 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2127 else if (strType.Equals("submenu"))
2128 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2129 else if (strType.Equals("buttonmenu"))
2130 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2132 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2134 // Check to make sure the pointer isn't still null
2135 if (pWindow == NULL)
2137 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2140 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2145 pWindow->SetVisibleCondition(visibleCondition);
2146 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2147 g_windowManager.AddCustomWindow(pWindow);
2155 bool CApplication::RenderNoPresent()
2159 // DXMERGE: This may have been important?
2160 // g_graphicsContext.AcquireCurrentContext();
2162 g_graphicsContext.Lock();
2164 // dont show GUI when playing full screen video
2165 if (g_graphicsContext.IsFullScreenVideo())
2167 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2168 g_renderManager.Render(true, 0, 255);
2170 // close window overlays
2171 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2172 if (overlay) overlay->Close(true);
2173 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2174 if (overlay) overlay->Close(true);
2178 bool hasRendered = g_windowManager.Render();
2180 g_graphicsContext.Unlock();
2185 float CApplication::GetDimScreenSaverLevel() const
2187 if (!m_bScreenSave || !m_screenSaver ||
2188 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2189 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2190 !m_screenSaver->ID().empty()))
2193 if (!m_screenSaver->GetSetting("level").empty())
2194 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2198 void CApplication::Render()
2200 // do not render if we are stopped or in background
2206 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2208 bool hasRendered = false;
2209 bool limitFrames = false;
2210 unsigned int singleFrameTime = 10; // default limit 100 fps
2214 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2215 // Whether externalplayer is playing and we're unfocused
2216 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2218 m_bPresentFrame = false;
2219 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2221 m_bPresentFrame = g_renderManager.FrameWait(100);
2226 // engage the frame limiter as needed
2227 limitFrames = lowfps || extPlayerActive;
2228 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2229 // perhaps allowing it to be set differently than the UI option??
2230 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2231 limitFrames = true; // not using vsync.
2232 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2233 limitFrames = true; // using vsync, but it isn't working.
2237 if (extPlayerActive)
2239 ResetScreenSaver(); // Prevent screensaver dimming the screen
2240 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2243 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2249 CSingleLock lock(g_graphicsContext);
2250 g_infoManager.UpdateFPS();
2252 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2253 g_Windowing.SetVSync(true);
2254 else if (vsync_mode == VSYNC_ALWAYS)
2255 g_Windowing.SetVSync(true);
2256 else if (vsync_mode != VSYNC_DRIVER)
2257 g_Windowing.SetVSync(false);
2259 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2262 if(!g_Windowing.BeginRender())
2265 g_renderManager.FrameMove();
2267 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2268 if(g_graphicsContext.GetStereoMode())
2270 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2271 if(RenderNoPresent())
2274 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2276 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2277 if(RenderNoPresent())
2280 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2284 if(RenderNoPresent())
2288 g_renderManager.FrameFinish();
2290 g_Windowing.EndRender();
2292 // execute post rendering actions (finalize window closing)
2293 g_windowManager.AfterRender();
2295 // reset our info cache - we do this at the end of Render so that it is
2296 // fresh for the next process(), or after a windowclose animation (where process()
2298 g_infoManager.ResetCache();
2301 unsigned int now = XbmcThreads::SystemClockMillis();
2303 m_lastRenderTime = now;
2305 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2306 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2308 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2309 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2313 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2314 if (limitFrames || !flip)
2317 singleFrameTime = 40; //if not flipping, loop at 25 fps
2319 unsigned int frameTime = now - m_lastFrameTime;
2320 if (frameTime < singleFrameTime)
2321 Sleep(singleFrameTime - frameTime);
2323 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2326 g_graphicsContext.Flip(dirtyRegions);
2327 CTimeUtils::UpdateFrameTime(flip);
2329 g_renderManager.UpdateResolution();
2330 g_renderManager.ManageCaptures();
2333 void CApplication::SetStandAlone(bool value)
2335 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2338 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2339 // The window manager will return true if the event is processed, false otherwise.
2340 // If not already processed, this routine handles global keypresses. It returns
2341 // true if the key has been processed, false otherwise.
2343 bool CApplication::OnKey(const CKey& key)
2346 // Turn the mouse off, as we've just got a keypress from controller or remote
2347 g_Mouse.SetActive(false);
2349 // get the current active window
2350 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2352 // this will be checked for certain keycodes that need
2353 // special handling if the screensaver is active
2354 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2356 // a key has been pressed.
2358 m_idleTimer.StartZero();
2359 bool processKey = AlwaysProcess(action);
2361 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2365 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2366 // do not wake up the screensaver right after switching off the playing device
2367 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2368 ret = CApplicationMessenger::Get().CECToggleState();
2370 ret = CApplicationMessenger::Get().CECStandby();
2371 if (!ret) /* display is switched off */
2377 // allow some keys to be processed while the screensaver is active
2378 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2380 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2384 // change this if we have a dialog up
2385 if (g_windowManager.HasModalDialog())
2387 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2389 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2390 { // fullscreen info dialog - special case
2391 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2393 if (!key.IsAnalogButton())
2394 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2396 if (OnAction(action))
2399 // fallthrough to the main window
2400 iWin = WINDOW_FULLSCREEN_VIDEO;
2402 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2404 // current active window is full screen video.
2405 if (g_application.m_pPlayer->IsInMenu())
2407 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2408 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2410 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2412 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2413 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2415 // if no PVR specific action/mapping is found, fall back to default
2416 if (action.GetID() == 0)
2417 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2421 // in any other case use the fullscreen window section of keymap.xml to map key->action
2422 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2427 // current active window isnt the fullscreen window
2428 // just use corresponding section from keymap.xml
2429 // to map key->action
2431 // first determine if we should use keyboard input directly
2432 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2433 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2436 CGUIControl *control = window->GetFocusedControl();
2439 // If this is an edit control set usekeyboard to true. This causes the
2440 // keypress to be processed directly not through the key mappings.
2441 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2444 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2445 // This causes the keypress to be used for list navigation.
2446 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2452 action = CAction(0); // reset our action
2453 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2455 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2456 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2457 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2458 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2459 action.GetID() == ACTION_MOVE_RIGHT ||
2460 action.GetID() == ACTION_MOVE_UP ||
2461 action.GetID() == ACTION_MOVE_DOWN ||
2462 action.GetID() == ACTION_SELECT_ITEM ||
2463 action.GetID() == ACTION_ENTER ||
2464 action.GetID() == ACTION_PREVIOUS_MENU ||
2465 action.GetID() == ACTION_NAV_BACK))
2467 // the action isn't plain navigation - check for a keyboard-specific keymap
2468 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2469 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2470 action.GetID() == ACTION_BACKSPACE ||
2471 action.GetID() == ACTION_SHIFT ||
2472 action.GetID() == ACTION_SYMBOLS ||
2473 action.GetID() == ACTION_CURSOR_LEFT ||
2474 action.GetID() == ACTION_CURSOR_RIGHT)
2475 action = CAction(0); // don't bother with this action
2478 if (!action.GetID())
2480 // keyboard entry - pass the keys through directly
2481 if (key.GetFromService())
2482 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2485 // Check for paste keypress
2486 #ifdef TARGET_WINDOWS
2487 // In Windows paste is ctrl-V
2488 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2489 #elif defined(TARGET_LINUX)
2490 // In Linux paste is ctrl-V
2491 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2492 #elif defined(TARGET_DARWIN_OSX)
2493 // In OSX paste is cmd-V
2494 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2496 // Placeholder for other operating systems
2499 action = CAction(ACTION_PASTE);
2500 // If the unicode is non-zero the keypress is a non-printing character
2501 else if (key.GetUnicode())
2502 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2503 // The keypress is a non-printing character
2505 action = CAction(key.GetVKey() | KEY_VKEY);
2509 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2511 if (OnAction(action))
2513 // failed to handle the keyboard action, drop down through to standard action
2515 if (key.GetFromService())
2517 if (key.GetButtonCode() != KEY_INVALID)
2518 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2521 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2523 if (!key.IsAnalogButton())
2524 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2526 return ExecuteInputAction(action);
2529 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2530 // This needs to return true if it processed the appcommand or false if it didn't
2531 bool CApplication::OnAppCommand(const CAction &action)
2533 // Reset the screen saver
2536 // If we were currently in the screen saver wake up and don't process the appcommand
2537 if (WakeUpScreenSaverAndDPMS())
2540 // The action ID is the APPCOMMAND code. We need to retrieve the action
2541 // associated with this appcommand from the mapping table.
2542 uint32_t appcmd = action.GetID();
2543 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2544 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2545 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2547 // If we couldn't find an action return false to indicate we have not
2548 // handled this appcommand
2549 if (!appcmdaction.GetID())
2551 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2555 // Process the appcommand
2556 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2557 OnAction(appcmdaction);
2559 // Always return true regardless of whether the action succeeded or not.
2560 // This stops Windows handling the appcommand itself.
2564 bool CApplication::OnAction(const CAction &action)
2566 // special case for switching between GUI & fullscreen mode.
2567 if (action.GetID() == ACTION_SHOW_GUI)
2568 { // Switch to fullscreen mode if we can
2569 if (SwitchToFullScreen())
2571 m_navigationTimer.StartZero();
2576 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2578 g_graphicsContext.ToggleFullScreenRoot();
2582 if (action.IsMouse())
2583 g_Mouse.SetActive(true);
2586 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2588 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2590 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2592 CGUIDialogVideoBookmarks::OnAddBookmark();
2595 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2596 // playing or ACTION_PLAYER_PLAY if we are not playing.
2597 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2599 if (m_pPlayer->IsPlaying())
2600 return OnAction(CAction(ACTION_PAUSE));
2602 return OnAction(CAction(ACTION_PLAYER_PLAY));
2605 //if the action would start or stop inertial scrolling
2606 //by gesture - bypass the normal OnAction handler of current window
2607 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2610 // just pass the action to the current window and let it handle it
2611 if (g_windowManager.OnAction(action))
2613 m_navigationTimer.StartZero();
2618 // handle extra global presses
2620 // screenshot : take a screenshot :)
2621 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2623 CScreenShot::TakeScreenshot();
2626 // built in functions : execute the built-in
2627 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2629 CBuiltins::Execute(action.GetName());
2630 m_navigationTimer.StartZero();
2635 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2637 CButtonTranslator::GetInstance().Clear();
2638 CButtonTranslator::GetInstance().Load();
2641 // show info : Shows the current video or song information
2642 if (action.GetID() == ACTION_SHOW_INFO)
2644 g_infoManager.ToggleShowInfo();
2648 // codec info : Shows the current song, video or picture codec information
2649 if (action.GetID() == ACTION_SHOW_CODEC)
2651 g_infoManager.ToggleShowCodec();
2655 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2657 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2660 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2661 char rating = tag->GetRating();
2662 bool needsUpdate(false);
2663 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2665 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2668 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2670 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2676 if (db.Open()) // OpenForWrite() ?
2678 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2681 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2682 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2683 g_windowManager.SendMessage(msg);
2689 // Now check with the playlist player if action can be handled.
2690 // 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.
2691 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2693 if (g_playlistPlayer.OnAction(action))
2697 // Now check with the player if action can be handled.
2698 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2699 (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)) ||
2700 action.GetID() == ACTION_STOP)
2702 if (m_pPlayer->OnAction(action))
2704 // Player ignored action; popup the OSD
2705 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2706 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2707 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2710 // stop : stops playing current audio song
2711 if (action.GetID() == ACTION_STOP)
2717 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2718 // If so, we just jump to the start of the track.
2719 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2722 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2726 // forward action to g_PVRManager and break if it was able to handle it
2727 if (g_PVRManager.OnAction(action))
2730 // forward action to graphic context and see if it can handle it
2731 if (CStereoscopicsManager::Get().OnAction(action))
2734 if (m_pPlayer->IsPlaying())
2736 // forward channel switches to the player - he knows what to do
2737 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2739 m_pPlayer->OnAction(action);
2743 // pause : pauses current audio song
2744 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2748 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2750 if (!m_pPlayer->IsPaused())
2751 { // unpaused - set the playspeed back to normal
2752 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2754 g_audioManager.Enable(m_pPlayer->IsPaused());
2757 if (!m_pPlayer->IsPaused())
2759 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2760 // if we are playing at normal speed, then allow play to pause
2761 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2763 if (m_pPlayer->GetPlaySpeed() != 1)
2765 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2773 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2775 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2776 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2778 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2780 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2785 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2787 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2790 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2793 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2795 // calculate the speed based on the amount the button is held down
2796 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2797 // returns 0 -> MAX_FFWD_SPEED
2798 int iSpeed = 1 << iPower;
2799 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2801 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2803 CLog::Log(LOGDEBUG,"Resetting playspeed");
2807 // allow play to unpause
2810 if (action.GetID() == ACTION_PLAYER_PLAY)
2812 // unpause, and set the playspeed back to normal
2814 g_audioManager.Enable(m_pPlayer->IsPaused());
2816 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2821 // record current file
2822 if (action.GetID() == ACTION_RECORD)
2824 if (m_pPlayer->CanRecord())
2825 m_pPlayer->Record(!m_pPlayer->IsRecording());
2828 if (m_playerController->OnAction(action))
2833 if (action.GetID() == ACTION_SWITCH_PLAYER)
2835 if(m_pPlayer->IsPlaying())
2837 VECPLAYERCORES cores;
2838 CFileItem item(*m_itemCurrentFile.get());
2839 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2840 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2841 if(core != EPC_NONE)
2843 g_application.m_eForcedNextPlayer = core;
2844 item.m_lStartOffset = (int)(GetTime() * 75);
2845 PlayFile(item, true);
2850 VECPLAYERCORES cores;
2851 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2852 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2853 if(core != EPC_NONE)
2856 g_application.m_eForcedNextPlayer = core;
2857 PlayFile(item, false);
2862 if (g_peripherals.OnAction(action))
2865 if (action.GetID() == ACTION_MUTE)
2871 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2873 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2874 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2876 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2878 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2879 g_windowManager.SendMessage(msg);
2884 // Check for global volume control
2885 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2887 if (!m_pPlayer->IsPassthrough())
2891 float volume = m_volumeLevel;
2892 // Android has steps based on the max available volume level
2893 #if defined(TARGET_ANDROID)
2894 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2896 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2898 if (action.GetRepeat())
2899 step *= action.GetRepeat() * 50; // 50 fps
2901 if (action.GetID() == ACTION_VOLUME_UP)
2902 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2904 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2905 SetVolume(volume, false);
2907 // show visual feedback of volume change...
2908 ShowVolumeBar(&action);
2911 // Check for global seek control
2912 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2914 if (!m_pPlayer->CanSeek()) return false;
2915 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2918 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2920 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2921 CGUIControlProfiler::Instance().Start();
2924 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2926 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2927 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2928 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2929 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2930 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2936 void CApplication::FrameMove(bool processEvents, bool processGUI)
2942 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2943 float frameTime = m_frameTime.GetElapsedSeconds();
2944 m_frameTime.StartZero();
2945 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2946 if( frameTime > 0.5 ) frameTime = 0.5;
2948 if (processGUI && m_renderGUI)
2950 g_graphicsContext.Lock();
2951 // check if there are notifications to display
2952 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2953 if (toast && toast->DoWork())
2955 if (!toast->IsDialogRunning())
2960 g_graphicsContext.Unlock();
2962 CWinEvents::MessagePump();
2964 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2965 // Read the input from a remote
2966 g_RemoteControl.Update();
2969 // process input actions
2970 ProcessRemote(frameTime);
2971 ProcessGamepad(frameTime);
2972 ProcessEventServer(frameTime);
2973 ProcessPeripherals(frameTime);
2974 if (processGUI && m_renderGUI)
2976 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2977 m_seekHandler->Process();
2980 if (processGUI && m_renderGUI)
2983 g_windowManager.Process(CTimeUtils::GetFrameTime());
2984 g_windowManager.FrameMove();
2988 bool CApplication::ProcessGamepad(float frameTime)
2990 #ifdef HAS_SDL_JOYSTICK
2994 int iWin = GetActiveWindowID();
2996 g_Joystick.Update();
2997 if (g_Joystick.GetButton(bid))
3000 m_idleTimer.StartZero();
3003 if (WakeUpScreenSaverAndDPMS())
3005 g_Joystick.Reset(true);
3010 CStdString actionName;
3012 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3014 CAction action(actionID, 1.0f, 0.0f, actionName);
3016 g_Mouse.SetActive(false);
3017 return ExecuteInputAction(action);
3024 if (g_Joystick.GetAxis(bid))
3026 if (g_Joystick.GetAmount() < 0)
3032 CStdString actionName;
3034 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3037 if (WakeUpScreenSaverAndDPMS())
3042 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3044 g_Mouse.SetActive(false);
3045 return ExecuteInputAction(action);
3049 g_Joystick.ResetAxis(abs(bid));
3053 if (g_Joystick.GetHat(bid, position))
3056 m_idleTimer.StartZero();
3059 if (WakeUpScreenSaverAndDPMS())
3066 CStdString actionName;
3069 bid = position<<16|bid;
3071 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3073 CAction action(actionID, 1.0f, 0.0f, actionName);
3075 g_Mouse.SetActive(false);
3076 return ExecuteInputAction(action);
3083 bool CApplication::ProcessRemote(float frameTime)
3085 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3086 if (g_RemoteControl.GetButton())
3088 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3089 g_RemoteControl.Reset();
3096 bool CApplication::ProcessPeripherals(float frameTime)
3099 if (g_peripherals.GetNextKeypress(frameTime, key))
3104 bool CApplication::ProcessMouse()
3108 if (!g_Mouse.IsActive() || !m_AppFocused)
3111 // Get the mouse command ID
3112 uint32_t mousecommand = g_Mouse.GetAction();
3113 if (mousecommand == ACTION_NOOP)
3116 // Reset the screensaver and idle timers
3117 m_idleTimer.StartZero();
3119 if (WakeUpScreenSaverAndDPMS())
3122 // Retrieve the corresponding action
3123 int iWin = GetActiveWindowID();
3124 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3125 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3127 // Deactivate mouse if non-mouse action
3128 if (!mouseaction.IsMouse())
3129 g_Mouse.SetActive(false);
3131 // Consume ACTION_NOOP.
3132 // Some views or dialogs gets closed after any ACTION and
3133 // a sensitive mouse might cause problems.
3134 if (mouseaction.GetID() == ACTION_NOOP)
3137 // If we couldn't find an action return false to indicate we have not
3138 // handled this mouse action
3139 if (!mouseaction.GetID())
3141 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3145 // Log mouse actions except for move and noop
3146 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3147 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3149 // The action might not be a mouse action. For example wheel moves might
3150 // be mapped to volume up/down in mouse.xml. In this case we do not want
3151 // the mouse position saved in the action.
3152 if (!mouseaction.IsMouse())
3153 return OnAction(mouseaction);
3155 // This is a mouse action so we need to record the mouse position
3156 return OnAction(CAction(mouseaction.GetID(),
3157 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3158 (float)g_Mouse.GetX(),
3159 (float)g_Mouse.GetY(),
3160 (float)g_Mouse.GetDX(),
3161 (float)g_Mouse.GetDY(),
3162 mouseaction.GetName()));
3165 bool CApplication::ProcessEventServer(float frameTime)
3167 #ifdef HAS_EVENT_SERVER
3168 CEventServer* es = CEventServer::GetInstance();
3169 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3172 // process any queued up actions
3173 if (es->ExecuteNextAction())
3175 // reset idle timers
3176 m_idleTimer.StartZero();
3178 WakeUpScreenSaverAndDPMS();
3181 // now handle any buttons or axis
3182 std::string joystickName;
3183 bool isAxis = false;
3184 float fAmount = 0.0;
3186 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3187 // when the action exits XBMC
3188 es = CEventServer::GetInstance();
3189 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3191 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3195 if (joystickName.length() > 0)
3199 if (fabs(fAmount) >= 0.08)
3200 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3202 m_lastAxisMap[joystickName].erase(wKeyID);
3205 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3210 if (wKeyID & ES_FLAG_UNICODE)
3212 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3216 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3217 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3219 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3221 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3222 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3223 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3224 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3225 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3226 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3227 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3228 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3229 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3230 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3231 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3232 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3233 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3234 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3235 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3238 key.SetFromService(true);
3243 if (m_lastAxisMap.size() > 0)
3245 // Process all the stored axis.
3246 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3248 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3249 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3255 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3257 XBMC_Event newEvent;
3258 newEvent.type = XBMC_MOUSEMOTION;
3259 newEvent.motion.xrel = 0;
3260 newEvent.motion.yrel = 0;
3261 newEvent.motion.state = 0;
3262 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3263 newEvent.motion.x = (uint16_t)pos.x;
3264 newEvent.motion.y = (uint16_t)pos.y;
3265 OnEvent(newEvent); // had to call this to update g_Mouse position
3266 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3273 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3275 #if defined(HAS_EVENT_SERVER)
3276 m_idleTimer.StartZero();
3278 // Make sure to reset screen saver, mouse.
3280 if (WakeUpScreenSaverAndDPMS())
3283 #ifdef HAS_SDL_JOYSTICK
3286 g_Mouse.SetActive(false);
3288 int iWin = GetActiveWindowID();
3290 CStdString actionName;
3291 bool fullRange = false;
3293 // Translate using regular joystick translator.
3294 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3295 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3297 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3303 bool CApplication::ExecuteInputAction(const CAction &action)
3305 bool bResult = false;
3307 // play sound before the action unless the button is held,
3308 // where we execute after the action as held actions aren't fired every time.
3309 if(action.GetHoldTime())
3311 bResult = OnAction(action);
3313 g_audioManager.PlayActionSound(action);
3317 g_audioManager.PlayActionSound(action);
3318 bResult = OnAction(action);
3323 int CApplication::GetActiveWindowID(void)
3325 // Get the currently active window
3326 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3328 // If there is a dialog active get the dialog id instead
3329 if (g_windowManager.HasModalDialog())
3330 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3332 // If the window is FullScreenVideo check for special cases
3333 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3335 // check if we're in a DVD menu
3336 if(g_application.m_pPlayer->IsInMenu())
3337 iWin = WINDOW_VIDEO_MENU;
3338 // check for LiveTV and switch to it's virtual window
3339 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3340 iWin = WINDOW_FULLSCREEN_LIVETV;
3343 // Return the window id
3347 bool CApplication::Cleanup()
3351 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3352 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3353 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3354 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3355 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3356 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3357 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3358 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3359 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3360 g_windowManager.Delete(WINDOW_FILES);
3361 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3362 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3363 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3364 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3365 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3366 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3367 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3368 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3369 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3370 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3371 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3372 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3373 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3374 g_windowManager.Delete(WINDOW_DIALOG_OK);
3375 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3376 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3377 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3378 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3379 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3380 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3381 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3382 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3383 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3384 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3385 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3386 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3387 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3388 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3389 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3390 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3391 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3392 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3393 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3394 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3395 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3396 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3397 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3399 /* Delete PVR related windows and dialogs */
3400 g_windowManager.Delete(WINDOW_PVR);
3401 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3402 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3403 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3404 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3405 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3406 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3407 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3408 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3409 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3410 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3411 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3412 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3413 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3415 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3416 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3417 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3418 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3419 g_windowManager.Delete(WINDOW_VISUALISATION);
3420 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3421 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3422 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3423 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3424 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3425 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3426 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3427 g_windowManager.Delete(WINDOW_SCREENSAVER);
3428 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3429 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3430 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3431 g_windowManager.Delete(WINDOW_SLIDESHOW);
3432 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3433 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3435 g_windowManager.Delete(WINDOW_HOME);
3436 g_windowManager.Delete(WINDOW_PROGRAMS);
3437 g_windowManager.Delete(WINDOW_PICTURES);
3438 g_windowManager.Delete(WINDOW_WEATHER);
3440 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3441 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3442 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3443 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3444 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3445 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3446 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3447 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3448 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3449 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3451 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3452 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3454 CAddonMgr::Get().DeInit();
3456 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3457 CLog::Log(LOGNOTICE, "closing down remote control service");
3458 g_RemoteControl.Disconnect();
3461 CLog::Log(LOGNOTICE, "unload sections");
3463 #ifdef HAS_PERFORMANCE_SAMPLE
3464 CLog::Log(LOGNOTICE, "performance statistics");
3465 m_perfStats.DumpStats();
3468 // Shutdown as much as possible of the
3469 // application, to reduce the leaks dumped
3470 // to the vc output window before calling
3471 // _CrtDumpMemoryLeaks(). Most of the leaks
3472 // shown are no real leaks, as parts of the app
3473 // are still allocated.
3475 g_localizeStrings.Clear();
3476 g_LangCodeExpander.Clear();
3477 g_charsetConverter.clear();
3478 g_directoryCache.Clear();
3479 CButtonTranslator::GetInstance().Clear();
3480 #ifdef HAS_EVENT_SERVER
3481 CEventServer::RemoveInstance();
3483 DllLoaderContainer::Clear();
3484 g_playlistPlayer.Clear();
3485 CSettings::Get().Uninitialize();
3486 g_advancedSettings.Clear();
3489 CXHandle::DumpObjectTracker();
3491 #ifdef HAS_DVD_DRIVE
3492 CLibcdio::ReleaseInstance();
3495 #if defined(TARGET_ANDROID)
3496 // enable for all platforms once it's safe
3497 g_sectionLoader.UnloadAll();
3499 #ifdef _CRTDBG_MAP_ALLOC
3500 _CrtDumpMemoryLeaks();
3501 while(1); // execution ends
3511 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3516 void CApplication::Stop(int exitCode)
3520 CVariant vExitCode(exitCode);
3521 CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
3523 SaveFileState(true);
3525 g_alarmClock.StopThread();
3527 if( m_bSystemScreenSaverEnable )
3528 g_Windowing.EnableSystemScreenSaver(true);
3530 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3531 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3533 // Update the settings information (volume, uptime etc. need saving)
3534 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3536 CLog::Log(LOGNOTICE, "Saving settings");
3537 CSettings::Get().Save();
3540 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3543 m_AppFocused = false;
3544 m_ExitCode = exitCode;
3545 CLog::Log(LOGNOTICE, "stop all");
3547 // cancel any jobs from the jobmanager
3548 CJobManager::GetInstance().CancelJobs();
3550 // stop scanning before we kill the network and so on
3551 if (m_musicInfoScanner->IsScanning())
3552 m_musicInfoScanner->Stop();
3554 if (m_videoInfoScanner->IsScanning())
3555 m_videoInfoScanner->Stop();
3557 CApplicationMessenger::Get().Cleanup();
3559 CLog::Log(LOGNOTICE, "stop player");
3560 m_pPlayer->ClosePlayer();
3562 CAnnouncementManager::Get().Deinitialize();
3568 #if HAS_FILESYTEM_DAAP
3569 CLog::Log(LOGNOTICE, "stop daap clients");
3570 g_DaapClient.Release();
3572 #ifdef HAS_FILESYSTEM_SAP
3573 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3574 g_sapsessions.StopThread();
3577 if(CZeroconfBrowser::IsInstantiated())
3579 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3580 CZeroconfBrowser::GetInstance()->Stop();
3581 CZeroconfBrowser::ReleaseInstance();
3585 CLog::Log(LOGNOTICE, "clean cached files!");
3586 #ifdef HAS_FILESYSTEM_RAR
3587 g_RarManager.ClearCache(true);
3590 #ifdef HAS_FILESYSTEM_SFTP
3591 CSFTPSessionManager::DisconnectAllSessions();
3594 CLog::Log(LOGNOTICE, "unload skin");
3597 #if defined(TARGET_DARWIN_OSX)
3598 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3599 XBMCHelper::GetInstance().Stop();
3602 #if defined(HAVE_LIBCRYSTALHD)
3603 CCrystalHD::RemoveInstance();
3606 g_mediaManager.Stop();
3608 // Stop services before unloading Python
3609 CAddonMgr::Get().StopServices(false);
3611 // stop all remaining scripts; must be done after skin has been unloaded,
3612 // not before some windows still need it when deinitializing during skin
3614 CScriptInvocationManager::Get().Uninitialize();
3616 g_Windowing.DestroyRenderSystem();
3617 g_Windowing.DestroyWindow();
3618 g_Windowing.DestroyWindowSystem();
3620 // shutdown the AudioEngine
3621 CAEFactory::Shutdown();
3622 CAEFactory::UnLoadEngine();
3624 // unregister ffmpeg lock manager call back
3625 av_lockmgr_register(NULL);
3627 CLog::Log(LOGNOTICE, "stopped");
3631 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3634 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3635 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3642 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3644 //If item is a plugin, expand out now and run ourselves again
3645 if (item.IsPlugin())
3647 CFileItem item_new(item);
3648 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3649 return PlayMedia(item_new, iPlaylist);
3652 if (item.IsSmartPlayList())
3654 CFileItemList items;
3655 CUtil::GetRecursiveListing(item.GetPath(), items, "", DIR_FLAG_NO_FILE_DIRS);
3658 CSmartPlaylist smartpl;
3659 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3660 smartpl.OpenAndReadName(item.GetURL());
3662 playlist.Add(items);
3663 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3666 else if (item.IsPlayList() || item.IsInternetStream())
3668 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3670 //is or could be a playlist
3671 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3672 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3677 if (dlgCache->IsCanceled())
3684 if (iPlaylist != PLAYLIST_NONE)
3687 if (item.HasProperty("playlist_starting_track"))
3688 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3689 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3693 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());
3694 if(pPlayList->size())
3695 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3700 //nothing special just play
3701 return PlayFile(item, false) == PLAYBACK_OK;
3705 // For playing a multi-file video. Particularly inefficient
3706 // on startup, as we are required to calculate the length
3707 // of each video, so we open + close each one in turn.
3708 // A faster calculation of video time would improve this
3710 // return value: same with PlayFile()
3711 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3713 if (!item.IsStack())
3714 return PLAYBACK_FAIL;
3718 // case 1: stacked ISOs
3719 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3721 CStackDirectory dir;
3722 CFileItemList movieList;
3723 dir.GetDirectory(item.GetURL(), movieList);
3725 // first assume values passed to the stack
3726 int selectedFile = item.m_lStartPartNumber;
3727 int startoffset = item.m_lStartOffset;
3729 // check if we instructed the stack to resume from default
3730 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3735 CStdString path = item.GetPath();
3736 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3737 path = item.GetProperty("original_listitem_url").asString();
3738 if( dbs.GetResumeBookMark(path, bookmark) )
3740 startoffset = (int)(bookmark.timeInSeconds*75);
3741 selectedFile = bookmark.partNumber;
3746 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3749 // make sure that the selected part is within the boundaries
3750 if (selectedFile <= 0)
3752 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3755 else if (selectedFile > movieList.Size())
3757 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3758 selectedFile = movieList.Size();
3761 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3762 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3763 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3764 *m_stackFileItemToUpdate = item;
3765 return PlayFile(*(movieList[selectedFile - 1]));
3767 // case 2: all other stacks
3770 // see if we have the info in the database
3771 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3772 // then these times will be wrong.
3773 // Also, this is really just a hack for the slow load up times we have
3774 // A much better solution is a fast reader of FPS and fileLength
3775 // that we can use on a file to get it's time.
3777 bool haveTimes(false);
3781 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3782 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3787 // calculate the total time of the stack
3788 CStackDirectory dir;
3789 dir.GetDirectory(item.GetURL(), *m_currentStack);
3791 for (int i = 0; i < m_currentStack->Size(); i++)
3794 (*m_currentStack)[i]->m_lEndOffset = times[i];
3798 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3800 m_currentStack->Clear();
3801 return PLAYBACK_FAIL;
3803 totalTime += duration / 1000;
3804 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3805 times.push_back(totalTime);
3809 double seconds = item.m_lStartOffset / 75.0;
3811 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3812 { // have our times now, so update the dB
3816 dbs.SetStackTimes(item.GetPath(), times);
3818 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3820 // can only resume seek here, not dvdstate
3822 CStdString path = item.GetPath();
3823 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3824 path = item.GetProperty("original_listitem_url").asString();
3825 if( dbs.GetResumeBookMark(path, bookmark) )
3826 seconds = bookmark.timeInSeconds;
3834 *m_itemCurrentFile = item;
3835 m_currentStackPosition = 0;
3836 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3840 // work out where to seek to
3841 for (int i = 0; i < m_currentStack->Size(); i++)
3843 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3845 CFileItem item(*(*m_currentStack)[i]);
3846 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3847 item.m_lStartOffset = (long)(seconds - start) * 75;
3848 m_currentStackPosition = i;
3849 return PlayFile(item, true);
3854 return PlayFile(*(*m_currentStack)[0], true);
3856 return PLAYBACK_FAIL;
3859 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3861 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3862 if (item.GetMimeType().empty())
3863 const_cast<CFileItem&>(item).FillInMimeType();
3867 SaveCurrentFileSettings();
3869 OutputDebugString("new file set audiostream:0\n");
3870 // Switch to default options
3871 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3872 // see if we have saved options in the database
3874 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3875 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3877 *m_itemCurrentFile = item;
3878 m_nextPlaylistItem = -1;
3879 m_currentStackPosition = 0;
3880 m_currentStack->Clear();
3883 CUtil::ClearSubtitles();
3886 if (item.IsDiscStub())
3888 #ifdef HAS_DVD_DRIVE
3889 // Display the Play Eject dialog if there is any optical disc drive
3890 if (g_mediaManager.HasOpticalDrive())
3892 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3893 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3894 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3895 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3899 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3904 if (item.IsPlayList())
3905 return PLAYBACK_FAIL;
3907 if (item.IsPlugin())
3908 { // we modify the item so that it becomes a real URL
3909 CFileItem item_new(item);
3910 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3911 return PlayFile(item_new, false);
3912 return PLAYBACK_FAIL;
3916 if (URIUtils::IsUPnP(item.GetPath()))
3918 CFileItem item_new(item);
3919 if (XFILE::CUPnPDirectory::GetResource(item.GetURL(), item_new))
3920 return PlayFile(item_new, false);
3921 return PLAYBACK_FAIL;
3925 // if we have a stacked set of files, we need to setup our stack routines for
3926 // "seamless" seeking and total time of the movie etc.
3927 // will recall with restart set to true
3929 return PlayStack(item, bRestart);
3931 //Is TuxBox, this should probably be moved to CTuxBoxFile
3934 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3936 if(g_tuxboxService.IsRunning())
3937 g_tuxboxService.Stop();
3939 PlayBackRet ret = PLAYBACK_FAIL;
3941 if(g_tuxbox.CreateNewItem(item, item_new))
3944 // Make sure it doesn't have a player
3945 // so we actually select one normally
3946 m_pPlayer->ResetPlayer();
3948 // keep the tuxbox:// url as playing url
3949 // and give the new url to the player
3950 ret = PlayFile(item_new, true);
3951 if(ret == PLAYBACK_OK)
3953 if(!g_tuxboxService.IsRunning())
3954 g_tuxboxService.Start();
3960 CPlayerOptions options;
3962 if( item.HasProperty("StartPercent") )
3964 double fallback = 0.0f;
3965 if(item.GetProperty("StartPercent").isString())
3966 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3967 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3970 PLAYERCOREID eNewCore = EPC_NONE;
3973 // have to be set here due to playstack using this for starting the file
3974 options.starttime = item.m_lStartOffset / 75.0;
3975 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3976 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3978 if( m_eForcedNextPlayer != EPC_NONE )
3979 eNewCore = m_eForcedNextPlayer;
3980 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3981 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3983 eNewCore = m_pPlayer->GetCurrentPlayer();
3987 options.starttime = item.m_lStartOffset / 75.0;
3991 // open the d/b and retrieve the bookmarks for the current movie
3994 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3996 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3998 options.starttime = 0.0f;
4000 CStdString path = item.GetPath();
4001 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
4002 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
4003 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
4004 path = item.GetProperty("original_listitem_url").asString();
4005 if(dbs.GetResumeBookMark(path, bookmark))
4007 options.starttime = bookmark.timeInSeconds;
4008 options.state = bookmark.playerState;
4011 override with information from the actual item if available. We do this as the VFS (eg plugins)
4012 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4013 should the playerState be required, it is fetched from the database.
4014 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4016 if (item.IsResumePointSet())
4017 options.starttime = item.GetCurrentResumeTime();
4019 else if (item.HasVideoInfoTag())
4021 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4023 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4026 dbs.GetBookMarkForEpisode(*tag, bookmark);
4027 options.starttime = bookmark.timeInSeconds;
4028 options.state = bookmark.playerState;
4035 if (m_eForcedNextPlayer != EPC_NONE)
4036 eNewCore = m_eForcedNextPlayer;
4038 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4041 // this really aught to be inside !bRestart, but since PlayStack
4042 // uses that to init playback, we have to keep it outside
4043 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4044 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4045 { // playing from a playlist by the looks
4046 // don't switch to fullscreen if we are not playing the first item...
4047 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4049 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4051 // TODO - this will fail if user seeks back to first file in stack
4052 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4053 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4055 options.fullscreen = false;
4056 // reset this so we don't think we are resuming on seek
4057 m_itemCurrentFile->m_lStartOffset = 0;
4060 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4062 // reset VideoStartWindowed as it's a temp setting
4063 CMediaSettings::Get().SetVideoStartWindowed(false);
4066 //We have to stop parsing a cdg before mplayer is deallocated
4067 // WHY do we have to do this????
4069 m_pKaraokeMgr->Stop();
4073 CSingleLock lock(m_playStateMutex);
4074 // tell system we are starting a file
4075 m_bPlaybackStarting = true;
4077 // for playing a new item, previous playing item's callback may already
4078 // pushed some delay message into the threadmessage list, they are not
4079 // expected be processed after or during the new item playback starting.
4080 // so we clean up previous playing item's playback callback delay messages here.
4081 int previousMsgsIgnoredByNewPlaying[] = {
4082 GUI_MSG_PLAYBACK_STARTED,
4083 GUI_MSG_PLAYBACK_ENDED,
4084 GUI_MSG_PLAYBACK_STOPPED,
4085 GUI_MSG_PLAYLIST_CHANGED,
4086 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4087 GUI_MSG_PLAYLISTPLAYER_STARTED,
4088 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4089 GUI_MSG_QUEUE_NEXT_ITEM,
4092 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4094 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4097 // We should restart the player, unless the previous and next tracks are using
4098 // one of the players that allows gapless playback (paplayer, dvdplayer)
4099 m_pPlayer->ClosePlayerGapless(eNewCore);
4101 // now reset play state to starting, since we already stopped the previous playing item if there is.
4102 // and from now there should be no playback callback from previous playing item be called.
4103 m_ePlayState = PLAY_STATE_STARTING;
4105 m_pPlayer->CreatePlayer(eNewCore, *this);
4107 PlayBackRet iResult;
4108 if (m_pPlayer->HasPlayer())
4110 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4111 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4112 * increase performance on low powered systems (Atom/ARM).
4116 CJobManager::GetInstance().PauseJobs();
4119 // don't hold graphicscontext here since player
4120 // may wait on another thread, that requires gfx
4121 CSingleExit ex(g_graphicsContext);
4123 iResult = m_pPlayer->OpenFile(item, options);
4127 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4128 iResult = PLAYBACK_FAIL;
4131 if(iResult == PLAYBACK_OK)
4133 if (m_pPlayer->GetPlaySpeed() != 1)
4135 int iSpeed = m_pPlayer->GetPlaySpeed();
4136 m_pPlayer->m_iPlaySpeed = 1;
4137 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4140 // if player has volume control, set it.
4141 if (m_pPlayer->ControlsVolume())
4143 m_pPlayer->SetVolume(m_volumeLevel);
4144 m_pPlayer->SetMute(m_muted);
4147 if( m_pPlayer->IsPlayingAudio() )
4149 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4150 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4153 #ifdef HAS_VIDEO_PLAYBACK
4154 else if( m_pPlayer->IsPlayingVideo() )
4156 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4157 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4159 // if player didn't manange to switch to fullscreen by itself do it here
4160 if( options.fullscreen && g_renderManager.IsStarted()
4161 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4162 SwitchToFullScreen();
4167 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4168 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4169 g_windowManager.PreviousWindow();
4173 #if !defined(TARGET_POSIX)
4174 g_audioManager.Enable(false);
4177 if (item.HasPVRChannelInfoTag())
4178 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4181 CSingleLock lock(m_playStateMutex);
4182 m_bPlaybackStarting = false;
4184 if (iResult == PLAYBACK_OK)
4186 // play state: none, starting; playing; stopped; ended.
4187 // last 3 states are set by playback callback, they are all ignored during starting,
4188 // but we recorded the state, here we can make up the callback for the state.
4189 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4190 switch (m_ePlayState)
4192 case PLAY_STATE_PLAYING:
4193 OnPlayBackStarted();
4195 // FIXME: it seems no meaning to callback started here if there was an started callback
4196 // before this stopped/ended callback we recorded. if we callback started here
4197 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4198 // which will send OnStop announce at once, so currently, just call stopped/ended.
4199 case PLAY_STATE_ENDED:
4202 case PLAY_STATE_STOPPED:
4203 OnPlayBackStopped();
4205 case PLAY_STATE_STARTING:
4206 // neither started nor stopped/ended callback be called, that means the item still
4207 // not started, we need not make up any callback, just leave this and
4208 // let the player callback do its work.
4214 else if (iResult == PLAYBACK_FAIL)
4216 // we send this if it isn't playlistplayer that is doing this
4217 int next = g_playlistPlayer.GetNextSong();
4218 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4221 OnPlayBackStopped();
4222 m_ePlayState = PLAY_STATE_NONE;
4228 void CApplication::OnPlayBackEnded()
4230 CSingleLock lock(m_playStateMutex);
4231 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4232 m_ePlayState = PLAY_STATE_ENDED;
4233 if(m_bPlaybackStarting)
4236 // informs python script currently running playback has ended
4237 // (does nothing if python is not loaded)
4239 g_pythonParser.OnPlayBackEnded();
4242 CVariant data(CVariant::VariantTypeObject);
4244 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4246 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4247 g_windowManager.SendThreadMessage(msg);
4250 void CApplication::OnPlayBackStarted()
4252 CSingleLock lock(m_playStateMutex);
4253 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4254 m_ePlayState = PLAY_STATE_PLAYING;
4255 if(m_bPlaybackStarting)
4259 // informs python script currently running playback has started
4260 // (does nothing if python is not loaded)
4261 g_pythonParser.OnPlayBackStarted();
4264 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4265 g_windowManager.SendThreadMessage(msg);
4268 void CApplication::OnQueueNextItem()
4270 CSingleLock lock(m_playStateMutex);
4271 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4272 if(m_bPlaybackStarting)
4274 // informs python script currently running that we are requesting the next track
4275 // (does nothing if python is not loaded)
4277 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4280 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4281 g_windowManager.SendThreadMessage(msg);
4284 void CApplication::OnPlayBackStopped()
4286 CSingleLock lock(m_playStateMutex);
4287 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4288 m_ePlayState = PLAY_STATE_STOPPED;
4289 if(m_bPlaybackStarting)
4292 // informs python script currently running playback has ended
4293 // (does nothing if python is not loaded)
4295 g_pythonParser.OnPlayBackStopped();
4298 CVariant data(CVariant::VariantTypeObject);
4299 data["end"] = false;
4300 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4302 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4303 g_windowManager.SendThreadMessage(msg);
4306 void CApplication::OnPlayBackPaused()
4309 g_pythonParser.OnPlayBackPaused();
4313 param["player"]["speed"] = 0;
4314 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4315 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4318 void CApplication::OnPlayBackResumed()
4321 g_pythonParser.OnPlayBackResumed();
4325 param["player"]["speed"] = 1;
4326 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4327 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4330 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4333 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4337 param["player"]["speed"] = iSpeed;
4338 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4339 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4342 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4345 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4349 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4350 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4351 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4352 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4353 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4354 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4357 void CApplication::OnPlayBackSeekChapter(int iChapter)
4360 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4364 bool CApplication::IsPlayingFullScreenVideo() const
4366 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4369 bool CApplication::IsFullScreen()
4371 return IsPlayingFullScreenVideo() ||
4372 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4373 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4376 void CApplication::SaveFileState(bool bForeground /* = false */)
4378 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4383 CSaveFileStateJob job(*m_progressTrackingItem,
4384 *m_stackFileItemToUpdate,
4385 m_progressTrackingVideoResumeBookmark,
4386 m_progressTrackingPlayCountUpdate);
4388 // Run job in the foreground to make sure it finishes
4393 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4394 *m_stackFileItemToUpdate,
4395 m_progressTrackingVideoResumeBookmark,
4396 m_progressTrackingPlayCountUpdate);
4397 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4401 void CApplication::UpdateFileState()
4403 // Did the file change?
4404 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4408 // Reset tracking item
4409 m_progressTrackingItem->Reset();
4413 if (m_pPlayer->IsPlaying())
4415 if (m_progressTrackingItem->GetPath() == "")
4418 *m_progressTrackingItem = CurrentFileItem();
4419 m_progressTrackingPlayCountUpdate = false;
4422 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4423 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4424 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4425 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4427 m_progressTrackingPlayCountUpdate = true;
4430 // Check whether we're *really* playing video else we may race when getting eg. stream details
4431 if (m_pPlayer->IsPlayingVideo())
4433 /* Always update streamdetails, except for DVDs where we only update
4434 streamdetails if title length > 15m (Should yield more correct info) */
4435 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4437 CStreamDetails details;
4438 // Update with stream details from player, if any
4439 if (m_pPlayer->GetStreamDetails(details))
4440 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4442 if (m_progressTrackingItem->IsStack())
4443 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4446 // Update bookmark for save
4447 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4448 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4449 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4451 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4452 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4454 // Delete the bookmark
4455 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4458 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4460 // Update the bookmark
4461 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4462 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4467 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4474 void CApplication::StopPlaying()
4476 int iWin = g_windowManager.GetActiveWindow();
4477 if ( m_pPlayer->IsPlaying() )
4481 m_pKaraokeMgr->Stop();
4484 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4485 g_PVRManager.SaveCurrentChannelSettings();
4487 m_pPlayer->CloseFile();
4489 // turn off visualisation window when stopping
4490 if ((iWin == WINDOW_VISUALISATION
4491 || iWin == WINDOW_FULLSCREEN_VIDEO)
4493 g_windowManager.PreviousWindow();
4495 g_partyModeManager.Disable();
4499 void CApplication::ResetSystemIdleTimer()
4501 // reset system idle timer
4502 m_idleTimer.StartZero();
4505 void CApplication::ResetScreenSaver()
4508 m_shutdownTimer.StartZero();
4510 // screen saver timer is reset only if we're not already in screensaver or
4512 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4513 ResetScreenSaverTimer();
4516 void CApplication::ResetScreenSaverTimer()
4518 m_screenSaverTimer.StartZero();
4521 void CApplication::StopScreenSaverTimer()
4523 m_screenSaverTimer.Stop();
4526 bool CApplication::ToggleDPMS(bool manual)
4528 if (manual || (m_dpmsIsManual == manual))
4532 m_dpmsIsActive = false;
4533 m_dpmsIsManual = false;
4534 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSDeactivated");
4535 return m_dpms->DisablePowerSaving();
4539 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4541 m_dpmsIsActive = true;
4542 m_dpmsIsManual = manual;
4543 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSActivated");
4551 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4555 // First reset DPMS, if active
4560 // TODO: if screensaver lock is specified but screensaver is not active
4561 // (DPMS came first), activate screensaver now.
4563 ResetScreenSaverTimer();
4564 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4567 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4571 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4572 CVariant data(bPowerOffKeyPressed);
4573 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4579 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4581 if (m_iScreenSaveLock == 2)
4584 // if Screen saver is active
4585 if (m_bScreenSave && m_screenSaver)
4587 if (m_iScreenSaveLock == 0)
4588 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4589 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4590 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4591 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4593 m_iScreenSaveLock = 2;
4594 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4596 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4598 pWindow->OnMessage(msg);
4600 if (m_iScreenSaveLock == -1)
4602 m_iScreenSaveLock = 0;
4606 // disable screensaver
4607 m_bScreenSave = false;
4608 m_iScreenSaveLock = 0;
4609 ResetScreenSaverTimer();
4611 if (m_screenSaver->ID() == "visualization")
4613 // we can just continue as usual from vis mode
4616 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4618 else if (!m_screenSaver->ID().empty())
4619 { // we're in screensaver window
4620 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4621 g_windowManager.PreviousWindow(); // show the previous window
4622 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4623 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4631 void CApplication::CheckScreenSaverAndDPMS()
4633 if (!m_dpmsIsActive)
4634 g_Windowing.ResetOSScreensaver();
4636 bool maybeScreensaver =
4637 !m_dpmsIsActive && !m_bScreenSave
4638 && !CSettings::Get().GetString("screensaver.mode").empty();
4640 !m_dpmsIsActive && m_dpms->IsSupported()
4641 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4643 // Has the screen saver window become active?
4644 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4646 m_bScreenSave = true;
4647 maybeScreensaver = false;
4650 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4652 WakeUpScreenSaverAndDPMS();
4656 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4658 // See if we need to reset timer.
4659 // * Are we playing a video and it is not paused?
4660 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4661 // * Are we playing some music in fullscreen vis?
4662 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4663 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4665 ResetScreenSaverTimer();
4669 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4671 // DPMS has priority (it makes the screensaver not needed)
4673 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4676 WakeUpScreenSaver();
4678 else if (maybeScreensaver
4679 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4681 ActivateScreenSaver();
4685 // activate the screensaver.
4686 // if forceType is true, we ignore the various conditions that can alter
4687 // the type of screensaver displayed
4688 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4690 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4691 { // just activate the visualisation if user toggled the usemusicvisinstead option
4692 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4696 m_bScreenSave = true;
4698 // Get Screensaver Mode
4699 m_screenSaver.reset();
4700 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4701 m_screenSaver.reset(new CScreenSaver(""));
4703 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverActivated");
4705 // disable screensaver lock from the login screen
4706 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4709 // set to Dim in the case of a dialog on screen or playing video
4710 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4712 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4713 m_screenSaver.reset(new CScreenSaver(""));
4716 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4718 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4720 else if (!m_screenSaver->ID().empty())
4721 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4724 void CApplication::CheckShutdown()
4726 // first check if we should reset the timer
4727 if (m_bInhibitIdleShutdown
4728 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4729 || m_musicInfoScanner->IsScanning()
4730 || m_videoInfoScanner->IsScanning()
4731 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4732 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4734 m_shutdownTimer.StartZero();
4738 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4740 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4741 m_shutdownTimer.Stop();
4744 CApplicationMessenger::Get().Shutdown();
4748 void CApplication::InhibitIdleShutdown(bool inhibit)
4750 m_bInhibitIdleShutdown = inhibit;
4753 bool CApplication::IsIdleShutdownInhibited() const
4755 return m_bInhibitIdleShutdown;
4758 bool CApplication::OnMessage(CGUIMessage& message)
4760 switch ( message.GetMessage() )
4762 case GUI_MSG_NOTIFY_ALL:
4764 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4766 // Update general playlist: Remove DVD playlist items
4767 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4770 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4771 g_windowManager.SendMessage( msg );
4773 // stop the file if it's on dvd (will set the resume point etc)
4774 if (m_itemCurrentFile->IsOnDVD())
4780 case GUI_MSG_PLAYBACK_STARTED:
4782 #ifdef TARGET_DARWIN
4783 DarwinSetScheduling(message.GetMessage());
4785 // reset the seek handler
4786 m_seekHandler->Reset();
4787 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4789 // Update our infoManager with the new details etc.
4790 if (m_nextPlaylistItem >= 0)
4792 // playing an item which is not in the list - player might be stopped already
4794 if (playList.size() <= m_nextPlaylistItem)
4797 // we've started a previously queued item
4798 CFileItemPtr item = playList[m_nextPlaylistItem];
4799 // update the playlist manager
4800 int currentSong = g_playlistPlayer.GetCurrentSong();
4801 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4802 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4803 g_windowManager.SendThreadMessage(msg);
4804 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4805 *m_itemCurrentFile = *item;
4807 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4808 g_partyModeManager.OnSongChange(true);
4811 param["player"]["speed"] = 1;
4812 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4813 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4815 if (m_pPlayer->IsPlayingAudio())
4817 // Start our cdg parser as appropriate
4819 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4821 m_pKaraokeMgr->Stop();
4822 if (m_itemCurrentFile->IsMusicDb())
4824 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4826 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4827 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4830 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4833 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4842 case GUI_MSG_QUEUE_NEXT_ITEM:
4844 // Check to see if our playlist player has a new item for us,
4845 // and if so, we check whether our current player wants the file
4846 int iNext = g_playlistPlayer.GetNextSong();
4847 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4848 if (iNext < 0 || iNext >= playlist.size())
4850 m_pPlayer->OnNothingToQueueNotify();
4851 return true; // nothing to do
4854 // ok, grab the next song
4855 CFileItem file(*playlist[iNext]);
4857 CURL url(file.GetPath());
4858 if (url.GetProtocol() == "plugin")
4859 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4862 if (URIUtils::IsUPnP(file.GetPath()))
4864 if (!XFILE::CUPnPDirectory::GetResource(file.GetURL(), file))
4869 // ok - send the file to the player, if it accepts it
4870 if (m_pPlayer->QueueNextFile(file))
4872 // player accepted the next file
4873 m_nextPlaylistItem = iNext;
4877 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4878 queue the next (if it wants to) and it doesn't keep looping on this song */
4879 g_playlistPlayer.SetCurrentSong(iNext);
4886 case GUI_MSG_PLAYBACK_STOPPED:
4887 case GUI_MSG_PLAYBACK_ENDED:
4888 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4892 m_pKaraokeMgr->Stop();
4894 #ifdef TARGET_DARWIN
4895 DarwinSetScheduling(message.GetMessage());
4897 // first check if we still have items in the stack to play
4898 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4900 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4901 { // just play the next item in the stack
4902 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4907 // In case playback ended due to user eg. skipping over the end, clear
4908 // our resume bookmark here
4909 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4911 // Delete the bookmark
4912 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4915 // reset the current playing file
4916 m_itemCurrentFile->Reset();
4917 g_infoManager.ResetCurrentItem();
4918 m_currentStack->Clear();
4920 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4922 g_playlistPlayer.PlayNext(1, true);
4926 // reset any forced player
4927 m_eForcedNextPlayer = EPC_NONE;
4929 m_pPlayer->ClosePlayer();
4932 m_pPlayer->m_iPlaySpeed = 1;
4935 if (!m_pPlayer->IsPlaying())
4937 g_audioManager.Enable(true);
4940 if (!m_pPlayer->IsPlayingVideo())
4942 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4944 g_windowManager.PreviousWindow();
4948 CSingleLock lock(g_graphicsContext);
4949 // resets to res_desktop or look&feel resolution (including refreshrate)
4950 g_graphicsContext.SetFullScreenVideo(false);
4954 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4956 CSettings::Get().Save(); // save vis settings
4957 WakeUpScreenSaverAndDPMS();
4958 g_windowManager.PreviousWindow();
4961 // DVD ejected while playing in vis ?
4962 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4965 CSettings::Get().Save(); // save vis settings
4966 WakeUpScreenSaverAndDPMS();
4967 g_windowManager.PreviousWindow();
4970 if (IsEnableTestMode())
4971 CApplicationMessenger::Get().Quit();
4976 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4977 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4982 case GUI_MSG_FULLSCREEN:
4983 { // Switch to fullscreen, if we can
4984 SwitchToFullScreen();
4988 case GUI_MSG_EXECUTE:
4989 if (message.GetNumStringParams())
4990 return ExecuteXBMCAction(message.GetStringParam());
4996 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4998 // see if it is a user set string
5000 //We don't know if there is unsecure information in this yet, so we
5001 //postpone any logging
5002 const std::string in_actionStr(actionStr);
5003 actionStr = CGUIInfoLabel::GetLabel(actionStr);
5005 // user has asked for something to be executed
5006 if (CBuiltins::HasCommand(actionStr))
5007 CBuiltins::Execute(actionStr);
5010 // try translating the action from our ButtonTranslator
5012 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5014 OnAction(CAction(actionID));
5017 CFileItem item(actionStr, false);
5019 if (item.IsPythonScript())
5020 { // a python script
5021 CScriptInvocationManager::Get().Execute(item.GetPath());
5025 if (item.IsAudio() || item.IsVideo())
5026 { // an audio or video file
5031 //At this point we have given up to translate, so even though
5032 //there may be insecure information, we log it.
5033 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5040 void CApplication::Process()
5044 // dispatch the messages generated by python or other threads to the current window
5045 g_windowManager.DispatchThreadMessages();
5047 // process messages which have to be send to the gui
5048 // (this can only be done after g_windowManager.Render())
5049 CApplicationMessenger::Get().ProcessWindowMessages();
5053 m_loggingIn = false;
5055 // autoexec.py - profile
5056 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5058 if (XFILE::CFile::Exists(strAutoExecPy))
5059 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5061 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5064 // handle any active scripts
5065 CScriptInvocationManager::Get().Process();
5067 // process messages, even if a movie is playing
5068 CApplicationMessenger::Get().ProcessMessages();
5069 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5071 // check how far we are through playing the current item
5072 // and do anything that needs doing (playcount updates etc)
5073 CheckPlayingProgress();
5076 m_pPlayer->DoAudioWork();
5078 // do any processing that isn't needed on each run
5079 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5081 m_slowTimer.Reset();
5085 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5088 // We get called every 500ms
5089 void CApplication::ProcessSlow()
5091 g_powerManager.ProcessEvents();
5093 #if defined(TARGET_DARWIN_OSX)
5094 // There is an issue on OS X that several system services ask the cursor to become visible
5095 // during their startup routines. Given that we can't control this, we hack it in by
5097 if (g_Windowing.IsFullScreen())
5098 { // SDL thinks it's hidden
5103 // Temporarely pause pausable jobs when viewing video/picture
5104 int currentWindow = g_windowManager.GetActiveWindow();
5105 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5107 CJobManager::GetInstance().PauseJobs();
5111 CJobManager::GetInstance().UnPauseJobs();
5114 // Store our file state for use on close()
5117 // Check if we need to activate the screensaver / DPMS.
5118 CheckScreenSaverAndDPMS();
5120 // Check if we need to shutdown (if enabled).
5121 #if defined(TARGET_DARWIN)
5122 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5124 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5130 // check if we should restart the player
5131 CheckDelayedPlayerRestart();
5133 // check if we can unload any unreferenced dlls or sections
5134 if (!m_pPlayer->IsPlayingVideo())
5135 CSectionLoader::UnloadDelayed();
5137 // check for any idle curl connections
5138 g_curlInterface.CheckIdle();
5140 // check for any idle myth sessions
5141 CMythSession::CheckIdle();
5143 #ifdef HAS_FILESYSTEM_HTSP
5144 // check for any idle htsp sessions
5145 HTSP::CHTSPDirectorySession::CheckIdle();
5149 if ( m_pKaraokeMgr )
5150 m_pKaraokeMgr->ProcessSlow();
5153 if (!m_pPlayer->IsPlayingVideo())
5154 g_largeTextureManager.CleanupUnusedImages();
5156 g_TextureManager.FreeUnusedTextures(5000);
5158 #ifdef HAS_DVD_DRIVE
5159 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5160 if (!m_pPlayer->IsPlayingVideo())
5161 m_Autorun->HandleAutorun();
5164 // update upnp server/renderer states
5166 if(UPNP::CUPnP::IsInstantiated())
5167 UPNP::CUPnP::GetInstance()->UpdateState();
5170 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5174 #ifdef HAS_FILESYSTEM_NFS
5175 gNfsConnection.CheckIfIdle();
5178 #ifdef HAS_FILESYSTEM_AFP
5179 gAfpConnection.CheckIfIdle();
5182 #ifdef HAS_FILESYSTEM_SFTP
5183 CSFTPSessionManager::ClearOutIdleSessions();
5186 g_mediaManager.ProcessEvents();
5189 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5190 g_RemoteControl.Initialize();
5193 if (!m_pPlayer->IsPlayingVideo() &&
5194 CSettings::Get().GetInt("general.addonupdates") != AUTO_UPDATES_NEVER)
5195 CAddonInstaller::Get().UpdateRepos();
5197 CAEFactory::GarbageCollect();
5199 // if we don't render the gui there's no reason to start the screensaver.
5200 // that way the screensaver won't kick in if we maximize the XBMC window
5201 // after the screensaver start time.
5203 ResetScreenSaverTimer();
5206 // Global Idle Time in Seconds
5207 // idle time will be resetet if on any OnKey()
5208 // int return: system Idle time in seconds! 0 is no idle!
5209 int CApplication::GlobalIdleTime()
5211 if(!m_idleTimer.IsRunning())
5214 m_idleTimer.StartZero();
5216 return (int)m_idleTimer.GetElapsedSeconds();
5219 float CApplication::NavigationIdleTime()
5221 if (!m_navigationTimer.IsRunning())
5223 m_navigationTimer.Stop();
5224 m_navigationTimer.StartZero();
5226 return m_navigationTimer.GetElapsedSeconds();
5229 void CApplication::DelayedPlayerRestart()
5231 m_restartPlayerTimer.StartZero();
5234 void CApplication::CheckDelayedPlayerRestart()
5236 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5238 m_restartPlayerTimer.Stop();
5239 m_restartPlayerTimer.Reset();
5244 void CApplication::Restart(bool bSamePosition)
5246 // this function gets called when the user changes a setting (like noninterleaved)
5247 // and which means we gotta close & reopen the current playing file
5249 // first check if we're playing a file
5250 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5253 if( !m_pPlayer->HasPlayer() )
5258 // do we want to return to the current position in the file
5259 if (false == bSamePosition)
5261 // no, then just reopen the file and start at the beginning
5262 PlayFile(*m_itemCurrentFile, true);
5266 // else get current position
5267 double time = GetTime();
5269 // get player state, needed for dvd's
5270 CStdString state = m_pPlayer->GetPlayerState();
5272 // set the requested starttime
5273 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5276 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5277 m_pPlayer->SetPlayerState(state);
5280 const std::string& CApplication::CurrentFile()
5282 return m_itemCurrentFile->GetPath();
5285 CFileItem& CApplication::CurrentFileItem()
5287 return *m_itemCurrentFile;
5290 CFileItem& CApplication::CurrentUnstackedItem()
5292 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5293 return *(*m_currentStack)[m_currentStackPosition];
5295 return *m_itemCurrentFile;
5298 void CApplication::ShowVolumeBar(const CAction *action)
5300 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5305 volumeBar->OnAction(*action);
5309 bool CApplication::IsMuted() const
5311 if (g_peripherals.IsMuted())
5313 return CAEFactory::IsMuted();
5316 void CApplication::ToggleMute(void)
5324 void CApplication::SetMute(bool mute)
5326 if (m_muted != mute)
5333 void CApplication::Mute()
5335 if (g_peripherals.Mute())
5338 CAEFactory::SetMute(true);
5343 void CApplication::UnMute()
5345 if (g_peripherals.UnMute())
5348 CAEFactory::SetMute(false);
5353 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5355 float hardwareVolume = iValue;
5358 hardwareVolume /= 100.0f;
5360 SetHardwareVolume(hardwareVolume);
5364 void CApplication::SetHardwareVolume(float hardwareVolume)
5366 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5367 m_volumeLevel = hardwareVolume;
5369 CAEFactory::SetVolume(hardwareVolume);
5372 float CApplication::GetVolume(bool percentage /* = true */) const
5376 // converts the hardware volume to a percentage
5377 return m_volumeLevel * 100.0f;
5380 return m_volumeLevel;
5383 void CApplication::VolumeChanged() const
5385 CVariant data(CVariant::VariantTypeObject);
5386 data["volume"] = GetVolume();
5387 data["muted"] = m_muted;
5388 CAnnouncementManager::Get().Announce(Application, "xbmc", "OnVolumeChanged", data);
5390 // if player has volume control, set it.
5391 if (m_pPlayer->ControlsVolume())
5393 m_pPlayer->SetVolume(m_volumeLevel);
5394 m_pPlayer->SetMute(m_muted);
5398 int CApplication::GetSubtitleDelay() const
5400 // converts subtitle delay to a percentage
5401 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5404 int CApplication::GetAudioDelay() const
5406 // converts audio delay to a percentage
5407 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5410 // Returns the total time in seconds of the current media. Fractional
5411 // portions of a second are possible - but not necessarily supported by the
5412 // player class. This returns a double to be consistent with GetTime() and
5414 double CApplication::GetTotalTime() const
5418 if (m_pPlayer->IsPlaying())
5420 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5421 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5423 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5429 void CApplication::StopShutdownTimer()
5431 if (m_shutdownTimer.IsRunning())
5432 m_shutdownTimer.Stop();
5435 void CApplication::ResetShutdownTimers()
5437 // reset system shutdown timer
5438 m_shutdownTimer.StartZero();
5440 // delete custom shutdown timer
5441 if (g_alarmClock.HasAlarm("shutdowntimer"))
5442 g_alarmClock.Stop("shutdowntimer", true);
5445 // Returns the current time in seconds of the currently playing media.
5446 // Fractional portions of a second are possible. This returns a double to
5447 // be consistent with GetTotalTime() and SeekTime().
5448 double CApplication::GetTime() const
5452 if (m_pPlayer->IsPlaying())
5454 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5456 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5457 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5460 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5466 // Sets the current position of the currently playing media to the specified
5467 // time in seconds. Fractional portions of a second are valid. The passed
5468 // time is the time offset from the beginning of the file as opposed to a
5469 // delta from the current position. This method accepts a double to be
5470 // consistent with GetTime() and GetTotalTime().
5471 void CApplication::SeekTime( double dTime )
5473 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5475 if (!m_pPlayer->CanSeek()) return;
5476 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5478 // find the item in the stack we are seeking to, and load the new
5479 // file if necessary, and calculate the correct seek within the new
5480 // file. Otherwise, just fall through to the usual routine if the
5481 // time is higher than our total time.
5482 for (int i = 0; i < m_currentStack->Size(); i++)
5484 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5486 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5487 if (m_currentStackPosition == i)
5488 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5490 { // seeking to a new file
5491 m_currentStackPosition = i;
5492 CFileItem item(*(*m_currentStack)[i]);
5493 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5494 // don't just call "PlayFile" here, as we are quite likely called from the
5495 // player thread, so we won't be able to delete ourselves.
5496 CApplicationMessenger::Get().PlayFile(item, true);
5502 // convert to milliseconds and perform seek
5503 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5507 float CApplication::GetPercentage() const
5509 if (m_pPlayer->IsPlaying())
5511 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5513 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5514 if (tag.GetDuration() > 0)
5515 return (float)(GetTime() / tag.GetDuration() * 100);
5518 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5520 double totalTime = GetTotalTime();
5521 if (totalTime > 0.0f)
5522 return (float)(GetTime() / totalTime * 100);
5525 return m_pPlayer->GetPercentage();
5530 float CApplication::GetCachePercentage() const
5532 if (m_pPlayer->IsPlaying())
5534 // Note that the player returns a relative cache percentage and we want an absolute percentage
5535 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5537 float stackedTotalTime = (float) GetTotalTime();
5538 // We need to take into account the stack's total time vs. currently playing file's total time
5539 if (stackedTotalTime > 0.0f)
5540 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5543 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5548 void CApplication::SeekPercentage(float percent)
5550 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5552 if (!m_pPlayer->CanSeek()) return;
5553 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5554 SeekTime(percent * 0.01 * GetTotalTime());
5556 m_pPlayer->SeekPercentage(percent);
5560 // SwitchToFullScreen() returns true if a switch is made, else returns false
5561 bool CApplication::SwitchToFullScreen()
5563 // if playing from the video info window, close it first!
5564 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5566 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5567 if (pDialog) pDialog->Close(true);
5570 // don't switch if there is a dialog on screen or the slideshow is active
5571 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5574 // See if we're playing a video, and are in GUI mode
5575 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5577 // then switch to fullscreen mode
5578 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5581 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5582 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5583 { // then switch to visualisation
5584 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5590 void CApplication::Minimize()
5592 g_Windowing.Minimize();
5595 PLAYERCOREID CApplication::GetCurrentPlayer()
5597 return m_pPlayer->GetCurrentPlayer();
5600 void CApplication::UpdateLibraries()
5602 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5604 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5608 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5610 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5615 bool CApplication::IsVideoScanning() const
5617 return m_videoInfoScanner->IsScanning();
5620 bool CApplication::IsMusicScanning() const
5622 return m_musicInfoScanner->IsScanning();
5625 void CApplication::StopVideoScan()
5627 if (m_videoInfoScanner->IsScanning())
5628 m_videoInfoScanner->Stop();
5631 void CApplication::StopMusicScan()
5633 if (m_musicInfoScanner->IsScanning())
5634 m_musicInfoScanner->Stop();
5637 void CApplication::StartVideoCleanup()
5639 if (m_videoInfoScanner->IsScanning())
5642 m_videoInfoScanner->CleanDatabase();
5645 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5647 if (m_videoInfoScanner->IsScanning())
5650 m_videoInfoScanner->ShowDialog(true);
5652 m_videoInfoScanner->Start(strDirectory,scanAll);
5655 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5657 if (m_musicInfoScanner->IsScanning())
5661 { // setup default flags
5662 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5663 flags |= CMusicInfoScanner::SCAN_ONLINE;
5664 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5665 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5668 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5669 m_musicInfoScanner->ShowDialog(true);
5671 m_musicInfoScanner->Start(strDirectory, flags);
5674 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5677 if (m_musicInfoScanner->IsScanning())
5680 m_musicInfoScanner->ShowDialog(true);
5682 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5685 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5688 if (m_musicInfoScanner->IsScanning())
5691 m_musicInfoScanner->ShowDialog(true);
5693 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5696 void CApplication::CheckPlayingProgress()
5698 // check if we haven't rewound past the start of the file
5699 if (m_pPlayer->IsPlaying())
5701 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5711 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5713 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5714 g_application.SeekTime(0);
5720 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5722 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5724 // initial exit conditions
5725 // no songs in playlist just return
5726 if (playlist.size() == 0)
5730 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5733 // setup correct playlist
5734 g_playlistPlayer.ClearPlaylist(iPlaylist);
5736 // if the playlist contains an internet stream, this file will be used
5737 // to generate a thumbnail for musicplayer.cover
5738 g_application.m_strPlayListFile = strPlayList;
5740 // add the items to the playlist player
5741 g_playlistPlayer.Add(iPlaylist, playlist);
5743 // if we have a playlist
5744 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5747 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5748 g_playlistPlayer.Reset();
5749 g_playlistPlayer.Play(track);
5755 void CApplication::SaveCurrentFileSettings()
5757 // don't store settings for PVR in video database
5758 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5760 // save video settings
5761 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5765 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5769 else if (m_itemCurrentFile->IsPVRChannel())
5771 g_PVRManager.SaveCurrentChannelSettings();
5775 bool CApplication::AlwaysProcess(const CAction& action)
5777 // check if this button is mapped to a built-in function
5778 if (!action.GetName().empty())
5780 CStdString builtInFunction;
5781 vector<string> params;
5782 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5783 StringUtils::ToLower(builtInFunction);
5785 // should this button be handled normally or just cancel the screensaver?
5786 if ( builtInFunction.Equals("powerdown")
5787 || builtInFunction.Equals("reboot")
5788 || builtInFunction.Equals("restart")
5789 || builtInFunction.Equals("restartapp")
5790 || builtInFunction.Equals("suspend")
5791 || builtInFunction.Equals("hibernate")
5792 || builtInFunction.Equals("quit")
5793 || builtInFunction.Equals("shutdown"))
5802 bool CApplication::IsCurrentThread() const
5804 return CThread::IsCurrentThread(m_threadID);
5807 void CApplication::SetRenderGUI(bool renderGUI)
5809 if (renderGUI && ! m_renderGUI)
5810 g_windowManager.MarkDirty();
5811 m_renderGUI = renderGUI;
5814 CNetwork& CApplication::getNetwork()
5818 #ifdef HAS_PERFORMANCE_SAMPLE
5819 CPerformanceStats &CApplication::GetPerformanceStats()
5825 bool CApplication::SetLanguage(const CStdString &strLanguage)
5827 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5828 if (strLanguage != strPreviousLanguage)
5830 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
5831 if (!g_langInfo.Load(strLangInfoPath))
5834 CSettings::Get().SetString("locale.language", strLanguage);
5836 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
5839 // also tell our weather and skin to reload as these are localized
5840 g_weatherManager.Refresh();
5841 g_PVRManager.LocalizationChanged();
5848 void CApplication::CloseNetworkShares()
5850 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5852 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5856 #ifdef HAS_FILESYSTEM_NFS
5857 gNfsConnection.Deinit();
5860 #ifdef HAS_FILESYSTEM_AFP
5861 gAfpConnection.Deinit();
5864 #ifdef HAS_FILESYSTEM_SFTP
5865 CSFTPSessionManager::DisconnectAllSessions();