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;
413 // we start in frontend
414 m_bInBackground = false;
416 /* for now always keep this around */
418 m_pKaraokeMgr = new CKaraokeLyricsManager();
420 m_currentStack = new CFileItemList;
422 m_bPresentFrame = false;
423 m_bPlatformDirectories = true;
425 m_bStandalone = false;
426 m_bEnableLegacyRes = false;
427 m_bSystemScreenSaverEnable = false;
428 m_pInertialScrollingHandler = new CInertialScrollingHandler();
430 m_Autorun = new CAutorun();
435 m_progressTrackingPlayCountUpdate = false;
436 m_currentStackPosition = 0;
438 m_lastRenderTime = 0;
442 m_volumeLevel = 1.0f;
445 CApplication::~CApplication(void)
447 delete m_musicInfoScanner;
448 delete m_videoInfoScanner;
449 delete &m_progressTrackingVideoResumeBookmark;
453 delete m_currentStack;
456 delete m_pKaraokeMgr;
460 delete m_seekHandler;
461 delete m_playerController;
462 delete m_pInertialScrollingHandler;
466 bool CApplication::OnEvent(XBMC_Event& newEvent)
468 switch(newEvent.type)
471 if (!g_application.m_bStop)
472 CApplicationMessenger::Get().Quit();
475 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
478 g_Keyboard.ProcessKeyUp();
480 case XBMC_MOUSEBUTTONDOWN:
481 case XBMC_MOUSEBUTTONUP:
482 case XBMC_MOUSEMOTION:
483 g_Mouse.HandleEvent(newEvent);
484 g_application.ProcessMouse();
486 case XBMC_VIDEORESIZE:
487 if (!g_application.m_bInitializing &&
488 !g_advancedSettings.m_fullScreen)
490 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
491 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
492 CSettings::Get().SetInt("window.width", newEvent.resize.w);
493 CSettings::Get().SetInt("window.height", newEvent.resize.h);
494 CSettings::Get().Save();
498 #ifdef TARGET_WINDOWS
499 if (g_advancedSettings.m_fullScreen)
501 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
502 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
503 if (newRes != g_graphicsContext.GetVideoResolution())
504 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
509 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
513 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
515 case XBMC_APPCOMMAND:
516 return g_application.OnAppCommand(newEvent.appcommand.action);
519 if (newEvent.touch.action == ACTION_TOUCH_TAP)
520 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
521 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
524 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
525 actionId = newEvent.touch.action;
528 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
529 // change this if we have a dialog up
530 if (g_windowManager.HasModalDialog())
532 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
534 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
535 { // fullscreen info dialog - special case
536 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
538 iWin = WINDOW_FULLSCREEN_VIDEO; // fallthrough to the main window
542 if (iWin == WINDOW_FULLSCREEN_VIDEO)
544 // current active window is full screen video.
545 if (g_application.m_pPlayer->IsInMenu())
547 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
548 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_VIDEO_MENU, newEvent.touch.action, newEvent.touch.pointers, actionId);
550 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
552 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
553 CButtonTranslator::GetInstance().TranslateTouchAction(WINDOW_FULLSCREEN_LIVETV, newEvent.touch.action, newEvent.touch.pointers, actionId);
555 // if no PVR specific action/mapping is found, fall back to default
557 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
561 // in any other case use the fullscreen window section of keymap.xml to map key->action
562 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
565 else // iWin != WINDOW_FULLSCREEN_VIDEO
566 CButtonTranslator::GetInstance().TranslateTouchAction(iWin, newEvent.touch.action, newEvent.touch.pointers, actionId);
573 if ((actionId >= ACTION_TOUCH_TAP && actionId <= ACTION_GESTURE_END)
574 || (actionId >= ACTION_MOUSE_START && actionId <= ACTION_MOUSE_END) )
575 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
577 CApplicationMessenger::Get().SendAction(CAction(actionId), WINDOW_INVALID, false);
579 // Post an unfocus message for touch device after the action.
580 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
582 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
583 CApplicationMessenger::Get().SendGUIMessage(msg);
588 // Reset the screensaver
589 g_application.ResetScreenSaver();
590 g_application.WakeUpScreenSaverAndDPMS();
591 // Send a mouse motion event with no dx,dy for getting the current guiitem selected
592 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.focus.x, newEvent.focus.y, 0, 0));
598 extern "C" void __stdcall init_emu_environ();
599 extern "C" void __stdcall update_emu_environ();
602 // Utility function used to copy files from the application bundle
603 // over to the user data directory in Application Support/XBMC.
605 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
607 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
608 if (!CFile::Exists(destPath))
610 // need to copy it across
611 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
612 CFile::Cache(srcPath, destPath);
616 void CApplication::Preflight()
619 // call 'dbus_threads_init_default' before any other dbus calls in order to
620 // avoid race conditions with other threads using dbus connections
621 dbus_threads_init_default();
624 // run any platform preflight scripts.
625 #if defined(TARGET_DARWIN_OSX)
626 CStdString install_path;
628 CUtil::GetHomePath(install_path);
629 setenv("XBMC_HOME", install_path.c_str(), 0);
630 install_path += "/tools/darwin/runtime/preflight";
631 system(install_path.c_str());
635 bool CApplication::Create()
637 #if defined(HAS_LINUX_NETWORK)
638 m_network = new CNetworkLinux();
639 #elif defined(HAS_WIN32_NETWORK)
640 m_network = new CNetworkWin32();
642 m_network = new CNetwork();
647 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
649 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
650 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
654 tzset(); // Initialize timezone information variables
657 // Grab a handle to our thread to be used later in identifying the render thread.
658 m_threadID = CThread::GetCurrentThreadId();
661 //floating point precision to 24 bits (faster performance)
662 _controlfp(_PC_24, _MCW_PC);
664 /* install win32 exception translator, win32 exceptions
665 * can now be caught using c++ try catch */
666 win32_exception::install_handler();
670 // only the InitDirectories* for the current platform should return true
671 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
672 bool inited = InitDirectoriesLinux();
674 inited = InitDirectoriesOSX();
676 inited = InitDirectoriesWin32();
678 // copy required files
679 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
680 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
681 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
683 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
685 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
686 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
690 // Init our DllLoaders emu env
693 CProfilesManager::Get().Load();
695 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
696 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetCpuFamily().c_str(),
697 g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness());
699 /* Expand macro before stringify */
700 #define STR_MACRO(x) #x
701 #define XSTR_MACRO(x) STR_MACRO(x)
703 std::string compilerStr;
704 #if defined(__clang__)
705 compilerStr = "Clang " XSTR_MACRO(__clang_major__) "." XSTR_MACRO(__clang_minor__) "." XSTR_MACRO(__clang_patchlevel__);
706 #elif defined (__INTEL_COMPILER)
707 compilerStr = "Intel Compiler " XSTR_MACRO(__INTEL_COMPILER);
708 #elif defined (__GNUC__)
710 /* Note: this will not detect GCC + DragonEgg */
711 compilerStr = "llvm-gcc ";
713 compilerStr = "GCC ";
715 compilerStr += XSTR_MACRO(__GNUC__) "." XSTR_MACRO(__GNUC_MINOR__) "." XSTR_MACRO(__GNUC_PATCHLEVEL__);
716 #elif defined (_MSC_VER)
717 compilerStr = "MSVC " XSTR_MACRO(_MSC_FULL_VER);
719 compilerStr = "unknown compiler";
721 std::string buildType;
724 #elif defined(NDEBUG)
725 buildType = "Release";
727 buildType = "Unknown";
729 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(),
730 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersion().c_str());
732 #if defined(TARGET_DARWIN_OSX)
733 CLog::Log(LOGNOTICE, "Running on Darwin OSX %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
734 #elif defined(TARGET_DARWIN_IOS)
735 CLog::Log(LOGNOTICE, "Running on Darwin iOS %d-bit %s%s", g_sysinfo.GetKernelBitness(), g_sysinfo.IsAppleTV2() ? "(AppleTV2) " : "", g_sysinfo.GetUnameVersion().c_str());
736 #elif defined(TARGET_FREEBSD)
737 CLog::Log(LOGNOTICE, "Running on FreeBSD %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
738 #elif defined(TARGET_ANDROID)
739 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());
740 #elif defined(TARGET_POSIX)
741 CLog::Log(LOGNOTICE, "Running on Linux %d-bit (%s, %s)", g_sysinfo.GetKernelBitness(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
742 #elif defined(TARGET_WINDOWS)
743 CLog::Log(LOGNOTICE, "Running on %s", g_sysinfo.GetKernelVersion().c_str());
746 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", g_cpuInfo.getCPUModel().c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount()==1) ? "" : "s");
747 #if defined(TARGET_WINDOWS)
748 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
749 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
750 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
752 #if defined(TARGET_ANDROID)
754 "Product: %s, Device: %s, Board: %s - Manufacturer: %s, Brand: %s, Model: %s, Hardware: %s",
755 CJNIBuild::PRODUCT.c_str(), CJNIBuild::DEVICE.c_str(), CJNIBuild::BOARD.c_str(),
756 CJNIBuild::MANUFACTURER.c_str(), CJNIBuild::BRAND.c_str(), CJNIBuild::MODEL.c_str(), CJNIBuild::HARDWARE.c_str());
760 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
761 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
763 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
765 CSpecialProtocol::LogPaths();
767 CStdString executable = CUtil::ResolveExecutablePath();
768 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
769 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
770 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
771 CRegExp::LogCheckUtf8Support();
772 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
774 CStdString strExecutablePath;
775 CUtil::GetHomePath(strExecutablePath);
778 g_xrandr.LoadCustomModeLinesToAllOutputs();
781 // for python scripts that check the OS
782 #if defined(TARGET_DARWIN)
783 setenv("OS","OS X",true);
784 #elif defined(TARGET_POSIX)
785 setenv("OS","Linux",true);
786 #elif defined(TARGET_WINDOWS)
787 CEnvironment::setenv("OS", "win32");
790 g_powerManager.Initialize();
792 // Load the AudioEngine before settings as they need to query the engine
793 if (!CAEFactory::LoadEngine())
795 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
799 // Initialize default Settings - don't move
800 CLog::Log(LOGNOTICE, "load settings...");
801 if (!CSettings::Get().Initialize())
804 g_powerManager.SetDefaults();
806 // load the actual values
807 if (!CSettings::Get().Load())
809 CLog::Log(LOGFATAL, "unable to load settings");
812 CSettings::Get().SetLoaded();
814 CLog::Log(LOGINFO, "creating subdirectories");
815 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
816 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
817 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
818 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
819 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
820 CProfilesManager::Get().CreateProfileFolders();
822 update_emu_environ();//apply the GUI settings
824 // Load the langinfo to have user charset <-> utf-8 conversion
825 CStdString strLanguage = CSettings::Get().GetString("locale.language");
826 strLanguage[0] = toupper(strLanguage[0]);
828 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
830 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
831 g_langInfo.Load(strLangInfoPath);
832 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
833 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
835 CStdString strLanguagePath = "special://xbmc/language/";
837 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
838 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
840 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
844 // start the AudioEngine
845 if (!CAEFactory::StartEngine())
847 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
851 // restore AE's previous volume state
852 SetHardwareVolume(m_volumeLevel);
853 CAEFactory::SetMute (m_muted);
854 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
856 // initialize m_replayGainSettings
857 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
858 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
859 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
860 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
862 // initialize the addon database (must be before the addon manager is init'd)
863 CDatabaseManager::Get().Initialize(true);
866 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
869 // start-up Addons Framework
870 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
871 if (!CAddonMgr::Get().Init())
873 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
876 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
877 g_RemoteControl.Initialize();
880 // set logging from debug add-on
882 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
884 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
886 g_peripherals.Initialise();
888 // Create the Mouse, Keyboard, Remote, and Joystick devices
889 // Initialize after loading settings to get joystick deadzone setting
890 g_Mouse.Initialize();
891 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
893 g_Keyboard.Initialize();
895 #if defined(TARGET_DARWIN_OSX)
896 // Configure and possible manually start the helper.
897 XBMCHelper::GetInstance().Configure();
900 CUtil::InitRandomSeed();
902 g_mediaManager.Initialize();
904 m_lastFrameTime = XbmcThreads::SystemClockMillis();
905 m_lastRenderTime = m_lastFrameTime;
909 bool CApplication::CreateGUI()
913 CLog::Log(LOGNOTICE, "Setup SDL");
915 /* Clean up on exit, exit on window close and interrupt */
918 uint32_t sdlFlags = 0;
920 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
921 sdlFlags |= SDL_INIT_VIDEO;
924 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
925 sdlFlags |= SDL_INIT_JOYSTICK;
928 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
929 //this might bring the monitor out of standby, so we have to disable it explicitly
930 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
931 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
932 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
938 // for nvidia cards - vsync currently ALWAYS enabled.
939 // the reason is that after screen has been setup changing this env var will make no difference.
940 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
941 setenv("__GL_YIELD", "USLEEP", 0);
944 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
945 g_Windowing.EnableSystemScreenSaver(false);
948 if (SDL_Init(sdlFlags) != 0)
950 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
953 #if defined(TARGET_DARWIN)
954 // SDL_Init will install a handler for segfaults, restore the default handler.
955 signal(SIGSEGV, SIG_DFL);
959 // Initialize core peripheral port support. Note: If these parameters
960 // are 0 and NULL, respectively, then the default number and types of
961 // controllers will be initialized.
962 if (!g_Windowing.InitWindowSystem())
964 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
968 // Retrieve the matching resolution based on GUI settings
969 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
970 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
971 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
973 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
974 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
977 // update the window resolution
978 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
980 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
981 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
983 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
985 // Oh uh - doesn't look good for starting in their wanted screenmode
986 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
987 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
994 if (g_advancedSettings.m_splashImage)
996 CStdString strUserSplash = "special://home/media/Splash.png";
997 if (CFile::Exists(strUserSplash))
999 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
1000 m_splash = new CSplash(strUserSplash);
1004 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
1005 m_splash = new CSplash("special://xbmc/media/Splash.png");
1010 // The key mappings may already have been loaded by a peripheral
1011 CLog::Log(LOGINFO, "load keymapping");
1012 if (!CButtonTranslator::GetInstance().Load())
1015 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
1016 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
1019 info.strMode.c_str());
1020 g_windowManager.Initialize();
1025 bool CApplication::InitWindow()
1027 #ifdef TARGET_DARWIN_OSX
1028 // force initial window creation to be windowed, if fullscreen, it will switch to it below
1029 // fixes the white screen of death if starting fullscreen and switching to windowed.
1030 bool bFullScreen = false;
1031 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
1033 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1037 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
1038 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
1040 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
1045 if (!g_Windowing.InitRenderSystem())
1047 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
1050 // set GUI res and force the clear of the screen
1051 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
1055 bool CApplication::DestroyWindow()
1057 return g_Windowing.DestroyWindow();
1060 bool CApplication::InitDirectoriesLinux()
1063 The following is the directory mapping for Platform Specific Mode:
1065 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1066 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1067 installations like skins, screensavers, etc.
1069 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1070 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1071 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1072 special://profile/ => [read-write] current profile's userdata directory.
1073 Generally special://masterprofile for the master profile or
1074 special://masterprofile/profiles/<profile_name> for other profiles.
1076 NOTE: All these root directories are lowercase. Some of the sub-directories
1077 might be mixed case.
1080 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1081 CStdString userName;
1083 userName = getenv("USER");
1087 CStdString userHome;
1089 userHome = getenv("HOME");
1093 CStdString xbmcBinPath, xbmcPath;
1094 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1095 xbmcPath = getenv("XBMC_HOME");
1097 if (xbmcPath.empty())
1099 xbmcPath = xbmcBinPath;
1100 /* Check if xbmc binaries and arch independent data files are being kept in
1101 * separate locations. */
1102 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1104 /* Attempt to locate arch independent data files. */
1105 CUtil::GetHomePath(xbmcPath);
1106 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1108 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1114 /* Set some environment variables */
1115 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1116 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1118 if (m_bPlatformDirectories)
1120 // map our special drives
1121 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1122 CSpecialProtocol::SetXBMCPath(xbmcPath);
1123 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1124 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1126 CStdString strTempPath = userHome;
1127 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1128 if (getenv("XBMC_TEMP"))
1129 strTempPath = getenv("XBMC_TEMP");
1130 CSpecialProtocol::SetTempPath(strTempPath);
1132 URIUtils::AddSlashAtEnd(strTempPath);
1133 g_advancedSettings.m_logFolder = strTempPath;
1140 URIUtils::AddSlashAtEnd(xbmcPath);
1141 g_advancedSettings.m_logFolder = xbmcPath;
1143 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1144 CSpecialProtocol::SetXBMCPath(xbmcPath);
1145 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1146 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1148 CStdString strTempPath = xbmcPath;
1149 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1150 if (getenv("XBMC_TEMP"))
1151 strTempPath = getenv("XBMC_TEMP");
1152 CSpecialProtocol::SetTempPath(strTempPath);
1155 URIUtils::AddSlashAtEnd(strTempPath);
1156 g_advancedSettings.m_logFolder = strTempPath;
1165 bool CApplication::InitDirectoriesOSX()
1167 #if defined(TARGET_DARWIN)
1168 CStdString userName;
1170 userName = getenv("USER");
1174 CStdString userHome;
1176 userHome = getenv("HOME");
1180 CStdString xbmcPath;
1181 CUtil::GetHomePath(xbmcPath);
1182 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1184 #if defined(TARGET_DARWIN_IOS)
1185 CStdString fontconfigPath;
1186 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1187 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1190 // setup path to our internal dylibs so loader can find them
1191 CStdString frameworksPath = CUtil::GetFrameworksPath();
1192 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1194 // OSX always runs with m_bPlatformDirectories == true
1195 if (m_bPlatformDirectories)
1197 // map our special drives
1198 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1199 CSpecialProtocol::SetXBMCPath(xbmcPath);
1200 #if defined(TARGET_DARWIN_IOS)
1201 CSpecialProtocol::SetHomePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC");
1202 CSpecialProtocol::SetMasterProfilePath(userHome + "/" + CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/userdata");
1204 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1205 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1208 // location for temp files
1209 #if defined(TARGET_DARWIN_IOS)
1210 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, CStdString(DarwinGetXbmcRootFolder()) + "/XBMC/temp");
1212 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1213 CDirectory::Create(strTempPath);
1214 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1216 CSpecialProtocol::SetTempPath(strTempPath);
1218 // xbmc.log file location
1219 #if defined(TARGET_DARWIN_IOS)
1220 strTempPath = userHome + "/" + CStdString(DarwinGetXbmcRootFolder());
1222 strTempPath = userHome + "/Library/Logs";
1224 URIUtils::AddSlashAtEnd(strTempPath);
1225 g_advancedSettings.m_logFolder = strTempPath;
1231 URIUtils::AddSlashAtEnd(xbmcPath);
1232 g_advancedSettings.m_logFolder = xbmcPath;
1234 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1235 CSpecialProtocol::SetXBMCPath(xbmcPath);
1236 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1237 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1239 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1240 CSpecialProtocol::SetTempPath(strTempPath);
1242 URIUtils::AddSlashAtEnd(strTempPath);
1243 g_advancedSettings.m_logFolder = strTempPath;
1252 bool CApplication::InitDirectoriesWin32()
1254 #ifdef TARGET_WINDOWS
1255 CStdString xbmcPath;
1257 CUtil::GetHomePath(xbmcPath);
1258 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1259 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1260 CSpecialProtocol::SetXBMCPath(xbmcPath);
1262 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1264 g_advancedSettings.m_logFolder = strWin32UserFolder;
1265 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1266 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1267 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1269 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1273 // Expand the DLL search path with our directories
1274 CWIN32Util::ExtendDllPath();
1282 void CApplication::CreateUserDirs()
1284 CDirectory::Create("special://home/");
1285 CDirectory::Create("special://home/addons");
1286 CDirectory::Create("special://home/addons/packages");
1287 CDirectory::Create("special://home/media");
1288 CDirectory::Create("special://home/sounds");
1289 CDirectory::Create("special://home/system");
1290 CDirectory::Create("special://masterprofile/");
1291 CDirectory::Create("special://temp/");
1292 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1295 bool CApplication::Initialize()
1297 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1298 // turn off cdio logging
1299 cdio_loglevel_default = CDIO_LOG_ERROR;
1302 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1303 // must create these here. Ideally this should be using special://home/ and
1304 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1305 if (!m_bPlatformDirectories)
1308 CDirectory::Create("special://xbmc/language");
1309 CDirectory::Create("special://xbmc/addons");
1310 CDirectory::Create("special://xbmc/sounds");
1313 // Load curl so curl_global_init gets called before any service threads
1314 // are started. Unloading will have no effect as curl is never fully unloaded.
1315 // To quote man curl_global_init:
1316 // "This function is not thread safe. You must not call it when any other
1317 // thread in the program (i.e. a thread sharing the same memory) is running.
1318 // This doesn't just mean no other thread that is using libcurl. Because
1319 // curl_global_init() calls functions of other libraries that are similarly
1320 // thread unsafe, it could conflict with any other thread that
1321 // uses these other libraries."
1322 g_curlInterface.Load();
1323 g_curlInterface.Unload();
1325 // initialize (and update as needed) our databases
1326 CDatabaseManager::Get().Initialize();
1330 // Init DPMS, before creating the corresponding setting control.
1331 m_dpms = new DPMSSupport();
1332 if (g_windowManager.Initialized())
1334 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1336 g_windowManager.Add(new CGUIWindowHome);
1337 g_windowManager.Add(new CGUIWindowPrograms);
1338 g_windowManager.Add(new CGUIWindowPictures);
1339 g_windowManager.Add(new CGUIWindowFileManager);
1340 g_windowManager.Add(new CGUIWindowSettings);
1341 g_windowManager.Add(new CGUIWindowSystemInfo);
1343 g_windowManager.Add(new CGUIWindowTestPatternGL);
1346 g_windowManager.Add(new CGUIWindowTestPatternDX);
1348 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1349 g_windowManager.Add(new CGUIWindowSettingsCategory);
1350 g_windowManager.Add(new CGUIWindowVideoNav);
1351 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1352 g_windowManager.Add(new CGUIWindowLoginScreen);
1353 g_windowManager.Add(new CGUIWindowSettingsProfile);
1354 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1355 g_windowManager.Add(new CGUIWindowAddonBrowser);
1356 g_windowManager.Add(new CGUIWindowScreensaverDim);
1357 g_windowManager.Add(new CGUIWindowDebugInfo);
1358 g_windowManager.Add(new CGUIWindowPointer);
1359 g_windowManager.Add(new CGUIDialogYesNo);
1360 g_windowManager.Add(new CGUIDialogProgress);
1361 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1362 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1363 g_windowManager.Add(new CGUIDialogVolumeBar);
1364 g_windowManager.Add(new CGUIDialogSeekBar);
1365 g_windowManager.Add(new CGUIDialogSubMenu);
1366 g_windowManager.Add(new CGUIDialogContextMenu);
1367 g_windowManager.Add(new CGUIDialogKaiToast);
1368 g_windowManager.Add(new CGUIDialogNumeric);
1369 g_windowManager.Add(new CGUIDialogGamepad);
1370 g_windowManager.Add(new CGUIDialogButtonMenu);
1371 g_windowManager.Add(new CGUIDialogMuteBug);
1372 g_windowManager.Add(new CGUIDialogPlayerControls);
1374 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1375 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1377 g_windowManager.Add(new CGUIDialogSlider);
1378 g_windowManager.Add(new CGUIDialogMusicOSD);
1379 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1380 g_windowManager.Add(new CGUIDialogVideoSettings);
1381 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1382 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1383 // Don't add the filebrowser dialog - it's created and added when it's needed
1384 g_windowManager.Add(new CGUIDialogNetworkSetup);
1385 g_windowManager.Add(new CGUIDialogMediaSource);
1386 g_windowManager.Add(new CGUIDialogProfileSettings);
1387 g_windowManager.Add(new CGUIDialogFavourites);
1388 g_windowManager.Add(new CGUIDialogSongInfo);
1389 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1390 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1391 g_windowManager.Add(new CGUIDialogBusy);
1392 g_windowManager.Add(new CGUIDialogPictureInfo);
1393 g_windowManager.Add(new CGUIDialogAddonInfo);
1394 g_windowManager.Add(new CGUIDialogAddonSettings);
1395 #ifdef HAS_LINUX_NETWORK
1396 g_windowManager.Add(new CGUIDialogAccessPoints);
1399 g_windowManager.Add(new CGUIDialogLockSettings);
1401 g_windowManager.Add(new CGUIDialogContentSettings);
1403 g_windowManager.Add(new CGUIDialogPlayEject);
1405 g_windowManager.Add(new CGUIDialogPeripheralManager);
1406 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1408 g_windowManager.Add(new CGUIDialogMediaFilter);
1409 g_windowManager.Add(new CGUIDialogSubtitles);
1411 g_windowManager.Add(new CGUIWindowMusicPlayList);
1412 g_windowManager.Add(new CGUIWindowMusicSongs);
1413 g_windowManager.Add(new CGUIWindowMusicNav);
1414 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1416 /* Load PVR related Windows and Dialogs */
1417 g_windowManager.Add(new CGUIDialogTeletext);
1418 g_windowManager.Add(new CGUIWindowPVR);
1419 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1420 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1421 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1422 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1423 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1424 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1425 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1426 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1427 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1428 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1430 g_windowManager.Add(new CGUIDialogSelect);
1431 g_windowManager.Add(new CGUIDialogMusicInfo);
1432 g_windowManager.Add(new CGUIDialogOK);
1433 g_windowManager.Add(new CGUIDialogVideoInfo);
1434 g_windowManager.Add(new CGUIDialogTextViewer);
1435 g_windowManager.Add(new CGUIWindowFullScreen);
1436 g_windowManager.Add(new CGUIWindowVisualisation);
1437 g_windowManager.Add(new CGUIWindowSlideShow);
1438 g_windowManager.Add(new CGUIDialogFileStacking);
1440 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1443 g_windowManager.Add(new CGUIDialogVideoOSD);
1444 g_windowManager.Add(new CGUIDialogMusicOverlay);
1445 g_windowManager.Add(new CGUIDialogVideoOverlay);
1446 g_windowManager.Add(new CGUIWindowScreensaver);
1447 g_windowManager.Add(new CGUIWindowWeather);
1448 g_windowManager.Add(new CGUIWindowStartup);
1450 /* window id's 3000 - 3100 are reserved for python */
1452 // Make sure we have at least the default skin
1453 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1454 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1456 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1460 if (g_advancedSettings.m_splashImage)
1461 SAFE_DELETE(m_splash);
1463 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1464 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1465 !CProfilesManager::Get().GetMasterProfile().getLockCode().empty())
1467 g_passwordManager.CheckStartUpLock();
1470 // check if we should use the login screen
1471 if (CProfilesManager::Get().UsingLoginScreen())
1472 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1476 CJSONRPC::Initialize();
1478 ADDON::CAddonMgr::Get().StartServices(false);
1479 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1481 g_windowManager.ActivateWindow(WINDOW_HOME);
1482 StartPVRManager(true);
1486 StartPVRManager(false);
1487 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1490 CStereoscopicsManager::Get().Initialize();
1494 else //No GUI Created
1497 CJSONRPC::Initialize();
1499 ADDON::CAddonMgr::Get().StartServices(false);
1502 g_sysinfo.Refresh();
1504 CLog::Log(LOGINFO, "removing tempfiles");
1505 CUtil::RemoveTempFiles();
1507 if (!CProfilesManager::Get().UsingLoginScreen())
1513 m_slowTimer.StartZero();
1515 #if defined(HAVE_LIBCRYSTALHD)
1516 CCrystalHD::GetInstance();
1519 CAddonMgr::Get().StartServices(true);
1521 CLog::Log(LOGNOTICE, "initialize done");
1523 m_bInitializing = false;
1525 // reset our screensaver (starts timers etc.)
1528 #ifdef HAS_SDL_JOYSTICK
1529 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1530 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1536 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1542 // the callback will take care of starting/stopping webserver
1543 ret = CSettings::Get().SetBool("services.webserver", bStart);
1546 case ES_AIRPLAYSERVER:
1547 // the callback will take care of starting/stopping airplay
1548 ret = CSettings::Get().SetBool("services.airplay", bStart);
1551 case ES_JSONRPCSERVER:
1552 // the callback will take care of starting/stopping jsonrpc server
1553 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1557 // the callback will take care of starting/stopping upnp server
1558 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1561 case ES_UPNPRENDERER:
1562 // the callback will take care of starting/stopping upnp renderer
1563 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1566 case ES_EVENTSERVER:
1567 // the callback will take care of starting/stopping event server
1568 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1572 // the callback will take care of starting/stopping zeroconf
1573 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1580 CSettings::Get().Save();
1585 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1587 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1588 g_PVRManager.Start(true, bOpenPVRWindow);
1591 void CApplication::StopPVRManager()
1593 CLog::Log(LOGINFO, "stopping PVRManager");
1594 if (g_PVRManager.IsPlaying())
1596 g_PVRManager.Stop();
1597 g_EpgContainer.Stop();
1600 void CApplication::StartServices()
1602 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1603 // Start Thread for DVD Mediatype detection
1604 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1605 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1608 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1609 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1610 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1611 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1612 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1613 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1616 void CApplication::StopServices()
1618 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1620 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1621 CLog::Log(LOGNOTICE, "stop dvd detect media");
1622 m_DetectDVDType.StopThread();
1625 g_peripherals.Clear();
1628 void CApplication::OnSettingChanged(const CSetting *setting)
1630 if (setting == NULL)
1633 const std::string &settingId = setting->GetId();
1634 if (settingId == "lookandfeel.skin" ||
1635 settingId == "lookandfeel.font" ||
1636 settingId == "lookandfeel.skincolors")
1638 // if the skin changes and the current theme is not the default one, reset
1639 // the theme to the default value (which will also change lookandfeel.skincolors
1640 // which in turn will reload the skin. Similarly, if the current skin font is not
1641 // the default, reset it as well.
1642 if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.skintheme") != "SKINDEFAULT")
1643 CSettings::Get().SetString("lookandfeel.skintheme", "SKINDEFAULT");
1644 else if (settingId == "lookandfeel.skin" && CSettings::Get().GetString("lookandfeel.font") != "Default")
1645 CSettings::Get().SetString("lookandfeel.font", "Default");
1648 std::string builtin("ReloadSkin");
1649 if (settingId == "lookandfeel.skin" && !m_skinReverting)
1650 builtin += "(confirm)";
1651 CApplicationMessenger::Get().ExecBuiltIn(builtin);
1654 else if (settingId == "lookandfeel.skintheme")
1656 // also set the default color theme
1657 CStdString colorTheme = ((CSettingString*)setting)->GetValue();
1658 URIUtils::RemoveExtension(colorTheme);
1659 if (StringUtils::EqualsNoCase(colorTheme, "Textures"))
1660 colorTheme = "defaults";
1662 // check if we have to change the skin color
1663 // if yes, it will trigger a call to ReloadSkin() in
1664 // it's OnSettingChanged() callback
1665 // if no we have to call ReloadSkin() ourselves
1666 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1667 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1669 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1671 else if (settingId == "lookandfeel.skinzoom")
1673 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1674 g_windowManager.SendThreadMessage(msg);
1676 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1678 // AE is master of audio settings and needs to be informed first
1679 CAEFactory::OnSettingsChange(settingId);
1681 if (settingId == "audiooutput.guisoundmode")
1683 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1685 // this tells player whether to open an audio stream passthrough or PCM
1686 // if this is changed, audio stream has to be reopened
1687 else if (settingId == "audiooutput.passthrough")
1689 CApplicationMessenger::Get().MediaRestart(false);
1692 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1693 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1694 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1695 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1696 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1697 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1698 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1699 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1702 void CApplication::OnSettingAction(const CSetting *setting)
1704 if (setting == NULL)
1707 const std::string &settingId = setting->GetId();
1708 if (settingId == "lookandfeel.skinsettings")
1709 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1710 else if (settingId == "screensaver.preview")
1711 ActivateScreenSaver(true);
1712 else if (settingId == "screensaver.settings")
1715 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1716 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1718 else if (settingId == "videoscreen.guicalibration")
1719 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1720 else if (settingId == "videoscreen.testpattern")
1721 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1724 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1726 if (setting == NULL)
1729 const std::string &settingId = setting->GetId();
1730 if (settingId == "audiooutput.channels")
1732 // check if this is an update from Eden
1733 if (oldSettingId != NULL && oldSettingNode != NULL &&
1734 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1737 CSettingInt* channels = (CSettingInt*)setting;
1738 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1739 ret = channels->SetValue(channels->GetValue() + 1);
1741 // let's just reset the audiodevice settings as well
1742 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1743 CAEFactory::VerifyOutputDevice(audiodevice, false);
1744 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1749 else if (settingId == "screensaver.mode")
1751 CSettingString *screensaverMode = (CSettingString*)setting;
1752 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1753 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1754 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1756 else if (settingId == "scrapers.musicvideosdefault")
1758 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1759 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1761 musicvideoScraper->Reset();
1765 #if defined(HAS_LIBAMCODEC)
1766 else if (settingId == "videoplayer.useamcodec")
1768 // Do not permit amcodec to be used on non-aml platforms.
1769 // The setting will be hidden but the default value is true,
1770 // so change it to false.
1773 CSettingBool *useamcodec = (CSettingBool*)setting;
1774 useamcodec->SetValue(false);
1778 #if defined(TARGET_ANDROID)
1779 else if (settingId == "videoplayer.usemediacodec")
1781 // Do not permit MediaCodec to be used Android platforms that do not have it.
1782 // The setting will be hidden but the default value is true,
1783 // so change it to false.
1784 if (CAndroidFeatures::GetVersion() < 16)
1786 CSettingBool *usemediacodec = (CSettingBool*)setting;
1787 usemediacodec->SetValue(false);
1790 else if (settingId == "videoplayer.usestagefright")
1792 CSettingBool *usestagefright = (CSettingBool*)setting;
1793 usestagefright->SetValue(false);
1800 bool CApplication::OnSettingsSaving() const
1802 // don't save settings when we're busy stopping the application
1803 // a lot of screens try to save settings on deinit and deinit is
1804 // called for every screen when the application is stopping
1811 void CApplication::ReloadSkin(bool confirm/*=false*/)
1813 m_skinReloading = false;
1814 std::string oldSkin = g_SkinInfo ? g_SkinInfo->ID() : "";
1816 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1817 g_windowManager.SendMessage(msg);
1819 // Reload the skin, restoring the previously focused control. We need this as
1820 // the window unload will reset all control states.
1822 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1824 iCtrlID = pWindow->GetFocusedControlID();
1826 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1830 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1831 if (pWindow && pWindow->HasSaveLastControl())
1833 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1834 pWindow->OnMessage(msg3);
1838 if (!m_skinReverting && confirm)
1841 if (!CGUIDialogYesNo::ShowAndGetInput(13123, 13111, -1, -1, -1, -1, cancelled, 10000))
1843 m_skinReverting = true;
1844 if (oldSkin.empty())
1845 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1847 CSettings::Get().SetString("lookandfeel.skin", oldSkin);
1851 m_skinReverting = false;
1854 bool CApplication::Load(const TiXmlNode *settings)
1856 if (settings == NULL)
1859 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1860 if (audioElement != NULL)
1862 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1863 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1864 m_volumeLevel = VOLUME_MAXIMUM;
1870 bool CApplication::Save(TiXmlNode *settings) const
1872 if (settings == NULL)
1875 TiXmlElement volumeNode("audio");
1876 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1877 if (audioNode == NULL)
1880 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1881 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1886 bool CApplication::LoadSkin(const CStdString& skinID)
1888 if (m_skinReloading)
1892 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1894 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1900 void CApplication::LoadSkin(const SkinPtr& skin)
1902 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1905 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1906 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1911 if (!skin->HasSkinFile("Home.xml"))
1913 // failed to find home.xml
1914 // fallback to default skin
1915 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1917 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1918 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1919 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1924 bool bPreviousPlayingState=false;
1925 bool bPreviousRenderingState=false;
1926 if (g_application.m_pPlayer->IsPlayingVideo())
1928 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1929 if (bPreviousPlayingState)
1930 g_application.m_pPlayer->Pause();
1931 #ifdef HAS_VIDEO_PLAYBACK
1932 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1934 g_windowManager.ActivateWindow(WINDOW_HOME);
1935 bPreviousRenderingState = true;
1939 // close the music and video overlays (they're re-opened automatically later)
1940 CSingleLock lock(g_graphicsContext);
1942 // save the current window details
1943 int currentWindow = g_windowManager.GetActiveWindow();
1944 vector<int> currentModelessWindows;
1945 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1949 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1951 g_SkinInfo->Start();
1953 CLog::Log(LOGINFO, " load fonts for skin...");
1954 g_graphicsContext.SetMediaDir(skin->Path());
1955 g_directoryCache.ClearSubPaths(skin->Path());
1956 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1958 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1959 CStdString strFontSet;
1960 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1962 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1963 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1964 CSettings::Get().Save();
1967 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1969 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1971 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1973 // load in the skin strings
1974 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1975 URIUtils::AddSlashAtEnd(langPath);
1977 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1979 g_SkinInfo->LoadIncludes();
1982 start = CurrentHostCounter();
1984 CLog::Log(LOGINFO, " load new skin...");
1986 // Load the user windows
1990 end = CurrentHostCounter();
1991 freq = CurrentHostFrequency();
1992 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1994 CLog::Log(LOGINFO, " initialize new skin...");
1995 g_windowManager.AddMsgTarget(this);
1996 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1997 g_windowManager.AddMsgTarget(&g_infoManager);
1998 g_windowManager.AddMsgTarget(&g_fontManager);
1999 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
2000 g_windowManager.SetCallback(*this);
2001 g_windowManager.Initialize();
2002 CTextureCache::Get().Initialize();
2003 g_audioManager.Enable(true);
2004 g_audioManager.Load();
2006 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
2007 g_windowManager.Add(new CGUIDialogFullScreenInfo);
2009 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
2010 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2011 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
2012 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2013 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
2016 CLog::Log(LOGINFO, " skin loaded...");
2018 // leave the graphics lock
2022 if (currentWindow != WINDOW_INVALID)
2024 g_windowManager.ActivateWindow(currentWindow);
2025 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
2027 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
2028 if (dialog) dialog->Show();
2032 if (g_application.m_pPlayer->IsPlayingVideo())
2034 if (bPreviousPlayingState)
2035 g_application.m_pPlayer->Pause();
2036 if (bPreviousRenderingState)
2037 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
2041 void CApplication::UnloadSkin(bool forReload /* = false */)
2043 m_skinReloading = forReload;
2045 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
2047 g_audioManager.Enable(false);
2049 g_windowManager.DeInitialize();
2050 CTextureCache::Get().Deinitialize();
2052 // remove the skin-dependent window
2053 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
2055 g_TextureManager.Cleanup();
2056 g_largeTextureManager.CleanupUnusedImages(true);
2058 g_fontManager.Clear();
2060 g_colorManager.Clear();
2062 g_infoManager.Clear();
2064 // The g_SkinInfo boost shared_ptr ought to be reset here
2065 // but there are too many places it's used without checking for NULL
2066 // and as a result a race condition on exit can cause a crash.
2069 bool CApplication::LoadUserWindows()
2071 // Start from wherever home.xml is
2072 std::vector<CStdString> vecSkinPath;
2073 g_SkinInfo->GetSkinPaths(vecSkinPath);
2074 for (unsigned int i = 0;i < vecSkinPath.size();++i)
2076 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
2077 CFileItemList items;
2078 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
2080 for (int i = 0; i < items.Size(); ++i)
2082 if (items[i]->m_bIsFolder)
2084 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
2085 if (StringUtils::StartsWithNoCase(skinFile, "custom"))
2087 CXBMCTinyXML xmlDoc;
2088 if (!xmlDoc.LoadFile(items[i]->GetPath()))
2090 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
2094 // Root element should be <window>
2095 TiXmlElement* pRootElement = xmlDoc.RootElement();
2096 CStdString strValue = pRootElement->Value();
2097 if (!strValue.Equals("window"))
2099 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
2103 // Read the <type> element to get the window type to create
2104 // If no type is specified, create a CGUIWindow as default
2105 CGUIWindow* pWindow = NULL;
2107 if (pRootElement->Attribute("type"))
2108 strType = pRootElement->Attribute("type");
2111 const TiXmlNode *pType = pRootElement->FirstChild("type");
2112 if (pType && pType->FirstChild())
2113 strType = pType->FirstChild()->Value();
2115 int id = WINDOW_INVALID;
2116 if (!pRootElement->Attribute("id", &id))
2118 const TiXmlNode *pType = pRootElement->FirstChild("id");
2119 if (pType && pType->FirstChild())
2120 id = atol(pType->FirstChild()->Value());
2122 CStdString visibleCondition;
2123 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
2125 if (strType.Equals("dialog"))
2126 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
2127 else if (strType.Equals("submenu"))
2128 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2129 else if (strType.Equals("buttonmenu"))
2130 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2132 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2134 // Check to make sure the pointer isn't still null
2135 if (pWindow == NULL)
2137 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2140 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2145 pWindow->SetVisibleCondition(visibleCondition);
2146 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2147 g_windowManager.AddCustomWindow(pWindow);
2155 bool CApplication::RenderNoPresent()
2159 // DXMERGE: This may have been important?
2160 // g_graphicsContext.AcquireCurrentContext();
2162 g_graphicsContext.Lock();
2164 // dont show GUI when playing full screen video
2165 if (g_graphicsContext.IsFullScreenVideo())
2167 g_graphicsContext.SetRenderingResolution(g_graphicsContext.GetVideoResolution(), false);
2168 g_renderManager.Render(true, 0, 255);
2170 // close window overlays
2171 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2172 if (overlay) overlay->Close(true);
2173 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2174 if (overlay) overlay->Close(true);
2178 bool hasRendered = g_windowManager.Render();
2180 g_graphicsContext.Unlock();
2185 float CApplication::GetDimScreenSaverLevel() const
2187 if (!m_bScreenSave || !m_screenSaver ||
2188 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2189 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2190 !m_screenSaver->ID().empty()))
2193 if (!m_screenSaver->GetSetting("level").empty())
2194 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2198 void CApplication::Render()
2200 // do not render if we are stopped or in background
2201 if (m_bStop || m_bInBackground)
2206 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2208 bool hasRendered = false;
2209 bool limitFrames = false;
2210 unsigned int singleFrameTime = 10; // default limit 100 fps
2214 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2215 // Whether externalplayer is playing and we're unfocused
2216 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2218 m_bPresentFrame = false;
2219 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2221 m_bPresentFrame = g_renderManager.FrameWait(100);
2226 // engage the frame limiter as needed
2227 limitFrames = lowfps || extPlayerActive;
2228 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2229 // perhaps allowing it to be set differently than the UI option??
2230 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2231 limitFrames = true; // not using vsync.
2232 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2233 limitFrames = true; // using vsync, but it isn't working.
2237 if (extPlayerActive)
2239 ResetScreenSaver(); // Prevent screensaver dimming the screen
2240 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2243 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2249 CSingleLock lock(g_graphicsContext);
2250 g_infoManager.UpdateFPS();
2252 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2253 g_Windowing.SetVSync(true);
2254 else if (vsync_mode == VSYNC_ALWAYS)
2255 g_Windowing.SetVSync(true);
2256 else if (vsync_mode != VSYNC_DRIVER)
2257 g_Windowing.SetVSync(false);
2259 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2262 if(!g_Windowing.BeginRender())
2265 g_renderManager.FrameMove();
2267 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2268 if(g_graphicsContext.GetStereoMode())
2270 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2271 if(RenderNoPresent())
2274 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2276 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2277 if(RenderNoPresent())
2280 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2284 if(RenderNoPresent())
2288 g_renderManager.FrameFinish();
2290 g_Windowing.EndRender();
2292 // execute post rendering actions (finalize window closing)
2293 g_windowManager.AfterRender();
2295 // reset our info cache - we do this at the end of Render so that it is
2296 // fresh for the next process(), or after a windowclose animation (where process()
2298 g_infoManager.ResetCache();
2301 unsigned int now = XbmcThreads::SystemClockMillis();
2303 m_lastRenderTime = now;
2305 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2306 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2308 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2309 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2313 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2314 if (limitFrames || !flip)
2317 singleFrameTime = 40; //if not flipping, loop at 25 fps
2319 unsigned int frameTime = now - m_lastFrameTime;
2320 if (frameTime < singleFrameTime)
2321 Sleep(singleFrameTime - frameTime);
2323 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2326 g_graphicsContext.Flip(dirtyRegions);
2327 CTimeUtils::UpdateFrameTime(flip);
2329 g_renderManager.UpdateResolution();
2330 g_renderManager.ManageCaptures();
2333 void CApplication::SetStandAlone(bool value)
2335 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2338 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2339 // The window manager will return true if the event is processed, false otherwise.
2340 // If not already processed, this routine handles global keypresses. It returns
2341 // true if the key has been processed, false otherwise.
2343 bool CApplication::OnKey(const CKey& key)
2346 // Turn the mouse off, as we've just got a keypress from controller or remote
2347 g_Mouse.SetActive(false);
2349 // get the current active window
2350 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2352 // this will be checked for certain keycodes that need
2353 // special handling if the screensaver is active
2354 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2356 // a key has been pressed.
2358 m_idleTimer.StartZero();
2359 bool processKey = AlwaysProcess(action);
2361 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2365 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2366 // do not wake up the screensaver right after switching off the playing device
2367 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2368 ret = CApplicationMessenger::Get().CECToggleState();
2370 ret = CApplicationMessenger::Get().CECStandby();
2371 if (!ret) /* display is switched off */
2377 // allow some keys to be processed while the screensaver is active
2378 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2380 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2384 // change this if we have a dialog up
2385 if (g_windowManager.HasModalDialog())
2387 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2389 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2390 { // fullscreen info dialog - special case
2391 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2393 if (!key.IsAnalogButton())
2394 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2396 if (OnAction(action))
2399 // fallthrough to the main window
2400 iWin = WINDOW_FULLSCREEN_VIDEO;
2402 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2404 // current active window is full screen video.
2405 if (g_application.m_pPlayer->IsInMenu())
2407 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2408 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2410 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2412 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2413 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2415 // if no PVR specific action/mapping is found, fall back to default
2416 if (action.GetID() == 0)
2417 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2421 // in any other case use the fullscreen window section of keymap.xml to map key->action
2422 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2427 // current active window isnt the fullscreen window
2428 // just use corresponding section from keymap.xml
2429 // to map key->action
2431 // first determine if we should use keyboard input directly
2432 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2433 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2436 CGUIControl *control = window->GetFocusedControl();
2439 // If this is an edit control set usekeyboard to true. This causes the
2440 // keypress to be processed directly not through the key mappings.
2441 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2444 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2445 // This causes the keypress to be used for list navigation.
2446 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2452 action = CAction(0); // reset our action
2453 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2455 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2456 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2457 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2458 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2459 action.GetID() == ACTION_MOVE_RIGHT ||
2460 action.GetID() == ACTION_MOVE_UP ||
2461 action.GetID() == ACTION_MOVE_DOWN ||
2462 action.GetID() == ACTION_SELECT_ITEM ||
2463 action.GetID() == ACTION_ENTER ||
2464 action.GetID() == ACTION_PREVIOUS_MENU ||
2465 action.GetID() == ACTION_NAV_BACK))
2467 // the action isn't plain navigation - check for a keyboard-specific keymap
2468 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2469 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2470 action.GetID() == ACTION_BACKSPACE ||
2471 action.GetID() == ACTION_SHIFT ||
2472 action.GetID() == ACTION_SYMBOLS ||
2473 action.GetID() == ACTION_CURSOR_LEFT ||
2474 action.GetID() == ACTION_CURSOR_RIGHT)
2475 action = CAction(0); // don't bother with this action
2478 if (!action.GetID())
2480 // keyboard entry - pass the keys through directly
2481 if (key.GetFromService())
2482 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2485 // Check for paste keypress
2486 #ifdef TARGET_WINDOWS
2487 // In Windows paste is ctrl-V
2488 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2489 #elif defined(TARGET_LINUX)
2490 // In Linux paste is ctrl-V
2491 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2492 #elif defined(TARGET_DARWIN_OSX)
2493 // In OSX paste is cmd-V
2494 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2496 // Placeholder for other operating systems
2499 action = CAction(ACTION_PASTE);
2500 // If the unicode is non-zero the keypress is a non-printing character
2501 else if (key.GetUnicode())
2502 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2503 // The keypress is a non-printing character
2505 action = CAction(key.GetVKey() | KEY_VKEY);
2509 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2511 if (OnAction(action))
2513 // failed to handle the keyboard action, drop down through to standard action
2515 if (key.GetFromService())
2517 if (key.GetButtonCode() != KEY_INVALID)
2518 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2521 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2523 if (!key.IsAnalogButton())
2524 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2526 return ExecuteInputAction(action);
2529 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2530 // This needs to return true if it processed the appcommand or false if it didn't
2531 bool CApplication::OnAppCommand(const CAction &action)
2533 // Reset the screen saver
2536 // If we were currently in the screen saver wake up and don't process the appcommand
2537 if (WakeUpScreenSaverAndDPMS())
2540 // The action ID is the APPCOMMAND code. We need to retrieve the action
2541 // associated with this appcommand from the mapping table.
2542 uint32_t appcmd = action.GetID();
2543 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2544 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2545 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2547 // If we couldn't find an action return false to indicate we have not
2548 // handled this appcommand
2549 if (!appcmdaction.GetID())
2551 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2555 // Process the appcommand
2556 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2557 OnAction(appcmdaction);
2559 // Always return true regardless of whether the action succeeded or not.
2560 // This stops Windows handling the appcommand itself.
2564 bool CApplication::OnAction(const CAction &action)
2566 // special case for switching between GUI & fullscreen mode.
2567 if (action.GetID() == ACTION_SHOW_GUI)
2568 { // Switch to fullscreen mode if we can
2569 if (SwitchToFullScreen())
2571 m_navigationTimer.StartZero();
2576 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2578 g_graphicsContext.ToggleFullScreenRoot();
2582 if (action.IsMouse())
2583 g_Mouse.SetActive(true);
2586 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2588 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2590 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2592 CGUIDialogVideoBookmarks::OnAddBookmark();
2595 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2596 // playing or ACTION_PLAYER_PLAY if we are not playing.
2597 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2599 if (m_pPlayer->IsPlaying())
2600 return OnAction(CAction(ACTION_PAUSE));
2602 return OnAction(CAction(ACTION_PLAYER_PLAY));
2605 //if the action would start or stop inertial scrolling
2606 //by gesture - bypass the normal OnAction handler of current window
2607 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2610 // just pass the action to the current window and let it handle it
2611 if (g_windowManager.OnAction(action))
2613 m_navigationTimer.StartZero();
2618 // handle extra global presses
2620 // screenshot : take a screenshot :)
2621 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2623 CScreenShot::TakeScreenshot();
2626 // built in functions : execute the built-in
2627 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2629 CBuiltins::Execute(action.GetName());
2630 m_navigationTimer.StartZero();
2635 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2637 CButtonTranslator::GetInstance().Clear();
2638 CButtonTranslator::GetInstance().Load();
2641 // show info : Shows the current video or song information
2642 if (action.GetID() == ACTION_SHOW_INFO)
2644 g_infoManager.ToggleShowInfo();
2648 // codec info : Shows the current song, video or picture codec information
2649 if (action.GetID() == ACTION_SHOW_CODEC)
2651 g_infoManager.ToggleShowCodec();
2655 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2657 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2660 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2661 char rating = tag->GetRating();
2662 bool needsUpdate(false);
2663 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2665 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2668 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2670 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2676 if (db.Open()) // OpenForWrite() ?
2678 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2681 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2682 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2683 g_windowManager.SendMessage(msg);
2689 // Now check with the playlist player if action can be handled.
2690 // 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.
2691 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2693 if (g_playlistPlayer.OnAction(action))
2697 // Now check with the player if action can be handled.
2698 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2699 (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)) ||
2700 action.GetID() == ACTION_STOP)
2702 if (m_pPlayer->OnAction(action))
2706 // stop : stops playing current audio song
2707 if (action.GetID() == ACTION_STOP)
2713 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2714 // If so, we just jump to the start of the track.
2715 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2718 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2722 // forward action to g_PVRManager and break if it was able to handle it
2723 if (g_PVRManager.OnAction(action))
2726 // forward action to graphic context and see if it can handle it
2727 if (CStereoscopicsManager::Get().OnAction(action))
2730 if (m_pPlayer->IsPlaying())
2732 // forward channel switches to the player - he knows what to do
2733 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2735 m_pPlayer->OnAction(action);
2739 // pause : pauses current audio song
2740 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2744 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2746 if (!m_pPlayer->IsPaused())
2747 { // unpaused - set the playspeed back to normal
2748 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2750 g_audioManager.Enable(m_pPlayer->IsPaused());
2753 if (!m_pPlayer->IsPaused())
2755 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2756 // if we are playing at normal speed, then allow play to pause
2757 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2759 if (m_pPlayer->GetPlaySpeed() != 1)
2761 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2769 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2771 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2772 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2774 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2776 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2781 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2783 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2786 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2789 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2791 // calculate the speed based on the amount the button is held down
2792 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2793 // returns 0 -> MAX_FFWD_SPEED
2794 int iSpeed = 1 << iPower;
2795 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2797 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2799 CLog::Log(LOGDEBUG,"Resetting playspeed");
2803 // allow play to unpause
2806 if (action.GetID() == ACTION_PLAYER_PLAY)
2808 // unpause, and set the playspeed back to normal
2810 g_audioManager.Enable(m_pPlayer->IsPaused());
2812 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2817 // record current file
2818 if (action.GetID() == ACTION_RECORD)
2820 if (m_pPlayer->CanRecord())
2821 m_pPlayer->Record(!m_pPlayer->IsRecording());
2824 if (m_playerController->OnAction(action))
2829 if (action.GetID() == ACTION_SWITCH_PLAYER)
2831 if(m_pPlayer->IsPlaying())
2833 VECPLAYERCORES cores;
2834 CFileItem item(*m_itemCurrentFile.get());
2835 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2836 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2837 if(core != EPC_NONE)
2839 g_application.m_eForcedNextPlayer = core;
2840 item.m_lStartOffset = (int)(GetTime() * 75);
2841 PlayFile(item, true);
2846 VECPLAYERCORES cores;
2847 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2848 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2849 if(core != EPC_NONE)
2852 g_application.m_eForcedNextPlayer = core;
2853 PlayFile(item, false);
2858 if (g_peripherals.OnAction(action))
2861 if (action.GetID() == ACTION_MUTE)
2867 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2869 bool passthrough = CSettings::Get().GetBool("audiooutput.passthrough");
2870 CSettings::Get().SetBool("audiooutput.passthrough", !passthrough);
2872 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2874 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2875 g_windowManager.SendMessage(msg);
2880 // Check for global volume control
2881 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2883 if (!m_pPlayer->IsPassthrough())
2887 float volume = m_volumeLevel;
2888 // Android has steps based on the max available volume level
2889 #if defined(TARGET_ANDROID)
2890 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2892 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2894 if (action.GetRepeat())
2895 step *= action.GetRepeat() * 50; // 50 fps
2897 if (action.GetID() == ACTION_VOLUME_UP)
2898 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2900 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2901 SetVolume(volume, false);
2903 // show visual feedback of volume change...
2904 ShowVolumeBar(&action);
2907 // Check for global seek control
2908 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2910 if (!m_pPlayer->CanSeek()) return false;
2911 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2914 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2916 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2917 CGUIControlProfiler::Instance().Start();
2920 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2922 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2923 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2924 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2925 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2926 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2932 void CApplication::FrameMove(bool processEvents, bool processGUI)
2938 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2939 float frameTime = m_frameTime.GetElapsedSeconds();
2940 m_frameTime.StartZero();
2941 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2942 if( frameTime > 0.5 ) frameTime = 0.5;
2944 if (processGUI && m_renderGUI)
2946 g_graphicsContext.Lock();
2947 // check if there are notifications to display
2948 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2949 if (toast && toast->DoWork())
2951 if (!toast->IsDialogRunning())
2956 g_graphicsContext.Unlock();
2958 CWinEvents::MessagePump();
2960 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2961 // Read the input from a remote
2962 g_RemoteControl.Update();
2965 // process input actions
2966 ProcessRemote(frameTime);
2967 ProcessGamepad(frameTime);
2968 ProcessEventServer(frameTime);
2969 ProcessPeripherals(frameTime);
2970 if (processGUI && m_renderGUI)
2972 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2973 m_seekHandler->Process();
2976 if (processGUI && m_renderGUI)
2979 g_windowManager.Process(CTimeUtils::GetFrameTime());
2980 g_windowManager.FrameMove();
2984 bool CApplication::ProcessGamepad(float frameTime)
2986 #ifdef HAS_SDL_JOYSTICK
2990 int iWin = GetActiveWindowID();
2992 g_Joystick.Update();
2993 if (g_Joystick.GetButton(bid))
2996 m_idleTimer.StartZero();
2999 if (WakeUpScreenSaverAndDPMS())
3001 g_Joystick.Reset(true);
3006 CStdString actionName;
3008 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
3010 CAction action(actionID, 1.0f, 0.0f, actionName);
3012 g_Mouse.SetActive(false);
3013 return ExecuteInputAction(action);
3020 if (g_Joystick.GetAxis(bid))
3022 if (g_Joystick.GetAmount() < 0)
3028 CStdString actionName;
3030 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
3033 if (WakeUpScreenSaverAndDPMS())
3038 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
3040 g_Mouse.SetActive(false);
3041 return ExecuteInputAction(action);
3045 g_Joystick.ResetAxis(abs(bid));
3049 if (g_Joystick.GetHat(bid, position))
3052 m_idleTimer.StartZero();
3055 if (WakeUpScreenSaverAndDPMS())
3062 CStdString actionName;
3065 bid = position<<16|bid;
3067 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
3069 CAction action(actionID, 1.0f, 0.0f, actionName);
3071 g_Mouse.SetActive(false);
3072 return ExecuteInputAction(action);
3079 bool CApplication::ProcessRemote(float frameTime)
3081 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3082 if (g_RemoteControl.GetButton())
3084 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
3085 g_RemoteControl.Reset();
3092 bool CApplication::ProcessPeripherals(float frameTime)
3095 if (g_peripherals.GetNextKeypress(frameTime, key))
3100 bool CApplication::ProcessMouse()
3104 if (!g_Mouse.IsActive() || !m_AppFocused)
3107 // Get the mouse command ID
3108 uint32_t mousecommand = g_Mouse.GetAction();
3109 if (mousecommand == ACTION_NOOP)
3112 // Reset the screensaver and idle timers
3113 m_idleTimer.StartZero();
3115 if (WakeUpScreenSaverAndDPMS())
3118 // Retrieve the corresponding action
3119 int iWin = GetActiveWindowID();
3120 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
3121 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
3123 // Deactivate mouse if non-mouse action
3124 if (!mouseaction.IsMouse())
3125 g_Mouse.SetActive(false);
3127 // Consume ACTION_NOOP.
3128 // Some views or dialogs gets closed after any ACTION and
3129 // a sensitive mouse might cause problems.
3130 if (mouseaction.GetID() == ACTION_NOOP)
3133 // If we couldn't find an action return false to indicate we have not
3134 // handled this mouse action
3135 if (!mouseaction.GetID())
3137 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3141 // Log mouse actions except for move and noop
3142 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3143 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3145 // The action might not be a mouse action. For example wheel moves might
3146 // be mapped to volume up/down in mouse.xml. In this case we do not want
3147 // the mouse position saved in the action.
3148 if (!mouseaction.IsMouse())
3149 return OnAction(mouseaction);
3151 // This is a mouse action so we need to record the mouse position
3152 return OnAction(CAction(mouseaction.GetID(),
3153 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3154 (float)g_Mouse.GetX(),
3155 (float)g_Mouse.GetY(),
3156 (float)g_Mouse.GetDX(),
3157 (float)g_Mouse.GetDY(),
3158 mouseaction.GetName()));
3161 bool CApplication::ProcessEventServer(float frameTime)
3163 #ifdef HAS_EVENT_SERVER
3164 CEventServer* es = CEventServer::GetInstance();
3165 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3168 // process any queued up actions
3169 if (es->ExecuteNextAction())
3171 // reset idle timers
3172 m_idleTimer.StartZero();
3174 WakeUpScreenSaverAndDPMS();
3177 // now handle any buttons or axis
3178 std::string joystickName;
3179 bool isAxis = false;
3180 float fAmount = 0.0;
3182 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3183 // when the action exits XBMC
3184 es = CEventServer::GetInstance();
3185 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3187 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3191 if (joystickName.length() > 0)
3195 if (fabs(fAmount) >= 0.08)
3196 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3198 m_lastAxisMap[joystickName].erase(wKeyID);
3201 return ProcessJoystickEvent(joystickName, wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, fAmount);
3206 if (wKeyID & ES_FLAG_UNICODE)
3208 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3212 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3213 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3214 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3215 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3216 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3217 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3218 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3219 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3220 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3221 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3222 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3223 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3224 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3225 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3226 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3227 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3228 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3229 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3230 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3231 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3234 key.SetFromService(true);
3239 if (m_lastAxisMap.size() > 0)
3241 // Process all the stored axis.
3242 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3244 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3245 ProcessJoystickEvent((*iter).first, (*iterAxis).first, JACTIVE_AXIS, (*iterAxis).second);
3251 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3253 XBMC_Event newEvent;
3254 newEvent.type = XBMC_MOUSEMOTION;
3255 newEvent.motion.xrel = 0;
3256 newEvent.motion.yrel = 0;
3257 newEvent.motion.state = 0;
3258 newEvent.motion.which = 0x10; // just a different value to distinguish between mouse and event client device.
3259 newEvent.motion.x = (uint16_t)pos.x;
3260 newEvent.motion.y = (uint16_t)pos.y;
3261 OnEvent(newEvent); // had to call this to update g_Mouse position
3262 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3269 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, short inputType, float fAmount, unsigned int holdTime /*=0*/)
3271 #if defined(HAS_EVENT_SERVER)
3272 m_idleTimer.StartZero();
3274 // Make sure to reset screen saver, mouse.
3276 if (WakeUpScreenSaverAndDPMS())
3279 #ifdef HAS_SDL_JOYSTICK
3282 g_Mouse.SetActive(false);
3284 int iWin = GetActiveWindowID();
3286 CStdString actionName;
3287 bool fullRange = false;
3289 // Translate using regular joystick translator.
3290 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, inputType, actionID, actionName, fullRange))
3291 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3293 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3299 bool CApplication::ExecuteInputAction(const CAction &action)
3301 bool bResult = false;
3303 // play sound before the action unless the button is held,
3304 // where we execute after the action as held actions aren't fired every time.
3305 if(action.GetHoldTime())
3307 bResult = OnAction(action);
3309 g_audioManager.PlayActionSound(action);
3313 g_audioManager.PlayActionSound(action);
3314 bResult = OnAction(action);
3319 int CApplication::GetActiveWindowID(void)
3321 // Get the currently active window
3322 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3324 // If there is a dialog active get the dialog id instead
3325 if (g_windowManager.HasModalDialog())
3326 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3328 // If the window is FullScreenVideo check for special cases
3329 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3331 // check if we're in a DVD menu
3332 if(g_application.m_pPlayer->IsInMenu())
3333 iWin = WINDOW_VIDEO_MENU;
3334 // check for LiveTV and switch to it's virtual window
3335 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3336 iWin = WINDOW_FULLSCREEN_LIVETV;
3339 // Return the window id
3343 bool CApplication::Cleanup()
3347 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3348 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3349 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3350 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3351 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3352 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3353 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3354 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3355 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3356 g_windowManager.Delete(WINDOW_FILES);
3357 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3358 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3359 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3360 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3361 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3362 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3363 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3364 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3365 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3366 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3367 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3368 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3369 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3370 g_windowManager.Delete(WINDOW_DIALOG_OK);
3371 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3372 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3373 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3374 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3375 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3376 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3377 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3378 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3379 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3380 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3381 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3382 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3383 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3384 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3385 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3386 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3387 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3388 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3389 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3390 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3391 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3392 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3393 g_windowManager.Delete(WINDOW_DIALOG_SUBTITLES);
3395 /* Delete PVR related windows and dialogs */
3396 g_windowManager.Delete(WINDOW_PVR);
3397 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3398 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3399 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3400 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3401 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3402 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3403 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3404 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3405 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3406 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3407 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3408 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3409 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3411 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3412 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3413 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3414 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3415 g_windowManager.Delete(WINDOW_VISUALISATION);
3416 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3417 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3418 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3419 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3420 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3421 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3422 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3423 g_windowManager.Delete(WINDOW_SCREENSAVER);
3424 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3425 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3426 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3427 g_windowManager.Delete(WINDOW_SLIDESHOW);
3428 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3429 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3431 g_windowManager.Delete(WINDOW_HOME);
3432 g_windowManager.Delete(WINDOW_PROGRAMS);
3433 g_windowManager.Delete(WINDOW_PICTURES);
3434 g_windowManager.Delete(WINDOW_WEATHER);
3436 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3437 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3438 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3439 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3440 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3441 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3442 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3443 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3444 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3445 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3447 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3448 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3450 CAddonMgr::Get().DeInit();
3452 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3453 CLog::Log(LOGNOTICE, "closing down remote control service");
3454 g_RemoteControl.Disconnect();
3457 CLog::Log(LOGNOTICE, "unload sections");
3459 #ifdef HAS_PERFORMANCE_SAMPLE
3460 CLog::Log(LOGNOTICE, "performance statistics");
3461 m_perfStats.DumpStats();
3464 // Shutdown as much as possible of the
3465 // application, to reduce the leaks dumped
3466 // to the vc output window before calling
3467 // _CrtDumpMemoryLeaks(). Most of the leaks
3468 // shown are no real leaks, as parts of the app
3469 // are still allocated.
3471 g_localizeStrings.Clear();
3472 g_LangCodeExpander.Clear();
3473 g_charsetConverter.clear();
3474 g_directoryCache.Clear();
3475 CButtonTranslator::GetInstance().Clear();
3476 #ifdef HAS_EVENT_SERVER
3477 CEventServer::RemoveInstance();
3479 DllLoaderContainer::Clear();
3480 g_playlistPlayer.Clear();
3481 CSettings::Get().Uninitialize();
3482 g_advancedSettings.Clear();
3485 CXHandle::DumpObjectTracker();
3487 #ifdef HAS_DVD_DRIVE
3488 CLibcdio::ReleaseInstance();
3491 #if defined(TARGET_ANDROID)
3492 // enable for all platforms once it's safe
3493 g_sectionLoader.UnloadAll();
3495 #ifdef _CRTDBG_MAP_ALLOC
3496 _CrtDumpMemoryLeaks();
3497 while(1); // execution ends
3507 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3512 void CApplication::Stop(int exitCode)
3516 CVariant vExitCode(exitCode);
3517 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3519 SaveFileState(true);
3521 g_alarmClock.StopThread();
3523 if( m_bSystemScreenSaverEnable )
3524 g_Windowing.EnableSystemScreenSaver(true);
3526 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3527 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3529 // Update the settings information (volume, uptime etc. need saving)
3530 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3532 CLog::Log(LOGNOTICE, "Saving settings");
3533 CSettings::Get().Save();
3536 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3539 m_AppFocused = false;
3540 m_ExitCode = exitCode;
3541 CLog::Log(LOGNOTICE, "stop all");
3543 // cancel any jobs from the jobmanager
3544 CJobManager::GetInstance().CancelJobs();
3546 // stop scanning before we kill the network and so on
3547 if (m_musicInfoScanner->IsScanning())
3548 m_musicInfoScanner->Stop();
3550 if (m_videoInfoScanner->IsScanning())
3551 m_videoInfoScanner->Stop();
3553 CApplicationMessenger::Get().Cleanup();
3555 CLog::Log(LOGNOTICE, "stop player");
3556 m_pPlayer->ClosePlayer();
3558 CAnnouncementManager::Deinitialize();
3564 #if HAS_FILESYTEM_DAAP
3565 CLog::Log(LOGNOTICE, "stop daap clients");
3566 g_DaapClient.Release();
3568 #ifdef HAS_FILESYSTEM_SAP
3569 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3570 g_sapsessions.StopThread();
3573 if(CZeroconfBrowser::IsInstantiated())
3575 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3576 CZeroconfBrowser::GetInstance()->Stop();
3577 CZeroconfBrowser::ReleaseInstance();
3581 CLog::Log(LOGNOTICE, "clean cached files!");
3582 #ifdef HAS_FILESYSTEM_RAR
3583 g_RarManager.ClearCache(true);
3586 #ifdef HAS_FILESYSTEM_SFTP
3587 CSFTPSessionManager::DisconnectAllSessions();
3590 CLog::Log(LOGNOTICE, "unload skin");
3593 #if defined(TARGET_DARWIN_OSX)
3594 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3595 XBMCHelper::GetInstance().Stop();
3598 #if defined(HAVE_LIBCRYSTALHD)
3599 CCrystalHD::RemoveInstance();
3602 g_mediaManager.Stop();
3604 // Stop services before unloading Python
3605 CAddonMgr::Get().StopServices(false);
3607 // stop all remaining scripts; must be done after skin has been unloaded,
3608 // not before some windows still need it when deinitializing during skin
3610 CScriptInvocationManager::Get().Uninitialize();
3612 g_Windowing.DestroyRenderSystem();
3613 g_Windowing.DestroyWindow();
3614 g_Windowing.DestroyWindowSystem();
3616 // shutdown the AudioEngine
3617 CAEFactory::Shutdown();
3618 CAEFactory::UnLoadEngine();
3620 CLog::Log(LOGNOTICE, "stopped");
3624 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3627 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3628 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3635 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3637 //If item is a plugin, expand out now and run ourselves again
3638 if (item.IsPlugin())
3640 CFileItem item_new(item);
3641 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3642 return PlayMedia(item_new, iPlaylist);
3645 if (item.IsSmartPlayList())
3647 CFileItemList items;
3648 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3651 CSmartPlaylist smartpl;
3652 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3653 smartpl.OpenAndReadName(item.GetPath());
3655 playlist.Add(items);
3656 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3659 else if (item.IsPlayList() || item.IsInternetStream())
3661 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3663 //is or could be a playlist
3664 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3665 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3670 if (dlgCache->IsCanceled())
3677 if (iPlaylist != PLAYLIST_NONE)
3680 if (item.HasProperty("playlist_starting_track"))
3681 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3682 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3686 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());
3687 if(pPlayList->size())
3688 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3693 //nothing special just play
3694 return PlayFile(item, false) == PLAYBACK_OK;
3698 // For playing a multi-file video. Particularly inefficient
3699 // on startup, as we are required to calculate the length
3700 // of each video, so we open + close each one in turn.
3701 // A faster calculation of video time would improve this
3703 // return value: same with PlayFile()
3704 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3706 if (!item.IsStack())
3707 return PLAYBACK_FAIL;
3711 // case 1: stacked ISOs
3712 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3714 CStackDirectory dir;
3715 CFileItemList movieList;
3716 dir.GetDirectory(item.GetPath(), movieList);
3718 // first assume values passed to the stack
3719 int selectedFile = item.m_lStartPartNumber;
3720 int startoffset = item.m_lStartOffset;
3722 // check if we instructed the stack to resume from default
3723 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3728 CStdString path = item.GetPath();
3729 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3730 path = item.GetProperty("original_listitem_url").asString();
3731 if( dbs.GetResumeBookMark(path, bookmark) )
3733 startoffset = (int)(bookmark.timeInSeconds*75);
3734 selectedFile = bookmark.partNumber;
3739 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3742 // make sure that the selected part is within the boundaries
3743 if (selectedFile <= 0)
3745 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3748 else if (selectedFile > movieList.Size())
3750 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3751 selectedFile = movieList.Size();
3754 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3755 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3756 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3757 *m_stackFileItemToUpdate = item;
3758 return PlayFile(*(movieList[selectedFile - 1]));
3760 // case 2: all other stacks
3763 // see if we have the info in the database
3764 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3765 // then these times will be wrong.
3766 // Also, this is really just a hack for the slow load up times we have
3767 // A much better solution is a fast reader of FPS and fileLength
3768 // that we can use on a file to get it's time.
3770 bool haveTimes(false);
3774 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3775 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3780 // calculate the total time of the stack
3781 CStackDirectory dir;
3782 dir.GetDirectory(item.GetPath(), *m_currentStack);
3784 for (int i = 0; i < m_currentStack->Size(); i++)
3787 (*m_currentStack)[i]->m_lEndOffset = times[i];
3791 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3793 m_currentStack->Clear();
3794 return PLAYBACK_FAIL;
3796 totalTime += duration / 1000;
3797 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3798 times.push_back(totalTime);
3802 double seconds = item.m_lStartOffset / 75.0;
3804 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3805 { // have our times now, so update the dB
3809 dbs.SetStackTimes(item.GetPath(), times);
3811 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3813 // can only resume seek here, not dvdstate
3815 CStdString path = item.GetPath();
3816 if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3817 path = item.GetProperty("original_listitem_url").asString();
3818 if( dbs.GetResumeBookMark(path, bookmark) )
3819 seconds = bookmark.timeInSeconds;
3827 *m_itemCurrentFile = item;
3828 m_currentStackPosition = 0;
3829 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3833 // work out where to seek to
3834 for (int i = 0; i < m_currentStack->Size(); i++)
3836 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3838 CFileItem item(*(*m_currentStack)[i]);
3839 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3840 item.m_lStartOffset = (long)(seconds - start) * 75;
3841 m_currentStackPosition = i;
3842 return PlayFile(item, true);
3847 return PlayFile(*(*m_currentStack)[0], true);
3849 return PLAYBACK_FAIL;
3852 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3854 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3855 if (item.GetMimeType().empty())
3856 const_cast<CFileItem&>(item).FillInMimeType();
3860 SaveCurrentFileSettings();
3862 OutputDebugString("new file set audiostream:0\n");
3863 // Switch to default options
3864 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3865 // see if we have saved options in the database
3867 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3868 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3870 *m_itemCurrentFile = item;
3871 m_nextPlaylistItem = -1;
3872 m_currentStackPosition = 0;
3873 m_currentStack->Clear();
3876 CUtil::ClearSubtitles();
3879 if (item.IsDiscStub())
3881 #ifdef HAS_DVD_DRIVE
3882 // Display the Play Eject dialog if there is any optical disc drive
3883 if (g_mediaManager.HasOpticalDrive())
3885 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3886 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3887 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3888 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3892 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3897 if (item.IsPlayList())
3898 return PLAYBACK_FAIL;
3900 if (item.IsPlugin())
3901 { // we modify the item so that it becomes a real URL
3902 CFileItem item_new(item);
3903 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3904 return PlayFile(item_new, false);
3905 return PLAYBACK_FAIL;
3909 if (URIUtils::IsUPnP(item.GetPath()))
3911 CFileItem item_new(item);
3912 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3913 return PlayFile(item_new, false);
3914 return PLAYBACK_FAIL;
3918 // if we have a stacked set of files, we need to setup our stack routines for
3919 // "seamless" seeking and total time of the movie etc.
3920 // will recall with restart set to true
3922 return PlayStack(item, bRestart);
3924 //Is TuxBox, this should probably be moved to CTuxBoxFile
3927 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3929 if(g_tuxboxService.IsRunning())
3930 g_tuxboxService.Stop();
3932 PlayBackRet ret = PLAYBACK_FAIL;
3934 if(g_tuxbox.CreateNewItem(item, item_new))
3937 // Make sure it doesn't have a player
3938 // so we actually select one normally
3939 m_pPlayer->ResetPlayer();
3941 // keep the tuxbox:// url as playing url
3942 // and give the new url to the player
3943 ret = PlayFile(item_new, true);
3944 if(ret == PLAYBACK_OK)
3946 if(!g_tuxboxService.IsRunning())
3947 g_tuxboxService.Start();
3953 CPlayerOptions options;
3955 if( item.HasProperty("StartPercent") )
3957 double fallback = 0.0f;
3958 if(item.GetProperty("StartPercent").isString())
3959 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3960 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3963 PLAYERCOREID eNewCore = EPC_NONE;
3966 // have to be set here due to playstack using this for starting the file
3967 options.starttime = item.m_lStartOffset / 75.0;
3968 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3969 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3971 if( m_eForcedNextPlayer != EPC_NONE )
3972 eNewCore = m_eForcedNextPlayer;
3973 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3974 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3976 eNewCore = m_pPlayer->GetCurrentPlayer();
3980 options.starttime = item.m_lStartOffset / 75.0;
3984 // open the d/b and retrieve the bookmarks for the current movie
3987 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3989 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3991 options.starttime = 0.0f;
3993 CStdString path = item.GetPath();
3994 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
3995 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3996 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3997 path = item.GetProperty("original_listitem_url").asString();
3998 if(dbs.GetResumeBookMark(path, bookmark))
4000 options.starttime = bookmark.timeInSeconds;
4001 options.state = bookmark.playerState;
4004 override with information from the actual item if available. We do this as the VFS (eg plugins)
4005 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
4006 should the playerState be required, it is fetched from the database.
4007 See the note in CGUIWindowVideoBase::ShowResumeMenu.
4009 if (item.IsResumePointSet())
4010 options.starttime = item.GetCurrentResumeTime();
4012 else if (item.HasVideoInfoTag())
4014 const CVideoInfoTag *tag = item.GetVideoInfoTag();
4016 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
4019 dbs.GetBookMarkForEpisode(*tag, bookmark);
4020 options.starttime = bookmark.timeInSeconds;
4021 options.state = bookmark.playerState;
4028 if (m_eForcedNextPlayer != EPC_NONE)
4029 eNewCore = m_eForcedNextPlayer;
4031 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
4034 // this really aught to be inside !bRestart, but since PlayStack
4035 // uses that to init playback, we have to keep it outside
4036 int playlist = g_playlistPlayer.GetCurrentPlaylist();
4037 if (item.IsVideo() && playlist == PLAYLIST_VIDEO && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
4038 { // playing from a playlist by the looks
4039 // don't switch to fullscreen if we are not playing the first item...
4040 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4042 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
4044 // TODO - this will fail if user seeks back to first file in stack
4045 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
4046 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4048 options.fullscreen = false;
4049 // reset this so we don't think we are resuming on seek
4050 m_itemCurrentFile->m_lStartOffset = 0;
4053 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
4055 // reset VideoStartWindowed as it's a temp setting
4056 CMediaSettings::Get().SetVideoStartWindowed(false);
4059 //We have to stop parsing a cdg before mplayer is deallocated
4060 // WHY do we have to do this????
4062 m_pKaraokeMgr->Stop();
4066 CSingleLock lock(m_playStateMutex);
4067 // tell system we are starting a file
4068 m_bPlaybackStarting = true;
4070 // for playing a new item, previous playing item's callback may already
4071 // pushed some delay message into the threadmessage list, they are not
4072 // expected be processed after or during the new item playback starting.
4073 // so we clean up previous playing item's playback callback delay messages here.
4074 int previousMsgsIgnoredByNewPlaying[] = {
4075 GUI_MSG_PLAYBACK_STARTED,
4076 GUI_MSG_PLAYBACK_ENDED,
4077 GUI_MSG_PLAYBACK_STOPPED,
4078 GUI_MSG_PLAYLIST_CHANGED,
4079 GUI_MSG_PLAYLISTPLAYER_STOPPED,
4080 GUI_MSG_PLAYLISTPLAYER_STARTED,
4081 GUI_MSG_PLAYLISTPLAYER_CHANGED,
4082 GUI_MSG_QUEUE_NEXT_ITEM,
4085 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
4087 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
4090 // We should restart the player, unless the previous and next tracks are using
4091 // one of the players that allows gapless playback (paplayer, dvdplayer)
4092 m_pPlayer->ClosePlayerGapless(eNewCore);
4094 // now reset play state to starting, since we already stopped the previous playing item if there is.
4095 // and from now there should be no playback callback from previous playing item be called.
4096 m_ePlayState = PLAY_STATE_STARTING;
4098 m_pPlayer->CreatePlayer(eNewCore, *this);
4100 PlayBackRet iResult;
4101 if (m_pPlayer->HasPlayer())
4103 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
4104 * This should speed up player startup for files on internet filesystems (eg. webdav) and
4105 * increase performance on low powered systems (Atom/ARM).
4109 CJobManager::GetInstance().PauseJobs();
4112 // don't hold graphicscontext here since player
4113 // may wait on another thread, that requires gfx
4114 CSingleExit ex(g_graphicsContext);
4116 iResult = m_pPlayer->OpenFile(item, options);
4120 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
4121 iResult = PLAYBACK_FAIL;
4124 if(iResult == PLAYBACK_OK)
4126 if (m_pPlayer->GetPlaySpeed() != 1)
4128 int iSpeed = m_pPlayer->GetPlaySpeed();
4129 m_pPlayer->m_iPlaySpeed = 1;
4130 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
4133 // if player has volume control, set it.
4134 if (m_pPlayer->ControlsVolume())
4136 m_pPlayer->SetVolume(m_volumeLevel);
4137 m_pPlayer->SetMute(m_muted);
4140 if( m_pPlayer->IsPlayingAudio() )
4142 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4143 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4146 #ifdef HAS_VIDEO_PLAYBACK
4147 else if( m_pPlayer->IsPlayingVideo() )
4149 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4150 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
4152 // if player didn't manange to switch to fullscreen by itself do it here
4153 if( options.fullscreen && g_renderManager.IsStarted()
4154 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4155 SwitchToFullScreen();
4160 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4161 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4162 g_windowManager.PreviousWindow();
4166 #if !defined(TARGET_POSIX)
4167 g_audioManager.Enable(false);
4170 if (item.HasPVRChannelInfoTag())
4171 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4174 CSingleLock lock(m_playStateMutex);
4175 m_bPlaybackStarting = false;
4177 if (iResult == PLAYBACK_OK)
4179 // play state: none, starting; playing; stopped; ended.
4180 // last 3 states are set by playback callback, they are all ignored during starting,
4181 // but we recorded the state, here we can make up the callback for the state.
4182 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4183 switch (m_ePlayState)
4185 case PLAY_STATE_PLAYING:
4186 OnPlayBackStarted();
4188 // FIXME: it seems no meaning to callback started here if there was an started callback
4189 // before this stopped/ended callback we recorded. if we callback started here
4190 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4191 // which will send OnStop announce at once, so currently, just call stopped/ended.
4192 case PLAY_STATE_ENDED:
4195 case PLAY_STATE_STOPPED:
4196 OnPlayBackStopped();
4198 case PLAY_STATE_STARTING:
4199 // neither started nor stopped/ended callback be called, that means the item still
4200 // not started, we need not make up any callback, just leave this and
4201 // let the player callback do its work.
4207 else if (iResult == PLAYBACK_FAIL)
4209 // we send this if it isn't playlistplayer that is doing this
4210 int next = g_playlistPlayer.GetNextSong();
4211 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4214 OnPlayBackStopped();
4215 m_ePlayState = PLAY_STATE_NONE;
4221 void CApplication::OnPlayBackEnded()
4223 CSingleLock lock(m_playStateMutex);
4224 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4225 m_ePlayState = PLAY_STATE_ENDED;
4226 if(m_bPlaybackStarting)
4229 // informs python script currently running playback has ended
4230 // (does nothing if python is not loaded)
4232 g_pythonParser.OnPlayBackEnded();
4235 CVariant data(CVariant::VariantTypeObject);
4237 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4239 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4240 g_windowManager.SendThreadMessage(msg);
4243 void CApplication::OnPlayBackStarted()
4245 CSingleLock lock(m_playStateMutex);
4246 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4247 m_ePlayState = PLAY_STATE_PLAYING;
4248 if(m_bPlaybackStarting)
4252 // informs python script currently running playback has started
4253 // (does nothing if python is not loaded)
4254 g_pythonParser.OnPlayBackStarted();
4257 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4258 g_windowManager.SendThreadMessage(msg);
4261 void CApplication::OnQueueNextItem()
4263 CSingleLock lock(m_playStateMutex);
4264 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4265 if(m_bPlaybackStarting)
4267 // informs python script currently running that we are requesting the next track
4268 // (does nothing if python is not loaded)
4270 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4273 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4274 g_windowManager.SendThreadMessage(msg);
4277 void CApplication::OnPlayBackStopped()
4279 CSingleLock lock(m_playStateMutex);
4280 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4281 m_ePlayState = PLAY_STATE_STOPPED;
4282 if(m_bPlaybackStarting)
4285 // informs python script currently running playback has ended
4286 // (does nothing if python is not loaded)
4288 g_pythonParser.OnPlayBackStopped();
4291 CVariant data(CVariant::VariantTypeObject);
4292 data["end"] = false;
4293 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4295 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4296 g_windowManager.SendThreadMessage(msg);
4299 void CApplication::OnPlayBackPaused()
4302 g_pythonParser.OnPlayBackPaused();
4306 param["player"]["speed"] = 0;
4307 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4308 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4311 void CApplication::OnPlayBackResumed()
4314 g_pythonParser.OnPlayBackResumed();
4318 param["player"]["speed"] = 1;
4319 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4320 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4323 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4326 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4330 param["player"]["speed"] = iSpeed;
4331 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4332 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4335 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4338 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4342 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4343 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4344 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4345 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4346 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4347 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4350 void CApplication::OnPlayBackSeekChapter(int iChapter)
4353 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4357 bool CApplication::IsPlayingFullScreenVideo() const
4359 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4362 bool CApplication::IsFullScreen()
4364 return IsPlayingFullScreenVideo() ||
4365 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4366 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4369 void CApplication::SaveFileState(bool bForeground /* = false */)
4371 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4376 CSaveFileStateJob job(*m_progressTrackingItem,
4377 *m_stackFileItemToUpdate,
4378 m_progressTrackingVideoResumeBookmark,
4379 m_progressTrackingPlayCountUpdate);
4381 // Run job in the foreground to make sure it finishes
4386 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4387 *m_stackFileItemToUpdate,
4388 m_progressTrackingVideoResumeBookmark,
4389 m_progressTrackingPlayCountUpdate);
4390 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4394 void CApplication::UpdateFileState()
4396 // Did the file change?
4397 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4401 // Reset tracking item
4402 m_progressTrackingItem->Reset();
4406 if (m_pPlayer->IsPlaying())
4408 if (m_progressTrackingItem->GetPath() == "")
4411 *m_progressTrackingItem = CurrentFileItem();
4412 m_progressTrackingPlayCountUpdate = false;
4415 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4416 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4417 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4418 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4420 m_progressTrackingPlayCountUpdate = true;
4423 // Check whether we're *really* playing video else we may race when getting eg. stream details
4424 if (m_pPlayer->IsPlayingVideo())
4426 /* Always update streamdetails, except for DVDs where we only update
4427 streamdetails if title length > 15m (Should yield more correct info) */
4428 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4430 CStreamDetails details;
4431 // Update with stream details from player, if any
4432 if (m_pPlayer->GetStreamDetails(details))
4433 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4435 if (m_progressTrackingItem->IsStack())
4436 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails.SetVideoDuration(0, (int)GetTotalTime()); // Overwrite with CApp's totaltime as it takes into account total stack time
4439 // Update bookmark for save
4440 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4441 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4442 m_progressTrackingVideoResumeBookmark.thumbNailImage.clear();
4444 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4445 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4447 // Delete the bookmark
4448 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4451 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4453 // Update the bookmark
4454 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4455 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4460 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4467 void CApplication::StopPlaying()
4469 int iWin = g_windowManager.GetActiveWindow();
4470 if ( m_pPlayer->IsPlaying() )
4474 m_pKaraokeMgr->Stop();
4477 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4478 g_PVRManager.SaveCurrentChannelSettings();
4480 m_pPlayer->CloseFile();
4482 // turn off visualisation window when stopping
4483 if ((iWin == WINDOW_VISUALISATION
4484 || iWin == WINDOW_FULLSCREEN_VIDEO)
4486 g_windowManager.PreviousWindow();
4488 g_partyModeManager.Disable();
4492 void CApplication::ResetSystemIdleTimer()
4494 // reset system idle timer
4495 m_idleTimer.StartZero();
4498 void CApplication::ResetScreenSaver()
4501 m_shutdownTimer.StartZero();
4503 // screen saver timer is reset only if we're not already in screensaver or
4505 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4506 ResetScreenSaverTimer();
4509 void CApplication::ResetScreenSaverTimer()
4511 m_screenSaverTimer.StartZero();
4514 void CApplication::StopScreenSaverTimer()
4516 m_screenSaverTimer.Stop();
4519 bool CApplication::ToggleDPMS(bool manual)
4521 if (manual || (m_dpmsIsManual == manual))
4525 m_dpmsIsActive = false;
4526 m_dpmsIsManual = false;
4527 return m_dpms->DisablePowerSaving();
4531 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4533 m_dpmsIsActive = true;
4534 m_dpmsIsManual = manual;
4542 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4546 // First reset DPMS, if active
4551 // TODO: if screensaver lock is specified but screensaver is not active
4552 // (DPMS came first), activate screensaver now.
4554 ResetScreenSaverTimer();
4555 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4558 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4562 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4563 CVariant data(bPowerOffKeyPressed);
4564 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4570 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4572 if (m_iScreenSaveLock == 2)
4575 // if Screen saver is active
4576 if (m_bScreenSave && m_screenSaver)
4578 if (m_iScreenSaveLock == 0)
4579 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4580 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4581 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4582 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4584 m_iScreenSaveLock = 2;
4585 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4587 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4589 pWindow->OnMessage(msg);
4591 if (m_iScreenSaveLock == -1)
4593 m_iScreenSaveLock = 0;
4597 // disable screensaver
4598 m_bScreenSave = false;
4599 m_iScreenSaveLock = 0;
4600 ResetScreenSaverTimer();
4602 if (m_screenSaver->ID() == "visualization")
4604 // we can just continue as usual from vis mode
4607 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4609 else if (!m_screenSaver->ID().empty())
4610 { // we're in screensaver window
4611 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4612 g_windowManager.PreviousWindow(); // show the previous window
4613 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4614 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4622 void CApplication::CheckScreenSaverAndDPMS()
4624 if (m_bInBackground)
4626 if (!m_dpmsIsActive)
4627 g_Windowing.ResetOSScreensaver();
4629 bool maybeScreensaver =
4630 !m_dpmsIsActive && !m_bScreenSave
4631 && !CSettings::Get().GetString("screensaver.mode").empty();
4633 !m_dpmsIsActive && m_dpms->IsSupported()
4634 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4636 // Has the screen saver window become active?
4637 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4639 m_bScreenSave = true;
4640 maybeScreensaver = false;
4643 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4645 WakeUpScreenSaverAndDPMS();
4649 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4651 // See if we need to reset timer.
4652 // * Are we playing a video and it is not paused?
4653 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4654 // * Are we playing some music in fullscreen vis?
4655 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4656 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4658 ResetScreenSaverTimer();
4662 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4664 // DPMS has priority (it makes the screensaver not needed)
4666 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4669 WakeUpScreenSaver();
4671 else if (maybeScreensaver
4672 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4674 ActivateScreenSaver();
4678 // activate the screensaver.
4679 // if forceType is true, we ignore the various conditions that can alter
4680 // the type of screensaver displayed
4681 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4683 if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4684 { // just activate the visualisation if user toggled the usemusicvisinstead option
4685 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4689 m_bScreenSave = true;
4691 // Get Screensaver Mode
4692 m_screenSaver.reset();
4693 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4694 m_screenSaver.reset(new CScreenSaver(""));
4696 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4698 // disable screensaver lock from the login screen
4699 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4702 // set to Dim in the case of a dialog on screen or playing video
4703 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4705 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4706 m_screenSaver.reset(new CScreenSaver(""));
4709 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4711 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4713 else if (!m_screenSaver->ID().empty())
4714 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4717 void CApplication::SetInBackground(bool background)
4721 ResetScreenSaverTimer();
4723 m_bInBackground = background;
4726 void CApplication::CheckShutdown()
4728 // first check if we should reset the timer
4729 if (m_bInhibitIdleShutdown
4730 || m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback() // is something playing?
4731 || m_musicInfoScanner->IsScanning()
4732 || m_videoInfoScanner->IsScanning()
4733 || g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS) // progress dialog is onscreen
4734 || (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()))
4736 m_shutdownTimer.StartZero();
4740 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4742 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4743 m_shutdownTimer.Stop();
4746 CApplicationMessenger::Get().Shutdown();
4750 void CApplication::InhibitIdleShutdown(bool inhibit)
4752 m_bInhibitIdleShutdown = inhibit;
4755 bool CApplication::IsIdleShutdownInhibited() const
4757 return m_bInhibitIdleShutdown;
4760 bool CApplication::OnMessage(CGUIMessage& message)
4762 switch ( message.GetMessage() )
4764 case GUI_MSG_NOTIFY_ALL:
4766 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4768 // Update general playlist: Remove DVD playlist items
4769 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4772 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4773 g_windowManager.SendMessage( msg );
4775 // stop the file if it's on dvd (will set the resume point etc)
4776 if (m_itemCurrentFile->IsOnDVD())
4782 case GUI_MSG_PLAYBACK_STARTED:
4784 #ifdef TARGET_DARWIN
4785 DarwinSetScheduling(message.GetMessage());
4787 // reset the seek handler
4788 m_seekHandler->Reset();
4789 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4791 // Update our infoManager with the new details etc.
4792 if (m_nextPlaylistItem >= 0)
4794 // playing an item which is not in the list - player might be stopped already
4796 if (playList.size() <= m_nextPlaylistItem)
4799 // we've started a previously queued item
4800 CFileItemPtr item = playList[m_nextPlaylistItem];
4801 // update the playlist manager
4802 int currentSong = g_playlistPlayer.GetCurrentSong();
4803 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4804 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4805 g_windowManager.SendThreadMessage(msg);
4806 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4807 *m_itemCurrentFile = *item;
4809 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4810 g_partyModeManager.OnSongChange(true);
4813 param["player"]["speed"] = 1;
4814 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4815 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4817 if (m_pPlayer->IsPlayingAudio())
4819 // Start our cdg parser as appropriate
4821 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4823 m_pKaraokeMgr->Stop();
4824 if (m_itemCurrentFile->IsMusicDb())
4826 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4828 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4829 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4832 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4835 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4844 case GUI_MSG_QUEUE_NEXT_ITEM:
4846 // Check to see if our playlist player has a new item for us,
4847 // and if so, we check whether our current player wants the file
4848 int iNext = g_playlistPlayer.GetNextSong();
4849 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4850 if (iNext < 0 || iNext >= playlist.size())
4852 m_pPlayer->OnNothingToQueueNotify();
4853 return true; // nothing to do
4856 // ok, grab the next song
4857 CFileItem file(*playlist[iNext]);
4859 CURL url(file.GetPath());
4860 if (url.GetProtocol() == "plugin")
4861 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4864 if (URIUtils::IsUPnP(file.GetPath()))
4866 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4871 // ok - send the file to the player, if it accepts it
4872 if (m_pPlayer->QueueNextFile(file))
4874 // player accepted the next file
4875 m_nextPlaylistItem = iNext;
4879 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4880 queue the next (if it wants to) and it doesn't keep looping on this song */
4881 g_playlistPlayer.SetCurrentSong(iNext);
4888 case GUI_MSG_PLAYBACK_STOPPED:
4889 case GUI_MSG_PLAYBACK_ENDED:
4890 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4894 m_pKaraokeMgr->Stop();
4896 #ifdef TARGET_DARWIN
4897 DarwinSetScheduling(message.GetMessage());
4899 // first check if we still have items in the stack to play
4900 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4902 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4903 { // just play the next item in the stack
4904 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4909 // In case playback ended due to user eg. skipping over the end, clear
4910 // our resume bookmark here
4911 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4913 // Delete the bookmark
4914 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4917 // reset the current playing file
4918 m_itemCurrentFile->Reset();
4919 g_infoManager.ResetCurrentItem();
4920 m_currentStack->Clear();
4922 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4924 g_playlistPlayer.PlayNext(1, true);
4928 // reset any forced player
4929 m_eForcedNextPlayer = EPC_NONE;
4931 m_pPlayer->ClosePlayer();
4934 m_pPlayer->m_iPlaySpeed = 1;
4937 if (!m_pPlayer->IsPlaying())
4939 g_audioManager.Enable(true);
4942 if (!m_pPlayer->IsPlayingVideo())
4944 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4946 g_windowManager.PreviousWindow();
4950 CSingleLock lock(g_graphicsContext);
4951 // resets to res_desktop or look&feel resolution (including refreshrate)
4952 g_graphicsContext.SetFullScreenVideo(false);
4956 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4958 CSettings::Get().Save(); // save vis settings
4959 WakeUpScreenSaverAndDPMS();
4960 g_windowManager.PreviousWindow();
4963 // DVD ejected while playing in vis ?
4964 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4967 CSettings::Get().Save(); // save vis settings
4968 WakeUpScreenSaverAndDPMS();
4969 g_windowManager.PreviousWindow();
4972 if (IsEnableTestMode())
4973 CApplicationMessenger::Get().Quit();
4978 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4979 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4984 case GUI_MSG_FULLSCREEN:
4985 { // Switch to fullscreen, if we can
4986 SwitchToFullScreen();
4990 case GUI_MSG_EXECUTE:
4991 if (message.GetNumStringParams())
4992 return ExecuteXBMCAction(message.GetStringParam());
4998 bool CApplication::ExecuteXBMCAction(std::string actionStr)
5000 // see if it is a user set string
5002 //We don't know if there is unsecure information in this yet, so we
5003 //postpone any logging
5004 const std::string in_actionStr(actionStr);
5005 CGUIInfoLabel info(actionStr, "");
5006 actionStr = info.GetLabel(0);
5008 // user has asked for something to be executed
5009 if (CBuiltins::HasCommand(actionStr))
5010 CBuiltins::Execute(actionStr);
5013 // try translating the action from our ButtonTranslator
5015 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
5017 OnAction(CAction(actionID));
5020 CFileItem item(actionStr, false);
5022 if (item.IsPythonScript())
5023 { // a python script
5024 CScriptInvocationManager::Get().Execute(item.GetPath());
5028 if (item.IsAudio() || item.IsVideo())
5029 { // an audio or video file
5034 //At this point we have given up to translate, so even though
5035 //there may be insecure information, we log it.
5036 CLog::Log(LOGDEBUG,"%s : Tried translating, but failed to understand %s", __FUNCTION__, in_actionStr.c_str());
5043 void CApplication::Process()
5047 // dispatch the messages generated by python or other threads to the current window
5048 g_windowManager.DispatchThreadMessages();
5050 // process messages which have to be send to the gui
5051 // (this can only be done after g_windowManager.Render())
5052 CApplicationMessenger::Get().ProcessWindowMessages();
5056 m_loggingIn = false;
5058 // autoexec.py - profile
5059 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
5061 if (XFILE::CFile::Exists(strAutoExecPy))
5062 CScriptInvocationManager::Get().Execute(strAutoExecPy);
5064 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
5067 // handle any active scripts
5068 CScriptInvocationManager::Get().Process();
5070 // process messages, even if a movie is playing
5071 CApplicationMessenger::Get().ProcessMessages();
5072 if (g_application.m_bStop) return; //we're done, everything has been unloaded
5074 // check how far we are through playing the current item
5075 // and do anything that needs doing (playcount updates etc)
5076 CheckPlayingProgress();
5079 m_pPlayer->DoAudioWork();
5081 // do any processing that isn't needed on each run
5082 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
5084 m_slowTimer.Reset();
5088 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
5091 // We get called every 500ms
5092 void CApplication::ProcessSlow()
5094 g_powerManager.ProcessEvents();
5096 #if defined(TARGET_DARWIN_OSX)
5097 // There is an issue on OS X that several system services ask the cursor to become visible
5098 // during their startup routines. Given that we can't control this, we hack it in by
5100 if (g_Windowing.IsFullScreen())
5101 { // SDL thinks it's hidden
5106 // Temporarely pause pausable jobs when viewing video/picture
5107 int currentWindow = g_windowManager.GetActiveWindow();
5108 if (CurrentFileItem().IsVideo() || CurrentFileItem().IsPicture() || currentWindow == WINDOW_FULLSCREEN_VIDEO || currentWindow == WINDOW_SLIDESHOW)
5110 CJobManager::GetInstance().PauseJobs();
5114 CJobManager::GetInstance().UnPauseJobs();
5117 // Store our file state for use on close()
5120 // Check if we need to activate the screensaver / DPMS.
5121 CheckScreenSaverAndDPMS();
5123 // Check if we need to shutdown (if enabled).
5124 #if defined(TARGET_DARWIN)
5125 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
5127 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
5133 // check if we should restart the player
5134 CheckDelayedPlayerRestart();
5136 // check if we can unload any unreferenced dlls or sections
5137 if (!m_pPlayer->IsPlayingVideo())
5138 CSectionLoader::UnloadDelayed();
5140 // check for any idle curl connections
5141 g_curlInterface.CheckIdle();
5143 // check for any idle myth sessions
5144 CMythSession::CheckIdle();
5146 #ifdef HAS_FILESYSTEM_HTSP
5147 // check for any idle htsp sessions
5148 HTSP::CHTSPDirectorySession::CheckIdle();
5152 if ( m_pKaraokeMgr )
5153 m_pKaraokeMgr->ProcessSlow();
5156 if (!m_pPlayer->IsPlayingVideo())
5157 g_largeTextureManager.CleanupUnusedImages();
5159 g_TextureManager.FreeUnusedTextures(5000);
5161 #ifdef HAS_DVD_DRIVE
5162 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5163 if (!m_pPlayer->IsPlayingVideo())
5164 m_Autorun->HandleAutorun();
5167 // update upnp server/renderer states
5169 if(UPNP::CUPnP::IsInstantiated())
5170 UPNP::CUPnP::GetInstance()->UpdateState();
5173 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5177 #ifdef HAS_FILESYSTEM_NFS
5178 gNfsConnection.CheckIfIdle();
5181 #ifdef HAS_FILESYSTEM_AFP
5182 gAfpConnection.CheckIfIdle();
5185 #ifdef HAS_FILESYSTEM_SFTP
5186 CSFTPSessionManager::ClearOutIdleSessions();
5189 g_mediaManager.ProcessEvents();
5192 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5193 g_RemoteControl.Initialize();
5196 if (!m_pPlayer->IsPlayingVideo())
5197 CAddonInstaller::Get().UpdateRepos();
5199 CAEFactory::GarbageCollect();
5201 // if we don't render the gui there's no reason to start the screensaver.
5202 // that way the screensaver won't kick in if we maximize the XBMC window
5203 // after the screensaver start time.
5205 ResetScreenSaverTimer();
5208 // Global Idle Time in Seconds
5209 // idle time will be resetet if on any OnKey()
5210 // int return: system Idle time in seconds! 0 is no idle!
5211 int CApplication::GlobalIdleTime()
5213 if(!m_idleTimer.IsRunning())
5216 m_idleTimer.StartZero();
5218 return (int)m_idleTimer.GetElapsedSeconds();
5221 float CApplication::NavigationIdleTime()
5223 if (!m_navigationTimer.IsRunning())
5225 m_navigationTimer.Stop();
5226 m_navigationTimer.StartZero();
5228 return m_navigationTimer.GetElapsedSeconds();
5231 void CApplication::DelayedPlayerRestart()
5233 m_restartPlayerTimer.StartZero();
5236 void CApplication::CheckDelayedPlayerRestart()
5238 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5240 m_restartPlayerTimer.Stop();
5241 m_restartPlayerTimer.Reset();
5246 void CApplication::Restart(bool bSamePosition)
5248 // this function gets called when the user changes a setting (like noninterleaved)
5249 // and which means we gotta close & reopen the current playing file
5251 // first check if we're playing a file
5252 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5255 if( !m_pPlayer->HasPlayer() )
5260 // do we want to return to the current position in the file
5261 if (false == bSamePosition)
5263 // no, then just reopen the file and start at the beginning
5264 PlayFile(*m_itemCurrentFile, true);
5268 // else get current position
5269 double time = GetTime();
5271 // get player state, needed for dvd's
5272 CStdString state = m_pPlayer->GetPlayerState();
5274 // set the requested starttime
5275 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5278 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5279 m_pPlayer->SetPlayerState(state);
5282 const CStdString& CApplication::CurrentFile()
5284 return m_itemCurrentFile->GetPath();
5287 CFileItem& CApplication::CurrentFileItem()
5289 return *m_itemCurrentFile;
5292 CFileItem& CApplication::CurrentUnstackedItem()
5294 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5295 return *(*m_currentStack)[m_currentStackPosition];
5297 return *m_itemCurrentFile;
5300 void CApplication::ShowVolumeBar(const CAction *action)
5302 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5307 volumeBar->OnAction(*action);
5311 bool CApplication::IsMuted() const
5313 if (g_peripherals.IsMuted())
5315 return CAEFactory::IsMuted();
5318 void CApplication::ToggleMute(void)
5326 void CApplication::SetMute(bool mute)
5328 if (m_muted != mute)
5335 void CApplication::Mute()
5337 if (g_peripherals.Mute())
5340 CAEFactory::SetMute(true);
5345 void CApplication::UnMute()
5347 if (g_peripherals.UnMute())
5350 CAEFactory::SetMute(false);
5355 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5357 float hardwareVolume = iValue;
5360 hardwareVolume /= 100.0f;
5362 SetHardwareVolume(hardwareVolume);
5366 void CApplication::SetHardwareVolume(float hardwareVolume)
5368 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5369 m_volumeLevel = hardwareVolume;
5371 CAEFactory::SetVolume(hardwareVolume);
5374 float CApplication::GetVolume(bool percentage /* = true */) const
5378 // converts the hardware volume to a percentage
5379 return m_volumeLevel * 100.0f;
5382 return m_volumeLevel;
5385 void CApplication::VolumeChanged() const
5387 CVariant data(CVariant::VariantTypeObject);
5388 data["volume"] = GetVolume();
5389 data["muted"] = m_muted;
5390 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5392 // if player has volume control, set it.
5393 if (m_pPlayer->ControlsVolume())
5395 m_pPlayer->SetVolume(m_volumeLevel);
5396 m_pPlayer->SetMute(m_muted);
5400 int CApplication::GetSubtitleDelay() const
5402 // converts subtitle delay to a percentage
5403 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5406 int CApplication::GetAudioDelay() const
5408 // converts audio delay to a percentage
5409 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5412 // Returns the total time in seconds of the current media. Fractional
5413 // portions of a second are possible - but not necessarily supported by the
5414 // player class. This returns a double to be consistent with GetTime() and
5416 double CApplication::GetTotalTime() const
5420 if (m_pPlayer->IsPlaying())
5422 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5423 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5425 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5431 void CApplication::StopShutdownTimer()
5433 if (m_shutdownTimer.IsRunning())
5434 m_shutdownTimer.Stop();
5437 void CApplication::ResetShutdownTimers()
5439 // reset system shutdown timer
5440 m_shutdownTimer.StartZero();
5442 // delete custom shutdown timer
5443 if (g_alarmClock.HasAlarm("shutdowntimer"))
5444 g_alarmClock.Stop("shutdowntimer", true);
5447 // Returns the current time in seconds of the currently playing media.
5448 // Fractional portions of a second are possible. This returns a double to
5449 // be consistent with GetTotalTime() and SeekTime().
5450 double CApplication::GetTime() const
5454 if (m_pPlayer->IsPlaying())
5456 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5458 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5459 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5462 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5468 // Sets the current position of the currently playing media to the specified
5469 // time in seconds. Fractional portions of a second are valid. The passed
5470 // time is the time offset from the beginning of the file as opposed to a
5471 // delta from the current position. This method accepts a double to be
5472 // consistent with GetTime() and GetTotalTime().
5473 void CApplication::SeekTime( double dTime )
5475 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5477 if (!m_pPlayer->CanSeek()) return;
5478 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5480 // find the item in the stack we are seeking to, and load the new
5481 // file if necessary, and calculate the correct seek within the new
5482 // file. Otherwise, just fall through to the usual routine if the
5483 // time is higher than our total time.
5484 for (int i = 0; i < m_currentStack->Size(); i++)
5486 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5488 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5489 if (m_currentStackPosition == i)
5490 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5492 { // seeking to a new file
5493 m_currentStackPosition = i;
5494 CFileItem item(*(*m_currentStack)[i]);
5495 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5496 // don't just call "PlayFile" here, as we are quite likely called from the
5497 // player thread, so we won't be able to delete ourselves.
5498 CApplicationMessenger::Get().PlayFile(item, true);
5504 // convert to milliseconds and perform seek
5505 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5509 float CApplication::GetPercentage() const
5511 if (m_pPlayer->IsPlaying())
5513 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5515 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5516 if (tag.GetDuration() > 0)
5517 return (float)(GetTime() / tag.GetDuration() * 100);
5520 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5522 double totalTime = GetTotalTime();
5523 if (totalTime > 0.0f)
5524 return (float)(GetTime() / totalTime * 100);
5527 return m_pPlayer->GetPercentage();
5532 float CApplication::GetCachePercentage() const
5534 if (m_pPlayer->IsPlaying())
5536 // Note that the player returns a relative cache percentage and we want an absolute percentage
5537 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5539 float stackedTotalTime = (float) GetTotalTime();
5540 // We need to take into account the stack's total time vs. currently playing file's total time
5541 if (stackedTotalTime > 0.0f)
5542 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5545 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5550 void CApplication::SeekPercentage(float percent)
5552 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5554 if (!m_pPlayer->CanSeek()) return;
5555 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5556 SeekTime(percent * 0.01 * GetTotalTime());
5558 m_pPlayer->SeekPercentage(percent);
5562 // SwitchToFullScreen() returns true if a switch is made, else returns false
5563 bool CApplication::SwitchToFullScreen()
5565 // if playing from the video info window, close it first!
5566 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5568 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5569 if (pDialog) pDialog->Close(true);
5572 // don't switch if there is a dialog on screen or the slideshow is active
5573 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5576 // See if we're playing a video, and are in GUI mode
5577 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5579 // then switch to fullscreen mode
5580 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5583 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5584 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5585 { // then switch to visualisation
5586 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5592 void CApplication::Minimize()
5594 g_Windowing.Minimize();
5597 PLAYERCOREID CApplication::GetCurrentPlayer()
5599 return m_pPlayer->GetCurrentPlayer();
5602 void CApplication::UpdateLibraries()
5604 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5606 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5610 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5612 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5617 bool CApplication::IsVideoScanning() const
5619 return m_videoInfoScanner->IsScanning();
5622 bool CApplication::IsMusicScanning() const
5624 return m_musicInfoScanner->IsScanning();
5627 void CApplication::StopVideoScan()
5629 if (m_videoInfoScanner->IsScanning())
5630 m_videoInfoScanner->Stop();
5633 void CApplication::StopMusicScan()
5635 if (m_musicInfoScanner->IsScanning())
5636 m_musicInfoScanner->Stop();
5639 void CApplication::StartVideoCleanup()
5641 if (m_videoInfoScanner->IsScanning())
5644 m_videoInfoScanner->CleanDatabase();
5647 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5649 if (m_videoInfoScanner->IsScanning())
5652 m_videoInfoScanner->ShowDialog(true);
5654 m_videoInfoScanner->Start(strDirectory,scanAll);
5657 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5659 if (m_musicInfoScanner->IsScanning())
5663 { // setup default flags
5664 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5665 flags |= CMusicInfoScanner::SCAN_ONLINE;
5666 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5667 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5670 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5671 m_musicInfoScanner->ShowDialog(true);
5673 m_musicInfoScanner->Start(strDirectory, flags);
5676 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5679 if (m_musicInfoScanner->IsScanning())
5682 m_musicInfoScanner->ShowDialog(true);
5684 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5687 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5690 if (m_musicInfoScanner->IsScanning())
5693 m_musicInfoScanner->ShowDialog(true);
5695 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5698 void CApplication::CheckPlayingProgress()
5700 // check if we haven't rewound past the start of the file
5701 if (m_pPlayer->IsPlaying())
5703 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5713 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5715 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5716 g_application.SeekTime(0);
5722 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5724 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5726 // initial exit conditions
5727 // no songs in playlist just return
5728 if (playlist.size() == 0)
5732 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5735 // setup correct playlist
5736 g_playlistPlayer.ClearPlaylist(iPlaylist);
5738 // if the playlist contains an internet stream, this file will be used
5739 // to generate a thumbnail for musicplayer.cover
5740 g_application.m_strPlayListFile = strPlayList;
5742 // add the items to the playlist player
5743 g_playlistPlayer.Add(iPlaylist, playlist);
5745 // if we have a playlist
5746 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5749 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5750 g_playlistPlayer.Reset();
5751 g_playlistPlayer.Play(track);
5757 void CApplication::SaveCurrentFileSettings()
5759 // don't store settings for PVR in video database
5760 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5762 // save video settings
5763 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5767 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5771 else if (m_itemCurrentFile->IsPVRChannel())
5773 g_PVRManager.SaveCurrentChannelSettings();
5777 bool CApplication::AlwaysProcess(const CAction& action)
5779 // check if this button is mapped to a built-in function
5780 if (!action.GetName().empty())
5782 CStdString builtInFunction;
5783 vector<CStdString> params;
5784 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5785 StringUtils::ToLower(builtInFunction);
5787 // should this button be handled normally or just cancel the screensaver?
5788 if ( builtInFunction.Equals("powerdown")
5789 || builtInFunction.Equals("reboot")
5790 || builtInFunction.Equals("restart")
5791 || builtInFunction.Equals("restartapp")
5792 || builtInFunction.Equals("suspend")
5793 || builtInFunction.Equals("hibernate")
5794 || builtInFunction.Equals("quit")
5795 || builtInFunction.Equals("shutdown"))
5804 bool CApplication::IsCurrentThread() const
5806 return CThread::IsCurrentThread(m_threadID);
5809 void CApplication::SetRenderGUI(bool renderGUI)
5811 if (renderGUI && ! m_renderGUI)
5812 g_windowManager.MarkDirty();
5813 m_renderGUI = renderGUI;
5816 CNetwork& CApplication::getNetwork()
5820 #ifdef HAS_PERFORMANCE_SAMPLE
5821 CPerformanceStats &CApplication::GetPerformanceStats()
5827 bool CApplication::SetLanguage(const CStdString &strLanguage)
5829 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5830 CStdString strNewLanguage = strLanguage;
5831 if (strNewLanguage != strPreviousLanguage)
5833 CStdString strLangInfoPath = StringUtils::Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5834 if (!g_langInfo.Load(strLangInfoPath))
5837 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5839 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5840 CStdString strFontSet;
5841 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5842 strNewLanguage = strFontSet;
5844 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5846 CSettings::Get().SetString("locale.language", strNewLanguage);
5848 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5851 // also tell our weather and skin to reload as these are localized
5852 g_weatherManager.Refresh();
5853 g_PVRManager.LocalizationChanged();
5860 void CApplication::CloseNetworkShares()
5862 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5864 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5868 #ifdef HAS_FILESYSTEM_NFS
5869 gNfsConnection.Deinit();
5872 #ifdef HAS_FILESYSTEM_AFP
5873 gAfpConnection.Deinit();
5876 #ifdef HAS_FILESYSTEM_SFTP
5877 CSFTPSessionManager::DisconnectAllSessions();