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/GUIWindowPVRChannels.h"
256 #include "pvr/windows/GUIWindowPVRRecordings.h"
257 #include "pvr/windows/GUIWindowPVRGuide.h"
258 #include "pvr/windows/GUIWindowPVRTimers.h"
259 #include "pvr/windows/GUIWindowPVRSearch.h"
260 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
261 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
262 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
263 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
264 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
265 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
266 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
267 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
268 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
269 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
271 #include "epg/EpgContainer.h"
273 #include "video/dialogs/GUIDialogFullScreenInfo.h"
274 #include "video/dialogs/GUIDialogTeletext.h"
275 #include "dialogs/GUIDialogSlider.h"
276 #include "guilib/GUIControlFactory.h"
277 #include "dialogs/GUIDialogCache.h"
278 #include "dialogs/GUIDialogPlayEject.h"
279 #include "dialogs/GUIDialogMediaFilter.h"
280 #include "video/dialogs/GUIDialogSubtitles.h"
281 #include "utils/XMLUtils.h"
282 #include "addons/AddonInstaller.h"
284 #ifdef HAS_PERFORMANCE_SAMPLE
285 #include "utils/PerformanceSample.h"
287 #define MEASURE_FUNCTION
290 #ifdef TARGET_WINDOWS
292 #include "win32util.h"
295 #include "windowing/X11/XRandR.h"
298 #ifdef TARGET_DARWIN_OSX
299 #include "osx/CocoaInterface.h"
300 #include "osx/XBMCHelper.h"
303 #include "osx/DarwinUtils.h"
308 #include <cdio/logging.h>
312 #include "linux/HALManager.h"
315 #include "storage/MediaManager.h"
316 #include "utils/JobManager.h"
317 #include "utils/SaveFileStateJob.h"
318 #include "utils/AlarmClock.h"
319 #include "utils/RssReader.h"
320 #include "utils/StringUtils.h"
321 #include "utils/Weather.h"
322 #include "DatabaseManager.h"
329 #include "input/linux/LIRC.h"
331 #ifdef HAS_IRSERVERSUITE
332 #include "input/windows/IRServerSuite.h"
335 #if defined(TARGET_WINDOWS)
336 #include "input/windows/WINJoystick.h"
337 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
338 #include "input/SDLJoystick.h"
341 #if defined(TARGET_ANDROID)
342 #include "android/activity/XBMCApp.h"
343 #include "android/activity/AndroidFeatures.h"
344 #include "android/jni/Build.h"
347 #ifdef TARGET_WINDOWS
348 #include "utils/Environment.h"
351 #if defined(HAS_LIBAMCODEC)
352 #include "utils/AMLUtils.h"
355 #include "cores/FFmpeg.h"
358 using namespace ADDON;
359 using namespace XFILE;
361 using namespace MEDIA_DETECT;
363 using namespace PLAYLIST;
364 using namespace VIDEO;
365 using namespace MUSIC_INFO;
366 #ifdef HAS_EVENT_SERVER
367 using namespace EVENTSERVER;
370 using namespace JSONRPC;
372 using namespace ANNOUNCEMENT;
375 using namespace PERIPHERALS;
377 using namespace XbmcThreads;
379 // uncomment this if you want to use release libs in the debug build.
380 // Atm this saves you 7 mb of memory
381 #define USE_RELEASE_LIBS
383 #define MAX_FFWD_SPEED 5
385 //extern IDirectSoundRenderer* m_pAudioDecoder;
386 CApplication::CApplication(void)
387 : m_pPlayer(new CApplicationPlayer)
388 , m_itemCurrentFile(new CFileItem)
389 , m_stackFileItemToUpdate(new CFileItem)
390 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
391 , m_progressTrackingItem(new CFileItem)
392 , m_videoInfoScanner(new CVideoInfoScanner)
393 , m_musicInfoScanner(new CMusicInfoScanner)
394 , m_seekHandler(new CSeekHandler)
395 , m_playerController(new CPlayerController)
398 TiXmlBase::SetCondenseWhiteSpace(false);
399 m_bInhibitIdleShutdown = false;
400 m_bScreenSave = false;
402 m_dpmsIsActive = false;
403 m_dpmsIsManual = false;
404 m_iScreenSaveLock = 0;
405 m_bInitializing = true;
406 m_eForcedNextPlayer = EPC_NONE;
407 m_strPlayListFile = "";
408 m_nextPlaylistItem = -1;
409 m_bPlaybackStarting = false;
410 m_ePlayState = PLAY_STATE_NONE;
411 m_skinReverting = false;
419 /* for now always keep this around */
421 m_pKaraokeMgr = new CKaraokeLyricsManager();
423 m_currentStack = new CFileItemList;
425 m_bPresentFrame = false;
426 m_bPlatformDirectories = true;
428 m_bStandalone = false;
429 m_bEnableLegacyRes = false;
430 m_bSystemScreenSaverEnable = false;
431 m_pInertialScrollingHandler = new CInertialScrollingHandler();
433 m_Autorun = new CAutorun();
438 m_progressTrackingPlayCountUpdate = false;
439 m_currentStackPosition = 0;
441 m_lastRenderTime = 0;
445 m_volumeLevel = 1.0f;
448 CApplication::~CApplication(void)
450 delete m_musicInfoScanner;
451 delete m_videoInfoScanner;
452 delete &m_progressTrackingVideoResumeBookmark;
456 delete m_currentStack;
459 delete m_pKaraokeMgr;
463 delete m_seekHandler;
464 delete m_playerController;
465 delete m_pInertialScrollingHandler;
469 bool CApplication::OnEvent(XBMC_Event& newEvent)
471 switch(newEvent.type)
474 if (!g_application.m_bStop)
475 CApplicationMessenger::Get().Quit();
478 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
481 g_Keyboard.ProcessKeyUp();
483 case XBMC_MOUSEBUTTONDOWN:
484 case XBMC_MOUSEBUTTONUP:
485 case XBMC_MOUSEMOTION:
486 g_Mouse.HandleEvent(newEvent);
487 g_application.ProcessMouse();
489 case XBMC_VIDEORESIZE:
490 if (!g_application.m_bInitializing &&
491 !g_advancedSettings.m_fullScreen)
493 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
494 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
495 CSettings::Get().SetInt("window.width", newEvent.resize.w);
496 CSettings::Get().SetInt("window.height", newEvent.resize.h);
497 CSettings::Get().Save();
501 #ifdef TARGET_WINDOWS
502 if (g_advancedSettings.m_fullScreen)
504 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
505 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
506 if (newRes != g_graphicsContext.GetVideoResolution())
507 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
512 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
516 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
518 case XBMC_APPCOMMAND:
519 return g_application.OnAppCommand(newEvent.appcommand.action);
522 if (newEvent.touch.action == ACTION_TOUCH_TAP)
523 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
524 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
527 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
528 actionId = newEvent.touch.action;
531 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
532 // change this if we have a dialog up
533 if (g_windowManager.HasModalDialog())
535 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
537 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
538 { // fullscreen info dialog - special case
539 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
541 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
545 if (iWin == WINDOW_FULLSCREEN_VIDEO)
547 // current active window is full screen video.
548 if (g_application.m_pPlayer->IsInMenu())
550 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
551 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_VIDEO_MENU, newEvent.touch.action, newEvent.touch.pointers, actionId);
553 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
555 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
556 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
558 // if no PVR specific action/mapping is found, fall back to default
560 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
564 // in any other case use the fullscreen window section of keymap.xml to map key->action
565 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
568 else // iWin != WINDOW_FULLSCREEN_VIDEO
569 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
576 if ((actionId >= ACTION_TOUCH_TAP && actionId <= ACTION_GESTURE_END)
577 || (actionId >= ACTION_MOUSE_START && actionId <= ACTION_MOUSE_END) )
578 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
580 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
582 // Post an unfocus message for touch device after the action.
583 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
585 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
586 CApplicationMessenger::Get().SendGUIMessage(msg);
591 // Reset the screensaver
592 g_application.ResetScreenSaver();
593 g_application.WakeUpScreenSaverAndDPMS();
594 // Send a mouse motion event with no dx,dy for getting the current guiitem selected
595 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, static_cast<float>(newEvent.focus.x), static_cast<float>(newEvent.focus.y), 0, 0));
601 extern "C" void __stdcall init_emu_environ();
602 extern "C" void __stdcall update_emu_environ();
603 extern "C" void __stdcall cleanup_emu_environ();
606 // Utility function used to copy files from the application bundle
607 // over to the user data directory in Application Support/XBMC.
609 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
611 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
612 if (!CFile::Exists(destPath))
614 // need to copy it across
615 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
616 CFile::Copy(srcPath, destPath);
620 void CApplication::Preflight()
623 // call 'dbus_threads_init_default' before any other dbus calls in order to
624 // avoid race conditions with other threads using dbus connections
625 dbus_threads_init_default();
628 // run any platform preflight scripts.
629 #if defined(TARGET_DARWIN_OSX)
630 CStdString install_path;
632 CUtil::GetHomePath(install_path);
633 setenv("XBMC_HOME", install_path.c_str(), 0);
634 install_path += "/tools/darwin/runtime/preflight";
635 system(install_path.c_str());
639 bool CApplication::Create()
641 #if defined(HAS_LINUX_NETWORK)
642 m_network = new CNetworkLinux();
643 #elif defined(HAS_WIN32_NETWORK)
644 m_network = new CNetworkWin32();
646 m_network = new CNetwork();
651 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
653 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
654 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
658 tzset(); // Initialize timezone information variables
661 // Grab a handle to our thread to be used later in identifying the render thread.
662 m_threadID = CThread::GetCurrentThreadId();
665 //floating point precision to 24 bits (faster performance)
666 _controlfp(_PC_24, _MCW_PC);
668 /* install win32 exception translator, win32 exceptions
669 * can now be caught using c++ try catch */
670 win32_exception::install_handler();
674 // only the InitDirectories* for the current platform should return true
675 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
676 bool inited = InitDirectoriesLinux();
678 inited = InitDirectoriesOSX();
680 inited = InitDirectoriesWin32();
682 // copy required files
683 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
684 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
685 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
687 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
689 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
690 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
694 // Init our DllLoaders emu env
697 CProfilesManager::Get().Load();
699 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
700 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(),
701 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness());
703 std::string buildType;
706 #elif defined(NDEBUG)
707 buildType = "Release";
709 buildType = "Unknown";
711 std::string specialVersion;
712 #if defined(TARGET_DARWIN_IOS_ATV2)
713 specialVersion = " (version for AppleTV2)";
714 #elif defined(TARGET_RASPBERRY_PI)
715 specialVersion = " (version for Raspberry Pi)";
716 //#elif defined(some_ID) // uncomment for special version/fork
717 // specialVersion = " (version for XXXX)";
719 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build%s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), specialVersion.c_str());
720 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(),
721 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersionDecoded().c_str(),
722 g_sysinfo.GetBuildTargetPlatformVersion().c_str());
724 std::string deviceModel(g_sysinfo.GetModelName());
725 if (!g_sysinfo.GetManufacturerName().empty())
726 deviceModel = g_sysinfo.GetManufacturerName() + " " + (deviceModel.empty() ? std::string("device") : deviceModel);
727 if (!deviceModel.empty())
728 CLog::Log(LOGNOTICE, "Running on %s with %s, kernel: %s %s %d-bit version %s", deviceModel.c_str(), g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
729 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
731 CLog::Log(LOGNOTICE, "Running on %s, kernel: %s %s %d-bit version %s", g_sysinfo.GetOsPrettyNameWithVersion().c_str(),
732 g_sysinfo.GetKernelName().c_str(), g_sysinfo.GetKernelCpuFamily().c_str(), g_sysinfo.GetKernelBitness(), g_sysinfo.GetKernelVersionFull().c_str());
734 #if defined(TARGET_LINUX)
735 #if USE_STATIC_FFMPEG
736 CLog::Log(LOGNOTICE, "FFmpeg statically linked, version: %s", FFMPEG_VERSION);
737 #else // !USE_STATIC_FFMPEG
738 CLog::Log(LOGNOTICE, "FFmpeg version: %s", FFMPEG_VERSION);
739 #endif // !USE_STATIC_FFMPEG
740 if (!strstr(FFMPEG_VERSION, FFMPEG_VER_SHA))
742 if (strstr(FFMPEG_VERSION, "xbmc"))
743 CLog::Log(LOGNOTICE, "WARNING: unknown ffmpeg-xbmc version detected");
745 CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected");
749 std::string cpuModel(g_cpuInfo.getCPUModel());
750 if (!cpuModel.empty())
751 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
753 CLog::Log(LOGNOTICE, "%d CPU core%s available", g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
754 #if defined(TARGET_WINDOWS)
755 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
756 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
757 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
759 #if defined(TARGET_ANDROID)
761 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
762 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
763 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
767 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
768 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
770 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
772 CSpecialProtocol::LogPaths();
774 CStdString executable = CUtil::ResolveExecutablePath();
775 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
776 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
777 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
778 CRegExp::LogCheckUtf8Support();
779 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
781 CStdString strExecutablePath;
782 CUtil::GetHomePath(strExecutablePath);
785 g_xrandr.LoadCustomModeLinesToAllOutputs();
788 // for python scripts that check the OS
789 #if defined(TARGET_DARWIN)
790 setenv("OS","OS X",true);
791 #elif defined(TARGET_POSIX)
792 setenv("OS","Linux",true);
793 #elif defined(TARGET_WINDOWS)
794 CEnvironment::setenv("OS", "win32");
797 // register ffmpeg lockmanager callback
798 av_lockmgr_register(&ffmpeg_lockmgr_cb);
800 avcodec_register_all();
804 avfilter_register_all();
805 // set avutil callback
806 av_log_set_callback(ff_avutil_log);
808 g_powerManager.Initialize();
810 // Load the AudioEngine before settings as they need to query the engine
811 if (!CAEFactory::LoadEngine())
813 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
817 // Initialize default Settings - don't move
818 CLog::Log(LOGNOTICE, "load settings...");
819 if (!CSettings::Get().Initialize())
822 g_powerManager.SetDefaults();
824 // load the actual values
825 if (!CSettings::Get().Load())
827 CLog::Log(LOGFATAL, "unable to load settings");
830 CSettings::Get().SetLoaded();
832 CLog::Log(LOGINFO, "creating subdirectories");
833 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
834 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
835 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
836 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
837 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
838 CProfilesManager::Get().CreateProfileFolders();
840 update_emu_environ();//apply the GUI settings
842 // Load the langinfo to have user charset <-> utf-8 conversion
843 CStdString strLanguage = CSettings::Get().GetString("locale.language");
844 strLanguage[0] = toupper(strLanguage[0]);
846 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
848 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
849 g_langInfo.Load(strLangInfoPath);
850 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
851 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
853 CStdString strLanguagePath = "special://xbmc/language/";
855 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
856 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
858 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
862 // start the AudioEngine
863 if (!CAEFactory::StartEngine())
865 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
869 // restore AE's previous volume state
870 SetHardwareVolume(m_volumeLevel);
871 CAEFactory::SetMute (m_muted);
872 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
874 // initialize m_replayGainSettings
875 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
876 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
877 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
878 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
880 // initialize the addon database (must be before the addon manager is init'd)
881 CDatabaseManager::Get().Initialize(true);
884 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
887 // start-up Addons Framework
888 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
889 if (!CAddonMgr::Get().Init())
891 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
894 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
895 g_RemoteControl.Initialize();
898 g_peripherals.Initialise();
900 // Create the Mouse, Keyboard, Remote, and Joystick devices
901 // Initialize after loading settings to get joystick deadzone setting
902 g_Mouse.Initialize();
903 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
905 g_Keyboard.Initialize();
907 #if defined(TARGET_DARWIN_OSX)
908 // Configure and possible manually start the helper.
909 XBMCHelper::GetInstance().Configure();
912 CUtil::InitRandomSeed();
914 g_mediaManager.Initialize();
916 m_lastFrameTime = XbmcThreads::SystemClockMillis();
917 m_lastRenderTime = m_lastFrameTime;
921 bool CApplication::CreateGUI()
925 CLog::Log(LOGNOTICE, "Setup SDL");
927 /* Clean up on exit, exit on window close and interrupt */
930 uint32_t sdlFlags = 0;
932 #if (defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)) && !defined(HAS_GLX)
933 sdlFlags |= SDL_INIT_VIDEO;
936 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
937 sdlFlags |= SDL_INIT_JOYSTICK;
940 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
941 //this might bring the monitor out of standby, so we have to disable it explicitly
942 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
943 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
944 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
950 // for nvidia cards - vsync currently ALWAYS enabled.
951 // the reason is that after screen has been setup changing this env var will make no difference.
952 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
953 setenv("__GL_YIELD", "USLEEP", 0);
956 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
957 g_Windowing.EnableSystemScreenSaver(false);
960 if (SDL_Init(sdlFlags) != 0)
962 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
965 #if defined(TARGET_DARWIN)
966 // SDL_Init will install a handler for segfaults, restore the default handler.
967 signal(SIGSEGV, SIG_DFL);
971 // Initialize core peripheral port support. Note: If these parameters
972 // are 0 and NULL, respectively, then the default number and types of
973 // controllers will be initialized.
974 if (!g_Windowing.InitWindowSystem())
976 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
980 // Retrieve the matching resolution based on GUI settings
981 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
982 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
983 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
985 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
986 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
989 // update the window resolution
990 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
992 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
993 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
995 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
997 // Oh uh - doesn't look good for starting in their wanted screenmode
998 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
999 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
1006 if (g_advancedSettings.m_splashImage)
1008 CStdString strUserSplash = "special://home/media/Splash.png";
1009 if (CFile::Exists(strUserSplash))
1011 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
1012 m_splash = new CSplash(strUserSplash);
1016 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1017 m_splash = new CSplash("special://xbmc/media/Splash.png");
1022 // The key mappings may already have been loaded by a peripheral
1023 CLog::Log(LOGINFO, "load keymapping");
1024 if (!CButtonTranslator::GetInstance().Load())
1027 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1028 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1031 info.strMode.c_str());
1032 g_windowManager.Initialize();
1037 bool CApplication::InitWindow()
1039 #ifdef TARGET_DARWIN_OSX
1040 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1041 // fixes the white screen of death if starting fullscreen and switching to windowed.
1042 bool bFullScreen = false;
1043 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1045 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1049 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1050 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1052 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1057 if (!g_Windowing.InitRenderSystem())
1059 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1062 // set GUI res and force the clear of the screen
1063 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1067 bool CApplication::DestroyWindow()
1069 return g_Windowing.DestroyWindow();
1072 bool CApplication::InitDirectoriesLinux()
1075 The following is the directory mapping for Platform Specific Mode:
1077 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1078 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1079 installations like skins, screensavers, etc.
1081 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1082 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1083 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1084 special://profile/ => [read-write] current profile's userdata directory.
1085 Generally special://masterprofile for the master profile or
1086 special://masterprofile/profiles/<profile_name> for other profiles.
1088 NOTE: All these root directories are lowercase. Some of the sub-directories
1089 might be mixed case.
1092 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1093 CStdString userName;
1095 userName = getenv("USER");
1099 CStdString userHome;
1101 userHome = getenv("HOME");
1105 CStdString xbmcBinPath, xbmcPath;
1106 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1107 xbmcPath = getenv("XBMC_HOME");
1109 if (xbmcPath.empty())
1111 xbmcPath = xbmcBinPath;
1112 /* Check if xbmc binaries and arch independent data files are being kept in
1113 * separate locations. */
1114 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1116 /* Attempt to locate arch independent data files. */
1117 CUtil::GetHomePath(xbmcPath);
1118 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1120 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1126 /* Set some environment variables */
1127 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1128 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1130 if (m_bPlatformDirectories)
1132 // map our special drives
1133 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1134 CSpecialProtocol::SetXBMCPath(xbmcPath);
1135 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1136 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1138 CStdString strTempPath = userHome;
1139 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1140 if (getenv("XBMC_TEMP"))
1141 strTempPath = getenv("XBMC_TEMP");
1142 CSpecialProtocol::SetTempPath(strTempPath);
1144 URIUtils::AddSlashAtEnd(strTempPath);
1145 g_advancedSettings.m_logFolder = strTempPath;
1152 URIUtils::AddSlashAtEnd(xbmcPath);
1153 g_advancedSettings.m_logFolder = xbmcPath;
1155 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1156 CSpecialProtocol::SetXBMCPath(xbmcPath);
1157 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1158 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1160 CStdString strTempPath = xbmcPath;
1161 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1162 if (getenv("XBMC_TEMP"))
1163 strTempPath = getenv("XBMC_TEMP");
1164 CSpecialProtocol::SetTempPath(strTempPath);
1167 URIUtils::AddSlashAtEnd(strTempPath);
1168 g_advancedSettings.m_logFolder = strTempPath;
1177 bool CApplication::InitDirectoriesOSX()
1179 #if defined(TARGET_DARWIN)
1180 CStdString userName;
1182 userName = getenv("USER");
1186 CStdString userHome;
1188 userHome = getenv("HOME");
1192 CStdString xbmcPath;
1193 CUtil::GetHomePath(xbmcPath);
1194 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1196 #if defined(TARGET_DARWIN_IOS)
1197 CStdString fontconfigPath;
1198 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1199 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1202 // setup path to our internal dylibs so loader can find them
1203 CStdString frameworksPath = CUtil::GetFrameworksPath();
1204 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1206 // OSX always runs with m_bPlatformDirectories == true
1207 if (m_bPlatformDirectories)
1209 // map our special drives
1210 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1211 CSpecialProtocol::SetXBMCPath(xbmcPath);
1212 #if defined(TARGET_DARWIN_IOS)
1213 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1214 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1216 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1217 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1220 // location for temp files
1221 #if defined(TARGET_DARWIN_IOS)
1222 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1224 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1225 CDirectory::Create(strTempPath);
1226 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1228 CSpecialProtocol::SetTempPath(strTempPath);
1230 // xbmc.log file location
1231 #if defined(TARGET_DARWIN_IOS)
1232 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1234 strTempPath = userHome + "/Library/Logs";
1236 URIUtils::AddSlashAtEnd(strTempPath);
1237 g_advancedSettings.m_logFolder = strTempPath;
1243 URIUtils::AddSlashAtEnd(xbmcPath);
1244 g_advancedSettings.m_logFolder = xbmcPath;
1246 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1247 CSpecialProtocol::SetXBMCPath(xbmcPath);
1248 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1249 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1251 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1252 CSpecialProtocol::SetTempPath(strTempPath);
1254 URIUtils::AddSlashAtEnd(strTempPath);
1255 g_advancedSettings.m_logFolder = strTempPath;
1264 bool CApplication::InitDirectoriesWin32()
1266 #ifdef TARGET_WINDOWS
1267 CStdString xbmcPath;
1269 CUtil::GetHomePath(xbmcPath);
1270 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1271 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1272 CSpecialProtocol::SetXBMCPath(xbmcPath);
1274 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1276 g_advancedSettings.m_logFolder = strWin32UserFolder;
1277 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1278 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1279 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1281 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1285 // Expand the DLL search path with our directories
1286 CWIN32Util::ExtendDllPath();
1294 void CApplication::CreateUserDirs()
1296 CDirectory::Create("special://home/");
1297 CDirectory::Create("special://home/addons");
1298 CDirectory::Create("special://home/addons/packages");
1299 CDirectory::Create("special://home/media");
1300 CDirectory::Create("special://home/sounds");
1301 CDirectory::Create("special://home/system");
1302 CDirectory::Create("special://masterprofile/");
1303 CDirectory::Create("special://temp/");
1304 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1307 bool CApplication::Initialize()
1309 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1310 // turn off cdio logging
1311 cdio_loglevel_default = CDIO_LOG_ERROR;
1314 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1315 // must create these here. Ideally this should be using special://home/ and
1316 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1317 if (!m_bPlatformDirectories)
1320 CDirectory::Create("special://xbmc/language");
1321 CDirectory::Create("special://xbmc/addons");
1322 CDirectory::Create("special://xbmc/sounds");
1325 // Load curl so curl_global_init gets called before any service threads
1326 // are started. Unloading will have no effect as curl is never fully unloaded.
1327 // To quote man curl_global_init:
1328 // "This function is not thread safe. You must not call it when any other
1329 // thread in the program (i.e. a thread sharing the same memory) is running.
1330 // This doesn't just mean no other thread that is using libcurl. Because
1331 // curl_global_init() calls functions of other libraries that are similarly
1332 // thread unsafe, it could conflict with any other thread that
1333 // uses these other libraries."
1334 g_curlInterface.Load();
1335 g_curlInterface.Unload();
1337 // initialize (and update as needed) our databases
1338 CDatabaseManager::Get().Initialize();
1342 // Init DPMS, before creating the corresponding setting control.
1343 m_dpms = new DPMSSupport();
1344 if (g_windowManager.Initialized())
1346 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1348 g_windowManager.Add(new CGUIWindowHome);
1349 g_windowManager.Add(new CGUIWindowPrograms);
1350 g_windowManager.Add(new CGUIWindowPictures);
1351 g_windowManager.Add(new CGUIWindowFileManager);
1352 g_windowManager.Add(new CGUIWindowSettings);
1353 g_windowManager.Add(new CGUIWindowSystemInfo);
1355 g_windowManager.Add(new CGUIWindowTestPatternGL);
1358 g_windowManager.Add(new CGUIWindowTestPatternDX);
1360 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1361 g_windowManager.Add(new CGUIWindowSettingsCategory);
1362 g_windowManager.Add(new CGUIWindowVideoNav);
1363 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1364 g_windowManager.Add(new CGUIWindowLoginScreen);
1365 g_windowManager.Add(new CGUIWindowSettingsProfile);
1366 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1367 g_windowManager.Add(new CGUIWindowAddonBrowser);
1368 g_windowManager.Add(new CGUIWindowScreensaverDim);
1369 g_windowManager.Add(new CGUIWindowDebugInfo);
1370 g_windowManager.Add(new CGUIWindowPointer);
1371 g_windowManager.Add(new CGUIDialogYesNo);
1372 g_windowManager.Add(new CGUIDialogProgress);
1373 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1374 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1375 g_windowManager.Add(new CGUIDialogVolumeBar);
1376 g_windowManager.Add(new CGUIDialogSeekBar);
1377 g_windowManager.Add(new CGUIDialogSubMenu);
1378 g_windowManager.Add(new CGUIDialogContextMenu);
1379 g_windowManager.Add(new CGUIDialogKaiToast);
1380 g_windowManager.Add(new CGUIDialogNumeric);
1381 g_windowManager.Add(new CGUIDialogGamepad);
1382 g_windowManager.Add(new CGUIDialogButtonMenu);
1383 g_windowManager.Add(new CGUIDialogMuteBug);
1384 g_windowManager.Add(new CGUIDialogPlayerControls);
1386 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1387 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1389 g_windowManager.Add(new CGUIDialogSlider);
1390 g_windowManager.Add(new CGUIDialogMusicOSD);
1391 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1392 g_windowManager.Add(new CGUIDialogVideoSettings);
1393 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1394 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1395 // Don't add the filebrowser dialog - it's created and added when it's needed
1396 g_windowManager.Add(new CGUIDialogNetworkSetup);
1397 g_windowManager.Add(new CGUIDialogMediaSource);
1398 g_windowManager.Add(new CGUIDialogProfileSettings);
1399 g_windowManager.Add(new CGUIDialogFavourites);
1400 g_windowManager.Add(new CGUIDialogSongInfo);
1401 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1402 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1403 g_windowManager.Add(new CGUIDialogBusy);
1404 g_windowManager.Add(new CGUIDialogPictureInfo);
1405 g_windowManager.Add(new CGUIDialogAddonInfo);
1406 g_windowManager.Add(new CGUIDialogAddonSettings);
1407 #ifdef HAS_LINUX_NETWORK
1408 g_windowManager.Add(new CGUIDialogAccessPoints);
1411 g_windowManager.Add(new CGUIDialogLockSettings);
1413 g_windowManager.Add(new CGUIDialogContentSettings);
1415 g_windowManager.Add(new CGUIDialogPlayEject);
1417 g_windowManager.Add(new CGUIDialogPeripheralManager);
1418 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1420 g_windowManager.Add(new CGUIDialogMediaFilter);
1421 g_windowManager.Add(new CGUIDialogSubtitles);
1423 g_windowManager.Add(new CGUIWindowMusicPlayList);
1424 g_windowManager.Add(new CGUIWindowMusicSongs);
1425 g_windowManager.Add(new CGUIWindowMusicNav);
1426 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1428 /* Load PVR related Windows and Dialogs */
1429 g_windowManager.Add(new CGUIDialogTeletext);
1430 g_windowManager.Add(new CGUIWindowPVRChannels(false));
1431 g_windowManager.Add(new CGUIWindowPVRRecordings(false));
1432 g_windowManager.Add(new CGUIWindowPVRGuide(false));
1433 g_windowManager.Add(new CGUIWindowPVRTimers(false));
1434 g_windowManager.Add(new CGUIWindowPVRSearch(false));
1435 g_windowManager.Add(new CGUIWindowPVRChannels(true));
1436 g_windowManager.Add(new CGUIWindowPVRRecordings(true));
1437 g_windowManager.Add(new CGUIWindowPVRGuide(true));
1438 g_windowManager.Add(new CGUIWindowPVRTimers(true));
1439 g_windowManager.Add(new CGUIWindowPVRSearch(true));
1440 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1441 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1442 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1443 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1444 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1445 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1446 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1447 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1448 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1449 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1451 g_windowManager.Add(new CGUIDialogSelect);
1452 g_windowManager.Add(new CGUIDialogMusicInfo);
1453 g_windowManager.Add(new CGUIDialogOK);
1454 g_windowManager.Add(new CGUIDialogVideoInfo);
1455 g_windowManager.Add(new CGUIDialogTextViewer);
1456 g_windowManager.Add(new CGUIWindowFullScreen);
1457 g_windowManager.Add(new CGUIWindowVisualisation);
1458 g_windowManager.Add(new CGUIWindowSlideShow);
1459 g_windowManager.Add(new CGUIDialogFileStacking);
1461 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1464 g_windowManager.Add(new CGUIDialogVideoOSD);
1465 g_windowManager.Add(new CGUIDialogMusicOverlay);
1466 g_windowManager.Add(new CGUIDialogVideoOverlay);
1467 g_windowManager.Add(new CGUIWindowScreensaver);
1468 g_windowManager.Add(new CGUIWindowWeather);
1469 g_windowManager.Add(new CGUIWindowStartup);
1471 /* window id's 3000 - 3100 are reserved for python */
1473 // Make sure we have at least the default skin
1474 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1475 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1477 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1481 if (g_advancedSettings.m_splashImage)
1482 SAFE_DELETE(m_splash);
1484 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1485 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1486 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1488 g_passwordManager.CheckStartUpLock();
1491 // check if we should use the login screen
1492 if (CProfilesManager::Get().UsingLoginScreen())
1493 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1497 CJSONRPC::Initialize();
1499 ADDON::CAddonMgr::Get().StartServices(false);
1501 // let's start the PVR manager and decide if the PVR manager handle the startup window activation
1502 if (!StartPVRManager())
1503 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1505 CStereoscopicsManager::Get().Initialize();
1509 else //No GUI Created
1512 CJSONRPC::Initialize();
1514 ADDON::CAddonMgr::Get().StartServices(false);
1517 g_sysinfo.Refresh();
1519 CLog::Log(LOGINFO, "removing tempfiles");
1520 CUtil::RemoveTempFiles();
1522 if (!CProfilesManager::Get().UsingLoginScreen())
1528 m_slowTimer.StartZero();
1530 #if defined(HAVE_LIBCRYSTALHD)
1531 CCrystalHD::GetInstance();
1534 CAddonMgr::Get().StartServices(true);
1536 CLog::Log(LOGNOTICE, "initialize done");
1538 m_bInitializing = false;
1540 // reset our screensaver (starts timers etc.)
1543 #ifdef HAS_SDL_JOYSTICK
1544 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1545 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1551 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1557 // the callback will take care of starting/stopping webserver
1558 ret = CSettings::Get().SetBool("services.webserver", bStart);
1561 case ES_AIRPLAYSERVER:
1562 // the callback will take care of starting/stopping airplay
1563 ret = CSettings::Get().SetBool("services.airplay", bStart);
1566 case ES_JSONRPCSERVER:
1567 // the callback will take care of starting/stopping jsonrpc server
1568 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1572 // the callback will take care of starting/stopping upnp server
1573 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1576 case ES_UPNPRENDERER:
1577 // the callback will take care of starting/stopping upnp renderer
1578 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1581 case ES_EVENTSERVER:
1582 // the callback will take care of starting/stopping event server
1583 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1587 // the callback will take care of starting/stopping zeroconf
1588 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1595 CSettings::Get().Save();
1600 bool CApplication::StartPVRManager()
1602 if (!CSettings::Get().GetBool("pvrmanager.enabled"))
1605 int firstWindowId = 0;
1606 if (g_PVRManager.IsPVRWindow(g_SkinInfo->GetStartWindow()))
1607 firstWindowId = g_SkinInfo->GetFirstWindow();
1609 g_PVRManager.Start(true, firstWindowId);
1611 return (firstWindowId > 0);
1614 void CApplication::StopPVRManager()
1616 CLog::Log(LOGINFO, "stopping PVRManager");
1617 if (g_PVRManager.IsPlaying())
1619 g_PVRManager.Stop();
1620 g_EpgContainer.Stop();
1623 void CApplication::StartServices()
1625 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1626 // Start Thread for DVD Mediatype detection
1627 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1628 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1632 void CApplication::StopServices()
1634 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1636 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1637 CLog::Log(LOGNOTICE, "stop dvd detect media");
1638 m_DetectDVDType.StopThread();
1641 g_peripherals.Clear();
1644 void CApplication::OnSettingChanged(const CSetting *setting)
1646 if (setting == NULL)
1649 const std::string &settingId = setting->GetId();
1650 if (settingId == "lookandfeel.skin" ||
1651 settingId == "lookandfeel.font" ||
1652 settingId == "lookandfeel.skincolors")
1654 // if the skin changes and the current theme is not the default one, reset
1655 // the theme to the default value (which will also change lookandfeel.skincolors
1656 // which in turn will reload the skin. Similarly, if the current skin font is not
1657 // the default, reset it as well.
1658 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1659 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1660 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1661 CSettings::Get().SetString("lookandfeel.font", "Default");
1664 std::string builtin("ReloadSkin");
1665 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1666 builtin += "(confirm)";
1667 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1670 else if (settingId == "lookandfeel.skintheme")
1672 // also set the default color theme
1673 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1674 URIUtils::RemoveExtension(colorTheme);
1675 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1676 colorTheme = "defaults";
1678 // check if we have to change the skin color
1679 // if yes, it will trigger a call to ReloadSkin() in
1680 // it's OnSettingChanged() callback
1681 // if no we have to call ReloadSkin() ourselves
1682 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1683 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1685 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1687 else if (settingId == "lookandfeel.skinzoom")
1689 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1690 g_windowManager.SendThreadMessage(msg);
1692 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1694 // AE is master of audio settings and needs to be informed first
1695 CAEFactory::OnSettingsChange(settingId);
1697 if (settingId == "audiooutput.guisoundmode")
1699 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1701 // this tells player whether to open an audio stream passthrough or PCM
1702 // if this is changed, audio stream has to be reopened
1703 else if (settingId == "audiooutput.passthrough")
1705 CApplicationMessenger::Get().MediaRestart(false);
1708 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1709 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1710 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1711 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1712 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1713 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1714 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1715 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1718 void CApplication::OnSettingAction(const CSetting *setting)
1720 if (setting == NULL)
1723 const std::string &settingId = setting->GetId();
1724 if (settingId == "lookandfeel.skinsettings")
1725 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1726 else if (settingId == "screensaver.preview")
1727 ActivateScreenSaver(true);
1728 else if (settingId == "screensaver.settings")
1731 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1732 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1734 else if (settingId == "audiocds.settings")
1737 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("audiocds.encoder"), addon, ADDON_AUDIOENCODER))
1738 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1740 else if (settingId == "videoscreen.guicalibration")
1741 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1742 else if (settingId == "videoscreen.testpattern")
1743 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1746 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1748 if (setting == NULL)
1751 const std::string &settingId = setting->GetId();
1752 if (settingId == "audiooutput.channels")
1754 // check if this is an update from Eden
1755 if (oldSettingId != NULL && oldSettingNode != NULL &&
1756 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1759 CSettingInt* channels = (CSettingInt*)setting;
1760 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1761 ret = channels->SetValue(channels->GetValue() + 1);
1763 // let's just reset the audiodevice settings as well
1764 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1765 CAEFactory::VerifyOutputDevice(audiodevice, false);
1766 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1771 else if (settingId == "screensaver.mode")
1773 CSettingString *screensaverMode = (CSettingString*)setting;
1774 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1775 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1776 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1778 else if (settingId == "scrapers.musicvideosdefault")
1780 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1781 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1783 musicvideoScraper->Reset();
1787 #if defined(HAS_LIBAMCODEC)
1788 else if (settingId == "videoplayer.useamcodec")
1790 // Do not permit amcodec to be used on non-aml platforms.
1791 // The setting will be hidden but the default value is true,
1792 // so change it to false.
1795 CSettingBool *useamcodec = (CSettingBool*)setting;
1796 useamcodec->SetValue(false);
1800 #if defined(TARGET_ANDROID)
1801 else if (settingId == "videoplayer.usemediacodec")
1803 // Do not permit MediaCodec to be used Android platforms that do not have it.
1804 // The setting will be hidden but the default value is true,
1805 // so change it to false.
1806 if (CAndroidFeatures::GetVersion() < 16)
1808 CSettingBool *usemediacodec = (CSettingBool*)setting;
1809 usemediacodec->SetValue(false);
1812 else if (settingId == "videoplayer.usestagefright")
1814 CSettingBool *usestagefright = (CSettingBool*)setting;
1815 usestagefright->SetValue(false);
1818 #if defined(TARGET_DARWIN_OSX)
1819 else if (settingId == "audiooutput.audiodevice")
1821 CSettingString *audioDevice = (CSettingString*)setting;
1822 // Gotham and older didn't enumerate audio devices per stream on osx
1823 // add stream0 per default which should be ok for all old settings.
1824 if (!StringUtils::EqualsNoCase(audioDevice->GetValue(), "DARWINOSX:default") &&
1825 StringUtils::FindWords(audioDevice->GetValue().c_str(), ":stream") == std::string::npos)
1827 std::string newSetting = audioDevice->GetValue();
1828 newSetting += ":stream0";
1829 return audioDevice->SetValue(newSetting);
1837 bool CApplication::OnSettingsSaving() const
1839 // don't save settings when we're busy stopping the application
1840 // a lot of screens try to save settings on deinit and deinit is
1841 // called for every screen when the application is stopping
1848 void CApplication::ReloadSkin(bool confirm/*=false*/)
1850 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1852 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1853 g_windowManager.SendMessage(msg);
1855 string newSkin = CSettings::Get().GetString("lookandfeel.skin");
1856 if (LoadSkin(newSkin))
1858 /* The Reset() or SetString() below will cause recursion, so the m_skinReverting boolean is set so as to not prompt the
1859 user as to whether they want to keep the current skin. */
1860 if (confirm && !m_skinReverting)
1863 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1865 m_skinReverting = true;
1866 if (oldSkin.empty())
1867 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1869 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1875 // skin failed to load - we revert to the default only if we didn't fail loading the default
1876 string defaultSkin = ((CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1877 if (newSkin != defaultSkin)
1879 m_skinReverting = true;
1880 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1881 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1884 m_skinReverting = false;
1887 bool CApplication::Load(const TiXmlNode *settings)
1889 if (settings == NULL)
1892 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1893 if (audioElement != NULL)
1895 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1896 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1897 m_volumeLevel = VOLUME_MAXIMUM;
1903 bool CApplication::Save(TiXmlNode *settings) const
1905 if (settings == NULL)
1908 TiXmlElement volumeNode("audio");
1909 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1910 if (audioNode == NULL)
1913 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1914 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1919 bool CApplication::LoadSkin(const CStdString& skinID)
1922 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1924 if (LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon)))
1927 CLog::Log(LOGERROR, "failed to load requested skin '%s'", skinID.c_str());
1931 bool CApplication::LoadSkin(const SkinPtr& skin)
1937 if (!skin->HasSkinFile("Home.xml"))
1940 bool bPreviousPlayingState=false;
1941 bool bPreviousRenderingState=false;
1942 if (g_application.m_pPlayer->IsPlayingVideo())
1944 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1945 if (bPreviousPlayingState)
1946 g_application.m_pPlayer->Pause();
1947 #ifdef HAS_VIDEO_PLAYBACK
1948 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1950 g_windowManager.ActivateWindow(WINDOW_HOME);
1951 bPreviousRenderingState = true;
1955 // close the music and video overlays (they're re-opened automatically later)
1956 CSingleLock lock(g_graphicsContext);
1958 // save the current window details and focused control
1959 int currentWindow = g_windowManager.GetActiveWindow();
1961 CGUIWindow* pWindow = g_windowManager.GetWindow(currentWindow);
1963 iCtrlID = pWindow->GetFocusedControlID();
1964 vector<int> currentModelessWindows;
1965 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1969 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().asString().c_str());
1971 g_SkinInfo->Start();
1973 CLog::Log(LOGINFO, " load fonts for skin...");
1974 g_graphicsContext.SetMediaDir(skin->Path());
1975 g_directoryCache.ClearSubPaths(skin->Path());
1977 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1979 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1981 // load in the skin strings
1982 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1983 URIUtils::AddSlashAtEnd(langPath);
1985 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1987 g_SkinInfo->LoadIncludes();
1990 start = CurrentHostCounter();
1992 CLog::Log(LOGINFO, " load new skin...");
1994 // Load the user windows
1998 end = CurrentHostCounter();
1999 freq = CurrentHostFrequency();
2000 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
2002 CLog::Log(LOGINFO, " initialize new skin...");
2003 g_windowManager.AddMsgTarget(this);
2004 g_windowManager.AddMsgTarget(&g_playlistPlayer);
2005 g_windowManager.AddMsgTarget(&g_infoManager);
2006 g_windowManager.AddMsgTarget(&g_fontManager);
2007 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
2008 g_windowManager.SetCallback(*this);
2009 g_windowManager.Initialize();
2010 CTextureCache::Get().Initialize();
2011 g_audioManager.Enable(true);
2012 g_audioManager.Load();
2014 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
2015 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2017 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2018 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2019 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2020 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2021 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2024 CLog::Log(LOGINFO, " skin loaded...");
2026 // leave the graphics lock
2030 if (currentWindow != WINDOW_INVALID)
2032 g_windowManager.ActivateWindow(currentWindow);
2033 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2035 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2036 if (dialog) dialog->Show();
2040 pWindow = g_windowManager.GetWindow(currentWindow);
2041 if (pWindow && pWindow->HasSaveLastControl())
2043 CGUIMessage msg(GUI_MSG_SETFOCUS, currentWindow, iCtrlID, 0);
2044 pWindow->OnMessage(msg);
2049 if (g_application.m_pPlayer->IsPlayingVideo())
2051 if (bPreviousPlayingState)
2052 g_application.m_pPlayer->Pause();
2053 if (bPreviousRenderingState)
2054 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2059 void CApplication::UnloadSkin(bool forReload /* = false */)
2061 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2063 g_audioManager.Enable(false);
2065 g_windowManager.DeInitialize();
2066 CTextureCache::Get().Deinitialize();
2068 // remove the skin-dependent window
2069 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2071 g_TextureManager.Cleanup();
2072 g_largeTextureManager.CleanupUnusedImages(true);
2074 g_fontManager.Clear();
2076 g_colorManager.Clear();
2078 g_infoManager.Clear();
2080 // The g_SkinInfo boost shared_ptr ought to be reset here
2081 // but there are too many places it's used without checking for NULL
2082 // and as a result a race condition on exit can cause a crash.
2085 bool CApplication::LoadUserWindows()
2087 // Start from wherever home.xml is
2088 std::vector<std::string> vecSkinPath;
2089 g_SkinInfo->GetSkinPaths(vecSkinPath);
2090 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2092 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2093 CFileItemList items;
2094 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2096 for (int i = 0; i < items.Size(); ++i)
2098 if (items[i]->m_bIsFolder)
2100 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2101 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2103 CXBMCTinyXML xmlDoc;
2104 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2106 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2110 // Root element should be <window>
2111 TiXmlElement* pRootElement = xmlDoc.RootElement();
2112 CStdString strValue = pRootElement->Value();
2113 if (!strValue.Equals("window"))
2115 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2119 // Read the <type> element to get the window type to create
2120 // If no type is specified, create a CGUIWindow as default
2121 CGUIWindow* pWindow = NULL;
2123 if (pRootElement->Attribute("type"))
2124 strType = pRootElement->Attribute("type");
2127 const TiXmlNode *pType = pRootElement->FirstChild("type");
2128 if (pType && pType->FirstChild())
2129 strType = pType->FirstChild()->Value();
2131 int id = WINDOW_INVALID;
2132 if (!pRootElement->Attribute("id", &id))
2134 const TiXmlNode *pType = pRootElement->FirstChild("id");
2135 if (pType && pType->FirstChild())
2136 id = atol(pType->FirstChild()->Value());
2138 CStdString visibleCondition;
2139 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2141 if (strType.Equals("dialog"))
2142 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2143 else if (strType.Equals("submenu"))
2144 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2145 else if (strType.Equals("buttonmenu"))
2146 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2148 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2150 // Check to make sure the pointer isn't still null
2151 if (pWindow == NULL)
2153 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2156 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2161 pWindow->SetVisibleCondition(visibleCondition);
2162 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2163 g_windowManager.AddCustomWindow(pWindow);
2171 bool CApplication::RenderNoPresent()
2175 // DXMERGE: This may have been important?
2176 // g_graphicsContext.AcquireCurrentContext();
2178 g_graphicsContext.Lock();
2180 // dont show GUI when playing full screen video
2181 if (g_graphicsContext.IsFullScreenVideo())
2183 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2184 g_renderManager.Render(true, 0, 255);
2186 // close window overlays
2187 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2188 if (overlay) overlay->Close(true);
2189 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2190 if (overlay) overlay->Close(true);
2194 bool hasRendered = g_windowManager.Render();
2196 g_graphicsContext.Unlock();
2201 float CApplication::GetDimScreenSaverLevel() const
2203 if (!m_bScreenSave || !m_screenSaver ||
2204 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2205 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2206 !m_screenSaver->ID().empty()))
2209 if (!m_screenSaver->GetSetting("level").empty())
2210 return 100.0f - (float)atof(m_screenSaver->GetSetting("level").c_str());
2214 void CApplication::Render()
2216 // do not render if we are stopped or in background
2222 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2224 bool hasRendered = false;
2225 bool limitFrames = false;
2226 unsigned int singleFrameTime = 10; // default limit 100 fps
2230 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2231 // Whether externalplayer is playing and we're unfocused
2232 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2234 m_bPresentFrame = false;
2235 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2237 m_bPresentFrame = g_renderManager.FrameWait(100);
2242 // engage the frame limiter as needed
2243 limitFrames = lowfps || extPlayerActive;
2244 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2245 // perhaps allowing it to be set differently than the UI option??
2246 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2247 limitFrames = true; // not using vsync.
2248 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2249 limitFrames = true; // using vsync, but it isn't working.
2253 if (extPlayerActive)
2255 ResetScreenSaver(); // Prevent screensaver dimming the screen
2256 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2259 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2265 CSingleLock lock(g_graphicsContext);
2266 g_infoManager.UpdateFPS();
2268 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2269 g_Windowing.SetVSync(true);
2270 else if (vsync_mode == VSYNC_ALWAYS)
2271 g_Windowing.SetVSync(true);
2272 else if (vsync_mode != VSYNC_DRIVER)
2273 g_Windowing.SetVSync(false);
2275 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2278 if(!g_Windowing.BeginRender())
2281 g_renderManager.FrameMove();
2283 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2284 if(g_graphicsContext.GetStereoMode())
2286 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2287 if(RenderNoPresent())
2290 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2292 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2293 if(RenderNoPresent())
2296 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2300 if(RenderNoPresent())
2304 g_renderManager.FrameFinish();
2306 g_Windowing.EndRender();
2308 // execute post rendering actions (finalize window closing)
2309 g_windowManager.AfterRender();
2311 // reset our info cache - we do this at the end of Render so that it is
2312 // fresh for the next process(), or after a windowclose animation (where process()
2314 g_infoManager.ResetCache();
2317 unsigned int now = XbmcThreads::SystemClockMillis();
2319 m_lastRenderTime = now;
2321 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2322 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2324 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2325 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2329 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2330 if (limitFrames || !flip)
2333 singleFrameTime = 40; //if not flipping, loop at 25 fps
2335 unsigned int frameTime = now - m_lastFrameTime;
2336 if (frameTime < singleFrameTime)
2337 Sleep(singleFrameTime - frameTime);
2339 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2342 g_graphicsContext.Flip(dirtyRegions);
2343 CTimeUtils::UpdateFrameTime(flip);
2345 g_renderManager.UpdateResolution();
2346 g_renderManager.ManageCaptures();
2349 void CApplication::SetStandAlone(bool value)
2351 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2354 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2355 // The window manager will return true if the event is processed, false otherwise.
2356 // If not already processed, this routine handles global keypresses. It returns
2357 // true if the key has been processed, false otherwise.
2359 bool CApplication::OnKey(const CKey& key)
2362 // Turn the mouse off, as we've just got a keypress from controller or remote
2363 g_Mouse.SetActive(false);
2365 // get the current active window
2366 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2368 // this will be checked for certain keycodes that need
2369 // special handling if the screensaver is active
2370 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2372 // a key has been pressed.
2374 m_idleTimer.StartZero();
2375 bool processKey = AlwaysProcess(action);
2377 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2381 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2382 // do not wake up the screensaver right after switching off the playing device
2383 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2384 ret = CApplicationMessenger::Get().CECToggleState();
2386 ret = CApplicationMessenger::Get().CECStandby();
2387 if (!ret) /* display is switched off */
2393 // allow some keys to be processed while the screensaver is active
2394 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2396 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2400 // change this if we have a dialog up
2401 if (g_windowManager.HasModalDialog())
2403 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2405 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2406 { // fullscreen info dialog - special case
2407 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2409 if (!key.IsAnalogButton())
2410 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2412 if (OnAction(action))
2415 // fallthrough to the main window
2416 iWin = WINDOW_FULLSCREEN_VIDEO;
2418 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2420 // current active window is full screen video.
2421 if (g_application.m_pPlayer->IsInMenu())
2423 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2424 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2426 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2428 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2429 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2431 // if no PVR specific action/mapping is found, fall back to default
2432 if (action.GetID() == 0)
2433 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2437 // in any other case use the fullscreen window section of keymap.xml to map key->action
2438 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2443 // current active window isnt the fullscreen window
2444 // just use corresponding section from keymap.xml
2445 // to map key->action
2447 // first determine if we should use keyboard input directly
2448 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2449 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2452 CGUIControl *control = window->GetFocusedControl();
2455 // If this is an edit control set usekeyboard to true. This causes the
2456 // keypress to be processed directly not through the key mappings.
2457 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2460 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2461 // This causes the keypress to be used for list navigation.
2462 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2468 action = CAction(0); // reset our action
2469 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2471 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2472 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2473 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2474 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2475 action.GetID() == ACTION_MOVE_RIGHT ||
2476 action.GetID() == ACTION_MOVE_UP ||
2477 action.GetID() == ACTION_MOVE_DOWN ||
2478 action.GetID() == ACTION_SELECT_ITEM ||
2479 action.GetID() == ACTION_ENTER ||
2480 action.GetID() == ACTION_PREVIOUS_MENU ||
2481 action.GetID() == ACTION_NAV_BACK))
2483 // the action isn't plain navigation - check for a keyboard-specific keymap
2484 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2485 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2486 action.GetID() == ACTION_BACKSPACE ||
2487 action.GetID() == ACTION_SHIFT ||
2488 action.GetID() == ACTION_SYMBOLS ||
2489 action.GetID() == ACTION_CURSOR_LEFT ||
2490 action.GetID() == ACTION_CURSOR_RIGHT)
2491 action = CAction(0); // don't bother with this action
2494 if (!action.GetID())
2496 // keyboard entry - pass the keys through directly
2497 if (key.GetFromService())
2498 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2501 // Check for paste keypress
2502 #ifdef TARGET_WINDOWS
2503 // In Windows paste is ctrl-V
2504 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2505 #elif defined(TARGET_LINUX)
2506 // In Linux paste is ctrl-V
2507 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2508 #elif defined(TARGET_DARWIN_OSX)
2509 // In OSX paste is cmd-V
2510 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2512 // Placeholder for other operating systems
2515 action = CAction(ACTION_PASTE);
2516 // If the unicode is non-zero the keypress is a non-printing character
2517 else if (key.GetUnicode())
2518 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2519 // The keypress is a non-printing character
2521 action = CAction(key.GetVKey() | KEY_VKEY);
2525 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2527 if (OnAction(action))
2529 // failed to handle the keyboard action, drop down through to standard action
2531 if (key.GetFromService())
2533 if (key.GetButtonCode() != KEY_INVALID)
2534 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2537 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2539 if (!key.IsAnalogButton())
2540 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2542 return ExecuteInputAction(action);
2545 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2546 // This needs to return true if it processed the appcommand or false if it didn't
2547 bool CApplication::OnAppCommand(const CAction &action)
2549 // Reset the screen saver
2552 // If we were currently in the screen saver wake up and don't process the appcommand
2553 if (WakeUpScreenSaverAndDPMS())
2556 // The action ID is the APPCOMMAND code. We need to retrieve the action
2557 // associated with this appcommand from the mapping table.
2558 uint32_t appcmd = action.GetID();
2559 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2560 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2561 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2563 // If we couldn't find an action return false to indicate we have not
2564 // handled this appcommand
2565 if (!appcmdaction.GetID())
2567 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2571 // Process the appcommand
2572 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2573 OnAction(appcmdaction);
2575 // Always return true regardless of whether the action succeeded or not.
2576 // This stops Windows handling the appcommand itself.
2580 bool CApplication::OnAction(const CAction &action)
2582 // special case for switching between GUI & fullscreen mode.
2583 if (action.GetID() == ACTION_SHOW_GUI)
2584 { // Switch to fullscreen mode if we can
2585 if (SwitchToFullScreen())
2587 m_navigationTimer.StartZero();
2592 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2594 g_graphicsContext.ToggleFullScreenRoot();
2598 if (action.IsMouse())
2599 g_Mouse.SetActive(true);
2602 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2604 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2606 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2608 CGUIDialogVideoBookmarks::OnAddBookmark();
2611 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2612 // playing or ACTION_PLAYER_PLAY if we are not playing.
2613 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2615 if (m_pPlayer->IsPlaying())
2616 return OnAction(CAction(ACTION_PAUSE));
2618 return OnAction(CAction(ACTION_PLAYER_PLAY));
2621 //if the action would start or stop inertial scrolling
2622 //by gesture - bypass the normal OnAction handler of current window
2623 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2626 // just pass the action to the current window and let it handle it
2627 if (g_windowManager.OnAction(action))
2629 m_navigationTimer.StartZero();
2634 // handle extra global presses
2636 // screenshot : take a screenshot :)
2637 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2639 CScreenShot::TakeScreenshot();
2642 // built in functions : execute the built-in
2643 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2645 CBuiltins::Execute(action.GetName());
2646 m_navigationTimer.StartZero();
2651 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2653 CButtonTranslator::GetInstance().Clear();
2654 CButtonTranslator::GetInstance().Load();
2657 // show info : Shows the current video or song information
2658 if (action.GetID() == ACTION_SHOW_INFO)
2660 g_infoManager.ToggleShowInfo();
2664 // codec info : Shows the current song, video or picture codec information
2665 if (action.GetID() == ACTION_SHOW_CODEC)
2667 g_infoManager.ToggleShowCodec();
2671 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2673 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2676 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2677 char rating = tag->GetRating();
2678 bool needsUpdate(false);
2679 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2681 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2684 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2686 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2692 if (db.Open()) // OpenForWrite() ?
2694 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2697 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2698 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2699 g_windowManager.SendMessage(msg);
2705 // Now check with the playlist player if action can be handled.
2706 // 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.
2707 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2709 if (g_playlistPlayer.OnAction(action))
2713 // Now check with the player if action can be handled.
2714 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2715 (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)) ||
2716 action.GetID() == ACTION_STOP)
2718 if (m_pPlayer->OnAction(action))
2720 // Player ignored action; popup the OSD
2721 if ((action.GetID() == ACTION_MOUSE_MOVE && (action.GetAmount(2) || action.GetAmount(3))) // filter "false" mouse move from touch
2722 || action.GetID() == ACTION_MOUSE_LEFT_CLICK)
2723 CApplicationMessenger::Get().SendAction(CAction(ACTION_TRIGGER_OSD), WINDOW_INVALID, false);
2726 // stop : stops playing current audio song
2727 if (action.GetID() == ACTION_STOP)
2733 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2734 // If so, we just jump to the start of the track.
2735 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2738 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2742 // forward action to g_PVRManager and break if it was able to handle it
2743 if (g_PVRManager.OnAction(action))
2746 // forward action to graphic context and see if it can handle it
2747 if (CStereoscopicsManager::Get().OnAction(action))
2750 if (m_pPlayer->IsPlaying())
2752 // forward channel switches to the player - he knows what to do
2753 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2755 m_pPlayer->OnAction(action);
2759 // pause : pauses current audio song
2760 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2764 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2766 if (!m_pPlayer->IsPaused())
2767 { // unpaused - set the playspeed back to normal
2768 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2770 g_audioManager.Enable(m_pPlayer->IsPaused());
2773 if (!m_pPlayer->IsPaused())
2775 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2776 // if we are playing at normal speed, then allow play to pause
2777 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2779 if (m_pPlayer->GetPlaySpeed() != 1)
2781 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2789 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2791 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2792 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2794 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2796 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2801 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2803 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2806 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2809 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2811 // calculate the speed based on the amount the button is held down
2812 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2813 // returns 0 -> MAX_FFWD_SPEED
2814 int iSpeed = 1 << iPower;
2815 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2817 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2819 CLog::Log(LOGDEBUG,"Resetting playspeed");
2823 // allow play to unpause
2826 if (action.GetID() == ACTION_PLAYER_PLAY)
2828 // unpause, and set the playspeed back to normal
2830 g_audioManager.Enable(m_pPlayer->IsPaused());
2832 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2837 // record current file
2838 if (action.GetID() == ACTION_RECORD)
2840 if (m_pPlayer->CanRecord())
2841 m_pPlayer->Record(!m_pPlayer->IsRecording());
2844 if (m_playerController->OnAction(action))
2849 if (action.GetID() == ACTION_SWITCH_PLAYER)
2851 if(m_pPlayer->IsPlaying())
2853 VECPLAYERCORES cores;
2854 CFileItem item(*m_itemCurrentFile.get());
2855 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2856 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2857 if(core != EPC_NONE)
2859 g_application.m_eForcedNextPlayer = core;
2860 item.m_lStartOffset = (int)(GetTime() * 75);
2861 PlayFile(item, true);
2866 VECPLAYERCORES cores;
2867 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2868 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2869 if(core != EPC_NONE)
2872 g_application.m_eForcedNextPlayer = core;
2873 PlayFile(item, false);
2878 if (g_peripherals.OnAction(action))
2881 if (action.GetID() == ACTION_MUTE)
2887 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2889 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2890 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2892 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2894 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2895 g_windowManager.SendMessage(msg);
2900 // Check for global volume control
2901 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2903 if (!m_pPlayer->IsPassthrough())
2907 float volume = m_volumeLevel;
2908 // Android has steps based on the max available volume level
2909 #if defined(TARGET_ANDROID)
2910 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2912 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2914 if (action.GetRepeat())
2915 step *= action.GetRepeat() * 50; // 50 fps
2917 if (action.GetID() == ACTION_VOLUME_UP)
2918 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2920 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2921 SetVolume(volume, false);
2923 // show visual feedback of volume change...
2924 ShowVolumeBar(&action);
2927 // Check for global seek control
2928 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2930 if (!m_pPlayer->CanSeek()) return false;
2931 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2934 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2936 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2937 CGUIControlProfiler::Instance().Start();
2940 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2942 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2943 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2944 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2945 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2946 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2952 void CApplication::FrameMove(bool processEvents, bool processGUI)
2958 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2959 float frameTime = m_frameTime.GetElapsedSeconds();
2960 m_frameTime.StartZero();
2961 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2962 if( frameTime > 0.5 ) frameTime = 0.5;
2964 if (processGUI && m_renderGUI)
2966 g_graphicsContext.Lock();
2967 // check if there are notifications to display
2968 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2969 if (toast && toast->DoWork())
2971 if (!toast->IsDialogRunning())
2976 g_graphicsContext.Unlock();
2978 CWinEvents::MessagePump();
2980 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2981 // Read the input from a remote
2982 g_RemoteControl.Update();
2985 // process input actions
2986 ProcessRemote(frameTime);
2987 ProcessGamepad(frameTime);
2988 ProcessEventServer(frameTime);
2989 ProcessPeripherals(frameTime);
2990 if (processGUI && m_renderGUI)
2992 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2993 m_seekHandler->Process();
2996 if (processGUI && m_renderGUI)
2999 g_windowManager.Process(CTimeUtils::GetFrameTime());
3000 g_windowManager.FrameMove();
3004 bool CApplication::ProcessGamepad(float frameTime)
3006 #ifdef HAS_SDL_JOYSTICK
3010 int iWin = GetActiveWindowID();
3012 g_Joystick.Update();
3013 if (g_Joystick.GetButton(bid))
3016 m_idleTimer.StartZero();
3019 if (WakeUpScreenSaverAndDPMS())
3021 g_Joystick.Reset(true);
3026 CStdString actionName;
3028 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3030 CAction action(actionID, 1.0f, 0.0f, actionName);
3032 g_Mouse.SetActive(false);
3033 return ExecuteInputAction(action);
3040 if (g_Joystick.GetAxis(bid))
3042 if (g_Joystick.GetAmount() < 0)
3048 CStdString actionName;
3050 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3053 if (WakeUpScreenSaverAndDPMS())
3058 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3060 g_Mouse.SetActive(false);
3061 return ExecuteInputAction(action);
3065 g_Joystick.ResetAxis(abs(bid));
3069 if (g_Joystick.GetHat(bid, position))
3072 m_idleTimer.StartZero();
3075 if (WakeUpScreenSaverAndDPMS())
3082 CStdString actionName;
3085 bid = position<<16|bid;
3087 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3089 CAction action(actionID, 1.0f, 0.0f, actionName);
3091 g_Mouse.SetActive(false);
3092 return ExecuteInputAction(action);
3099 bool CApplication::ProcessRemote(float frameTime)
3101 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3102 if (g_RemoteControl.GetButton())
3104 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3105 g_RemoteControl.Reset();
3112 bool CApplication::ProcessPeripherals(float frameTime)
3115 if (g_peripherals.GetNextKeypress(frameTime, key))
3120 bool CApplication::ProcessMouse()
3124 if (!g_Mouse.IsActive() || !m_AppFocused)
3127 // Get the mouse command ID
3128 uint32_t mousecommand = g_Mouse.GetAction();
3129 if (mousecommand == ACTION_NOOP)
3132 // Reset the screensaver and idle timers
3133 m_idleTimer.StartZero();
3135 if (WakeUpScreenSaverAndDPMS())
3138 // Retrieve the corresponding action
3139 int iWin = GetActiveWindowID();
3140 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3141 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3143 // Deactivate mouse if non-mouse action
3144 if (!mouseaction.IsMouse())
3145 g_Mouse.SetActive(false);
3147 // Consume ACTION_NOOP.
3148 // Some views or dialogs gets closed after any ACTION and
3149 // a sensitive mouse might cause problems.
3150 if (mouseaction.GetID() == ACTION_NOOP)
3153 // If we couldn't find an action return false to indicate we have not
3154 // handled this mouse action
3155 if (!mouseaction.GetID())
3157 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3161 // Log mouse actions except for move and noop
3162 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3163 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3165 // The action might not be a mouse action. For example wheel moves might
3166 // be mapped to volume up/down in mouse.xml. In this case we do not want
3167 // the mouse position saved in the action.
3168 if (!mouseaction.IsMouse())
3169 return OnAction(mouseaction);
3171 // This is a mouse action so we need to record the mouse position
3172 return OnAction(CAction(mouseaction.GetID(),
3173 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3174 (float)g_Mouse.GetX(),
3175 (float)g_Mouse.GetY(),
3176 (float)g_Mouse.GetDX(),
3177 (float)g_Mouse.GetDY(),
3178 mouseaction.GetName()));
3181 bool CApplication::ProcessEventServer(float frameTime)
3183 #ifdef HAS_EVENT_SERVER
3184 CEventServer* es = CEventServer::GetInstance();
3185 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3188 // process any queued up actions
3189 if (es->ExecuteNextAction())
3191 // reset idle timers
3192 m_idleTimer.StartZero();
3194 WakeUpScreenSaverAndDPMS();
3197 // now handle any buttons or axis
3198 std::string joystickName;
3199 bool isAxis = false;
3200 float fAmount = 0.0;
3202 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3203 // when the action exits XBMC
3204 es = CEventServer::GetInstance();
3205 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3207 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3211 if (joystickName.length() > 0)
3215 if (fabs(fAmount) >= 0.08)
3216 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3218 m_lastAxisMap[joystickName].erase(wKeyID);
3221 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3226 if (wKeyID & ES_FLAG_UNICODE)
3228 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3232 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3233 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3234 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3235 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3236 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3237 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3238 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3239 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3240 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3241 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3242 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3243 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3244 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3245 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3246 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3247 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3248 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3249 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3250 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3251 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3254 key.SetFromService(true);
3259 if (m_lastAxisMap.size() > 0)
3261 // Process all the stored axis.
3262 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3264 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3265 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3271 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3273 XBMC_Event newEvent;
3274 newEvent.type = XBMC_MOUSEMOTION;
3275 newEvent.motion.xrel = 0;
3276 newEvent.motion.yrel = 0;
3277 newEvent.motion.state = 0;
3278 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3279 newEvent.motion.x = (uint16_t)pos.x;
3280 newEvent.motion.y = (uint16_t)pos.y;
3281 OnEvent(newEvent); // had to call this to update g_Mouse position
3282 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3289 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3291 #if defined(HAS_EVENT_SERVER)
3292 m_idleTimer.StartZero();
3294 // Make sure to reset screen saver, mouse.
3296 if (WakeUpScreenSaverAndDPMS())
3299 #ifdef HAS_SDL_JOYSTICK
3302 g_Mouse.SetActive(false);
3304 int iWin = GetActiveWindowID();
3306 CStdString actionName;
3307 bool fullRange = false;
3309 // Translate using regular joystick translator.
3310 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3311 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3313 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3319 bool CApplication::ExecuteInputAction(const CAction &action)
3321 bool bResult = false;
3323 // play sound before the action unless the button is held,
3324 // where we execute after the action as held actions aren't fired every time.
3325 if(action.GetHoldTime())
3327 bResult = OnAction(action);
3329 g_audioManager.PlayActionSound(action);
3333 g_audioManager.PlayActionSound(action);
3334 bResult = OnAction(action);
3339 int CApplication::GetActiveWindowID(void)
3341 // Get the currently active window
3342 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3344 // If there is a dialog active get the dialog id instead
3345 if (g_windowManager.HasModalDialog())
3346 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3348 // If the window is FullScreenVideo check for special cases
3349 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3351 // check if we're in a DVD menu
3352 if(g_application.m_pPlayer->IsInMenu())
3353 iWin = WINDOW_VIDEO_MENU;
3354 // check for LiveTV and switch to it's virtual window
3355 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3356 iWin = WINDOW_FULLSCREEN_LIVETV;
3359 // Return the window id
3363 bool CApplication::Cleanup()
3367 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3368 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3369 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3370 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3371 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3372 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3373 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3374 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3375 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3376 g_windowManager.Delete(WINDOW_FILES);
3377 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3378 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3379 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3380 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3381 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3382 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3383 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3384 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3385 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3386 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3387 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3388 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3389 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3390 g_windowManager.Delete(WINDOW_DIALOG_OK);
3391 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3392 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3393 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3394 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3395 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3396 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3397 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3398 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3399 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3400 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3401 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3402 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3403 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3404 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3405 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3406 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3407 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3408 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3409 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3410 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3411 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3412 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3413 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3415 /* Delete PVR related windows and dialogs */
3416 g_windowManager.Delete(WINDOW_TV_CHANNELS);
3417 g_windowManager.Delete(WINDOW_TV_RECORDINGS);
3418 g_windowManager.Delete(WINDOW_TV_GUIDE);
3419 g_windowManager.Delete(WINDOW_TV_TIMERS);
3420 g_windowManager.Delete(WINDOW_TV_SEARCH);
3421 g_windowManager.Delete(WINDOW_RADIO_CHANNELS);
3422 g_windowManager.Delete(WINDOW_RADIO_RECORDINGS);
3423 g_windowManager.Delete(WINDOW_RADIO_GUIDE);
3424 g_windowManager.Delete(WINDOW_RADIO_TIMERS);
3425 g_windowManager.Delete(WINDOW_RADIO_SEARCH);
3426 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3427 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3428 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3429 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3430 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3431 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3432 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3433 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3434 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3435 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3436 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3437 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3438 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3440 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3441 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3442 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3443 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3444 g_windowManager.Delete(WINDOW_VISUALISATION);
3445 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3446 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3447 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3448 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3449 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3450 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3451 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3452 g_windowManager.Delete(WINDOW_SCREENSAVER);
3453 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3454 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3455 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3456 g_windowManager.Delete(WINDOW_SLIDESHOW);
3457 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3458 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3460 g_windowManager.Delete(WINDOW_HOME);
3461 g_windowManager.Delete(WINDOW_PROGRAMS);
3462 g_windowManager.Delete(WINDOW_PICTURES);
3463 g_windowManager.Delete(WINDOW_WEATHER);
3465 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3466 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3467 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3468 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3469 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3470 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3471 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3472 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3473 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3474 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3476 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3477 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3479 CAddonMgr::Get().DeInit();
3481 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3482 CLog::Log(LOGNOTICE, "closing down remote control service");
3483 g_RemoteControl.Disconnect();
3486 CLog::Log(LOGNOTICE, "unload sections");
3488 #ifdef HAS_PERFORMANCE_SAMPLE
3489 CLog::Log(LOGNOTICE, "performance statistics");
3490 m_perfStats.DumpStats();
3493 // Shutdown as much as possible of the
3494 // application, to reduce the leaks dumped
3495 // to the vc output window before calling
3496 // _CrtDumpMemoryLeaks(). Most of the leaks
3497 // shown are no real leaks, as parts of the app
3498 // are still allocated.
3500 g_localizeStrings.Clear();
3501 g_LangCodeExpander.Clear();
3502 g_charsetConverter.clear();
3503 g_directoryCache.Clear();
3504 CButtonTranslator::GetInstance().Clear();
3505 #ifdef HAS_EVENT_SERVER
3506 CEventServer::RemoveInstance();
3508 DllLoaderContainer::Clear();
3509 g_playlistPlayer.Clear();
3510 CSettings::Get().Uninitialize();
3511 g_advancedSettings.Clear();
3514 CXHandle::DumpObjectTracker();
3516 #ifdef HAS_DVD_DRIVE
3517 CLibcdio::ReleaseInstance();
3520 #if defined(TARGET_ANDROID)
3521 // enable for all platforms once it's safe
3522 g_sectionLoader.UnloadAll();
3524 #ifdef _CRTDBG_MAP_ALLOC
3525 _CrtDumpMemoryLeaks();
3526 while(1); // execution ends
3536 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3541 void CApplication::Stop(int exitCode)
3545 CVariant vExitCode(exitCode);
3546 CAnnouncementManager::Get().Announce(System, "xbmc", "OnQuit", vExitCode);
3548 SaveFileState(true);
3550 g_alarmClock.StopThread();
3552 if( m_bSystemScreenSaverEnable )
3553 g_Windowing.EnableSystemScreenSaver(true);
3555 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3556 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3558 // Update the settings information (volume, uptime etc. need saving)
3559 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3561 CLog::Log(LOGNOTICE, "Saving settings");
3562 CSettings::Get().Save();
3565 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3568 m_AppFocused = false;
3569 m_ExitCode = exitCode;
3570 CLog::Log(LOGNOTICE, "stop all");
3572 // cancel any jobs from the jobmanager
3573 CJobManager::GetInstance().CancelJobs();
3575 // stop scanning before we kill the network and so on
3576 if (m_musicInfoScanner->IsScanning())
3577 m_musicInfoScanner->Stop();
3579 if (m_videoInfoScanner->IsScanning())
3580 m_videoInfoScanner->Stop();
3582 CApplicationMessenger::Get().Cleanup();
3584 CLog::Log(LOGNOTICE, "stop player");
3585 m_pPlayer->ClosePlayer();
3587 CAnnouncementManager::Get().Deinitialize();
3593 #if HAS_FILESYTEM_DAAP
3594 CLog::Log(LOGNOTICE, "stop daap clients");
3595 g_DaapClient.Release();
3597 #ifdef HAS_FILESYSTEM_SAP
3598 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3599 g_sapsessions.StopThread();
3602 if(CZeroconfBrowser::IsInstantiated())
3604 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3605 CZeroconfBrowser::GetInstance()->Stop();
3606 CZeroconfBrowser::ReleaseInstance();
3610 CLog::Log(LOGNOTICE, "clean cached files!");
3611 #ifdef HAS_FILESYSTEM_RAR
3612 g_RarManager.ClearCache(true);
3615 #ifdef HAS_FILESYSTEM_SFTP
3616 CSFTPSessionManager::DisconnectAllSessions();
3619 CLog::Log(LOGNOTICE, "unload skin");
3622 #if defined(TARGET_DARWIN_OSX)
3623 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3624 XBMCHelper::GetInstance().Stop();
3627 #if defined(HAVE_LIBCRYSTALHD)
3628 CCrystalHD::RemoveInstance();
3631 g_mediaManager.Stop();
3633 // Stop services before unloading Python
3634 CAddonMgr::Get().StopServices(false);
3636 // stop all remaining scripts; must be done after skin has been unloaded,
3637 // not before some windows still need it when deinitializing during skin
3639 CScriptInvocationManager::Get().Uninitialize();
3641 g_Windowing.DestroyRenderSystem();
3642 g_Windowing.DestroyWindow();
3643 g_Windowing.DestroyWindowSystem();
3645 // shutdown the AudioEngine
3646 CAEFactory::Shutdown();
3647 CAEFactory::UnLoadEngine();
3649 // unregister ffmpeg lock manager call back
3650 av_lockmgr_register(NULL);
3652 CLog::Log(LOGNOTICE, "stopped");
3656 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3659 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3660 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3662 cleanup_emu_environ();
3663 CTimeUtils::Close();
3669 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3671 //If item is a plugin, expand out now and run ourselves again
3672 if (item.IsPlugin())
3674 CFileItem item_new(item);
3675 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3676 return PlayMedia(item_new, iPlaylist);
3679 if (item.IsSmartPlayList())
3681 CFileItemList items;
3682 CUtil::GetRecursiveListing(item.GetPath(), items, "", DIR_FLAG_NO_FILE_DIRS);
3685 CSmartPlaylist smartpl;
3686 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3687 smartpl.OpenAndReadName(item.GetURL());
3689 playlist.Add(items);
3690 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3693 else if (item.IsPlayList() || item.IsInternetStream())
3695 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3697 //is or could be a playlist
3698 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3699 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3704 if (dlgCache->IsCanceled())
3711 if (iPlaylist != PLAYLIST_NONE)
3714 if (item.HasProperty("playlist_starting_track"))
3715 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3716 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3720 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());
3721 if(pPlayList->size())
3722 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3727 //nothing special just play
3728 return PlayFile(item, false) == PLAYBACK_OK;
3732 // For playing a multi-file video. Particularly inefficient
3733 // on startup, as we are required to calculate the length
3734 // of each video, so we open + close each one in turn.
3735 // A faster calculation of video time would improve this
3737 // return value: same with PlayFile()
3738 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3740 if (!item.IsStack())
3741 return PLAYBACK_FAIL;
3745 // case 1: stacked ISOs
3746 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3748 CStackDirectory dir;
3749 CFileItemList movieList;
3750 dir.GetDirectory(item.GetURL(), movieList);
3752 // first assume values passed to the stack
3753 int selectedFile = item.m_lStartPartNumber;
3754 int startoffset = item.m_lStartOffset;
3756 // check if we instructed the stack to resume from default
3757 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3762 CStdString path = item.GetPath();
3763 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3764 path = item.GetProperty("original_listitem_url").asString();
3765 if( dbs.GetResumeBookMark(path, bookmark) )
3767 startoffset = (int)(bookmark.timeInSeconds*75);
3768 selectedFile = bookmark.partNumber;
3773 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3776 // make sure that the selected part is within the boundaries
3777 if (selectedFile <= 0)
3779 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3782 else if (selectedFile > movieList.Size())
3784 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3785 selectedFile = movieList.Size();
3788 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3789 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3790 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3791 *m_stackFileItemToUpdate = item;
3792 return PlayFile(*(movieList[selectedFile - 1]));
3794 // case 2: all other stacks
3797 LoadVideoSettings(item.GetPath());
3799 // see if we have the info in the database
3800 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3801 // then these times will be wrong.
3802 // Also, this is really just a hack for the slow load up times we have
3803 // A much better solution is a fast reader of FPS and fileLength
3804 // that we can use on a file to get it's time.
3806 bool haveTimes(false);
3810 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3815 // calculate the total time of the stack
3816 CStackDirectory dir;
3817 dir.GetDirectory(item.GetURL(), *m_currentStack);
3819 for (int i = 0; i < m_currentStack->Size(); i++)
3822 (*m_currentStack)[i]->m_lEndOffset = times[i];
3826 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3828 m_currentStack->Clear();
3829 return PLAYBACK_FAIL;
3831 totalTime += duration / 1000;
3832 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3833 times.push_back(totalTime);
3837 double seconds = item.m_lStartOffset / 75.0;
3839 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3840 { // have our times now, so update the dB
3844 dbs.SetStackTimes(item.GetPath(), times);
3846 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3848 // can only resume seek here, not dvdstate
3850 CStdString path = item.GetPath();
3851 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3852 path = item.GetProperty("original_listitem_url").asString();
3853 if( dbs.GetResumeBookMark(path, bookmark) )
3854 seconds = bookmark.timeInSeconds;
3862 *m_itemCurrentFile = item;
3863 m_currentStackPosition = 0;
3864 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3868 // work out where to seek to
3869 for (int i = 0; i < m_currentStack->Size(); i++)
3871 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3873 CFileItem item(*(*m_currentStack)[i]);
3874 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3875 item.m_lStartOffset = (long)(seconds - start) * 75;
3876 m_currentStackPosition = i;
3877 return PlayFile(item, true);
3882 return PlayFile(*(*m_currentStack)[0], true);
3884 return PLAYBACK_FAIL;
3887 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3889 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3890 if (item.GetMimeType().empty())
3891 const_cast<CFileItem&>(item).FillInMimeType();
3895 SaveFileState(true);
3897 OutputDebugString("new file set audiostream:0\n");
3898 // Switch to default options
3899 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3900 // see if we have saved options in the database
3902 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3903 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3905 *m_itemCurrentFile = item;
3906 m_nextPlaylistItem = -1;
3907 m_currentStackPosition = 0;
3908 m_currentStack->Clear();
3911 CUtil::ClearSubtitles();
3914 if (item.IsDiscStub())
3916 #ifdef HAS_DVD_DRIVE
3917 // Display the Play Eject dialog if there is any optical disc drive
3918 if (g_mediaManager.HasOpticalDrive())
3920 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3921 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3922 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3923 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3927 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3932 if (item.IsPlayList())
3933 return PLAYBACK_FAIL;
3935 if (item.IsPlugin())
3936 { // we modify the item so that it becomes a real URL
3937 CFileItem item_new(item);
3938 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3939 return PlayFile(item_new, false);
3940 return PLAYBACK_FAIL;
3944 if (URIUtils::IsUPnP(item.GetPath()))
3946 CFileItem item_new(item);
3947 if (XFILE::CUPnPDirectory::GetResource(item.GetURL(), item_new))
3948 return PlayFile(item_new, false);
3949 return PLAYBACK_FAIL;
3953 // if we have a stacked set of files, we need to setup our stack routines for
3954 // "seamless" seeking and total time of the movie etc.
3955 // will recall with restart set to true
3957 return PlayStack(item, bRestart);
3959 //Is TuxBox, this should probably be moved to CTuxBoxFile
3962 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3964 if(g_tuxboxService.IsRunning())
3965 g_tuxboxService.Stop();
3967 PlayBackRet ret = PLAYBACK_FAIL;
3969 if(g_tuxbox.CreateNewItem(item, item_new))
3972 // Make sure it doesn't have a player
3973 // so we actually select one normally
3974 m_pPlayer->ResetPlayer();
3976 // keep the tuxbox:// url as playing url
3977 // and give the new url to the player
3978 ret = PlayFile(item_new, true);
3979 if(ret == PLAYBACK_OK)
3981 if(!g_tuxboxService.IsRunning())
3982 g_tuxboxService.Start();
3988 CPlayerOptions options;
3990 if( item.HasProperty("StartPercent") )
3992 double fallback = 0.0f;
3993 if(item.GetProperty("StartPercent").isString())
3994 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3995 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3998 PLAYERCOREID eNewCore = EPC_NONE;
4001 // have to be set here due to playstack using this for starting the file
4002 options.starttime = item.m_lStartOffset / 75.0;
4003 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
4004 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
4006 if( m_eForcedNextPlayer != EPC_NONE )
4007 eNewCore = m_eForcedNextPlayer;
4008 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
4009 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4011 eNewCore = m_pPlayer->GetCurrentPlayer();
4015 options.starttime = item.m_lStartOffset / 75.0;
4016 LoadVideoSettings(item.GetPath());
4020 // open the d/b and retrieve the bookmarks for the current movie
4024 if( item.m_lStartOffset == STARTOFFSET_RESUME )
4026 options.starttime = 0.0f;
4028 CStdString path = item.GetPath();
4029 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
4030 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
4031 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
4032 path = item.GetProperty("original_listitem_url").asString();
4033 if(dbs.GetResumeBookMark(path, bookmark))
4035 options.starttime = bookmark.timeInSeconds;
4036 options.state = bookmark.playerState;
4039 override with information from the actual item if available. We do this as the VFS (eg plugins)
4040 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4041 should the playerState be required, it is fetched from the database.
4042 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4044 if (item.IsResumePointSet())
4045 options.starttime = item.GetCurrentResumeTime();
4047 else if (item.HasVideoInfoTag())
4049 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4051 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4054 dbs.GetBookMarkForEpisode(*tag, bookmark);
4055 options.starttime = bookmark.timeInSeconds;
4056 options.state = bookmark.playerState;
4063 if (m_eForcedNextPlayer != EPC_NONE)
4064 eNewCore = m_eForcedNextPlayer;
4066 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4069 // this really aught to be inside !bRestart, but since PlayStack
4070 // uses that to init playback, we have to keep it outside
4071 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4072 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4073 { // playing from a playlist by the looks
4074 // don't switch to fullscreen if we are not playing the first item...
4075 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4077 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4079 // TODO - this will fail if user seeks back to first file in stack
4080 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4081 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4083 options.fullscreen = false;
4084 // reset this so we don't think we are resuming on seek
4085 m_itemCurrentFile->m_lStartOffset = 0;
4088 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4090 // reset VideoStartWindowed as it's a temp setting
4091 CMediaSettings::Get().SetVideoStartWindowed(false);
4094 //We have to stop parsing a cdg before mplayer is deallocated
4095 // WHY do we have to do this????
4097 m_pKaraokeMgr->Stop();
4101 CSingleLock lock(m_playStateMutex);
4102 // tell system we are starting a file
4103 m_bPlaybackStarting = true;
4105 // for playing a new item, previous playing item's callback may already
4106 // pushed some delay message into the threadmessage list, they are not
4107 // expected be processed after or during the new item playback starting.
4108 // so we clean up previous playing item's playback callback delay messages here.
4109 int previousMsgsIgnoredByNewPlaying[] = {
4110 GUI_MSG_PLAYBACK_STARTED,
4111 GUI_MSG_PLAYBACK_ENDED,
4112 GUI_MSG_PLAYBACK_STOPPED,
4113 GUI_MSG_PLAYLIST_CHANGED,
4114 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4115 GUI_MSG_PLAYLISTPLAYER_STARTED,
4116 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4117 GUI_MSG_QUEUE_NEXT_ITEM,
4120 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4122 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4125 // We should restart the player, unless the previous and next tracks are using
4126 // one of the players that allows gapless playback (paplayer, dvdplayer)
4127 m_pPlayer->ClosePlayerGapless(eNewCore);
4129 // now reset play state to starting, since we already stopped the previous playing item if there is.
4130 // and from now there should be no playback callback from previous playing item be called.
4131 m_ePlayState = PLAY_STATE_STARTING;
4133 m_pPlayer->CreatePlayer(eNewCore, *this);
4135 PlayBackRet iResult;
4136 if (m_pPlayer->HasPlayer())
4138 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4139 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4140 * increase performance on low powered systems (Atom/ARM).
4144 CJobManager::GetInstance().PauseJobs();
4147 // don't hold graphicscontext here since player
4148 // may wait on another thread, that requires gfx
4149 CSingleExit ex(g_graphicsContext);
4151 iResult = m_pPlayer->OpenFile(item, options);
4155 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4156 iResult = PLAYBACK_FAIL;
4159 if(iResult == PLAYBACK_OK)
4161 if (m_pPlayer->GetPlaySpeed() != 1)
4163 int iSpeed = m_pPlayer->GetPlaySpeed();
4164 m_pPlayer->m_iPlaySpeed = 1;
4165 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4168 // if player has volume control, set it.
4169 if (m_pPlayer->ControlsVolume())
4171 m_pPlayer->SetVolume(m_volumeLevel);
4172 m_pPlayer->SetMute(m_muted);
4175 if( m_pPlayer->IsPlayingAudio() )
4177 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4178 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4181 #ifdef HAS_VIDEO_PLAYBACK
4182 else if( m_pPlayer->IsPlayingVideo() )
4184 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4185 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4187 // if player didn't manange to switch to fullscreen by itself do it here
4188 if( options.fullscreen && g_renderManager.IsStarted()
4189 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4190 SwitchToFullScreen();
4195 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4196 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4197 g_windowManager.PreviousWindow();
4201 #if !defined(TARGET_POSIX)
4202 g_audioManager.Enable(false);
4205 if (item.HasPVRChannelInfoTag())
4206 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4209 CSingleLock lock(m_playStateMutex);
4210 m_bPlaybackStarting = false;
4212 if (iResult == PLAYBACK_OK)
4214 // play state: none, starting; playing; stopped; ended.
4215 // last 3 states are set by playback callback, they are all ignored during starting,
4216 // but we recorded the state, here we can make up the callback for the state.
4217 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4218 switch (m_ePlayState)
4220 case PLAY_STATE_PLAYING:
4221 OnPlayBackStarted();
4223 // FIXME: it seems no meaning to callback started here if there was an started callback
4224 // before this stopped/ended callback we recorded. if we callback started here
4225 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4226 // which will send OnStop announce at once, so currently, just call stopped/ended.
4227 case PLAY_STATE_ENDED:
4230 case PLAY_STATE_STOPPED:
4231 OnPlayBackStopped();
4233 case PLAY_STATE_STARTING:
4234 // neither started nor stopped/ended callback be called, that means the item still
4235 // not started, we need not make up any callback, just leave this and
4236 // let the player callback do its work.
4242 else if (iResult == PLAYBACK_FAIL)
4244 // we send this if it isn't playlistplayer that is doing this
4245 int next = g_playlistPlayer.GetNextSong();
4246 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4249 OnPlayBackStopped();
4250 m_ePlayState = PLAY_STATE_NONE;
4256 void CApplication::OnPlayBackEnded()
4258 CSingleLock lock(m_playStateMutex);
4259 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4260 m_ePlayState = PLAY_STATE_ENDED;
4261 if(m_bPlaybackStarting)
4264 // informs python script currently running playback has ended
4265 // (does nothing if python is not loaded)
4267 g_pythonParser.OnPlayBackEnded();
4270 CVariant data(CVariant::VariantTypeObject);
4272 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4274 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4275 g_windowManager.SendThreadMessage(msg);
4278 void CApplication::OnPlayBackStarted()
4280 CSingleLock lock(m_playStateMutex);
4281 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4282 m_ePlayState = PLAY_STATE_PLAYING;
4283 if(m_bPlaybackStarting)
4287 // informs python script currently running playback has started
4288 // (does nothing if python is not loaded)
4289 g_pythonParser.OnPlayBackStarted();
4292 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4293 g_windowManager.SendThreadMessage(msg);
4296 void CApplication::OnQueueNextItem()
4298 CSingleLock lock(m_playStateMutex);
4299 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4300 if(m_bPlaybackStarting)
4302 // informs python script currently running that we are requesting the next track
4303 // (does nothing if python is not loaded)
4305 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4308 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4309 g_windowManager.SendThreadMessage(msg);
4312 void CApplication::OnPlayBackStopped()
4314 CSingleLock lock(m_playStateMutex);
4315 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4316 m_ePlayState = PLAY_STATE_STOPPED;
4317 if(m_bPlaybackStarting)
4320 // informs python script currently running playback has ended
4321 // (does nothing if python is not loaded)
4323 g_pythonParser.OnPlayBackStopped();
4326 CVariant data(CVariant::VariantTypeObject);
4327 data["end"] = false;
4328 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4330 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4331 g_windowManager.SendThreadMessage(msg);
4334 void CApplication::OnPlayBackPaused()
4337 g_pythonParser.OnPlayBackPaused();
4341 param["player"]["speed"] = 0;
4342 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4343 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4346 void CApplication::OnPlayBackResumed()
4349 g_pythonParser.OnPlayBackResumed();
4353 param["player"]["speed"] = 1;
4354 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4355 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4358 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4361 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4365 param["player"]["speed"] = iSpeed;
4366 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4367 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4370 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4373 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4377 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4378 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4379 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4380 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4381 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4382 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4385 void CApplication::OnPlayBackSeekChapter(int iChapter)
4388 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4392 bool CApplication::IsPlayingFullScreenVideo() const
4394 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4397 bool CApplication::IsFullScreen()
4399 return IsPlayingFullScreenVideo() ||
4400 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4401 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4404 void CApplication::SaveFileState(bool bForeground /* = false */)
4406 if (!CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4409 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4410 *m_stackFileItemToUpdate,
4411 m_progressTrackingVideoResumeBookmark,
4412 m_progressTrackingPlayCountUpdate,
4413 CMediaSettings::Get().GetCurrentVideoSettings());
4417 // Run job in the foreground to make sure it finishes
4422 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4425 void CApplication::UpdateFileState()
4427 // Did the file change?
4428 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4430 // Ignore for PVR channels, PerformChannelSwitch takes care of this
4431 if (!m_progressTrackingItem->IsPVRChannel())
4434 // Reset tracking item
4435 m_progressTrackingItem->Reset();
4439 if (m_pPlayer->IsPlaying())
4441 if (m_progressTrackingItem->GetPath() == "")
4444 *m_progressTrackingItem = CurrentFileItem();
4445 m_progressTrackingPlayCountUpdate = false;
4448 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4449 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4450 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4451 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4453 m_progressTrackingPlayCountUpdate = true;
4456 // Check whether we're *really* playing video else we may race when getting eg. stream details
4457 if (m_pPlayer->IsPlayingVideo())
4459 /* Always update streamdetails, except for DVDs where we only update
4460 streamdetails if title length > 15m (Should yield more correct info) */
4461 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4463 CStreamDetails details;
4464 // Update with stream details from player, if any
4465 if (m_pPlayer->GetStreamDetails(details))
4466 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4468 if (m_progressTrackingItem->IsStack())
4469 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4472 // Update bookmark for save
4473 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4474 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4475 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4477 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4478 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4480 // Delete the bookmark
4481 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4484 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4486 // Update the bookmark
4487 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4488 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4493 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4500 void CApplication::LoadVideoSettings(const std::string &path)
4505 CLog::Log(LOGDEBUG, "Loading settings for %s", path.c_str());
4507 // Load stored settings if they exist, otherwise use default
4508 if (!dbs.GetVideoSettings(path, CMediaSettings::Get().GetCurrentVideoSettings()))
4509 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
4515 void CApplication::StopPlaying()
4517 int iWin = g_windowManager.GetActiveWindow();
4518 if ( m_pPlayer->IsPlaying() )
4522 m_pKaraokeMgr->Stop();
4525 m_pPlayer->CloseFile();
4527 // turn off visualisation window when stopping
4528 if ((iWin == WINDOW_VISUALISATION
4529 || iWin == WINDOW_FULLSCREEN_VIDEO)
4531 g_windowManager.PreviousWindow();
4533 g_partyModeManager.Disable();
4537 void CApplication::ResetSystemIdleTimer()
4539 // reset system idle timer
4540 m_idleTimer.StartZero();
4543 void CApplication::ResetScreenSaver()
4546 m_shutdownTimer.StartZero();
4548 // screen saver timer is reset only if we're not already in screensaver or
4550 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4551 ResetScreenSaverTimer();
4554 void CApplication::ResetScreenSaverTimer()
4556 m_screenSaverTimer.StartZero();
4559 void CApplication::StopScreenSaverTimer()
4561 m_screenSaverTimer.Stop();
4564 bool CApplication::ToggleDPMS(bool manual)
4566 if (manual || (m_dpmsIsManual == manual))
4570 m_dpmsIsActive = false;
4571 m_dpmsIsManual = false;
4572 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSDeactivated");
4573 return m_dpms->DisablePowerSaving();
4577 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4579 m_dpmsIsActive = true;
4580 m_dpmsIsManual = manual;
4581 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnDPMSActivated");
4589 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4593 // First reset DPMS, if active
4598 // TODO: if screensaver lock is specified but screensaver is not active
4599 // (DPMS came first), activate screensaver now.
4601 ResetScreenSaverTimer();
4602 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4605 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4609 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4610 CVariant data(bPowerOffKeyPressed);
4611 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4617 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4619 if (m_iScreenSaveLock == 2)
4622 // if Screen saver is active
4623 if (m_bScreenSave && m_screenSaver)
4625 if (m_iScreenSaveLock == 0)
4626 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4627 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4628 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4629 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4631 m_iScreenSaveLock = 2;
4632 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4634 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4636 pWindow->OnMessage(msg);
4638 if (m_iScreenSaveLock == -1)
4640 m_iScreenSaveLock = 0;
4644 // disable screensaver
4645 m_bScreenSave = false;
4646 m_iScreenSaveLock = 0;
4647 ResetScreenSaverTimer();
4649 if (m_screenSaver->ID() == "visualization")
4651 // we can just continue as usual from vis mode
4654 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4656 else if (!m_screenSaver->ID().empty())
4657 { // we're in screensaver window
4658 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4659 g_windowManager.PreviousWindow(); // show the previous window
4660 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4661 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4669 void CApplication::CheckScreenSaverAndDPMS()
4671 if (!m_dpmsIsActive)
4672 g_Windowing.ResetOSScreensaver();
4674 bool maybeScreensaver =
4675 !m_dpmsIsActive && !m_bScreenSave
4676 && !CSettings::Get().GetString("screensaver.mode").empty();
4678 !m_dpmsIsActive && m_dpms->IsSupported()
4679 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4681 // Has the screen saver window become active?
4682 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4684 m_bScreenSave = true;
4685 maybeScreensaver = false;
4688 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4690 WakeUpScreenSaverAndDPMS();
4694 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4696 // See if we need to reset timer.
4697 // * Are we playing a video and it is not paused?
4698 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4699 // * Are we playing some music in fullscreen vis?
4700 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4701 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4703 ResetScreenSaverTimer();
4707 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4709 // DPMS has priority (it makes the screensaver not needed)
4711 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4714 WakeUpScreenSaver();
4716 else if (maybeScreensaver
4717 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4719 ActivateScreenSaver();
4723 // activate the screensaver.
4724 // if forceType is true, we ignore the various conditions that can alter
4725 // the type of screensaver displayed
4726 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4728 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4729 { // just activate the visualisation if user toggled the usemusicvisinstead option
4730 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4734 m_bScreenSave = true;
4736 // Get Screensaver Mode
4737 m_screenSaver.reset();
4738 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4739 m_screenSaver.reset(new CScreenSaver(""));
4741 CAnnouncementManager::Get().Announce(GUI, "xbmc", "OnScreensaverActivated");
4743 // disable screensaver lock from the login screen
4744 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4747 // set to Dim in the case of a dialog on screen or playing video
4748 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4750 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4751 m_screenSaver.reset(new CScreenSaver(""));
4754 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4756 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4758 else if (!m_screenSaver->ID().empty())
4759 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4762 void CApplication::CheckShutdown()
4764 // first check if we should reset the timer
4765 if (m_bInhibitIdleShutdown
4766 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4767 || m_musicInfoScanner->IsScanning()
4768 || m_videoInfoScanner->IsScanning()
4769 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4770 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4772 m_shutdownTimer.StartZero();
4776 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4778 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4779 m_shutdownTimer.Stop();
4782 CApplicationMessenger::Get().Shutdown();
4786 void CApplication::InhibitIdleShutdown(bool inhibit)
4788 m_bInhibitIdleShutdown = inhibit;
4791 bool CApplication::IsIdleShutdownInhibited() const
4793 return m_bInhibitIdleShutdown;
4796 bool CApplication::OnMessage(CGUIMessage& message)
4798 switch ( message.GetMessage() )
4800 case GUI_MSG_NOTIFY_ALL:
4802 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4804 // Update general playlist: Remove DVD playlist items
4805 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4808 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4809 g_windowManager.SendMessage( msg );
4811 // stop the file if it's on dvd (will set the resume point etc)
4812 if (m_itemCurrentFile->IsOnDVD())
4818 case GUI_MSG_PLAYBACK_STARTED:
4820 #ifdef TARGET_DARWIN
4821 DarwinSetScheduling(message.GetMessage());
4823 // reset the seek handler
4824 m_seekHandler->Reset();
4825 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4827 // Update our infoManager with the new details etc.
4828 if (m_nextPlaylistItem >= 0)
4830 // playing an item which is not in the list - player might be stopped already
4832 if (playList.size() <= m_nextPlaylistItem)
4835 // we've started a previously queued item
4836 CFileItemPtr item = playList[m_nextPlaylistItem];
4837 // update the playlist manager
4838 int currentSong = g_playlistPlayer.GetCurrentSong();
4839 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4840 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4841 g_windowManager.SendThreadMessage(msg);
4842 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4843 *m_itemCurrentFile = *item;
4845 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4846 g_partyModeManager.OnSongChange(true);
4849 param["player"]["speed"] = 1;
4850 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4851 CAnnouncementManager::Get().Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4853 if (m_pPlayer->IsPlayingAudio())
4855 // Start our cdg parser as appropriate
4857 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4859 m_pKaraokeMgr->Stop();
4860 if (m_itemCurrentFile->IsMusicDb())
4862 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4864 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4865 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4868 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4871 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4880 case GUI_MSG_QUEUE_NEXT_ITEM:
4882 // Check to see if our playlist player has a new item for us,
4883 // and if so, we check whether our current player wants the file
4884 int iNext = g_playlistPlayer.GetNextSong();
4885 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4886 if (iNext < 0 || iNext >= playlist.size())
4888 m_pPlayer->OnNothingToQueueNotify();
4889 return true; // nothing to do
4892 // ok, grab the next song
4893 CFileItem file(*playlist[iNext]);
4895 CURL url(file.GetPath());
4896 if (url.GetProtocol() == "plugin")
4897 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4900 if (URIUtils::IsUPnP(file.GetPath()))
4902 if (!XFILE::CUPnPDirectory::GetResource(file.GetURL(), file))
4907 // ok - send the file to the player, if it accepts it
4908 if (m_pPlayer->QueueNextFile(file))
4910 // player accepted the next file
4911 m_nextPlaylistItem = iNext;
4915 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4916 queue the next (if it wants to) and it doesn't keep looping on this song */
4917 g_playlistPlayer.SetCurrentSong(iNext);
4924 case GUI_MSG_PLAYBACK_STOPPED:
4925 case GUI_MSG_PLAYBACK_ENDED:
4926 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4930 m_pKaraokeMgr->Stop();
4932 #ifdef TARGET_DARWIN
4933 DarwinSetScheduling(message.GetMessage());
4935 // first check if we still have items in the stack to play
4936 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4938 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4939 { // just play the next item in the stack
4940 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4945 // In case playback ended due to user eg. skipping over the end, clear
4946 // our resume bookmark here
4947 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4949 // Delete the bookmark
4950 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4953 // reset the current playing file
4954 m_itemCurrentFile->Reset();
4955 g_infoManager.ResetCurrentItem();
4956 m_currentStack->Clear();
4958 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4960 g_playlistPlayer.PlayNext(1, true);
4964 // reset any forced player
4965 m_eForcedNextPlayer = EPC_NONE;
4967 m_pPlayer->ClosePlayer();
4970 m_pPlayer->m_iPlaySpeed = 1;
4973 if (!m_pPlayer->IsPlaying())
4975 g_audioManager.Enable(true);
4978 if (!m_pPlayer->IsPlayingVideo())
4980 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4982 g_windowManager.PreviousWindow();
4986 CSingleLock lock(g_graphicsContext);
4987 // resets to res_desktop or look&feel resolution (including refreshrate)
4988 g_graphicsContext.SetFullScreenVideo(false);
4992 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4994 CSettings::Get().Save(); // save vis settings
4995 WakeUpScreenSaverAndDPMS();
4996 g_windowManager.PreviousWindow();
4999 // DVD ejected while playing in vis ?
5000 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
5003 CSettings::Get().Save(); // save vis settings
5004 WakeUpScreenSaverAndDPMS();
5005 g_windowManager.PreviousWindow();
5008 if (IsEnableTestMode())
5009 CApplicationMessenger::Get().Quit();
5014 case GUI_MSG_PLAYLISTPLAYER_STARTED:
5015 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
5020 case GUI_MSG_FULLSCREEN:
5021 { // Switch to fullscreen, if we can
5022 SwitchToFullScreen();
5026 case GUI_MSG_EXECUTE:
5027 if (message.GetNumStringParams())
5028 return ExecuteXBMCAction(message.GetStringParam());
5034 bool CApplication::ExecuteXBMCAction(std::string actionStr)
5036 // see if it is a user set string
5038 //We don't know if there is unsecure information in this yet, so we
5039 //postpone any logging
5040 const std::string in_actionStr(actionStr);
5041 actionStr = CGUIInfoLabel::GetLabel(actionStr);
5043 // user has asked for something to be executed
5044 if (CBuiltins::HasCommand(actionStr))
5045 CBuiltins::Execute(actionStr);
5048 // try translating the action from our ButtonTranslator
5050 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5052 OnAction(CAction(actionID));
5055 CFileItem item(actionStr, false);
5057 if (item.IsPythonScript())
5058 { // a python script
5059 CScriptInvocationManager::Get().Execute(item.GetPath());
5063 if (item.IsAudio() || item.IsVideo())
5064 { // an audio or video file
5069 //At this point we have given up to translate, so even though
5070 //there may be insecure information, we log it.
5071 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5078 void CApplication::Process()
5082 // dispatch the messages generated by python or other threads to the current window
5083 g_windowManager.DispatchThreadMessages();
5085 // process messages which have to be send to the gui
5086 // (this can only be done after g_windowManager.Render())
5087 CApplicationMessenger::Get().ProcessWindowMessages();
5091 m_loggingIn = false;
5093 // autoexec.py - profile
5094 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5096 if (XFILE::CFile::Exists(strAutoExecPy))
5097 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5099 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5102 // handle any active scripts
5103 CScriptInvocationManager::Get().Process();
5105 // process messages, even if a movie is playing
5106 CApplicationMessenger::Get().ProcessMessages();
5107 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5109 // check how far we are through playing the current item
5110 // and do anything that needs doing (playcount updates etc)
5111 CheckPlayingProgress();
5114 m_pPlayer->DoAudioWork();
5116 // do any processing that isn't needed on each run
5117 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5119 m_slowTimer.Reset();
5123 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5126 // We get called every 500ms
5127 void CApplication::ProcessSlow()
5129 g_powerManager.ProcessEvents();
5131 #if defined(TARGET_DARWIN_OSX)
5132 // There is an issue on OS X that several system services ask the cursor to become visible
5133 // during their startup routines. Given that we can't control this, we hack it in by
5135 if (g_Windowing.IsFullScreen())
5136 { // SDL thinks it's hidden
5141 // Temporarely pause pausable jobs when viewing video/picture
5142 int currentWindow = g_windowManager.GetActiveWindow();
5143 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5145 CJobManager::GetInstance().PauseJobs();
5149 CJobManager::GetInstance().UnPauseJobs();
5152 // Store our file state for use on close()
5155 // Check if we need to activate the screensaver / DPMS.
5156 CheckScreenSaverAndDPMS();
5158 // Check if we need to shutdown (if enabled).
5159 #if defined(TARGET_DARWIN)
5160 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5162 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5168 // check if we should restart the player
5169 CheckDelayedPlayerRestart();
5171 // check if we can unload any unreferenced dlls or sections
5172 if (!m_pPlayer->IsPlayingVideo())
5173 CSectionLoader::UnloadDelayed();
5175 // check for any idle curl connections
5176 g_curlInterface.CheckIdle();
5178 // check for any idle myth sessions
5179 CMythSession::CheckIdle();
5181 #ifdef HAS_FILESYSTEM_HTSP
5182 // check for any idle htsp sessions
5183 HTSP::CHTSPDirectorySession::CheckIdle();
5187 if ( m_pKaraokeMgr )
5188 m_pKaraokeMgr->ProcessSlow();
5191 if (!m_pPlayer->IsPlayingVideo())
5192 g_largeTextureManager.CleanupUnusedImages();
5194 g_TextureManager.FreeUnusedTextures(5000);
5196 #ifdef HAS_DVD_DRIVE
5197 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5198 if (!m_pPlayer->IsPlayingVideo())
5199 m_Autorun->HandleAutorun();
5202 // update upnp server/renderer states
5204 if(UPNP::CUPnP::IsInstantiated())
5205 UPNP::CUPnP::GetInstance()->UpdateState();
5208 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5212 #ifdef HAS_FILESYSTEM_NFS
5213 gNfsConnection.CheckIfIdle();
5216 #ifdef HAS_FILESYSTEM_AFP
5217 gAfpConnection.CheckIfIdle();
5220 #ifdef HAS_FILESYSTEM_SFTP
5221 CSFTPSessionManager::ClearOutIdleSessions();
5224 g_mediaManager.ProcessEvents();
5227 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5228 g_RemoteControl.Initialize();
5231 if (!m_pPlayer->IsPlayingVideo() &&
5232 CSettings::Get().GetInt("general.addonupdates") != AUTO_UPDATES_NEVER)
5233 CAddonInstaller::Get().UpdateRepos();
5235 CAEFactory::GarbageCollect();
5237 // if we don't render the gui there's no reason to start the screensaver.
5238 // that way the screensaver won't kick in if we maximize the XBMC window
5239 // after the screensaver start time.
5241 ResetScreenSaverTimer();
5244 // Global Idle Time in Seconds
5245 // idle time will be resetet if on any OnKey()
5246 // int return: system Idle time in seconds! 0 is no idle!
5247 int CApplication::GlobalIdleTime()
5249 if(!m_idleTimer.IsRunning())
5252 m_idleTimer.StartZero();
5254 return (int)m_idleTimer.GetElapsedSeconds();
5257 float CApplication::NavigationIdleTime()
5259 if (!m_navigationTimer.IsRunning())
5261 m_navigationTimer.Stop();
5262 m_navigationTimer.StartZero();
5264 return m_navigationTimer.GetElapsedSeconds();
5267 void CApplication::DelayedPlayerRestart()
5269 m_restartPlayerTimer.StartZero();
5272 void CApplication::CheckDelayedPlayerRestart()
5274 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5276 m_restartPlayerTimer.Stop();
5277 m_restartPlayerTimer.Reset();
5282 void CApplication::Restart(bool bSamePosition)
5284 // this function gets called when the user changes a setting (like noninterleaved)
5285 // and which means we gotta close & reopen the current playing file
5287 // first check if we're playing a file
5288 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5291 if( !m_pPlayer->HasPlayer() )
5296 // do we want to return to the current position in the file
5297 if (false == bSamePosition)
5299 // no, then just reopen the file and start at the beginning
5300 PlayFile(*m_itemCurrentFile, true);
5304 // else get current position
5305 double time = GetTime();
5307 // get player state, needed for dvd's
5308 CStdString state = m_pPlayer->GetPlayerState();
5310 // set the requested starttime
5311 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5314 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5315 m_pPlayer->SetPlayerState(state);
5318 const std::string& CApplication::CurrentFile()
5320 return m_itemCurrentFile->GetPath();
5323 CFileItem& CApplication::CurrentFileItem()
5325 return *m_itemCurrentFile;
5328 CFileItem& CApplication::CurrentUnstackedItem()
5330 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5331 return *(*m_currentStack)[m_currentStackPosition];
5333 return *m_itemCurrentFile;
5336 void CApplication::ShowVolumeBar(const CAction *action)
5338 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5343 volumeBar->OnAction(*action);
5347 bool CApplication::IsMuted() const
5349 if (g_peripherals.IsMuted())
5351 return CAEFactory::IsMuted();
5354 void CApplication::ToggleMute(void)
5362 void CApplication::SetMute(bool mute)
5364 if (m_muted != mute)
5371 void CApplication::Mute()
5373 if (g_peripherals.Mute())
5376 CAEFactory::SetMute(true);
5381 void CApplication::UnMute()
5383 if (g_peripherals.UnMute())
5386 CAEFactory::SetMute(false);
5391 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5393 float hardwareVolume = iValue;
5396 hardwareVolume /= 100.0f;
5398 SetHardwareVolume(hardwareVolume);
5402 void CApplication::SetHardwareVolume(float hardwareVolume)
5404 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5405 m_volumeLevel = hardwareVolume;
5407 CAEFactory::SetVolume(hardwareVolume);
5410 float CApplication::GetVolume(bool percentage /* = true */) const
5414 // converts the hardware volume to a percentage
5415 return m_volumeLevel * 100.0f;
5418 return m_volumeLevel;
5421 void CApplication::VolumeChanged() const
5423 CVariant data(CVariant::VariantTypeObject);
5424 data["volume"] = GetVolume();
5425 data["muted"] = m_muted;
5426 CAnnouncementManager::Get().Announce(Application, "xbmc", "OnVolumeChanged", data);
5428 // if player has volume control, set it.
5429 if (m_pPlayer->ControlsVolume())
5431 m_pPlayer->SetVolume(m_volumeLevel);
5432 m_pPlayer->SetMute(m_muted);
5436 int CApplication::GetSubtitleDelay() const
5438 // converts subtitle delay to a percentage
5439 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5442 int CApplication::GetAudioDelay() const
5444 // converts audio delay to a percentage
5445 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5448 // Returns the total time in seconds of the current media. Fractional
5449 // portions of a second are possible - but not necessarily supported by the
5450 // player class. This returns a double to be consistent with GetTime() and
5452 double CApplication::GetTotalTime() const
5456 if (m_pPlayer->IsPlaying())
5458 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5459 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5461 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5467 void CApplication::StopShutdownTimer()
5469 if (m_shutdownTimer.IsRunning())
5470 m_shutdownTimer.Stop();
5473 void CApplication::ResetShutdownTimers()
5475 // reset system shutdown timer
5476 m_shutdownTimer.StartZero();
5478 // delete custom shutdown timer
5479 if (g_alarmClock.HasAlarm("shutdowntimer"))
5480 g_alarmClock.Stop("shutdowntimer", true);
5483 // Returns the current time in seconds of the currently playing media.
5484 // Fractional portions of a second are possible. This returns a double to
5485 // be consistent with GetTotalTime() and SeekTime().
5486 double CApplication::GetTime() const
5490 if (m_pPlayer->IsPlaying())
5492 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5494 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5495 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5498 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5504 // Sets the current position of the currently playing media to the specified
5505 // time in seconds. Fractional portions of a second are valid. The passed
5506 // time is the time offset from the beginning of the file as opposed to a
5507 // delta from the current position. This method accepts a double to be
5508 // consistent with GetTime() and GetTotalTime().
5509 void CApplication::SeekTime( double dTime )
5511 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5513 if (!m_pPlayer->CanSeek()) return;
5514 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5516 // find the item in the stack we are seeking to, and load the new
5517 // file if necessary, and calculate the correct seek within the new
5518 // file. Otherwise, just fall through to the usual routine if the
5519 // time is higher than our total time.
5520 for (int i = 0; i < m_currentStack->Size(); i++)
5522 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5524 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5525 if (m_currentStackPosition == i)
5526 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5528 { // seeking to a new file
5529 m_currentStackPosition = i;
5530 CFileItem item(*(*m_currentStack)[i]);
5531 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5532 // don't just call "PlayFile" here, as we are quite likely called from the
5533 // player thread, so we won't be able to delete ourselves.
5534 CApplicationMessenger::Get().PlayFile(item, true);
5540 // convert to milliseconds and perform seek
5541 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5545 float CApplication::GetPercentage() const
5547 if (m_pPlayer->IsPlaying())
5549 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5551 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5552 if (tag.GetDuration() > 0)
5553 return (float)(GetTime() / tag.GetDuration() * 100);
5556 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5558 double totalTime = GetTotalTime();
5559 if (totalTime > 0.0f)
5560 return (float)(GetTime() / totalTime * 100);
5563 return m_pPlayer->GetPercentage();
5568 float CApplication::GetCachePercentage() const
5570 if (m_pPlayer->IsPlaying())
5572 // Note that the player returns a relative cache percentage and we want an absolute percentage
5573 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5575 float stackedTotalTime = (float) GetTotalTime();
5576 // We need to take into account the stack's total time vs. currently playing file's total time
5577 if (stackedTotalTime > 0.0f)
5578 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5581 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5586 void CApplication::SeekPercentage(float percent)
5588 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5590 if (!m_pPlayer->CanSeek()) return;
5591 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5592 SeekTime(percent * 0.01 * GetTotalTime());
5594 m_pPlayer->SeekPercentage(percent);
5598 // SwitchToFullScreen() returns true if a switch is made, else returns false
5599 bool CApplication::SwitchToFullScreen()
5601 // if playing from the video info window, close it first!
5602 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5604 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5605 if (pDialog) pDialog->Close(true);
5608 // don't switch if there is a dialog on screen or the slideshow is active
5609 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5612 // See if we're playing a video, and are in GUI mode
5613 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5615 // then switch to fullscreen mode
5616 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5619 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5620 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5621 { // then switch to visualisation
5622 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5628 void CApplication::Minimize()
5630 g_Windowing.Minimize();
5633 PLAYERCOREID CApplication::GetCurrentPlayer()
5635 return m_pPlayer->GetCurrentPlayer();
5638 void CApplication::UpdateLibraries()
5640 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5642 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5646 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5648 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5653 bool CApplication::IsVideoScanning() const
5655 return m_videoInfoScanner->IsScanning();
5658 bool CApplication::IsMusicScanning() const
5660 return m_musicInfoScanner->IsScanning();
5663 void CApplication::StopVideoScan()
5665 if (m_videoInfoScanner->IsScanning())
5666 m_videoInfoScanner->Stop();
5669 void CApplication::StopMusicScan()
5671 if (m_musicInfoScanner->IsScanning())
5672 m_musicInfoScanner->Stop();
5675 void CApplication::StartVideoCleanup()
5677 if (m_videoInfoScanner->IsScanning())
5680 m_videoInfoScanner->CleanDatabase();
5683 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5685 if (m_videoInfoScanner->IsScanning())
5688 m_videoInfoScanner->ShowDialog(true);
5690 m_videoInfoScanner->Start(strDirectory,scanAll);
5693 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5695 if (m_musicInfoScanner->IsScanning())
5699 { // setup default flags
5700 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5701 flags |= CMusicInfoScanner::SCAN_ONLINE;
5702 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5703 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5706 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5707 m_musicInfoScanner->ShowDialog(true);
5709 m_musicInfoScanner->Start(strDirectory, flags);
5712 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5715 if (m_musicInfoScanner->IsScanning())
5718 m_musicInfoScanner->ShowDialog(true);
5720 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5723 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5726 if (m_musicInfoScanner->IsScanning())
5729 m_musicInfoScanner->ShowDialog(true);
5731 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5734 void CApplication::CheckPlayingProgress()
5736 // check if we haven't rewound past the start of the file
5737 if (m_pPlayer->IsPlaying())
5739 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5749 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5751 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5752 g_application.SeekTime(0);
5758 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5760 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5762 // initial exit conditions
5763 // no songs in playlist just return
5764 if (playlist.size() == 0)
5768 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5771 // setup correct playlist
5772 g_playlistPlayer.ClearPlaylist(iPlaylist);
5774 // if the playlist contains an internet stream, this file will be used
5775 // to generate a thumbnail for musicplayer.cover
5776 g_application.m_strPlayListFile = strPlayList;
5778 // add the items to the playlist player
5779 g_playlistPlayer.Add(iPlaylist, playlist);
5781 // if we have a playlist
5782 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5785 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5786 g_playlistPlayer.Reset();
5787 g_playlistPlayer.Play(track);
5793 bool CApplication::AlwaysProcess(const CAction& action)
5795 // check if this button is mapped to a built-in function
5796 if (!action.GetName().empty())
5798 CStdString builtInFunction;
5799 vector<string> params;
5800 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5801 StringUtils::ToLower(builtInFunction);
5803 // should this button be handled normally or just cancel the screensaver?
5804 if ( builtInFunction.Equals("powerdown")
5805 || builtInFunction.Equals("reboot")
5806 || builtInFunction.Equals("restart")
5807 || builtInFunction.Equals("restartapp")
5808 || builtInFunction.Equals("suspend")
5809 || builtInFunction.Equals("hibernate")
5810 || builtInFunction.Equals("quit")
5811 || builtInFunction.Equals("shutdown"))
5820 bool CApplication::IsCurrentThread() const
5822 return CThread::IsCurrentThread(m_threadID);
5825 void CApplication::SetRenderGUI(bool renderGUI)
5827 if (renderGUI && ! m_renderGUI)
5828 g_windowManager.MarkDirty();
5829 m_renderGUI = renderGUI;
5832 CNetwork& CApplication::getNetwork()
5836 #ifdef HAS_PERFORMANCE_SAMPLE
5837 CPerformanceStats &CApplication::GetPerformanceStats()
5843 bool CApplication::SetLanguage(const CStdString &strLanguage)
5845 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5846 if (strLanguage != strPreviousLanguage)
5848 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
5849 if (!g_langInfo.Load(strLangInfoPath))
5852 CSettings::Get().SetString("locale.language", strLanguage);
5854 if (!g_localizeStrings.Load("special://xbmc/language/", strLanguage))
5857 // also tell our weather and skin to reload as these are localized
5858 g_weatherManager.Refresh();
5859 g_PVRManager.LocalizationChanged();
5866 void CApplication::CloseNetworkShares()
5868 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5870 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5874 #ifdef HAS_FILESYSTEM_NFS
5875 gNfsConnection.Deinit();
5878 #ifdef HAS_FILESYSTEM_AFP
5879 gAfpConnection.Deinit();
5882 #ifdef HAS_FILESYSTEM_SFTP
5883 CSFTPSessionManager::DisconnectAllSessions();