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. Similarly, if the current skin font is not
1631 // the default, reset it as well.
1632 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1633 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1634 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1635 CSettings::Get().SetString("lookandfeel.font", "Default");
1638 std::string builtin("ReloadSkin");
1639 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1640 builtin += "(confirm)";
1641 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1644 else if (settingId == "lookandfeel.skintheme")
1646 // also set the default color theme
1647 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1648 URIUtils::RemoveExtension(colorTheme);
1649 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1650 colorTheme = "defaults";
1652 // check if we have to change the skin color
1653 // if yes, it will trigger a call to ReloadSkin() in
1654 // it's OnSettingChanged() callback
1655 // if no we have to call ReloadSkin() ourselves
1656 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1657 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1659 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1661 else if (settingId == "lookandfeel.skinzoom")
1662 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1663 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1665 // AE is master of audio settings and needs to be informed first
1666 CAEFactory::OnSettingsChange(settingId);
1668 if (settingId == "audiooutput.guisoundmode")
1670 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1672 // this tells player whether to open an audio stream passthrough or PCM
1673 // if this is changed, audio stream has to be reopened
1674 else if (settingId == "audiooutput.passthrough")
1676 CApplicationMessenger::Get().MediaRestart(false);
1679 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1680 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1681 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1682 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1683 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1684 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1685 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1686 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1689 void CApplication::OnSettingAction(const CSetting *setting)
1691 if (setting == NULL)
1694 const std::string &settingId = setting->GetId();
1695 if (settingId == "lookandfeel.skinsettings")
1696 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1697 else if (settingId == "screensaver.preview")
1698 ActivateScreenSaver(true);
1699 else if (settingId == "screensaver.settings")
1702 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1703 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1705 else if (settingId == "videoscreen.guicalibration")
1706 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1707 else if (settingId == "videoscreen.testpattern")
1708 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1711 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1713 if (setting == NULL)
1716 const std::string &settingId = setting->GetId();
1717 if (settingId == "audiooutput.channels")
1719 // check if this is an update from Eden
1720 if (oldSettingId != NULL && oldSettingNode != NULL &&
1721 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1724 CSettingInt* channels = (CSettingInt*)setting;
1725 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1726 ret = channels->SetValue(channels->GetValue() + 1);
1728 // let's just reset the audiodevice settings as well
1729 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1730 CAEFactory::VerifyOutputDevice(audiodevice, false);
1731 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1736 else if (settingId == "screensaver.mode")
1738 CSettingString *screensaverMode = (CSettingString*)setting;
1739 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1740 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1741 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1743 else if (settingId == "scrapers.musicvideosdefault")
1745 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1746 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1748 musicvideoScraper->Reset();
1752 #if defined(HAS_LIBAMCODEC)
1753 else if (settingId == "videoplayer.useamcodec")
1755 // Do not permit amcodec to be used on non-aml platforms.
1756 // The setting will be hidden but the default value is true,
1757 // so change it to false.
1760 CSettingBool *useamcodec = (CSettingBool*)setting;
1761 useamcodec->SetValue(false);
1765 #if defined(TARGET_ANDROID)
1766 else if (settingId == "videoplayer.usemediacodec")
1768 // Do not permit MediaCodec to be used Android platforms that do not have it.
1769 // The setting will be hidden but the default value is true,
1770 // so change it to false.
1771 if (CAndroidFeatures::GetVersion() < 16)
1773 CSettingBool *usemediacodec = (CSettingBool*)setting;
1774 usemediacodec->SetValue(false);
1777 else if (settingId == "videoplayer.usestagefright")
1779 CSettingBool *usestagefright = (CSettingBool*)setting;
1780 usestagefright->SetValue(false);
1787 bool CApplication::OnSettingsSaving() const
1789 // don't save settings when we're busy stopping the application
1790 // a lot of screens try to save settings on deinit and deinit is
1791 // called for every screen when the application is stopping
1798 void CApplication::ReloadSkin(bool confirm/*=false*/)
1800 m_skinReloading = false;
1801 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1803 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1804 g_windowManager.SendMessage(msg);
1806 // Reload the skin, restoring the previously focused control. We need this as
1807 // the window unload will reset all control states.
1809 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1811 iCtrlID = pWindow->GetFocusedControlID();
1813 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1817 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1818 if (pWindow && pWindow->HasSaveLastControl())
1820 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1821 pWindow->OnMessage(msg3);
1825 if (!m_skinReverting && confirm)
1828 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1830 m_skinReverting = true;
1831 if (oldSkin.empty())
1832 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1834 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1838 m_skinReverting = false;
1841 bool CApplication::Load(const TiXmlNode *settings)
1843 if (settings == NULL)
1846 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1847 if (audioElement != NULL)
1849 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1850 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1851 m_volumeLevel = VOLUME_MAXIMUM;
1857 bool CApplication::Save(TiXmlNode *settings) const
1859 if (settings == NULL)
1862 TiXmlElement volumeNode("audio");
1863 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1864 if (audioNode == NULL)
1867 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1868 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1873 bool CApplication::LoadSkin(const CStdString& skinID)
1875 if (m_skinReloading)
1879 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1881 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1887 void CApplication::LoadSkin(const SkinPtr& skin)
1889 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1892 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1893 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1898 if (!skin->HasSkinFile("Home.xml"))
1900 // failed to find home.xml
1901 // fallback to default skin
1902 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1904 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1905 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1906 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1911 bool bPreviousPlayingState=false;
1912 bool bPreviousRenderingState=false;
1913 if (g_application.m_pPlayer->IsPlayingVideo())
1915 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1916 if (bPreviousPlayingState)
1917 g_application.m_pPlayer->Pause();
1918 #ifdef HAS_VIDEO_PLAYBACK
1919 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1921 g_windowManager.ActivateWindow(WINDOW_HOME);
1922 bPreviousRenderingState = true;
1926 // close the music and video overlays (they're re-opened automatically later)
1927 CSingleLock lock(g_graphicsContext);
1929 // save the current window details
1930 int currentWindow = g_windowManager.GetActiveWindow();
1931 vector<int> currentModelessWindows;
1932 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1936 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1938 g_SkinInfo->Start();
1940 CLog::Log(LOGINFO, " load fonts for skin...");
1941 g_graphicsContext.SetMediaDir(skin->Path());
1942 g_directoryCache.ClearSubPaths(skin->Path());
1943 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1945 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1946 CStdString strFontSet;
1947 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1949 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1950 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1951 CSettings::Get().Save();
1954 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1956 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1958 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1960 // load in the skin strings
1961 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1962 URIUtils::AddSlashAtEnd(langPath);
1964 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1966 g_SkinInfo->LoadIncludes();
1969 start = CurrentHostCounter();
1971 CLog::Log(LOGINFO, " load new skin...");
1973 // Load the user windows
1977 end = CurrentHostCounter();
1978 freq = CurrentHostFrequency();
1979 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1981 CLog::Log(LOGINFO, " initialize new skin...");
1982 g_windowManager.AddMsgTarget(this);
1983 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1984 g_windowManager.AddMsgTarget(&g_infoManager);
1985 g_windowManager.AddMsgTarget(&g_fontManager);
1986 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1987 g_windowManager.SetCallback(*this);
1988 g_windowManager.Initialize();
1989 CTextureCache::Get().Initialize();
1990 g_audioManager.Enable(true);
1991 g_audioManager.Load();
1993 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1994 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1996 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1997 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1998 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1999 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2000 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2003 CLog::Log(LOGINFO, " skin loaded...");
2005 // leave the graphics lock
2009 if (currentWindow != WINDOW_INVALID)
2011 g_windowManager.ActivateWindow(currentWindow);
2012 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2014 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2015 if (dialog) dialog->Show();
2019 if (g_application.m_pPlayer->IsPlayingVideo())
2021 if (bPreviousPlayingState)
2022 g_application.m_pPlayer->Pause();
2023 if (bPreviousRenderingState)
2024 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2028 void CApplication::UnloadSkin(bool forReload /* = false */)
2030 m_skinReloading = forReload;
2032 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2034 g_audioManager.Enable(false);
2036 g_windowManager.DeInitialize();
2037 CTextureCache::Get().Deinitialize();
2039 // remove the skin-dependent window
2040 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2042 g_TextureManager.Cleanup();
2043 g_largeTextureManager.CleanupUnusedImages(true);
2045 g_fontManager.Clear();
2047 g_colorManager.Clear();
2049 g_infoManager.Clear();
2051 // The g_SkinInfo boost shared_ptr ought to be reset here
2052 // but there are too many places it's used without checking for NULL
2053 // and as a result a race condition on exit can cause a crash.
2056 bool CApplication::LoadUserWindows()
2058 // Start from wherever home.xml is
2059 std::vector<CStdString> vecSkinPath;
2060 g_SkinInfo->GetSkinPaths(vecSkinPath);
2061 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2063 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2064 CFileItemList items;
2065 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2067 for (int i = 0; i < items.Size(); ++i)
2069 if (items[i]->m_bIsFolder)
2071 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2072 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2074 CXBMCTinyXML xmlDoc;
2075 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2077 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2081 // Root element should be <window>
2082 TiXmlElement* pRootElement = xmlDoc.RootElement();
2083 CStdString strValue = pRootElement->Value();
2084 if (!strValue.Equals("window"))
2086 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2090 // Read the <type> element to get the window type to create
2091 // If no type is specified, create a CGUIWindow as default
2092 CGUIWindow* pWindow = NULL;
2094 if (pRootElement->Attribute("type"))
2095 strType = pRootElement->Attribute("type");
2098 const TiXmlNode *pType = pRootElement->FirstChild("type");
2099 if (pType && pType->FirstChild())
2100 strType = pType->FirstChild()->Value();
2102 int id = WINDOW_INVALID;
2103 if (!pRootElement->Attribute("id", &id))
2105 const TiXmlNode *pType = pRootElement->FirstChild("id");
2106 if (pType && pType->FirstChild())
2107 id = atol(pType->FirstChild()->Value());
2109 CStdString visibleCondition;
2110 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2112 if (strType.Equals("dialog"))
2113 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2114 else if (strType.Equals("submenu"))
2115 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2116 else if (strType.Equals("buttonmenu"))
2117 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2119 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2121 // Check to make sure the pointer isn't still null
2122 if (pWindow == NULL)
2124 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2127 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2132 pWindow->SetVisibleCondition(visibleCondition);
2133 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2134 g_windowManager.AddCustomWindow(pWindow);
2142 bool CApplication::RenderNoPresent()
2146 // DXMERGE: This may have been important?
2147 // g_graphicsContext.AcquireCurrentContext();
2149 g_graphicsContext.Lock();
2151 // dont show GUI when playing full screen video
2152 if (g_graphicsContext.IsFullScreenVideo())
2154 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2155 g_renderManager.Render(true, 0, 255);
2157 // close window overlays
2158 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2159 if (overlay) overlay->Close(true);
2160 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2161 if (overlay) overlay->Close(true);
2165 bool hasRendered = g_windowManager.Render();
2167 g_graphicsContext.Unlock();
2172 float CApplication::GetDimScreenSaverLevel() const
2174 if (!m_bScreenSave || !m_screenSaver ||
2175 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2176 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2177 !m_screenSaver->ID().empty()))
2180 if (!m_screenSaver->GetSetting("level").empty())
2181 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2185 void CApplication::Render()
2187 // do not render if we are stopped or in background
2188 if (m_bStop || m_bInBackground)
2193 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2195 bool hasRendered = false;
2196 bool limitFrames = false;
2197 unsigned int singleFrameTime = 10; // default limit 100 fps
2201 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2202 // Whether externalplayer is playing and we're unfocused
2203 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2205 m_bPresentFrame = false;
2206 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2208 m_bPresentFrame = g_renderManager.FrameWait(100);
2213 // engage the frame limiter as needed
2214 limitFrames = lowfps || extPlayerActive;
2215 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2216 // perhaps allowing it to be set differently than the UI option??
2217 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2218 limitFrames = true; // not using vsync.
2219 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2220 limitFrames = true; // using vsync, but it isn't working.
2224 if (extPlayerActive)
2226 ResetScreenSaver(); // Prevent screensaver dimming the screen
2227 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2230 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2236 CSingleLock lock(g_graphicsContext);
2237 g_infoManager.UpdateFPS();
2239 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2240 g_Windowing.SetVSync(true);
2241 else if (vsync_mode == VSYNC_ALWAYS)
2242 g_Windowing.SetVSync(true);
2243 else if (vsync_mode != VSYNC_DRIVER)
2244 g_Windowing.SetVSync(false);
2246 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2249 if(!g_Windowing.BeginRender())
2252 g_renderManager.FrameMove();
2254 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2255 if(g_graphicsContext.GetStereoMode())
2257 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2258 if(RenderNoPresent())
2261 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2263 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2264 if(RenderNoPresent())
2267 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2271 if(RenderNoPresent())
2275 g_renderManager.FrameFinish();
2277 g_Windowing.EndRender();
2279 // execute post rendering actions (finalize window closing)
2280 g_windowManager.AfterRender();
2282 // reset our info cache - we do this at the end of Render so that it is
2283 // fresh for the next process(), or after a windowclose animation (where process()
2285 g_infoManager.ResetCache();
2288 unsigned int now = XbmcThreads::SystemClockMillis();
2290 m_lastRenderTime = now;
2292 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2293 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2295 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2296 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2300 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2301 if (limitFrames || !flip)
2304 singleFrameTime = 40; //if not flipping, loop at 25 fps
2306 unsigned int frameTime = now - m_lastFrameTime;
2307 if (frameTime < singleFrameTime)
2308 Sleep(singleFrameTime - frameTime);
2310 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2313 g_graphicsContext.Flip(dirtyRegions);
2314 CTimeUtils::UpdateFrameTime(flip);
2316 g_renderManager.UpdateResolution();
2317 g_renderManager.ManageCaptures();
2320 void CApplication::SetStandAlone(bool value)
2322 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2325 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2326 // The window manager will return true if the event is processed, false otherwise.
2327 // If not already processed, this routine handles global keypresses. It returns
2328 // true if the key has been processed, false otherwise.
2330 bool CApplication::OnKey(const CKey& key)
2333 // Turn the mouse off, as we've just got a keypress from controller or remote
2334 g_Mouse.SetActive(false);
2336 // get the current active window
2337 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2339 // this will be checked for certain keycodes that need
2340 // special handling if the screensaver is active
2341 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2343 // a key has been pressed.
2345 m_idleTimer.StartZero();
2346 bool processKey = AlwaysProcess(action);
2348 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2352 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2353 // do not wake up the screensaver right after switching off the playing device
2354 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2355 ret = CApplicationMessenger::Get().CECToggleState();
2357 ret = CApplicationMessenger::Get().CECStandby();
2358 if (!ret) /* display is switched off */
2364 // allow some keys to be processed while the screensaver is active
2365 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2367 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2371 // change this if we have a dialog up
2372 if (g_windowManager.HasModalDialog())
2374 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2376 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2377 { // fullscreen info dialog - special case
2378 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2380 if (!key.IsAnalogButton())
2381 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2383 if (OnAction(action))
2386 // fallthrough to the main window
2387 iWin = WINDOW_FULLSCREEN_VIDEO;
2389 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2391 // current active window is full screen video.
2392 if (g_application.m_pPlayer->IsInMenu())
2394 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2395 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2397 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2399 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2400 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2402 // if no PVR specific action/mapping is found, fall back to default
2403 if (action.GetID() == 0)
2404 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2408 // in any other case use the fullscreen window section of keymap.xml to map key->action
2409 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2414 // current active window isnt the fullscreen window
2415 // just use corresponding section from keymap.xml
2416 // to map key->action
2418 // first determine if we should use keyboard input directly
2419 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2420 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2423 CGUIControl *control = window->GetFocusedControl();
2426 // If this is an edit control set usekeyboard to true. This causes the
2427 // keypress to be processed directly not through the key mappings.
2428 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2431 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2432 // This causes the keypress to be used for list navigation.
2433 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2439 action = CAction(0); // reset our action
2440 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2442 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2443 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2444 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2445 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2446 action.GetID() == ACTION_MOVE_RIGHT ||
2447 action.GetID() == ACTION_MOVE_UP ||
2448 action.GetID() == ACTION_MOVE_DOWN ||
2449 action.GetID() == ACTION_SELECT_ITEM ||
2450 action.GetID() == ACTION_ENTER ||
2451 action.GetID() == ACTION_PREVIOUS_MENU ||
2452 action.GetID() == ACTION_NAV_BACK))
2454 // the action isn't plain navigation - check for a keyboard-specific keymap
2455 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2456 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2457 action.GetID() == ACTION_BACKSPACE ||
2458 action.GetID() == ACTION_SHIFT ||
2459 action.GetID() == ACTION_SYMBOLS ||
2460 action.GetID() == ACTION_CURSOR_LEFT ||
2461 action.GetID() == ACTION_CURSOR_RIGHT)
2462 action = CAction(0); // don't bother with this action
2465 if (!action.GetID())
2467 // keyboard entry - pass the keys through directly
2468 if (key.GetFromService())
2469 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2472 // Check for paste keypress
2473 #ifdef TARGET_WINDOWS
2474 // In Windows paste is ctrl-V
2475 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2476 #elif defined(TARGET_LINUX)
2477 // In Linux paste is ctrl-V
2478 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2479 #elif defined(TARGET_DARWIN_OSX)
2480 // In OSX paste is cmd-V
2481 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2483 // Placeholder for other operating systems
2486 action = CAction(ACTION_PASTE);
2487 // If the unicode is non-zero the keypress is a non-printing character
2488 else if (key.GetUnicode())
2489 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2490 // The keypress is a non-printing character
2492 action = CAction(key.GetVKey() | KEY_VKEY);
2496 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2498 if (OnAction(action))
2500 // failed to handle the keyboard action, drop down through to standard action
2502 if (key.GetFromService())
2504 if (key.GetButtonCode() != KEY_INVALID)
2505 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2508 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2510 if (!key.IsAnalogButton())
2511 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2513 return ExecuteInputAction(action);
2516 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2517 // This needs to return true if it processed the appcommand or false if it didn't
2518 bool CApplication::OnAppCommand(const CAction &action)
2520 // Reset the screen saver
2523 // If we were currently in the screen saver wake up and don't process the appcommand
2524 if (WakeUpScreenSaverAndDPMS())
2527 // The action ID is the APPCOMMAND code. We need to retrieve the action
2528 // associated with this appcommand from the mapping table.
2529 uint32_t appcmd = action.GetID();
2530 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2531 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2532 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2534 // If we couldn't find an action return false to indicate we have not
2535 // handled this appcommand
2536 if (!appcmdaction.GetID())
2538 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2542 // Process the appcommand
2543 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2544 OnAction(appcmdaction);
2546 // Always return true regardless of whether the action succeeded or not.
2547 // This stops Windows handling the appcommand itself.
2551 bool CApplication::OnAction(const CAction &action)
2553 // special case for switching between GUI & fullscreen mode.
2554 if (action.GetID() == ACTION_SHOW_GUI)
2555 { // Switch to fullscreen mode if we can
2556 if (SwitchToFullScreen())
2558 m_navigationTimer.StartZero();
2563 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2565 g_graphicsContext.ToggleFullScreenRoot();
2569 if (action.IsMouse())
2570 g_Mouse.SetActive(true);
2573 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2575 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2577 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2579 CGUIDialogVideoBookmarks::OnAddBookmark();
2582 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2583 // playing or ACTION_PLAYER_PLAY if we are not playing.
2584 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2586 if (m_pPlayer->IsPlaying())
2587 return OnAction(CAction(ACTION_PAUSE));
2589 return OnAction(CAction(ACTION_PLAYER_PLAY));
2592 //if the action would start or stop inertial scrolling
2593 //by gesture - bypass the normal OnAction handler of current window
2594 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2597 // just pass the action to the current window and let it handle it
2598 if (g_windowManager.OnAction(action))
2600 m_navigationTimer.StartZero();
2605 // handle extra global presses
2607 // screenshot : take a screenshot :)
2608 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2610 CScreenShot::TakeScreenshot();
2613 // built in functions : execute the built-in
2614 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2616 CBuiltins::Execute(action.GetName());
2617 m_navigationTimer.StartZero();
2622 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2624 CButtonTranslator::GetInstance().Clear();
2625 CButtonTranslator::GetInstance().Load();
2628 // show info : Shows the current video or song information
2629 if (action.GetID() == ACTION_SHOW_INFO)
2631 g_infoManager.ToggleShowInfo();
2635 // codec info : Shows the current song, video or picture codec information
2636 if (action.GetID() == ACTION_SHOW_CODEC)
2638 g_infoManager.ToggleShowCodec();
2642 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2644 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2647 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2648 char rating = tag->GetRating();
2649 bool needsUpdate(false);
2650 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2652 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2655 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2657 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2663 if (db.Open()) // OpenForWrite() ?
2665 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2668 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2669 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2670 g_windowManager.SendMessage(msg);
2676 // Now check with the playlist player if action can be handled.
2677 // 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.
2678 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2680 if (g_playlistPlayer.OnAction(action))
2684 // Now check with the player if action can be handled.
2685 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2686 (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)) ||
2687 action.GetID() == ACTION_STOP)
2689 if (m_pPlayer->OnAction(action))
2693 // stop : stops playing current audio song
2694 if (action.GetID() == ACTION_STOP)
2700 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2701 // If so, we just jump to the start of the track.
2702 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2705 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2709 // forward action to g_PVRManager and break if it was able to handle it
2710 if (g_PVRManager.OnAction(action))
2713 // forward action to graphic context and see if it can handle it
2714 if (CStereoscopicsManager::Get().OnAction(action))
2717 if (m_pPlayer->IsPlaying())
2719 // forward channel switches to the player - he knows what to do
2720 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2722 m_pPlayer->OnAction(action);
2726 // pause : pauses current audio song
2727 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2731 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2733 if (!m_pPlayer->IsPaused())
2734 { // unpaused - set the playspeed back to normal
2735 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2737 g_audioManager.Enable(m_pPlayer->IsPaused());
2740 if (!m_pPlayer->IsPaused())
2742 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2743 // if we are playing at normal speed, then allow play to pause
2744 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2746 if (m_pPlayer->GetPlaySpeed() != 1)
2748 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2756 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2758 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2759 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2761 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2763 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2768 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2770 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2773 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2776 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2778 // calculate the speed based on the amount the button is held down
2779 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2780 // returns 0 -> MAX_FFWD_SPEED
2781 int iSpeed = 1 << iPower;
2782 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2784 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2786 CLog::Log(LOGDEBUG,"Resetting playspeed");
2790 // allow play to unpause
2793 if (action.GetID() == ACTION_PLAYER_PLAY)
2795 // unpause, and set the playspeed back to normal
2797 g_audioManager.Enable(m_pPlayer->IsPaused());
2799 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2804 // record current file
2805 if (action.GetID() == ACTION_RECORD)
2807 if (m_pPlayer->CanRecord())
2808 m_pPlayer->Record(!m_pPlayer->IsRecording());
2811 if (m_playerController->OnAction(action))
2816 if (action.GetID() == ACTION_SWITCH_PLAYER)
2818 if(m_pPlayer->IsPlaying())
2820 VECPLAYERCORES cores;
2821 CFileItem item(*m_itemCurrentFile.get());
2822 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2823 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2824 if(core != EPC_NONE)
2826 g_application.m_eForcedNextPlayer = core;
2827 item.m_lStartOffset = (int)(GetTime() * 75);
2828 PlayFile(item, true);
2833 VECPLAYERCORES cores;
2834 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2835 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2836 if(core != EPC_NONE)
2839 g_application.m_eForcedNextPlayer = core;
2840 PlayFile(item, false);
2845 if (g_peripherals.OnAction(action))
2848 if (action.GetID() == ACTION_MUTE)
2854 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2856 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2857 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2859 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2861 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2862 g_windowManager.SendMessage(msg);
2867 // Check for global volume control
2868 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2870 if (!m_pPlayer->IsPassthrough())
2874 float volume = m_volumeLevel;
2875 // Android has steps based on the max available volume level
2876 #if defined(TARGET_ANDROID)
2877 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2879 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2881 if (action.GetRepeat())
2882 step *= action.GetRepeat() * 50; // 50 fps
2884 if (action.GetID() == ACTION_VOLUME_UP)
2885 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2887 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2888 SetVolume(volume, false);
2890 // show visual feedback of volume change...
2891 ShowVolumeBar(&action);
2894 // Check for global seek control
2895 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2897 if (!m_pPlayer->CanSeek()) return false;
2898 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2901 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2903 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2904 CGUIControlProfiler::Instance().Start();
2907 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2909 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2910 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2911 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2912 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2913 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2919 void CApplication::FrameMove(bool processEvents, bool processGUI)
2925 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2926 float frameTime = m_frameTime.GetElapsedSeconds();
2927 m_frameTime.StartZero();
2928 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2929 if( frameTime > 0.5 ) frameTime = 0.5;
2931 if (processGUI && m_renderGUI)
2933 g_graphicsContext.Lock();
2934 // check if there are notifications to display
2935 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2936 if (toast && toast->DoWork())
2938 if (!toast->IsDialogRunning())
2943 g_graphicsContext.Unlock();
2945 CWinEvents::MessagePump();
2947 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2948 // Read the input from a remote
2949 g_RemoteControl.Update();
2952 // process input actions
2953 ProcessRemote(frameTime);
2954 ProcessGamepad(frameTime);
2955 ProcessEventServer(frameTime);
2956 ProcessPeripherals(frameTime);
2957 if (processGUI && m_renderGUI)
2959 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2960 m_seekHandler->Process();
2963 if (processGUI && m_renderGUI)
2966 g_windowManager.Process(CTimeUtils::GetFrameTime());
2967 g_windowManager.FrameMove();
2971 bool CApplication::ProcessGamepad(float frameTime)
2973 #ifdef HAS_SDL_JOYSTICK
2977 int iWin = GetActiveWindowID();
2979 g_Joystick.Update();
2980 if (g_Joystick.GetButton(bid))
2983 m_idleTimer.StartZero();
2986 if (WakeUpScreenSaverAndDPMS())
2988 g_Joystick.Reset(true);
2993 CStdString actionName;
2995 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2997 CAction action(actionID, 1.0f, 0.0f, actionName);
2999 g_Mouse.SetActive(false);
3000 return ExecuteInputAction(action);
3007 if (g_Joystick.GetAxis(bid))
3009 if (g_Joystick.GetAmount() < 0)
3015 CStdString actionName;
3017 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3020 if (WakeUpScreenSaverAndDPMS())
3025 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3027 g_Mouse.SetActive(false);
3028 return ExecuteInputAction(action);
3032 g_Joystick.ResetAxis(abs(bid));
3036 if (g_Joystick.GetHat(bid, position))
3039 m_idleTimer.StartZero();
3042 if (WakeUpScreenSaverAndDPMS())
3049 CStdString actionName;
3052 bid = position<<16|bid;
3054 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3056 CAction action(actionID, 1.0f, 0.0f, actionName);
3058 g_Mouse.SetActive(false);
3059 return ExecuteInputAction(action);
3066 bool CApplication::ProcessRemote(float frameTime)
3068 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3069 if (g_RemoteControl.GetButton())
3071 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3072 g_RemoteControl.Reset();
3079 bool CApplication::ProcessPeripherals(float frameTime)
3082 if (g_peripherals.GetNextKeypress(frameTime, key))
3087 bool CApplication::ProcessMouse()
3091 if (!g_Mouse.IsActive() || !m_AppFocused)
3094 // Get the mouse command ID
3095 uint32_t mousecommand = g_Mouse.GetAction();
3096 if (mousecommand == ACTION_NOOP)
3099 // Reset the screensaver and idle timers
3100 m_idleTimer.StartZero();
3102 if (WakeUpScreenSaverAndDPMS())
3105 // Retrieve the corresponding action
3106 int iWin = GetActiveWindowID();
3107 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3108 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3110 // Deactivate mouse if non-mouse action
3111 if (!mouseaction.IsMouse())
3112 g_Mouse.SetActive(false);
3114 // Consume ACTION_NOOP.
3115 // Some views or dialogs gets closed after any ACTION and
3116 // a sensitive mouse might cause problems.
3117 if (mouseaction.GetID() == ACTION_NOOP)
3120 // If we couldn't find an action return false to indicate we have not
3121 // handled this mouse action
3122 if (!mouseaction.GetID())
3124 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3128 // Log mouse actions except for move and noop
3129 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3130 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3132 // The action might not be a mouse action. For example wheel moves might
3133 // be mapped to volume up/down in mouse.xml. In this case we do not want
3134 // the mouse position saved in the action.
3135 if (!mouseaction.IsMouse())
3136 return OnAction(mouseaction);
3138 // This is a mouse action so we need to record the mouse position
3139 return OnAction(CAction(mouseaction.GetID(),
3140 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3141 (float)g_Mouse.GetX(),
3142 (float)g_Mouse.GetY(),
3143 (float)g_Mouse.GetDX(),
3144 (float)g_Mouse.GetDY(),
3145 mouseaction.GetName()));
3148 bool CApplication::ProcessEventServer(float frameTime)
3150 #ifdef HAS_EVENT_SERVER
3151 CEventServer* es = CEventServer::GetInstance();
3152 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3155 // process any queued up actions
3156 if (es->ExecuteNextAction())
3158 // reset idle timers
3159 m_idleTimer.StartZero();
3161 WakeUpScreenSaverAndDPMS();
3164 // now handle any buttons or axis
3165 std::string joystickName;
3166 bool isAxis = false;
3167 float fAmount = 0.0;
3169 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3170 // when the action exits XBMC
3171 es = CEventServer::GetInstance();
3172 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3174 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3178 if (joystickName.length() > 0)
3182 if (fabs(fAmount) >= 0.08)
3183 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3185 m_lastAxisMap[joystickName].erase(wKeyID);
3188 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3193 if (wKeyID & ES_FLAG_UNICODE)
3195 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3199 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3200 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3201 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3202 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3203 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3204 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3205 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3206 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3207 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3208 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3209 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3210 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3211 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3212 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3213 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3214 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3215 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3216 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3217 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3218 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3221 key.SetFromService(true);
3226 if (m_lastAxisMap.size() > 0)
3228 // Process all the stored axis.
3229 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3231 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3232 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3238 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3240 XBMC_Event newEvent;
3241 newEvent.type = XBMC_MOUSEMOTION;
3242 newEvent.motion.xrel = 0;
3243 newEvent.motion.yrel = 0;
3244 newEvent.motion.state = 0;
3245 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3246 newEvent.motion.x = (uint16_t)pos.x;
3247 newEvent.motion.y = (uint16_t)pos.y;
3248 OnEvent(newEvent); // had to call this to update g_Mouse position
3249 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3256 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3258 #if defined(HAS_EVENT_SERVER)
3259 m_idleTimer.StartZero();
3261 // Make sure to reset screen saver, mouse.
3263 if (WakeUpScreenSaverAndDPMS())
3266 #ifdef HAS_SDL_JOYSTICK
3269 g_Mouse.SetActive(false);
3271 int iWin = GetActiveWindowID();
3273 CStdString actionName;
3274 bool fullRange = false;
3276 // Translate using regular joystick translator.
3277 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3278 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3280 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3286 bool CApplication::ExecuteInputAction(const CAction &action)
3288 bool bResult = false;
3290 // play sound before the action unless the button is held,
3291 // where we execute after the action as held actions aren't fired every time.
3292 if(action.GetHoldTime())
3294 bResult = OnAction(action);
3296 g_audioManager.PlayActionSound(action);
3300 g_audioManager.PlayActionSound(action);
3301 bResult = OnAction(action);
3306 int CApplication::GetActiveWindowID(void)
3308 // Get the currently active window
3309 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3311 // If there is a dialog active get the dialog id instead
3312 if (g_windowManager.HasModalDialog())
3313 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3315 // If the window is FullScreenVideo check for special cases
3316 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3318 // check if we're in a DVD menu
3319 if(g_application.m_pPlayer->IsInMenu())
3320 iWin = WINDOW_VIDEO_MENU;
3321 // check for LiveTV and switch to it's virtual window
3322 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3323 iWin = WINDOW_FULLSCREEN_LIVETV;
3326 // Return the window id
3330 bool CApplication::Cleanup()
3334 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3335 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3336 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3337 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3338 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3339 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3340 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3341 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3342 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3343 g_windowManager.Delete(WINDOW_FILES);
3344 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3345 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3346 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3347 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3348 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3349 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3350 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3351 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3352 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3353 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3354 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3355 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3356 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3357 g_windowManager.Delete(WINDOW_DIALOG_OK);
3358 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3359 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3360 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3361 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3362 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3363 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3364 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3365 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3366 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3367 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3368 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3369 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3370 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3371 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3372 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3373 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3374 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3375 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3376 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3377 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3378 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3379 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3380 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3382 /* Delete PVR related windows and dialogs */
3383 g_windowManager.Delete(WINDOW_PVR);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3387 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3388 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3389 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3390 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3391 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3392 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3393 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3394 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3395 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3396 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3398 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3399 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3400 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3401 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3402 g_windowManager.Delete(WINDOW_VISUALISATION);
3403 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3404 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3405 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3406 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3407 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3408 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3409 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3410 g_windowManager.Delete(WINDOW_SCREENSAVER);
3411 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3412 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3413 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3414 g_windowManager.Delete(WINDOW_SLIDESHOW);
3415 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3416 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3418 g_windowManager.Delete(WINDOW_HOME);
3419 g_windowManager.Delete(WINDOW_PROGRAMS);
3420 g_windowManager.Delete(WINDOW_PICTURES);
3421 g_windowManager.Delete(WINDOW_WEATHER);
3423 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3424 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3425 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3426 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3427 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3428 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3429 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3430 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3431 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3432 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3434 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3435 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3437 CAddonMgr::Get().DeInit();
3439 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3440 CLog::Log(LOGNOTICE, "closing down remote control service");
3441 g_RemoteControl.Disconnect();
3444 CLog::Log(LOGNOTICE, "unload sections");
3446 #ifdef HAS_PERFORMANCE_SAMPLE
3447 CLog::Log(LOGNOTICE, "performance statistics");
3448 m_perfStats.DumpStats();
3451 // Shutdown as much as possible of the
3452 // application, to reduce the leaks dumped
3453 // to the vc output window before calling
3454 // _CrtDumpMemoryLeaks(). Most of the leaks
3455 // shown are no real leaks, as parts of the app
3456 // are still allocated.
3458 g_localizeStrings.Clear();
3459 g_LangCodeExpander.Clear();
3460 g_charsetConverter.clear();
3461 g_directoryCache.Clear();
3462 CButtonTranslator::GetInstance().Clear();
3463 #ifdef HAS_EVENT_SERVER
3464 CEventServer::RemoveInstance();
3466 DllLoaderContainer::Clear();
3467 g_playlistPlayer.Clear();
3468 CSettings::Get().Uninitialize();
3469 g_advancedSettings.Clear();
3472 CXHandle::DumpObjectTracker();
3474 #ifdef HAS_DVD_DRIVE
3475 CLibcdio::ReleaseInstance();
3478 #if defined(TARGET_ANDROID)
3479 // enable for all platforms once it's safe
3480 g_sectionLoader.UnloadAll();
3482 #ifdef _CRTDBG_MAP_ALLOC
3483 _CrtDumpMemoryLeaks();
3484 while(1); // execution ends
3494 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3499 void CApplication::Stop(int exitCode)
3503 CVariant vExitCode(exitCode);
3504 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3506 SaveFileState(true);
3508 g_alarmClock.StopThread();
3510 if( m_bSystemScreenSaverEnable )
3511 g_Windowing.EnableSystemScreenSaver(true);
3513 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3514 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3516 // Update the settings information (volume, uptime etc. need saving)
3517 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3519 CLog::Log(LOGNOTICE, "Saving settings");
3520 CSettings::Get().Save();
3523 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3526 m_AppFocused = false;
3527 m_ExitCode = exitCode;
3528 CLog::Log(LOGNOTICE, "stop all");
3530 // cancel any jobs from the jobmanager
3531 CJobManager::GetInstance().CancelJobs();
3533 // stop scanning before we kill the network and so on
3534 if (m_musicInfoScanner->IsScanning())
3535 m_musicInfoScanner->Stop();
3537 if (m_videoInfoScanner->IsScanning())
3538 m_videoInfoScanner->Stop();
3540 CApplicationMessenger::Get().Cleanup();
3542 CLog::Log(LOGNOTICE, "stop player");
3543 m_pPlayer->ClosePlayer();
3549 #if HAS_FILESYTEM_DAAP
3550 CLog::Log(LOGNOTICE, "stop daap clients");
3551 g_DaapClient.Release();
3553 #ifdef HAS_FILESYSTEM_SAP
3554 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3555 g_sapsessions.StopThread();
3558 if(CZeroconfBrowser::IsInstantiated())
3560 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3561 CZeroconfBrowser::GetInstance()->Stop();
3562 CZeroconfBrowser::ReleaseInstance();
3566 CLog::Log(LOGNOTICE, "clean cached files!");
3567 #ifdef HAS_FILESYSTEM_RAR
3568 g_RarManager.ClearCache(true);
3571 #ifdef HAS_FILESYSTEM_SFTP
3572 CSFTPSessionManager::DisconnectAllSessions();
3575 CLog::Log(LOGNOTICE, "unload skin");
3578 #if defined(TARGET_DARWIN_OSX)
3579 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3580 XBMCHelper::GetInstance().Stop();
3583 #if defined(HAVE_LIBCRYSTALHD)
3584 CCrystalHD::RemoveInstance();
3587 g_mediaManager.Stop();
3589 // Stop services before unloading Python
3590 CAddonMgr::Get().StopServices(false);
3592 // stop all remaining scripts; must be done after skin has been unloaded,
3593 // not before some windows still need it when deinitializing during skin
3595 CScriptInvocationManager::Get().Uninitialize();
3597 g_Windowing.DestroyRenderSystem();
3598 g_Windowing.DestroyWindow();
3599 g_Windowing.DestroyWindowSystem();
3601 // shutdown the AudioEngine
3602 CAEFactory::Shutdown();
3603 CAEFactory::UnLoadEngine();
3605 CLog::Log(LOGNOTICE, "stopped");
3609 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3612 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3613 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3620 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3622 //If item is a plugin, expand out now and run ourselves again
3623 if (item.IsPlugin())
3625 CFileItem item_new(item);
3626 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3627 return PlayMedia(item_new, iPlaylist);
3630 if (item.IsSmartPlayList())
3632 CFileItemList items;
3633 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3636 CSmartPlaylist smartpl;
3637 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3638 smartpl.OpenAndReadName(item.GetPath());
3640 playlist.Add(items);
3641 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3644 else if (item.IsPlayList() || item.IsInternetStream())
3646 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3648 //is or could be a playlist
3649 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3650 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3655 if (dlgCache->IsCanceled())
3662 if (iPlaylist != PLAYLIST_NONE)
3665 if (item.HasProperty("playlist_starting_track"))
3666 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3667 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3671 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());
3672 if(pPlayList->size())
3673 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3678 //nothing special just play
3679 return PlayFile(item, false) == PLAYBACK_OK;
3683 // For playing a multi-file video. Particularly inefficient
3684 // on startup, as we are required to calculate the length
3685 // of each video, so we open + close each one in turn.
3686 // A faster calculation of video time would improve this
3688 // return value: same with PlayFile()
3689 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3691 if (!item.IsStack())
3692 return PLAYBACK_FAIL;
3696 // case 1: stacked ISOs
3697 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3699 CStackDirectory dir;
3700 CFileItemList movieList;
3701 dir.GetDirectory(item.GetPath(), movieList);
3703 // first assume values passed to the stack
3704 int selectedFile = item.m_lStartPartNumber;
3705 int startoffset = item.m_lStartOffset;
3707 // check if we instructed the stack to resume from default
3708 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3713 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3715 startoffset = (int)(bookmark.timeInSeconds*75);
3716 selectedFile = bookmark.partNumber;
3721 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3724 // make sure that the selected part is within the boundaries
3725 if (selectedFile <= 0)
3727 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3730 else if (selectedFile > movieList.Size())
3732 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3733 selectedFile = movieList.Size();
3736 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3737 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3738 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3739 *m_stackFileItemToUpdate = item;
3740 return PlayFile(*(movieList[selectedFile - 1]));
3742 // case 2: all other stacks
3745 // see if we have the info in the database
3746 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3747 // then these times will be wrong.
3748 // Also, this is really just a hack for the slow load up times we have
3749 // A much better solution is a fast reader of FPS and fileLength
3750 // that we can use on a file to get it's time.
3752 bool haveTimes(false);
3756 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3757 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3762 // calculate the total time of the stack
3763 CStackDirectory dir;
3764 dir.GetDirectory(item.GetPath(), *m_currentStack);
3766 for (int i = 0; i < m_currentStack->Size(); i++)
3769 (*m_currentStack)[i]->m_lEndOffset = times[i];
3773 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3775 m_currentStack->Clear();
3776 return PLAYBACK_FAIL;
3778 totalTime += duration / 1000;
3779 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3780 times.push_back(totalTime);
3784 double seconds = item.m_lStartOffset / 75.0;
3786 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3787 { // have our times now, so update the dB
3791 dbs.SetStackTimes(item.GetPath(), times);
3793 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3795 // can only resume seek here, not dvdstate
3797 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3798 seconds = bookmark.timeInSeconds;
3806 *m_itemCurrentFile = item;
3807 m_currentStackPosition = 0;
3808 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3812 // work out where to seek to
3813 for (int i = 0; i < m_currentStack->Size(); i++)
3815 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3817 CFileItem item(*(*m_currentStack)[i]);
3818 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3819 item.m_lStartOffset = (long)(seconds - start) * 75;
3820 m_currentStackPosition = i;
3821 return PlayFile(item, true);
3826 return PlayFile(*(*m_currentStack)[0], true);
3828 return PLAYBACK_FAIL;
3831 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3833 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3834 if (item.GetMimeType().empty())
3835 const_cast<CFileItem&>(item).FillInMimeType();
3839 SaveCurrentFileSettings();
3841 OutputDebugString("new file set audiostream:0\n");
3842 // Switch to default options
3843 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3844 // see if we have saved options in the database
3846 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3847 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3849 *m_itemCurrentFile = item;
3850 m_nextPlaylistItem = -1;
3851 m_currentStackPosition = 0;
3852 m_currentStack->Clear();
3855 CUtil::ClearSubtitles();
3858 if (item.IsDiscStub())
3860 #ifdef HAS_DVD_DRIVE
3861 // Display the Play Eject dialog if there is any optical disc drive
3862 if (g_mediaManager.HasOpticalDrive())
3864 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3865 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3866 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3867 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3871 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3876 if (item.IsPlayList())
3877 return PLAYBACK_FAIL;
3879 if (item.IsPlugin())
3880 { // we modify the item so that it becomes a real URL
3881 CFileItem item_new(item);
3882 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3883 return PlayFile(item_new, false);
3884 return PLAYBACK_FAIL;
3888 if (URIUtils::IsUPnP(item.GetPath()))
3890 CFileItem item_new(item);
3891 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3892 return PlayFile(item_new, false);
3893 return PLAYBACK_FAIL;
3897 // if we have a stacked set of files, we need to setup our stack routines for
3898 // "seamless" seeking and total time of the movie etc.
3899 // will recall with restart set to true
3901 return PlayStack(item, bRestart);
3903 //Is TuxBox, this should probably be moved to CTuxBoxFile
3906 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3908 if(g_tuxboxService.IsRunning())
3909 g_tuxboxService.Stop();
3911 PlayBackRet ret = PLAYBACK_FAIL;
3913 if(g_tuxbox.CreateNewItem(item, item_new))
3916 // Make sure it doesn't have a player
3917 // so we actually select one normally
3918 m_pPlayer->ResetPlayer();
3920 // keep the tuxbox:// url as playing url
3921 // and give the new url to the player
3922 ret = PlayFile(item_new, true);
3923 if(ret == PLAYBACK_OK)
3925 if(!g_tuxboxService.IsRunning())
3926 g_tuxboxService.Start();
3932 CPlayerOptions options;
3934 if( item.HasProperty("StartPercent") )
3936 double fallback = 0.0f;
3937 if(item.GetProperty("StartPercent").isString())
3938 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3939 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3942 PLAYERCOREID eNewCore = EPC_NONE;
3945 // have to be set here due to playstack using this for starting the file
3946 options.starttime = item.m_lStartOffset / 75.0;
3947 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3948 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3950 if( m_eForcedNextPlayer != EPC_NONE )
3951 eNewCore = m_eForcedNextPlayer;
3952 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3953 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3955 eNewCore = m_pPlayer->GetCurrentPlayer();
3959 options.starttime = item.m_lStartOffset / 75.0;
3963 // open the d/b and retrieve the bookmarks for the current movie
3966 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3968 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3970 options.starttime = 0.0f;
3972 CStdString path = item.GetPath();
3973 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3974 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3975 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3976 path = item.GetProperty("original_listitem_url").asString();
3977 if(dbs.GetResumeBookMark(path, bookmark))
3979 options.starttime = bookmark.timeInSeconds;
3980 options.state = bookmark.playerState;
3983 override with information from the actual item if available. We do this as the VFS (eg plugins)
3984 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3985 should the playerState be required, it is fetched from the database.
3986 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3988 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3989 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3991 else if (item.HasVideoInfoTag())
3993 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3995 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3998 dbs.GetBookMarkForEpisode(*tag, bookmark);
3999 options.starttime = bookmark.timeInSeconds;
4000 options.state = bookmark.playerState;
4007 if (m_eForcedNextPlayer != EPC_NONE)
4008 eNewCore = m_eForcedNextPlayer;
4010 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4013 // this really aught to be inside !bRestart, but since PlayStack
4014 // uses that to init playback, we have to keep it outside
4015 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4016 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4017 { // playing from a playlist by the looks
4018 // don't switch to fullscreen if we are not playing the first item...
4019 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4021 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4023 // TODO - this will fail if user seeks back to first file in stack
4024 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4025 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4027 options.fullscreen = false;
4028 // reset this so we don't think we are resuming on seek
4029 m_itemCurrentFile->m_lStartOffset = 0;
4032 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4034 // reset VideoStartWindowed as it's a temp setting
4035 CMediaSettings::Get().SetVideoStartWindowed(false);
4038 //We have to stop parsing a cdg before mplayer is deallocated
4039 // WHY do we have to do this????
4041 m_pKaraokeMgr->Stop();
4045 CSingleLock lock(m_playStateMutex);
4046 // tell system we are starting a file
4047 m_bPlaybackStarting = true;
4049 // for playing a new item, previous playing item's callback may already
4050 // pushed some delay message into the threadmessage list, they are not
4051 // expected be processed after or during the new item playback starting.
4052 // so we clean up previous playing item's playback callback delay messages here.
4053 int previousMsgsIgnoredByNewPlaying[] = {
4054 GUI_MSG_PLAYBACK_STARTED,
4055 GUI_MSG_PLAYBACK_ENDED,
4056 GUI_MSG_PLAYBACK_STOPPED,
4057 GUI_MSG_PLAYLIST_CHANGED,
4058 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4059 GUI_MSG_PLAYLISTPLAYER_STARTED,
4060 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4061 GUI_MSG_QUEUE_NEXT_ITEM,
4064 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4066 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4069 // We should restart the player, unless the previous and next tracks are using
4070 // one of the players that allows gapless playback (paplayer, dvdplayer)
4071 m_pPlayer->ClosePlayerGapless(eNewCore);
4073 // now reset play state to starting, since we already stopped the previous playing item if there is.
4074 // and from now there should be no playback callback from previous playing item be called.
4075 m_ePlayState = PLAY_STATE_STARTING;
4077 m_pPlayer->CreatePlayer(eNewCore, *this);
4079 PlayBackRet iResult;
4080 if (m_pPlayer->HasPlayer())
4082 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4083 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4084 * increase performance on low powered systems (Atom/ARM).
4088 CJobManager::GetInstance().PauseJobs();
4091 // don't hold graphicscontext here since player
4092 // may wait on another thread, that requires gfx
4093 CSingleExit ex(g_graphicsContext);
4095 iResult = m_pPlayer->OpenFile(item, options);
4099 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4100 iResult = PLAYBACK_FAIL;
4103 if(iResult == PLAYBACK_OK)
4105 if (m_pPlayer->GetPlaySpeed() != 1)
4107 int iSpeed = m_pPlayer->GetPlaySpeed();
4108 m_pPlayer->m_iPlaySpeed = 1;
4109 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4112 // if player has volume control, set it.
4113 if (m_pPlayer->ControlsVolume())
4115 m_pPlayer->SetVolume(m_volumeLevel);
4116 m_pPlayer->SetMute(m_muted);
4119 if( m_pPlayer->IsPlayingAudio() )
4121 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4122 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4125 #ifdef HAS_VIDEO_PLAYBACK
4126 else if( m_pPlayer->IsPlayingVideo() )
4128 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4129 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4131 // if player didn't manange to switch to fullscreen by itself do it here
4132 if( options.fullscreen && g_renderManager.IsStarted()
4133 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4134 SwitchToFullScreen();
4139 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4140 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4141 g_windowManager.PreviousWindow();
4145 #if !defined(TARGET_POSIX)
4146 g_audioManager.Enable(false);
4149 if (item.HasPVRChannelInfoTag())
4150 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4153 CSingleLock lock(m_playStateMutex);
4154 m_bPlaybackStarting = false;
4156 if (iResult == PLAYBACK_OK)
4158 // play state: none, starting; playing; stopped; ended.
4159 // last 3 states are set by playback callback, they are all ignored during starting,
4160 // but we recorded the state, here we can make up the callback for the state.
4161 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4162 switch (m_ePlayState)
4164 case PLAY_STATE_PLAYING:
4165 OnPlayBackStarted();
4167 // FIXME: it seems no meaning to callback started here if there was an started callback
4168 // before this stopped/ended callback we recorded. if we callback started here
4169 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4170 // which will send OnStop announce at once, so currently, just call stopped/ended.
4171 case PLAY_STATE_ENDED:
4174 case PLAY_STATE_STOPPED:
4175 OnPlayBackStopped();
4177 case PLAY_STATE_STARTING:
4178 // neither started nor stopped/ended callback be called, that means the item still
4179 // not started, we need not make up any callback, just leave this and
4180 // let the player callback do its work.
4186 else if (iResult == PLAYBACK_FAIL)
4188 // we send this if it isn't playlistplayer that is doing this
4189 int next = g_playlistPlayer.GetNextSong();
4190 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4193 OnPlayBackStopped();
4194 m_ePlayState = PLAY_STATE_NONE;
4200 void CApplication::OnPlayBackEnded()
4202 CSingleLock lock(m_playStateMutex);
4203 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4204 m_ePlayState = PLAY_STATE_ENDED;
4205 if(m_bPlaybackStarting)
4208 // informs python script currently running playback has ended
4209 // (does nothing if python is not loaded)
4211 g_pythonParser.OnPlayBackEnded();
4214 CVariant data(CVariant::VariantTypeObject);
4216 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4218 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4219 g_windowManager.SendThreadMessage(msg);
4222 void CApplication::OnPlayBackStarted()
4224 CSingleLock lock(m_playStateMutex);
4225 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4226 m_ePlayState = PLAY_STATE_PLAYING;
4227 if(m_bPlaybackStarting)
4231 // informs python script currently running playback has started
4232 // (does nothing if python is not loaded)
4233 g_pythonParser.OnPlayBackStarted();
4236 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4237 g_windowManager.SendThreadMessage(msg);
4240 void CApplication::OnQueueNextItem()
4242 CSingleLock lock(m_playStateMutex);
4243 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4244 if(m_bPlaybackStarting)
4246 // informs python script currently running that we are requesting the next track
4247 // (does nothing if python is not loaded)
4249 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4252 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4253 g_windowManager.SendThreadMessage(msg);
4256 void CApplication::OnPlayBackStopped()
4258 CSingleLock lock(m_playStateMutex);
4259 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4260 m_ePlayState = PLAY_STATE_STOPPED;
4261 if(m_bPlaybackStarting)
4264 // informs python script currently running playback has ended
4265 // (does nothing if python is not loaded)
4267 g_pythonParser.OnPlayBackStopped();
4270 CVariant data(CVariant::VariantTypeObject);
4271 data["end"] = false;
4272 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4274 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4275 g_windowManager.SendThreadMessage(msg);
4278 void CApplication::OnPlayBackPaused()
4281 g_pythonParser.OnPlayBackPaused();
4285 param["player"]["speed"] = 0;
4286 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4287 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4290 void CApplication::OnPlayBackResumed()
4293 g_pythonParser.OnPlayBackResumed();
4297 param["player"]["speed"] = 1;
4298 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4299 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4302 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4305 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4309 param["player"]["speed"] = iSpeed;
4310 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4311 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4314 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4317 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4321 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4322 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4323 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4324 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4325 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4326 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4329 void CApplication::OnPlayBackSeekChapter(int iChapter)
4332 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4336 bool CApplication::IsPlayingFullScreenVideo() const
4338 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4341 bool CApplication::IsFullScreen()
4343 return IsPlayingFullScreenVideo() ||
4344 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4345 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4348 void CApplication::SaveFileState(bool bForeground /* = false */)
4350 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4355 CSaveFileStateJob job(*m_progressTrackingItem,
4356 *m_stackFileItemToUpdate,
4357 m_progressTrackingVideoResumeBookmark,
4358 m_progressTrackingPlayCountUpdate);
4360 // Run job in the foreground to make sure it finishes
4365 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4366 *m_stackFileItemToUpdate,
4367 m_progressTrackingVideoResumeBookmark,
4368 m_progressTrackingPlayCountUpdate);
4369 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4373 void CApplication::UpdateFileState()
4375 // Did the file change?
4376 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4380 // Reset tracking item
4381 m_progressTrackingItem->Reset();
4385 if (m_pPlayer->IsPlaying())
4387 if (m_progressTrackingItem->GetPath() == "")
4390 *m_progressTrackingItem = CurrentFileItem();
4391 m_progressTrackingPlayCountUpdate = false;
4394 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4395 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4396 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4397 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4399 m_progressTrackingPlayCountUpdate = true;
4402 // Check whether we're *really* playing video else we may race when getting eg. stream details
4403 if (m_pPlayer->IsPlayingVideo())
4405 /* Always update streamdetails, except for DVDs where we only update
4406 streamdetails if title length > 15m (Should yield more correct info) */
4407 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4409 CStreamDetails details;
4410 // Update with stream details from player, if any
4411 if (m_pPlayer->GetStreamDetails(details))
4412 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4414 if (m_progressTrackingItem->IsStack())
4415 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4418 // Update bookmark for save
4419 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4420 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4421 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4423 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4424 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4426 // Delete the bookmark
4427 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4430 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4432 // Update the bookmark
4433 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4434 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4439 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4446 void CApplication::StopPlaying()
4448 int iWin = g_windowManager.GetActiveWindow();
4449 if ( m_pPlayer->IsPlaying() )
4453 m_pKaraokeMgr->Stop();
4456 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4457 g_PVRManager.SaveCurrentChannelSettings();
4459 m_pPlayer->CloseFile();
4461 // turn off visualisation window when stopping
4462 if ((iWin == WINDOW_VISUALISATION
4463 || iWin == WINDOW_FULLSCREEN_VIDEO)
4465 g_windowManager.PreviousWindow();
4467 g_partyModeManager.Disable();
4471 void CApplication::ResetSystemIdleTimer()
4473 // reset system idle timer
4474 m_idleTimer.StartZero();
4477 void CApplication::ResetScreenSaver()
4480 m_shutdownTimer.StartZero();
4482 // screen saver timer is reset only if we're not already in screensaver or
4484 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4485 ResetScreenSaverTimer();
4488 void CApplication::ResetScreenSaverTimer()
4490 m_screenSaverTimer.StartZero();
4493 void CApplication::StopScreenSaverTimer()
4495 m_screenSaverTimer.Stop();
4498 bool CApplication::ToggleDPMS(bool manual)
4500 if (manual || (m_dpmsIsManual == manual))
4504 m_dpmsIsActive = false;
4505 m_dpmsIsManual = false;
4506 return m_dpms->DisablePowerSaving();
4510 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4512 m_dpmsIsActive = true;
4513 m_dpmsIsManual = manual;
4521 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4525 // First reset DPMS, if active
4530 // TODO: if screensaver lock is specified but screensaver is not active
4531 // (DPMS came first), activate screensaver now.
4533 ResetScreenSaverTimer();
4534 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4537 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4541 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4542 CVariant data(bPowerOffKeyPressed);
4543 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4549 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4551 if (m_iScreenSaveLock == 2)
4554 // if Screen saver is active
4555 if (m_bScreenSave && m_screenSaver)
4557 if (m_iScreenSaveLock == 0)
4558 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4559 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4560 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4561 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4563 m_iScreenSaveLock = 2;
4564 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4566 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4568 pWindow->OnMessage(msg);
4570 if (m_iScreenSaveLock == -1)
4572 m_iScreenSaveLock = 0;
4576 // disable screensaver
4577 m_bScreenSave = false;
4578 m_iScreenSaveLock = 0;
4579 ResetScreenSaverTimer();
4581 if (m_screenSaver->ID() == "visualization")
4583 // we can just continue as usual from vis mode
4586 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4588 else if (!m_screenSaver->ID().empty())
4589 { // we're in screensaver window
4590 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4591 g_windowManager.PreviousWindow(); // show the previous window
4592 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4593 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4601 void CApplication::CheckScreenSaverAndDPMS()
4603 if (m_bInBackground)
4605 if (!m_dpmsIsActive)
4606 g_Windowing.ResetOSScreensaver();
4608 bool maybeScreensaver =
4609 !m_dpmsIsActive && !m_bScreenSave
4610 && !CSettings::Get().GetString("screensaver.mode").empty();
4612 !m_dpmsIsActive && m_dpms->IsSupported()
4613 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4615 // Has the screen saver window become active?
4616 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4618 m_bScreenSave = true;
4619 maybeScreensaver = false;
4622 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4624 WakeUpScreenSaverAndDPMS();
4628 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4630 // See if we need to reset timer.
4631 // * Are we playing a video and it is not paused?
4632 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4633 // * Are we playing some music in fullscreen vis?
4634 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4635 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4637 ResetScreenSaverTimer();
4641 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4643 // DPMS has priority (it makes the screensaver not needed)
4645 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4648 WakeUpScreenSaver();
4650 else if (maybeScreensaver
4651 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4653 ActivateScreenSaver();
4657 // activate the screensaver.
4658 // if forceType is true, we ignore the various conditions that can alter
4659 // the type of screensaver displayed
4660 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4662 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4663 { // just activate the visualisation if user toggled the usemusicvisinstead option
4664 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4668 m_bScreenSave = true;
4670 // Get Screensaver Mode
4671 m_screenSaver.reset();
4672 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4673 m_screenSaver.reset(new CScreenSaver(""));
4675 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4677 // disable screensaver lock from the login screen
4678 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4681 // set to Dim in the case of a dialog on screen or playing video
4682 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4684 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4685 m_screenSaver.reset(new CScreenSaver(""));
4688 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4690 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4692 else if (!m_screenSaver->ID().empty())
4693 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4696 void CApplication::SetInBackground(bool background)
4700 ResetScreenSaverTimer();
4702 m_bInBackground = background;
4705 void CApplication::CheckShutdown()
4707 // first check if we should reset the timer
4708 bool resetTimer = m_bInhibitIdleShutdown;
4710 if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4713 if (m_musicInfoScanner->IsScanning())
4716 if (m_videoInfoScanner->IsScanning())
4719 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4722 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4727 m_shutdownTimer.StartZero();
4731 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4733 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4734 m_shutdownTimer.Stop();
4737 CApplicationMessenger::Get().Shutdown();
4741 void CApplication::InhibitIdleShutdown(bool inhibit)
4743 m_bInhibitIdleShutdown = inhibit;
4746 bool CApplication::IsIdleShutdownInhibited() const
4748 return m_bInhibitIdleShutdown;
4751 bool CApplication::OnMessage(CGUIMessage& message)
4753 switch ( message.GetMessage() )
4755 case GUI_MSG_NOTIFY_ALL:
4757 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4759 // Update general playlist: Remove DVD playlist items
4760 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4763 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4764 g_windowManager.SendMessage( msg );
4766 // stop the file if it's on dvd (will set the resume point etc)
4767 if (m_itemCurrentFile->IsOnDVD())
4773 case GUI_MSG_PLAYBACK_STARTED:
4775 #ifdef TARGET_DARWIN
4776 DarwinSetScheduling(message.GetMessage());
4778 // reset the seek handler
4779 m_seekHandler->Reset();
4780 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4782 // Update our infoManager with the new details etc.
4783 if (m_nextPlaylistItem >= 0)
4785 // playing an item which is not in the list - player might be stopped already
4787 if (playList.size() <= m_nextPlaylistItem)
4790 // we've started a previously queued item
4791 CFileItemPtr item = playList[m_nextPlaylistItem];
4792 // update the playlist manager
4793 int currentSong = g_playlistPlayer.GetCurrentSong();
4794 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4795 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4796 g_windowManager.SendThreadMessage(msg);
4797 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4798 *m_itemCurrentFile = *item;
4800 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4801 g_partyModeManager.OnSongChange(true);
4804 param["player"]["speed"] = 1;
4805 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4806 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4808 if (m_pPlayer->IsPlayingAudio())
4810 // Start our cdg parser as appropriate
4812 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4814 m_pKaraokeMgr->Stop();
4815 if (m_itemCurrentFile->IsMusicDb())
4817 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4819 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4820 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4823 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4826 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4835 case GUI_MSG_QUEUE_NEXT_ITEM:
4837 // Check to see if our playlist player has a new item for us,
4838 // and if so, we check whether our current player wants the file
4839 int iNext = g_playlistPlayer.GetNextSong();
4840 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4841 if (iNext < 0 || iNext >= playlist.size())
4843 m_pPlayer->OnNothingToQueueNotify();
4844 return true; // nothing to do
4847 // ok, grab the next song
4848 CFileItem file(*playlist[iNext]);
4850 CURL url(file.GetPath());
4851 if (url.GetProtocol() == "plugin")
4852 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4855 if (URIUtils::IsUPnP(file.GetPath()))
4857 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4862 // ok - send the file to the player, if it accepts it
4863 if (m_pPlayer->QueueNextFile(file))
4865 // player accepted the next file
4866 m_nextPlaylistItem = iNext;
4870 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4871 queue the next (if it wants to) and it doesn't keep looping on this song */
4872 g_playlistPlayer.SetCurrentSong(iNext);
4879 case GUI_MSG_PLAYBACK_STOPPED:
4880 case GUI_MSG_PLAYBACK_ENDED:
4881 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4885 m_pKaraokeMgr->Stop();
4887 #ifdef TARGET_DARWIN
4888 DarwinSetScheduling(message.GetMessage());
4890 // first check if we still have items in the stack to play
4891 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4893 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4894 { // just play the next item in the stack
4895 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4900 // In case playback ended due to user eg. skipping over the end, clear
4901 // our resume bookmark here
4902 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4904 // Delete the bookmark
4905 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4908 // reset the current playing file
4909 m_itemCurrentFile->Reset();
4910 g_infoManager.ResetCurrentItem();
4911 m_currentStack->Clear();
4913 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4915 g_playlistPlayer.PlayNext(1, true);
4919 // reset any forced player
4920 m_eForcedNextPlayer = EPC_NONE;
4922 m_pPlayer->ClosePlayer();
4925 m_pPlayer->m_iPlaySpeed = 1;
4928 if (!m_pPlayer->IsPlaying())
4930 g_audioManager.Enable(true);
4933 if (!m_pPlayer->IsPlayingVideo())
4935 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4937 g_windowManager.PreviousWindow();
4941 CSingleLock lock(g_graphicsContext);
4942 // resets to res_desktop or look&feel resolution (including refreshrate)
4943 g_graphicsContext.SetFullScreenVideo(false);
4947 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4949 CSettings::Get().Save(); // save vis settings
4950 WakeUpScreenSaverAndDPMS();
4951 g_windowManager.PreviousWindow();
4954 // DVD ejected while playing in vis ?
4955 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4958 CSettings::Get().Save(); // save vis settings
4959 WakeUpScreenSaverAndDPMS();
4960 g_windowManager.PreviousWindow();
4963 if (IsEnableTestMode())
4964 CApplicationMessenger::Get().Quit();
4969 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4970 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4975 case GUI_MSG_FULLSCREEN:
4976 { // Switch to fullscreen, if we can
4977 SwitchToFullScreen();
4981 case GUI_MSG_EXECUTE:
4982 if (message.GetNumStringParams())
4983 return ExecuteXBMCAction(message.GetStringParam());
4989 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4991 // see if it is a user set string
4993 //We don't know if there is unsecure information in this yet, so we
4994 //postpone any logging
4995 const std::string in_actionStr(actionStr);
4996 CLog::Log(LOGDEBUG,"%s : Translating action string", __FUNCTION__);
4997 CGUIInfoLabel info(actionStr, "");
4998 actionStr = info.GetLabel(0);
5000 // user has asked for something to be executed
5001 if (CBuiltins::HasCommand(actionStr))
5002 CBuiltins::Execute(actionStr);
5005 // try translating the action from our ButtonTranslator
5007 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5009 OnAction(CAction(actionID));
5012 CFileItem item(actionStr, false);
5014 if (item.IsPythonScript())
5015 { // a python script
5016 CScriptInvocationManager::Get().Execute(item.GetPath());
5020 if (item.IsAudio() || item.IsVideo())
5021 { // an audio or video file
5026 //At this point we have given up to translate, so even though
5027 //there may be insecure information, we log it.
5028 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5035 void CApplication::Process()
5039 // dispatch the messages generated by python or other threads to the current window
5040 g_windowManager.DispatchThreadMessages();
5042 // process messages which have to be send to the gui
5043 // (this can only be done after g_windowManager.Render())
5044 CApplicationMessenger::Get().ProcessWindowMessages();
5048 m_loggingIn = false;
5050 // autoexec.py - profile
5051 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5053 if (XFILE::CFile::Exists(strAutoExecPy))
5054 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5056 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5059 // handle any active scripts
5060 CScriptInvocationManager::Get().Process();
5062 // process messages, even if a movie is playing
5063 CApplicationMessenger::Get().ProcessMessages();
5064 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5066 // check how far we are through playing the current item
5067 // and do anything that needs doing (playcount updates etc)
5068 CheckPlayingProgress();
5071 m_pPlayer->DoAudioWork();
5073 // do any processing that isn't needed on each run
5074 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5076 m_slowTimer.Reset();
5080 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5083 // We get called every 500ms
5084 void CApplication::ProcessSlow()
5086 g_powerManager.ProcessEvents();
5088 #if defined(TARGET_DARWIN_OSX)
5089 // There is an issue on OS X that several system services ask the cursor to become visible
5090 // during their startup routines. Given that we can't control this, we hack it in by
5092 if (g_Windowing.IsFullScreen())
5093 { // SDL thinks it's hidden
5098 // Temporarely pause pausable jobs when viewing video/picture
5099 int currentWindow = g_windowManager.GetActiveWindow();
5100 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5102 CJobManager::GetInstance().PauseJobs();
5106 CJobManager::GetInstance().UnPauseJobs();
5109 // Store our file state for use on close()
5112 // Check if we need to activate the screensaver / DPMS.
5113 CheckScreenSaverAndDPMS();
5115 // Check if we need to shutdown (if enabled).
5116 #if defined(TARGET_DARWIN)
5117 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5119 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5125 // check if we should restart the player
5126 CheckDelayedPlayerRestart();
5128 // check if we can unload any unreferenced dlls or sections
5129 if (!m_pPlayer->IsPlayingVideo())
5130 CSectionLoader::UnloadDelayed();
5132 // check for any idle curl connections
5133 g_curlInterface.CheckIdle();
5135 // check for any idle myth sessions
5136 CMythSession::CheckIdle();
5138 #ifdef HAS_FILESYSTEM_HTSP
5139 // check for any idle htsp sessions
5140 HTSP::CHTSPDirectorySession::CheckIdle();
5144 if ( m_pKaraokeMgr )
5145 m_pKaraokeMgr->ProcessSlow();
5148 if (!m_pPlayer->IsPlayingVideo())
5149 g_largeTextureManager.CleanupUnusedImages();
5151 g_TextureManager.FreeUnusedTextures(5000);
5153 #ifdef HAS_DVD_DRIVE
5154 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5155 if (!m_pPlayer->IsPlayingVideo())
5156 m_Autorun->HandleAutorun();
5159 // update upnp server/renderer states
5161 if(UPNP::CUPnP::IsInstantiated())
5162 UPNP::CUPnP::GetInstance()->UpdateState();
5165 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5169 #ifdef HAS_FILESYSTEM_NFS
5170 gNfsConnection.CheckIfIdle();
5173 #ifdef HAS_FILESYSTEM_AFP
5174 gAfpConnection.CheckIfIdle();
5177 #ifdef HAS_FILESYSTEM_SFTP
5178 CSFTPSessionManager::ClearOutIdleSessions();
5181 g_mediaManager.ProcessEvents();
5184 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5185 g_RemoteControl.Initialize();
5188 if (!m_pPlayer->IsPlayingVideo())
5189 CAddonInstaller::Get().UpdateRepos();
5191 CAEFactory::GarbageCollect();
5195 // Global Idle Time in Seconds
5196 // idle time will be resetet if on any OnKey()
5197 // int return: system Idle time in seconds! 0 is no idle!
5198 int CApplication::GlobalIdleTime()
5200 if(!m_idleTimer.IsRunning())
5203 m_idleTimer.StartZero();
5205 return (int)m_idleTimer.GetElapsedSeconds();
5208 float CApplication::NavigationIdleTime()
5210 if (!m_navigationTimer.IsRunning())
5212 m_navigationTimer.Stop();
5213 m_navigationTimer.StartZero();
5215 return m_navigationTimer.GetElapsedSeconds();
5218 void CApplication::DelayedPlayerRestart()
5220 m_restartPlayerTimer.StartZero();
5223 void CApplication::CheckDelayedPlayerRestart()
5225 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5227 m_restartPlayerTimer.Stop();
5228 m_restartPlayerTimer.Reset();
5233 void CApplication::Restart(bool bSamePosition)
5235 // this function gets called when the user changes a setting (like noninterleaved)
5236 // and which means we gotta close & reopen the current playing file
5238 // first check if we're playing a file
5239 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5242 if( !m_pPlayer->HasPlayer() )
5247 // do we want to return to the current position in the file
5248 if (false == bSamePosition)
5250 // no, then just reopen the file and start at the beginning
5251 PlayFile(*m_itemCurrentFile, true);
5255 // else get current position
5256 double time = GetTime();
5258 // get player state, needed for dvd's
5259 CStdString state = m_pPlayer->GetPlayerState();
5261 // set the requested starttime
5262 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5265 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5266 m_pPlayer->SetPlayerState(state);
5269 const CStdString& CApplication::CurrentFile()
5271 return m_itemCurrentFile->GetPath();
5274 CFileItem& CApplication::CurrentFileItem()
5276 return *m_itemCurrentFile;
5279 CFileItem& CApplication::CurrentUnstackedItem()
5281 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5282 return *(*m_currentStack)[m_currentStackPosition];
5284 return *m_itemCurrentFile;
5287 void CApplication::ShowVolumeBar(const CAction *action)
5289 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5294 volumeBar->OnAction(*action);
5298 bool CApplication::IsMuted() const
5300 if (g_peripherals.IsMuted())
5302 return CAEFactory::IsMuted();
5305 void CApplication::ToggleMute(void)
5313 void CApplication::SetMute(bool mute)
5315 if (m_muted != mute)
5322 void CApplication::Mute()
5324 if (g_peripherals.Mute())
5327 CAEFactory::SetMute(true);
5332 void CApplication::UnMute()
5334 if (g_peripherals.UnMute())
5337 CAEFactory::SetMute(false);
5342 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5344 float hardwareVolume = iValue;
5347 hardwareVolume /= 100.0f;
5349 SetHardwareVolume(hardwareVolume);
5353 void CApplication::SetHardwareVolume(float hardwareVolume)
5355 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5356 m_volumeLevel = hardwareVolume;
5359 if (hardwareVolume > VOLUME_MINIMUM)
5361 float dB = CAEUtil::PercentToGain(hardwareVolume);
5362 value = CAEUtil::GainToScale(dB);
5367 CAEFactory::SetVolume(value);
5370 float CApplication::GetVolume(bool percentage /* = true */) const
5374 // converts the hardware volume to a percentage
5375 return m_volumeLevel * 100.0f;
5378 return m_volumeLevel;
5381 void CApplication::VolumeChanged() const
5383 CVariant data(CVariant::VariantTypeObject);
5384 data["volume"] = GetVolume();
5385 data["muted"] = m_muted;
5386 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5388 // if player has volume control, set it.
5389 if (m_pPlayer->ControlsVolume())
5391 m_pPlayer->SetVolume(m_volumeLevel);
5392 m_pPlayer->SetMute(m_muted);
5396 int CApplication::GetSubtitleDelay() const
5398 // converts subtitle delay to a percentage
5399 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5402 int CApplication::GetAudioDelay() const
5404 // converts audio delay to a percentage
5405 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5408 // Returns the total time in seconds of the current media. Fractional
5409 // portions of a second are possible - but not necessarily supported by the
5410 // player class. This returns a double to be consistent with GetTime() and
5412 double CApplication::GetTotalTime() const
5416 if (m_pPlayer->IsPlaying())
5418 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5419 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5421 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5427 void CApplication::StopShutdownTimer()
5429 if (m_shutdownTimer.IsRunning())
5430 m_shutdownTimer.Stop();
5433 void CApplication::ResetShutdownTimers()
5435 // reset system shutdown timer
5436 m_shutdownTimer.StartZero();
5438 // delete custom shutdown timer
5439 if (g_alarmClock.HasAlarm("shutdowntimer"))
5440 g_alarmClock.Stop("shutdowntimer", true);
5443 // Returns the current time in seconds of the currently playing media.
5444 // Fractional portions of a second are possible. This returns a double to
5445 // be consistent with GetTotalTime() and SeekTime().
5446 double CApplication::GetTime() const
5450 if (m_pPlayer->IsPlaying())
5452 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5454 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5455 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5458 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5464 // Sets the current position of the currently playing media to the specified
5465 // time in seconds. Fractional portions of a second are valid. The passed
5466 // time is the time offset from the beginning of the file as opposed to a
5467 // delta from the current position. This method accepts a double to be
5468 // consistent with GetTime() and GetTotalTime().
5469 void CApplication::SeekTime( double dTime )
5471 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5473 if (!m_pPlayer->CanSeek()) return;
5474 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5476 // find the item in the stack we are seeking to, and load the new
5477 // file if necessary, and calculate the correct seek within the new
5478 // file. Otherwise, just fall through to the usual routine if the
5479 // time is higher than our total time.
5480 for (int i = 0; i < m_currentStack->Size(); i++)
5482 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5484 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5485 if (m_currentStackPosition == i)
5486 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5488 { // seeking to a new file
5489 m_currentStackPosition = i;
5490 CFileItem item(*(*m_currentStack)[i]);
5491 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5492 // don't just call "PlayFile" here, as we are quite likely called from the
5493 // player thread, so we won't be able to delete ourselves.
5494 CApplicationMessenger::Get().PlayFile(item, true);
5500 // convert to milliseconds and perform seek
5501 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5505 float CApplication::GetPercentage() const
5507 if (m_pPlayer->IsPlaying())
5509 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5511 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5512 if (tag.GetDuration() > 0)
5513 return (float)(GetTime() / tag.GetDuration() * 100);
5516 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5518 double totalTime = GetTotalTime();
5519 if (totalTime > 0.0f)
5520 return (float)(GetTime() / totalTime * 100);
5523 return m_pPlayer->GetPercentage();
5528 float CApplication::GetCachePercentage() const
5530 if (m_pPlayer->IsPlaying())
5532 // Note that the player returns a relative cache percentage and we want an absolute percentage
5533 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5535 float stackedTotalTime = (float) GetTotalTime();
5536 // We need to take into account the stack's total time vs. currently playing file's total time
5537 if (stackedTotalTime > 0.0f)
5538 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5541 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5546 void CApplication::SeekPercentage(float percent)
5548 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5550 if (!m_pPlayer->CanSeek()) return;
5551 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5552 SeekTime(percent * 0.01 * GetTotalTime());
5554 m_pPlayer->SeekPercentage(percent);
5558 // SwitchToFullScreen() returns true if a switch is made, else returns false
5559 bool CApplication::SwitchToFullScreen()
5561 // if playing from the video info window, close it first!
5562 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5564 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5565 if (pDialog) pDialog->Close(true);
5568 // don't switch if there is a dialog on screen or the slideshow is active
5569 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5572 // See if we're playing a video, and are in GUI mode
5573 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5575 // then switch to fullscreen mode
5576 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5579 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5580 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5581 { // then switch to visualisation
5582 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5588 void CApplication::Minimize()
5590 g_Windowing.Minimize();
5593 PLAYERCOREID CApplication::GetCurrentPlayer()
5595 return m_pPlayer->GetCurrentPlayer();
5598 void CApplication::UpdateLibraries()
5600 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5602 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5606 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5608 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5613 bool CApplication::IsVideoScanning() const
5615 return m_videoInfoScanner->IsScanning();
5618 bool CApplication::IsMusicScanning() const
5620 return m_musicInfoScanner->IsScanning();
5623 void CApplication::StopVideoScan()
5625 if (m_videoInfoScanner->IsScanning())
5626 m_videoInfoScanner->Stop();
5629 void CApplication::StopMusicScan()
5631 if (m_musicInfoScanner->IsScanning())
5632 m_musicInfoScanner->Stop();
5635 void CApplication::StartVideoCleanup()
5637 if (m_videoInfoScanner->IsScanning())
5640 m_videoInfoScanner->CleanDatabase();
5643 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5645 if (m_videoInfoScanner->IsScanning())
5648 m_videoInfoScanner->ShowDialog(true);
5650 m_videoInfoScanner->Start(strDirectory,scanAll);
5653 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5655 if (m_musicInfoScanner->IsScanning())
5659 { // setup default flags
5660 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5661 flags |= CMusicInfoScanner::SCAN_ONLINE;
5662 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5663 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5666 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5667 m_musicInfoScanner->ShowDialog(true);
5669 m_musicInfoScanner->Start(strDirectory, flags);
5672 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5675 if (m_musicInfoScanner->IsScanning())
5678 m_musicInfoScanner->ShowDialog(true);
5680 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5683 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5686 if (m_musicInfoScanner->IsScanning())
5689 m_musicInfoScanner->ShowDialog(true);
5691 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5694 void CApplication::CheckPlayingProgress()
5696 // check if we haven't rewound past the start of the file
5697 if (m_pPlayer->IsPlaying())
5699 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5709 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5711 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5712 g_application.SeekTime(0);
5718 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5720 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5722 // initial exit conditions
5723 // no songs in playlist just return
5724 if (playlist.size() == 0)
5728 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5731 // setup correct playlist
5732 g_playlistPlayer.ClearPlaylist(iPlaylist);
5734 // if the playlist contains an internet stream, this file will be used
5735 // to generate a thumbnail for musicplayer.cover
5736 g_application.m_strPlayListFile = strPlayList;
5738 // add the items to the playlist player
5739 g_playlistPlayer.Add(iPlaylist, playlist);
5741 // if we have a playlist
5742 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5745 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5746 g_playlistPlayer.Reset();
5747 g_playlistPlayer.Play(track);
5753 void CApplication::SaveCurrentFileSettings()
5755 // don't store settings for PVR in video database
5756 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5758 // save video settings
5759 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5763 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5767 else if (m_itemCurrentFile->IsPVRChannel())
5769 g_PVRManager.SaveCurrentChannelSettings();
5773 bool CApplication::AlwaysProcess(const CAction& action)
5775 // check if this button is mapped to a built-in function
5776 if (!action.GetName().empty())
5778 CStdString builtInFunction;
5779 vector<CStdString> params;
5780 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5781 StringUtils::ToLower(builtInFunction);
5783 // should this button be handled normally or just cancel the screensaver?
5784 if ( builtInFunction.Equals("powerdown")
5785 || builtInFunction.Equals("reboot")
5786 || builtInFunction.Equals("restart")
5787 || builtInFunction.Equals("restartapp")
5788 || builtInFunction.Equals("suspend")
5789 || builtInFunction.Equals("hibernate")
5790 || builtInFunction.Equals("quit")
5791 || builtInFunction.Equals("shutdown"))
5800 bool CApplication::IsCurrentThread() const
5802 return CThread::IsCurrentThread(m_threadID);
5805 void CApplication::SetRenderGUI(bool renderGUI)
5807 if (renderGUI && ! m_renderGUI)
5808 g_windowManager.MarkDirty();
5809 m_renderGUI = renderGUI;
5812 CNetwork& CApplication::getNetwork()
5816 #ifdef HAS_PERFORMANCE_SAMPLE
5817 CPerformanceStats &CApplication::GetPerformanceStats()
5823 bool CApplication::SetLanguage(const CStdString &strLanguage)
5825 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5826 CStdString strNewLanguage = strLanguage;
5827 if (strNewLanguage != strPreviousLanguage)
5829 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5830 if (!g_langInfo.Load(strLangInfoPath))
5833 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5835 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5836 CStdString strFontSet;
5837 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5838 strNewLanguage = strFontSet;
5840 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5842 CSettings::Get().SetString("locale.language", strNewLanguage);
5844 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5847 // also tell our weather and skin to reload as these are localized
5848 g_weatherManager.Refresh();
5849 g_PVRManager.LocalizationChanged();
5856 void CApplication::CloseNetworkShares()
5858 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5860 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5864 #ifdef HAS_FILESYSTEM_NFS
5865 gNfsConnection.Deinit();
5868 #ifdef HAS_FILESYSTEM_AFP
5869 gAfpConnection.Deinit();
5872 #ifdef HAS_FILESYSTEM_SFTP
5873 CSFTPSessionManager::DisconnectAllSessions();