2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "network/Network.h"
22 #include "threads/SystemClock.h"
24 #include "Application.h"
25 #include "interfaces/Builtins.h"
26 #include "utils/Variant.h"
27 #include "utils/Splash.h"
29 #include "utils/Screenshot.h"
32 #include "guilib/TextureManager.h"
33 #include "cores/IPlayer.h"
34 #include "cores/dvdplayer/DVDFileInfo.h"
35 #include "cores/AudioEngine/AEFactory.h"
36 #include "cores/AudioEngine/Utils/AEUtil.h"
37 #include "PlayListPlayer.h"
39 #include "video/Bookmark.h"
40 #include "network/NetworkServices.h"
41 #include "guilib/GUIControlProfiler.h"
42 #include "utils/LangCodeExpander.h"
43 #include "GUIInfoManager.h"
44 #include "playlists/PlayListFactory.h"
45 #include "guilib/GUIFontManager.h"
46 #include "guilib/GUIColorManager.h"
47 #include "guilib/StereoscopicsManager.h"
48 #include "guilib/GUITextLayout.h"
49 #include "addons/Skin.h"
50 #include "interfaces/generic/ScriptInvocationManager.h"
52 #include "interfaces/python/XBPython.h"
54 #include "input/ButtonTranslator.h"
55 #include "guilib/GUIAudioManager.h"
56 #include "GUIPassword.h"
57 #include "input/InertialScrollingHandler.h"
58 #include "ApplicationMessenger.h"
59 #include "SectionLoader.h"
60 #include "cores/DllLoader/DllLoaderContainer.h"
61 #include "GUIUserMessages.h"
62 #include "filesystem/DirectoryCache.h"
63 #include "filesystem/StackDirectory.h"
64 #include "filesystem/SpecialProtocol.h"
65 #include "filesystem/DllLibCurl.h"
66 #include "filesystem/MythSession.h"
67 #include "filesystem/PluginDirectory.h"
68 #ifdef HAS_FILESYSTEM_SAP
69 #include "filesystem/SAPDirectory.h"
71 #ifdef HAS_FILESYSTEM_HTSP
72 #include "filesystem/HTSPDirectory.h"
74 #include "utils/TuxBoxUtil.h"
75 #include "utils/SystemInfo.h"
76 #include "utils/TimeUtils.h"
77 #include "GUILargeTextureManager.h"
78 #include "TextureCache.h"
79 #include "playlists/SmartPlayList.h"
80 #ifdef HAS_FILESYSTEM_RAR
81 #include "filesystem/RarManager.h"
83 #include "playlists/PlayList.h"
84 #include "profiles/ProfilesManager.h"
85 #include "windowing/WindowingFactory.h"
86 #include "powermanagement/PowerManager.h"
87 #include "powermanagement/DPMSSupport.h"
88 #include "settings/SettingAddon.h"
89 #include "settings/Settings.h"
90 #include "settings/AdvancedSettings.h"
91 #include "settings/DisplaySettings.h"
92 #include "settings/MediaSettings.h"
93 #include "settings/MediaSourceSettings.h"
94 #include "settings/SkinSettings.h"
95 #include "guilib/LocalizeStrings.h"
96 #include "utils/CPUInfo.h"
97 #include "utils/RssManager.h"
98 #include "utils/SeekHandler.h"
99 #include "view/ViewStateSettings.h"
101 #include "input/KeyboardStat.h"
102 #include "input/XBMC_vkeys.h"
103 #include "input/MouseStat.h"
109 #if defined(FILESYSTEM) && !defined(TARGET_POSIX)
110 #include "filesystem/FileDAAP.h"
113 #include "network/upnp/UPnP.h"
114 #include "network/upnp/UPnPSettings.h"
115 #include "filesystem/UPnPDirectory.h"
117 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
118 #include "filesystem/SMBDirectory.h"
120 #ifdef HAS_FILESYSTEM_NFS
121 #include "filesystem/NFSFile.h"
123 #ifdef HAS_FILESYSTEM_AFP
124 #include "filesystem/AFPFile.h"
126 #ifdef HAS_FILESYSTEM_SFTP
127 #include "filesystem/SFTPFile.h"
129 #include "PartyModeManager.h"
130 #ifdef HAS_VIDEO_PLAYBACK
131 #include "cores/VideoRenderers/RenderManager.h"
134 #include "music/karaoke/karaokelyricsmanager.h"
135 #include "music/karaoke/GUIDialogKaraokeSongSelector.h"
136 #include "music/karaoke/GUIWindowKaraokeLyrics.h"
138 #include "network/Zeroconf.h"
139 #include "network/ZeroconfBrowser.h"
141 #include "threads/platform/win/Win32Exception.h"
143 #ifdef HAS_EVENT_SERVER
144 #include "network/EventServer.h"
147 #include <dbus/dbus.h>
150 #include "interfaces/json-rpc/JSONRPC.h"
151 #include "network/TCPServer.h"
154 #include "network/AirPlayServer.h"
157 #include "network/AirTunesServer.h"
159 #if defined(HAVE_LIBCRYSTALHD)
160 #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
162 #include "interfaces/AnnouncementManager.h"
163 #include "peripherals/Peripherals.h"
164 #include "peripherals/dialogs/GUIDialogPeripheralManager.h"
165 #include "peripherals/dialogs/GUIDialogPeripheralSettings.h"
166 #include "peripherals/devices/PeripheralImon.h"
167 #include "music/infoscanner/MusicInfoScanner.h"
170 #include "guilib/GUIWindowManager.h"
171 #include "windows/GUIWindowHome.h"
172 #include "settings/windows/GUIWindowSettings.h"
173 #include "windows/GUIWindowFileManager.h"
174 #include "settings/windows/GUIWindowSettingsCategory.h"
175 #include "music/windows/GUIWindowMusicPlaylist.h"
176 #include "music/windows/GUIWindowMusicSongs.h"
177 #include "music/windows/GUIWindowMusicNav.h"
178 #include "music/windows/GUIWindowMusicPlaylistEditor.h"
179 #include "video/windows/GUIWindowVideoPlaylist.h"
180 #include "music/dialogs/GUIDialogMusicInfo.h"
181 #include "video/dialogs/GUIDialogVideoInfo.h"
182 #include "video/windows/GUIWindowVideoNav.h"
183 #include "profiles/windows/GUIWindowSettingsProfile.h"
185 #include "rendering/gl/GUIWindowTestPatternGL.h"
188 #include "rendering/dx/GUIWindowTestPatternDX.h"
190 #include "settings/windows/GUIWindowSettingsScreenCalibration.h"
191 #include "programs/GUIWindowPrograms.h"
192 #include "pictures/GUIWindowPictures.h"
193 #include "windows/GUIWindowWeather.h"
194 #include "windows/GUIWindowLoginScreen.h"
195 #include "addons/GUIWindowAddonBrowser.h"
196 #include "music/windows/GUIWindowVisualisation.h"
197 #include "windows/GUIWindowDebugInfo.h"
198 #include "windows/GUIWindowPointer.h"
199 #include "windows/GUIWindowSystemInfo.h"
200 #include "windows/GUIWindowScreensaver.h"
201 #include "windows/GUIWindowScreensaverDim.h"
202 #include "pictures/GUIWindowSlideShow.h"
203 #include "windows/GUIWindowStartup.h"
204 #include "video/windows/GUIWindowFullScreen.h"
205 #include "video/dialogs/GUIDialogVideoOSD.h"
206 #include "music/dialogs/GUIDialogMusicOverlay.h"
207 #include "video/dialogs/GUIDialogVideoOverlay.h"
208 #include "video/VideoInfoScanner.h"
209 #include "video/PlayerController.h"
212 #include "music/dialogs/GUIDialogMusicOSD.h"
213 #include "music/dialogs/GUIDialogVisualisationPresetList.h"
214 #include "dialogs/GUIDialogTextViewer.h"
215 #include "network/GUIDialogNetworkSetup.h"
216 #include "dialogs/GUIDialogMediaSource.h"
217 #include "video/dialogs/GUIDialogVideoSettings.h"
218 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
219 #include "video/dialogs/GUIDialogVideoBookmarks.h"
220 #include "profiles/dialogs/GUIDialogProfileSettings.h"
221 #include "profiles/dialogs/GUIDialogLockSettings.h"
222 #include "settings/dialogs/GUIDialogContentSettings.h"
223 #include "dialogs/GUIDialogBusy.h"
224 #include "dialogs/GUIDialogKeyboardGeneric.h"
225 #include "dialogs/GUIDialogYesNo.h"
226 #include "dialogs/GUIDialogOK.h"
227 #include "dialogs/GUIDialogProgress.h"
228 #include "dialogs/GUIDialogExtendedProgressBar.h"
229 #include "dialogs/GUIDialogSelect.h"
230 #include "dialogs/GUIDialogSeekBar.h"
231 #include "dialogs/GUIDialogKaiToast.h"
232 #include "dialogs/GUIDialogVolumeBar.h"
233 #include "dialogs/GUIDialogMuteBug.h"
234 #include "video/dialogs/GUIDialogFileStacking.h"
235 #include "dialogs/GUIDialogNumeric.h"
236 #include "dialogs/GUIDialogGamepad.h"
237 #include "dialogs/GUIDialogSubMenu.h"
238 #include "dialogs/GUIDialogFavourites.h"
239 #include "dialogs/GUIDialogButtonMenu.h"
240 #include "dialogs/GUIDialogContextMenu.h"
241 #include "dialogs/GUIDialogPlayerControls.h"
242 #include "music/dialogs/GUIDialogSongInfo.h"
243 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
244 #include "dialogs/GUIDialogSmartPlaylistRule.h"
245 #include "pictures/GUIDialogPictureInfo.h"
246 #include "addons/GUIDialogAddonSettings.h"
247 #include "addons/GUIDialogAddonInfo.h"
248 #ifdef HAS_LINUX_NETWORK
249 #include "network/GUIDialogAccessPoints.h"
252 /* PVR related include Files */
253 #include "pvr/PVRManager.h"
254 #include "pvr/timers/PVRTimers.h"
255 #include "pvr/windows/GUIWindowPVR.h"
256 #include "pvr/dialogs/GUIDialogPVRChannelManager.h"
257 #include "pvr/dialogs/GUIDialogPVRChannelsOSD.h"
258 #include "pvr/dialogs/GUIDialogPVRCutterOSD.h"
259 #include "pvr/dialogs/GUIDialogPVRDirectorOSD.h"
260 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
261 #include "pvr/dialogs/GUIDialogPVRGuideInfo.h"
262 #include "pvr/dialogs/GUIDialogPVRGuideOSD.h"
263 #include "pvr/dialogs/GUIDialogPVRGuideSearch.h"
264 #include "pvr/dialogs/GUIDialogPVRRecordingInfo.h"
265 #include "pvr/dialogs/GUIDialogPVRTimerSettings.h"
267 #include "epg/EpgContainer.h"
269 #include "video/dialogs/GUIDialogFullScreenInfo.h"
270 #include "video/dialogs/GUIDialogTeletext.h"
271 #include "dialogs/GUIDialogSlider.h"
272 #include "guilib/GUIControlFactory.h"
273 #include "dialogs/GUIDialogCache.h"
274 #include "dialogs/GUIDialogPlayEject.h"
275 #include "dialogs/GUIDialogMediaFilter.h"
276 #include "video/dialogs/GUIDialogSubtitles.h"
277 #include "utils/XMLUtils.h"
278 #include "addons/AddonInstaller.h"
280 #ifdef HAS_PERFORMANCE_SAMPLE
281 #include "utils/PerformanceSample.h"
283 #define MEASURE_FUNCTION
286 #ifdef TARGET_WINDOWS
288 #include "win32util.h"
291 #include "windowing/X11/XRandR.h"
294 #ifdef TARGET_DARWIN_OSX
295 #include "osx/CocoaInterface.h"
296 #include "osx/XBMCHelper.h"
299 #include "osx/DarwinUtils.h"
304 #include <cdio/logging.h>
308 #include "linux/HALManager.h"
311 #include "storage/MediaManager.h"
312 #include "utils/JobManager.h"
313 #include "utils/SaveFileStateJob.h"
314 #include "utils/AlarmClock.h"
315 #include "utils/RssReader.h"
316 #include "utils/StringUtils.h"
317 #include "utils/Weather.h"
318 #include "DatabaseManager.h"
325 #include "input/linux/LIRC.h"
327 #ifdef HAS_IRSERVERSUITE
328 #include "input/windows/IRServerSuite.h"
331 #if defined(TARGET_WINDOWS)
332 #include "input/windows/WINJoystick.h"
333 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
334 #include "input/SDLJoystick.h"
337 #if defined(TARGET_ANDROID)
338 #include "android/activity/XBMCApp.h"
339 #include "android/activity/AndroidFeatures.h"
340 #include "android/jni/Build.h"
343 #ifdef TARGET_WINDOWS
344 #include "utils/Environment.h"
347 #if defined(HAS_LIBAMCODEC)
348 #include "utils/AMLUtils.h"
352 using namespace ADDON;
353 using namespace XFILE;
355 using namespace MEDIA_DETECT;
357 using namespace PLAYLIST;
358 using namespace VIDEO;
359 using namespace MUSIC_INFO;
360 #ifdef HAS_EVENT_SERVER
361 using namespace EVENTSERVER;
364 using namespace JSONRPC;
366 using namespace ANNOUNCEMENT;
369 using namespace PERIPHERALS;
371 using namespace XbmcThreads;
373 // uncomment this if you want to use release libs in the debug build.
374 // Atm this saves you 7 mb of memory
375 #define USE_RELEASE_LIBS
377 #define MAX_FFWD_SPEED 5
379 //extern IDirectSoundRenderer* m_pAudioDecoder;
380 CApplication::CApplication(void)
381 : m_pPlayer(new CApplicationPlayer)
382 , m_itemCurrentFile(new CFileItem)
383 , m_stackFileItemToUpdate(new CFileItem)
384 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
385 , m_progressTrackingItem(new CFileItem)
386 , m_videoInfoScanner(new CVideoInfoScanner)
387 , m_musicInfoScanner(new CMusicInfoScanner)
388 , m_seekHandler(new CSeekHandler)
389 , m_playerController(new CPlayerController)
392 TiXmlBase::SetCondenseWhiteSpace(false);
393 m_bInhibitIdleShutdown = false;
394 m_bScreenSave = false;
396 m_dpmsIsActive = false;
397 m_dpmsIsManual = false;
398 m_iScreenSaveLock = 0;
399 m_bInitializing = true;
400 m_eForcedNextPlayer = EPC_NONE;
401 m_strPlayListFile = "";
402 m_nextPlaylistItem = -1;
403 m_bPlaybackStarting = false;
404 m_ePlayState = PLAY_STATE_NONE;
405 m_skinReloading = false;
406 m_skinReverting = false;
414 /* for now always keep this around */
416 m_pKaraokeMgr = new CKaraokeLyricsManager();
418 m_currentStack = new CFileItemList;
420 m_bPresentFrame = false;
421 m_bPlatformDirectories = true;
423 m_bStandalone = false;
424 m_bEnableLegacyRes = false;
425 m_bSystemScreenSaverEnable = false;
426 m_pInertialScrollingHandler = new CInertialScrollingHandler();
428 m_Autorun = new CAutorun();
433 m_progressTrackingPlayCountUpdate = false;
434 m_currentStackPosition = 0;
436 m_lastRenderTime = 0;
440 m_volumeLevel = 1.0f;
443 CApplication::~CApplication(void)
445 delete m_musicInfoScanner;
446 delete m_videoInfoScanner;
447 delete &m_progressTrackingVideoResumeBookmark;
451 delete m_currentStack;
454 delete m_pKaraokeMgr;
458 delete m_seekHandler;
459 delete m_playerController;
460 delete m_pInertialScrollingHandler;
464 bool CApplication::OnEvent(XBMC_Event& newEvent)
466 switch(newEvent.type)
469 if (!g_application.m_bStop)
470 CApplicationMessenger::Get().Quit();
473 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
476 g_Keyboard.ProcessKeyUp();
478 case XBMC_MOUSEBUTTONDOWN:
479 case XBMC_MOUSEBUTTONUP:
480 case XBMC_MOUSEMOTION:
481 g_Mouse.HandleEvent(newEvent);
482 g_application.ProcessMouse();
484 case XBMC_VIDEORESIZE:
485 if (!g_application.m_bInitializing &&
486 !g_advancedSettings.m_fullScreen)
488 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
489 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
490 CSettings::Get().SetInt("window.width", newEvent.resize.w);
491 CSettings::Get().SetInt("window.height", newEvent.resize.h);
492 CSettings::Get().Save();
496 #ifdef TARGET_WINDOWS
497 if (g_advancedSettings.m_fullScreen)
499 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
500 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
501 if (newRes != g_graphicsContext.GetVideoResolution())
502 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
507 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
511 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
513 case XBMC_APPCOMMAND:
514 return g_application.OnAppCommand(newEvent.appcommand.action);
517 if (newEvent.touch.action == ACTION_TOUCH_TAP)
518 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
519 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
522 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
523 actionId = newEvent.touch.action;
526 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
527 // change this if we have a dialog up
528 if (g_windowManager.HasModalDialog())
530 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
532 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
533 { // fullscreen info dialog - special case
534 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
536 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
540 if (iWin == WINDOW_FULLSCREEN_VIDEO)
542 // current active window is full screen video.
543 if (g_application.m_pPlayer->IsInMenu())
545 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
546 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_VIDEO_MENU, newEvent.touch.action, newEvent.touch.pointers, actionId);
548 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
550 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
551 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
553 // if no PVR specific action/mapping is found, fall back to default
555 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
559 // in any other case use the fullscreen window section of keymap.xml to map key->action
560 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
563 else // iWin != WINDOW_FULLSCREEN_VIDEO
564 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
571 if ((actionId >= ACTION_TOUCH_TAP && actionId <= ACTION_GESTURE_END)
572 || (actionId >= ACTION_MOUSE_START && actionId <= ACTION_MOUSE_END) )
573 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
575 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
577 // Post an unfocus message for touch device after the action.
578 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
580 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
581 CApplicationMessenger::Get().SendGUIMessage(msg);
586 // Reset the screensaver
587 g_application.ResetScreenSaver();
588 g_application.WakeUpScreenSaverAndDPMS();
589 // Send a mouse motion event with no dx,dy for getting the current guiitem selected
590 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.focus.x, newEvent.focus.y, 0, 0));
596 extern "C" void __stdcall init_emu_environ();
597 extern "C" void __stdcall update_emu_environ();
600 // Utility function used to copy files from the application bundle
601 // over to the user data directory in Application Support/XBMC.
603 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
605 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
606 if (!CFile::Exists(destPath))
608 // need to copy it across
609 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
610 CFile::Cache(srcPath, destPath);
614 void CApplication::Preflight()
617 // call 'dbus_threads_init_default' before any other dbus calls in order to
618 // avoid race conditions with other threads using dbus connections
619 dbus_threads_init_default();
622 // run any platform preflight scripts.
623 #if defined(TARGET_DARWIN_OSX)
624 CStdString install_path;
626 CUtil::GetHomePath(install_path);
627 setenv("XBMC_HOME", install_path.c_str(), 0);
628 install_path += "/tools/darwin/runtime/preflight";
629 system(install_path.c_str());
633 bool CApplication::Create()
635 #if defined(HAS_LINUX_NETWORK)
636 m_network = new CNetworkLinux();
637 #elif defined(HAS_WIN32_NETWORK)
638 m_network = new CNetworkWin32();
640 m_network = new CNetwork();
645 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
647 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
648 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
652 tzset(); // Initialize timezone information variables
655 // Grab a handle to our thread to be used later in identifying the render thread.
656 m_threadID = CThread::GetCurrentThreadId();
659 //floating point precision to 24 bits (faster performance)
660 _controlfp(_PC_24, _MCW_PC);
662 /* install win32 exception translator, win32 exceptions
663 * can now be caught using c++ try catch */
664 win32_exception::install_handler();
668 // only the InitDirectories* for the current platform should return true
669 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
670 bool inited = InitDirectoriesLinux();
672 inited = InitDirectoriesOSX();
674 inited = InitDirectoriesWin32();
676 // copy required files
677 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
678 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
679 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
681 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
683 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
684 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
688 // Init our DllLoaders emu env
691 CProfilesManager::Get().Load();
693 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
694 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetCpuFamily().c_str(),
695 g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness());
697 /* Expand macro before stringify */
698 #define STR_MACRO(x) #x
699 #define XSTR_MACRO(x) STR_MACRO(x)
701 std::string compilerStr;
702 #if defined(__clang__)
703 compilerStr = "Clang " XSTR_MACRO(__clang_major__) "." XSTR_MACRO(__clang_minor__) "." XSTR_MACRO(__clang_patchlevel__);
704 #elif defined (__INTEL_COMPILER)
705 compilerStr = "Intel Compiler " XSTR_MACRO(__INTEL_COMPILER);
706 #elif defined (__GNUC__)
708 /* Note: this will not detect GCC + DragonEgg */
709 compilerStr = "llvm-gcc ";
711 compilerStr = "GCC ";
713 compilerStr += XSTR_MACRO(__GNUC__) "." XSTR_MACRO(__GNUC_MINOR__) "." XSTR_MACRO(__GNUC_PATCHLEVEL__);
714 #elif defined (_MSC_VER)
715 compilerStr = "MSVC " XSTR_MACRO(_MSC_FULL_VER);
717 compilerStr = "unknown compiler";
719 std::string buildType;
722 #elif defined(NDEBUG)
723 buildType = "Release";
725 buildType = "Unknown";
727 CLog::Log(LOGNOTICE, "Using %s XBMC x%d build, compiled " __DATE__ " by %s for %s %s %d-bit %s", buildType.c_str(), g_sysinfo.GetXbmcBitness(), compilerStr.c_str(),
728 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersion().c_str());
730 #if defined(TARGET_DARWIN_OSX)
731 CLog::Log(LOGNOTICE, "Running on Darwin OSX %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
732 #elif defined(TARGET_DARWIN_IOS)
733 CLog::Log(LOGNOTICE, "Running on Darwin iOS %d-bit %s%s", g_sysinfo.GetKernelBitness(), g_sysinfo.IsAppleTV2() ? "(AppleTV2) " : "", g_sysinfo.GetUnameVersion().c_str());
734 #elif defined(TARGET_FREEBSD)
735 CLog::Log(LOGNOTICE, "Running on FreeBSD %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
736 #elif defined(TARGET_ANDROID)
737 CLog::Log(LOGNOTICE, "Running on Android %d-bit API level %d (%s, %s)", g_sysinfo.GetKernelBitness(), CJNIBuild::SDK_INT, g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
738 #elif defined(TARGET_POSIX)
739 CLog::Log(LOGNOTICE, "Running on Linux %d-bit (%s, %s)", g_sysinfo.GetKernelBitness(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
740 #elif defined(TARGET_WINDOWS)
741 CLog::Log(LOGNOTICE, "Running on %s", g_sysinfo.GetKernelVersion().c_str());
744 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", g_cpuInfo.getCPUModel().c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount()==1) ? "" : "s");
745 #if defined(TARGET_WINDOWS)
746 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
747 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
748 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
750 #if defined(TARGET_ANDROID)
752 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
753 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
754 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
758 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
759 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
761 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
763 CSpecialProtocol::LogPaths();
765 CStdString executable = CUtil::ResolveExecutablePath();
766 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
767 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
768 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
769 CRegExp::LogCheckUtf8Support();
770 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
772 CStdString strExecutablePath;
773 CUtil::GetHomePath(strExecutablePath);
776 g_xrandr.LoadCustomModeLinesToAllOutputs();
779 // for python scripts that check the OS
780 #if defined(TARGET_DARWIN)
781 setenv("OS","OS X",true);
782 #elif defined(TARGET_POSIX)
783 setenv("OS","Linux",true);
784 #elif defined(TARGET_WINDOWS)
785 CEnvironment::setenv("OS", "win32");
788 g_powerManager.Initialize();
790 // Load the AudioEngine before settings as they need to query the engine
791 if (!CAEFactory::LoadEngine())
793 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
797 // Initialize default Settings - don't move
798 CLog::Log(LOGNOTICE, "load settings...");
799 if (!CSettings::Get().Initialize())
802 g_powerManager.SetDefaults();
804 // load the actual values
805 if (!CSettings::Get().Load())
807 CLog::Log(LOGFATAL, "unable to load settings");
810 CSettings::Get().SetLoaded();
812 CLog::Log(LOGINFO, "creating subdirectories");
813 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
814 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
815 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
816 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
817 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
818 CProfilesManager::Get().CreateProfileFolders();
820 update_emu_environ();//apply the GUI settings
822 // Load the langinfo to have user charset <-> utf-8 conversion
823 CStdString strLanguage = CSettings::Get().GetString("locale.language");
824 strLanguage[0] = toupper(strLanguage[0]);
826 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
828 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
829 g_langInfo.Load(strLangInfoPath);
830 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
831 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
833 CStdString strLanguagePath = "special://xbmc/language/";
835 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
836 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
838 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
842 // start the AudioEngine
843 if (!CAEFactory::StartEngine())
845 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
849 // restore AE's previous volume state
850 SetHardwareVolume(m_volumeLevel);
851 CAEFactory::SetMute (m_muted);
852 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
854 // initialize m_replayGainSettings
855 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
856 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
857 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
858 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
860 // initialize the addon database (must be before the addon manager is init'd)
861 CDatabaseManager::Get().Initialize(true);
864 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
867 // start-up Addons Framework
868 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
869 if (!CAddonMgr::Get().Init())
871 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
874 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
875 g_RemoteControl.Initialize();
878 // set logging from debug add-on
880 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
882 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
884 g_peripherals.Initialise();
886 // Create the Mouse, Keyboard, Remote, and Joystick devices
887 // Initialize after loading settings to get joystick deadzone setting
888 g_Mouse.Initialize();
889 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
891 g_Keyboard.Initialize();
893 #if defined(TARGET_DARWIN_OSX)
894 // Configure and possible manually start the helper.
895 XBMCHelper::GetInstance().Configure();
898 CUtil::InitRandomSeed();
900 g_mediaManager.Initialize();
902 m_lastFrameTime = XbmcThreads::SystemClockMillis();
903 m_lastRenderTime = m_lastFrameTime;
907 bool CApplication::CreateGUI()
911 CLog::Log(LOGNOTICE, "Setup SDL");
913 /* Clean up on exit, exit on window close and interrupt */
916 uint32_t sdlFlags = 0;
918 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
919 sdlFlags |= SDL_INIT_VIDEO;
922 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
923 sdlFlags |= SDL_INIT_JOYSTICK;
926 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
927 //this might bring the monitor out of standby, so we have to disable it explicitly
928 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
929 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
930 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
936 // for nvidia cards - vsync currently ALWAYS enabled.
937 // the reason is that after screen has been setup changing this env var will make no difference.
938 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
939 setenv("__GL_YIELD", "USLEEP", 0);
942 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
943 g_Windowing.EnableSystemScreenSaver(false);
946 if (SDL_Init(sdlFlags) != 0)
948 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
951 #if defined(TARGET_DARWIN)
952 // SDL_Init will install a handler for segfaults, restore the default handler.
953 signal(SIGSEGV, SIG_DFL);
957 // Initialize core peripheral port support. Note: If these parameters
958 // are 0 and NULL, respectively, then the default number and types of
959 // controllers will be initialized.
960 if (!g_Windowing.InitWindowSystem())
962 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
966 // Retrieve the matching resolution based on GUI settings
967 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
968 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
969 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
971 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
972 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
975 // update the window resolution
976 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
978 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
979 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
981 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
983 // Oh uh - doesn't look good for starting in their wanted screenmode
984 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
985 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
992 if (g_advancedSettings.m_splashImage)
994 CStdString strUserSplash = "special://home/media/Splash.png";
995 if (CFile::Exists(strUserSplash))
997 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
998 m_splash = new CSplash(strUserSplash);
1002 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1003 m_splash = new CSplash("special://xbmc/media/Splash.png");
1008 // The key mappings may already have been loaded by a peripheral
1009 CLog::Log(LOGINFO, "load keymapping");
1010 if (!CButtonTranslator::GetInstance().Load())
1013 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1014 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1017 info.strMode.c_str());
1018 g_windowManager.Initialize();
1023 bool CApplication::InitWindow()
1025 #ifdef TARGET_DARWIN_OSX
1026 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1027 // fixes the white screen of death if starting fullscreen and switching to windowed.
1028 bool bFullScreen = false;
1029 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1031 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1035 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1036 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1038 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1043 if (!g_Windowing.InitRenderSystem())
1045 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1048 // set GUI res and force the clear of the screen
1049 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1053 bool CApplication::DestroyWindow()
1055 return g_Windowing.DestroyWindow();
1058 bool CApplication::InitDirectoriesLinux()
1061 The following is the directory mapping for Platform Specific Mode:
1063 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1064 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1065 installations like skins, screensavers, etc.
1067 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1068 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1069 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1070 special://profile/ => [read-write] current profile's userdata directory.
1071 Generally special://masterprofile for the master profile or
1072 special://masterprofile/profiles/<profile_name> for other profiles.
1074 NOTE: All these root directories are lowercase. Some of the sub-directories
1075 might be mixed case.
1078 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1079 CStdString userName;
1081 userName = getenv("USER");
1085 CStdString userHome;
1087 userHome = getenv("HOME");
1091 CStdString xbmcBinPath, xbmcPath;
1092 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1093 xbmcPath = getenv("XBMC_HOME");
1095 if (xbmcPath.empty())
1097 xbmcPath = xbmcBinPath;
1098 /* Check if xbmc binaries and arch independent data files are being kept in
1099 * separate locations. */
1100 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1102 /* Attempt to locate arch independent data files. */
1103 CUtil::GetHomePath(xbmcPath);
1104 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1106 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1112 /* Set some environment variables */
1113 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1114 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1116 if (m_bPlatformDirectories)
1118 // map our special drives
1119 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1120 CSpecialProtocol::SetXBMCPath(xbmcPath);
1121 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1122 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1124 CStdString strTempPath = userHome;
1125 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1126 if (getenv("XBMC_TEMP"))
1127 strTempPath = getenv("XBMC_TEMP");
1128 CSpecialProtocol::SetTempPath(strTempPath);
1130 URIUtils::AddSlashAtEnd(strTempPath);
1131 g_advancedSettings.m_logFolder = strTempPath;
1138 URIUtils::AddSlashAtEnd(xbmcPath);
1139 g_advancedSettings.m_logFolder = xbmcPath;
1141 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1142 CSpecialProtocol::SetXBMCPath(xbmcPath);
1143 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1144 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1146 CStdString strTempPath = xbmcPath;
1147 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1148 if (getenv("XBMC_TEMP"))
1149 strTempPath = getenv("XBMC_TEMP");
1150 CSpecialProtocol::SetTempPath(strTempPath);
1153 URIUtils::AddSlashAtEnd(strTempPath);
1154 g_advancedSettings.m_logFolder = strTempPath;
1163 bool CApplication::InitDirectoriesOSX()
1165 #if defined(TARGET_DARWIN)
1166 CStdString userName;
1168 userName = getenv("USER");
1172 CStdString userHome;
1174 userHome = getenv("HOME");
1178 CStdString xbmcPath;
1179 CUtil::GetHomePath(xbmcPath);
1180 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1182 #if defined(TARGET_DARWIN_IOS)
1183 CStdString fontconfigPath;
1184 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1185 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1188 // setup path to our internal dylibs so loader can find them
1189 CStdString frameworksPath = CUtil::GetFrameworksPath();
1190 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1192 // OSX always runs with m_bPlatformDirectories == true
1193 if (m_bPlatformDirectories)
1195 // map our special drives
1196 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1197 CSpecialProtocol::SetXBMCPath(xbmcPath);
1198 #if defined(TARGET_DARWIN_IOS)
1199 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1200 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1202 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1203 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1206 // location for temp files
1207 #if defined(TARGET_DARWIN_IOS)
1208 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1210 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1211 CDirectory::Create(strTempPath);
1212 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1214 CSpecialProtocol::SetTempPath(strTempPath);
1216 // xbmc.log file location
1217 #if defined(TARGET_DARWIN_IOS)
1218 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1220 strTempPath = userHome + "/Library/Logs";
1222 URIUtils::AddSlashAtEnd(strTempPath);
1223 g_advancedSettings.m_logFolder = strTempPath;
1229 URIUtils::AddSlashAtEnd(xbmcPath);
1230 g_advancedSettings.m_logFolder = xbmcPath;
1232 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1233 CSpecialProtocol::SetXBMCPath(xbmcPath);
1234 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1235 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1237 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1238 CSpecialProtocol::SetTempPath(strTempPath);
1240 URIUtils::AddSlashAtEnd(strTempPath);
1241 g_advancedSettings.m_logFolder = strTempPath;
1250 bool CApplication::InitDirectoriesWin32()
1252 #ifdef TARGET_WINDOWS
1253 CStdString xbmcPath;
1255 CUtil::GetHomePath(xbmcPath);
1256 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1257 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1258 CSpecialProtocol::SetXBMCPath(xbmcPath);
1260 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1262 g_advancedSettings.m_logFolder = strWin32UserFolder;
1263 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1264 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1265 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1267 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1271 // Expand the DLL search path with our directories
1272 CWIN32Util::ExtendDllPath();
1280 void CApplication::CreateUserDirs()
1282 CDirectory::Create("special://home/");
1283 CDirectory::Create("special://home/addons");
1284 CDirectory::Create("special://home/addons/packages");
1285 CDirectory::Create("special://home/media");
1286 CDirectory::Create("special://home/sounds");
1287 CDirectory::Create("special://home/system");
1288 CDirectory::Create("special://masterprofile/");
1289 CDirectory::Create("special://temp/");
1290 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1293 bool CApplication::Initialize()
1295 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1296 // turn off cdio logging
1297 cdio_loglevel_default = CDIO_LOG_ERROR;
1300 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1301 // must create these here. Ideally this should be using special://home/ and
1302 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1303 if (!m_bPlatformDirectories)
1306 CDirectory::Create("special://xbmc/language");
1307 CDirectory::Create("special://xbmc/addons");
1308 CDirectory::Create("special://xbmc/sounds");
1311 // Load curl so curl_global_init gets called before any service threads
1312 // are started. Unloading will have no effect as curl is never fully unloaded.
1313 // To quote man curl_global_init:
1314 // "This function is not thread safe. You must not call it when any other
1315 // thread in the program (i.e. a thread sharing the same memory) is running.
1316 // This doesn't just mean no other thread that is using libcurl. Because
1317 // curl_global_init() calls functions of other libraries that are similarly
1318 // thread unsafe, it could conflict with any other thread that
1319 // uses these other libraries."
1320 g_curlInterface.Load();
1321 g_curlInterface.Unload();
1323 // initialize (and update as needed) our databases
1324 CDatabaseManager::Get().Initialize();
1328 // Init DPMS, before creating the corresponding setting control.
1329 m_dpms = new DPMSSupport();
1330 if (g_windowManager.Initialized())
1332 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1334 g_windowManager.Add(new CGUIWindowHome);
1335 g_windowManager.Add(new CGUIWindowPrograms);
1336 g_windowManager.Add(new CGUIWindowPictures);
1337 g_windowManager.Add(new CGUIWindowFileManager);
1338 g_windowManager.Add(new CGUIWindowSettings);
1339 g_windowManager.Add(new CGUIWindowSystemInfo);
1341 g_windowManager.Add(new CGUIWindowTestPatternGL);
1344 g_windowManager.Add(new CGUIWindowTestPatternDX);
1346 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1347 g_windowManager.Add(new CGUIWindowSettingsCategory);
1348 g_windowManager.Add(new CGUIWindowVideoNav);
1349 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1350 g_windowManager.Add(new CGUIWindowLoginScreen);
1351 g_windowManager.Add(new CGUIWindowSettingsProfile);
1352 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1353 g_windowManager.Add(new CGUIWindowAddonBrowser);
1354 g_windowManager.Add(new CGUIWindowScreensaverDim);
1355 g_windowManager.Add(new CGUIWindowDebugInfo);
1356 g_windowManager.Add(new CGUIWindowPointer);
1357 g_windowManager.Add(new CGUIDialogYesNo);
1358 g_windowManager.Add(new CGUIDialogProgress);
1359 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1360 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1361 g_windowManager.Add(new CGUIDialogVolumeBar);
1362 g_windowManager.Add(new CGUIDialogSeekBar);
1363 g_windowManager.Add(new CGUIDialogSubMenu);
1364 g_windowManager.Add(new CGUIDialogContextMenu);
1365 g_windowManager.Add(new CGUIDialogKaiToast);
1366 g_windowManager.Add(new CGUIDialogNumeric);
1367 g_windowManager.Add(new CGUIDialogGamepad);
1368 g_windowManager.Add(new CGUIDialogButtonMenu);
1369 g_windowManager.Add(new CGUIDialogMuteBug);
1370 g_windowManager.Add(new CGUIDialogPlayerControls);
1372 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1373 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1375 g_windowManager.Add(new CGUIDialogSlider);
1376 g_windowManager.Add(new CGUIDialogMusicOSD);
1377 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1378 g_windowManager.Add(new CGUIDialogVideoSettings);
1379 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1380 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1381 // Don't add the filebrowser dialog - it's created and added when it's needed
1382 g_windowManager.Add(new CGUIDialogNetworkSetup);
1383 g_windowManager.Add(new CGUIDialogMediaSource);
1384 g_windowManager.Add(new CGUIDialogProfileSettings);
1385 g_windowManager.Add(new CGUIDialogFavourites);
1386 g_windowManager.Add(new CGUIDialogSongInfo);
1387 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1388 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1389 g_windowManager.Add(new CGUIDialogBusy);
1390 g_windowManager.Add(new CGUIDialogPictureInfo);
1391 g_windowManager.Add(new CGUIDialogAddonInfo);
1392 g_windowManager.Add(new CGUIDialogAddonSettings);
1393 #ifdef HAS_LINUX_NETWORK
1394 g_windowManager.Add(new CGUIDialogAccessPoints);
1397 g_windowManager.Add(new CGUIDialogLockSettings);
1399 g_windowManager.Add(new CGUIDialogContentSettings);
1401 g_windowManager.Add(new CGUIDialogPlayEject);
1403 g_windowManager.Add(new CGUIDialogPeripheralManager);
1404 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1406 g_windowManager.Add(new CGUIDialogMediaFilter);
1407 g_windowManager.Add(new CGUIDialogSubtitles);
1409 g_windowManager.Add(new CGUIWindowMusicPlayList);
1410 g_windowManager.Add(new CGUIWindowMusicSongs);
1411 g_windowManager.Add(new CGUIWindowMusicNav);
1412 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1414 /* Load PVR related Windows and Dialogs */
1415 g_windowManager.Add(new CGUIDialogTeletext);
1416 g_windowManager.Add(new CGUIWindowPVR);
1417 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1418 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1419 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1420 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1421 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1422 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1423 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1424 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1425 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1426 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1428 g_windowManager.Add(new CGUIDialogSelect);
1429 g_windowManager.Add(new CGUIDialogMusicInfo);
1430 g_windowManager.Add(new CGUIDialogOK);
1431 g_windowManager.Add(new CGUIDialogVideoInfo);
1432 g_windowManager.Add(new CGUIDialogTextViewer);
1433 g_windowManager.Add(new CGUIWindowFullScreen);
1434 g_windowManager.Add(new CGUIWindowVisualisation);
1435 g_windowManager.Add(new CGUIWindowSlideShow);
1436 g_windowManager.Add(new CGUIDialogFileStacking);
1438 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1441 g_windowManager.Add(new CGUIDialogVideoOSD);
1442 g_windowManager.Add(new CGUIDialogMusicOverlay);
1443 g_windowManager.Add(new CGUIDialogVideoOverlay);
1444 g_windowManager.Add(new CGUIWindowScreensaver);
1445 g_windowManager.Add(new CGUIWindowWeather);
1446 g_windowManager.Add(new CGUIWindowStartup);
1448 /* window id's 3000 - 3100 are reserved for python */
1450 // Make sure we have at least the default skin
1451 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1452 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1454 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1458 if (g_advancedSettings.m_splashImage)
1459 SAFE_DELETE(m_splash);
1461 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1462 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1463 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1465 g_passwordManager.CheckStartUpLock();
1468 // check if we should use the login screen
1469 if (CProfilesManager::Get().UsingLoginScreen())
1470 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1474 CJSONRPC::Initialize();
1476 ADDON::CAddonMgr::Get().StartServices(false);
1477 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1479 g_windowManager.ActivateWindow(WINDOW_HOME);
1480 StartPVRManager(true);
1484 StartPVRManager(false);
1485 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1488 CStereoscopicsManager::Get().Initialize();
1492 else //No GUI Created
1495 CJSONRPC::Initialize();
1497 ADDON::CAddonMgr::Get().StartServices(false);
1500 g_sysinfo.Refresh();
1502 CLog::Log(LOGINFO, "removing tempfiles");
1503 CUtil::RemoveTempFiles();
1505 if (!CProfilesManager::Get().UsingLoginScreen())
1511 m_slowTimer.StartZero();
1513 #if defined(HAVE_LIBCRYSTALHD)
1514 CCrystalHD::GetInstance();
1517 CAddonMgr::Get().StartServices(true);
1519 CLog::Log(LOGNOTICE, "initialize done");
1521 m_bInitializing = false;
1523 // reset our screensaver (starts timers etc.)
1526 #ifdef HAS_SDL_JOYSTICK
1527 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1528 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1534 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1540 // the callback will take care of starting/stopping webserver
1541 ret = CSettings::Get().SetBool("services.webserver", bStart);
1544 case ES_AIRPLAYSERVER:
1545 // the callback will take care of starting/stopping airplay
1546 ret = CSettings::Get().SetBool("services.airplay", bStart);
1549 case ES_JSONRPCSERVER:
1550 // the callback will take care of starting/stopping jsonrpc server
1551 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1555 // the callback will take care of starting/stopping upnp server
1556 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1559 case ES_UPNPRENDERER:
1560 // the callback will take care of starting/stopping upnp renderer
1561 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1564 case ES_EVENTSERVER:
1565 // the callback will take care of starting/stopping event server
1566 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1570 // the callback will take care of starting/stopping zeroconf
1571 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1578 CSettings::Get().Save();
1583 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1585 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1586 g_PVRManager.Start(true, bOpenPVRWindow);
1589 void CApplication::StopPVRManager()
1591 CLog::Log(LOGINFO, "stopping PVRManager");
1592 if (g_PVRManager.IsPlaying())
1594 g_PVRManager.Stop();
1595 g_EpgContainer.Stop();
1598 void CApplication::StartServices()
1600 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1601 // Start Thread for DVD Mediatype detection
1602 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1603 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1606 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1607 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1608 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1609 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1610 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1611 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1614 void CApplication::StopServices()
1616 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1618 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1619 CLog::Log(LOGNOTICE, "stop dvd detect media");
1620 m_DetectDVDType.StopThread();
1623 g_peripherals.Clear();
1626 void CApplication::OnSettingChanged(const CSetting *setting)
1628 if (setting == NULL)
1631 const std::string &settingId = setting->GetId();
1632 if (settingId == "lookandfeel.skin" ||
1633 settingId == "lookandfeel.font" ||
1634 settingId == "lookandfeel.skincolors")
1636 // if the skin changes and the current theme is not the default one, reset
1637 // the theme to the default value (which will also change lookandfeel.skincolors
1638 // which in turn will reload the skin. Similarly, if the current skin font is not
1639 // the default, reset it as well.
1640 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1641 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1642 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1643 CSettings::Get().SetString("lookandfeel.font", "Default");
1646 std::string builtin("ReloadSkin");
1647 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1648 builtin += "(confirm)";
1649 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1652 else if (settingId == "lookandfeel.skintheme")
1654 // also set the default color theme
1655 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1656 URIUtils::RemoveExtension(colorTheme);
1657 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1658 colorTheme = "defaults";
1660 // check if we have to change the skin color
1661 // if yes, it will trigger a call to ReloadSkin() in
1662 // it's OnSettingChanged() callback
1663 // if no we have to call ReloadSkin() ourselves
1664 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1665 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1667 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1669 else if (settingId == "lookandfeel.skinzoom")
1671 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1672 g_windowManager.SendThreadMessage(msg);
1674 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1676 // AE is master of audio settings and needs to be informed first
1677 CAEFactory::OnSettingsChange(settingId);
1679 if (settingId == "audiooutput.guisoundmode")
1681 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1683 // this tells player whether to open an audio stream passthrough or PCM
1684 // if this is changed, audio stream has to be reopened
1685 else if (settingId == "audiooutput.passthrough")
1687 CApplicationMessenger::Get().MediaRestart(false);
1690 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1691 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1692 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1693 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1694 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1695 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1696 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1697 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1700 void CApplication::OnSettingAction(const CSetting *setting)
1702 if (setting == NULL)
1705 const std::string &settingId = setting->GetId();
1706 if (settingId == "lookandfeel.skinsettings")
1707 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1708 else if (settingId == "screensaver.preview")
1709 ActivateScreenSaver(true);
1710 else if (settingId == "screensaver.settings")
1713 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1714 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1716 else if (settingId == "videoscreen.guicalibration")
1717 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1718 else if (settingId == "videoscreen.testpattern")
1719 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1722 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1724 if (setting == NULL)
1727 const std::string &settingId = setting->GetId();
1728 if (settingId == "audiooutput.channels")
1730 // check if this is an update from Eden
1731 if (oldSettingId != NULL && oldSettingNode != NULL &&
1732 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1735 CSettingInt* channels = (CSettingInt*)setting;
1736 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1737 ret = channels->SetValue(channels->GetValue() + 1);
1739 // let's just reset the audiodevice settings as well
1740 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1741 CAEFactory::VerifyOutputDevice(audiodevice, false);
1742 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1747 else if (settingId == "screensaver.mode")
1749 CSettingString *screensaverMode = (CSettingString*)setting;
1750 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1751 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1752 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1754 else if (settingId == "scrapers.musicvideosdefault")
1756 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1757 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1759 musicvideoScraper->Reset();
1763 #if defined(HAS_LIBAMCODEC)
1764 else if (settingId == "videoplayer.useamcodec")
1766 // Do not permit amcodec to be used on non-aml platforms.
1767 // The setting will be hidden but the default value is true,
1768 // so change it to false.
1771 CSettingBool *useamcodec = (CSettingBool*)setting;
1772 useamcodec->SetValue(false);
1776 #if defined(TARGET_ANDROID)
1777 else if (settingId == "videoplayer.usemediacodec")
1779 // Do not permit MediaCodec to be used Android platforms that do not have it.
1780 // The setting will be hidden but the default value is true,
1781 // so change it to false.
1782 if (CAndroidFeatures::GetVersion() < 16)
1784 CSettingBool *usemediacodec = (CSettingBool*)setting;
1785 usemediacodec->SetValue(false);
1788 else if (settingId == "videoplayer.usestagefright")
1790 CSettingBool *usestagefright = (CSettingBool*)setting;
1791 usestagefright->SetValue(false);
1798 bool CApplication::OnSettingsSaving() const
1800 // don't save settings when we're busy stopping the application
1801 // a lot of screens try to save settings on deinit and deinit is
1802 // called for every screen when the application is stopping
1809 void CApplication::ReloadSkin(bool confirm/*=false*/)
1811 m_skinReloading = false;
1812 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1814 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1815 g_windowManager.SendMessage(msg);
1817 // Reload the skin, restoring the previously focused control. We need this as
1818 // the window unload will reset all control states.
1820 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1822 iCtrlID = pWindow->GetFocusedControlID();
1824 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1828 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1829 if (pWindow && pWindow->HasSaveLastControl())
1831 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1832 pWindow->OnMessage(msg3);
1836 if (!m_skinReverting && confirm)
1839 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1841 m_skinReverting = true;
1842 if (oldSkin.empty())
1843 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1845 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1849 m_skinReverting = false;
1852 bool CApplication::Load(const TiXmlNode *settings)
1854 if (settings == NULL)
1857 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1858 if (audioElement != NULL)
1860 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1861 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1862 m_volumeLevel = VOLUME_MAXIMUM;
1868 bool CApplication::Save(TiXmlNode *settings) const
1870 if (settings == NULL)
1873 TiXmlElement volumeNode("audio");
1874 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1875 if (audioNode == NULL)
1878 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1879 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1884 bool CApplication::LoadSkin(const CStdString& skinID)
1886 if (m_skinReloading)
1890 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1892 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1898 void CApplication::LoadSkin(const SkinPtr& skin)
1900 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1903 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1904 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1909 if (!skin->HasSkinFile("Home.xml"))
1911 // failed to find home.xml
1912 // fallback to default skin
1913 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1915 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1916 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1917 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1922 bool bPreviousPlayingState=false;
1923 bool bPreviousRenderingState=false;
1924 if (g_application.m_pPlayer->IsPlayingVideo())
1926 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1927 if (bPreviousPlayingState)
1928 g_application.m_pPlayer->Pause();
1929 #ifdef HAS_VIDEO_PLAYBACK
1930 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1932 g_windowManager.ActivateWindow(WINDOW_HOME);
1933 bPreviousRenderingState = true;
1937 // close the music and video overlays (they're re-opened automatically later)
1938 CSingleLock lock(g_graphicsContext);
1940 // save the current window details
1941 int currentWindow = g_windowManager.GetActiveWindow();
1942 vector<int> currentModelessWindows;
1943 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1947 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1949 g_SkinInfo->Start();
1951 CLog::Log(LOGINFO, " load fonts for skin...");
1952 g_graphicsContext.SetMediaDir(skin->Path());
1953 g_directoryCache.ClearSubPaths(skin->Path());
1954 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1956 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1957 CStdString strFontSet;
1958 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1960 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1961 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1962 CSettings::Get().Save();
1965 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1967 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1969 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1971 // load in the skin strings
1972 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1973 URIUtils::AddSlashAtEnd(langPath);
1975 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1977 g_SkinInfo->LoadIncludes();
1980 start = CurrentHostCounter();
1982 CLog::Log(LOGINFO, " load new skin...");
1984 // Load the user windows
1988 end = CurrentHostCounter();
1989 freq = CurrentHostFrequency();
1990 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1992 CLog::Log(LOGINFO, " initialize new skin...");
1993 g_windowManager.AddMsgTarget(this);
1994 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1995 g_windowManager.AddMsgTarget(&g_infoManager);
1996 g_windowManager.AddMsgTarget(&g_fontManager);
1997 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1998 g_windowManager.SetCallback(*this);
1999 g_windowManager.Initialize();
2000 CTextureCache::Get().Initialize();
2001 g_audioManager.Enable(true);
2002 g_audioManager.Load();
2004 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
2005 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2007 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2008 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2009 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2010 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2011 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2014 CLog::Log(LOGINFO, " skin loaded...");
2016 // leave the graphics lock
2020 if (currentWindow != WINDOW_INVALID)
2022 g_windowManager.ActivateWindow(currentWindow);
2023 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2025 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2026 if (dialog) dialog->Show();
2030 if (g_application.m_pPlayer->IsPlayingVideo())
2032 if (bPreviousPlayingState)
2033 g_application.m_pPlayer->Pause();
2034 if (bPreviousRenderingState)
2035 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2039 void CApplication::UnloadSkin(bool forReload /* = false */)
2041 m_skinReloading = forReload;
2043 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2045 g_audioManager.Enable(false);
2047 g_windowManager.DeInitialize();
2048 CTextureCache::Get().Deinitialize();
2050 // remove the skin-dependent window
2051 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2053 g_TextureManager.Cleanup();
2054 g_largeTextureManager.CleanupUnusedImages(true);
2056 g_fontManager.Clear();
2058 g_colorManager.Clear();
2060 g_infoManager.Clear();
2062 // The g_SkinInfo boost shared_ptr ought to be reset here
2063 // but there are too many places it's used without checking for NULL
2064 // and as a result a race condition on exit can cause a crash.
2067 bool CApplication::LoadUserWindows()
2069 // Start from wherever home.xml is
2070 std::vector<CStdString> vecSkinPath;
2071 g_SkinInfo->GetSkinPaths(vecSkinPath);
2072 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2074 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2075 CFileItemList items;
2076 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2078 for (int i = 0; i < items.Size(); ++i)
2080 if (items[i]->m_bIsFolder)
2082 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2083 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2085 CXBMCTinyXML xmlDoc;
2086 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2088 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2092 // Root element should be <window>
2093 TiXmlElement* pRootElement = xmlDoc.RootElement();
2094 CStdString strValue = pRootElement->Value();
2095 if (!strValue.Equals("window"))
2097 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2101 // Read the <type> element to get the window type to create
2102 // If no type is specified, create a CGUIWindow as default
2103 CGUIWindow* pWindow = NULL;
2105 if (pRootElement->Attribute("type"))
2106 strType = pRootElement->Attribute("type");
2109 const TiXmlNode *pType = pRootElement->FirstChild("type");
2110 if (pType && pType->FirstChild())
2111 strType = pType->FirstChild()->Value();
2113 int id = WINDOW_INVALID;
2114 if (!pRootElement->Attribute("id", &id))
2116 const TiXmlNode *pType = pRootElement->FirstChild("id");
2117 if (pType && pType->FirstChild())
2118 id = atol(pType->FirstChild()->Value());
2120 CStdString visibleCondition;
2121 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2123 if (strType.Equals("dialog"))
2124 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2125 else if (strType.Equals("submenu"))
2126 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2127 else if (strType.Equals("buttonmenu"))
2128 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2130 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2132 // Check to make sure the pointer isn't still null
2133 if (pWindow == NULL)
2135 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2138 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2143 pWindow->SetVisibleCondition(visibleCondition);
2144 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2145 g_windowManager.AddCustomWindow(pWindow);
2153 bool CApplication::RenderNoPresent()
2157 // DXMERGE: This may have been important?
2158 // g_graphicsContext.AcquireCurrentContext();
2160 g_graphicsContext.Lock();
2162 // dont show GUI when playing full screen video
2163 if (g_graphicsContext.IsFullScreenVideo())
2165 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2166 g_renderManager.Render(true, 0, 255);
2168 // close window overlays
2169 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2170 if (overlay) overlay->Close(true);
2171 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2172 if (overlay) overlay->Close(true);
2176 bool hasRendered = g_windowManager.Render();
2178 g_graphicsContext.Unlock();
2183 float CApplication::GetDimScreenSaverLevel() const
2185 if (!m_bScreenSave || !m_screenSaver ||
2186 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2187 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2188 !m_screenSaver->ID().empty()))
2191 if (!m_screenSaver->GetSetting("level").empty())
2192 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2196 void CApplication::Render()
2198 // do not render if we are stopped or in background
2204 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2206 bool hasRendered = false;
2207 bool limitFrames = false;
2208 unsigned int singleFrameTime = 10; // default limit 100 fps
2212 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2213 // Whether externalplayer is playing and we're unfocused
2214 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2216 m_bPresentFrame = false;
2217 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2219 m_bPresentFrame = g_renderManager.FrameWait(100);
2224 // engage the frame limiter as needed
2225 limitFrames = lowfps || extPlayerActive;
2226 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2227 // perhaps allowing it to be set differently than the UI option??
2228 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2229 limitFrames = true; // not using vsync.
2230 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2231 limitFrames = true; // using vsync, but it isn't working.
2235 if (extPlayerActive)
2237 ResetScreenSaver(); // Prevent screensaver dimming the screen
2238 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2241 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2247 CSingleLock lock(g_graphicsContext);
2248 g_infoManager.UpdateFPS();
2250 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2251 g_Windowing.SetVSync(true);
2252 else if (vsync_mode == VSYNC_ALWAYS)
2253 g_Windowing.SetVSync(true);
2254 else if (vsync_mode != VSYNC_DRIVER)
2255 g_Windowing.SetVSync(false);
2257 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2260 if(!g_Windowing.BeginRender())
2263 g_renderManager.FrameMove();
2265 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2266 if(g_graphicsContext.GetStereoMode())
2268 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2269 if(RenderNoPresent())
2272 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2274 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2275 if(RenderNoPresent())
2278 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2282 if(RenderNoPresent())
2286 g_renderManager.FrameFinish();
2288 g_Windowing.EndRender();
2290 // execute post rendering actions (finalize window closing)
2291 g_windowManager.AfterRender();
2293 // reset our info cache - we do this at the end of Render so that it is
2294 // fresh for the next process(), or after a windowclose animation (where process()
2296 g_infoManager.ResetCache();
2299 unsigned int now = XbmcThreads::SystemClockMillis();
2301 m_lastRenderTime = now;
2303 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2304 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2306 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2307 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2311 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2312 if (limitFrames || !flip)
2315 singleFrameTime = 40; //if not flipping, loop at 25 fps
2317 unsigned int frameTime = now - m_lastFrameTime;
2318 if (frameTime < singleFrameTime)
2319 Sleep(singleFrameTime - frameTime);
2321 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2324 g_graphicsContext.Flip(dirtyRegions);
2325 CTimeUtils::UpdateFrameTime(flip);
2327 g_renderManager.UpdateResolution();
2328 g_renderManager.ManageCaptures();
2331 void CApplication::SetStandAlone(bool value)
2333 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2336 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2337 // The window manager will return true if the event is processed, false otherwise.
2338 // If not already processed, this routine handles global keypresses. It returns
2339 // true if the key has been processed, false otherwise.
2341 bool CApplication::OnKey(const CKey& key)
2344 // Turn the mouse off, as we've just got a keypress from controller or remote
2345 g_Mouse.SetActive(false);
2347 // get the current active window
2348 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2350 // this will be checked for certain keycodes that need
2351 // special handling if the screensaver is active
2352 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2354 // a key has been pressed.
2356 m_idleTimer.StartZero();
2357 bool processKey = AlwaysProcess(action);
2359 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2363 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2364 // do not wake up the screensaver right after switching off the playing device
2365 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2366 ret = CApplicationMessenger::Get().CECToggleState();
2368 ret = CApplicationMessenger::Get().CECStandby();
2369 if (!ret) /* display is switched off */
2375 // allow some keys to be processed while the screensaver is active
2376 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2378 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2382 // change this if we have a dialog up
2383 if (g_windowManager.HasModalDialog())
2385 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2387 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2388 { // fullscreen info dialog - special case
2389 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2391 if (!key.IsAnalogButton())
2392 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2394 if (OnAction(action))
2397 // fallthrough to the main window
2398 iWin = WINDOW_FULLSCREEN_VIDEO;
2400 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2402 // current active window is full screen video.
2403 if (g_application.m_pPlayer->IsInMenu())
2405 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2406 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2408 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2410 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2411 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2413 // if no PVR specific action/mapping is found, fall back to default
2414 if (action.GetID() == 0)
2415 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2419 // in any other case use the fullscreen window section of keymap.xml to map key->action
2420 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2425 // current active window isnt the fullscreen window
2426 // just use corresponding section from keymap.xml
2427 // to map key->action
2429 // first determine if we should use keyboard input directly
2430 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2431 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2434 CGUIControl *control = window->GetFocusedControl();
2437 // If this is an edit control set usekeyboard to true. This causes the
2438 // keypress to be processed directly not through the key mappings.
2439 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2442 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2443 // This causes the keypress to be used for list navigation.
2444 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2450 action = CAction(0); // reset our action
2451 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2453 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2454 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2455 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2456 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2457 action.GetID() == ACTION_MOVE_RIGHT ||
2458 action.GetID() == ACTION_MOVE_UP ||
2459 action.GetID() == ACTION_MOVE_DOWN ||
2460 action.GetID() == ACTION_SELECT_ITEM ||
2461 action.GetID() == ACTION_ENTER ||
2462 action.GetID() == ACTION_PREVIOUS_MENU ||
2463 action.GetID() == ACTION_NAV_BACK))
2465 // the action isn't plain navigation - check for a keyboard-specific keymap
2466 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2467 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2468 action.GetID() == ACTION_BACKSPACE ||
2469 action.GetID() == ACTION_SHIFT ||
2470 action.GetID() == ACTION_SYMBOLS ||
2471 action.GetID() == ACTION_CURSOR_LEFT ||
2472 action.GetID() == ACTION_CURSOR_RIGHT)
2473 action = CAction(0); // don't bother with this action
2476 if (!action.GetID())
2478 // keyboard entry - pass the keys through directly
2479 if (key.GetFromService())
2480 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2483 // Check for paste keypress
2484 #ifdef TARGET_WINDOWS
2485 // In Windows paste is ctrl-V
2486 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2487 #elif defined(TARGET_LINUX)
2488 // In Linux paste is ctrl-V
2489 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2490 #elif defined(TARGET_DARWIN_OSX)
2491 // In OSX paste is cmd-V
2492 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2494 // Placeholder for other operating systems
2497 action = CAction(ACTION_PASTE);
2498 // If the unicode is non-zero the keypress is a non-printing character
2499 else if (key.GetUnicode())
2500 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2501 // The keypress is a non-printing character
2503 action = CAction(key.GetVKey() | KEY_VKEY);
2507 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2509 if (OnAction(action))
2511 // failed to handle the keyboard action, drop down through to standard action
2513 if (key.GetFromService())
2515 if (key.GetButtonCode() != KEY_INVALID)
2516 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2519 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2521 if (!key.IsAnalogButton())
2522 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2524 return ExecuteInputAction(action);
2527 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2528 // This needs to return true if it processed the appcommand or false if it didn't
2529 bool CApplication::OnAppCommand(const CAction &action)
2531 // Reset the screen saver
2534 // If we were currently in the screen saver wake up and don't process the appcommand
2535 if (WakeUpScreenSaverAndDPMS())
2538 // The action ID is the APPCOMMAND code. We need to retrieve the action
2539 // associated with this appcommand from the mapping table.
2540 uint32_t appcmd = action.GetID();
2541 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2542 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2543 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2545 // If we couldn't find an action return false to indicate we have not
2546 // handled this appcommand
2547 if (!appcmdaction.GetID())
2549 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2553 // Process the appcommand
2554 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2555 OnAction(appcmdaction);
2557 // Always return true regardless of whether the action succeeded or not.
2558 // This stops Windows handling the appcommand itself.
2562 bool CApplication::OnAction(const CAction &action)
2564 // special case for switching between GUI & fullscreen mode.
2565 if (action.GetID() == ACTION_SHOW_GUI)
2566 { // Switch to fullscreen mode if we can
2567 if (SwitchToFullScreen())
2569 m_navigationTimer.StartZero();
2574 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2576 g_graphicsContext.ToggleFullScreenRoot();
2580 if (action.IsMouse())
2581 g_Mouse.SetActive(true);
2584 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2586 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2588 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2590 CGUIDialogVideoBookmarks::OnAddBookmark();
2593 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2594 // playing or ACTION_PLAYER_PLAY if we are not playing.
2595 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2597 if (m_pPlayer->IsPlaying())
2598 return OnAction(CAction(ACTION_PAUSE));
2600 return OnAction(CAction(ACTION_PLAYER_PLAY));
2603 //if the action would start or stop inertial scrolling
2604 //by gesture - bypass the normal OnAction handler of current window
2605 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2608 // just pass the action to the current window and let it handle it
2609 if (g_windowManager.OnAction(action))
2611 m_navigationTimer.StartZero();
2616 // handle extra global presses
2618 // screenshot : take a screenshot :)
2619 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2621 CScreenShot::TakeScreenshot();
2624 // built in functions : execute the built-in
2625 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2627 CBuiltins::Execute(action.GetName());
2628 m_navigationTimer.StartZero();
2633 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2635 CButtonTranslator::GetInstance().Clear();
2636 CButtonTranslator::GetInstance().Load();
2639 // show info : Shows the current video or song information
2640 if (action.GetID() == ACTION_SHOW_INFO)
2642 g_infoManager.ToggleShowInfo();
2646 // codec info : Shows the current song, video or picture codec information
2647 if (action.GetID() == ACTION_SHOW_CODEC)
2649 g_infoManager.ToggleShowCodec();
2653 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2655 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2658 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2659 char rating = tag->GetRating();
2660 bool needsUpdate(false);
2661 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2663 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2666 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2668 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2674 if (db.Open()) // OpenForWrite() ?
2676 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2679 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2680 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2681 g_windowManager.SendMessage(msg);
2687 // Now check with the playlist player if action can be handled.
2688 // 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.
2689 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2691 if (g_playlistPlayer.OnAction(action))
2695 // Now check with the player if action can be handled.
2696 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2697 (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)) ||
2698 action.GetID() == ACTION_STOP)
2700 if (m_pPlayer->OnAction(action))
2704 // stop : stops playing current audio song
2705 if (action.GetID() == ACTION_STOP)
2711 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2712 // If so, we just jump to the start of the track.
2713 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2716 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2720 // forward action to g_PVRManager and break if it was able to handle it
2721 if (g_PVRManager.OnAction(action))
2724 // forward action to graphic context and see if it can handle it
2725 if (CStereoscopicsManager::Get().OnAction(action))
2728 if (m_pPlayer->IsPlaying())
2730 // forward channel switches to the player - he knows what to do
2731 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2733 m_pPlayer->OnAction(action);
2737 // pause : pauses current audio song
2738 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2742 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2744 if (!m_pPlayer->IsPaused())
2745 { // unpaused - set the playspeed back to normal
2746 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2748 g_audioManager.Enable(m_pPlayer->IsPaused());
2751 if (!m_pPlayer->IsPaused())
2753 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2754 // if we are playing at normal speed, then allow play to pause
2755 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2757 if (m_pPlayer->GetPlaySpeed() != 1)
2759 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2767 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2769 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2770 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2772 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2774 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2779 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2781 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2784 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2787 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2789 // calculate the speed based on the amount the button is held down
2790 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2791 // returns 0 -> MAX_FFWD_SPEED
2792 int iSpeed = 1 << iPower;
2793 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2795 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2797 CLog::Log(LOGDEBUG,"Resetting playspeed");
2801 // allow play to unpause
2804 if (action.GetID() == ACTION_PLAYER_PLAY)
2806 // unpause, and set the playspeed back to normal
2808 g_audioManager.Enable(m_pPlayer->IsPaused());
2810 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2815 // record current file
2816 if (action.GetID() == ACTION_RECORD)
2818 if (m_pPlayer->CanRecord())
2819 m_pPlayer->Record(!m_pPlayer->IsRecording());
2822 if (m_playerController->OnAction(action))
2827 if (action.GetID() == ACTION_SWITCH_PLAYER)
2829 if(m_pPlayer->IsPlaying())
2831 VECPLAYERCORES cores;
2832 CFileItem item(*m_itemCurrentFile.get());
2833 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2834 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2835 if(core != EPC_NONE)
2837 g_application.m_eForcedNextPlayer = core;
2838 item.m_lStartOffset = (int)(GetTime() * 75);
2839 PlayFile(item, true);
2844 VECPLAYERCORES cores;
2845 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2846 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2847 if(core != EPC_NONE)
2850 g_application.m_eForcedNextPlayer = core;
2851 PlayFile(item, false);
2856 if (g_peripherals.OnAction(action))
2859 if (action.GetID() == ACTION_MUTE)
2865 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2867 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2868 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2870 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2872 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2873 g_windowManager.SendMessage(msg);
2878 // Check for global volume control
2879 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2881 if (!m_pPlayer->IsPassthrough())
2885 float volume = m_volumeLevel;
2886 // Android has steps based on the max available volume level
2887 #if defined(TARGET_ANDROID)
2888 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2890 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2892 if (action.GetRepeat())
2893 step *= action.GetRepeat() * 50; // 50 fps
2895 if (action.GetID() == ACTION_VOLUME_UP)
2896 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2898 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2899 SetVolume(volume, false);
2901 // show visual feedback of volume change...
2902 ShowVolumeBar(&action);
2905 // Check for global seek control
2906 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2908 if (!m_pPlayer->CanSeek()) return false;
2909 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2912 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2914 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2915 CGUIControlProfiler::Instance().Start();
2918 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2920 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2921 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2922 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2923 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2924 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2930 void CApplication::FrameMove(bool processEvents, bool processGUI)
2936 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2937 float frameTime = m_frameTime.GetElapsedSeconds();
2938 m_frameTime.StartZero();
2939 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2940 if( frameTime > 0.5 ) frameTime = 0.5;
2942 if (processGUI && m_renderGUI)
2944 g_graphicsContext.Lock();
2945 // check if there are notifications to display
2946 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2947 if (toast && toast->DoWork())
2949 if (!toast->IsDialogRunning())
2954 g_graphicsContext.Unlock();
2956 CWinEvents::MessagePump();
2958 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2959 // Read the input from a remote
2960 g_RemoteControl.Update();
2963 // process input actions
2964 ProcessRemote(frameTime);
2965 ProcessGamepad(frameTime);
2966 ProcessEventServer(frameTime);
2967 ProcessPeripherals(frameTime);
2968 if (processGUI && m_renderGUI)
2970 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2971 m_seekHandler->Process();
2974 if (processGUI && m_renderGUI)
2977 g_windowManager.Process(CTimeUtils::GetFrameTime());
2978 g_windowManager.FrameMove();
2982 bool CApplication::ProcessGamepad(float frameTime)
2984 #ifdef HAS_SDL_JOYSTICK
2988 int iWin = GetActiveWindowID();
2990 g_Joystick.Update();
2991 if (g_Joystick.GetButton(bid))
2994 m_idleTimer.StartZero();
2997 if (WakeUpScreenSaverAndDPMS())
2999 g_Joystick.Reset(true);
3004 CStdString actionName;
3006 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3008 CAction action(actionID, 1.0f, 0.0f, actionName);
3010 g_Mouse.SetActive(false);
3011 return ExecuteInputAction(action);
3018 if (g_Joystick.GetAxis(bid))
3020 if (g_Joystick.GetAmount() < 0)
3026 CStdString actionName;
3028 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3031 if (WakeUpScreenSaverAndDPMS())
3036 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3038 g_Mouse.SetActive(false);
3039 return ExecuteInputAction(action);
3043 g_Joystick.ResetAxis(abs(bid));
3047 if (g_Joystick.GetHat(bid, position))
3050 m_idleTimer.StartZero();
3053 if (WakeUpScreenSaverAndDPMS())
3060 CStdString actionName;
3063 bid = position<<16|bid;
3065 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3067 CAction action(actionID, 1.0f, 0.0f, actionName);
3069 g_Mouse.SetActive(false);
3070 return ExecuteInputAction(action);
3077 bool CApplication::ProcessRemote(float frameTime)
3079 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3080 if (g_RemoteControl.GetButton())
3082 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3083 g_RemoteControl.Reset();
3090 bool CApplication::ProcessPeripherals(float frameTime)
3093 if (g_peripherals.GetNextKeypress(frameTime, key))
3098 bool CApplication::ProcessMouse()
3102 if (!g_Mouse.IsActive() || !m_AppFocused)
3105 // Get the mouse command ID
3106 uint32_t mousecommand = g_Mouse.GetAction();
3107 if (mousecommand == ACTION_NOOP)
3110 // Reset the screensaver and idle timers
3111 m_idleTimer.StartZero();
3113 if (WakeUpScreenSaverAndDPMS())
3116 // Retrieve the corresponding action
3117 int iWin = GetActiveWindowID();
3118 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3119 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3121 // Deactivate mouse if non-mouse action
3122 if (!mouseaction.IsMouse())
3123 g_Mouse.SetActive(false);
3125 // Consume ACTION_NOOP.
3126 // Some views or dialogs gets closed after any ACTION and
3127 // a sensitive mouse might cause problems.
3128 if (mouseaction.GetID() == ACTION_NOOP)
3131 // If we couldn't find an action return false to indicate we have not
3132 // handled this mouse action
3133 if (!mouseaction.GetID())
3135 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3139 // Log mouse actions except for move and noop
3140 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3141 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3143 // The action might not be a mouse action. For example wheel moves might
3144 // be mapped to volume up/down in mouse.xml. In this case we do not want
3145 // the mouse position saved in the action.
3146 if (!mouseaction.IsMouse())
3147 return OnAction(mouseaction);
3149 // This is a mouse action so we need to record the mouse position
3150 return OnAction(CAction(mouseaction.GetID(),
3151 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3152 (float)g_Mouse.GetX(),
3153 (float)g_Mouse.GetY(),
3154 (float)g_Mouse.GetDX(),
3155 (float)g_Mouse.GetDY(),
3156 mouseaction.GetName()));
3159 bool CApplication::ProcessEventServer(float frameTime)
3161 #ifdef HAS_EVENT_SERVER
3162 CEventServer* es = CEventServer::GetInstance();
3163 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3166 // process any queued up actions
3167 if (es->ExecuteNextAction())
3169 // reset idle timers
3170 m_idleTimer.StartZero();
3172 WakeUpScreenSaverAndDPMS();
3175 // now handle any buttons or axis
3176 std::string joystickName;
3177 bool isAxis = false;
3178 float fAmount = 0.0;
3180 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3181 // when the action exits XBMC
3182 es = CEventServer::GetInstance();
3183 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3185 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3189 if (joystickName.length() > 0)
3193 if (fabs(fAmount) >= 0.08)
3194 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3196 m_lastAxisMap[joystickName].erase(wKeyID);
3199 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3204 if (wKeyID & ES_FLAG_UNICODE)
3206 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3210 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3211 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3212 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3213 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3214 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3215 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3216 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3217 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3219 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3221 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3222 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3223 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3224 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3225 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3226 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3227 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3228 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3229 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3232 key.SetFromService(true);
3237 if (m_lastAxisMap.size() > 0)
3239 // Process all the stored axis.
3240 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3242 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3243 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3249 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3251 XBMC_Event newEvent;
3252 newEvent.type = XBMC_MOUSEMOTION;
3253 newEvent.motion.xrel = 0;
3254 newEvent.motion.yrel = 0;
3255 newEvent.motion.state = 0;
3256 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3257 newEvent.motion.x = (uint16_t)pos.x;
3258 newEvent.motion.y = (uint16_t)pos.y;
3259 OnEvent(newEvent); // had to call this to update g_Mouse position
3260 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3267 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3269 #if defined(HAS_EVENT_SERVER)
3270 m_idleTimer.StartZero();
3272 // Make sure to reset screen saver, mouse.
3274 if (WakeUpScreenSaverAndDPMS())
3277 #ifdef HAS_SDL_JOYSTICK
3280 g_Mouse.SetActive(false);
3282 int iWin = GetActiveWindowID();
3284 CStdString actionName;
3285 bool fullRange = false;
3287 // Translate using regular joystick translator.
3288 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3289 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3291 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3297 bool CApplication::ExecuteInputAction(const CAction &action)
3299 bool bResult = false;
3301 // play sound before the action unless the button is held,
3302 // where we execute after the action as held actions aren't fired every time.
3303 if(action.GetHoldTime())
3305 bResult = OnAction(action);
3307 g_audioManager.PlayActionSound(action);
3311 g_audioManager.PlayActionSound(action);
3312 bResult = OnAction(action);
3317 int CApplication::GetActiveWindowID(void)
3319 // Get the currently active window
3320 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3322 // If there is a dialog active get the dialog id instead
3323 if (g_windowManager.HasModalDialog())
3324 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3326 // If the window is FullScreenVideo check for special cases
3327 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3329 // check if we're in a DVD menu
3330 if(g_application.m_pPlayer->IsInMenu())
3331 iWin = WINDOW_VIDEO_MENU;
3332 // check for LiveTV and switch to it's virtual window
3333 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3334 iWin = WINDOW_FULLSCREEN_LIVETV;
3337 // Return the window id
3341 bool CApplication::Cleanup()
3345 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3346 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3347 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3348 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3349 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3350 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3351 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3352 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3353 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3354 g_windowManager.Delete(WINDOW_FILES);
3355 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3356 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3357 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3358 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3359 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3360 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3361 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3362 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3363 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3364 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3365 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3366 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3367 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3368 g_windowManager.Delete(WINDOW_DIALOG_OK);
3369 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3370 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3371 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3372 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3373 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3374 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3375 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3376 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3377 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3378 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3379 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3380 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3381 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3382 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3383 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3384 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3385 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3386 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3387 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3388 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3389 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3390 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3391 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3393 /* Delete PVR related windows and dialogs */
3394 g_windowManager.Delete(WINDOW_PVR);
3395 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3396 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3397 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3398 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3399 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3400 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3401 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3402 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3403 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3404 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3405 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3406 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3407 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3409 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3410 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3411 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3412 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3413 g_windowManager.Delete(WINDOW_VISUALISATION);
3414 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3415 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3416 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3417 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3418 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3419 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3420 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3421 g_windowManager.Delete(WINDOW_SCREENSAVER);
3422 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3423 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3424 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3425 g_windowManager.Delete(WINDOW_SLIDESHOW);
3426 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3427 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3429 g_windowManager.Delete(WINDOW_HOME);
3430 g_windowManager.Delete(WINDOW_PROGRAMS);
3431 g_windowManager.Delete(WINDOW_PICTURES);
3432 g_windowManager.Delete(WINDOW_WEATHER);
3434 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3435 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3436 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3437 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3438 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3439 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3440 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3441 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3442 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3443 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3445 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3446 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3448 CAddonMgr::Get().DeInit();
3450 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3451 CLog::Log(LOGNOTICE, "closing down remote control service");
3452 g_RemoteControl.Disconnect();
3455 CLog::Log(LOGNOTICE, "unload sections");
3457 #ifdef HAS_PERFORMANCE_SAMPLE
3458 CLog::Log(LOGNOTICE, "performance statistics");
3459 m_perfStats.DumpStats();
3462 // Shutdown as much as possible of the
3463 // application, to reduce the leaks dumped
3464 // to the vc output window before calling
3465 // _CrtDumpMemoryLeaks(). Most of the leaks
3466 // shown are no real leaks, as parts of the app
3467 // are still allocated.
3469 g_localizeStrings.Clear();
3470 g_LangCodeExpander.Clear();
3471 g_charsetConverter.clear();
3472 g_directoryCache.Clear();
3473 CButtonTranslator::GetInstance().Clear();
3474 #ifdef HAS_EVENT_SERVER
3475 CEventServer::RemoveInstance();
3477 DllLoaderContainer::Clear();
3478 g_playlistPlayer.Clear();
3479 CSettings::Get().Uninitialize();
3480 g_advancedSettings.Clear();
3483 CXHandle::DumpObjectTracker();
3485 #ifdef HAS_DVD_DRIVE
3486 CLibcdio::ReleaseInstance();
3489 #if defined(TARGET_ANDROID)
3490 // enable for all platforms once it's safe
3491 g_sectionLoader.UnloadAll();
3493 #ifdef _CRTDBG_MAP_ALLOC
3494 _CrtDumpMemoryLeaks();
3495 while(1); // execution ends
3505 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3510 void CApplication::Stop(int exitCode)
3514 CVariant vExitCode(exitCode);
3515 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3517 SaveFileState(true);
3519 g_alarmClock.StopThread();
3521 if( m_bSystemScreenSaverEnable )
3522 g_Windowing.EnableSystemScreenSaver(true);
3524 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3525 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3527 // Update the settings information (volume, uptime etc. need saving)
3528 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3530 CLog::Log(LOGNOTICE, "Saving settings");
3531 CSettings::Get().Save();
3534 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3537 m_AppFocused = false;
3538 m_ExitCode = exitCode;
3539 CLog::Log(LOGNOTICE, "stop all");
3541 // cancel any jobs from the jobmanager
3542 CJobManager::GetInstance().CancelJobs();
3544 // stop scanning before we kill the network and so on
3545 if (m_musicInfoScanner->IsScanning())
3546 m_musicInfoScanner->Stop();
3548 if (m_videoInfoScanner->IsScanning())
3549 m_videoInfoScanner->Stop();
3551 CApplicationMessenger::Get().Cleanup();
3553 CLog::Log(LOGNOTICE, "stop player");
3554 m_pPlayer->ClosePlayer();
3556 CAnnouncementManager::Deinitialize();
3562 #if HAS_FILESYTEM_DAAP
3563 CLog::Log(LOGNOTICE, "stop daap clients");
3564 g_DaapClient.Release();
3566 #ifdef HAS_FILESYSTEM_SAP
3567 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3568 g_sapsessions.StopThread();
3571 if(CZeroconfBrowser::IsInstantiated())
3573 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3574 CZeroconfBrowser::GetInstance()->Stop();
3575 CZeroconfBrowser::ReleaseInstance();
3579 CLog::Log(LOGNOTICE, "clean cached files!");
3580 #ifdef HAS_FILESYSTEM_RAR
3581 g_RarManager.ClearCache(true);
3584 #ifdef HAS_FILESYSTEM_SFTP
3585 CSFTPSessionManager::DisconnectAllSessions();
3588 CLog::Log(LOGNOTICE, "unload skin");
3591 #if defined(TARGET_DARWIN_OSX)
3592 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3593 XBMCHelper::GetInstance().Stop();
3596 #if defined(HAVE_LIBCRYSTALHD)
3597 CCrystalHD::RemoveInstance();
3600 g_mediaManager.Stop();
3602 // Stop services before unloading Python
3603 CAddonMgr::Get().StopServices(false);
3605 // stop all remaining scripts; must be done after skin has been unloaded,
3606 // not before some windows still need it when deinitializing during skin
3608 CScriptInvocationManager::Get().Uninitialize();
3610 g_Windowing.DestroyRenderSystem();
3611 g_Windowing.DestroyWindow();
3612 g_Windowing.DestroyWindowSystem();
3614 // shutdown the AudioEngine
3615 CAEFactory::Shutdown();
3616 CAEFactory::UnLoadEngine();
3618 CLog::Log(LOGNOTICE, "stopped");
3622 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3625 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3626 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3633 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3635 //If item is a plugin, expand out now and run ourselves again
3636 if (item.IsPlugin())
3638 CFileItem item_new(item);
3639 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3640 return PlayMedia(item_new, iPlaylist);
3643 if (item.IsSmartPlayList())
3645 CFileItemList items;
3646 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3649 CSmartPlaylist smartpl;
3650 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3651 smartpl.OpenAndReadName(item.GetPath());
3653 playlist.Add(items);
3654 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3657 else if (item.IsPlayList() || item.IsInternetStream())
3659 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3661 //is or could be a playlist
3662 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3663 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3668 if (dlgCache->IsCanceled())
3675 if (iPlaylist != PLAYLIST_NONE)
3678 if (item.HasProperty("playlist_starting_track"))
3679 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3680 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3684 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());
3685 if(pPlayList->size())
3686 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3691 //nothing special just play
3692 return PlayFile(item, false) == PLAYBACK_OK;
3696 // For playing a multi-file video. Particularly inefficient
3697 // on startup, as we are required to calculate the length
3698 // of each video, so we open + close each one in turn.
3699 // A faster calculation of video time would improve this
3701 // return value: same with PlayFile()
3702 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3704 if (!item.IsStack())
3705 return PLAYBACK_FAIL;
3709 // case 1: stacked ISOs
3710 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3712 CStackDirectory dir;
3713 CFileItemList movieList;
3714 dir.GetDirectory(item.GetPath(), movieList);
3716 // first assume values passed to the stack
3717 int selectedFile = item.m_lStartPartNumber;
3718 int startoffset = item.m_lStartOffset;
3720 // check if we instructed the stack to resume from default
3721 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3726 CStdString path = item.GetPath();
3727 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3728 path = item.GetProperty("original_listitem_url").asString();
3729 if( dbs.GetResumeBookMark(path, bookmark) )
3731 startoffset = (int)(bookmark.timeInSeconds*75);
3732 selectedFile = bookmark.partNumber;
3737 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3740 // make sure that the selected part is within the boundaries
3741 if (selectedFile <= 0)
3743 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3746 else if (selectedFile > movieList.Size())
3748 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3749 selectedFile = movieList.Size();
3752 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3753 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3754 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3755 *m_stackFileItemToUpdate = item;
3756 return PlayFile(*(movieList[selectedFile - 1]));
3758 // case 2: all other stacks
3761 // see if we have the info in the database
3762 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3763 // then these times will be wrong.
3764 // Also, this is really just a hack for the slow load up times we have
3765 // A much better solution is a fast reader of FPS and fileLength
3766 // that we can use on a file to get it's time.
3768 bool haveTimes(false);
3772 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3773 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3778 // calculate the total time of the stack
3779 CStackDirectory dir;
3780 dir.GetDirectory(item.GetPath(), *m_currentStack);
3782 for (int i = 0; i < m_currentStack->Size(); i++)
3785 (*m_currentStack)[i]->m_lEndOffset = times[i];
3789 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3791 m_currentStack->Clear();
3792 return PLAYBACK_FAIL;
3794 totalTime += duration / 1000;
3795 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3796 times.push_back(totalTime);
3800 double seconds = item.m_lStartOffset / 75.0;
3802 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3803 { // have our times now, so update the dB
3807 dbs.SetStackTimes(item.GetPath(), times);
3809 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3811 // can only resume seek here, not dvdstate
3813 CStdString path = item.GetPath();
3814 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3815 path = item.GetProperty("original_listitem_url").asString();
3816 if( dbs.GetResumeBookMark(path, bookmark) )
3817 seconds = bookmark.timeInSeconds;
3825 *m_itemCurrentFile = item;
3826 m_currentStackPosition = 0;
3827 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3831 // work out where to seek to
3832 for (int i = 0; i < m_currentStack->Size(); i++)
3834 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3836 CFileItem item(*(*m_currentStack)[i]);
3837 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3838 item.m_lStartOffset = (long)(seconds - start) * 75;
3839 m_currentStackPosition = i;
3840 return PlayFile(item, true);
3845 return PlayFile(*(*m_currentStack)[0], true);
3847 return PLAYBACK_FAIL;
3850 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3852 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3853 if (item.GetMimeType().empty())
3854 const_cast<CFileItem&>(item).FillInMimeType();
3858 SaveCurrentFileSettings();
3860 OutputDebugString("new file set audiostream:0\n");
3861 // Switch to default options
3862 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3863 // see if we have saved options in the database
3865 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3866 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3868 *m_itemCurrentFile = item;
3869 m_nextPlaylistItem = -1;
3870 m_currentStackPosition = 0;
3871 m_currentStack->Clear();
3874 CUtil::ClearSubtitles();
3877 if (item.IsDiscStub())
3879 #ifdef HAS_DVD_DRIVE
3880 // Display the Play Eject dialog if there is any optical disc drive
3881 if (g_mediaManager.HasOpticalDrive())
3883 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3884 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3885 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3886 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3890 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3895 if (item.IsPlayList())
3896 return PLAYBACK_FAIL;
3898 if (item.IsPlugin())
3899 { // we modify the item so that it becomes a real URL
3900 CFileItem item_new(item);
3901 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3902 return PlayFile(item_new, false);
3903 return PLAYBACK_FAIL;
3907 if (URIUtils::IsUPnP(item.GetPath()))
3909 CFileItem item_new(item);
3910 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3911 return PlayFile(item_new, false);
3912 return PLAYBACK_FAIL;
3916 // if we have a stacked set of files, we need to setup our stack routines for
3917 // "seamless" seeking and total time of the movie etc.
3918 // will recall with restart set to true
3920 return PlayStack(item, bRestart);
3922 //Is TuxBox, this should probably be moved to CTuxBoxFile
3925 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3927 if(g_tuxboxService.IsRunning())
3928 g_tuxboxService.Stop();
3930 PlayBackRet ret = PLAYBACK_FAIL;
3932 if(g_tuxbox.CreateNewItem(item, item_new))
3935 // Make sure it doesn't have a player
3936 // so we actually select one normally
3937 m_pPlayer->ResetPlayer();
3939 // keep the tuxbox:// url as playing url
3940 // and give the new url to the player
3941 ret = PlayFile(item_new, true);
3942 if(ret == PLAYBACK_OK)
3944 if(!g_tuxboxService.IsRunning())
3945 g_tuxboxService.Start();
3951 CPlayerOptions options;
3953 if( item.HasProperty("StartPercent") )
3955 double fallback = 0.0f;
3956 if(item.GetProperty("StartPercent").isString())
3957 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3958 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3961 PLAYERCOREID eNewCore = EPC_NONE;
3964 // have to be set here due to playstack using this for starting the file
3965 options.starttime = item.m_lStartOffset / 75.0;
3966 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3967 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3969 if( m_eForcedNextPlayer != EPC_NONE )
3970 eNewCore = m_eForcedNextPlayer;
3971 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3972 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3974 eNewCore = m_pPlayer->GetCurrentPlayer();
3978 options.starttime = item.m_lStartOffset / 75.0;
3982 // open the d/b and retrieve the bookmarks for the current movie
3985 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3987 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3989 options.starttime = 0.0f;
3991 CStdString path = item.GetPath();
3992 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3993 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3994 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3995 path = item.GetProperty("original_listitem_url").asString();
3996 if(dbs.GetResumeBookMark(path, bookmark))
3998 options.starttime = bookmark.timeInSeconds;
3999 options.state = bookmark.playerState;
4002 override with information from the actual item if available. We do this as the VFS (eg plugins)
4003 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4004 should the playerState be required, it is fetched from the database.
4005 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4007 if (item.IsResumePointSet())
4008 options.starttime = item.GetCurrentResumeTime();
4010 else if (item.HasVideoInfoTag())
4012 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4014 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4017 dbs.GetBookMarkForEpisode(*tag, bookmark);
4018 options.starttime = bookmark.timeInSeconds;
4019 options.state = bookmark.playerState;
4026 if (m_eForcedNextPlayer != EPC_NONE)
4027 eNewCore = m_eForcedNextPlayer;
4029 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4032 // this really aught to be inside !bRestart, but since PlayStack
4033 // uses that to init playback, we have to keep it outside
4034 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4035 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4036 { // playing from a playlist by the looks
4037 // don't switch to fullscreen if we are not playing the first item...
4038 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4040 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4042 // TODO - this will fail if user seeks back to first file in stack
4043 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4044 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4046 options.fullscreen = false;
4047 // reset this so we don't think we are resuming on seek
4048 m_itemCurrentFile->m_lStartOffset = 0;
4051 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4053 // reset VideoStartWindowed as it's a temp setting
4054 CMediaSettings::Get().SetVideoStartWindowed(false);
4057 //We have to stop parsing a cdg before mplayer is deallocated
4058 // WHY do we have to do this????
4060 m_pKaraokeMgr->Stop();
4064 CSingleLock lock(m_playStateMutex);
4065 // tell system we are starting a file
4066 m_bPlaybackStarting = true;
4068 // for playing a new item, previous playing item's callback may already
4069 // pushed some delay message into the threadmessage list, they are not
4070 // expected be processed after or during the new item playback starting.
4071 // so we clean up previous playing item's playback callback delay messages here.
4072 int previousMsgsIgnoredByNewPlaying[] = {
4073 GUI_MSG_PLAYBACK_STARTED,
4074 GUI_MSG_PLAYBACK_ENDED,
4075 GUI_MSG_PLAYBACK_STOPPED,
4076 GUI_MSG_PLAYLIST_CHANGED,
4077 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4078 GUI_MSG_PLAYLISTPLAYER_STARTED,
4079 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4080 GUI_MSG_QUEUE_NEXT_ITEM,
4083 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4085 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4088 // We should restart the player, unless the previous and next tracks are using
4089 // one of the players that allows gapless playback (paplayer, dvdplayer)
4090 m_pPlayer->ClosePlayerGapless(eNewCore);
4092 // now reset play state to starting, since we already stopped the previous playing item if there is.
4093 // and from now there should be no playback callback from previous playing item be called.
4094 m_ePlayState = PLAY_STATE_STARTING;
4096 m_pPlayer->CreatePlayer(eNewCore, *this);
4098 PlayBackRet iResult;
4099 if (m_pPlayer->HasPlayer())
4101 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4102 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4103 * increase performance on low powered systems (Atom/ARM).
4107 CJobManager::GetInstance().PauseJobs();
4110 // don't hold graphicscontext here since player
4111 // may wait on another thread, that requires gfx
4112 CSingleExit ex(g_graphicsContext);
4114 iResult = m_pPlayer->OpenFile(item, options);
4118 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4119 iResult = PLAYBACK_FAIL;
4122 if(iResult == PLAYBACK_OK)
4124 if (m_pPlayer->GetPlaySpeed() != 1)
4126 int iSpeed = m_pPlayer->GetPlaySpeed();
4127 m_pPlayer->m_iPlaySpeed = 1;
4128 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4131 // if player has volume control, set it.
4132 if (m_pPlayer->ControlsVolume())
4134 m_pPlayer->SetVolume(m_volumeLevel);
4135 m_pPlayer->SetMute(m_muted);
4138 if( m_pPlayer->IsPlayingAudio() )
4140 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4141 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4144 #ifdef HAS_VIDEO_PLAYBACK
4145 else if( m_pPlayer->IsPlayingVideo() )
4147 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4148 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4150 // if player didn't manange to switch to fullscreen by itself do it here
4151 if( options.fullscreen && g_renderManager.IsStarted()
4152 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4153 SwitchToFullScreen();
4158 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4159 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4160 g_windowManager.PreviousWindow();
4164 #if !defined(TARGET_POSIX)
4165 g_audioManager.Enable(false);
4168 if (item.HasPVRChannelInfoTag())
4169 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4172 CSingleLock lock(m_playStateMutex);
4173 m_bPlaybackStarting = false;
4175 if (iResult == PLAYBACK_OK)
4177 // play state: none, starting; playing; stopped; ended.
4178 // last 3 states are set by playback callback, they are all ignored during starting,
4179 // but we recorded the state, here we can make up the callback for the state.
4180 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4181 switch (m_ePlayState)
4183 case PLAY_STATE_PLAYING:
4184 OnPlayBackStarted();
4186 // FIXME: it seems no meaning to callback started here if there was an started callback
4187 // before this stopped/ended callback we recorded. if we callback started here
4188 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4189 // which will send OnStop announce at once, so currently, just call stopped/ended.
4190 case PLAY_STATE_ENDED:
4193 case PLAY_STATE_STOPPED:
4194 OnPlayBackStopped();
4196 case PLAY_STATE_STARTING:
4197 // neither started nor stopped/ended callback be called, that means the item still
4198 // not started, we need not make up any callback, just leave this and
4199 // let the player callback do its work.
4205 else if (iResult == PLAYBACK_FAIL)
4207 // we send this if it isn't playlistplayer that is doing this
4208 int next = g_playlistPlayer.GetNextSong();
4209 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4212 OnPlayBackStopped();
4213 m_ePlayState = PLAY_STATE_NONE;
4219 void CApplication::OnPlayBackEnded()
4221 CSingleLock lock(m_playStateMutex);
4222 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4223 m_ePlayState = PLAY_STATE_ENDED;
4224 if(m_bPlaybackStarting)
4227 // informs python script currently running playback has ended
4228 // (does nothing if python is not loaded)
4230 g_pythonParser.OnPlayBackEnded();
4233 CVariant data(CVariant::VariantTypeObject);
4235 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4237 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4238 g_windowManager.SendThreadMessage(msg);
4241 void CApplication::OnPlayBackStarted()
4243 CSingleLock lock(m_playStateMutex);
4244 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4245 m_ePlayState = PLAY_STATE_PLAYING;
4246 if(m_bPlaybackStarting)
4250 // informs python script currently running playback has started
4251 // (does nothing if python is not loaded)
4252 g_pythonParser.OnPlayBackStarted();
4255 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4256 g_windowManager.SendThreadMessage(msg);
4259 void CApplication::OnQueueNextItem()
4261 CSingleLock lock(m_playStateMutex);
4262 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4263 if(m_bPlaybackStarting)
4265 // informs python script currently running that we are requesting the next track
4266 // (does nothing if python is not loaded)
4268 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4271 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4272 g_windowManager.SendThreadMessage(msg);
4275 void CApplication::OnPlayBackStopped()
4277 CSingleLock lock(m_playStateMutex);
4278 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4279 m_ePlayState = PLAY_STATE_STOPPED;
4280 if(m_bPlaybackStarting)
4283 // informs python script currently running playback has ended
4284 // (does nothing if python is not loaded)
4286 g_pythonParser.OnPlayBackStopped();
4289 CVariant data(CVariant::VariantTypeObject);
4290 data["end"] = false;
4291 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4293 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4294 g_windowManager.SendThreadMessage(msg);
4297 void CApplication::OnPlayBackPaused()
4300 g_pythonParser.OnPlayBackPaused();
4304 param["player"]["speed"] = 0;
4305 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4306 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4309 void CApplication::OnPlayBackResumed()
4312 g_pythonParser.OnPlayBackResumed();
4316 param["player"]["speed"] = 1;
4317 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4318 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4321 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4324 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4328 param["player"]["speed"] = iSpeed;
4329 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4330 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4333 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4336 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4340 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4341 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4342 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4343 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4344 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4345 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4348 void CApplication::OnPlayBackSeekChapter(int iChapter)
4351 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4355 bool CApplication::IsPlayingFullScreenVideo() const
4357 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4360 bool CApplication::IsFullScreen()
4362 return IsPlayingFullScreenVideo() ||
4363 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4364 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4367 void CApplication::SaveFileState(bool bForeground /* = false */)
4369 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4374 CSaveFileStateJob job(*m_progressTrackingItem,
4375 *m_stackFileItemToUpdate,
4376 m_progressTrackingVideoResumeBookmark,
4377 m_progressTrackingPlayCountUpdate);
4379 // Run job in the foreground to make sure it finishes
4384 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4385 *m_stackFileItemToUpdate,
4386 m_progressTrackingVideoResumeBookmark,
4387 m_progressTrackingPlayCountUpdate);
4388 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4392 void CApplication::UpdateFileState()
4394 // Did the file change?
4395 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4399 // Reset tracking item
4400 m_progressTrackingItem->Reset();
4404 if (m_pPlayer->IsPlaying())
4406 if (m_progressTrackingItem->GetPath() == "")
4409 *m_progressTrackingItem = CurrentFileItem();
4410 m_progressTrackingPlayCountUpdate = false;
4413 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4414 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4415 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4416 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4418 m_progressTrackingPlayCountUpdate = true;
4421 // Check whether we're *really* playing video else we may race when getting eg. stream details
4422 if (m_pPlayer->IsPlayingVideo())
4424 /* Always update streamdetails, except for DVDs where we only update
4425 streamdetails if title length > 15m (Should yield more correct info) */
4426 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4428 CStreamDetails details;
4429 // Update with stream details from player, if any
4430 if (m_pPlayer->GetStreamDetails(details))
4431 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4433 if (m_progressTrackingItem->IsStack())
4434 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4437 // Update bookmark for save
4438 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4439 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4440 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4442 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4443 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4445 // Delete the bookmark
4446 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4449 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4451 // Update the bookmark
4452 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4453 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4458 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4465 void CApplication::StopPlaying()
4467 int iWin = g_windowManager.GetActiveWindow();
4468 if ( m_pPlayer->IsPlaying() )
4472 m_pKaraokeMgr->Stop();
4475 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4476 g_PVRManager.SaveCurrentChannelSettings();
4478 m_pPlayer->CloseFile();
4480 // turn off visualisation window when stopping
4481 if ((iWin == WINDOW_VISUALISATION
4482 || iWin == WINDOW_FULLSCREEN_VIDEO)
4484 g_windowManager.PreviousWindow();
4486 g_partyModeManager.Disable();
4490 void CApplication::ResetSystemIdleTimer()
4492 // reset system idle timer
4493 m_idleTimer.StartZero();
4496 void CApplication::ResetScreenSaver()
4499 m_shutdownTimer.StartZero();
4501 // screen saver timer is reset only if we're not already in screensaver or
4503 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4504 ResetScreenSaverTimer();
4507 void CApplication::ResetScreenSaverTimer()
4509 m_screenSaverTimer.StartZero();
4512 void CApplication::StopScreenSaverTimer()
4514 m_screenSaverTimer.Stop();
4517 bool CApplication::ToggleDPMS(bool manual)
4519 if (manual || (m_dpmsIsManual == manual))
4523 m_dpmsIsActive = false;
4524 m_dpmsIsManual = false;
4525 return m_dpms->DisablePowerSaving();
4529 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4531 m_dpmsIsActive = true;
4532 m_dpmsIsManual = manual;
4540 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4544 // First reset DPMS, if active
4549 // TODO: if screensaver lock is specified but screensaver is not active
4550 // (DPMS came first), activate screensaver now.
4552 ResetScreenSaverTimer();
4553 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4556 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4560 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4561 CVariant data(bPowerOffKeyPressed);
4562 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4568 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4570 if (m_iScreenSaveLock == 2)
4573 // if Screen saver is active
4574 if (m_bScreenSave && m_screenSaver)
4576 if (m_iScreenSaveLock == 0)
4577 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4578 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4579 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4580 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4582 m_iScreenSaveLock = 2;
4583 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4585 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4587 pWindow->OnMessage(msg);
4589 if (m_iScreenSaveLock == -1)
4591 m_iScreenSaveLock = 0;
4595 // disable screensaver
4596 m_bScreenSave = false;
4597 m_iScreenSaveLock = 0;
4598 ResetScreenSaverTimer();
4600 if (m_screenSaver->ID() == "visualization")
4602 // we can just continue as usual from vis mode
4605 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4607 else if (!m_screenSaver->ID().empty())
4608 { // we're in screensaver window
4609 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4610 g_windowManager.PreviousWindow(); // show the previous window
4611 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4612 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4620 void CApplication::CheckScreenSaverAndDPMS()
4622 if (!m_dpmsIsActive)
4623 g_Windowing.ResetOSScreensaver();
4625 bool maybeScreensaver =
4626 !m_dpmsIsActive && !m_bScreenSave
4627 && !CSettings::Get().GetString("screensaver.mode").empty();
4629 !m_dpmsIsActive && m_dpms->IsSupported()
4630 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4632 // Has the screen saver window become active?
4633 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4635 m_bScreenSave = true;
4636 maybeScreensaver = false;
4639 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4641 WakeUpScreenSaverAndDPMS();
4645 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4647 // See if we need to reset timer.
4648 // * Are we playing a video and it is not paused?
4649 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4650 // * Are we playing some music in fullscreen vis?
4651 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4652 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4654 ResetScreenSaverTimer();
4658 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4660 // DPMS has priority (it makes the screensaver not needed)
4662 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4665 WakeUpScreenSaver();
4667 else if (maybeScreensaver
4668 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4670 ActivateScreenSaver();
4674 // activate the screensaver.
4675 // if forceType is true, we ignore the various conditions that can alter
4676 // the type of screensaver displayed
4677 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4679 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4680 { // just activate the visualisation if user toggled the usemusicvisinstead option
4681 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4685 m_bScreenSave = true;
4687 // Get Screensaver Mode
4688 m_screenSaver.reset();
4689 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4690 m_screenSaver.reset(new CScreenSaver(""));
4692 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4694 // disable screensaver lock from the login screen
4695 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4698 // set to Dim in the case of a dialog on screen or playing video
4699 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4701 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4702 m_screenSaver.reset(new CScreenSaver(""));
4705 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4707 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4709 else if (!m_screenSaver->ID().empty())
4710 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4713 void CApplication::CheckShutdown()
4715 // first check if we should reset the timer
4716 if (m_bInhibitIdleShutdown
4717 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4718 || m_musicInfoScanner->IsScanning()
4719 || m_videoInfoScanner->IsScanning()
4720 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4721 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4723 m_shutdownTimer.StartZero();
4727 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4729 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4730 m_shutdownTimer.Stop();
4733 CApplicationMessenger::Get().Shutdown();
4737 void CApplication::InhibitIdleShutdown(bool inhibit)
4739 m_bInhibitIdleShutdown = inhibit;
4742 bool CApplication::IsIdleShutdownInhibited() const
4744 return m_bInhibitIdleShutdown;
4747 bool CApplication::OnMessage(CGUIMessage& message)
4749 switch ( message.GetMessage() )
4751 case GUI_MSG_NOTIFY_ALL:
4753 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4755 // Update general playlist: Remove DVD playlist items
4756 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4759 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4760 g_windowManager.SendMessage( msg );
4762 // stop the file if it's on dvd (will set the resume point etc)
4763 if (m_itemCurrentFile->IsOnDVD())
4769 case GUI_MSG_PLAYBACK_STARTED:
4771 #ifdef TARGET_DARWIN
4772 DarwinSetScheduling(message.GetMessage());
4774 // reset the seek handler
4775 m_seekHandler->Reset();
4776 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4778 // Update our infoManager with the new details etc.
4779 if (m_nextPlaylistItem >= 0)
4781 // playing an item which is not in the list - player might be stopped already
4783 if (playList.size() <= m_nextPlaylistItem)
4786 // we've started a previously queued item
4787 CFileItemPtr item = playList[m_nextPlaylistItem];
4788 // update the playlist manager
4789 int currentSong = g_playlistPlayer.GetCurrentSong();
4790 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4791 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4792 g_windowManager.SendThreadMessage(msg);
4793 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4794 *m_itemCurrentFile = *item;
4796 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4797 g_partyModeManager.OnSongChange(true);
4800 param["player"]["speed"] = 1;
4801 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4802 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4804 if (m_pPlayer->IsPlayingAudio())
4806 // Start our cdg parser as appropriate
4808 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4810 m_pKaraokeMgr->Stop();
4811 if (m_itemCurrentFile->IsMusicDb())
4813 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4815 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4816 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4819 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4822 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4831 case GUI_MSG_QUEUE_NEXT_ITEM:
4833 // Check to see if our playlist player has a new item for us,
4834 // and if so, we check whether our current player wants the file
4835 int iNext = g_playlistPlayer.GetNextSong();
4836 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4837 if (iNext < 0 || iNext >= playlist.size())
4839 m_pPlayer->OnNothingToQueueNotify();
4840 return true; // nothing to do
4843 // ok, grab the next song
4844 CFileItem file(*playlist[iNext]);
4846 CURL url(file.GetPath());
4847 if (url.GetProtocol() == "plugin")
4848 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4851 if (URIUtils::IsUPnP(file.GetPath()))
4853 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4858 // ok - send the file to the player, if it accepts it
4859 if (m_pPlayer->QueueNextFile(file))
4861 // player accepted the next file
4862 m_nextPlaylistItem = iNext;
4866 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4867 queue the next (if it wants to) and it doesn't keep looping on this song */
4868 g_playlistPlayer.SetCurrentSong(iNext);
4875 case GUI_MSG_PLAYBACK_STOPPED:
4876 case GUI_MSG_PLAYBACK_ENDED:
4877 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4881 m_pKaraokeMgr->Stop();
4883 #ifdef TARGET_DARWIN
4884 DarwinSetScheduling(message.GetMessage());
4886 // first check if we still have items in the stack to play
4887 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4889 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4890 { // just play the next item in the stack
4891 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4896 // In case playback ended due to user eg. skipping over the end, clear
4897 // our resume bookmark here
4898 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4900 // Delete the bookmark
4901 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4904 // reset the current playing file
4905 m_itemCurrentFile->Reset();
4906 g_infoManager.ResetCurrentItem();
4907 m_currentStack->Clear();
4909 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4911 g_playlistPlayer.PlayNext(1, true);
4915 // reset any forced player
4916 m_eForcedNextPlayer = EPC_NONE;
4918 m_pPlayer->ClosePlayer();
4921 m_pPlayer->m_iPlaySpeed = 1;
4924 if (!m_pPlayer->IsPlaying())
4926 g_audioManager.Enable(true);
4929 if (!m_pPlayer->IsPlayingVideo())
4931 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4933 g_windowManager.PreviousWindow();
4937 CSingleLock lock(g_graphicsContext);
4938 // resets to res_desktop or look&feel resolution (including refreshrate)
4939 g_graphicsContext.SetFullScreenVideo(false);
4943 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4945 CSettings::Get().Save(); // save vis settings
4946 WakeUpScreenSaverAndDPMS();
4947 g_windowManager.PreviousWindow();
4950 // DVD ejected while playing in vis ?
4951 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4954 CSettings::Get().Save(); // save vis settings
4955 WakeUpScreenSaverAndDPMS();
4956 g_windowManager.PreviousWindow();
4959 if (IsEnableTestMode())
4960 CApplicationMessenger::Get().Quit();
4965 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4966 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4971 case GUI_MSG_FULLSCREEN:
4972 { // Switch to fullscreen, if we can
4973 SwitchToFullScreen();
4977 case GUI_MSG_EXECUTE:
4978 if (message.GetNumStringParams())
4979 return ExecuteXBMCAction(message.GetStringParam());
4985 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4987 // see if it is a user set string
4989 //We don't know if there is unsecure information in this yet, so we
4990 //postpone any logging
4991 const std::string in_actionStr(actionStr);
4992 CGUIInfoLabel info(actionStr, "");
4993 actionStr = info.GetLabel(0);
4995 // user has asked for something to be executed
4996 if (CBuiltins::HasCommand(actionStr))
4997 CBuiltins::Execute(actionStr);
5000 // try translating the action from our ButtonTranslator
5002 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5004 OnAction(CAction(actionID));
5007 CFileItem item(actionStr, false);
5009 if (item.IsPythonScript())
5010 { // a python script
5011 CScriptInvocationManager::Get().Execute(item.GetPath());
5015 if (item.IsAudio() || item.IsVideo())
5016 { // an audio or video file
5021 //At this point we have given up to translate, so even though
5022 //there may be insecure information, we log it.
5023 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5030 void CApplication::Process()
5034 // dispatch the messages generated by python or other threads to the current window
5035 g_windowManager.DispatchThreadMessages();
5037 // process messages which have to be send to the gui
5038 // (this can only be done after g_windowManager.Render())
5039 CApplicationMessenger::Get().ProcessWindowMessages();
5043 m_loggingIn = false;
5045 // autoexec.py - profile
5046 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5048 if (XFILE::CFile::Exists(strAutoExecPy))
5049 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5051 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5054 // handle any active scripts
5055 CScriptInvocationManager::Get().Process();
5057 // process messages, even if a movie is playing
5058 CApplicationMessenger::Get().ProcessMessages();
5059 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5061 // check how far we are through playing the current item
5062 // and do anything that needs doing (playcount updates etc)
5063 CheckPlayingProgress();
5066 m_pPlayer->DoAudioWork();
5068 // do any processing that isn't needed on each run
5069 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5071 m_slowTimer.Reset();
5075 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5078 // We get called every 500ms
5079 void CApplication::ProcessSlow()
5081 g_powerManager.ProcessEvents();
5083 #if defined(TARGET_DARWIN_OSX)
5084 // There is an issue on OS X that several system services ask the cursor to become visible
5085 // during their startup routines. Given that we can't control this, we hack it in by
5087 if (g_Windowing.IsFullScreen())
5088 { // SDL thinks it's hidden
5093 // Temporarely pause pausable jobs when viewing video/picture
5094 int currentWindow = g_windowManager.GetActiveWindow();
5095 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5097 CJobManager::GetInstance().PauseJobs();
5101 CJobManager::GetInstance().UnPauseJobs();
5104 // Store our file state for use on close()
5107 // Check if we need to activate the screensaver / DPMS.
5108 CheckScreenSaverAndDPMS();
5110 // Check if we need to shutdown (if enabled).
5111 #if defined(TARGET_DARWIN)
5112 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5114 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5120 // check if we should restart the player
5121 CheckDelayedPlayerRestart();
5123 // check if we can unload any unreferenced dlls or sections
5124 if (!m_pPlayer->IsPlayingVideo())
5125 CSectionLoader::UnloadDelayed();
5127 // check for any idle curl connections
5128 g_curlInterface.CheckIdle();
5130 // check for any idle myth sessions
5131 CMythSession::CheckIdle();
5133 #ifdef HAS_FILESYSTEM_HTSP
5134 // check for any idle htsp sessions
5135 HTSP::CHTSPDirectorySession::CheckIdle();
5139 if ( m_pKaraokeMgr )
5140 m_pKaraokeMgr->ProcessSlow();
5143 if (!m_pPlayer->IsPlayingVideo())
5144 g_largeTextureManager.CleanupUnusedImages();
5146 g_TextureManager.FreeUnusedTextures(5000);
5148 #ifdef HAS_DVD_DRIVE
5149 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5150 if (!m_pPlayer->IsPlayingVideo())
5151 m_Autorun->HandleAutorun();
5154 // update upnp server/renderer states
5156 if(UPNP::CUPnP::IsInstantiated())
5157 UPNP::CUPnP::GetInstance()->UpdateState();
5160 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5164 #ifdef HAS_FILESYSTEM_NFS
5165 gNfsConnection.CheckIfIdle();
5168 #ifdef HAS_FILESYSTEM_AFP
5169 gAfpConnection.CheckIfIdle();
5172 #ifdef HAS_FILESYSTEM_SFTP
5173 CSFTPSessionManager::ClearOutIdleSessions();
5176 g_mediaManager.ProcessEvents();
5179 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5180 g_RemoteControl.Initialize();
5183 if (!m_pPlayer->IsPlayingVideo())
5184 CAddonInstaller::Get().UpdateRepos();
5186 CAEFactory::GarbageCollect();
5188 // if we don't render the gui there's no reason to start the screensaver.
5189 // that way the screensaver won't kick in if we maximize the XBMC window
5190 // after the screensaver start time.
5192 ResetScreenSaverTimer();
5195 // Global Idle Time in Seconds
5196 // idle time will be resetet if on any OnKey()
5197 // int return: system Idle time in seconds! 0 is no idle!
5198 int CApplication::GlobalIdleTime()
5200 if(!m_idleTimer.IsRunning())
5203 m_idleTimer.StartZero();
5205 return (int)m_idleTimer.GetElapsedSeconds();
5208 float CApplication::NavigationIdleTime()
5210 if (!m_navigationTimer.IsRunning())
5212 m_navigationTimer.Stop();
5213 m_navigationTimer.StartZero();
5215 return m_navigationTimer.GetElapsedSeconds();
5218 void CApplication::DelayedPlayerRestart()
5220 m_restartPlayerTimer.StartZero();
5223 void CApplication::CheckDelayedPlayerRestart()
5225 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5227 m_restartPlayerTimer.Stop();
5228 m_restartPlayerTimer.Reset();
5233 void CApplication::Restart(bool bSamePosition)
5235 // this function gets called when the user changes a setting (like noninterleaved)
5236 // and which means we gotta close & reopen the current playing file
5238 // first check if we're playing a file
5239 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5242 if( !m_pPlayer->HasPlayer() )
5247 // do we want to return to the current position in the file
5248 if (false == bSamePosition)
5250 // no, then just reopen the file and start at the beginning
5251 PlayFile(*m_itemCurrentFile, true);
5255 // else get current position
5256 double time = GetTime();
5258 // get player state, needed for dvd's
5259 CStdString state = m_pPlayer->GetPlayerState();
5261 // set the requested starttime
5262 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5265 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5266 m_pPlayer->SetPlayerState(state);
5269 const CStdString& CApplication::CurrentFile()
5271 return m_itemCurrentFile->GetPath();
5274 CFileItem& CApplication::CurrentFileItem()
5276 return *m_itemCurrentFile;
5279 CFileItem& CApplication::CurrentUnstackedItem()
5281 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5282 return *(*m_currentStack)[m_currentStackPosition];
5284 return *m_itemCurrentFile;
5287 void CApplication::ShowVolumeBar(const CAction *action)
5289 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5294 volumeBar->OnAction(*action);
5298 bool CApplication::IsMuted() const
5300 if (g_peripherals.IsMuted())
5302 return CAEFactory::IsMuted();
5305 void CApplication::ToggleMute(void)
5313 void CApplication::SetMute(bool mute)
5315 if (m_muted != mute)
5322 void CApplication::Mute()
5324 if (g_peripherals.Mute())
5327 CAEFactory::SetMute(true);
5332 void CApplication::UnMute()
5334 if (g_peripherals.UnMute())
5337 CAEFactory::SetMute(false);
5342 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5344 float hardwareVolume = iValue;
5347 hardwareVolume /= 100.0f;
5349 SetHardwareVolume(hardwareVolume);
5353 void CApplication::SetHardwareVolume(float hardwareVolume)
5355 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5356 m_volumeLevel = hardwareVolume;
5358 CAEFactory::SetVolume(hardwareVolume);
5361 float CApplication::GetVolume(bool percentage /* = true */) const
5365 // converts the hardware volume to a percentage
5366 return m_volumeLevel * 100.0f;
5369 return m_volumeLevel;
5372 void CApplication::VolumeChanged() const
5374 CVariant data(CVariant::VariantTypeObject);
5375 data["volume"] = GetVolume();
5376 data["muted"] = m_muted;
5377 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5379 // if player has volume control, set it.
5380 if (m_pPlayer->ControlsVolume())
5382 m_pPlayer->SetVolume(m_volumeLevel);
5383 m_pPlayer->SetMute(m_muted);
5387 int CApplication::GetSubtitleDelay() const
5389 // converts subtitle delay to a percentage
5390 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5393 int CApplication::GetAudioDelay() const
5395 // converts audio delay to a percentage
5396 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5399 // Returns the total time in seconds of the current media. Fractional
5400 // portions of a second are possible - but not necessarily supported by the
5401 // player class. This returns a double to be consistent with GetTime() and
5403 double CApplication::GetTotalTime() const
5407 if (m_pPlayer->IsPlaying())
5409 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5410 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5412 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5418 void CApplication::StopShutdownTimer()
5420 if (m_shutdownTimer.IsRunning())
5421 m_shutdownTimer.Stop();
5424 void CApplication::ResetShutdownTimers()
5426 // reset system shutdown timer
5427 m_shutdownTimer.StartZero();
5429 // delete custom shutdown timer
5430 if (g_alarmClock.HasAlarm("shutdowntimer"))
5431 g_alarmClock.Stop("shutdowntimer", true);
5434 // Returns the current time in seconds of the currently playing media.
5435 // Fractional portions of a second are possible. This returns a double to
5436 // be consistent with GetTotalTime() and SeekTime().
5437 double CApplication::GetTime() const
5441 if (m_pPlayer->IsPlaying())
5443 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5445 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5446 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5449 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5455 // Sets the current position of the currently playing media to the specified
5456 // time in seconds. Fractional portions of a second are valid. The passed
5457 // time is the time offset from the beginning of the file as opposed to a
5458 // delta from the current position. This method accepts a double to be
5459 // consistent with GetTime() and GetTotalTime().
5460 void CApplication::SeekTime( double dTime )
5462 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5464 if (!m_pPlayer->CanSeek()) return;
5465 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5467 // find the item in the stack we are seeking to, and load the new
5468 // file if necessary, and calculate the correct seek within the new
5469 // file. Otherwise, just fall through to the usual routine if the
5470 // time is higher than our total time.
5471 for (int i = 0; i < m_currentStack->Size(); i++)
5473 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5475 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5476 if (m_currentStackPosition == i)
5477 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5479 { // seeking to a new file
5480 m_currentStackPosition = i;
5481 CFileItem item(*(*m_currentStack)[i]);
5482 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5483 // don't just call "PlayFile" here, as we are quite likely called from the
5484 // player thread, so we won't be able to delete ourselves.
5485 CApplicationMessenger::Get().PlayFile(item, true);
5491 // convert to milliseconds and perform seek
5492 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5496 float CApplication::GetPercentage() const
5498 if (m_pPlayer->IsPlaying())
5500 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5502 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5503 if (tag.GetDuration() > 0)
5504 return (float)(GetTime() / tag.GetDuration() * 100);
5507 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5509 double totalTime = GetTotalTime();
5510 if (totalTime > 0.0f)
5511 return (float)(GetTime() / totalTime * 100);
5514 return m_pPlayer->GetPercentage();
5519 float CApplication::GetCachePercentage() const
5521 if (m_pPlayer->IsPlaying())
5523 // Note that the player returns a relative cache percentage and we want an absolute percentage
5524 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5526 float stackedTotalTime = (float) GetTotalTime();
5527 // We need to take into account the stack's total time vs. currently playing file's total time
5528 if (stackedTotalTime > 0.0f)
5529 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5532 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5537 void CApplication::SeekPercentage(float percent)
5539 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5541 if (!m_pPlayer->CanSeek()) return;
5542 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5543 SeekTime(percent * 0.01 * GetTotalTime());
5545 m_pPlayer->SeekPercentage(percent);
5549 // SwitchToFullScreen() returns true if a switch is made, else returns false
5550 bool CApplication::SwitchToFullScreen()
5552 // if playing from the video info window, close it first!
5553 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5555 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5556 if (pDialog) pDialog->Close(true);
5559 // don't switch if there is a dialog on screen or the slideshow is active
5560 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5563 // See if we're playing a video, and are in GUI mode
5564 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5566 // then switch to fullscreen mode
5567 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5570 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5571 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5572 { // then switch to visualisation
5573 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5579 void CApplication::Minimize()
5581 g_Windowing.Minimize();
5584 PLAYERCOREID CApplication::GetCurrentPlayer()
5586 return m_pPlayer->GetCurrentPlayer();
5589 void CApplication::UpdateLibraries()
5591 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5593 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5597 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5599 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5604 bool CApplication::IsVideoScanning() const
5606 return m_videoInfoScanner->IsScanning();
5609 bool CApplication::IsMusicScanning() const
5611 return m_musicInfoScanner->IsScanning();
5614 void CApplication::StopVideoScan()
5616 if (m_videoInfoScanner->IsScanning())
5617 m_videoInfoScanner->Stop();
5620 void CApplication::StopMusicScan()
5622 if (m_musicInfoScanner->IsScanning())
5623 m_musicInfoScanner->Stop();
5626 void CApplication::StartVideoCleanup()
5628 if (m_videoInfoScanner->IsScanning())
5631 m_videoInfoScanner->CleanDatabase();
5634 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5636 if (m_videoInfoScanner->IsScanning())
5639 m_videoInfoScanner->ShowDialog(true);
5641 m_videoInfoScanner->Start(strDirectory,scanAll);
5644 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5646 if (m_musicInfoScanner->IsScanning())
5650 { // setup default flags
5651 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5652 flags |= CMusicInfoScanner::SCAN_ONLINE;
5653 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5654 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5657 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5658 m_musicInfoScanner->ShowDialog(true);
5660 m_musicInfoScanner->Start(strDirectory, flags);
5663 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5666 if (m_musicInfoScanner->IsScanning())
5669 m_musicInfoScanner->ShowDialog(true);
5671 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5674 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5677 if (m_musicInfoScanner->IsScanning())
5680 m_musicInfoScanner->ShowDialog(true);
5682 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5685 void CApplication::CheckPlayingProgress()
5687 // check if we haven't rewound past the start of the file
5688 if (m_pPlayer->IsPlaying())
5690 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5700 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5702 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5703 g_application.SeekTime(0);
5709 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5711 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5713 // initial exit conditions
5714 // no songs in playlist just return
5715 if (playlist.size() == 0)
5719 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5722 // setup correct playlist
5723 g_playlistPlayer.ClearPlaylist(iPlaylist);
5725 // if the playlist contains an internet stream, this file will be used
5726 // to generate a thumbnail for musicplayer.cover
5727 g_application.m_strPlayListFile = strPlayList;
5729 // add the items to the playlist player
5730 g_playlistPlayer.Add(iPlaylist, playlist);
5732 // if we have a playlist
5733 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5736 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5737 g_playlistPlayer.Reset();
5738 g_playlistPlayer.Play(track);
5744 void CApplication::SaveCurrentFileSettings()
5746 // don't store settings for PVR in video database
5747 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5749 // save video settings
5750 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5754 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5758 else if (m_itemCurrentFile->IsPVRChannel())
5760 g_PVRManager.SaveCurrentChannelSettings();
5764 bool CApplication::AlwaysProcess(const CAction& action)
5766 // check if this button is mapped to a built-in function
5767 if (!action.GetName().empty())
5769 CStdString builtInFunction;
5770 vector<CStdString> params;
5771 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5772 StringUtils::ToLower(builtInFunction);
5774 // should this button be handled normally or just cancel the screensaver?
5775 if ( builtInFunction.Equals("powerdown")
5776 || builtInFunction.Equals("reboot")
5777 || builtInFunction.Equals("restart")
5778 || builtInFunction.Equals("restartapp")
5779 || builtInFunction.Equals("suspend")
5780 || builtInFunction.Equals("hibernate")
5781 || builtInFunction.Equals("quit")
5782 || builtInFunction.Equals("shutdown"))
5791 bool CApplication::IsCurrentThread() const
5793 return CThread::IsCurrentThread(m_threadID);
5796 void CApplication::SetRenderGUI(bool renderGUI)
5798 if (renderGUI && ! m_renderGUI)
5799 g_windowManager.MarkDirty();
5800 m_renderGUI = renderGUI;
5803 CNetwork& CApplication::getNetwork()
5807 #ifdef HAS_PERFORMANCE_SAMPLE
5808 CPerformanceStats &CApplication::GetPerformanceStats()
5814 bool CApplication::SetLanguage(const CStdString &strLanguage)
5816 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5817 CStdString strNewLanguage = strLanguage;
5818 if (strNewLanguage != strPreviousLanguage)
5820 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5821 if (!g_langInfo.Load(strLangInfoPath))
5824 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5826 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5827 CStdString strFontSet;
5828 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5829 strNewLanguage = strFontSet;
5831 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5833 CSettings::Get().SetString("locale.language", strNewLanguage);
5835 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5838 // also tell our weather and skin to reload as these are localized
5839 g_weatherManager.Refresh();
5840 g_PVRManager.LocalizationChanged();
5847 void CApplication::CloseNetworkShares()
5849 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5851 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5855 #ifdef HAS_FILESYSTEM_NFS
5856 gNfsConnection.Deinit();
5859 #ifdef HAS_FILESYSTEM_AFP
5860 gAfpConnection.Deinit();
5863 #ifdef HAS_FILESYSTEM_SFTP
5864 CSFTPSessionManager::DisconnectAllSessions();