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"
342 #ifdef TARGET_WINDOWS
343 #include "utils/Environment.h"
346 #if defined(HAS_LIBAMCODEC)
347 #include "utils/AMLUtils.h"
351 using namespace ADDON;
352 using namespace XFILE;
354 using namespace MEDIA_DETECT;
356 using namespace PLAYLIST;
357 using namespace VIDEO;
358 using namespace MUSIC_INFO;
359 #ifdef HAS_EVENT_SERVER
360 using namespace EVENTSERVER;
363 using namespace JSONRPC;
365 using namespace ANNOUNCEMENT;
368 using namespace PERIPHERALS;
370 using namespace XbmcThreads;
372 // uncomment this if you want to use release libs in the debug build.
373 // Atm this saves you 7 mb of memory
374 #define USE_RELEASE_LIBS
376 #define MAX_FFWD_SPEED 5
378 //extern IDirectSoundRenderer* m_pAudioDecoder;
379 CApplication::CApplication(void)
380 : m_pPlayer(new CApplicationPlayer)
381 , m_itemCurrentFile(new CFileItem)
382 , m_stackFileItemToUpdate(new CFileItem)
383 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
384 , m_progressTrackingItem(new CFileItem)
385 , m_videoInfoScanner(new CVideoInfoScanner)
386 , m_musicInfoScanner(new CMusicInfoScanner)
387 , m_seekHandler(new CSeekHandler)
388 , m_playerController(new CPlayerController)
391 TiXmlBase::SetCondenseWhiteSpace(false);
392 m_bInhibitIdleShutdown = false;
393 m_bScreenSave = false;
395 m_dpmsIsActive = false;
396 m_dpmsIsManual = false;
397 m_iScreenSaveLock = 0;
398 m_bInitializing = true;
399 m_eForcedNextPlayer = EPC_NONE;
400 m_strPlayListFile = "";
401 m_nextPlaylistItem = -1;
402 m_bPlaybackStarting = false;
403 m_ePlayState = PLAY_STATE_NONE;
404 m_skinReloading = false;
405 m_skinReverting = false;
412 // we start in frontend
413 m_bInBackground = 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, newEvent.focus.x, 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::Cache(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.GetBuildTargetCpuFamily().c_str(),
696 g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness());
698 /* Expand macro before stringify */
699 #define STR_MACRO(x) #x
700 #define XSTR_MACRO(x) STR_MACRO(x)
702 std::string compilerStr;
703 #if defined(__clang__)
704 compilerStr = "Clang " XSTR_MACRO(__clang_major__) "." XSTR_MACRO(__clang_minor__) "." XSTR_MACRO(__clang_patchlevel__);
705 #elif defined (__INTEL_COMPILER)
706 compilerStr = "Intel Compiler " XSTR_MACRO(__INTEL_COMPILER);
707 #elif defined (__GNUC__)
709 /* Note: this will not detect GCC + DragonEgg */
710 compilerStr = "llvm-gcc ";
712 compilerStr = "GCC ";
714 compilerStr += XSTR_MACRO(__GNUC__) "." XSTR_MACRO(__GNUC_MINOR__) "." XSTR_MACRO(__GNUC_PATCHLEVEL__);
715 #elif defined (_MSC_VER)
716 compilerStr = "MSVC " XSTR_MACRO(_MSC_FULL_VER);
718 compilerStr = "unknown compiler";
720 std::string buildType;
723 #elif defined(NDEBUG)
724 buildType = "Release";
726 buildType = "Unknown";
728 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build, compiled " __DATE__ " by %s for %s %s %d-bit %s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), compilerStr.c_str(),
729 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersion().c_str());
731 #if defined(TARGET_DARWIN_OSX)
732 CLog::Log(LOGNOTICE, "Running on Darwin OSX %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
733 #elif defined(TARGET_DARWIN_IOS)
734 CLog::Log(LOGNOTICE, "Running on Darwin iOS %d-bit %s%s", g_sysinfo.GetKernelBitness(), g_sysinfo.IsAppleTV2() ? "(AppleTV2) " : "", g_sysinfo.GetUnameVersion().c_str());
735 #elif defined(TARGET_FREEBSD)
736 CLog::Log(LOGNOTICE, "Running on FreeBSD %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
737 #elif defined(TARGET_POSIX)
738 CLog::Log(LOGNOTICE, "Running on Linux %d-bit (%s, %s)", g_sysinfo.GetKernelBitness(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
739 #elif defined(TARGET_WINDOWS)
740 CLog::Log(LOGNOTICE, "Running on %s", g_sysinfo.GetKernelVersion().c_str());
743 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", g_cpuInfo.getCPUModel().c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount()==1) ? "" : "s");
744 #if defined(TARGET_WINDOWS)
745 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
746 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
747 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
750 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
751 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
753 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
755 CSpecialProtocol::LogPaths();
757 CStdString executable = CUtil::ResolveExecutablePath();
758 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
759 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
760 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
761 CRegExp::LogCheckUtf8Support();
762 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
764 CStdString strExecutablePath;
765 CUtil::GetHomePath(strExecutablePath);
768 g_xrandr.LoadCustomModeLinesToAllOutputs();
771 // for python scripts that check the OS
772 #if defined(TARGET_DARWIN)
773 setenv("OS","OS X",true);
774 #elif defined(TARGET_POSIX)
775 setenv("OS","Linux",true);
776 #elif defined(TARGET_WINDOWS)
777 CEnvironment::setenv("OS", "win32");
780 g_powerManager.Initialize();
782 // Load the AudioEngine before settings as they need to query the engine
783 if (!CAEFactory::LoadEngine())
785 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
789 // Initialize default Settings - don't move
790 CLog::Log(LOGNOTICE, "load settings...");
791 if (!CSettings::Get().Initialize())
794 g_powerManager.SetDefaults();
796 // load the actual values
797 if (!CSettings::Get().Load())
799 CLog::Log(LOGFATAL, "unable to load settings");
802 CSettings::Get().SetLoaded();
804 CLog::Log(LOGINFO, "creating subdirectories");
805 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
806 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
807 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
808 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
809 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
810 CProfilesManager::Get().CreateProfileFolders();
812 update_emu_environ();//apply the GUI settings
814 // Load the langinfo to have user charset <-> utf-8 conversion
815 CStdString strLanguage = CSettings::Get().GetString("locale.language");
816 strLanguage[0] = toupper(strLanguage[0]);
818 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
820 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
821 g_langInfo.Load(strLangInfoPath);
822 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
823 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
825 CStdString strLanguagePath = "special://xbmc/language/";
827 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
828 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
830 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
834 // start the AudioEngine
835 if (!CAEFactory::StartEngine())
837 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
841 // restore AE's previous volume state
842 SetHardwareVolume(m_volumeLevel);
843 CAEFactory::SetMute (m_muted);
844 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
846 // initialize m_replayGainSettings
847 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
848 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
849 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
850 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
852 // initialize the addon database (must be before the addon manager is init'd)
853 CDatabaseManager::Get().Initialize(true);
856 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
859 // start-up Addons Framework
860 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
861 if (!CAddonMgr::Get().Init())
863 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
866 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
867 g_RemoteControl.Initialize();
870 // set logging from debug add-on
872 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
874 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
876 g_peripherals.Initialise();
878 // Create the Mouse, Keyboard, Remote, and Joystick devices
879 // Initialize after loading settings to get joystick deadzone setting
880 g_Mouse.Initialize();
881 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
883 g_Keyboard.Initialize();
885 #if defined(TARGET_DARWIN_OSX)
886 // Configure and possible manually start the helper.
887 XBMCHelper::GetInstance().Configure();
890 CUtil::InitRandomSeed();
892 g_mediaManager.Initialize();
894 m_lastFrameTime = XbmcThreads::SystemClockMillis();
895 m_lastRenderTime = m_lastFrameTime;
899 bool CApplication::CreateGUI()
903 CLog::Log(LOGNOTICE, "Setup SDL");
905 /* Clean up on exit, exit on window close and interrupt */
908 uint32_t sdlFlags = 0;
910 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
911 sdlFlags |= SDL_INIT_VIDEO;
914 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
915 sdlFlags |= SDL_INIT_JOYSTICK;
918 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
919 //this might bring the monitor out of standby, so we have to disable it explicitly
920 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
921 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
922 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
928 // for nvidia cards - vsync currently ALWAYS enabled.
929 // the reason is that after screen has been setup changing this env var will make no difference.
930 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
931 setenv("__GL_YIELD", "USLEEP", 0);
934 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
935 g_Windowing.EnableSystemScreenSaver(false);
938 if (SDL_Init(sdlFlags) != 0)
940 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
943 #if defined(TARGET_DARWIN)
944 // SDL_Init will install a handler for segfaults, restore the default handler.
945 signal(SIGSEGV, SIG_DFL);
949 // Initialize core peripheral port support. Note: If these parameters
950 // are 0 and NULL, respectively, then the default number and types of
951 // controllers will be initialized.
952 if (!g_Windowing.InitWindowSystem())
954 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
958 // Retrieve the matching resolution based on GUI settings
959 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
960 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
961 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
963 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
964 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
967 // update the window resolution
968 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
970 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
971 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
973 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
975 // Oh uh - doesn't look good for starting in their wanted screenmode
976 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
977 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
984 if (g_advancedSettings.m_splashImage)
986 CStdString strUserSplash = "special://home/media/Splash.png";
987 if (CFile::Exists(strUserSplash))
989 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
990 m_splash = new CSplash(strUserSplash);
994 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
995 m_splash = new CSplash("special://xbmc/media/Splash.png");
1000 // The key mappings may already have been loaded by a peripheral
1001 CLog::Log(LOGINFO, "load keymapping");
1002 if (!CButtonTranslator::GetInstance().Load())
1005 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1006 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1009 info.strMode.c_str());
1010 g_windowManager.Initialize();
1015 bool CApplication::InitWindow()
1017 #ifdef TARGET_DARWIN_OSX
1018 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1019 // fixes the white screen of death if starting fullscreen and switching to windowed.
1020 bool bFullScreen = false;
1021 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1023 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1027 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1028 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1030 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1035 if (!g_Windowing.InitRenderSystem())
1037 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1040 // set GUI res and force the clear of the screen
1041 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1045 bool CApplication::DestroyWindow()
1047 return g_Windowing.DestroyWindow();
1050 bool CApplication::InitDirectoriesLinux()
1053 The following is the directory mapping for Platform Specific Mode:
1055 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1056 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1057 installations like skins, screensavers, etc.
1059 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1060 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1061 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1062 special://profile/ => [read-write] current profile's userdata directory.
1063 Generally special://masterprofile for the master profile or
1064 special://masterprofile/profiles/<profile_name> for other profiles.
1066 NOTE: All these root directories are lowercase. Some of the sub-directories
1067 might be mixed case.
1070 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1071 CStdString userName;
1073 userName = getenv("USER");
1077 CStdString userHome;
1079 userHome = getenv("HOME");
1083 CStdString xbmcBinPath, xbmcPath;
1084 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1085 xbmcPath = getenv("XBMC_HOME");
1087 if (xbmcPath.empty())
1089 xbmcPath = xbmcBinPath;
1090 /* Check if xbmc binaries and arch independent data files are being kept in
1091 * separate locations. */
1092 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1094 /* Attempt to locate arch independent data files. */
1095 CUtil::GetHomePath(xbmcPath);
1096 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1098 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1104 /* Set some environment variables */
1105 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1106 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1108 if (m_bPlatformDirectories)
1110 // map our special drives
1111 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1112 CSpecialProtocol::SetXBMCPath(xbmcPath);
1113 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1114 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1116 CStdString strTempPath = userHome;
1117 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1118 if (getenv("XBMC_TEMP"))
1119 strTempPath = getenv("XBMC_TEMP");
1120 CSpecialProtocol::SetTempPath(strTempPath);
1122 URIUtils::AddSlashAtEnd(strTempPath);
1123 g_advancedSettings.m_logFolder = strTempPath;
1130 URIUtils::AddSlashAtEnd(xbmcPath);
1131 g_advancedSettings.m_logFolder = xbmcPath;
1133 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1134 CSpecialProtocol::SetXBMCPath(xbmcPath);
1135 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1136 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1138 CStdString strTempPath = xbmcPath;
1139 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1140 if (getenv("XBMC_TEMP"))
1141 strTempPath = getenv("XBMC_TEMP");
1142 CSpecialProtocol::SetTempPath(strTempPath);
1145 URIUtils::AddSlashAtEnd(strTempPath);
1146 g_advancedSettings.m_logFolder = strTempPath;
1155 bool CApplication::InitDirectoriesOSX()
1157 #if defined(TARGET_DARWIN)
1158 CStdString userName;
1160 userName = getenv("USER");
1164 CStdString userHome;
1166 userHome = getenv("HOME");
1170 CStdString xbmcPath;
1171 CUtil::GetHomePath(xbmcPath);
1172 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1174 #if defined(TARGET_DARWIN_IOS)
1175 CStdString fontconfigPath;
1176 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1177 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1180 // setup path to our internal dylibs so loader can find them
1181 CStdString frameworksPath = CUtil::GetFrameworksPath();
1182 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1184 // OSX always runs with m_bPlatformDirectories == true
1185 if (m_bPlatformDirectories)
1187 // map our special drives
1188 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1189 CSpecialProtocol::SetXBMCPath(xbmcPath);
1190 #if defined(TARGET_DARWIN_IOS)
1191 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1192 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1194 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1195 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1198 // location for temp files
1199 #if defined(TARGET_DARWIN_IOS)
1200 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1202 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1203 CDirectory::Create(strTempPath);
1204 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1206 CSpecialProtocol::SetTempPath(strTempPath);
1208 // xbmc.log file location
1209 #if defined(TARGET_DARWIN_IOS)
1210 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1212 strTempPath = userHome + "/Library/Logs";
1214 URIUtils::AddSlashAtEnd(strTempPath);
1215 g_advancedSettings.m_logFolder = strTempPath;
1221 URIUtils::AddSlashAtEnd(xbmcPath);
1222 g_advancedSettings.m_logFolder = xbmcPath;
1224 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1225 CSpecialProtocol::SetXBMCPath(xbmcPath);
1226 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1227 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1229 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1230 CSpecialProtocol::SetTempPath(strTempPath);
1232 URIUtils::AddSlashAtEnd(strTempPath);
1233 g_advancedSettings.m_logFolder = strTempPath;
1242 bool CApplication::InitDirectoriesWin32()
1244 #ifdef TARGET_WINDOWS
1245 CStdString xbmcPath;
1247 CUtil::GetHomePath(xbmcPath);
1248 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1249 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1250 CSpecialProtocol::SetXBMCPath(xbmcPath);
1252 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1254 g_advancedSettings.m_logFolder = strWin32UserFolder;
1255 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1256 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1257 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1259 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1263 // Expand the DLL search path with our directories
1264 CWIN32Util::ExtendDllPath();
1272 void CApplication::CreateUserDirs()
1274 CDirectory::Create("special://home/");
1275 CDirectory::Create("special://home/addons");
1276 CDirectory::Create("special://home/addons/packages");
1277 CDirectory::Create("special://home/media");
1278 CDirectory::Create("special://home/sounds");
1279 CDirectory::Create("special://home/system");
1280 CDirectory::Create("special://masterprofile/");
1281 CDirectory::Create("special://temp/");
1282 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1285 bool CApplication::Initialize()
1287 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1288 // turn off cdio logging
1289 cdio_loglevel_default = CDIO_LOG_ERROR;
1292 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1293 // must create these here. Ideally this should be using special://home/ and
1294 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1295 if (!m_bPlatformDirectories)
1298 CDirectory::Create("special://xbmc/language");
1299 CDirectory::Create("special://xbmc/addons");
1300 CDirectory::Create("special://xbmc/sounds");
1303 // Load curl so curl_global_init gets called before any service threads
1304 // are started. Unloading will have no effect as curl is never fully unloaded.
1305 // To quote man curl_global_init:
1306 // "This function is not thread safe. You must not call it when any other
1307 // thread in the program (i.e. a thread sharing the same memory) is running.
1308 // This doesn't just mean no other thread that is using libcurl. Because
1309 // curl_global_init() calls functions of other libraries that are similarly
1310 // thread unsafe, it could conflict with any other thread that
1311 // uses these other libraries."
1312 g_curlInterface.Load();
1313 g_curlInterface.Unload();
1315 // initialize (and update as needed) our databases
1316 CDatabaseManager::Get().Initialize();
1320 // Init DPMS, before creating the corresponding setting control.
1321 m_dpms = new DPMSSupport();
1322 if (g_windowManager.Initialized())
1324 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1326 g_windowManager.Add(new CGUIWindowHome);
1327 g_windowManager.Add(new CGUIWindowPrograms);
1328 g_windowManager.Add(new CGUIWindowPictures);
1329 g_windowManager.Add(new CGUIWindowFileManager);
1330 g_windowManager.Add(new CGUIWindowSettings);
1331 g_windowManager.Add(new CGUIWindowSystemInfo);
1333 g_windowManager.Add(new CGUIWindowTestPatternGL);
1336 g_windowManager.Add(new CGUIWindowTestPatternDX);
1338 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1339 g_windowManager.Add(new CGUIWindowSettingsCategory);
1340 g_windowManager.Add(new CGUIWindowVideoNav);
1341 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1342 g_windowManager.Add(new CGUIWindowLoginScreen);
1343 g_windowManager.Add(new CGUIWindowSettingsProfile);
1344 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1345 g_windowManager.Add(new CGUIWindowAddonBrowser);
1346 g_windowManager.Add(new CGUIWindowScreensaverDim);
1347 g_windowManager.Add(new CGUIWindowDebugInfo);
1348 g_windowManager.Add(new CGUIWindowPointer);
1349 g_windowManager.Add(new CGUIDialogYesNo);
1350 g_windowManager.Add(new CGUIDialogProgress);
1351 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1352 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1353 g_windowManager.Add(new CGUIDialogVolumeBar);
1354 g_windowManager.Add(new CGUIDialogSeekBar);
1355 g_windowManager.Add(new CGUIDialogSubMenu);
1356 g_windowManager.Add(new CGUIDialogContextMenu);
1357 g_windowManager.Add(new CGUIDialogKaiToast);
1358 g_windowManager.Add(new CGUIDialogNumeric);
1359 g_windowManager.Add(new CGUIDialogGamepad);
1360 g_windowManager.Add(new CGUIDialogButtonMenu);
1361 g_windowManager.Add(new CGUIDialogMuteBug);
1362 g_windowManager.Add(new CGUIDialogPlayerControls);
1364 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1365 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1367 g_windowManager.Add(new CGUIDialogSlider);
1368 g_windowManager.Add(new CGUIDialogMusicOSD);
1369 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1370 g_windowManager.Add(new CGUIDialogVideoSettings);
1371 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1372 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1373 // Don't add the filebrowser dialog - it's created and added when it's needed
1374 g_windowManager.Add(new CGUIDialogNetworkSetup);
1375 g_windowManager.Add(new CGUIDialogMediaSource);
1376 g_windowManager.Add(new CGUIDialogProfileSettings);
1377 g_windowManager.Add(new CGUIDialogFavourites);
1378 g_windowManager.Add(new CGUIDialogSongInfo);
1379 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1380 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1381 g_windowManager.Add(new CGUIDialogBusy);
1382 g_windowManager.Add(new CGUIDialogPictureInfo);
1383 g_windowManager.Add(new CGUIDialogAddonInfo);
1384 g_windowManager.Add(new CGUIDialogAddonSettings);
1385 #ifdef HAS_LINUX_NETWORK
1386 g_windowManager.Add(new CGUIDialogAccessPoints);
1389 g_windowManager.Add(new CGUIDialogLockSettings);
1391 g_windowManager.Add(new CGUIDialogContentSettings);
1393 g_windowManager.Add(new CGUIDialogPlayEject);
1395 g_windowManager.Add(new CGUIDialogPeripheralManager);
1396 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1398 g_windowManager.Add(new CGUIDialogMediaFilter);
1399 g_windowManager.Add(new CGUIDialogSubtitles);
1401 g_windowManager.Add(new CGUIWindowMusicPlayList);
1402 g_windowManager.Add(new CGUIWindowMusicSongs);
1403 g_windowManager.Add(new CGUIWindowMusicNav);
1404 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1406 /* Load PVR related Windows and Dialogs */
1407 g_windowManager.Add(new CGUIDialogTeletext);
1408 g_windowManager.Add(new CGUIWindowPVR);
1409 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1410 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1411 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1412 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1413 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1414 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1415 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1416 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1417 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1418 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1420 g_windowManager.Add(new CGUIDialogSelect);
1421 g_windowManager.Add(new CGUIDialogMusicInfo);
1422 g_windowManager.Add(new CGUIDialogOK);
1423 g_windowManager.Add(new CGUIDialogVideoInfo);
1424 g_windowManager.Add(new CGUIDialogTextViewer);
1425 g_windowManager.Add(new CGUIWindowFullScreen);
1426 g_windowManager.Add(new CGUIWindowVisualisation);
1427 g_windowManager.Add(new CGUIWindowSlideShow);
1428 g_windowManager.Add(new CGUIDialogFileStacking);
1430 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1433 g_windowManager.Add(new CGUIDialogVideoOSD);
1434 g_windowManager.Add(new CGUIDialogMusicOverlay);
1435 g_windowManager.Add(new CGUIDialogVideoOverlay);
1436 g_windowManager.Add(new CGUIWindowScreensaver);
1437 g_windowManager.Add(new CGUIWindowWeather);
1438 g_windowManager.Add(new CGUIWindowStartup);
1440 /* window id's 3000 - 3100 are reserved for python */
1442 // Make sure we have at least the default skin
1443 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1444 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1446 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1450 if (g_advancedSettings.m_splashImage)
1451 SAFE_DELETE(m_splash);
1453 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1454 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1455 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1457 g_passwordManager.CheckStartUpLock();
1460 // check if we should use the login screen
1461 if (CProfilesManager::Get().UsingLoginScreen())
1462 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1466 CJSONRPC::Initialize();
1468 ADDON::CAddonMgr::Get().StartServices(false);
1469 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1471 g_windowManager.ActivateWindow(WINDOW_HOME);
1472 StartPVRManager(true);
1476 StartPVRManager(false);
1477 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1480 CStereoscopicsManager::Get().Initialize();
1484 else //No GUI Created
1487 CJSONRPC::Initialize();
1489 ADDON::CAddonMgr::Get().StartServices(false);
1492 g_sysinfo.Refresh();
1494 CLog::Log(LOGINFO, "removing tempfiles");
1495 CUtil::RemoveTempFiles();
1497 if (!CProfilesManager::Get().UsingLoginScreen())
1503 m_slowTimer.StartZero();
1505 #if defined(HAVE_LIBCRYSTALHD)
1506 CCrystalHD::GetInstance();
1509 CAddonMgr::Get().StartServices(true);
1511 CLog::Log(LOGNOTICE, "initialize done");
1513 m_bInitializing = false;
1515 // reset our screensaver (starts timers etc.)
1518 #ifdef HAS_SDL_JOYSTICK
1519 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1520 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1526 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1532 // the callback will take care of starting/stopping webserver
1533 ret = CSettings::Get().SetBool("services.webserver", bStart);
1536 case ES_AIRPLAYSERVER:
1537 // the callback will take care of starting/stopping airplay
1538 ret = CSettings::Get().SetBool("services.airplay", bStart);
1541 case ES_JSONRPCSERVER:
1542 // the callback will take care of starting/stopping jsonrpc server
1543 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1547 // the callback will take care of starting/stopping upnp server
1548 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1551 case ES_UPNPRENDERER:
1552 // the callback will take care of starting/stopping upnp renderer
1553 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1556 case ES_EVENTSERVER:
1557 // the callback will take care of starting/stopping event server
1558 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1562 // the callback will take care of starting/stopping zeroconf
1563 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1570 CSettings::Get().Save();
1575 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1577 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1578 g_PVRManager.Start(true, bOpenPVRWindow);
1581 void CApplication::StopPVRManager()
1583 CLog::Log(LOGINFO, "stopping PVRManager");
1584 if (g_PVRManager.IsPlaying())
1586 g_PVRManager.Stop();
1587 g_EpgContainer.Stop();
1590 void CApplication::StartServices()
1592 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1593 // Start Thread for DVD Mediatype detection
1594 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1595 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1598 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1599 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1600 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1601 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1602 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1603 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1606 void CApplication::StopServices()
1608 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1610 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1611 CLog::Log(LOGNOTICE, "stop dvd detect media");
1612 m_DetectDVDType.StopThread();
1615 g_peripherals.Clear();
1618 void CApplication::OnSettingChanged(const CSetting *setting)
1620 if (setting == NULL)
1623 const std::string &settingId = setting->GetId();
1624 if (settingId == "lookandfeel.skin" ||
1625 settingId == "lookandfeel.font" ||
1626 settingId == "lookandfeel.skincolors")
1628 // if the skin changes and the current theme is not the default one, reset
1629 // the theme to the default value (which will also change lookandfeel.skincolors
1630 // which in turn will reload the skin
1631 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1632 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1635 std::string builtin("ReloadSkin");
1636 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1637 builtin += "(confirm)";
1638 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1641 else if (settingId == "lookandfeel.skintheme")
1643 // also set the default color theme
1644 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1645 URIUtils::RemoveExtension(colorTheme);
1646 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1647 colorTheme = "defaults";
1649 // check if we have to change the skin color
1650 // if yes, it will trigger a call to ReloadSkin() in
1651 // it's OnSettingChanged() callback
1652 // if no we have to call ReloadSkin() ourselves
1653 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1654 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1656 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1658 else if (settingId == "lookandfeel.skinzoom")
1659 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1660 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1662 // AE is master of audio settings and needs to be informed first
1663 CAEFactory::OnSettingsChange(settingId);
1665 if (settingId == "audiooutput.guisoundmode")
1667 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1669 // this tells player whether to open an audio stream passthrough or PCM
1670 // if this is changed, audio stream has to be reopened
1671 else if (settingId == "audiooutput.passthrough")
1673 CApplicationMessenger::Get().MediaRestart(false);
1676 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1677 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1678 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1679 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1680 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1681 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1682 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1683 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1686 void CApplication::OnSettingAction(const CSetting *setting)
1688 if (setting == NULL)
1691 const std::string &settingId = setting->GetId();
1692 if (settingId == "lookandfeel.skinsettings")
1693 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1694 else if (settingId == "screensaver.preview")
1695 ActivateScreenSaver(true);
1696 else if (settingId == "screensaver.settings")
1699 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1700 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1702 else if (settingId == "videoscreen.guicalibration")
1703 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1704 else if (settingId == "videoscreen.testpattern")
1705 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1708 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1710 if (setting == NULL)
1713 const std::string &settingId = setting->GetId();
1714 if (settingId == "audiooutput.channels")
1716 // check if this is an update from Eden
1717 if (oldSettingId != NULL && oldSettingNode != NULL &&
1718 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1721 CSettingInt* channels = (CSettingInt*)setting;
1722 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1723 ret = channels->SetValue(channels->GetValue() + 1);
1725 // let's just reset the audiodevice settings as well
1726 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1727 CAEFactory::VerifyOutputDevice(audiodevice, false);
1728 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1733 else if (settingId == "screensaver.mode")
1735 CSettingString *screensaverMode = (CSettingString*)setting;
1736 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1737 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1738 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1740 else if (settingId == "scrapers.musicvideosdefault")
1742 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1743 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1745 musicvideoScraper->Reset();
1749 #if defined(HAS_LIBAMCODEC)
1750 else if (settingId == "videoplayer.useamcodec")
1752 // Do not permit amcodec to be used on non-aml platforms.
1753 // The setting will be hidden but the default value is true,
1754 // so change it to false.
1757 CSettingBool *useamcodec = (CSettingBool*)setting;
1758 useamcodec->SetValue(false);
1762 #if defined(TARGET_ANDROID)
1763 else if (settingId == "videoplayer.usemediacodec")
1765 // Do not permit MediaCodec to be used Android platforms that do not have it.
1766 // The setting will be hidden but the default value is true,
1767 // so change it to false.
1768 if (CAndroidFeatures::GetVersion() < 16)
1770 CSettingBool *usemediacodec = (CSettingBool*)setting;
1771 usemediacodec->SetValue(false);
1774 else if (settingId == "videoplayer.usestagefright")
1776 CSettingBool *usestagefright = (CSettingBool*)setting;
1777 usestagefright->SetValue(false);
1784 bool CApplication::OnSettingsSaving() const
1786 // don't save settings when we're busy stopping the application
1787 // a lot of screens try to save settings on deinit and deinit is
1788 // called for every screen when the application is stopping
1795 void CApplication::ReloadSkin(bool confirm/*=false*/)
1797 m_skinReloading = false;
1798 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1800 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1801 g_windowManager.SendMessage(msg);
1803 // Reload the skin, restoring the previously focused control. We need this as
1804 // the window unload will reset all control states.
1806 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1808 iCtrlID = pWindow->GetFocusedControlID();
1810 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1814 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1815 if (pWindow && pWindow->HasSaveLastControl())
1817 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1818 pWindow->OnMessage(msg3);
1822 if (!m_skinReverting && confirm)
1825 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1827 m_skinReverting = true;
1828 if (oldSkin.empty())
1829 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1831 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1835 m_skinReverting = false;
1838 bool CApplication::Load(const TiXmlNode *settings)
1840 if (settings == NULL)
1843 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1844 if (audioElement != NULL)
1846 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1847 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1848 m_volumeLevel = VOLUME_MAXIMUM;
1854 bool CApplication::Save(TiXmlNode *settings) const
1856 if (settings == NULL)
1859 TiXmlElement volumeNode("audio");
1860 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1861 if (audioNode == NULL)
1864 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1865 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1870 bool CApplication::LoadSkin(const CStdString& skinID)
1872 if (m_skinReloading)
1876 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1878 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1884 void CApplication::LoadSkin(const SkinPtr& skin)
1886 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1889 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1890 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1895 if (!skin->HasSkinFile("Home.xml"))
1897 // failed to find home.xml
1898 // fallback to default skin
1899 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1901 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1902 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1903 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1908 bool bPreviousPlayingState=false;
1909 bool bPreviousRenderingState=false;
1910 if (g_application.m_pPlayer->IsPlayingVideo())
1912 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1913 if (bPreviousPlayingState)
1914 g_application.m_pPlayer->Pause();
1915 #ifdef HAS_VIDEO_PLAYBACK
1916 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1918 g_windowManager.ActivateWindow(WINDOW_HOME);
1919 bPreviousRenderingState = true;
1923 // close the music and video overlays (they're re-opened automatically later)
1924 CSingleLock lock(g_graphicsContext);
1926 // save the current window details
1927 int currentWindow = g_windowManager.GetActiveWindow();
1928 vector<int> currentModelessWindows;
1929 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1933 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1935 g_SkinInfo->Start();
1937 CLog::Log(LOGINFO, " load fonts for skin...");
1938 g_graphicsContext.SetMediaDir(skin->Path());
1939 g_directoryCache.ClearSubPaths(skin->Path());
1940 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1942 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1943 CStdString strFontSet;
1944 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1946 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1947 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1948 CSettings::Get().Save();
1951 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1953 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1955 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1957 // load in the skin strings
1958 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1959 URIUtils::AddSlashAtEnd(langPath);
1961 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1963 g_SkinInfo->LoadIncludes();
1966 start = CurrentHostCounter();
1968 CLog::Log(LOGINFO, " load new skin...");
1970 // Load the user windows
1974 end = CurrentHostCounter();
1975 freq = CurrentHostFrequency();
1976 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1978 CLog::Log(LOGINFO, " initialize new skin...");
1979 g_windowManager.AddMsgTarget(this);
1980 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1981 g_windowManager.AddMsgTarget(&g_infoManager);
1982 g_windowManager.AddMsgTarget(&g_fontManager);
1983 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1984 g_windowManager.SetCallback(*this);
1985 g_windowManager.Initialize();
1986 CTextureCache::Get().Initialize();
1987 g_audioManager.Enable(true);
1988 g_audioManager.Load();
1990 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1991 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1993 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1994 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1995 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1996 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1997 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2000 CLog::Log(LOGINFO, " skin loaded...");
2002 // leave the graphics lock
2006 if (currentWindow != WINDOW_INVALID)
2008 g_windowManager.ActivateWindow(currentWindow);
2009 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2011 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2012 if (dialog) dialog->Show();
2016 if (g_application.m_pPlayer->IsPlayingVideo())
2018 if (bPreviousPlayingState)
2019 g_application.m_pPlayer->Pause();
2020 if (bPreviousRenderingState)
2021 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2025 void CApplication::UnloadSkin(bool forReload /* = false */)
2027 m_skinReloading = forReload;
2029 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2031 g_audioManager.Enable(false);
2033 g_windowManager.DeInitialize();
2034 CTextureCache::Get().Deinitialize();
2036 // remove the skin-dependent window
2037 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2039 g_TextureManager.Cleanup();
2040 g_largeTextureManager.CleanupUnusedImages(true);
2042 g_fontManager.Clear();
2044 g_colorManager.Clear();
2046 g_infoManager.Clear();
2048 // The g_SkinInfo boost shared_ptr ought to be reset here
2049 // but there are too many places it's used without checking for NULL
2050 // and as a result a race condition on exit can cause a crash.
2053 bool CApplication::LoadUserWindows()
2055 // Start from wherever home.xml is
2056 std::vector<CStdString> vecSkinPath;
2057 g_SkinInfo->GetSkinPaths(vecSkinPath);
2058 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2060 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2061 CFileItemList items;
2062 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2064 for (int i = 0; i < items.Size(); ++i)
2066 if (items[i]->m_bIsFolder)
2068 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2069 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2071 CXBMCTinyXML xmlDoc;
2072 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2074 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2078 // Root element should be <window>
2079 TiXmlElement* pRootElement = xmlDoc.RootElement();
2080 CStdString strValue = pRootElement->Value();
2081 if (!strValue.Equals("window"))
2083 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2087 // Read the <type> element to get the window type to create
2088 // If no type is specified, create a CGUIWindow as default
2089 CGUIWindow* pWindow = NULL;
2091 if (pRootElement->Attribute("type"))
2092 strType = pRootElement->Attribute("type");
2095 const TiXmlNode *pType = pRootElement->FirstChild("type");
2096 if (pType && pType->FirstChild())
2097 strType = pType->FirstChild()->Value();
2099 int id = WINDOW_INVALID;
2100 if (!pRootElement->Attribute("id", &id))
2102 const TiXmlNode *pType = pRootElement->FirstChild("id");
2103 if (pType && pType->FirstChild())
2104 id = atol(pType->FirstChild()->Value());
2106 CStdString visibleCondition;
2107 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2109 if (strType.Equals("dialog"))
2110 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2111 else if (strType.Equals("submenu"))
2112 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2113 else if (strType.Equals("buttonmenu"))
2114 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2116 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2118 // Check to make sure the pointer isn't still null
2119 if (pWindow == NULL)
2121 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2124 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2129 pWindow->SetVisibleCondition(visibleCondition);
2130 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2131 g_windowManager.AddCustomWindow(pWindow);
2139 bool CApplication::RenderNoPresent()
2143 // DXMERGE: This may have been important?
2144 // g_graphicsContext.AcquireCurrentContext();
2146 g_graphicsContext.Lock();
2148 // dont show GUI when playing full screen video
2149 if (g_graphicsContext.IsFullScreenVideo())
2151 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2152 g_renderManager.Render(true, 0, 255);
2154 // close window overlays
2155 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2156 if (overlay) overlay->Close(true);
2157 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2158 if (overlay) overlay->Close(true);
2162 bool hasRendered = g_windowManager.Render();
2164 g_graphicsContext.Unlock();
2169 float CApplication::GetDimScreenSaverLevel() const
2171 if (!m_bScreenSave || !m_screenSaver ||
2172 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2173 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2174 !m_screenSaver->ID().empty()))
2177 if (!m_screenSaver->GetSetting("level").empty())
2178 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2182 void CApplication::Render()
2184 // do not render if we are stopped or in background
2185 if (m_bStop || m_bInBackground)
2190 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2192 bool hasRendered = false;
2193 bool limitFrames = false;
2194 unsigned int singleFrameTime = 10; // default limit 100 fps
2198 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2199 // Whether externalplayer is playing and we're unfocused
2200 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2202 m_bPresentFrame = false;
2203 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2205 m_bPresentFrame = g_renderManager.FrameWait(100);
2210 // engage the frame limiter as needed
2211 limitFrames = lowfps || extPlayerActive;
2212 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2213 // perhaps allowing it to be set differently than the UI option??
2214 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2215 limitFrames = true; // not using vsync.
2216 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2217 limitFrames = true; // using vsync, but it isn't working.
2221 if (extPlayerActive)
2223 ResetScreenSaver(); // Prevent screensaver dimming the screen
2224 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2227 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2233 CSingleLock lock(g_graphicsContext);
2234 g_infoManager.UpdateFPS();
2236 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2237 g_Windowing.SetVSync(true);
2238 else if (vsync_mode == VSYNC_ALWAYS)
2239 g_Windowing.SetVSync(true);
2240 else if (vsync_mode != VSYNC_DRIVER)
2241 g_Windowing.SetVSync(false);
2243 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2246 if(!g_Windowing.BeginRender())
2249 g_renderManager.FrameMove();
2251 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2252 if(g_graphicsContext.GetStereoMode())
2254 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2255 if(RenderNoPresent())
2258 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2260 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2261 if(RenderNoPresent())
2264 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2268 if(RenderNoPresent())
2272 g_renderManager.FrameFinish();
2274 g_Windowing.EndRender();
2276 // execute post rendering actions (finalize window closing)
2277 g_windowManager.AfterRender();
2279 // reset our info cache - we do this at the end of Render so that it is
2280 // fresh for the next process(), or after a windowclose animation (where process()
2282 g_infoManager.ResetCache();
2285 unsigned int now = XbmcThreads::SystemClockMillis();
2287 m_lastRenderTime = now;
2289 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2290 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2292 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2293 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2297 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2298 if (limitFrames || !flip)
2301 singleFrameTime = 40; //if not flipping, loop at 25 fps
2303 unsigned int frameTime = now - m_lastFrameTime;
2304 if (frameTime < singleFrameTime)
2305 Sleep(singleFrameTime - frameTime);
2307 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2310 g_graphicsContext.Flip(dirtyRegions);
2311 CTimeUtils::UpdateFrameTime(flip);
2313 g_renderManager.UpdateResolution();
2314 g_renderManager.ManageCaptures();
2317 void CApplication::SetStandAlone(bool value)
2319 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2322 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2323 // The window manager will return true if the event is processed, false otherwise.
2324 // If not already processed, this routine handles global keypresses. It returns
2325 // true if the key has been processed, false otherwise.
2327 bool CApplication::OnKey(const CKey& key)
2330 // Turn the mouse off, as we've just got a keypress from controller or remote
2331 g_Mouse.SetActive(false);
2333 // get the current active window
2334 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2336 // this will be checked for certain keycodes that need
2337 // special handling if the screensaver is active
2338 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2340 // a key has been pressed.
2342 m_idleTimer.StartZero();
2343 bool processKey = AlwaysProcess(action);
2345 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2349 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2350 // do not wake up the screensaver right after switching off the playing device
2351 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2352 ret = CApplicationMessenger::Get().CECToggleState();
2354 ret = CApplicationMessenger::Get().CECStandby();
2355 if (!ret) /* display is switched off */
2361 // allow some keys to be processed while the screensaver is active
2362 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2364 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2368 // change this if we have a dialog up
2369 if (g_windowManager.HasModalDialog())
2371 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2373 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2374 { // fullscreen info dialog - special case
2375 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2377 if (!key.IsAnalogButton())
2378 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2380 if (OnAction(action))
2383 // fallthrough to the main window
2384 iWin = WINDOW_FULLSCREEN_VIDEO;
2386 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2388 // current active window is full screen video.
2389 if (g_application.m_pPlayer->IsInMenu())
2391 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2392 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2394 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2396 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2397 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2399 // if no PVR specific action/mapping is found, fall back to default
2400 if (action.GetID() == 0)
2401 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2405 // in any other case use the fullscreen window section of keymap.xml to map key->action
2406 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2411 // current active window isnt the fullscreen window
2412 // just use corresponding section from keymap.xml
2413 // to map key->action
2415 // first determine if we should use keyboard input directly
2416 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2417 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2420 CGUIControl *control = window->GetFocusedControl();
2423 // If this is an edit control set usekeyboard to true. This causes the
2424 // keypress to be processed directly not through the key mappings.
2425 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2428 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2429 // This causes the keypress to be used for list navigation.
2430 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2436 action = CAction(0); // reset our action
2437 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2439 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2440 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2441 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2442 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2443 action.GetID() == ACTION_MOVE_RIGHT ||
2444 action.GetID() == ACTION_MOVE_UP ||
2445 action.GetID() == ACTION_MOVE_DOWN ||
2446 action.GetID() == ACTION_SELECT_ITEM ||
2447 action.GetID() == ACTION_ENTER ||
2448 action.GetID() == ACTION_PREVIOUS_MENU ||
2449 action.GetID() == ACTION_NAV_BACK))
2451 // the action isn't plain navigation - check for a keyboard-specific keymap
2452 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2453 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2454 action.GetID() == ACTION_BACKSPACE ||
2455 action.GetID() == ACTION_SHIFT ||
2456 action.GetID() == ACTION_SYMBOLS ||
2457 action.GetID() == ACTION_CURSOR_LEFT ||
2458 action.GetID() == ACTION_CURSOR_RIGHT)
2459 action = CAction(0); // don't bother with this action
2462 if (!action.GetID())
2464 // keyboard entry - pass the keys through directly
2465 if (key.GetFromService())
2466 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2469 // Check for paste keypress
2470 #ifdef TARGET_WINDOWS
2471 // In Windows paste is ctrl-V
2472 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2473 #elif defined(TARGET_LINUX)
2474 // In Linux paste is ctrl-V
2475 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2476 #elif defined(TARGET_DARWIN_OSX)
2477 // In OSX paste is cmd-V
2478 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2480 // Placeholder for other operating systems
2483 action = CAction(ACTION_PASTE);
2484 // If the unicode is non-zero the keypress is a non-printing character
2485 else if (key.GetUnicode())
2486 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2487 // The keypress is a non-printing character
2489 action = CAction(key.GetVKey() | KEY_VKEY);
2493 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2495 if (OnAction(action))
2497 // failed to handle the keyboard action, drop down through to standard action
2499 if (key.GetFromService())
2501 if (key.GetButtonCode() != KEY_INVALID)
2502 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2505 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2507 if (!key.IsAnalogButton())
2508 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2510 return ExecuteInputAction(action);
2513 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2514 // This needs to return true if it processed the appcommand or false if it didn't
2515 bool CApplication::OnAppCommand(const CAction &action)
2517 // Reset the screen saver
2520 // If we were currently in the screen saver wake up and don't process the appcommand
2521 if (WakeUpScreenSaverAndDPMS())
2524 // The action ID is the APPCOMMAND code. We need to retrieve the action
2525 // associated with this appcommand from the mapping table.
2526 uint32_t appcmd = action.GetID();
2527 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2528 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2529 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2531 // If we couldn't find an action return false to indicate we have not
2532 // handled this appcommand
2533 if (!appcmdaction.GetID())
2535 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2539 // Process the appcommand
2540 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2541 OnAction(appcmdaction);
2543 // Always return true regardless of whether the action succeeded or not.
2544 // This stops Windows handling the appcommand itself.
2548 bool CApplication::OnAction(const CAction &action)
2550 // special case for switching between GUI & fullscreen mode.
2551 if (action.GetID() == ACTION_SHOW_GUI)
2552 { // Switch to fullscreen mode if we can
2553 if (SwitchToFullScreen())
2555 m_navigationTimer.StartZero();
2560 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2562 g_graphicsContext.ToggleFullScreenRoot();
2566 if (action.IsMouse())
2567 g_Mouse.SetActive(true);
2570 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2572 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2574 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2576 CGUIDialogVideoBookmarks::OnAddBookmark();
2579 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2580 // playing or ACTION_PLAYER_PLAY if we are not playing.
2581 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2583 if (m_pPlayer->IsPlaying())
2584 return OnAction(CAction(ACTION_PAUSE));
2586 return OnAction(CAction(ACTION_PLAYER_PLAY));
2589 //if the action would start or stop inertial scrolling
2590 //by gesture - bypass the normal OnAction handler of current window
2591 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2594 // just pass the action to the current window and let it handle it
2595 if (g_windowManager.OnAction(action))
2597 m_navigationTimer.StartZero();
2602 // handle extra global presses
2604 // screenshot : take a screenshot :)
2605 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2607 CScreenShot::TakeScreenshot();
2610 // built in functions : execute the built-in
2611 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2613 CBuiltins::Execute(action.GetName());
2614 m_navigationTimer.StartZero();
2619 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2621 CButtonTranslator::GetInstance().Clear();
2622 CButtonTranslator::GetInstance().Load();
2625 // show info : Shows the current video or song information
2626 if (action.GetID() == ACTION_SHOW_INFO)
2628 g_infoManager.ToggleShowInfo();
2632 // codec info : Shows the current song, video or picture codec information
2633 if (action.GetID() == ACTION_SHOW_CODEC)
2635 g_infoManager.ToggleShowCodec();
2639 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2641 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2644 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2645 char rating = tag->GetRating();
2646 bool needsUpdate(false);
2647 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2649 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2652 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2654 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2660 if (db.Open()) // OpenForWrite() ?
2662 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2665 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2666 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2667 g_windowManager.SendMessage(msg);
2673 // Now check with the playlist player if action can be handled.
2674 // 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.
2675 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2677 if (g_playlistPlayer.OnAction(action))
2681 // Now check with the player if action can be handled.
2682 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2683 (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)) ||
2684 action.GetID() == ACTION_STOP)
2686 if (m_pPlayer->OnAction(action))
2690 // stop : stops playing current audio song
2691 if (action.GetID() == ACTION_STOP)
2697 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2698 // If so, we just jump to the start of the track.
2699 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2702 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2706 // forward action to g_PVRManager and break if it was able to handle it
2707 if (g_PVRManager.OnAction(action))
2710 // forward action to graphic context and see if it can handle it
2711 if (CStereoscopicsManager::Get().OnAction(action))
2714 if (m_pPlayer->IsPlaying())
2716 // forward channel switches to the player - he knows what to do
2717 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2719 m_pPlayer->OnAction(action);
2723 // pause : pauses current audio song
2724 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2728 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2730 if (!m_pPlayer->IsPaused())
2731 { // unpaused - set the playspeed back to normal
2732 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2734 g_audioManager.Enable(m_pPlayer->IsPaused());
2737 if (!m_pPlayer->IsPaused())
2739 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2740 // if we are playing at normal speed, then allow play to pause
2741 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2743 if (m_pPlayer->GetPlaySpeed() != 1)
2745 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2753 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2755 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2756 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2758 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2760 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2765 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2767 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2770 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2773 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2775 // calculate the speed based on the amount the button is held down
2776 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2777 // returns 0 -> MAX_FFWD_SPEED
2778 int iSpeed = 1 << iPower;
2779 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2781 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2783 CLog::Log(LOGDEBUG,"Resetting playspeed");
2787 // allow play to unpause
2790 if (action.GetID() == ACTION_PLAYER_PLAY)
2792 // unpause, and set the playspeed back to normal
2794 g_audioManager.Enable(m_pPlayer->IsPaused());
2796 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2801 // record current file
2802 if (action.GetID() == ACTION_RECORD)
2804 if (m_pPlayer->CanRecord())
2805 m_pPlayer->Record(!m_pPlayer->IsRecording());
2808 if (m_playerController->OnAction(action))
2813 if (action.GetID() == ACTION_SWITCH_PLAYER)
2815 if(m_pPlayer->IsPlaying())
2817 VECPLAYERCORES cores;
2818 CFileItem item(*m_itemCurrentFile.get());
2819 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2820 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2821 if(core != EPC_NONE)
2823 g_application.m_eForcedNextPlayer = core;
2824 item.m_lStartOffset = (int)(GetTime() * 75);
2825 PlayFile(item, true);
2830 VECPLAYERCORES cores;
2831 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2832 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2833 if(core != EPC_NONE)
2836 g_application.m_eForcedNextPlayer = core;
2837 PlayFile(item, false);
2842 if (g_peripherals.OnAction(action))
2845 if (action.GetID() == ACTION_MUTE)
2851 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2853 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2854 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2856 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2858 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2859 g_windowManager.SendMessage(msg);
2864 // Check for global volume control
2865 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2867 if (!m_pPlayer->IsPassthrough())
2871 float volume = m_volumeLevel;
2872 // Android has steps based on the max available volume level
2873 #if defined(TARGET_ANDROID)
2874 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2876 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2878 if (action.GetRepeat())
2879 step *= action.GetRepeat() * 50; // 50 fps
2881 if (action.GetID() == ACTION_VOLUME_UP)
2882 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2884 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2885 SetVolume(volume, false);
2887 // show visual feedback of volume change...
2888 ShowVolumeBar(&action);
2891 // Check for global seek control
2892 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2894 if (!m_pPlayer->CanSeek()) return false;
2895 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2898 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2900 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2901 CGUIControlProfiler::Instance().Start();
2904 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2906 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2907 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2908 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2909 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2910 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2916 void CApplication::FrameMove(bool processEvents, bool processGUI)
2922 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2923 float frameTime = m_frameTime.GetElapsedSeconds();
2924 m_frameTime.StartZero();
2925 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2926 if( frameTime > 0.5 ) frameTime = 0.5;
2928 if (processGUI && m_renderGUI)
2930 g_graphicsContext.Lock();
2931 // check if there are notifications to display
2932 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2933 if (toast && toast->DoWork())
2935 if (!toast->IsDialogRunning())
2940 g_graphicsContext.Unlock();
2942 CWinEvents::MessagePump();
2944 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2945 // Read the input from a remote
2946 g_RemoteControl.Update();
2949 // process input actions
2950 ProcessRemote(frameTime);
2951 ProcessGamepad(frameTime);
2952 ProcessEventServer(frameTime);
2953 ProcessPeripherals(frameTime);
2954 if (processGUI && m_renderGUI)
2956 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2957 m_seekHandler->Process();
2960 if (processGUI && m_renderGUI)
2963 g_windowManager.Process(CTimeUtils::GetFrameTime());
2964 g_windowManager.FrameMove();
2968 bool CApplication::ProcessGamepad(float frameTime)
2970 #ifdef HAS_SDL_JOYSTICK
2974 int iWin = GetActiveWindowID();
2976 g_Joystick.Update();
2977 if (g_Joystick.GetButton(bid))
2980 m_idleTimer.StartZero();
2983 if (WakeUpScreenSaverAndDPMS())
2985 g_Joystick.Reset(true);
2990 CStdString actionName;
2992 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2994 CAction action(actionID, 1.0f, 0.0f, actionName);
2996 g_Mouse.SetActive(false);
2997 return ExecuteInputAction(action);
3004 if (g_Joystick.GetAxis(bid))
3006 if (g_Joystick.GetAmount() < 0)
3012 CStdString actionName;
3014 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3017 if (WakeUpScreenSaverAndDPMS())
3022 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3024 g_Mouse.SetActive(false);
3025 return ExecuteInputAction(action);
3029 g_Joystick.ResetAxis(abs(bid));
3033 if (g_Joystick.GetHat(bid, position))
3036 m_idleTimer.StartZero();
3039 if (WakeUpScreenSaverAndDPMS())
3046 CStdString actionName;
3049 bid = position<<16|bid;
3051 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3053 CAction action(actionID, 1.0f, 0.0f, actionName);
3055 g_Mouse.SetActive(false);
3056 return ExecuteInputAction(action);
3063 bool CApplication::ProcessRemote(float frameTime)
3065 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3066 if (g_RemoteControl.GetButton())
3068 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3069 g_RemoteControl.Reset();
3076 bool CApplication::ProcessPeripherals(float frameTime)
3079 if (g_peripherals.GetNextKeypress(frameTime, key))
3084 bool CApplication::ProcessMouse()
3088 if (!g_Mouse.IsActive() || !m_AppFocused)
3091 // Get the mouse command ID
3092 uint32_t mousecommand = g_Mouse.GetAction();
3093 if (mousecommand == ACTION_NOOP)
3096 // Reset the screensaver and idle timers
3097 m_idleTimer.StartZero();
3099 if (WakeUpScreenSaverAndDPMS())
3102 // Retrieve the corresponding action
3103 int iWin = GetActiveWindowID();
3104 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3105 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3107 // Deactivate mouse if non-mouse action
3108 if (!mouseaction.IsMouse())
3109 g_Mouse.SetActive(false);
3111 // Consume ACTION_NOOP.
3112 // Some views or dialogs gets closed after any ACTION and
3113 // a sensitive mouse might cause problems.
3114 if (mouseaction.GetID() == ACTION_NOOP)
3117 // If we couldn't find an action return false to indicate we have not
3118 // handled this mouse action
3119 if (!mouseaction.GetID())
3121 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3125 // Log mouse actions except for move and noop
3126 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3127 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3129 // The action might not be a mouse action. For example wheel moves might
3130 // be mapped to volume up/down in mouse.xml. In this case we do not want
3131 // the mouse position saved in the action.
3132 if (!mouseaction.IsMouse())
3133 return OnAction(mouseaction);
3135 // This is a mouse action so we need to record the mouse position
3136 return OnAction(CAction(mouseaction.GetID(),
3137 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3138 (float)g_Mouse.GetX(),
3139 (float)g_Mouse.GetY(),
3140 (float)g_Mouse.GetDX(),
3141 (float)g_Mouse.GetDY(),
3142 mouseaction.GetName()));
3145 bool CApplication::ProcessEventServer(float frameTime)
3147 #ifdef HAS_EVENT_SERVER
3148 CEventServer* es = CEventServer::GetInstance();
3149 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3152 // process any queued up actions
3153 if (es->ExecuteNextAction())
3155 // reset idle timers
3156 m_idleTimer.StartZero();
3158 WakeUpScreenSaverAndDPMS();
3161 // now handle any buttons or axis
3162 std::string joystickName;
3163 bool isAxis = false;
3164 float fAmount = 0.0;
3166 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3167 // when the action exits XBMC
3168 es = CEventServer::GetInstance();
3169 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3171 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3175 if (joystickName.length() > 0)
3179 if (fabs(fAmount) >= 0.08)
3180 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3182 m_lastAxisMap[joystickName].erase(wKeyID);
3185 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3190 if (wKeyID & ES_FLAG_UNICODE)
3192 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3196 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3197 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3198 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3199 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3200 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3201 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3202 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3203 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3204 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3205 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3206 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3207 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3208 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3209 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3210 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3211 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3213 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3214 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3215 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3218 key.SetFromService(true);
3223 if (m_lastAxisMap.size() > 0)
3225 // Process all the stored axis.
3226 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3228 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3229 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3235 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3237 XBMC_Event newEvent;
3238 newEvent.type = XBMC_MOUSEMOTION;
3239 newEvent.motion.xrel = 0;
3240 newEvent.motion.yrel = 0;
3241 newEvent.motion.state = 0;
3242 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3243 newEvent.motion.x = (uint16_t)pos.x;
3244 newEvent.motion.y = (uint16_t)pos.y;
3245 OnEvent(newEvent); // had to call this to update g_Mouse position
3246 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3253 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3255 #if defined(HAS_EVENT_SERVER)
3256 m_idleTimer.StartZero();
3258 // Make sure to reset screen saver, mouse.
3260 if (WakeUpScreenSaverAndDPMS())
3263 #ifdef HAS_SDL_JOYSTICK
3266 g_Mouse.SetActive(false);
3268 int iWin = GetActiveWindowID();
3270 CStdString actionName;
3271 bool fullRange = false;
3273 // Translate using regular joystick translator.
3274 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3275 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3277 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3283 bool CApplication::ExecuteInputAction(const CAction &action)
3285 bool bResult = false;
3287 // play sound before the action unless the button is held,
3288 // where we execute after the action as held actions aren't fired every time.
3289 if(action.GetHoldTime())
3291 bResult = OnAction(action);
3293 g_audioManager.PlayActionSound(action);
3297 g_audioManager.PlayActionSound(action);
3298 bResult = OnAction(action);
3303 int CApplication::GetActiveWindowID(void)
3305 // Get the currently active window
3306 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3308 // If there is a dialog active get the dialog id instead
3309 if (g_windowManager.HasModalDialog())
3310 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3312 // If the window is FullScreenVideo check for special cases
3313 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3315 // check if we're in a DVD menu
3316 if(g_application.m_pPlayer->IsInMenu())
3317 iWin = WINDOW_VIDEO_MENU;
3318 // check for LiveTV and switch to it's virtual window
3319 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3320 iWin = WINDOW_FULLSCREEN_LIVETV;
3323 // Return the window id
3327 bool CApplication::Cleanup()
3331 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3332 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3333 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3334 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3335 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3336 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3337 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3338 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3339 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3340 g_windowManager.Delete(WINDOW_FILES);
3341 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3342 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3343 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3344 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3345 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3346 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3347 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3348 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3349 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3350 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3351 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3352 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3353 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3354 g_windowManager.Delete(WINDOW_DIALOG_OK);
3355 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3356 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3357 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3358 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3359 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3360 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3361 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3362 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3363 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3364 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3365 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3366 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3367 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3368 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3369 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3370 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3371 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3372 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3373 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3374 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3375 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3376 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3377 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3379 /* Delete PVR related windows and dialogs */
3380 g_windowManager.Delete(WINDOW_PVR);
3381 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3382 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3383 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3387 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3388 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3389 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3390 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3391 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3392 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3393 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3395 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3396 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3397 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3398 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3399 g_windowManager.Delete(WINDOW_VISUALISATION);
3400 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3401 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3402 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3403 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3404 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3405 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3406 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3407 g_windowManager.Delete(WINDOW_SCREENSAVER);
3408 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3409 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3410 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3411 g_windowManager.Delete(WINDOW_SLIDESHOW);
3412 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3413 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3415 g_windowManager.Delete(WINDOW_HOME);
3416 g_windowManager.Delete(WINDOW_PROGRAMS);
3417 g_windowManager.Delete(WINDOW_PICTURES);
3418 g_windowManager.Delete(WINDOW_WEATHER);
3420 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3421 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3422 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3423 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3424 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3425 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3426 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3427 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3428 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3429 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3431 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3432 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3434 CAddonMgr::Get().DeInit();
3436 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3437 CLog::Log(LOGNOTICE, "closing down remote control service");
3438 g_RemoteControl.Disconnect();
3441 CLog::Log(LOGNOTICE, "unload sections");
3443 #ifdef HAS_PERFORMANCE_SAMPLE
3444 CLog::Log(LOGNOTICE, "performance statistics");
3445 m_perfStats.DumpStats();
3448 // Shutdown as much as possible of the
3449 // application, to reduce the leaks dumped
3450 // to the vc output window before calling
3451 // _CrtDumpMemoryLeaks(). Most of the leaks
3452 // shown are no real leaks, as parts of the app
3453 // are still allocated.
3455 g_localizeStrings.Clear();
3456 g_LangCodeExpander.Clear();
3457 g_charsetConverter.clear();
3458 g_directoryCache.Clear();
3459 CButtonTranslator::GetInstance().Clear();
3460 #ifdef HAS_EVENT_SERVER
3461 CEventServer::RemoveInstance();
3463 DllLoaderContainer::Clear();
3464 g_playlistPlayer.Clear();
3465 CSettings::Get().Uninitialize();
3466 g_advancedSettings.Clear();
3469 CXHandle::DumpObjectTracker();
3471 #ifdef HAS_DVD_DRIVE
3472 CLibcdio::ReleaseInstance();
3475 #if defined(TARGET_ANDROID)
3476 // enable for all platforms once it's safe
3477 g_sectionLoader.UnloadAll();
3479 #ifdef _CRTDBG_MAP_ALLOC
3480 _CrtDumpMemoryLeaks();
3481 while(1); // execution ends
3491 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3496 void CApplication::Stop(int exitCode)
3500 CVariant vExitCode(exitCode);
3501 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3503 SaveFileState(true);
3505 g_alarmClock.StopThread();
3507 if( m_bSystemScreenSaverEnable )
3508 g_Windowing.EnableSystemScreenSaver(true);
3510 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3511 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3513 // Update the settings information (volume, uptime etc. need saving)
3514 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3516 CLog::Log(LOGNOTICE, "Saving settings");
3517 CSettings::Get().Save();
3520 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3523 m_AppFocused = false;
3524 m_ExitCode = exitCode;
3525 CLog::Log(LOGNOTICE, "stop all");
3527 // cancel any jobs from the jobmanager
3528 CJobManager::GetInstance().CancelJobs();
3530 // stop scanning before we kill the network and so on
3531 if (m_musicInfoScanner->IsScanning())
3532 m_musicInfoScanner->Stop();
3534 if (m_videoInfoScanner->IsScanning())
3535 m_videoInfoScanner->Stop();
3537 CApplicationMessenger::Get().Cleanup();
3539 CLog::Log(LOGNOTICE, "stop player");
3540 m_pPlayer->ClosePlayer();
3546 #if HAS_FILESYTEM_DAAP
3547 CLog::Log(LOGNOTICE, "stop daap clients");
3548 g_DaapClient.Release();
3550 #ifdef HAS_FILESYSTEM_SAP
3551 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3552 g_sapsessions.StopThread();
3555 if(CZeroconfBrowser::IsInstantiated())
3557 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3558 CZeroconfBrowser::GetInstance()->Stop();
3559 CZeroconfBrowser::ReleaseInstance();
3563 CLog::Log(LOGNOTICE, "clean cached files!");
3564 #ifdef HAS_FILESYSTEM_RAR
3565 g_RarManager.ClearCache(true);
3568 #ifdef HAS_FILESYSTEM_SFTP
3569 CSFTPSessionManager::DisconnectAllSessions();
3572 CLog::Log(LOGNOTICE, "unload skin");
3575 #if defined(TARGET_DARWIN_OSX)
3576 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3577 XBMCHelper::GetInstance().Stop();
3580 #if defined(HAVE_LIBCRYSTALHD)
3581 CCrystalHD::RemoveInstance();
3584 g_mediaManager.Stop();
3586 // Stop services before unloading Python
3587 CAddonMgr::Get().StopServices(false);
3589 // stop all remaining scripts; must be done after skin has been unloaded,
3590 // not before some windows still need it when deinitializing during skin
3592 CScriptInvocationManager::Get().Uninitialize();
3594 g_Windowing.DestroyRenderSystem();
3595 g_Windowing.DestroyWindow();
3596 g_Windowing.DestroyWindowSystem();
3598 // shutdown the AudioEngine
3599 CAEFactory::Shutdown();
3600 CAEFactory::UnLoadEngine();
3602 CLog::Log(LOGNOTICE, "stopped");
3606 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3609 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3610 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3617 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3619 //If item is a plugin, expand out now and run ourselves again
3620 if (item.IsPlugin())
3622 CFileItem item_new(item);
3623 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3624 return PlayMedia(item_new, iPlaylist);
3627 if (item.IsSmartPlayList())
3629 CFileItemList items;
3630 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3633 CSmartPlaylist smartpl;
3634 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3635 smartpl.OpenAndReadName(item.GetPath());
3637 playlist.Add(items);
3638 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3641 else if (item.IsPlayList() || item.IsInternetStream())
3643 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3645 //is or could be a playlist
3646 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3647 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3652 if (dlgCache->IsCanceled())
3659 if (iPlaylist != PLAYLIST_NONE)
3662 if (item.HasProperty("playlist_starting_track"))
3663 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3664 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3668 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());
3669 if(pPlayList->size())
3670 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3675 //nothing special just play
3676 return PlayFile(item, false) == PLAYBACK_OK;
3680 // For playing a multi-file video. Particularly inefficient
3681 // on startup, as we are required to calculate the length
3682 // of each video, so we open + close each one in turn.
3683 // A faster calculation of video time would improve this
3685 // return value: same with PlayFile()
3686 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3688 if (!item.IsStack())
3689 return PLAYBACK_FAIL;
3693 // case 1: stacked ISOs
3694 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3696 CStackDirectory dir;
3697 CFileItemList movieList;
3698 dir.GetDirectory(item.GetPath(), movieList);
3700 // first assume values passed to the stack
3701 int selectedFile = item.m_lStartPartNumber;
3702 int startoffset = item.m_lStartOffset;
3704 // check if we instructed the stack to resume from default
3705 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3710 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3712 startoffset = (int)(bookmark.timeInSeconds*75);
3713 selectedFile = bookmark.partNumber;
3718 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3721 // make sure that the selected part is within the boundaries
3722 if (selectedFile <= 0)
3724 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3727 else if (selectedFile > movieList.Size())
3729 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3730 selectedFile = movieList.Size();
3733 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3734 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3735 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3736 *m_stackFileItemToUpdate = item;
3737 return PlayFile(*(movieList[selectedFile - 1]));
3739 // case 2: all other stacks
3742 // see if we have the info in the database
3743 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3744 // then these times will be wrong.
3745 // Also, this is really just a hack for the slow load up times we have
3746 // A much better solution is a fast reader of FPS and fileLength
3747 // that we can use on a file to get it's time.
3749 bool haveTimes(false);
3753 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3754 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3759 // calculate the total time of the stack
3760 CStackDirectory dir;
3761 dir.GetDirectory(item.GetPath(), *m_currentStack);
3763 for (int i = 0; i < m_currentStack->Size(); i++)
3766 (*m_currentStack)[i]->m_lEndOffset = times[i];
3770 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3772 m_currentStack->Clear();
3773 return PLAYBACK_FAIL;
3775 totalTime += duration / 1000;
3776 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3777 times.push_back(totalTime);
3781 double seconds = item.m_lStartOffset / 75.0;
3783 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3784 { // have our times now, so update the dB
3788 dbs.SetStackTimes(item.GetPath(), times);
3790 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3792 // can only resume seek here, not dvdstate
3794 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3795 seconds = bookmark.timeInSeconds;
3803 *m_itemCurrentFile = item;
3804 m_currentStackPosition = 0;
3805 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3809 // work out where to seek to
3810 for (int i = 0; i < m_currentStack->Size(); i++)
3812 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3814 CFileItem item(*(*m_currentStack)[i]);
3815 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3816 item.m_lStartOffset = (long)(seconds - start) * 75;
3817 m_currentStackPosition = i;
3818 return PlayFile(item, true);
3823 return PlayFile(*(*m_currentStack)[0], true);
3825 return PLAYBACK_FAIL;
3828 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3830 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3831 if (item.GetMimeType().empty())
3832 const_cast<CFileItem&>(item).FillInMimeType();
3836 SaveCurrentFileSettings();
3838 OutputDebugString("new file set audiostream:0\n");
3839 // Switch to default options
3840 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3841 // see if we have saved options in the database
3843 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3844 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3846 *m_itemCurrentFile = item;
3847 m_nextPlaylistItem = -1;
3848 m_currentStackPosition = 0;
3849 m_currentStack->Clear();
3852 CUtil::ClearSubtitles();
3855 if (item.IsDiscStub())
3857 #ifdef HAS_DVD_DRIVE
3858 // Display the Play Eject dialog if there is any optical disc drive
3859 if (g_mediaManager.HasOpticalDrive())
3861 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3862 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3863 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3864 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3868 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3873 if (item.IsPlayList())
3874 return PLAYBACK_FAIL;
3876 if (item.IsPlugin())
3877 { // we modify the item so that it becomes a real URL
3878 CFileItem item_new(item);
3879 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3880 return PlayFile(item_new, false);
3881 return PLAYBACK_FAIL;
3885 if (URIUtils::IsUPnP(item.GetPath()))
3887 CFileItem item_new(item);
3888 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3889 return PlayFile(item_new, false);
3890 return PLAYBACK_FAIL;
3894 // if we have a stacked set of files, we need to setup our stack routines for
3895 // "seamless" seeking and total time of the movie etc.
3896 // will recall with restart set to true
3898 return PlayStack(item, bRestart);
3900 //Is TuxBox, this should probably be moved to CTuxBoxFile
3903 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3905 if(g_tuxboxService.IsRunning())
3906 g_tuxboxService.Stop();
3908 PlayBackRet ret = PLAYBACK_FAIL;
3910 if(g_tuxbox.CreateNewItem(item, item_new))
3913 // Make sure it doesn't have a player
3914 // so we actually select one normally
3915 m_pPlayer->ResetPlayer();
3917 // keep the tuxbox:// url as playing url
3918 // and give the new url to the player
3919 ret = PlayFile(item_new, true);
3920 if(ret == PLAYBACK_OK)
3922 if(!g_tuxboxService.IsRunning())
3923 g_tuxboxService.Start();
3929 CPlayerOptions options;
3931 if( item.HasProperty("StartPercent") )
3933 double fallback = 0.0f;
3934 if(item.GetProperty("StartPercent").isString())
3935 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3936 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3939 PLAYERCOREID eNewCore = EPC_NONE;
3942 // have to be set here due to playstack using this for starting the file
3943 options.starttime = item.m_lStartOffset / 75.0;
3944 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3945 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3947 if( m_eForcedNextPlayer != EPC_NONE )
3948 eNewCore = m_eForcedNextPlayer;
3949 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3950 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3952 eNewCore = m_pPlayer->GetCurrentPlayer();
3956 options.starttime = item.m_lStartOffset / 75.0;
3960 // open the d/b and retrieve the bookmarks for the current movie
3963 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3965 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3967 options.starttime = 0.0f;
3969 CStdString path = item.GetPath();
3970 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3971 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3972 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3973 path = item.GetProperty("original_listitem_url").asString();
3974 if(dbs.GetResumeBookMark(path, bookmark))
3976 options.starttime = bookmark.timeInSeconds;
3977 options.state = bookmark.playerState;
3980 override with information from the actual item if available. We do this as the VFS (eg plugins)
3981 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3982 should the playerState be required, it is fetched from the database.
3983 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3985 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3986 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3988 else if (item.HasVideoInfoTag())
3990 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3992 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3995 dbs.GetBookMarkForEpisode(*tag, bookmark);
3996 options.starttime = bookmark.timeInSeconds;
3997 options.state = bookmark.playerState;
4004 if (m_eForcedNextPlayer != EPC_NONE)
4005 eNewCore = m_eForcedNextPlayer;
4007 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4010 // this really aught to be inside !bRestart, but since PlayStack
4011 // uses that to init playback, we have to keep it outside
4012 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4013 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4014 { // playing from a playlist by the looks
4015 // don't switch to fullscreen if we are not playing the first item...
4016 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4018 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4020 // TODO - this will fail if user seeks back to first file in stack
4021 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4022 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4024 options.fullscreen = false;
4025 // reset this so we don't think we are resuming on seek
4026 m_itemCurrentFile->m_lStartOffset = 0;
4029 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4031 // reset VideoStartWindowed as it's a temp setting
4032 CMediaSettings::Get().SetVideoStartWindowed(false);
4035 //We have to stop parsing a cdg before mplayer is deallocated
4036 // WHY do we have to do this????
4038 m_pKaraokeMgr->Stop();
4042 CSingleLock lock(m_playStateMutex);
4043 // tell system we are starting a file
4044 m_bPlaybackStarting = true;
4046 // for playing a new item, previous playing item's callback may already
4047 // pushed some delay message into the threadmessage list, they are not
4048 // expected be processed after or during the new item playback starting.
4049 // so we clean up previous playing item's playback callback delay messages here.
4050 int previousMsgsIgnoredByNewPlaying[] = {
4051 GUI_MSG_PLAYBACK_STARTED,
4052 GUI_MSG_PLAYBACK_ENDED,
4053 GUI_MSG_PLAYBACK_STOPPED,
4054 GUI_MSG_PLAYLIST_CHANGED,
4055 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4056 GUI_MSG_PLAYLISTPLAYER_STARTED,
4057 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4058 GUI_MSG_QUEUE_NEXT_ITEM,
4061 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4063 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4066 // We should restart the player, unless the previous and next tracks are using
4067 // one of the players that allows gapless playback (paplayer, dvdplayer)
4068 m_pPlayer->ClosePlayerGapless(eNewCore);
4070 // now reset play state to starting, since we already stopped the previous playing item if there is.
4071 // and from now there should be no playback callback from previous playing item be called.
4072 m_ePlayState = PLAY_STATE_STARTING;
4074 m_pPlayer->CreatePlayer(eNewCore, *this);
4076 PlayBackRet iResult;
4077 if (m_pPlayer->HasPlayer())
4079 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4080 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4081 * increase performance on low powered systems (Atom/ARM).
4085 CJobManager::GetInstance().PauseJobs();
4088 // don't hold graphicscontext here since player
4089 // may wait on another thread, that requires gfx
4090 CSingleExit ex(g_graphicsContext);
4092 iResult = m_pPlayer->OpenFile(item, options);
4096 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4097 iResult = PLAYBACK_FAIL;
4100 if(iResult == PLAYBACK_OK)
4102 if (m_pPlayer->GetPlaySpeed() != 1)
4104 int iSpeed = m_pPlayer->GetPlaySpeed();
4105 m_pPlayer->m_iPlaySpeed = 1;
4106 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4109 // if player has volume control, set it.
4110 if (m_pPlayer->ControlsVolume())
4112 m_pPlayer->SetVolume(m_volumeLevel);
4113 m_pPlayer->SetMute(m_muted);
4116 if( m_pPlayer->IsPlayingAudio() )
4118 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4119 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4122 #ifdef HAS_VIDEO_PLAYBACK
4123 else if( m_pPlayer->IsPlayingVideo() )
4125 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4126 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4128 // if player didn't manange to switch to fullscreen by itself do it here
4129 if( options.fullscreen && g_renderManager.IsStarted()
4130 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4131 SwitchToFullScreen();
4136 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4137 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4138 g_windowManager.PreviousWindow();
4142 #if !defined(TARGET_POSIX)
4143 g_audioManager.Enable(false);
4146 if (item.HasPVRChannelInfoTag())
4147 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4150 CSingleLock lock(m_playStateMutex);
4151 m_bPlaybackStarting = false;
4153 if (iResult == PLAYBACK_OK)
4155 // play state: none, starting; playing; stopped; ended.
4156 // last 3 states are set by playback callback, they are all ignored during starting,
4157 // but we recorded the state, here we can make up the callback for the state.
4158 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4159 switch (m_ePlayState)
4161 case PLAY_STATE_PLAYING:
4162 OnPlayBackStarted();
4164 // FIXME: it seems no meaning to callback started here if there was an started callback
4165 // before this stopped/ended callback we recorded. if we callback started here
4166 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4167 // which will send OnStop announce at once, so currently, just call stopped/ended.
4168 case PLAY_STATE_ENDED:
4171 case PLAY_STATE_STOPPED:
4172 OnPlayBackStopped();
4174 case PLAY_STATE_STARTING:
4175 // neither started nor stopped/ended callback be called, that means the item still
4176 // not started, we need not make up any callback, just leave this and
4177 // let the player callback do its work.
4183 else if (iResult == PLAYBACK_FAIL)
4185 // we send this if it isn't playlistplayer that is doing this
4186 int next = g_playlistPlayer.GetNextSong();
4187 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4190 OnPlayBackStopped();
4191 m_ePlayState = PLAY_STATE_NONE;
4197 void CApplication::OnPlayBackEnded()
4199 CSingleLock lock(m_playStateMutex);
4200 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4201 m_ePlayState = PLAY_STATE_ENDED;
4202 if(m_bPlaybackStarting)
4205 // informs python script currently running playback has ended
4206 // (does nothing if python is not loaded)
4208 g_pythonParser.OnPlayBackEnded();
4211 CVariant data(CVariant::VariantTypeObject);
4213 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4215 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4216 g_windowManager.SendThreadMessage(msg);
4219 void CApplication::OnPlayBackStarted()
4221 CSingleLock lock(m_playStateMutex);
4222 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4223 m_ePlayState = PLAY_STATE_PLAYING;
4224 if(m_bPlaybackStarting)
4228 // informs python script currently running playback has started
4229 // (does nothing if python is not loaded)
4230 g_pythonParser.OnPlayBackStarted();
4233 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4234 g_windowManager.SendThreadMessage(msg);
4237 void CApplication::OnQueueNextItem()
4239 CSingleLock lock(m_playStateMutex);
4240 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4241 if(m_bPlaybackStarting)
4243 // informs python script currently running that we are requesting the next track
4244 // (does nothing if python is not loaded)
4246 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4249 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4250 g_windowManager.SendThreadMessage(msg);
4253 void CApplication::OnPlayBackStopped()
4255 CSingleLock lock(m_playStateMutex);
4256 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4257 m_ePlayState = PLAY_STATE_STOPPED;
4258 if(m_bPlaybackStarting)
4261 // informs python script currently running playback has ended
4262 // (does nothing if python is not loaded)
4264 g_pythonParser.OnPlayBackStopped();
4267 CVariant data(CVariant::VariantTypeObject);
4268 data["end"] = false;
4269 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4271 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4272 g_windowManager.SendThreadMessage(msg);
4275 void CApplication::OnPlayBackPaused()
4278 g_pythonParser.OnPlayBackPaused();
4282 param["player"]["speed"] = 0;
4283 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4284 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4287 void CApplication::OnPlayBackResumed()
4290 g_pythonParser.OnPlayBackResumed();
4294 param["player"]["speed"] = 1;
4295 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4296 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4299 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4302 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4306 param["player"]["speed"] = iSpeed;
4307 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4308 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4311 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4314 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4318 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4319 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4320 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4321 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4322 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4323 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4326 void CApplication::OnPlayBackSeekChapter(int iChapter)
4329 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4333 bool CApplication::IsPlayingFullScreenVideo() const
4335 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4338 bool CApplication::IsFullScreen()
4340 return IsPlayingFullScreenVideo() ||
4341 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4342 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4345 void CApplication::SaveFileState(bool bForeground /* = false */)
4347 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4352 CSaveFileStateJob job(*m_progressTrackingItem,
4353 *m_stackFileItemToUpdate,
4354 m_progressTrackingVideoResumeBookmark,
4355 m_progressTrackingPlayCountUpdate);
4357 // Run job in the foreground to make sure it finishes
4362 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4363 *m_stackFileItemToUpdate,
4364 m_progressTrackingVideoResumeBookmark,
4365 m_progressTrackingPlayCountUpdate);
4366 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4370 void CApplication::UpdateFileState()
4372 // Did the file change?
4373 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4377 // Reset tracking item
4378 m_progressTrackingItem->Reset();
4382 if (m_pPlayer->IsPlaying())
4384 if (m_progressTrackingItem->GetPath() == "")
4387 *m_progressTrackingItem = CurrentFileItem();
4388 m_progressTrackingPlayCountUpdate = false;
4391 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4392 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4393 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4394 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4396 m_progressTrackingPlayCountUpdate = true;
4399 // Check whether we're *really* playing video else we may race when getting eg. stream details
4400 if (m_pPlayer->IsPlayingVideo())
4402 /* Always update streamdetails, except for DVDs where we only update
4403 streamdetails if title length > 15m (Should yield more correct info) */
4404 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4406 CStreamDetails details;
4407 // Update with stream details from player, if any
4408 if (m_pPlayer->GetStreamDetails(details))
4409 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4411 if (m_progressTrackingItem->IsStack())
4412 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4415 // Update bookmark for save
4416 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4417 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4418 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4420 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4421 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4423 // Delete the bookmark
4424 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4427 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4429 // Update the bookmark
4430 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4431 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4436 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4443 void CApplication::StopPlaying()
4445 int iWin = g_windowManager.GetActiveWindow();
4446 if ( m_pPlayer->IsPlaying() )
4450 m_pKaraokeMgr->Stop();
4453 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4454 g_PVRManager.SaveCurrentChannelSettings();
4456 m_pPlayer->CloseFile();
4458 // turn off visualisation window when stopping
4459 if ((iWin == WINDOW_VISUALISATION
4460 || iWin == WINDOW_FULLSCREEN_VIDEO)
4462 g_windowManager.PreviousWindow();
4464 g_partyModeManager.Disable();
4468 void CApplication::ResetSystemIdleTimer()
4470 // reset system idle timer
4471 m_idleTimer.StartZero();
4474 void CApplication::ResetScreenSaver()
4477 m_shutdownTimer.StartZero();
4479 // screen saver timer is reset only if we're not already in screensaver or
4481 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4482 ResetScreenSaverTimer();
4485 void CApplication::ResetScreenSaverTimer()
4487 m_screenSaverTimer.StartZero();
4490 void CApplication::StopScreenSaverTimer()
4492 m_screenSaverTimer.Stop();
4495 bool CApplication::ToggleDPMS(bool manual)
4497 if (manual || (m_dpmsIsManual == manual))
4501 m_dpmsIsActive = false;
4502 m_dpmsIsManual = false;
4503 return m_dpms->DisablePowerSaving();
4507 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4509 m_dpmsIsActive = true;
4510 m_dpmsIsManual = manual;
4518 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4522 // First reset DPMS, if active
4527 // TODO: if screensaver lock is specified but screensaver is not active
4528 // (DPMS came first), activate screensaver now.
4530 ResetScreenSaverTimer();
4531 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4534 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4538 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4539 CVariant data(bPowerOffKeyPressed);
4540 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4546 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4548 if (m_iScreenSaveLock == 2)
4551 // if Screen saver is active
4552 if (m_bScreenSave && m_screenSaver)
4554 if (m_iScreenSaveLock == 0)
4555 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4556 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4557 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4558 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4560 m_iScreenSaveLock = 2;
4561 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4563 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4565 pWindow->OnMessage(msg);
4567 if (m_iScreenSaveLock == -1)
4569 m_iScreenSaveLock = 0;
4573 // disable screensaver
4574 m_bScreenSave = false;
4575 m_iScreenSaveLock = 0;
4576 ResetScreenSaverTimer();
4578 if (m_screenSaver->ID() == "visualization")
4580 // we can just continue as usual from vis mode
4583 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4585 else if (!m_screenSaver->ID().empty())
4586 { // we're in screensaver window
4587 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4588 g_windowManager.PreviousWindow(); // show the previous window
4589 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4590 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4598 void CApplication::CheckScreenSaverAndDPMS()
4600 if (m_bInBackground)
4602 if (!m_dpmsIsActive)
4603 g_Windowing.ResetOSScreensaver();
4605 bool maybeScreensaver =
4606 !m_dpmsIsActive && !m_bScreenSave
4607 && !CSettings::Get().GetString("screensaver.mode").empty();
4609 !m_dpmsIsActive && m_dpms->IsSupported()
4610 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4612 // Has the screen saver window become active?
4613 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4615 m_bScreenSave = true;
4616 maybeScreensaver = false;
4619 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4621 WakeUpScreenSaverAndDPMS();
4625 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4627 // See if we need to reset timer.
4628 // * Are we playing a video and it is not paused?
4629 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4630 // * Are we playing some music in fullscreen vis?
4631 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4632 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4634 ResetScreenSaverTimer();
4638 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4640 // DPMS has priority (it makes the screensaver not needed)
4642 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4645 WakeUpScreenSaver();
4647 else if (maybeScreensaver
4648 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4650 ActivateScreenSaver();
4654 // activate the screensaver.
4655 // if forceType is true, we ignore the various conditions that can alter
4656 // the type of screensaver displayed
4657 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4659 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4660 { // just activate the visualisation if user toggled the usemusicvisinstead option
4661 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4665 m_bScreenSave = true;
4667 // Get Screensaver Mode
4668 m_screenSaver.reset();
4669 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4670 m_screenSaver.reset(new CScreenSaver(""));
4672 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4674 // disable screensaver lock from the login screen
4675 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4678 // set to Dim in the case of a dialog on screen or playing video
4679 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4681 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4682 m_screenSaver.reset(new CScreenSaver(""));
4685 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4687 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4689 else if (!m_screenSaver->ID().empty())
4690 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4693 void CApplication::SetInBackground(bool background)
4697 ResetScreenSaverTimer();
4699 m_bInBackground = background;
4702 void CApplication::CheckShutdown()
4704 // first check if we should reset the timer
4705 bool resetTimer = m_bInhibitIdleShutdown;
4707 if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4710 if (m_musicInfoScanner->IsScanning())
4713 if (m_videoInfoScanner->IsScanning())
4716 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4719 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4724 m_shutdownTimer.StartZero();
4728 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4730 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4731 m_shutdownTimer.Stop();
4734 CApplicationMessenger::Get().Shutdown();
4738 void CApplication::InhibitIdleShutdown(bool inhibit)
4740 m_bInhibitIdleShutdown = inhibit;
4743 bool CApplication::IsIdleShutdownInhibited() const
4745 return m_bInhibitIdleShutdown;
4748 bool CApplication::OnMessage(CGUIMessage& message)
4750 switch ( message.GetMessage() )
4752 case GUI_MSG_NOTIFY_ALL:
4754 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4756 // Update general playlist: Remove DVD playlist items
4757 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4760 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4761 g_windowManager.SendMessage( msg );
4763 // stop the file if it's on dvd (will set the resume point etc)
4764 if (m_itemCurrentFile->IsOnDVD())
4770 case GUI_MSG_PLAYBACK_STARTED:
4772 #ifdef TARGET_DARWIN
4773 DarwinSetScheduling(message.GetMessage());
4775 // reset the seek handler
4776 m_seekHandler->Reset();
4777 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4779 // Update our infoManager with the new details etc.
4780 if (m_nextPlaylistItem >= 0)
4782 // playing an item which is not in the list - player might be stopped already
4784 if (playList.size() <= m_nextPlaylistItem)
4787 // we've started a previously queued item
4788 CFileItemPtr item = playList[m_nextPlaylistItem];
4789 // update the playlist manager
4790 int currentSong = g_playlistPlayer.GetCurrentSong();
4791 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4792 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4793 g_windowManager.SendThreadMessage(msg);
4794 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4795 *m_itemCurrentFile = *item;
4797 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4798 g_partyModeManager.OnSongChange(true);
4801 param["player"]["speed"] = 1;
4802 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4803 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4805 if (m_pPlayer->IsPlayingAudio())
4807 // Start our cdg parser as appropriate
4809 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4811 m_pKaraokeMgr->Stop();
4812 if (m_itemCurrentFile->IsMusicDb())
4814 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4816 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4817 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4820 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4823 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4832 case GUI_MSG_QUEUE_NEXT_ITEM:
4834 // Check to see if our playlist player has a new item for us,
4835 // and if so, we check whether our current player wants the file
4836 int iNext = g_playlistPlayer.GetNextSong();
4837 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4838 if (iNext < 0 || iNext >= playlist.size())
4840 m_pPlayer->OnNothingToQueueNotify();
4841 return true; // nothing to do
4844 // ok, grab the next song
4845 CFileItem file(*playlist[iNext]);
4847 CURL url(file.GetPath());
4848 if (url.GetProtocol() == "plugin")
4849 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4852 if (URIUtils::IsUPnP(file.GetPath()))
4854 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4859 // ok - send the file to the player, if it accepts it
4860 if (m_pPlayer->QueueNextFile(file))
4862 // player accepted the next file
4863 m_nextPlaylistItem = iNext;
4867 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4868 queue the next (if it wants to) and it doesn't keep looping on this song */
4869 g_playlistPlayer.SetCurrentSong(iNext);
4876 case GUI_MSG_PLAYBACK_STOPPED:
4877 case GUI_MSG_PLAYBACK_ENDED:
4878 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4882 m_pKaraokeMgr->Stop();
4884 #ifdef TARGET_DARWIN
4885 DarwinSetScheduling(message.GetMessage());
4887 // first check if we still have items in the stack to play
4888 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4890 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4891 { // just play the next item in the stack
4892 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4897 // In case playback ended due to user eg. skipping over the end, clear
4898 // our resume bookmark here
4899 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4901 // Delete the bookmark
4902 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4905 // reset the current playing file
4906 m_itemCurrentFile->Reset();
4907 g_infoManager.ResetCurrentItem();
4908 m_currentStack->Clear();
4910 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4912 g_playlistPlayer.PlayNext(1, true);
4916 // reset any forced player
4917 m_eForcedNextPlayer = EPC_NONE;
4919 m_pPlayer->ClosePlayer();
4922 m_pPlayer->m_iPlaySpeed = 1;
4925 if (!m_pPlayer->IsPlaying())
4927 g_audioManager.Enable(true);
4930 if (!m_pPlayer->IsPlayingVideo())
4932 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4934 g_windowManager.PreviousWindow();
4938 CSingleLock lock(g_graphicsContext);
4939 // resets to res_desktop or look&feel resolution (including refreshrate)
4940 g_graphicsContext.SetFullScreenVideo(false);
4944 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4946 CSettings::Get().Save(); // save vis settings
4947 WakeUpScreenSaverAndDPMS();
4948 g_windowManager.PreviousWindow();
4951 // DVD ejected while playing in vis ?
4952 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4955 CSettings::Get().Save(); // save vis settings
4956 WakeUpScreenSaverAndDPMS();
4957 g_windowManager.PreviousWindow();
4960 if (IsEnableTestMode())
4961 CApplicationMessenger::Get().Quit();
4966 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4967 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4972 case GUI_MSG_FULLSCREEN:
4973 { // Switch to fullscreen, if we can
4974 SwitchToFullScreen();
4978 case GUI_MSG_EXECUTE:
4979 if (message.GetNumStringParams())
4980 return ExecuteXBMCAction(message.GetStringParam());
4986 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4988 // see if it is a user set string
4990 //We don't know if there is unsecure information in this yet, so we
4991 //postpone any logging
4992 const std::string in_actionStr(actionStr);
4993 CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
4994 CGUIInfoLabel info(actionStr, "");
4995 actionStr = info.GetLabel(0);
4997 // user has asked for something to be executed
4998 if (CBuiltins::HasCommand(actionStr))
4999 CBuiltins::Execute(actionStr);
5002 // try translating the action from our ButtonTranslator
5004 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5006 OnAction(CAction(actionID));
5009 CFileItem item(actionStr, false);
5011 if (item.IsPythonScript())
5012 { // a python script
5013 CScriptInvocationManager::Get().Execute(item.GetPath());
5017 if (item.IsAudio() || item.IsVideo())
5018 { // an audio or video file
5023 //At this point we have given up to translate, so even though
5024 //there may be insecure information, we log it.
5025 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5032 void CApplication::Process()
5036 // dispatch the messages generated by python or other threads to the current window
5037 g_windowManager.DispatchThreadMessages();
5039 // process messages which have to be send to the gui
5040 // (this can only be done after g_windowManager.Render())
5041 CApplicationMessenger::Get().ProcessWindowMessages();
5045 m_loggingIn = false;
5047 // autoexec.py - profile
5048 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5050 if (XFILE::CFile::Exists(strAutoExecPy))
5051 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5053 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5056 // handle any active scripts
5057 CScriptInvocationManager::Get().Process();
5059 // process messages, even if a movie is playing
5060 CApplicationMessenger::Get().ProcessMessages();
5061 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5063 // check how far we are through playing the current item
5064 // and do anything that needs doing (playcount updates etc)
5065 CheckPlayingProgress();
5068 m_pPlayer->DoAudioWork();
5070 // do any processing that isn't needed on each run
5071 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5073 m_slowTimer.Reset();
5077 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5080 // We get called every 500ms
5081 void CApplication::ProcessSlow()
5083 g_powerManager.ProcessEvents();
5085 #if defined(TARGET_DARWIN_OSX)
5086 // There is an issue on OS X that several system services ask the cursor to become visible
5087 // during their startup routines. Given that we can't control this, we hack it in by
5089 if (g_Windowing.IsFullScreen())
5090 { // SDL thinks it's hidden
5095 // Temporarely pause pausable jobs when viewing video/picture
5096 int currentWindow = g_windowManager.GetActiveWindow();
5097 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5099 CJobManager::GetInstance().PauseJobs();
5103 CJobManager::GetInstance().UnPauseJobs();
5106 // Store our file state for use on close()
5109 // Check if we need to activate the screensaver / DPMS.
5110 CheckScreenSaverAndDPMS();
5112 // Check if we need to shutdown (if enabled).
5113 #if defined(TARGET_DARWIN)
5114 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5116 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5122 // check if we should restart the player
5123 CheckDelayedPlayerRestart();
5125 // check if we can unload any unreferenced dlls or sections
5126 if (!m_pPlayer->IsPlayingVideo())
5127 CSectionLoader::UnloadDelayed();
5129 // check for any idle curl connections
5130 g_curlInterface.CheckIdle();
5132 // check for any idle myth sessions
5133 CMythSession::CheckIdle();
5135 #ifdef HAS_FILESYSTEM_HTSP
5136 // check for any idle htsp sessions
5137 HTSP::CHTSPDirectorySession::CheckIdle();
5141 if ( m_pKaraokeMgr )
5142 m_pKaraokeMgr->ProcessSlow();
5145 if (!m_pPlayer->IsPlayingVideo())
5146 g_largeTextureManager.CleanupUnusedImages();
5148 g_TextureManager.FreeUnusedTextures(5000);
5150 #ifdef HAS_DVD_DRIVE
5151 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5152 if (!m_pPlayer->IsPlayingVideo())
5153 m_Autorun->HandleAutorun();
5156 // update upnp server/renderer states
5158 if(UPNP::CUPnP::IsInstantiated())
5159 UPNP::CUPnP::GetInstance()->UpdateState();
5162 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5166 #ifdef HAS_FILESYSTEM_NFS
5167 gNfsConnection.CheckIfIdle();
5170 #ifdef HAS_FILESYSTEM_AFP
5171 gAfpConnection.CheckIfIdle();
5174 #ifdef HAS_FILESYSTEM_SFTP
5175 CSFTPSessionManager::ClearOutIdleSessions();
5178 g_mediaManager.ProcessEvents();
5181 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5182 g_RemoteControl.Initialize();
5185 if (!m_pPlayer->IsPlayingVideo())
5186 CAddonInstaller::Get().UpdateRepos();
5188 CAEFactory::GarbageCollect();
5192 // Global Idle Time in Seconds
5193 // idle time will be resetet if on any OnKey()
5194 // int return: system Idle time in seconds! 0 is no idle!
5195 int CApplication::GlobalIdleTime()
5197 if(!m_idleTimer.IsRunning())
5200 m_idleTimer.StartZero();
5202 return (int)m_idleTimer.GetElapsedSeconds();
5205 float CApplication::NavigationIdleTime()
5207 if (!m_navigationTimer.IsRunning())
5209 m_navigationTimer.Stop();
5210 m_navigationTimer.StartZero();
5212 return m_navigationTimer.GetElapsedSeconds();
5215 void CApplication::DelayedPlayerRestart()
5217 m_restartPlayerTimer.StartZero();
5220 void CApplication::CheckDelayedPlayerRestart()
5222 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5224 m_restartPlayerTimer.Stop();
5225 m_restartPlayerTimer.Reset();
5230 void CApplication::Restart(bool bSamePosition)
5232 // this function gets called when the user changes a setting (like noninterleaved)
5233 // and which means we gotta close & reopen the current playing file
5235 // first check if we're playing a file
5236 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5239 if( !m_pPlayer->HasPlayer() )
5244 // do we want to return to the current position in the file
5245 if (false == bSamePosition)
5247 // no, then just reopen the file and start at the beginning
5248 PlayFile(*m_itemCurrentFile, true);
5252 // else get current position
5253 double time = GetTime();
5255 // get player state, needed for dvd's
5256 CStdString state = m_pPlayer->GetPlayerState();
5258 // set the requested starttime
5259 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5262 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5263 m_pPlayer->SetPlayerState(state);
5266 const CStdString& CApplication::CurrentFile()
5268 return m_itemCurrentFile->GetPath();
5271 CFileItem& CApplication::CurrentFileItem()
5273 return *m_itemCurrentFile;
5276 CFileItem& CApplication::CurrentUnstackedItem()
5278 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5279 return *(*m_currentStack)[m_currentStackPosition];
5281 return *m_itemCurrentFile;
5284 void CApplication::ShowVolumeBar(const CAction *action)
5286 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5291 volumeBar->OnAction(*action);
5295 bool CApplication::IsMuted() const
5297 if (g_peripherals.IsMuted())
5299 return CAEFactory::IsMuted();
5302 void CApplication::ToggleMute(void)
5310 void CApplication::SetMute(bool mute)
5312 if (m_muted != mute)
5319 void CApplication::Mute()
5321 if (g_peripherals.Mute())
5324 CAEFactory::SetMute(true);
5329 void CApplication::UnMute()
5331 if (g_peripherals.UnMute())
5334 CAEFactory::SetMute(false);
5339 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5341 float hardwareVolume = iValue;
5344 hardwareVolume /= 100.0f;
5346 SetHardwareVolume(hardwareVolume);
5350 void CApplication::SetHardwareVolume(float hardwareVolume)
5352 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5353 m_volumeLevel = hardwareVolume;
5356 if (hardwareVolume > VOLUME_MINIMUM)
5358 float dB = CAEUtil::PercentToGain(hardwareVolume);
5359 value = CAEUtil::GainToScale(dB);
5364 CAEFactory::SetVolume(value);
5367 float CApplication::GetVolume(bool percentage /* = true */) const
5371 // converts the hardware volume to a percentage
5372 return m_volumeLevel * 100.0f;
5375 return m_volumeLevel;
5378 void CApplication::VolumeChanged() const
5380 CVariant data(CVariant::VariantTypeObject);
5381 data["volume"] = GetVolume();
5382 data["muted"] = m_muted;
5383 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5385 // if player has volume control, set it.
5386 if (m_pPlayer->ControlsVolume())
5388 m_pPlayer->SetVolume(m_volumeLevel);
5389 m_pPlayer->SetMute(m_muted);
5393 int CApplication::GetSubtitleDelay() const
5395 // converts subtitle delay to a percentage
5396 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5399 int CApplication::GetAudioDelay() const
5401 // converts audio delay to a percentage
5402 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5405 // Returns the total time in seconds of the current media. Fractional
5406 // portions of a second are possible - but not necessarily supported by the
5407 // player class. This returns a double to be consistent with GetTime() and
5409 double CApplication::GetTotalTime() const
5413 if (m_pPlayer->IsPlaying())
5415 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5416 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5418 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5424 void CApplication::StopShutdownTimer()
5426 if (m_shutdownTimer.IsRunning())
5427 m_shutdownTimer.Stop();
5430 void CApplication::ResetShutdownTimers()
5432 // reset system shutdown timer
5433 m_shutdownTimer.StartZero();
5435 // delete custom shutdown timer
5436 if (g_alarmClock.HasAlarm("shutdowntimer"))
5437 g_alarmClock.Stop("shutdowntimer", true);
5440 // Returns the current time in seconds of the currently playing media.
5441 // Fractional portions of a second are possible. This returns a double to
5442 // be consistent with GetTotalTime() and SeekTime().
5443 double CApplication::GetTime() const
5447 if (m_pPlayer->IsPlaying())
5449 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5451 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5452 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5455 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5461 // Sets the current position of the currently playing media to the specified
5462 // time in seconds. Fractional portions of a second are valid. The passed
5463 // time is the time offset from the beginning of the file as opposed to a
5464 // delta from the current position. This method accepts a double to be
5465 // consistent with GetTime() and GetTotalTime().
5466 void CApplication::SeekTime( double dTime )
5468 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5470 if (!m_pPlayer->CanSeek()) return;
5471 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5473 // find the item in the stack we are seeking to, and load the new
5474 // file if necessary, and calculate the correct seek within the new
5475 // file. Otherwise, just fall through to the usual routine if the
5476 // time is higher than our total time.
5477 for (int i = 0; i < m_currentStack->Size(); i++)
5479 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5481 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5482 if (m_currentStackPosition == i)
5483 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5485 { // seeking to a new file
5486 m_currentStackPosition = i;
5487 CFileItem item(*(*m_currentStack)[i]);
5488 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5489 // don't just call "PlayFile" here, as we are quite likely called from the
5490 // player thread, so we won't be able to delete ourselves.
5491 CApplicationMessenger::Get().PlayFile(item, true);
5497 // convert to milliseconds and perform seek
5498 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5502 float CApplication::GetPercentage() const
5504 if (m_pPlayer->IsPlaying())
5506 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5508 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5509 if (tag.GetDuration() > 0)
5510 return (float)(GetTime() / tag.GetDuration() * 100);
5513 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5515 double totalTime = GetTotalTime();
5516 if (totalTime > 0.0f)
5517 return (float)(GetTime() / totalTime * 100);
5520 return m_pPlayer->GetPercentage();
5525 float CApplication::GetCachePercentage() const
5527 if (m_pPlayer->IsPlaying())
5529 // Note that the player returns a relative cache percentage and we want an absolute percentage
5530 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5532 float stackedTotalTime = (float) GetTotalTime();
5533 // We need to take into account the stack's total time vs. currently playing file's total time
5534 if (stackedTotalTime > 0.0f)
5535 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5538 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5543 void CApplication::SeekPercentage(float percent)
5545 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5547 if (!m_pPlayer->CanSeek()) return;
5548 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5549 SeekTime(percent * 0.01 * GetTotalTime());
5551 m_pPlayer->SeekPercentage(percent);
5555 // SwitchToFullScreen() returns true if a switch is made, else returns false
5556 bool CApplication::SwitchToFullScreen()
5558 // if playing from the video info window, close it first!
5559 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5561 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5562 if (pDialog) pDialog->Close(true);
5565 // don't switch if there is a dialog on screen or the slideshow is active
5566 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5569 // See if we're playing a video, and are in GUI mode
5570 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5572 // then switch to fullscreen mode
5573 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5576 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5577 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5578 { // then switch to visualisation
5579 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5585 void CApplication::Minimize()
5587 g_Windowing.Minimize();
5590 PLAYERCOREID CApplication::GetCurrentPlayer()
5592 return m_pPlayer->GetCurrentPlayer();
5595 void CApplication::UpdateLibraries()
5597 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5599 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5603 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5605 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5610 bool CApplication::IsVideoScanning() const
5612 return m_videoInfoScanner->IsScanning();
5615 bool CApplication::IsMusicScanning() const
5617 return m_musicInfoScanner->IsScanning();
5620 void CApplication::StopVideoScan()
5622 if (m_videoInfoScanner->IsScanning())
5623 m_videoInfoScanner->Stop();
5626 void CApplication::StopMusicScan()
5628 if (m_musicInfoScanner->IsScanning())
5629 m_musicInfoScanner->Stop();
5632 void CApplication::StartVideoCleanup()
5634 if (m_videoInfoScanner->IsScanning())
5637 m_videoInfoScanner->CleanDatabase();
5640 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5642 if (m_videoInfoScanner->IsScanning())
5645 m_videoInfoScanner->ShowDialog(true);
5647 m_videoInfoScanner->Start(strDirectory,scanAll);
5650 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5652 if (m_musicInfoScanner->IsScanning())
5656 { // setup default flags
5657 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5658 flags |= CMusicInfoScanner::SCAN_ONLINE;
5659 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5660 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5663 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5664 m_musicInfoScanner->ShowDialog(true);
5666 m_musicInfoScanner->Start(strDirectory, flags);
5669 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5672 if (m_musicInfoScanner->IsScanning())
5675 m_musicInfoScanner->ShowDialog(true);
5677 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5680 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5683 if (m_musicInfoScanner->IsScanning())
5686 m_musicInfoScanner->ShowDialog(true);
5688 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5691 void CApplication::CheckPlayingProgress()
5693 // check if we haven't rewound past the start of the file
5694 if (m_pPlayer->IsPlaying())
5696 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5706 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5708 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5709 g_application.SeekTime(0);
5715 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5717 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5719 // initial exit conditions
5720 // no songs in playlist just return
5721 if (playlist.size() == 0)
5725 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5728 // setup correct playlist
5729 g_playlistPlayer.ClearPlaylist(iPlaylist);
5731 // if the playlist contains an internet stream, this file will be used
5732 // to generate a thumbnail for musicplayer.cover
5733 g_application.m_strPlayListFile = strPlayList;
5735 // add the items to the playlist player
5736 g_playlistPlayer.Add(iPlaylist, playlist);
5738 // if we have a playlist
5739 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5742 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5743 g_playlistPlayer.Reset();
5744 g_playlistPlayer.Play(track);
5750 void CApplication::SaveCurrentFileSettings()
5752 // don't store settings for PVR in video database
5753 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5755 // save video settings
5756 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5760 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5764 else if (m_itemCurrentFile->IsPVRChannel())
5766 g_PVRManager.SaveCurrentChannelSettings();
5770 bool CApplication::AlwaysProcess(const CAction& action)
5772 // check if this button is mapped to a built-in function
5773 if (!action.GetName().empty())
5775 CStdString builtInFunction;
5776 vector<CStdString> params;
5777 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5778 StringUtils::ToLower(builtInFunction);
5780 // should this button be handled normally or just cancel the screensaver?
5781 if ( builtInFunction.Equals("powerdown")
5782 || builtInFunction.Equals("reboot")
5783 || builtInFunction.Equals("restart")
5784 || builtInFunction.Equals("restartapp")
5785 || builtInFunction.Equals("suspend")
5786 || builtInFunction.Equals("hibernate")
5787 || builtInFunction.Equals("quit")
5788 || builtInFunction.Equals("shutdown"))
5797 bool CApplication::IsCurrentThread() const
5799 return CThread::IsCurrentThread(m_threadID);
5802 void CApplication::SetRenderGUI(bool renderGUI)
5804 if (renderGUI && ! m_renderGUI)
5805 g_windowManager.MarkDirty();
5806 m_renderGUI = renderGUI;
5809 CNetwork& CApplication::getNetwork()
5813 #ifdef HAS_PERFORMANCE_SAMPLE
5814 CPerformanceStats &CApplication::GetPerformanceStats()
5820 bool CApplication::SetLanguage(const CStdString &strLanguage)
5822 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5823 CStdString strNewLanguage = strLanguage;
5824 if (strNewLanguage != strPreviousLanguage)
5826 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5827 if (!g_langInfo.Load(strLangInfoPath))
5830 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5832 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5833 CStdString strFontSet;
5834 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5835 strNewLanguage = strFontSet;
5837 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5839 CSettings::Get().SetString("locale.language", strNewLanguage);
5841 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5844 // also tell our weather and skin to reload as these are localized
5845 g_weatherManager.Refresh();
5846 g_PVRManager.LocalizationChanged();
5853 void CApplication::CloseNetworkShares()
5855 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5857 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5861 #ifdef HAS_FILESYSTEM_NFS
5862 gNfsConnection.Deinit();
5865 #ifdef HAS_FILESYSTEM_AFP
5866 gAfpConnection.Deinit();
5869 #ifdef HAS_FILESYSTEM_SFTP
5870 CSFTPSessionManager::DisconnectAllSessions();