2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "network/Network.h"
22 #include "threads/SystemClock.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
29 #include "utils/Screenshot.h"
32 #include "guilib/TextureManager.h"
33 #include "cores/IPlayer.h"
34 #include "cores/dvdplayer/DVDFileInfo.h"
35 #include "cores/AudioEngine/AEFactory.h"
36 #include "cores/AudioEngine/Utils/AEUtil.h"
37 #include "PlayListPlayer.h"
39 #include "video/Bookmark.h"
40 #include "network/NetworkServices.h"
41 #include "guilib/GUIControlProfiler.h"
42 #include "utils/LangCodeExpander.h"
43 #include "GUIInfoManager.h"
44 #include "playlists/PlayListFactory.h"
45 #include "guilib/GUIFontManager.h"
46 #include "guilib/GUIColorManager.h"
47 #include "guilib/StereoscopicsManager.h"
48 #include "guilib/GUITextLayout.h"
49 #include "addons/Skin.h"
50 #include "interfaces/generic/ScriptInvocationManager.h"
52 #include "interfaces/python/XBPython.h"
54 #include "input/ButtonTranslator.h"
55 #include "guilib/GUIAudioManager.h"
56 #include "GUIPassword.h"
57 #include "input/InertialScrollingHandler.h"
58 #include "ApplicationMessenger.h"
59 #include "SectionLoader.h"
60 #include "cores/DllLoader/DllLoaderContainer.h"
61 #include "GUIUserMessages.h"
62 #include "filesystem/DirectoryCache.h"
63 #include "filesystem/StackDirectory.h"
64 #include "filesystem/SpecialProtocol.h"
65 #include "filesystem/DllLibCurl.h"
66 #include "filesystem/MythSession.h"
67 #include "filesystem/PluginDirectory.h"
68 #ifdef HAS_FILESYSTEM_SAP
69 #include "filesystem/SAPDirectory.h"
71 #ifdef HAS_FILESYSTEM_HTSP
72 #include "filesystem/HTSPDirectory.h"
74 #include "utils/TuxBoxUtil.h"
75 #include "utils/SystemInfo.h"
76 #include "utils/TimeUtils.h"
77 #include "GUILargeTextureManager.h"
78 #include "TextureCache.h"
79 #include "playlists/SmartPlayList.h"
80 #ifdef HAS_FILESYSTEM_RAR
81 #include "filesystem/RarManager.h"
83 #include "playlists/PlayList.h"
84 #include "profiles/ProfilesManager.h"
85 #include "windowing/WindowingFactory.h"
86 #include "powermanagement/PowerManager.h"
87 #include "powermanagement/DPMSSupport.h"
88 #include "settings/SettingAddon.h"
89 #include "settings/Settings.h"
90 #include "settings/AdvancedSettings.h"
91 #include "settings/DisplaySettings.h"
92 #include "settings/MediaSettings.h"
93 #include "settings/MediaSourceSettings.h"
94 #include "settings/SkinSettings.h"
95 #include "guilib/LocalizeStrings.h"
96 #include "utils/CPUInfo.h"
97 #include "utils/RssManager.h"
98 #include "utils/SeekHandler.h"
99 #include "view/ViewStateSettings.h"
101 #include "input/KeyboardStat.h"
102 #include "input/XBMC_vkeys.h"
103 #include "input/MouseStat.h"
109 #if defined(FILESYSTEM) && !defined(TARGET_POSIX)
110 #include "filesystem/FileDAAP.h"
113 #include "network/upnp/UPnP.h"
114 #include "network/upnp/UPnPSettings.h"
115 #include "filesystem/UPnPDirectory.h"
117 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
118 #include "filesystem/SMBDirectory.h"
120 #ifdef HAS_FILESYSTEM_NFS
121 #include "filesystem/NFSFile.h"
123 #ifdef HAS_FILESYSTEM_AFP
124 #include "filesystem/AFPFile.h"
126 #ifdef HAS_FILESYSTEM_SFTP
127 #include "filesystem/SFTPFile.h"
129 #include "PartyModeManager.h"
130 #ifdef HAS_VIDEO_PLAYBACK
131 #include "cores/VideoRenderers/RenderManager.h"
134 #include "music/karaoke/karaokelyricsmanager.h"
135 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
136 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
138 #include "network/Zeroconf.h"
139 #include "network/ZeroconfBrowser.h"
141 #include "threads/platform/win/Win32Exception.h"
143 #ifdef HAS_EVENT_SERVER
144 #include "network/EventServer.h"
147 #include <dbus/dbus.h>
150 #include "interfaces/json-rpc/JSONRPC.h"
151 #include "network/TCPServer.h"
154 #include "network/AirPlayServer.h"
157 #include "network/AirTunesServer.h"
159 #if defined(HAVE_LIBCRYSTALHD)
160 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
162 #include "interfaces/AnnouncementManager.h"
163 #include "peripherals/Peripherals.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
165 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
166 #include "peripherals/devices/PeripheralImon.h"
167 #include "music/infoscanner/MusicInfoScanner.h"
170 #include "guilib/GUIWindowManager.h"
171 #include "windows/GUIWindowHome.h"
172 #include "settings/windows/GUIWindowSettings.h"
173 #include "windows/GUIWindowFileManager.h"
174 #include "settings/windows/GUIWindowSettingsCategory.h"
175 #include "music/windows/GUIWindowMusicPlaylist.h"
176 #include "music/windows/GUIWindowMusicSongs.h"
177 #include "music/windows/GUIWindowMusicNav.h"
178 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
179 #include "video/windows/GUIWindowVideoPlaylist.h"
180 #include "music/dialogs/GUIDialogMusicInfo.h"
181 #include "video/dialogs/GUIDialogVideoInfo.h"
182 #include "video/windows/GUIWindowVideoNav.h"
183 #include "profiles/windows/GUIWindowSettingsProfile.h"
185 #include "rendering/gl/GUIWindowTestPatternGL.h"
188 #include "rendering/dx/GUIWindowTestPatternDX.h"
190 #include "settings/windows/GUIWindowSettingsScreenCalibration.h"
191 #include "programs/GUIWindowPrograms.h"
192 #include "pictures/GUIWindowPictures.h"
193 #include "windows/GUIWindowWeather.h"
194 #include "windows/GUIWindowLoginScreen.h"
195 #include "addons/GUIWindowAddonBrowser.h"
196 #include "music/windows/GUIWindowVisualisation.h"
197 #include "windows/GUIWindowDebugInfo.h"
198 #include "windows/GUIWindowPointer.h"
199 #include "windows/GUIWindowSystemInfo.h"
200 #include "windows/GUIWindowScreensaver.h"
201 #include "windows/GUIWindowScreensaverDim.h"
202 #include "pictures/GUIWindowSlideShow.h"
203 #include "windows/GUIWindowStartup.h"
204 #include "video/windows/GUIWindowFullScreen.h"
205 #include "video/dialogs/GUIDialogVideoOSD.h"
206 #include "music/dialogs/GUIDialogMusicOverlay.h"
207 #include "video/dialogs/GUIDialogVideoOverlay.h"
208 #include "video/VideoInfoScanner.h"
209 #include "video/PlayerController.h"
212 #include "music/dialogs/GUIDialogMusicOSD.h"
213 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
214 #include "dialogs/GUIDialogTextViewer.h"
215 #include "network/GUIDialogNetworkSetup.h"
216 #include "dialogs/GUIDialogMediaSource.h"
217 #include "video/dialogs/GUIDialogVideoSettings.h"
218 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
219 #include "video/dialogs/GUIDialogVideoBookmarks.h"
220 #include "profiles/dialogs/GUIDialogProfileSettings.h"
221 #include "profiles/dialogs/GUIDialogLockSettings.h"
222 #include "settings/dialogs/GUIDialogContentSettings.h"
223 #include "dialogs/GUIDialogBusy.h"
224 #include "dialogs/GUIDialogKeyboardGeneric.h"
225 #include "dialogs/GUIDialogYesNo.h"
226 #include "dialogs/GUIDialogOK.h"
227 #include "dialogs/GUIDialogProgress.h"
228 #include "dialogs/GUIDialogExtendedProgressBar.h"
229 #include "dialogs/GUIDialogSelect.h"
230 #include "dialogs/GUIDialogSeekBar.h"
231 #include "dialogs/GUIDialogKaiToast.h"
232 #include "dialogs/GUIDialogVolumeBar.h"
233 #include "dialogs/GUIDialogMuteBug.h"
234 #include "video/dialogs/GUIDialogFileStacking.h"
235 #include "dialogs/GUIDialogNumeric.h"
236 #include "dialogs/GUIDialogGamepad.h"
237 #include "dialogs/GUIDialogSubMenu.h"
238 #include "dialogs/GUIDialogFavourites.h"
239 #include "dialogs/GUIDialogButtonMenu.h"
240 #include "dialogs/GUIDialogContextMenu.h"
241 #include "dialogs/GUIDialogPlayerControls.h"
242 #include "music/dialogs/GUIDialogSongInfo.h"
243 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
244 #include "dialogs/GUIDialogSmartPlaylistRule.h"
245 #include "pictures/GUIDialogPictureInfo.h"
246 #include "addons/GUIDialogAddonSettings.h"
247 #include "addons/GUIDialogAddonInfo.h"
248 #ifdef HAS_LINUX_NETWORK
249 #include "network/GUIDialogAccessPoints.h"
252 /* PVR related include Files */
253 #include "pvr/PVRManager.h"
254 #include "pvr/timers/PVRTimers.h"
255 #include "pvr/windows/GUIWindowPVR.h"
256 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
257 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
258 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
260 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
261 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
263 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
264 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
265 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
267 #include "epg/EpgContainer.h"
269 #include "video/dialogs/GUIDialogFullScreenInfo.h"
270 #include "video/dialogs/GUIDialogTeletext.h"
271 #include "dialogs/GUIDialogSlider.h"
272 #include "guilib/GUIControlFactory.h"
273 #include "dialogs/GUIDialogCache.h"
274 #include "dialogs/GUIDialogPlayEject.h"
275 #include "dialogs/GUIDialogMediaFilter.h"
276 #include "video/dialogs/GUIDialogSubtitles.h"
277 #include "utils/XMLUtils.h"
278 #include "addons/AddonInstaller.h"
280 #ifdef HAS_PERFORMANCE_SAMPLE
281 #include "utils/PerformanceSample.h"
283 #define MEASURE_FUNCTION
286 #ifdef TARGET_WINDOWS
288 #include "win32util.h"
291 #include "windowing/X11/XRandR.h"
294 #ifdef TARGET_DARWIN_OSX
295 #include "osx/CocoaInterface.h"
296 #include "osx/XBMCHelper.h"
299 #include "osx/DarwinUtils.h"
304 #include <cdio/logging.h>
308 #include "linux/HALManager.h"
311 #include "storage/MediaManager.h"
312 #include "utils/JobManager.h"
313 #include "utils/SaveFileStateJob.h"
314 #include "utils/AlarmClock.h"
315 #include "utils/RssReader.h"
316 #include "utils/StringUtils.h"
317 #include "utils/Weather.h"
318 #include "DatabaseManager.h"
325 #include "input/linux/LIRC.h"
327 #ifdef HAS_IRSERVERSUITE
328 #include "input/windows/IRServerSuite.h"
331 #if defined(TARGET_WINDOWS)
332 #include "input/windows/WINJoystick.h"
333 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
334 #include "input/SDLJoystick.h"
337 #if defined(TARGET_ANDROID)
338 #include "android/activity/XBMCApp.h"
339 #include "android/activity/AndroidFeatures.h"
340 #include "android/jni/Build.h"
343 #ifdef TARGET_WINDOWS
344 #include "utils/Environment.h"
347 #if defined(HAS_LIBAMCODEC)
348 #include "utils/AMLUtils.h"
351 #include "cores/FFmpeg.h"
354 using namespace ADDON;
355 using namespace XFILE;
357 using namespace MEDIA_DETECT;
359 using namespace PLAYLIST;
360 using namespace VIDEO;
361 using namespace MUSIC_INFO;
362 #ifdef HAS_EVENT_SERVER
363 using namespace EVENTSERVER;
366 using namespace JSONRPC;
368 using namespace ANNOUNCEMENT;
371 using namespace PERIPHERALS;
373 using namespace XbmcThreads;
375 // uncomment this if you want to use release libs in the debug build.
376 // Atm this saves you 7 mb of memory
377 #define USE_RELEASE_LIBS
379 #define MAX_FFWD_SPEED 5
381 //extern IDirectSoundRenderer* m_pAudioDecoder;
382 CApplication::CApplication(void)
383 : m_pPlayer(new CApplicationPlayer)
384 , m_itemCurrentFile(new CFileItem)
385 , m_stackFileItemToUpdate(new CFileItem)
386 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
387 , m_progressTrackingItem(new CFileItem)
388 , m_videoInfoScanner(new CVideoInfoScanner)
389 , m_musicInfoScanner(new CMusicInfoScanner)
390 , m_seekHandler(new CSeekHandler)
391 , m_playerController(new CPlayerController)
394 TiXmlBase::SetCondenseWhiteSpace(false);
395 m_bInhibitIdleShutdown = false;
396 m_bScreenSave = false;
398 m_dpmsIsActive = false;
399 m_dpmsIsManual = false;
400 m_iScreenSaveLock = 0;
401 m_bInitializing = true;
402 m_eForcedNextPlayer = EPC_NONE;
403 m_strPlayListFile = "";
404 m_nextPlaylistItem = -1;
405 m_bPlaybackStarting = false;
406 m_ePlayState = PLAY_STATE_NONE;
407 m_skinReverting = false;
415 /* for now always keep this around */
417 m_pKaraokeMgr = new CKaraokeLyricsManager();
419 m_currentStack = new CFileItemList;
421 m_bPresentFrame = false;
422 m_bPlatformDirectories = true;
424 m_bStandalone = false;
425 m_bEnableLegacyRes = false;
426 m_bSystemScreenSaverEnable = false;
427 m_pInertialScrollingHandler = new CInertialScrollingHandler();
429 m_Autorun = new CAutorun();
434 m_progressTrackingPlayCountUpdate = false;
435 m_currentStackPosition = 0;
437 m_lastRenderTime = 0;
441 m_volumeLevel = 1.0f;
444 CApplication::~CApplication(void)
446 delete m_musicInfoScanner;
447 delete m_videoInfoScanner;
448 delete &m_progressTrackingVideoResumeBookmark;
452 delete m_currentStack;
455 delete m_pKaraokeMgr;
459 delete m_seekHandler;
460 delete m_playerController;
461 delete m_pInertialScrollingHandler;
465 bool CApplication::OnEvent(XBMC_Event& newEvent)
467 switch(newEvent.type)
470 if (!g_application.m_bStop)
471 CApplicationMessenger::Get().Quit();
474 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
477 g_Keyboard.ProcessKeyUp();
479 case XBMC_MOUSEBUTTONDOWN:
480 case XBMC_MOUSEBUTTONUP:
481 case XBMC_MOUSEMOTION:
482 g_Mouse.HandleEvent(newEvent);
483 g_application.ProcessMouse();
485 case XBMC_VIDEORESIZE:
486 if (!g_application.m_bInitializing &&
487 !g_advancedSettings.m_fullScreen)
489 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
490 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
491 CSettings::Get().SetInt("window.width", newEvent.resize.w);
492 CSettings::Get().SetInt("window.height", newEvent.resize.h);
493 CSettings::Get().Save();
497 #ifdef TARGET_WINDOWS
498 if (g_advancedSettings.m_fullScreen)
500 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
501 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
502 if (newRes != g_graphicsContext.GetVideoResolution())
503 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
508 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
512 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
514 case XBMC_APPCOMMAND:
515 return g_application.OnAppCommand(newEvent.appcommand.action);
518 if (newEvent.touch.action == ACTION_TOUCH_TAP)
519 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
520 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
523 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
524 actionId = newEvent.touch.action;
527 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
528 // change this if we have a dialog up
529 if (g_windowManager.HasModalDialog())
531 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
533 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
534 { // fullscreen info dialog - special case
535 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
537 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
541 if (iWin == WINDOW_FULLSCREEN_VIDEO)
543 // current active window is full screen video.
544 if (g_application.m_pPlayer->IsInMenu())
546 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
547 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_VIDEO_MENU, newEvent.touch.action, newEvent.touch.pointers, actionId);
549 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
551 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
552 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
554 // if no PVR specific action/mapping is found, fall back to default
556 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
560 // in any other case use the fullscreen window section of keymap.xml to map key->action
561 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
564 else // iWin != WINDOW_FULLSCREEN_VIDEO
565 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
572 if ((actionId >= ACTION_TOUCH_TAP && actionId <= ACTION_GESTURE_END)
573 || (actionId >= ACTION_MOUSE_START && actionId <= ACTION_MOUSE_END) )
574 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
576 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
578 // Post an unfocus message for touch device after the action.
579 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
581 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
582 CApplicationMessenger::Get().SendGUIMessage(msg);
587 // Reset the screensaver
588 g_application.ResetScreenSaver();
589 g_application.WakeUpScreenSaverAndDPMS();
590 // Send a mouse motion event with no dx,dy for getting the current guiitem selected
591 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, static_cast<float>(newEvent.focus.x), static_cast<float>(newEvent.focus.y), 0, 0));
597 extern "C" void __stdcall init_emu_environ();
598 extern "C" void __stdcall update_emu_environ();
601 // Utility function used to copy files from the application bundle
602 // over to the user data directory in Application Support/XBMC.
604 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
606 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
607 if (!CFile::Exists(destPath))
609 // need to copy it across
610 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
611 CFile::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.GetBuildTargetPlatformName().c_str(),
696 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness());
698 std::string buildType;
701 #elif defined(NDEBUG)
702 buildType = "Release";
704 buildType = "Unknown";
706 std::string specialVersion;
707 #if defined(TARGET_DARWIN_IOS_ATV2)
708 specialVersion = " (version for AppleTV2)";
709 #elif defined(TARGET_RASPBERRY_PI)
710 specialVersion = " (version for Raspberry Pi)";
711 //#elif defined(some_ID) // uncomment for special version/fork
712 // specialVersion = " (version for XXXX)";
714 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build%s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), specialVersion.c_str());
715 CLog::Log(LOGNOTICE, "XBMC compiled " __DATE__ " by %s for %s %s %d-bit %s (%s)", g_sysinfo.GetUsedCompilerNameAndVer().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(),
716 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersionDecoded().c_str(),
717 g_sysinfo.GetBuildTargetPlatformVersion().c_str());
719 std::string deviceModel(g_sysinfo.GetModelName());
720 if (!g_sysinfo.GetManufacturerName().empty())
721 deviceModel = g_sysinfo.GetManufacturerName() + " " + (deviceModel.empty() ? std::string("device") : deviceModel);
722 if (!deviceModel.empty())
723 CLog::Log(LOGNOTICE, "Running on %s with %s, kernel: %s %s %d-bit version %s", deviceModel.c_str(), g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
724 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
726 CLog::Log(LOGNOTICE, "Running on %s, kernel: %s %s %d-bit version %s", g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
727 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
729 #if defined(TARGET_LINUX)
730 #if USE_STATIC_FFMPEG
731 CLog::Log(LOGNOTICE, "FFmpeg statically linked, version: %s", FFMPEG_VERSION);
732 #else // !USE_STATIC_FFMPEG
733 CLog::Log(LOGNOTICE, "FFmpeg version: %s", FFMPEG_VERSION);
734 #endif // !USE_STATIC_FFMPEG
735 if (!strstr(FFMPEG_VERSION, FFMPEG_VER_SHA))
737 if (strstr(FFMPEG_VERSION, "xbmc"))
738 CLog::Log(LOGNOTICE, "WARNING: unknown ffmpeg-xbmc version detected");
740 CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected");
744 std::string cpuModel(g_cpuInfo.getCPUModel());
745 if (!cpuModel.empty())
746 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
748 CLog::Log(LOGNOTICE, "%d CPU core%s available", g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
749 #if defined(TARGET_WINDOWS)
750 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
751 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
752 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
754 #if defined(TARGET_ANDROID)
756 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
757 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
758 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
762 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
763 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
765 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
767 CSpecialProtocol::LogPaths();
769 CStdString executable = CUtil::ResolveExecutablePath();
770 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
771 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
772 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
773 CRegExp::LogCheckUtf8Support();
774 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
776 CStdString strExecutablePath;
777 CUtil::GetHomePath(strExecutablePath);
780 g_xrandr.LoadCustomModeLinesToAllOutputs();
783 // for python scripts that check the OS
784 #if defined(TARGET_DARWIN)
785 setenv("OS","OS X",true);
786 #elif defined(TARGET_POSIX)
787 setenv("OS","Linux",true);
788 #elif defined(TARGET_WINDOWS)
789 CEnvironment::setenv("OS", "win32");
792 // register ffmpeg lockmanager callback
793 av_lockmgr_register(&ffmpeg_lockmgr_cb);
795 avcodec_register_all();
799 avfilter_register_all();
800 // set avutil callback
801 av_log_set_callback(ff_avutil_log);
803 g_powerManager.Initialize();
805 // Load the AudioEngine before settings as they need to query the engine
806 if (!CAEFactory::LoadEngine())
808 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
812 // Initialize default Settings - don't move
813 CLog::Log(LOGNOTICE, "load settings...");
814 if (!CSettings::Get().Initialize())
817 g_powerManager.SetDefaults();
819 // load the actual values
820 if (!CSettings::Get().Load())
822 CLog::Log(LOGFATAL, "unable to load settings");
825 CSettings::Get().SetLoaded();
827 CLog::Log(LOGINFO, "creating subdirectories");
828 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
829 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
830 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
831 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
832 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
833 CProfilesManager::Get().CreateProfileFolders();
835 update_emu_environ();//apply the GUI settings
837 // Load the langinfo to have user charset <-> utf-8 conversion
838 CStdString strLanguage = CSettings::Get().GetString("locale.language");
839 strLanguage[0] = toupper(strLanguage[0]);
841 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
843 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
844 g_langInfo.Load(strLangInfoPath);
845 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
846 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
848 CStdString strLanguagePath = "special://xbmc/language/";
850 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
851 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
853 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
857 // start the AudioEngine
858 if (!CAEFactory::StartEngine())
860 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
864 // restore AE's previous volume state
865 SetHardwareVolume(m_volumeLevel);
866 CAEFactory::SetMute (m_muted);
867 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
869 // initialize m_replayGainSettings
870 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
871 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
872 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
873 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
875 // initialize the addon database (must be before the addon manager is init'd)
876 CDatabaseManager::Get().Initialize(true);
879 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
882 // start-up Addons Framework
883 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
884 if (!CAddonMgr::Get().Init())
886 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
889 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
890 g_RemoteControl.Initialize();
893 g_peripherals.Initialise();
895 // Create the Mouse, Keyboard, Remote, and Joystick devices
896 // Initialize after loading settings to get joystick deadzone setting
897 g_Mouse.Initialize();
898 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
900 g_Keyboard.Initialize();
902 #if defined(TARGET_DARWIN_OSX)
903 // Configure and possible manually start the helper.
904 XBMCHelper::GetInstance().Configure();
907 CUtil::InitRandomSeed();
909 g_mediaManager.Initialize();
911 m_lastFrameTime = XbmcThreads::SystemClockMillis();
912 m_lastRenderTime = m_lastFrameTime;
916 bool CApplication::CreateGUI()
920 CLog::Log(LOGNOTICE, "Setup SDL");
922 /* Clean up on exit, exit on window close and interrupt */
925 uint32_t sdlFlags = 0;
927 #if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX)
928 sdlFlags |= SDL_INIT_VIDEO;
931 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
932 sdlFlags |= SDL_INIT_JOYSTICK;
935 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
936 //this might bring the monitor out of standby, so we have to disable it explicitly
937 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
938 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
939 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
945 // for nvidia cards - vsync currently ALWAYS enabled.
946 // the reason is that after screen has been setup changing this env var will make no difference.
947 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
948 setenv("__GL_YIELD", "USLEEP", 0);
951 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
952 g_Windowing.EnableSystemScreenSaver(false);
955 if (SDL_Init(sdlFlags) != 0)
957 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
960 #if defined(TARGET_DARWIN)
961 // SDL_Init will install a handler for segfaults, restore the default handler.
962 signal(SIGSEGV, SIG_DFL);
966 // Initialize core peripheral port support. Note: If these parameters
967 // are 0 and NULL, respectively, then the default number and types of
968 // controllers will be initialized.
969 if (!g_Windowing.InitWindowSystem())
971 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
975 // Retrieve the matching resolution based on GUI settings
976 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
977 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
978 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
980 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
981 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
984 // update the window resolution
985 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
987 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
988 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
990 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
992 // Oh uh - doesn't look good for starting in their wanted screenmode
993 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
994 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
1001 if (g_advancedSettings.m_splashImage)
1003 CStdString strUserSplash = "special://home/media/Splash.png";
1004 if (CFile::Exists(strUserSplash))
1006 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
1007 m_splash = new CSplash(strUserSplash);
1011 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1012 m_splash = new CSplash("special://xbmc/media/Splash.png");
1017 // The key mappings may already have been loaded by a peripheral
1018 CLog::Log(LOGINFO, "load keymapping");
1019 if (!CButtonTranslator::GetInstance().Load())
1022 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1023 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1026 info.strMode.c_str());
1027 g_windowManager.Initialize();
1032 bool CApplication::InitWindow()
1034 #ifdef TARGET_DARWIN_OSX
1035 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1036 // fixes the white screen of death if starting fullscreen and switching to windowed.
1037 bool bFullScreen = false;
1038 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1040 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1044 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1045 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1047 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1052 if (!g_Windowing.InitRenderSystem())
1054 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1057 // set GUI res and force the clear of the screen
1058 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1062 bool CApplication::DestroyWindow()
1064 return g_Windowing.DestroyWindow();
1067 bool CApplication::InitDirectoriesLinux()
1070 The following is the directory mapping for Platform Specific Mode:
1072 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1073 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1074 installations like skins, screensavers, etc.
1076 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1077 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1078 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1079 special://profile/ => [read-write] current profile's userdata directory.
1080 Generally special://masterprofile for the master profile or
1081 special://masterprofile/profiles/<profile_name> for other profiles.
1083 NOTE: All these root directories are lowercase. Some of the sub-directories
1084 might be mixed case.
1087 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1088 CStdString userName;
1090 userName = getenv("USER");
1094 CStdString userHome;
1096 userHome = getenv("HOME");
1100 CStdString xbmcBinPath, xbmcPath;
1101 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1102 xbmcPath = getenv("XBMC_HOME");
1104 if (xbmcPath.empty())
1106 xbmcPath = xbmcBinPath;
1107 /* Check if xbmc binaries and arch independent data files are being kept in
1108 * separate locations. */
1109 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1111 /* Attempt to locate arch independent data files. */
1112 CUtil::GetHomePath(xbmcPath);
1113 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1115 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1121 /* Set some environment variables */
1122 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1123 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1125 if (m_bPlatformDirectories)
1127 // map our special drives
1128 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1129 CSpecialProtocol::SetXBMCPath(xbmcPath);
1130 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1131 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1133 CStdString strTempPath = userHome;
1134 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1135 if (getenv("XBMC_TEMP"))
1136 strTempPath = getenv("XBMC_TEMP");
1137 CSpecialProtocol::SetTempPath(strTempPath);
1139 URIUtils::AddSlashAtEnd(strTempPath);
1140 g_advancedSettings.m_logFolder = strTempPath;
1147 URIUtils::AddSlashAtEnd(xbmcPath);
1148 g_advancedSettings.m_logFolder = xbmcPath;
1150 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1151 CSpecialProtocol::SetXBMCPath(xbmcPath);
1152 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1153 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1155 CStdString strTempPath = xbmcPath;
1156 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1157 if (getenv("XBMC_TEMP"))
1158 strTempPath = getenv("XBMC_TEMP");
1159 CSpecialProtocol::SetTempPath(strTempPath);
1162 URIUtils::AddSlashAtEnd(strTempPath);
1163 g_advancedSettings.m_logFolder = strTempPath;
1172 bool CApplication::InitDirectoriesOSX()
1174 #if defined(TARGET_DARWIN)
1175 CStdString userName;
1177 userName = getenv("USER");
1181 CStdString userHome;
1183 userHome = getenv("HOME");
1187 CStdString xbmcPath;
1188 CUtil::GetHomePath(xbmcPath);
1189 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1191 #if defined(TARGET_DARWIN_IOS)
1192 CStdString fontconfigPath;
1193 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1194 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1197 // setup path to our internal dylibs so loader can find them
1198 CStdString frameworksPath = CUtil::GetFrameworksPath();
1199 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1201 // OSX always runs with m_bPlatformDirectories == true
1202 if (m_bPlatformDirectories)
1204 // map our special drives
1205 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1206 CSpecialProtocol::SetXBMCPath(xbmcPath);
1207 #if defined(TARGET_DARWIN_IOS)
1208 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1209 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1211 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1212 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1215 // location for temp files
1216 #if defined(TARGET_DARWIN_IOS)
1217 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1219 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1220 CDirectory::Create(strTempPath);
1221 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1223 CSpecialProtocol::SetTempPath(strTempPath);
1225 // xbmc.log file location
1226 #if defined(TARGET_DARWIN_IOS)
1227 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1229 strTempPath = userHome + "/Library/Logs";
1231 URIUtils::AddSlashAtEnd(strTempPath);
1232 g_advancedSettings.m_logFolder = strTempPath;
1238 URIUtils::AddSlashAtEnd(xbmcPath);
1239 g_advancedSettings.m_logFolder = xbmcPath;
1241 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1242 CSpecialProtocol::SetXBMCPath(xbmcPath);
1243 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1244 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1246 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1247 CSpecialProtocol::SetTempPath(strTempPath);
1249 URIUtils::AddSlashAtEnd(strTempPath);
1250 g_advancedSettings.m_logFolder = strTempPath;
1259 bool CApplication::InitDirectoriesWin32()
1261 #ifdef TARGET_WINDOWS
1262 CStdString xbmcPath;
1264 CUtil::GetHomePath(xbmcPath);
1265 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1266 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1267 CSpecialProtocol::SetXBMCPath(xbmcPath);
1269 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1271 g_advancedSettings.m_logFolder = strWin32UserFolder;
1272 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1273 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1274 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1276 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1280 // Expand the DLL search path with our directories
1281 CWIN32Util::ExtendDllPath();
1289 void CApplication::CreateUserDirs()
1291 CDirectory::Create("special://home/");
1292 CDirectory::Create("special://home/addons");
1293 CDirectory::Create("special://home/addons/packages");
1294 CDirectory::Create("special://home/media");
1295 CDirectory::Create("special://home/sounds");
1296 CDirectory::Create("special://home/system");
1297 CDirectory::Create("special://masterprofile/");
1298 CDirectory::Create("special://temp/");
1299 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1302 bool CApplication::Initialize()
1304 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1305 // turn off cdio logging
1306 cdio_loglevel_default = CDIO_LOG_ERROR;
1309 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1310 // must create these here. Ideally this should be using special://home/ and
1311 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1312 if (!m_bPlatformDirectories)
1315 CDirectory::Create("special://xbmc/language");
1316 CDirectory::Create("special://xbmc/addons");
1317 CDirectory::Create("special://xbmc/sounds");
1320 // Load curl so curl_global_init gets called before any service threads
1321 // are started. Unloading will have no effect as curl is never fully unloaded.
1322 // To quote man curl_global_init:
1323 // "This function is not thread safe. You must not call it when any other
1324 // thread in the program (i.e. a thread sharing the same memory) is running.
1325 // This doesn't just mean no other thread that is using libcurl. Because
1326 // curl_global_init() calls functions of other libraries that are similarly
1327 // thread unsafe, it could conflict with any other thread that
1328 // uses these other libraries."
1329 g_curlInterface.Load();
1330 g_curlInterface.Unload();
1332 // initialize (and update as needed) our databases
1333 CDatabaseManager::Get().Initialize();
1337 // Init DPMS, before creating the corresponding setting control.
1338 m_dpms = new DPMSSupport();
1339 if (g_windowManager.Initialized())
1341 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1343 g_windowManager.Add(new CGUIWindowHome);
1344 g_windowManager.Add(new CGUIWindowPrograms);
1345 g_windowManager.Add(new CGUIWindowPictures);
1346 g_windowManager.Add(new CGUIWindowFileManager);
1347 g_windowManager.Add(new CGUIWindowSettings);
1348 g_windowManager.Add(new CGUIWindowSystemInfo);
1350 g_windowManager.Add(new CGUIWindowTestPatternGL);
1353 g_windowManager.Add(new CGUIWindowTestPatternDX);
1355 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1356 g_windowManager.Add(new CGUIWindowSettingsCategory);
1357 g_windowManager.Add(new CGUIWindowVideoNav);
1358 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1359 g_windowManager.Add(new CGUIWindowLoginScreen);
1360 g_windowManager.Add(new CGUIWindowSettingsProfile);
1361 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1362 g_windowManager.Add(new CGUIWindowAddonBrowser);
1363 g_windowManager.Add(new CGUIWindowScreensaverDim);
1364 g_windowManager.Add(new CGUIWindowDebugInfo);
1365 g_windowManager.Add(new CGUIWindowPointer);
1366 g_windowManager.Add(new CGUIDialogYesNo);
1367 g_windowManager.Add(new CGUIDialogProgress);
1368 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1369 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1370 g_windowManager.Add(new CGUIDialogVolumeBar);
1371 g_windowManager.Add(new CGUIDialogSeekBar);
1372 g_windowManager.Add(new CGUIDialogSubMenu);
1373 g_windowManager.Add(new CGUIDialogContextMenu);
1374 g_windowManager.Add(new CGUIDialogKaiToast);
1375 g_windowManager.Add(new CGUIDialogNumeric);
1376 g_windowManager.Add(new CGUIDialogGamepad);
1377 g_windowManager.Add(new CGUIDialogButtonMenu);
1378 g_windowManager.Add(new CGUIDialogMuteBug);
1379 g_windowManager.Add(new CGUIDialogPlayerControls);
1381 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1382 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1384 g_windowManager.Add(new CGUIDialogSlider);
1385 g_windowManager.Add(new CGUIDialogMusicOSD);
1386 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1387 g_windowManager.Add(new CGUIDialogVideoSettings);
1388 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1389 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1390 // Don't add the filebrowser dialog - it's created and added when it's needed
1391 g_windowManager.Add(new CGUIDialogNetworkSetup);
1392 g_windowManager.Add(new CGUIDialogMediaSource);
1393 g_windowManager.Add(new CGUIDialogProfileSettings);
1394 g_windowManager.Add(new CGUIDialogFavourites);
1395 g_windowManager.Add(new CGUIDialogSongInfo);
1396 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1397 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1398 g_windowManager.Add(new CGUIDialogBusy);
1399 g_windowManager.Add(new CGUIDialogPictureInfo);
1400 g_windowManager.Add(new CGUIDialogAddonInfo);
1401 g_windowManager.Add(new CGUIDialogAddonSettings);
1402 #ifdef HAS_LINUX_NETWORK
1403 g_windowManager.Add(new CGUIDialogAccessPoints);
1406 g_windowManager.Add(new CGUIDialogLockSettings);
1408 g_windowManager.Add(new CGUIDialogContentSettings);
1410 g_windowManager.Add(new CGUIDialogPlayEject);
1412 g_windowManager.Add(new CGUIDialogPeripheralManager);
1413 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1415 g_windowManager.Add(new CGUIDialogMediaFilter);
1416 g_windowManager.Add(new CGUIDialogSubtitles);
1418 g_windowManager.Add(new CGUIWindowMusicPlayList);
1419 g_windowManager.Add(new CGUIWindowMusicSongs);
1420 g_windowManager.Add(new CGUIWindowMusicNav);
1421 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1423 /* Load PVR related Windows and Dialogs */
1424 g_windowManager.Add(new CGUIDialogTeletext);
1425 g_windowManager.Add(new CGUIWindowPVR);
1426 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1427 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1428 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1429 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1430 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1431 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1432 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1433 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1434 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1435 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1437 g_windowManager.Add(new CGUIDialogSelect);
1438 g_windowManager.Add(new CGUIDialogMusicInfo);
1439 g_windowManager.Add(new CGUIDialogOK);
1440 g_windowManager.Add(new CGUIDialogVideoInfo);
1441 g_windowManager.Add(new CGUIDialogTextViewer);
1442 g_windowManager.Add(new CGUIWindowFullScreen);
1443 g_windowManager.Add(new CGUIWindowVisualisation);
1444 g_windowManager.Add(new CGUIWindowSlideShow);
1445 g_windowManager.Add(new CGUIDialogFileStacking);
1447 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1450 g_windowManager.Add(new CGUIDialogVideoOSD);
1451 g_windowManager.Add(new CGUIDialogMusicOverlay);
1452 g_windowManager.Add(new CGUIDialogVideoOverlay);
1453 g_windowManager.Add(new CGUIWindowScreensaver);
1454 g_windowManager.Add(new CGUIWindowWeather);
1455 g_windowManager.Add(new CGUIWindowStartup);
1457 /* window id's 3000 - 3100 are reserved for python */
1459 // Make sure we have at least the default skin
1460 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1461 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1463 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1467 if (g_advancedSettings.m_splashImage)
1468 SAFE_DELETE(m_splash);
1470 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1471 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1472 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1474 g_passwordManager.CheckStartUpLock();
1477 // check if we should use the login screen
1478 if (CProfilesManager::Get().UsingLoginScreen())
1479 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1483 CJSONRPC::Initialize();
1485 ADDON::CAddonMgr::Get().StartServices(false);
1486 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1488 g_windowManager.ActivateWindow(WINDOW_HOME);
1489 StartPVRManager(true);
1493 StartPVRManager(false);
1494 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1497 CStereoscopicsManager::Get().Initialize();
1501 else //No GUI Created
1504 CJSONRPC::Initialize();
1506 ADDON::CAddonMgr::Get().StartServices(false);
1509 g_sysinfo.Refresh();
1511 CLog::Log(LOGINFO, "removing tempfiles");
1512 CUtil::RemoveTempFiles();
1514 if (!CProfilesManager::Get().UsingLoginScreen())
1520 m_slowTimer.StartZero();
1522 #if defined(HAVE_LIBCRYSTALHD)
1523 CCrystalHD::GetInstance();
1526 CAddonMgr::Get().StartServices(true);
1528 CLog::Log(LOGNOTICE, "initialize done");
1530 m_bInitializing = false;
1532 // reset our screensaver (starts timers etc.)
1535 #ifdef HAS_SDL_JOYSTICK
1536 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1537 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1543 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1549 // the callback will take care of starting/stopping webserver
1550 ret = CSettings::Get().SetBool("services.webserver", bStart);
1553 case ES_AIRPLAYSERVER:
1554 // the callback will take care of starting/stopping airplay
1555 ret = CSettings::Get().SetBool("services.airplay", bStart);
1558 case ES_JSONRPCSERVER:
1559 // the callback will take care of starting/stopping jsonrpc server
1560 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1564 // the callback will take care of starting/stopping upnp server
1565 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1568 case ES_UPNPRENDERER:
1569 // the callback will take care of starting/stopping upnp renderer
1570 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1573 case ES_EVENTSERVER:
1574 // the callback will take care of starting/stopping event server
1575 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1579 // the callback will take care of starting/stopping zeroconf
1580 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1587 CSettings::Get().Save();
1592 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1594 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1595 g_PVRManager.Start(true, bOpenPVRWindow);
1598 void CApplication::StopPVRManager()
1600 CLog::Log(LOGINFO, "stopping PVRManager");
1601 if (g_PVRManager.IsPlaying())
1603 g_PVRManager.Stop();
1604 g_EpgContainer.Stop();
1607 void CApplication::StartServices()
1609 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1610 // Start Thread for DVD Mediatype detection
1611 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1612 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1616 void CApplication::StopServices()
1618 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1620 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1621 CLog::Log(LOGNOTICE, "stop dvd detect media");
1622 m_DetectDVDType.StopThread();
1625 g_peripherals.Clear();
1628 void CApplication::OnSettingChanged(const CSetting *setting)
1630 if (setting == NULL)
1633 const std::string &settingId = setting->GetId();
1634 if (settingId == "lookandfeel.skin" ||
1635 settingId == "lookandfeel.font" ||
1636 settingId == "lookandfeel.skincolors")
1638 // if the skin changes and the current theme is not the default one, reset
1639 // the theme to the default value (which will also change lookandfeel.skincolors
1640 // which in turn will reload the skin. Similarly, if the current skin font is not
1641 // the default, reset it as well.
1642 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1643 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1644 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1645 CSettings::Get().SetString("lookandfeel.font", "Default");
1648 std::string builtin("ReloadSkin");
1649 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1650 builtin += "(confirm)";
1651 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1654 else if (settingId == "lookandfeel.skintheme")
1656 // also set the default color theme
1657 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1658 URIUtils::RemoveExtension(colorTheme);
1659 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1660 colorTheme = "defaults";
1662 // check if we have to change the skin color
1663 // if yes, it will trigger a call to ReloadSkin() in
1664 // it's OnSettingChanged() callback
1665 // if no we have to call ReloadSkin() ourselves
1666 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1667 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1669 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1671 else if (settingId == "lookandfeel.skinzoom")
1673 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1674 g_windowManager.SendThreadMessage(msg);
1676 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1678 // AE is master of audio settings and needs to be informed first
1679 CAEFactory::OnSettingsChange(settingId);
1681 if (settingId == "audiooutput.guisoundmode")
1683 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1685 // this tells player whether to open an audio stream passthrough or PCM
1686 // if this is changed, audio stream has to be reopened
1687 else if (settingId == "audiooutput.passthrough")
1689 CApplicationMessenger::Get().MediaRestart(false);
1692 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1693 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1694 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1695 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1696 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1697 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1698 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1699 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1702 void CApplication::OnSettingAction(const CSetting *setting)
1704 if (setting == NULL)
1707 const std::string &settingId = setting->GetId();
1708 if (settingId == "lookandfeel.skinsettings")
1709 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1710 else if (settingId == "screensaver.preview")
1711 ActivateScreenSaver(true);
1712 else if (settingId == "screensaver.settings")
1715 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1716 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1718 else if (settingId == "videoscreen.guicalibration")
1719 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1720 else if (settingId == "videoscreen.testpattern")
1721 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1724 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1726 if (setting == NULL)
1729 const std::string &settingId = setting->GetId();
1730 if (settingId == "audiooutput.channels")
1732 // check if this is an update from Eden
1733 if (oldSettingId != NULL && oldSettingNode != NULL &&
1734 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1737 CSettingInt* channels = (CSettingInt*)setting;
1738 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1739 ret = channels->SetValue(channels->GetValue() + 1);
1741 // let's just reset the audiodevice settings as well
1742 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1743 CAEFactory::VerifyOutputDevice(audiodevice, false);
1744 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1749 else if (settingId == "screensaver.mode")
1751 CSettingString *screensaverMode = (CSettingString*)setting;
1752 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1753 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1754 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1756 else if (settingId == "scrapers.musicvideosdefault")
1758 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1759 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1761 musicvideoScraper->Reset();
1765 #if defined(HAS_LIBAMCODEC)
1766 else if (settingId == "videoplayer.useamcodec")
1768 // Do not permit amcodec to be used on non-aml platforms.
1769 // The setting will be hidden but the default value is true,
1770 // so change it to false.
1773 CSettingBool *useamcodec = (CSettingBool*)setting;
1774 useamcodec->SetValue(false);
1778 #if defined(TARGET_ANDROID)
1779 else if (settingId == "videoplayer.usemediacodec")
1781 // Do not permit MediaCodec to be used Android platforms that do not have it.
1782 // The setting will be hidden but the default value is true,
1783 // so change it to false.
1784 if (CAndroidFeatures::GetVersion() < 16)
1786 CSettingBool *usemediacodec = (CSettingBool*)setting;
1787 usemediacodec->SetValue(false);
1790 else if (settingId == "videoplayer.usestagefright")
1792 CSettingBool *usestagefright = (CSettingBool*)setting;
1793 usestagefright->SetValue(false);
1800 bool CApplication::OnSettingsSaving() const
1802 // don't save settings when we're busy stopping the application
1803 // a lot of screens try to save settings on deinit and deinit is
1804 // called for every screen when the application is stopping
1811 void CApplication::ReloadSkin(bool confirm/*=false*/)
1813 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1815 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1816 g_windowManager.SendMessage(msg);
1818 string newSkin = CSettings::Get().GetString("lookandfeel.skin");
1819 if (LoadSkin(newSkin))
1821 /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
1822 user as to whether they want to keep the current skin. */
1823 if (confirm && !m_skinReverting)
1826 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1828 m_skinReverting = true;
1829 if (oldSkin.empty())
1830 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1832 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1838 // skin failed to load - we revert to the default only if we didn't fail loading the default
1839 string defaultSkin = ((CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1840 if (newSkin != defaultSkin)
1842 m_skinReverting = true;
1843 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1844 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1847 m_skinReverting = false;
1850 bool CApplication::Load(const TiXmlNode *settings)
1852 if (settings == NULL)
1855 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1856 if (audioElement != NULL)
1858 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1859 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1860 m_volumeLevel = VOLUME_MAXIMUM;
1866 bool CApplication::Save(TiXmlNode *settings) const
1868 if (settings == NULL)
1871 TiXmlElement volumeNode("audio");
1872 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1873 if (audioNode == NULL)
1876 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1877 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1882 bool CApplication::LoadSkin(const CStdString& skinID)
1885 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1887 if (LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
1890 CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
1894 bool CApplication::LoadSkin(const SkinPtr& skin)
1900 if (!skin->HasSkinFile("Home.xml"))
1903 bool bPreviousPlayingState=false;
1904 bool bPreviousRenderingState=false;
1905 if (g_application.m_pPlayer->IsPlayingVideo())
1907 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1908 if (bPreviousPlayingState)
1909 g_application.m_pPlayer->Pause();
1910 #ifdef HAS_VIDEO_PLAYBACK
1911 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1913 g_windowManager.ActivateWindow(WINDOW_HOME);
1914 bPreviousRenderingState = true;
1918 // close the music and video overlays (they're re-opened automatically later)
1919 CSingleLock lock(g_graphicsContext);
1921 // save the current window details and focused control
1922 int currentWindow = g_windowManager.GetActiveWindow();
1924 CGUIWindow* pWindow = g_windowManager.GetWindow(currentWindow);
1926 iCtrlID = pWindow->GetFocusedControlID();
1927 vector<int> currentModelessWindows;
1928 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1932 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
1934 g_SkinInfo->Start();
1936 CLog::Log(LOGINFO, " load fonts for skin...");
1937 g_graphicsContext.SetMediaDir(skin->Path());
1938 g_directoryCache.ClearSubPaths(skin->Path());
1940 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1942 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1944 // load in the skin strings
1945 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1946 URIUtils::AddSlashAtEnd(langPath);
1948 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1950 g_SkinInfo->LoadIncludes();
1953 start = CurrentHostCounter();
1955 CLog::Log(LOGINFO, " load new skin...");
1957 // Load the user windows
1961 end = CurrentHostCounter();
1962 freq = CurrentHostFrequency();
1963 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1965 CLog::Log(LOGINFO, " initialize new skin...");
1966 g_windowManager.AddMsgTarget(this);
1967 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1968 g_windowManager.AddMsgTarget(&g_infoManager);
1969 g_windowManager.AddMsgTarget(&g_fontManager);
1970 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1971 g_windowManager.SetCallback(*this);
1972 g_windowManager.Initialize();
1973 CTextureCache::Get().Initialize();
1974 g_audioManager.Enable(true);
1975 g_audioManager.Load();
1977 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1978 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1980 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1981 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1982 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1983 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1984 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1987 CLog::Log(LOGINFO, " skin loaded...");
1989 // leave the graphics lock
1993 if (currentWindow != WINDOW_INVALID)
1995 g_windowManager.ActivateWindow(currentWindow);
1996 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1998 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1999 if (dialog) dialog->Show();
2003 pWindow = g_windowManager.GetWindow(currentWindow);
2004 if (pWindow && pWindow->HasSaveLastControl())
2006 CGUIMessage msg(GUI_MSG_SETFOCUS, currentWindow, iCtrlID, 0);
2007 pWindow->OnMessage(msg);
2012 if (g_application.m_pPlayer->IsPlayingVideo())
2014 if (bPreviousPlayingState)
2015 g_application.m_pPlayer->Pause();
2016 if (bPreviousRenderingState)
2017 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2022 void CApplication::UnloadSkin(bool forReload /* = false */)
2024 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2026 g_audioManager.Enable(false);
2028 g_windowManager.DeInitialize();
2029 CTextureCache::Get().Deinitialize();
2031 // remove the skin-dependent window
2032 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2034 g_TextureManager.Cleanup();
2035 g_largeTextureManager.CleanupUnusedImages(true);
2037 g_fontManager.Clear();
2039 g_colorManager.Clear();
2041 g_infoManager.Clear();
2043 // The g_SkinInfo boost shared_ptr ought to be reset here
2044 // but there are too many places it's used without checking for NULL
2045 // and as a result a race condition on exit can cause a crash.
2048 bool CApplication::LoadUserWindows()
2050 // Start from wherever home.xml is
2051 std::vector<CStdString> vecSkinPath;
2052 g_SkinInfo->GetSkinPaths(vecSkinPath);
2053 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2055 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2056 CFileItemList items;
2057 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2059 for (int i = 0; i < items.Size(); ++i)
2061 if (items[i]->m_bIsFolder)
2063 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2064 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2066 CXBMCTinyXML xmlDoc;
2067 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2069 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2073 // Root element should be <window>
2074 TiXmlElement* pRootElement = xmlDoc.RootElement();
2075 CStdString strValue = pRootElement->Value();
2076 if (!strValue.Equals("window"))
2078 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2082 // Read the <type> element to get the window type to create
2083 // If no type is specified, create a CGUIWindow as default
2084 CGUIWindow* pWindow = NULL;
2086 if (pRootElement->Attribute("type"))
2087 strType = pRootElement->Attribute("type");
2090 const TiXmlNode *pType = pRootElement->FirstChild("type");
2091 if (pType && pType->FirstChild())
2092 strType = pType->FirstChild()->Value();
2094 int id = WINDOW_INVALID;
2095 if (!pRootElement->Attribute("id", &id))
2097 const TiXmlNode *pType = pRootElement->FirstChild("id");
2098 if (pType && pType->FirstChild())
2099 id = atol(pType->FirstChild()->Value());
2101 CStdString visibleCondition;
2102 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2104 if (strType.Equals("dialog"))
2105 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2106 else if (strType.Equals("submenu"))
2107 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2108 else if (strType.Equals("buttonmenu"))
2109 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2111 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2113 // Check to make sure the pointer isn't still null
2114 if (pWindow == NULL)
2116 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2119 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2124 pWindow->SetVisibleCondition(visibleCondition);
2125 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2126 g_windowManager.AddCustomWindow(pWindow);
2134 bool CApplication::RenderNoPresent()
2138 // DXMERGE: This may have been important?
2139 // g_graphicsContext.AcquireCurrentContext();
2141 g_graphicsContext.Lock();
2143 // dont show GUI when playing full screen video
2144 if (g_graphicsContext.IsFullScreenVideo())
2146 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2147 g_renderManager.Render(true, 0, 255);
2149 // close window overlays
2150 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2151 if (overlay) overlay->Close(true);
2152 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2153 if (overlay) overlay->Close(true);
2157 bool hasRendered = g_windowManager.Render();
2159 g_graphicsContext.Unlock();
2164 float CApplication::GetDimScreenSaverLevel() const
2166 if (!m_bScreenSave || !m_screenSaver ||
2167 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2168 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2169 !m_screenSaver->ID().empty()))
2172 if (!m_screenSaver->GetSetting("level").empty())
2173 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2177 void CApplication::Render()
2179 // do not render if we are stopped or in background
2185 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2187 bool hasRendered = false;
2188 bool limitFrames = false;
2189 unsigned int singleFrameTime = 10; // default limit 100 fps
2193 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2194 // Whether externalplayer is playing and we're unfocused
2195 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2197 m_bPresentFrame = false;
2198 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2200 m_bPresentFrame = g_renderManager.FrameWait(100);
2205 // engage the frame limiter as needed
2206 limitFrames = lowfps || extPlayerActive;
2207 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2208 // perhaps allowing it to be set differently than the UI option??
2209 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2210 limitFrames = true; // not using vsync.
2211 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2212 limitFrames = true; // using vsync, but it isn't working.
2216 if (extPlayerActive)
2218 ResetScreenSaver(); // Prevent screensaver dimming the screen
2219 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2222 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2228 CSingleLock lock(g_graphicsContext);
2229 g_infoManager.UpdateFPS();
2231 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2232 g_Windowing.SetVSync(true);
2233 else if (vsync_mode == VSYNC_ALWAYS)
2234 g_Windowing.SetVSync(true);
2235 else if (vsync_mode != VSYNC_DRIVER)
2236 g_Windowing.SetVSync(false);
2238 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2241 if(!g_Windowing.BeginRender())
2244 g_renderManager.FrameMove();
2246 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2247 if(g_graphicsContext.GetStereoMode())
2249 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2250 if(RenderNoPresent())
2253 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2255 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2256 if(RenderNoPresent())
2259 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2263 if(RenderNoPresent())
2267 g_renderManager.FrameFinish();
2269 g_Windowing.EndRender();
2271 // execute post rendering actions (finalize window closing)
2272 g_windowManager.AfterRender();
2274 // reset our info cache - we do this at the end of Render so that it is
2275 // fresh for the next process(), or after a windowclose animation (where process()
2277 g_infoManager.ResetCache();
2280 unsigned int now = XbmcThreads::SystemClockMillis();
2282 m_lastRenderTime = now;
2284 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2285 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2287 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2288 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2292 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2293 if (limitFrames || !flip)
2296 singleFrameTime = 40; //if not flipping, loop at 25 fps
2298 unsigned int frameTime = now - m_lastFrameTime;
2299 if (frameTime < singleFrameTime)
2300 Sleep(singleFrameTime - frameTime);
2302 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2305 g_graphicsContext.Flip(dirtyRegions);
2306 CTimeUtils::UpdateFrameTime(flip);
2308 g_renderManager.UpdateResolution();
2309 g_renderManager.ManageCaptures();
2312 void CApplication::SetStandAlone(bool value)
2314 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2317 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2318 // The window manager will return true if the event is processed, false otherwise.
2319 // If not already processed, this routine handles global keypresses. It returns
2320 // true if the key has been processed, false otherwise.
2322 bool CApplication::OnKey(const CKey& key)
2325 // Turn the mouse off, as we've just got a keypress from controller or remote
2326 g_Mouse.SetActive(false);
2328 // get the current active window
2329 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2331 // this will be checked for certain keycodes that need
2332 // special handling if the screensaver is active
2333 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2335 // a key has been pressed.
2337 m_idleTimer.StartZero();
2338 bool processKey = AlwaysProcess(action);
2340 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2344 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2345 // do not wake up the screensaver right after switching off the playing device
2346 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2347 ret = CApplicationMessenger::Get().CECToggleState();
2349 ret = CApplicationMessenger::Get().CECStandby();
2350 if (!ret) /* display is switched off */
2356 // allow some keys to be processed while the screensaver is active
2357 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2359 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2363 // change this if we have a dialog up
2364 if (g_windowManager.HasModalDialog())
2366 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2368 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2369 { // fullscreen info dialog - special case
2370 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2372 if (!key.IsAnalogButton())
2373 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2375 if (OnAction(action))
2378 // fallthrough to the main window
2379 iWin = WINDOW_FULLSCREEN_VIDEO;
2381 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2383 // current active window is full screen video.
2384 if (g_application.m_pPlayer->IsInMenu())
2386 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2387 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2389 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2391 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2392 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2394 // if no PVR specific action/mapping is found, fall back to default
2395 if (action.GetID() == 0)
2396 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2400 // in any other case use the fullscreen window section of keymap.xml to map key->action
2401 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2406 // current active window isnt the fullscreen window
2407 // just use corresponding section from keymap.xml
2408 // to map key->action
2410 // first determine if we should use keyboard input directly
2411 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2412 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2415 CGUIControl *control = window->GetFocusedControl();
2418 // If this is an edit control set usekeyboard to true. This causes the
2419 // keypress to be processed directly not through the key mappings.
2420 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2423 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2424 // This causes the keypress to be used for list navigation.
2425 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2431 action = CAction(0); // reset our action
2432 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2434 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2435 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2436 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2437 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2438 action.GetID() == ACTION_MOVE_RIGHT ||
2439 action.GetID() == ACTION_MOVE_UP ||
2440 action.GetID() == ACTION_MOVE_DOWN ||
2441 action.GetID() == ACTION_SELECT_ITEM ||
2442 action.GetID() == ACTION_ENTER ||
2443 action.GetID() == ACTION_PREVIOUS_MENU ||
2444 action.GetID() == ACTION_NAV_BACK))
2446 // the action isn't plain navigation - check for a keyboard-specific keymap
2447 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2448 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2449 action.GetID() == ACTION_BACKSPACE ||
2450 action.GetID() == ACTION_SHIFT ||
2451 action.GetID() == ACTION_SYMBOLS ||
2452 action.GetID() == ACTION_CURSOR_LEFT ||
2453 action.GetID() == ACTION_CURSOR_RIGHT)
2454 action = CAction(0); // don't bother with this action
2457 if (!action.GetID())
2459 // keyboard entry - pass the keys through directly
2460 if (key.GetFromService())
2461 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2464 // Check for paste keypress
2465 #ifdef TARGET_WINDOWS
2466 // In Windows paste is ctrl-V
2467 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2468 #elif defined(TARGET_LINUX)
2469 // In Linux paste is ctrl-V
2470 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2471 #elif defined(TARGET_DARWIN_OSX)
2472 // In OSX paste is cmd-V
2473 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2475 // Placeholder for other operating systems
2478 action = CAction(ACTION_PASTE);
2479 // If the unicode is non-zero the keypress is a non-printing character
2480 else if (key.GetUnicode())
2481 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2482 // The keypress is a non-printing character
2484 action = CAction(key.GetVKey() | KEY_VKEY);
2488 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2490 if (OnAction(action))
2492 // failed to handle the keyboard action, drop down through to standard action
2494 if (key.GetFromService())
2496 if (key.GetButtonCode() != KEY_INVALID)
2497 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2500 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2502 if (!key.IsAnalogButton())
2503 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2505 return ExecuteInputAction(action);
2508 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2509 // This needs to return true if it processed the appcommand or false if it didn't
2510 bool CApplication::OnAppCommand(const CAction &action)
2512 // Reset the screen saver
2515 // If we were currently in the screen saver wake up and don't process the appcommand
2516 if (WakeUpScreenSaverAndDPMS())
2519 // The action ID is the APPCOMMAND code. We need to retrieve the action
2520 // associated with this appcommand from the mapping table.
2521 uint32_t appcmd = action.GetID();
2522 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2523 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2524 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2526 // If we couldn't find an action return false to indicate we have not
2527 // handled this appcommand
2528 if (!appcmdaction.GetID())
2530 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2534 // Process the appcommand
2535 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2536 OnAction(appcmdaction);
2538 // Always return true regardless of whether the action succeeded or not.
2539 // This stops Windows handling the appcommand itself.
2543 bool CApplication::OnAction(const CAction &action)
2545 // special case for switching between GUI & fullscreen mode.
2546 if (action.GetID() == ACTION_SHOW_GUI)
2547 { // Switch to fullscreen mode if we can
2548 if (SwitchToFullScreen())
2550 m_navigationTimer.StartZero();
2555 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2557 g_graphicsContext.ToggleFullScreenRoot();
2561 if (action.IsMouse())
2562 g_Mouse.SetActive(true);
2565 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2567 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2569 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2571 CGUIDialogVideoBookmarks::OnAddBookmark();
2574 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2575 // playing or ACTION_PLAYER_PLAY if we are not playing.
2576 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2578 if (m_pPlayer->IsPlaying())
2579 return OnAction(CAction(ACTION_PAUSE));
2581 return OnAction(CAction(ACTION_PLAYER_PLAY));
2584 //if the action would start or stop inertial scrolling
2585 //by gesture - bypass the normal OnAction handler of current window
2586 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2589 // just pass the action to the current window and let it handle it
2590 if (g_windowManager.OnAction(action))
2592 m_navigationTimer.StartZero();
2597 // handle extra global presses
2599 // screenshot : take a screenshot :)
2600 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2602 CScreenShot::TakeScreenshot();
2605 // built in functions : execute the built-in
2606 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2608 CBuiltins::Execute(action.GetName());
2609 m_navigationTimer.StartZero();
2614 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2616 CButtonTranslator::GetInstance().Clear();
2617 CButtonTranslator::GetInstance().Load();
2620 // show info : Shows the current video or song information
2621 if (action.GetID() == ACTION_SHOW_INFO)
2623 g_infoManager.ToggleShowInfo();
2627 // codec info : Shows the current song, video or picture codec information
2628 if (action.GetID() == ACTION_SHOW_CODEC)
2630 g_infoManager.ToggleShowCodec();
2634 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2636 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2639 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2640 char rating = tag->GetRating();
2641 bool needsUpdate(false);
2642 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2644 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2647 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2649 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2655 if (db.Open()) // OpenForWrite() ?
2657 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2660 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2661 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2662 g_windowManager.SendMessage(msg);
2668 // Now check with the playlist player if action can be handled.
2669 // 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.
2670 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2672 if (g_playlistPlayer.OnAction(action))
2676 // Now check with the player if action can be handled.
2677 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2678 (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)) ||
2679 action.GetID() == ACTION_STOP)
2681 if (m_pPlayer->OnAction(action))
2683 // Player ignored action; popup the OSD
2684 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2685 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2686 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2689 // stop : stops playing current audio song
2690 if (action.GetID() == ACTION_STOP)
2696 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2697 // If so, we just jump to the start of the track.
2698 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2701 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2705 // forward action to g_PVRManager and break if it was able to handle it
2706 if (g_PVRManager.OnAction(action))
2709 // forward action to graphic context and see if it can handle it
2710 if (CStereoscopicsManager::Get().OnAction(action))
2713 if (m_pPlayer->IsPlaying())
2715 // forward channel switches to the player - he knows what to do
2716 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2718 m_pPlayer->OnAction(action);
2722 // pause : pauses current audio song
2723 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2727 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2729 if (!m_pPlayer->IsPaused())
2730 { // unpaused - set the playspeed back to normal
2731 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2733 g_audioManager.Enable(m_pPlayer->IsPaused());
2736 if (!m_pPlayer->IsPaused())
2738 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2739 // if we are playing at normal speed, then allow play to pause
2740 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2742 if (m_pPlayer->GetPlaySpeed() != 1)
2744 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2752 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2754 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2755 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2757 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2759 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2764 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2766 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2769 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2772 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2774 // calculate the speed based on the amount the button is held down
2775 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2776 // returns 0 -> MAX_FFWD_SPEED
2777 int iSpeed = 1 << iPower;
2778 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2780 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2782 CLog::Log(LOGDEBUG,"Resetting playspeed");
2786 // allow play to unpause
2789 if (action.GetID() == ACTION_PLAYER_PLAY)
2791 // unpause, and set the playspeed back to normal
2793 g_audioManager.Enable(m_pPlayer->IsPaused());
2795 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2800 // record current file
2801 if (action.GetID() == ACTION_RECORD)
2803 if (m_pPlayer->CanRecord())
2804 m_pPlayer->Record(!m_pPlayer->IsRecording());
2807 if (m_playerController->OnAction(action))
2812 if (action.GetID() == ACTION_SWITCH_PLAYER)
2814 if(m_pPlayer->IsPlaying())
2816 VECPLAYERCORES cores;
2817 CFileItem item(*m_itemCurrentFile.get());
2818 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2819 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2820 if(core != EPC_NONE)
2822 g_application.m_eForcedNextPlayer = core;
2823 item.m_lStartOffset = (int)(GetTime() * 75);
2824 PlayFile(item, true);
2829 VECPLAYERCORES cores;
2830 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2831 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2832 if(core != EPC_NONE)
2835 g_application.m_eForcedNextPlayer = core;
2836 PlayFile(item, false);
2841 if (g_peripherals.OnAction(action))
2844 if (action.GetID() == ACTION_MUTE)
2850 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2852 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2853 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2855 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2857 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2858 g_windowManager.SendMessage(msg);
2863 // Check for global volume control
2864 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2866 if (!m_pPlayer->IsPassthrough())
2870 float volume = m_volumeLevel;
2871 // Android has steps based on the max available volume level
2872 #if defined(TARGET_ANDROID)
2873 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2875 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2877 if (action.GetRepeat())
2878 step *= action.GetRepeat() * 50; // 50 fps
2880 if (action.GetID() == ACTION_VOLUME_UP)
2881 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2883 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2884 SetVolume(volume, false);
2886 // show visual feedback of volume change...
2887 ShowVolumeBar(&action);
2890 // Check for global seek control
2891 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2893 if (!m_pPlayer->CanSeek()) return false;
2894 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2897 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2899 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2900 CGUIControlProfiler::Instance().Start();
2903 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2905 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2906 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2907 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2908 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2909 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2915 void CApplication::FrameMove(bool processEvents, bool processGUI)
2921 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2922 float frameTime = m_frameTime.GetElapsedSeconds();
2923 m_frameTime.StartZero();
2924 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2925 if( frameTime > 0.5 ) frameTime = 0.5;
2927 if (processGUI && m_renderGUI)
2929 g_graphicsContext.Lock();
2930 // check if there are notifications to display
2931 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2932 if (toast && toast->DoWork())
2934 if (!toast->IsDialogRunning())
2939 g_graphicsContext.Unlock();
2941 CWinEvents::MessagePump();
2943 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2944 // Read the input from a remote
2945 g_RemoteControl.Update();
2948 // process input actions
2949 ProcessRemote(frameTime);
2950 ProcessGamepad(frameTime);
2951 ProcessEventServer(frameTime);
2952 ProcessPeripherals(frameTime);
2953 if (processGUI && m_renderGUI)
2955 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2956 m_seekHandler->Process();
2959 if (processGUI && m_renderGUI)
2962 g_windowManager.Process(CTimeUtils::GetFrameTime());
2963 g_windowManager.FrameMove();
2967 bool CApplication::ProcessGamepad(float frameTime)
2969 #ifdef HAS_SDL_JOYSTICK
2973 int iWin = GetActiveWindowID();
2975 g_Joystick.Update();
2976 if (g_Joystick.GetButton(bid))
2979 m_idleTimer.StartZero();
2982 if (WakeUpScreenSaverAndDPMS())
2984 g_Joystick.Reset(true);
2989 CStdString actionName;
2991 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2993 CAction action(actionID, 1.0f, 0.0f, actionName);
2995 g_Mouse.SetActive(false);
2996 return ExecuteInputAction(action);
3003 if (g_Joystick.GetAxis(bid))
3005 if (g_Joystick.GetAmount() < 0)
3011 CStdString actionName;
3013 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3016 if (WakeUpScreenSaverAndDPMS())
3021 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3023 g_Mouse.SetActive(false);
3024 return ExecuteInputAction(action);
3028 g_Joystick.ResetAxis(abs(bid));
3032 if (g_Joystick.GetHat(bid, position))
3035 m_idleTimer.StartZero();
3038 if (WakeUpScreenSaverAndDPMS())
3045 CStdString actionName;
3048 bid = position<<16|bid;
3050 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3052 CAction action(actionID, 1.0f, 0.0f, actionName);
3054 g_Mouse.SetActive(false);
3055 return ExecuteInputAction(action);
3062 bool CApplication::ProcessRemote(float frameTime)
3064 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3065 if (g_RemoteControl.GetButton())
3067 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3068 g_RemoteControl.Reset();
3075 bool CApplication::ProcessPeripherals(float frameTime)
3078 if (g_peripherals.GetNextKeypress(frameTime, key))
3083 bool CApplication::ProcessMouse()
3087 if (!g_Mouse.IsActive() || !m_AppFocused)
3090 // Get the mouse command ID
3091 uint32_t mousecommand = g_Mouse.GetAction();
3092 if (mousecommand == ACTION_NOOP)
3095 // Reset the screensaver and idle timers
3096 m_idleTimer.StartZero();
3098 if (WakeUpScreenSaverAndDPMS())
3101 // Retrieve the corresponding action
3102 int iWin = GetActiveWindowID();
3103 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3104 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3106 // Deactivate mouse if non-mouse action
3107 if (!mouseaction.IsMouse())
3108 g_Mouse.SetActive(false);
3110 // Consume ACTION_NOOP.
3111 // Some views or dialogs gets closed after any ACTION and
3112 // a sensitive mouse might cause problems.
3113 if (mouseaction.GetID() == ACTION_NOOP)
3116 // If we couldn't find an action return false to indicate we have not
3117 // handled this mouse action
3118 if (!mouseaction.GetID())
3120 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3124 // Log mouse actions except for move and noop
3125 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3126 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3128 // The action might not be a mouse action. For example wheel moves might
3129 // be mapped to volume up/down in mouse.xml. In this case we do not want
3130 // the mouse position saved in the action.
3131 if (!mouseaction.IsMouse())
3132 return OnAction(mouseaction);
3134 // This is a mouse action so we need to record the mouse position
3135 return OnAction(CAction(mouseaction.GetID(),
3136 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3137 (float)g_Mouse.GetX(),
3138 (float)g_Mouse.GetY(),
3139 (float)g_Mouse.GetDX(),
3140 (float)g_Mouse.GetDY(),
3141 mouseaction.GetName()));
3144 bool CApplication::ProcessEventServer(float frameTime)
3146 #ifdef HAS_EVENT_SERVER
3147 CEventServer* es = CEventServer::GetInstance();
3148 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3151 // process any queued up actions
3152 if (es->ExecuteNextAction())
3154 // reset idle timers
3155 m_idleTimer.StartZero();
3157 WakeUpScreenSaverAndDPMS();
3160 // now handle any buttons or axis
3161 std::string joystickName;
3162 bool isAxis = false;
3163 float fAmount = 0.0;
3165 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3166 // when the action exits XBMC
3167 es = CEventServer::GetInstance();
3168 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3170 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3174 if (joystickName.length() > 0)
3178 if (fabs(fAmount) >= 0.08)
3179 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3181 m_lastAxisMap[joystickName].erase(wKeyID);
3184 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3189 if (wKeyID & ES_FLAG_UNICODE)
3191 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3195 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3196 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3197 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3198 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3199 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3200 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3201 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3202 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3203 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3204 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3205 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3206 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3207 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3208 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3209 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3210 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3211 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3212 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3213 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3214 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3217 key.SetFromService(true);
3222 if (m_lastAxisMap.size() > 0)
3224 // Process all the stored axis.
3225 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3227 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3228 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3234 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3236 XBMC_Event newEvent;
3237 newEvent.type = XBMC_MOUSEMOTION;
3238 newEvent.motion.xrel = 0;
3239 newEvent.motion.yrel = 0;
3240 newEvent.motion.state = 0;
3241 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3242 newEvent.motion.x = (uint16_t)pos.x;
3243 newEvent.motion.y = (uint16_t)pos.y;
3244 OnEvent(newEvent); // had to call this to update g_Mouse position
3245 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3252 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3254 #if defined(HAS_EVENT_SERVER)
3255 m_idleTimer.StartZero();
3257 // Make sure to reset screen saver, mouse.
3259 if (WakeUpScreenSaverAndDPMS())
3262 #ifdef HAS_SDL_JOYSTICK
3265 g_Mouse.SetActive(false);
3267 int iWin = GetActiveWindowID();
3269 CStdString actionName;
3270 bool fullRange = false;
3272 // Translate using regular joystick translator.
3273 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3274 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3276 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3282 bool CApplication::ExecuteInputAction(const CAction &action)
3284 bool bResult = false;
3286 // play sound before the action unless the button is held,
3287 // where we execute after the action as held actions aren't fired every time.
3288 if(action.GetHoldTime())
3290 bResult = OnAction(action);
3292 g_audioManager.PlayActionSound(action);
3296 g_audioManager.PlayActionSound(action);
3297 bResult = OnAction(action);
3302 int CApplication::GetActiveWindowID(void)
3304 // Get the currently active window
3305 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3307 // If there is a dialog active get the dialog id instead
3308 if (g_windowManager.HasModalDialog())
3309 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3311 // If the window is FullScreenVideo check for special cases
3312 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3314 // check if we're in a DVD menu
3315 if(g_application.m_pPlayer->IsInMenu())
3316 iWin = WINDOW_VIDEO_MENU;
3317 // check for LiveTV and switch to it's virtual window
3318 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3319 iWin = WINDOW_FULLSCREEN_LIVETV;
3322 // Return the window id
3326 bool CApplication::Cleanup()
3330 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3331 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3332 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3333 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3334 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3335 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3336 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3337 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3338 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3339 g_windowManager.Delete(WINDOW_FILES);
3340 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3341 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3342 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3343 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3344 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3345 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3346 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3347 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3348 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3349 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3350 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3351 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3352 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3353 g_windowManager.Delete(WINDOW_DIALOG_OK);
3354 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3355 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3356 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3357 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3358 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3359 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3360 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3361 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3362 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3363 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3364 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3365 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3366 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3367 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3368 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3369 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3370 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3371 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3372 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3373 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3374 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3375 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3376 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3378 /* Delete PVR related windows and dialogs */
3379 g_windowManager.Delete(WINDOW_PVR);
3380 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3381 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3382 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3383 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3384 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3385 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3386 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3387 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3388 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3389 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3390 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3391 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3392 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3394 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3395 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3396 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3397 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3398 g_windowManager.Delete(WINDOW_VISUALISATION);
3399 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3400 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3401 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3402 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3403 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3404 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3405 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3406 g_windowManager.Delete(WINDOW_SCREENSAVER);
3407 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3408 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3409 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3410 g_windowManager.Delete(WINDOW_SLIDESHOW);
3411 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3412 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3414 g_windowManager.Delete(WINDOW_HOME);
3415 g_windowManager.Delete(WINDOW_PROGRAMS);
3416 g_windowManager.Delete(WINDOW_PICTURES);
3417 g_windowManager.Delete(WINDOW_WEATHER);
3419 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3420 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3421 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3422 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3423 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3424 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3425 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3426 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3427 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3428 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3430 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3431 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3433 CAddonMgr::Get().DeInit();
3435 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3436 CLog::Log(LOGNOTICE, "closing down remote control service");
3437 g_RemoteControl.Disconnect();
3440 CLog::Log(LOGNOTICE, "unload sections");
3442 #ifdef HAS_PERFORMANCE_SAMPLE
3443 CLog::Log(LOGNOTICE, "performance statistics");
3444 m_perfStats.DumpStats();
3447 // Shutdown as much as possible of the
3448 // application, to reduce the leaks dumped
3449 // to the vc output window before calling
3450 // _CrtDumpMemoryLeaks(). Most of the leaks
3451 // shown are no real leaks, as parts of the app
3452 // are still allocated.
3454 g_localizeStrings.Clear();
3455 g_LangCodeExpander.Clear();
3456 g_charsetConverter.clear();
3457 g_directoryCache.Clear();
3458 CButtonTranslator::GetInstance().Clear();
3459 #ifdef HAS_EVENT_SERVER
3460 CEventServer::RemoveInstance();
3462 DllLoaderContainer::Clear();
3463 g_playlistPlayer.Clear();
3464 CSettings::Get().Uninitialize();
3465 g_advancedSettings.Clear();
3468 CXHandle::DumpObjectTracker();
3470 #ifdef HAS_DVD_DRIVE
3471 CLibcdio::ReleaseInstance();
3474 #if defined(TARGET_ANDROID)
3475 // enable for all platforms once it's safe
3476 g_sectionLoader.UnloadAll();
3478 #ifdef _CRTDBG_MAP_ALLOC
3479 _CrtDumpMemoryLeaks();
3480 while(1); // execution ends
3490 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3495 void CApplication::Stop(int exitCode)
3499 CVariant vExitCode(exitCode);
3500 CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
3502 SaveFileState(true);
3504 g_alarmClock.StopThread();
3506 if( m_bSystemScreenSaverEnable )
3507 g_Windowing.EnableSystemScreenSaver(true);
3509 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3510 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3512 // Update the settings information (volume, uptime etc. need saving)
3513 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3515 CLog::Log(LOGNOTICE, "Saving settings");
3516 CSettings::Get().Save();
3519 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3522 m_AppFocused = false;
3523 m_ExitCode = exitCode;
3524 CLog::Log(LOGNOTICE, "stop all");
3526 // cancel any jobs from the jobmanager
3527 CJobManager::GetInstance().CancelJobs();
3529 // stop scanning before we kill the network and so on
3530 if (m_musicInfoScanner->IsScanning())
3531 m_musicInfoScanner->Stop();
3533 if (m_videoInfoScanner->IsScanning())
3534 m_videoInfoScanner->Stop();
3536 CApplicationMessenger::Get().Cleanup();
3538 CLog::Log(LOGNOTICE, "stop player");
3539 m_pPlayer->ClosePlayer();
3541 CAnnouncementManager::Get().Deinitialize();
3547 #if HAS_FILESYTEM_DAAP
3548 CLog::Log(LOGNOTICE, "stop daap clients");
3549 g_DaapClient.Release();
3551 #ifdef HAS_FILESYSTEM_SAP
3552 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3553 g_sapsessions.StopThread();
3556 if(CZeroconfBrowser::IsInstantiated())
3558 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3559 CZeroconfBrowser::GetInstance()->Stop();
3560 CZeroconfBrowser::ReleaseInstance();
3564 CLog::Log(LOGNOTICE, "clean cached files!");
3565 #ifdef HAS_FILESYSTEM_RAR
3566 g_RarManager.ClearCache(true);
3569 #ifdef HAS_FILESYSTEM_SFTP
3570 CSFTPSessionManager::DisconnectAllSessions();
3573 CLog::Log(LOGNOTICE, "unload skin");
3576 #if defined(TARGET_DARWIN_OSX)
3577 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3578 XBMCHelper::GetInstance().Stop();
3581 #if defined(HAVE_LIBCRYSTALHD)
3582 CCrystalHD::RemoveInstance();
3585 g_mediaManager.Stop();
3587 // Stop services before unloading Python
3588 CAddonMgr::Get().StopServices(false);
3590 // stop all remaining scripts; must be done after skin has been unloaded,
3591 // not before some windows still need it when deinitializing during skin
3593 CScriptInvocationManager::Get().Uninitialize();
3595 g_Windowing.DestroyRenderSystem();
3596 g_Windowing.DestroyWindow();
3597 g_Windowing.DestroyWindowSystem();
3599 // shutdown the AudioEngine
3600 CAEFactory::Shutdown();
3601 CAEFactory::UnLoadEngine();
3603 // unregister ffmpeg lock manager call back
3604 av_lockmgr_register(NULL);
3606 CLog::Log(LOGNOTICE, "stopped");
3610 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3613 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3614 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3621 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3623 //If item is a plugin, expand out now and run ourselves again
3624 if (item.IsPlugin())
3626 CFileItem item_new(item);
3627 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3628 return PlayMedia(item_new, iPlaylist);
3631 if (item.IsSmartPlayList())
3633 CFileItemList items;
3634 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3637 CSmartPlaylist smartpl;
3638 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3639 smartpl.OpenAndReadName(item.GetPath());
3641 playlist.Add(items);
3642 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3645 else if (item.IsPlayList() || item.IsInternetStream())
3647 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3649 //is or could be a playlist
3650 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3651 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3656 if (dlgCache->IsCanceled())
3663 if (iPlaylist != PLAYLIST_NONE)
3666 if (item.HasProperty("playlist_starting_track"))
3667 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3668 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3672 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());
3673 if(pPlayList->size())
3674 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3679 //nothing special just play
3680 return PlayFile(item, false) == PLAYBACK_OK;
3684 // For playing a multi-file video. Particularly inefficient
3685 // on startup, as we are required to calculate the length
3686 // of each video, so we open + close each one in turn.
3687 // A faster calculation of video time would improve this
3689 // return value: same with PlayFile()
3690 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3692 if (!item.IsStack())
3693 return PLAYBACK_FAIL;
3697 // case 1: stacked ISOs
3698 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3700 CStackDirectory dir;
3701 CFileItemList movieList;
3702 dir.GetDirectory(item.GetPath(), movieList);
3704 // first assume values passed to the stack
3705 int selectedFile = item.m_lStartPartNumber;
3706 int startoffset = item.m_lStartOffset;
3708 // check if we instructed the stack to resume from default
3709 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3714 CStdString path = item.GetPath();
3715 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3716 path = item.GetProperty("original_listitem_url").asString();
3717 if( dbs.GetResumeBookMark(path, bookmark) )
3719 startoffset = (int)(bookmark.timeInSeconds*75);
3720 selectedFile = bookmark.partNumber;
3725 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3728 // make sure that the selected part is within the boundaries
3729 if (selectedFile <= 0)
3731 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3734 else if (selectedFile > movieList.Size())
3736 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3737 selectedFile = movieList.Size();
3740 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3741 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3742 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3743 *m_stackFileItemToUpdate = item;
3744 return PlayFile(*(movieList[selectedFile - 1]));
3746 // case 2: all other stacks
3749 // see if we have the info in the database
3750 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3751 // then these times will be wrong.
3752 // Also, this is really just a hack for the slow load up times we have
3753 // A much better solution is a fast reader of FPS and fileLength
3754 // that we can use on a file to get it's time.
3756 bool haveTimes(false);
3760 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3761 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3766 // calculate the total time of the stack
3767 CStackDirectory dir;
3768 dir.GetDirectory(item.GetPath(), *m_currentStack);
3770 for (int i = 0; i < m_currentStack->Size(); i++)
3773 (*m_currentStack)[i]->m_lEndOffset = times[i];
3777 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3779 m_currentStack->Clear();
3780 return PLAYBACK_FAIL;
3782 totalTime += duration / 1000;
3783 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3784 times.push_back(totalTime);
3788 double seconds = item.m_lStartOffset / 75.0;
3790 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3791 { // have our times now, so update the dB
3795 dbs.SetStackTimes(item.GetPath(), times);
3797 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3799 // can only resume seek here, not dvdstate
3801 CStdString path = item.GetPath();
3802 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3803 path = item.GetProperty("original_listitem_url").asString();
3804 if( dbs.GetResumeBookMark(path, bookmark) )
3805 seconds = bookmark.timeInSeconds;
3813 *m_itemCurrentFile = item;
3814 m_currentStackPosition = 0;
3815 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3819 // work out where to seek to
3820 for (int i = 0; i < m_currentStack->Size(); i++)
3822 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3824 CFileItem item(*(*m_currentStack)[i]);
3825 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3826 item.m_lStartOffset = (long)(seconds - start) * 75;
3827 m_currentStackPosition = i;
3828 return PlayFile(item, true);
3833 return PlayFile(*(*m_currentStack)[0], true);
3835 return PLAYBACK_FAIL;
3838 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3840 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3841 if (item.GetMimeType().empty())
3842 const_cast<CFileItem&>(item).FillInMimeType();
3846 SaveCurrentFileSettings();
3848 OutputDebugString("new file set audiostream:0\n");
3849 // Switch to default options
3850 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3851 // see if we have saved options in the database
3853 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3854 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3856 *m_itemCurrentFile = item;
3857 m_nextPlaylistItem = -1;
3858 m_currentStackPosition = 0;
3859 m_currentStack->Clear();
3862 CUtil::ClearSubtitles();
3865 if (item.IsDiscStub())
3867 #ifdef HAS_DVD_DRIVE
3868 // Display the Play Eject dialog if there is any optical disc drive
3869 if (g_mediaManager.HasOpticalDrive())
3871 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3872 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3873 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3874 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3878 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3883 if (item.IsPlayList())
3884 return PLAYBACK_FAIL;
3886 if (item.IsPlugin())
3887 { // we modify the item so that it becomes a real URL
3888 CFileItem item_new(item);
3889 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3890 return PlayFile(item_new, false);
3891 return PLAYBACK_FAIL;
3895 if (URIUtils::IsUPnP(item.GetPath()))
3897 CFileItem item_new(item);
3898 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3899 return PlayFile(item_new, false);
3900 return PLAYBACK_FAIL;
3904 // if we have a stacked set of files, we need to setup our stack routines for
3905 // "seamless" seeking and total time of the movie etc.
3906 // will recall with restart set to true
3908 return PlayStack(item, bRestart);
3910 //Is TuxBox, this should probably be moved to CTuxBoxFile
3913 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3915 if(g_tuxboxService.IsRunning())
3916 g_tuxboxService.Stop();
3918 PlayBackRet ret = PLAYBACK_FAIL;
3920 if(g_tuxbox.CreateNewItem(item, item_new))
3923 // Make sure it doesn't have a player
3924 // so we actually select one normally
3925 m_pPlayer->ResetPlayer();
3927 // keep the tuxbox:// url as playing url
3928 // and give the new url to the player
3929 ret = PlayFile(item_new, true);
3930 if(ret == PLAYBACK_OK)
3932 if(!g_tuxboxService.IsRunning())
3933 g_tuxboxService.Start();
3939 CPlayerOptions options;
3941 if( item.HasProperty("StartPercent") )
3943 double fallback = 0.0f;
3944 if(item.GetProperty("StartPercent").isString())
3945 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3946 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3949 PLAYERCOREID eNewCore = EPC_NONE;
3952 // have to be set here due to playstack using this for starting the file
3953 options.starttime = item.m_lStartOffset / 75.0;
3954 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3955 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3957 if( m_eForcedNextPlayer != EPC_NONE )
3958 eNewCore = m_eForcedNextPlayer;
3959 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3960 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3962 eNewCore = m_pPlayer->GetCurrentPlayer();
3966 options.starttime = item.m_lStartOffset / 75.0;
3970 // open the d/b and retrieve the bookmarks for the current movie
3973 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3975 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3977 options.starttime = 0.0f;
3979 CStdString path = item.GetPath();
3980 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3981 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3982 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3983 path = item.GetProperty("original_listitem_url").asString();
3984 if(dbs.GetResumeBookMark(path, bookmark))
3986 options.starttime = bookmark.timeInSeconds;
3987 options.state = bookmark.playerState;
3990 override with information from the actual item if available. We do this as the VFS (eg plugins)
3991 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3992 should the playerState be required, it is fetched from the database.
3993 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3995 if (item.IsResumePointSet())
3996 options.starttime = item.GetCurrentResumeTime();
3998 else if (item.HasVideoInfoTag())
4000 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4002 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4005 dbs.GetBookMarkForEpisode(*tag, bookmark);
4006 options.starttime = bookmark.timeInSeconds;
4007 options.state = bookmark.playerState;
4014 if (m_eForcedNextPlayer != EPC_NONE)
4015 eNewCore = m_eForcedNextPlayer;
4017 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4020 // this really aught to be inside !bRestart, but since PlayStack
4021 // uses that to init playback, we have to keep it outside
4022 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4023 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4024 { // playing from a playlist by the looks
4025 // don't switch to fullscreen if we are not playing the first item...
4026 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4028 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4030 // TODO - this will fail if user seeks back to first file in stack
4031 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4032 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4034 options.fullscreen = false;
4035 // reset this so we don't think we are resuming on seek
4036 m_itemCurrentFile->m_lStartOffset = 0;
4039 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4041 // reset VideoStartWindowed as it's a temp setting
4042 CMediaSettings::Get().SetVideoStartWindowed(false);
4045 //We have to stop parsing a cdg before mplayer is deallocated
4046 // WHY do we have to do this????
4048 m_pKaraokeMgr->Stop();
4052 CSingleLock lock(m_playStateMutex);
4053 // tell system we are starting a file
4054 m_bPlaybackStarting = true;
4056 // for playing a new item, previous playing item's callback may already
4057 // pushed some delay message into the threadmessage list, they are not
4058 // expected be processed after or during the new item playback starting.
4059 // so we clean up previous playing item's playback callback delay messages here.
4060 int previousMsgsIgnoredByNewPlaying[] = {
4061 GUI_MSG_PLAYBACK_STARTED,
4062 GUI_MSG_PLAYBACK_ENDED,
4063 GUI_MSG_PLAYBACK_STOPPED,
4064 GUI_MSG_PLAYLIST_CHANGED,
4065 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4066 GUI_MSG_PLAYLISTPLAYER_STARTED,
4067 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4068 GUI_MSG_QUEUE_NEXT_ITEM,
4071 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4073 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4076 // We should restart the player, unless the previous and next tracks are using
4077 // one of the players that allows gapless playback (paplayer, dvdplayer)
4078 m_pPlayer->ClosePlayerGapless(eNewCore);
4080 // now reset play state to starting, since we already stopped the previous playing item if there is.
4081 // and from now there should be no playback callback from previous playing item be called.
4082 m_ePlayState = PLAY_STATE_STARTING;
4084 m_pPlayer->CreatePlayer(eNewCore, *this);
4086 PlayBackRet iResult;
4087 if (m_pPlayer->HasPlayer())
4089 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4090 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4091 * increase performance on low powered systems (Atom/ARM).
4095 CJobManager::GetInstance().PauseJobs();
4098 // don't hold graphicscontext here since player
4099 // may wait on another thread, that requires gfx
4100 CSingleExit ex(g_graphicsContext);
4102 iResult = m_pPlayer->OpenFile(item, options);
4106 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4107 iResult = PLAYBACK_FAIL;
4110 if(iResult == PLAYBACK_OK)
4112 if (m_pPlayer->GetPlaySpeed() != 1)
4114 int iSpeed = m_pPlayer->GetPlaySpeed();
4115 m_pPlayer->m_iPlaySpeed = 1;
4116 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4119 // if player has volume control, set it.
4120 if (m_pPlayer->ControlsVolume())
4122 m_pPlayer->SetVolume(m_volumeLevel);
4123 m_pPlayer->SetMute(m_muted);
4126 if( m_pPlayer->IsPlayingAudio() )
4128 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4129 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4132 #ifdef HAS_VIDEO_PLAYBACK
4133 else if( m_pPlayer->IsPlayingVideo() )
4135 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4136 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4138 // if player didn't manange to switch to fullscreen by itself do it here
4139 if( options.fullscreen && g_renderManager.IsStarted()
4140 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4141 SwitchToFullScreen();
4146 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4147 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4148 g_windowManager.PreviousWindow();
4152 #if !defined(TARGET_POSIX)
4153 g_audioManager.Enable(false);
4156 if (item.HasPVRChannelInfoTag())
4157 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4160 CSingleLock lock(m_playStateMutex);
4161 m_bPlaybackStarting = false;
4163 if (iResult == PLAYBACK_OK)
4165 // play state: none, starting; playing; stopped; ended.
4166 // last 3 states are set by playback callback, they are all ignored during starting,
4167 // but we recorded the state, here we can make up the callback for the state.
4168 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4169 switch (m_ePlayState)
4171 case PLAY_STATE_PLAYING:
4172 OnPlayBackStarted();
4174 // FIXME: it seems no meaning to callback started here if there was an started callback
4175 // before this stopped/ended callback we recorded. if we callback started here
4176 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4177 // which will send OnStop announce at once, so currently, just call stopped/ended.
4178 case PLAY_STATE_ENDED:
4181 case PLAY_STATE_STOPPED:
4182 OnPlayBackStopped();
4184 case PLAY_STATE_STARTING:
4185 // neither started nor stopped/ended callback be called, that means the item still
4186 // not started, we need not make up any callback, just leave this and
4187 // let the player callback do its work.
4193 else if (iResult == PLAYBACK_FAIL)
4195 // we send this if it isn't playlistplayer that is doing this
4196 int next = g_playlistPlayer.GetNextSong();
4197 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4200 OnPlayBackStopped();
4201 m_ePlayState = PLAY_STATE_NONE;
4207 void CApplication::OnPlayBackEnded()
4209 CSingleLock lock(m_playStateMutex);
4210 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4211 m_ePlayState = PLAY_STATE_ENDED;
4212 if(m_bPlaybackStarting)
4215 // informs python script currently running playback has ended
4216 // (does nothing if python is not loaded)
4218 g_pythonParser.OnPlayBackEnded();
4221 CVariant data(CVariant::VariantTypeObject);
4223 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4225 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4226 g_windowManager.SendThreadMessage(msg);
4229 void CApplication::OnPlayBackStarted()
4231 CSingleLock lock(m_playStateMutex);
4232 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4233 m_ePlayState = PLAY_STATE_PLAYING;
4234 if(m_bPlaybackStarting)
4238 // informs python script currently running playback has started
4239 // (does nothing if python is not loaded)
4240 g_pythonParser.OnPlayBackStarted();
4243 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4244 g_windowManager.SendThreadMessage(msg);
4247 void CApplication::OnQueueNextItem()
4249 CSingleLock lock(m_playStateMutex);
4250 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4251 if(m_bPlaybackStarting)
4253 // informs python script currently running that we are requesting the next track
4254 // (does nothing if python is not loaded)
4256 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4259 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4260 g_windowManager.SendThreadMessage(msg);
4263 void CApplication::OnPlayBackStopped()
4265 CSingleLock lock(m_playStateMutex);
4266 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4267 m_ePlayState = PLAY_STATE_STOPPED;
4268 if(m_bPlaybackStarting)
4271 // informs python script currently running playback has ended
4272 // (does nothing if python is not loaded)
4274 g_pythonParser.OnPlayBackStopped();
4277 CVariant data(CVariant::VariantTypeObject);
4278 data["end"] = false;
4279 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4281 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4282 g_windowManager.SendThreadMessage(msg);
4285 void CApplication::OnPlayBackPaused()
4288 g_pythonParser.OnPlayBackPaused();
4292 param["player"]["speed"] = 0;
4293 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4294 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4297 void CApplication::OnPlayBackResumed()
4300 g_pythonParser.OnPlayBackResumed();
4304 param["player"]["speed"] = 1;
4305 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4306 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4309 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4312 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4316 param["player"]["speed"] = iSpeed;
4317 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4318 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4321 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4324 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4328 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4329 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4330 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4331 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4332 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4333 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4336 void CApplication::OnPlayBackSeekChapter(int iChapter)
4339 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4343 bool CApplication::IsPlayingFullScreenVideo() const
4345 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4348 bool CApplication::IsFullScreen()
4350 return IsPlayingFullScreenVideo() ||
4351 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4352 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4355 void CApplication::SaveFileState(bool bForeground /* = false */)
4357 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4362 CSaveFileStateJob job(*m_progressTrackingItem,
4363 *m_stackFileItemToUpdate,
4364 m_progressTrackingVideoResumeBookmark,
4365 m_progressTrackingPlayCountUpdate);
4367 // Run job in the foreground to make sure it finishes
4372 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4373 *m_stackFileItemToUpdate,
4374 m_progressTrackingVideoResumeBookmark,
4375 m_progressTrackingPlayCountUpdate);
4376 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4380 void CApplication::UpdateFileState()
4382 // Did the file change?
4383 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4387 // Reset tracking item
4388 m_progressTrackingItem->Reset();
4392 if (m_pPlayer->IsPlaying())
4394 if (m_progressTrackingItem->GetPath() == "")
4397 *m_progressTrackingItem = CurrentFileItem();
4398 m_progressTrackingPlayCountUpdate = false;
4401 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4402 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4403 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4404 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4406 m_progressTrackingPlayCountUpdate = true;
4409 // Check whether we're *really* playing video else we may race when getting eg. stream details
4410 if (m_pPlayer->IsPlayingVideo())
4412 /* Always update streamdetails, except for DVDs where we only update
4413 streamdetails if title length > 15m (Should yield more correct info) */
4414 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4416 CStreamDetails details;
4417 // Update with stream details from player, if any
4418 if (m_pPlayer->GetStreamDetails(details))
4419 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4421 if (m_progressTrackingItem->IsStack())
4422 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4425 // Update bookmark for save
4426 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4427 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4428 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4430 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4431 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4433 // Delete the bookmark
4434 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4437 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4439 // Update the bookmark
4440 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4441 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4446 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4453 void CApplication::StopPlaying()
4455 int iWin = g_windowManager.GetActiveWindow();
4456 if ( m_pPlayer->IsPlaying() )
4460 m_pKaraokeMgr->Stop();
4463 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4464 g_PVRManager.SaveCurrentChannelSettings();
4466 m_pPlayer->CloseFile();
4468 // turn off visualisation window when stopping
4469 if ((iWin == WINDOW_VISUALISATION
4470 || iWin == WINDOW_FULLSCREEN_VIDEO)
4472 g_windowManager.PreviousWindow();
4474 g_partyModeManager.Disable();
4478 void CApplication::ResetSystemIdleTimer()
4480 // reset system idle timer
4481 m_idleTimer.StartZero();
4484 void CApplication::ResetScreenSaver()
4487 m_shutdownTimer.StartZero();
4489 // screen saver timer is reset only if we're not already in screensaver or
4491 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4492 ResetScreenSaverTimer();
4495 void CApplication::ResetScreenSaverTimer()
4497 m_screenSaverTimer.StartZero();
4500 void CApplication::StopScreenSaverTimer()
4502 m_screenSaverTimer.Stop();
4505 bool CApplication::ToggleDPMS(bool manual)
4507 if (manual || (m_dpmsIsManual == manual))
4511 m_dpmsIsActive = false;
4512 m_dpmsIsManual = false;
4513 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSDeactivated");
4514 return m_dpms->DisablePowerSaving();
4518 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4520 m_dpmsIsActive = true;
4521 m_dpmsIsManual = manual;
4522 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSActivated");
4530 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4534 // First reset DPMS, if active
4539 // TODO: if screensaver lock is specified but screensaver is not active
4540 // (DPMS came first), activate screensaver now.
4542 ResetScreenSaverTimer();
4543 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4546 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4550 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4551 CVariant data(bPowerOffKeyPressed);
4552 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4558 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4560 if (m_iScreenSaveLock == 2)
4563 // if Screen saver is active
4564 if (m_bScreenSave && m_screenSaver)
4566 if (m_iScreenSaveLock == 0)
4567 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4568 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4569 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4570 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4572 m_iScreenSaveLock = 2;
4573 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4575 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4577 pWindow->OnMessage(msg);
4579 if (m_iScreenSaveLock == -1)
4581 m_iScreenSaveLock = 0;
4585 // disable screensaver
4586 m_bScreenSave = false;
4587 m_iScreenSaveLock = 0;
4588 ResetScreenSaverTimer();
4590 if (m_screenSaver->ID() == "visualization")
4592 // we can just continue as usual from vis mode
4595 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4597 else if (!m_screenSaver->ID().empty())
4598 { // we're in screensaver window
4599 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4600 g_windowManager.PreviousWindow(); // show the previous window
4601 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4602 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4610 void CApplication::CheckScreenSaverAndDPMS()
4612 if (!m_dpmsIsActive)
4613 g_Windowing.ResetOSScreensaver();
4615 bool maybeScreensaver =
4616 !m_dpmsIsActive && !m_bScreenSave
4617 && !CSettings::Get().GetString("screensaver.mode").empty();
4619 !m_dpmsIsActive && m_dpms->IsSupported()
4620 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4622 // Has the screen saver window become active?
4623 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4625 m_bScreenSave = true;
4626 maybeScreensaver = false;
4629 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4631 WakeUpScreenSaverAndDPMS();
4635 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4637 // See if we need to reset timer.
4638 // * Are we playing a video and it is not paused?
4639 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4640 // * Are we playing some music in fullscreen vis?
4641 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4642 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4644 ResetScreenSaverTimer();
4648 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4650 // DPMS has priority (it makes the screensaver not needed)
4652 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4655 WakeUpScreenSaver();
4657 else if (maybeScreensaver
4658 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4660 ActivateScreenSaver();
4664 // activate the screensaver.
4665 // if forceType is true, we ignore the various conditions that can alter
4666 // the type of screensaver displayed
4667 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4669 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4670 { // just activate the visualisation if user toggled the usemusicvisinstead option
4671 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4675 m_bScreenSave = true;
4677 // Get Screensaver Mode
4678 m_screenSaver.reset();
4679 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4680 m_screenSaver.reset(new CScreenSaver(""));
4682 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverActivated");
4684 // disable screensaver lock from the login screen
4685 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4688 // set to Dim in the case of a dialog on screen or playing video
4689 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4691 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4692 m_screenSaver.reset(new CScreenSaver(""));
4695 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4697 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4699 else if (!m_screenSaver->ID().empty())
4700 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4703 void CApplication::CheckShutdown()
4705 // first check if we should reset the timer
4706 if (m_bInhibitIdleShutdown
4707 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4708 || m_musicInfoScanner->IsScanning()
4709 || m_videoInfoScanner->IsScanning()
4710 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4711 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4713 m_shutdownTimer.StartZero();
4717 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4719 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4720 m_shutdownTimer.Stop();
4723 CApplicationMessenger::Get().Shutdown();
4727 void CApplication::InhibitIdleShutdown(bool inhibit)
4729 m_bInhibitIdleShutdown = inhibit;
4732 bool CApplication::IsIdleShutdownInhibited() const
4734 return m_bInhibitIdleShutdown;
4737 bool CApplication::OnMessage(CGUIMessage& message)
4739 switch ( message.GetMessage() )
4741 case GUI_MSG_NOTIFY_ALL:
4743 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4745 // Update general playlist: Remove DVD playlist items
4746 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4749 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4750 g_windowManager.SendMessage( msg );
4752 // stop the file if it's on dvd (will set the resume point etc)
4753 if (m_itemCurrentFile->IsOnDVD())
4759 case GUI_MSG_PLAYBACK_STARTED:
4761 #ifdef TARGET_DARWIN
4762 DarwinSetScheduling(message.GetMessage());
4764 // reset the seek handler
4765 m_seekHandler->Reset();
4766 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4768 // Update our infoManager with the new details etc.
4769 if (m_nextPlaylistItem >= 0)
4771 // playing an item which is not in the list - player might be stopped already
4773 if (playList.size() <= m_nextPlaylistItem)
4776 // we've started a previously queued item
4777 CFileItemPtr item = playList[m_nextPlaylistItem];
4778 // update the playlist manager
4779 int currentSong = g_playlistPlayer.GetCurrentSong();
4780 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4781 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4782 g_windowManager.SendThreadMessage(msg);
4783 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4784 *m_itemCurrentFile = *item;
4786 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4787 g_partyModeManager.OnSongChange(true);
4790 param["player"]["speed"] = 1;
4791 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4792 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4794 if (m_pPlayer->IsPlayingAudio())
4796 // Start our cdg parser as appropriate
4798 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4800 m_pKaraokeMgr->Stop();
4801 if (m_itemCurrentFile->IsMusicDb())
4803 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4805 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4806 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4809 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4812 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4821 case GUI_MSG_QUEUE_NEXT_ITEM:
4823 // Check to see if our playlist player has a new item for us,
4824 // and if so, we check whether our current player wants the file
4825 int iNext = g_playlistPlayer.GetNextSong();
4826 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4827 if (iNext < 0 || iNext >= playlist.size())
4829 m_pPlayer->OnNothingToQueueNotify();
4830 return true; // nothing to do
4833 // ok, grab the next song
4834 CFileItem file(*playlist[iNext]);
4836 CURL url(file.GetPath());
4837 if (url.GetProtocol() == "plugin")
4838 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4841 if (URIUtils::IsUPnP(file.GetPath()))
4843 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4848 // ok - send the file to the player, if it accepts it
4849 if (m_pPlayer->QueueNextFile(file))
4851 // player accepted the next file
4852 m_nextPlaylistItem = iNext;
4856 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4857 queue the next (if it wants to) and it doesn't keep looping on this song */
4858 g_playlistPlayer.SetCurrentSong(iNext);
4865 case GUI_MSG_PLAYBACK_STOPPED:
4866 case GUI_MSG_PLAYBACK_ENDED:
4867 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4871 m_pKaraokeMgr->Stop();
4873 #ifdef TARGET_DARWIN
4874 DarwinSetScheduling(message.GetMessage());
4876 // first check if we still have items in the stack to play
4877 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4879 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4880 { // just play the next item in the stack
4881 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4886 // In case playback ended due to user eg. skipping over the end, clear
4887 // our resume bookmark here
4888 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4890 // Delete the bookmark
4891 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4894 // reset the current playing file
4895 m_itemCurrentFile->Reset();
4896 g_infoManager.ResetCurrentItem();
4897 m_currentStack->Clear();
4899 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4901 g_playlistPlayer.PlayNext(1, true);
4905 // reset any forced player
4906 m_eForcedNextPlayer = EPC_NONE;
4908 m_pPlayer->ClosePlayer();
4911 m_pPlayer->m_iPlaySpeed = 1;
4914 if (!m_pPlayer->IsPlaying())
4916 g_audioManager.Enable(true);
4919 if (!m_pPlayer->IsPlayingVideo())
4921 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4923 g_windowManager.PreviousWindow();
4927 CSingleLock lock(g_graphicsContext);
4928 // resets to res_desktop or look&feel resolution (including refreshrate)
4929 g_graphicsContext.SetFullScreenVideo(false);
4933 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4935 CSettings::Get().Save(); // save vis settings
4936 WakeUpScreenSaverAndDPMS();
4937 g_windowManager.PreviousWindow();
4940 // DVD ejected while playing in vis ?
4941 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4944 CSettings::Get().Save(); // save vis settings
4945 WakeUpScreenSaverAndDPMS();
4946 g_windowManager.PreviousWindow();
4949 if (IsEnableTestMode())
4950 CApplicationMessenger::Get().Quit();
4955 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4956 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4961 case GUI_MSG_FULLSCREEN:
4962 { // Switch to fullscreen, if we can
4963 SwitchToFullScreen();
4967 case GUI_MSG_EXECUTE:
4968 if (message.GetNumStringParams())
4969 return ExecuteXBMCAction(message.GetStringParam());
4975 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4977 // see if it is a user set string
4979 //We don't know if there is unsecure information in this yet, so we
4980 //postpone any logging
4981 const std::string in_actionStr(actionStr);
4982 CGUIInfoLabel info(actionStr, "");
4983 actionStr = info.GetLabel(0);
4985 // user has asked for something to be executed
4986 if (CBuiltins::HasCommand(actionStr))
4987 CBuiltins::Execute(actionStr);
4990 // try translating the action from our ButtonTranslator
4992 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4994 OnAction(CAction(actionID));
4997 CFileItem item(actionStr, false);
4999 if (item.IsPythonScript())
5000 { // a python script
5001 CScriptInvocationManager::Get().Execute(item.GetPath());
5005 if (item.IsAudio() || item.IsVideo())
5006 { // an audio or video file
5011 //At this point we have given up to translate, so even though
5012 //there may be insecure information, we log it.
5013 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5020 void CApplication::Process()
5024 // dispatch the messages generated by python or other threads to the current window
5025 g_windowManager.DispatchThreadMessages();
5027 // process messages which have to be send to the gui
5028 // (this can only be done after g_windowManager.Render())
5029 CApplicationMessenger::Get().ProcessWindowMessages();
5033 m_loggingIn = false;
5035 // autoexec.py - profile
5036 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5038 if (XFILE::CFile::Exists(strAutoExecPy))
5039 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5041 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5044 // handle any active scripts
5045 CScriptInvocationManager::Get().Process();
5047 // process messages, even if a movie is playing
5048 CApplicationMessenger::Get().ProcessMessages();
5049 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5051 // check how far we are through playing the current item
5052 // and do anything that needs doing (playcount updates etc)
5053 CheckPlayingProgress();
5056 m_pPlayer->DoAudioWork();
5058 // do any processing that isn't needed on each run
5059 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5061 m_slowTimer.Reset();
5065 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5068 // We get called every 500ms
5069 void CApplication::ProcessSlow()
5071 g_powerManager.ProcessEvents();
5073 #if defined(TARGET_DARWIN_OSX)
5074 // There is an issue on OS X that several system services ask the cursor to become visible
5075 // during their startup routines. Given that we can't control this, we hack it in by
5077 if (g_Windowing.IsFullScreen())
5078 { // SDL thinks it's hidden
5083 // Temporarely pause pausable jobs when viewing video/picture
5084 int currentWindow = g_windowManager.GetActiveWindow();
5085 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5087 CJobManager::GetInstance().PauseJobs();
5091 CJobManager::GetInstance().UnPauseJobs();
5094 // Store our file state for use on close()
5097 // Check if we need to activate the screensaver / DPMS.
5098 CheckScreenSaverAndDPMS();
5100 // Check if we need to shutdown (if enabled).
5101 #if defined(TARGET_DARWIN)
5102 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5104 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5110 // check if we should restart the player
5111 CheckDelayedPlayerRestart();
5113 // check if we can unload any unreferenced dlls or sections
5114 if (!m_pPlayer->IsPlayingVideo())
5115 CSectionLoader::UnloadDelayed();
5117 // check for any idle curl connections
5118 g_curlInterface.CheckIdle();
5120 // check for any idle myth sessions
5121 CMythSession::CheckIdle();
5123 #ifdef HAS_FILESYSTEM_HTSP
5124 // check for any idle htsp sessions
5125 HTSP::CHTSPDirectorySession::CheckIdle();
5129 if ( m_pKaraokeMgr )
5130 m_pKaraokeMgr->ProcessSlow();
5133 if (!m_pPlayer->IsPlayingVideo())
5134 g_largeTextureManager.CleanupUnusedImages();
5136 g_TextureManager.FreeUnusedTextures(5000);
5138 #ifdef HAS_DVD_DRIVE
5139 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5140 if (!m_pPlayer->IsPlayingVideo())
5141 m_Autorun->HandleAutorun();
5144 // update upnp server/renderer states
5146 if(UPNP::CUPnP::IsInstantiated())
5147 UPNP::CUPnP::GetInstance()->UpdateState();
5150 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5154 #ifdef HAS_FILESYSTEM_NFS
5155 gNfsConnection.CheckIfIdle();
5158 #ifdef HAS_FILESYSTEM_AFP
5159 gAfpConnection.CheckIfIdle();
5162 #ifdef HAS_FILESYSTEM_SFTP
5163 CSFTPSessionManager::ClearOutIdleSessions();
5166 g_mediaManager.ProcessEvents();
5169 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5170 g_RemoteControl.Initialize();
5173 if (!m_pPlayer->IsPlayingVideo())
5174 CAddonInstaller::Get().UpdateRepos();
5176 CAEFactory::GarbageCollect();
5178 // if we don't render the gui there's no reason to start the screensaver.
5179 // that way the screensaver won't kick in if we maximize the XBMC window
5180 // after the screensaver start time.
5182 ResetScreenSaverTimer();
5185 // Global Idle Time in Seconds
5186 // idle time will be resetet if on any OnKey()
5187 // int return: system Idle time in seconds! 0 is no idle!
5188 int CApplication::GlobalIdleTime()
5190 if(!m_idleTimer.IsRunning())
5193 m_idleTimer.StartZero();
5195 return (int)m_idleTimer.GetElapsedSeconds();
5198 float CApplication::NavigationIdleTime()
5200 if (!m_navigationTimer.IsRunning())
5202 m_navigationTimer.Stop();
5203 m_navigationTimer.StartZero();
5205 return m_navigationTimer.GetElapsedSeconds();
5208 void CApplication::DelayedPlayerRestart()
5210 m_restartPlayerTimer.StartZero();
5213 void CApplication::CheckDelayedPlayerRestart()
5215 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5217 m_restartPlayerTimer.Stop();
5218 m_restartPlayerTimer.Reset();
5223 void CApplication::Restart(bool bSamePosition)
5225 // this function gets called when the user changes a setting (like noninterleaved)
5226 // and which means we gotta close & reopen the current playing file
5228 // first check if we're playing a file
5229 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5232 if( !m_pPlayer->HasPlayer() )
5237 // do we want to return to the current position in the file
5238 if (false == bSamePosition)
5240 // no, then just reopen the file and start at the beginning
5241 PlayFile(*m_itemCurrentFile, true);
5245 // else get current position
5246 double time = GetTime();
5248 // get player state, needed for dvd's
5249 CStdString state = m_pPlayer->GetPlayerState();
5251 // set the requested starttime
5252 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5255 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5256 m_pPlayer->SetPlayerState(state);
5259 const CStdString& CApplication::CurrentFile()
5261 return m_itemCurrentFile->GetPath();
5264 CFileItem& CApplication::CurrentFileItem()
5266 return *m_itemCurrentFile;
5269 CFileItem& CApplication::CurrentUnstackedItem()
5271 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5272 return *(*m_currentStack)[m_currentStackPosition];
5274 return *m_itemCurrentFile;
5277 void CApplication::ShowVolumeBar(const CAction *action)
5279 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5284 volumeBar->OnAction(*action);
5288 bool CApplication::IsMuted() const
5290 if (g_peripherals.IsMuted())
5292 return CAEFactory::IsMuted();
5295 void CApplication::ToggleMute(void)
5303 void CApplication::SetMute(bool mute)
5305 if (m_muted != mute)
5312 void CApplication::Mute()
5314 if (g_peripherals.Mute())
5317 CAEFactory::SetMute(true);
5322 void CApplication::UnMute()
5324 if (g_peripherals.UnMute())
5327 CAEFactory::SetMute(false);
5332 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5334 float hardwareVolume = iValue;
5337 hardwareVolume /= 100.0f;
5339 SetHardwareVolume(hardwareVolume);
5343 void CApplication::SetHardwareVolume(float hardwareVolume)
5345 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5346 m_volumeLevel = hardwareVolume;
5348 CAEFactory::SetVolume(hardwareVolume);
5351 float CApplication::GetVolume(bool percentage /* = true */) const
5355 // converts the hardware volume to a percentage
5356 return m_volumeLevel * 100.0f;
5359 return m_volumeLevel;
5362 void CApplication::VolumeChanged() const
5364 CVariant data(CVariant::VariantTypeObject);
5365 data["volume"] = GetVolume();
5366 data["muted"] = m_muted;
5367 CAnnouncementManager::Get().Announce(Application, "xbmc", "OnVolumeChanged", data);
5369 // if player has volume control, set it.
5370 if (m_pPlayer->ControlsVolume())
5372 m_pPlayer->SetVolume(m_volumeLevel);
5373 m_pPlayer->SetMute(m_muted);
5377 int CApplication::GetSubtitleDelay() const
5379 // converts subtitle delay to a percentage
5380 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5383 int CApplication::GetAudioDelay() const
5385 // converts audio delay to a percentage
5386 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5389 // Returns the total time in seconds of the current media. Fractional
5390 // portions of a second are possible - but not necessarily supported by the
5391 // player class. This returns a double to be consistent with GetTime() and
5393 double CApplication::GetTotalTime() const
5397 if (m_pPlayer->IsPlaying())
5399 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5400 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5402 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5408 void CApplication::StopShutdownTimer()
5410 if (m_shutdownTimer.IsRunning())
5411 m_shutdownTimer.Stop();
5414 void CApplication::ResetShutdownTimers()
5416 // reset system shutdown timer
5417 m_shutdownTimer.StartZero();
5419 // delete custom shutdown timer
5420 if (g_alarmClock.HasAlarm("shutdowntimer"))
5421 g_alarmClock.Stop("shutdowntimer", true);
5424 // Returns the current time in seconds of the currently playing media.
5425 // Fractional portions of a second are possible. This returns a double to
5426 // be consistent with GetTotalTime() and SeekTime().
5427 double CApplication::GetTime() const
5431 if (m_pPlayer->IsPlaying())
5433 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5435 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5436 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5439 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5445 // Sets the current position of the currently playing media to the specified
5446 // time in seconds. Fractional portions of a second are valid. The passed
5447 // time is the time offset from the beginning of the file as opposed to a
5448 // delta from the current position. This method accepts a double to be
5449 // consistent with GetTime() and GetTotalTime().
5450 void CApplication::SeekTime( double dTime )
5452 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5454 if (!m_pPlayer->CanSeek()) return;
5455 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5457 // find the item in the stack we are seeking to, and load the new
5458 // file if necessary, and calculate the correct seek within the new
5459 // file. Otherwise, just fall through to the usual routine if the
5460 // time is higher than our total time.
5461 for (int i = 0; i < m_currentStack->Size(); i++)
5463 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5465 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5466 if (m_currentStackPosition == i)
5467 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5469 { // seeking to a new file
5470 m_currentStackPosition = i;
5471 CFileItem item(*(*m_currentStack)[i]);
5472 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5473 // don't just call "PlayFile" here, as we are quite likely called from the
5474 // player thread, so we won't be able to delete ourselves.
5475 CApplicationMessenger::Get().PlayFile(item, true);
5481 // convert to milliseconds and perform seek
5482 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5486 float CApplication::GetPercentage() const
5488 if (m_pPlayer->IsPlaying())
5490 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5492 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5493 if (tag.GetDuration() > 0)
5494 return (float)(GetTime() / tag.GetDuration() * 100);
5497 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5499 double totalTime = GetTotalTime();
5500 if (totalTime > 0.0f)
5501 return (float)(GetTime() / totalTime * 100);
5504 return m_pPlayer->GetPercentage();
5509 float CApplication::GetCachePercentage() const
5511 if (m_pPlayer->IsPlaying())
5513 // Note that the player returns a relative cache percentage and we want an absolute percentage
5514 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5516 float stackedTotalTime = (float) GetTotalTime();
5517 // We need to take into account the stack's total time vs. currently playing file's total time
5518 if (stackedTotalTime > 0.0f)
5519 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5522 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5527 void CApplication::SeekPercentage(float percent)
5529 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5531 if (!m_pPlayer->CanSeek()) return;
5532 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5533 SeekTime(percent * 0.01 * GetTotalTime());
5535 m_pPlayer->SeekPercentage(percent);
5539 // SwitchToFullScreen() returns true if a switch is made, else returns false
5540 bool CApplication::SwitchToFullScreen()
5542 // if playing from the video info window, close it first!
5543 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5545 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5546 if (pDialog) pDialog->Close(true);
5549 // don't switch if there is a dialog on screen or the slideshow is active
5550 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5553 // See if we're playing a video, and are in GUI mode
5554 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5556 // then switch to fullscreen mode
5557 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5560 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5561 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5562 { // then switch to visualisation
5563 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5569 void CApplication::Minimize()
5571 g_Windowing.Minimize();
5574 PLAYERCOREID CApplication::GetCurrentPlayer()
5576 return m_pPlayer->GetCurrentPlayer();
5579 void CApplication::UpdateLibraries()
5581 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5583 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5587 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5589 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5594 bool CApplication::IsVideoScanning() const
5596 return m_videoInfoScanner->IsScanning();
5599 bool CApplication::IsMusicScanning() const
5601 return m_musicInfoScanner->IsScanning();
5604 void CApplication::StopVideoScan()
5606 if (m_videoInfoScanner->IsScanning())
5607 m_videoInfoScanner->Stop();
5610 void CApplication::StopMusicScan()
5612 if (m_musicInfoScanner->IsScanning())
5613 m_musicInfoScanner->Stop();
5616 void CApplication::StartVideoCleanup()
5618 if (m_videoInfoScanner->IsScanning())
5621 m_videoInfoScanner->CleanDatabase();
5624 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5626 if (m_videoInfoScanner->IsScanning())
5629 m_videoInfoScanner->ShowDialog(true);
5631 m_videoInfoScanner->Start(strDirectory,scanAll);
5634 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5636 if (m_musicInfoScanner->IsScanning())
5640 { // setup default flags
5641 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5642 flags |= CMusicInfoScanner::SCAN_ONLINE;
5643 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5644 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5647 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5648 m_musicInfoScanner->ShowDialog(true);
5650 m_musicInfoScanner->Start(strDirectory, flags);
5653 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5656 if (m_musicInfoScanner->IsScanning())
5659 m_musicInfoScanner->ShowDialog(true);
5661 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5664 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5667 if (m_musicInfoScanner->IsScanning())
5670 m_musicInfoScanner->ShowDialog(true);
5672 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5675 void CApplication::CheckPlayingProgress()
5677 // check if we haven't rewound past the start of the file
5678 if (m_pPlayer->IsPlaying())
5680 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5690 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5692 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5693 g_application.SeekTime(0);
5699 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5701 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5703 // initial exit conditions
5704 // no songs in playlist just return
5705 if (playlist.size() == 0)
5709 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5712 // setup correct playlist
5713 g_playlistPlayer.ClearPlaylist(iPlaylist);
5715 // if the playlist contains an internet stream, this file will be used
5716 // to generate a thumbnail for musicplayer.cover
5717 g_application.m_strPlayListFile = strPlayList;
5719 // add the items to the playlist player
5720 g_playlistPlayer.Add(iPlaylist, playlist);
5722 // if we have a playlist
5723 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5726 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5727 g_playlistPlayer.Reset();
5728 g_playlistPlayer.Play(track);
5734 void CApplication::SaveCurrentFileSettings()
5736 // don't store settings for PVR in video database
5737 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5739 // save video settings
5740 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5744 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5748 else if (m_itemCurrentFile->IsPVRChannel())
5750 g_PVRManager.SaveCurrentChannelSettings();
5754 bool CApplication::AlwaysProcess(const CAction& action)
5756 // check if this button is mapped to a built-in function
5757 if (!action.GetName().empty())
5759 CStdString builtInFunction;
5760 vector<CStdString> params;
5761 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5762 StringUtils::ToLower(builtInFunction);
5764 // should this button be handled normally or just cancel the screensaver?
5765 if ( builtInFunction.Equals("powerdown")
5766 || builtInFunction.Equals("reboot")
5767 || builtInFunction.Equals("restart")
5768 || builtInFunction.Equals("restartapp")
5769 || builtInFunction.Equals("suspend")
5770 || builtInFunction.Equals("hibernate")
5771 || builtInFunction.Equals("quit")
5772 || builtInFunction.Equals("shutdown"))
5781 bool CApplication::IsCurrentThread() const
5783 return CThread::IsCurrentThread(m_threadID);
5786 void CApplication::SetRenderGUI(bool renderGUI)
5788 if (renderGUI && ! m_renderGUI)
5789 g_windowManager.MarkDirty();
5790 m_renderGUI = renderGUI;
5793 CNetwork& CApplication::getNetwork()
5797 #ifdef HAS_PERFORMANCE_SAMPLE
5798 CPerformanceStats &CApplication::GetPerformanceStats()
5804 bool CApplication::SetLanguage(const CStdString &strLanguage)
5806 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5807 if (strLanguage != strPreviousLanguage)
5809 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
5810 if (!g_langInfo.Load(strLangInfoPath))
5813 CSettings::Get().SetString("locale.language", strLanguage);
5815 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
5818 // also tell our weather and skin to reload as these are localized
5819 g_weatherManager.Refresh();
5820 g_PVRManager.LocalizationChanged();
5827 void CApplication::CloseNetworkShares()
5829 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5831 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5835 #ifdef HAS_FILESYSTEM_NFS
5836 gNfsConnection.Deinit();
5839 #ifdef HAS_FILESYSTEM_AFP
5840 gAfpConnection.Deinit();
5843 #ifdef HAS_FILESYSTEM_SFTP
5844 CSFTPSessionManager::DisconnectAllSessions();