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 "utils/XMLUtils.h"
277 #include "addons/AddonInstaller.h"
279 #ifdef HAS_PERFORMANCE_SAMPLE
280 #include "utils/PerformanceSample.h"
282 #define MEASURE_FUNCTION
285 #ifdef TARGET_WINDOWS
287 #include "win32util.h"
290 #include "windowing/X11/XRandR.h"
293 #ifdef TARGET_DARWIN_OSX
294 #include "osx/CocoaInterface.h"
295 #include "osx/XBMCHelper.h"
298 #include "osx/DarwinUtils.h"
303 #include <cdio/logging.h>
307 #include "linux/HALManager.h"
310 #include "storage/MediaManager.h"
311 #include "utils/JobManager.h"
312 #include "utils/SaveFileStateJob.h"
313 #include "utils/AlarmClock.h"
314 #include "utils/RssReader.h"
315 #include "utils/StringUtils.h"
316 #include "utils/Weather.h"
317 #include "DatabaseManager.h"
324 #include "input/linux/LIRC.h"
326 #ifdef HAS_IRSERVERSUITE
327 #include "input/windows/IRServerSuite.h"
330 #if defined(TARGET_WINDOWS)
331 #include "input/windows/WINJoystick.h"
332 #elif defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
333 #include "input/SDLJoystick.h"
336 #if defined(TARGET_ANDROID)
337 #include "android/activity/XBMCApp.h"
340 #ifdef TARGET_WINDOWS
341 #include "utils/Environment.h"
345 using namespace ADDON;
346 using namespace XFILE;
348 using namespace MEDIA_DETECT;
350 using namespace PLAYLIST;
351 using namespace VIDEO;
352 using namespace MUSIC_INFO;
353 #ifdef HAS_EVENT_SERVER
354 using namespace EVENTSERVER;
357 using namespace JSONRPC;
359 using namespace ANNOUNCEMENT;
362 using namespace PERIPHERALS;
364 using namespace XbmcThreads;
366 // uncomment this if you want to use release libs in the debug build.
367 // Atm this saves you 7 mb of memory
368 #define USE_RELEASE_LIBS
370 #define MAX_FFWD_SPEED 5
372 //extern IDirectSoundRenderer* m_pAudioDecoder;
373 CApplication::CApplication(void)
374 : m_pPlayer(new CApplicationPlayer)
375 , m_itemCurrentFile(new CFileItem)
376 , m_stackFileItemToUpdate(new CFileItem)
377 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
378 , m_progressTrackingItem(new CFileItem)
379 , m_videoInfoScanner(new CVideoInfoScanner)
380 , m_musicInfoScanner(new CMusicInfoScanner)
381 , m_seekHandler(new CSeekHandler)
382 , m_playerController(new CPlayerController)
385 TiXmlBase::SetCondenseWhiteSpace(false);
386 m_bInhibitIdleShutdown = false;
387 m_bScreenSave = false;
389 m_dpmsIsActive = false;
390 m_dpmsIsManual = false;
391 m_iScreenSaveLock = 0;
392 m_bInitializing = true;
393 m_eForcedNextPlayer = EPC_NONE;
394 m_strPlayListFile = "";
395 m_nextPlaylistItem = -1;
396 m_bPlaybackStarting = false;
397 m_ePlayState = PLAY_STATE_NONE;
398 m_skinReloading = false;
405 // we start in frontend
406 m_bInBackground = false;
408 /* for now always keep this around */
410 m_pKaraokeMgr = new CKaraokeLyricsManager();
412 m_currentStack = new CFileItemList;
414 m_bPresentFrame = false;
415 m_bPlatformDirectories = true;
417 m_bStandalone = false;
418 m_bEnableLegacyRes = false;
419 m_bSystemScreenSaverEnable = false;
420 m_pInertialScrollingHandler = new CInertialScrollingHandler();
422 m_Autorun = new CAutorun();
427 m_progressTrackingPlayCountUpdate = false;
428 m_currentStackPosition = 0;
430 m_lastRenderTime = 0;
434 m_volumeLevel = 1.0f;
437 CApplication::~CApplication(void)
439 delete m_musicInfoScanner;
440 delete m_videoInfoScanner;
441 delete &m_progressTrackingVideoResumeBookmark;
445 delete m_currentStack;
448 delete m_pKaraokeMgr;
452 delete m_seekHandler;
453 delete m_playerController;
454 delete m_pInertialScrollingHandler;
458 bool CApplication::OnEvent(XBMC_Event& newEvent)
460 switch(newEvent.type)
463 if (!g_application.m_bStop)
464 CApplicationMessenger::Get().Quit();
467 g_application.OnKey(g_Keyboard.ProcessKeyDown(newEvent.key.keysym));
470 g_Keyboard.ProcessKeyUp();
472 case XBMC_MOUSEBUTTONDOWN:
473 case XBMC_MOUSEBUTTONUP:
474 case XBMC_MOUSEMOTION:
475 g_Mouse.HandleEvent(newEvent);
476 g_application.ProcessMouse();
478 case XBMC_VIDEORESIZE:
479 if (!g_application.m_bInitializing &&
480 !g_advancedSettings.m_fullScreen)
482 g_Windowing.SetWindowResolution(newEvent.resize.w, newEvent.resize.h);
483 g_graphicsContext.SetVideoResolution(RES_WINDOW, true);
484 CSettings::Get().SetInt("window.width", newEvent.resize.w);
485 CSettings::Get().SetInt("window.height", newEvent.resize.h);
486 CSettings::Get().Save();
490 #ifdef TARGET_WINDOWS
491 if (g_advancedSettings.m_fullScreen)
493 // when fullscreen, remain fullscreen and resize to the dimensions of the new screen
494 RESOLUTION newRes = (RESOLUTION) g_Windowing.DesktopResolution(g_Windowing.GetCurrentScreen());
495 if (newRes != g_graphicsContext.GetVideoResolution())
496 CDisplaySettings::Get().SetCurrentResolution(newRes, true);
501 g_Windowing.OnMove(newEvent.move.x, newEvent.move.y);
505 CApplicationMessenger::Get().UserEvent(newEvent.user.code);
507 case XBMC_APPCOMMAND:
508 return g_application.OnAppCommand(newEvent.appcommand.action);
511 int windowId = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
513 if (newEvent.touch.action == ACTION_TOUCH_TAP)
514 { // Send a mouse motion event with no dx,dy for getting the current guiitem selected
515 g_application.OnAction(CAction(ACTION_MOUSE_MOVE, 0, newEvent.touch.x, newEvent.touch.y, 0, 0));
518 if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
520 actionId = newEvent.touch.action;
521 windowId = WINDOW_INVALID;
523 else if (!CButtonTranslator::GetInstance().TranslateTouchAction(newEvent.touch.action, newEvent.touch.pointers, windowId, actionId) ||
527 CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), windowId, false);
528 // Post an unfocus message for touch device after the action.
529 if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP)
531 CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
532 CApplicationMessenger::Get().SendGUIMessage(msg);
540 extern "C" void __stdcall init_emu_environ();
541 extern "C" void __stdcall update_emu_environ();
544 // Utility function used to copy files from the application bundle
545 // over to the user data directory in Application Support/XBMC.
547 static void CopyUserDataIfNeeded(const CStdString &strPath, const CStdString &file)
549 CStdString destPath = URIUtils::AddFileToFolder(strPath, file);
550 if (!CFile::Exists(destPath))
552 // need to copy it across
553 CStdString srcPath = URIUtils::AddFileToFolder("special://xbmc/userdata/", file);
554 CFile::Cache(srcPath, destPath);
558 void CApplication::Preflight()
561 // call 'dbus_threads_init_default' before any other dbus calls in order to
562 // avoid race conditions with other threads using dbus connections
563 dbus_threads_init_default();
566 // run any platform preflight scripts.
567 #if defined(TARGET_DARWIN_OSX)
568 CStdString install_path;
570 CUtil::GetHomePath(install_path);
571 setenv("XBMC_HOME", install_path.c_str(), 0);
572 install_path += "/tools/darwin/runtime/preflight";
573 system(install_path.c_str());
577 bool CApplication::Create()
579 #if defined(HAS_LINUX_NETWORK)
580 m_network = new CNetworkLinux();
581 #elif defined(HAS_WIN32_NETWORK)
582 m_network = new CNetworkWin32();
584 m_network = new CNetwork();
589 for (int i = RES_HDTV_1080i; i <= RES_PAL60_16x9; i++)
591 g_graphicsContext.ResetScreenParameters((RESOLUTION)i);
592 g_graphicsContext.ResetOverscan((RESOLUTION)i, CDisplaySettings::Get().GetResolutionInfo(i).Overscan);
596 tzset(); // Initialize timezone information variables
599 // Grab a handle to our thread to be used later in identifying the render thread.
600 m_threadID = CThread::GetCurrentThreadId();
603 //floating point precision to 24 bits (faster performance)
604 _controlfp(_PC_24, _MCW_PC);
606 /* install win32 exception translator, win32 exceptions
607 * can now be caught using c++ try catch */
608 win32_exception::install_handler();
612 // only the InitDirectories* for the current platform should return true
613 // putting this before the first log entries saves another ifdef for g_advancedSettings.m_logFolder
614 bool inited = InitDirectoriesLinux();
616 inited = InitDirectoriesOSX();
618 inited = InitDirectoriesWin32();
620 // copy required files
621 CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
622 CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
623 CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
625 if (!CLog::Init(CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str()))
627 fprintf(stderr,"Could not init logging classes. Permission errors on ~/.xbmc (%s)\n",
628 CSpecialProtocol::TranslatePath(g_advancedSettings.m_logFolder).c_str());
632 // Init our DllLoaders emu env
635 CProfilesManager::Get().Load();
637 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
638 CLog::Log(LOGNOTICE, "Starting XBMC (%s). Platform: %s %s %d-bit", g_infoManager.GetVersion().c_str(), g_sysinfo.GetBuildTargetCpuFamily().c_str(),
639 g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness());
641 /* Expand macro before stringify */
642 #define STR_MACRO(x) #x
643 #define XSTR_MACRO(x) STR_MACRO(x)
645 std::string compilerStr;
646 #if defined(__clang__)
647 compilerStr = "Clang " XSTR_MACRO(__clang_major__) "." XSTR_MACRO(__clang_minor__) "." XSTR_MACRO(__clang_patchlevel__);
648 #elif defined (__INTEL_COMPILER)
649 compilerStr = "Intel Compiler " XSTR_MACRO(__INTEL_COMPILER);
650 #elif defined (__GNUC__)
652 /* Note: this will not detect GCC + DragonEgg */
653 compilerStr = "llvm-gcc ";
655 compilerStr = "GCC ";
657 compilerStr += XSTR_MACRO(__GNUC__) "." XSTR_MACRO(__GNUC_MINOR__) "." XSTR_MACRO(__GNUC_PATCHLEVEL__);
658 #elif defined (_MSC_VER)
659 compilerStr = "MSVC " XSTR_MACRO(_MSC_FULL_VER);
661 compilerStr = "unknown compiler";
663 std::string buildType;
666 #elif defined(NDEBUG)
667 buildType = "Release";
669 buildType = "Unknown";
671 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(),
672 g_sysinfo.GetBuildTargetCpuFamily().c_str(), g_sysinfo.GetBuildTargetPlatformName().c_str(), g_sysinfo.GetXbmcBitness(), g_sysinfo.GetBuildTargetPlatformVersion().c_str());
674 #if defined(TARGET_DARWIN_OSX)
675 CLog::Log(LOGNOTICE, "Running on Darwin OSX %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
676 #elif defined(TARGET_DARWIN_IOS)
677 CLog::Log(LOGNOTICE, "Running on Darwin iOS %d-bit %s%s", g_sysinfo.GetKernelBitness(), g_sysinfo.IsAppleTV2() ? "(AppleTV2) " : "", g_sysinfo.GetUnameVersion().c_str());
678 #elif defined(TARGET_FREEBSD)
679 CLog::Log(LOGNOTICE, "Running on FreeBSD %d-bit %s", g_sysinfo.GetKernelBitness(), g_sysinfo.GetUnameVersion().c_str());
680 #elif defined(TARGET_POSIX)
681 CLog::Log(LOGNOTICE, "Running on Linux %d-bit (%s, %s)", g_sysinfo.GetKernelBitness(), g_sysinfo.GetLinuxDistro().c_str(), g_sysinfo.GetUnameVersion().c_str());
682 #elif defined(TARGET_WINDOWS)
683 CLog::Log(LOGNOTICE, "Running on %s", g_sysinfo.GetKernelVersion().c_str());
686 CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", g_cpuInfo.getCPUModel().c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount()==1) ? "" : "s");
687 #if defined(TARGET_WINDOWS)
688 CLog::Log(LOGNOTICE, "%s", CWIN32Util::GetResInfoString().c_str());
689 CLog::Log(LOGNOTICE, "Running with %s rights", (CWIN32Util::IsCurrentUserLocalAdministrator() == TRUE) ? "administrator" : "restricted");
690 CLog::Log(LOGNOTICE, "Aero is %s", (g_sysinfo.IsAeroDisabled() == true) ? "disabled" : "enabled");
693 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
694 CLog::Log(LOGNOTICE, "ARM Features: Neon enabled");
696 CLog::Log(LOGNOTICE, "ARM Features: Neon disabled");
698 CSpecialProtocol::LogPaths();
700 CStdString executable = CUtil::ResolveExecutablePath();
701 CLog::Log(LOGNOTICE, "The executable running is: %s", executable.c_str());
702 CLog::Log(LOGNOTICE, "Local hostname: %s", m_network->GetHostName().c_str());
703 CLog::Log(LOGNOTICE, "Log File is located: %sxbmc.log", g_advancedSettings.m_logFolder.c_str());
704 CLog::Log(LOGNOTICE, "-----------------------------------------------------------------------");
706 CStdString strExecutablePath;
707 CUtil::GetHomePath(strExecutablePath);
710 g_xrandr.LoadCustomModeLinesToAllOutputs();
713 // for python scripts that check the OS
714 #if defined(TARGET_DARWIN)
715 setenv("OS","OS X",true);
716 #elif defined(TARGET_POSIX)
717 setenv("OS","Linux",true);
718 #elif defined(TARGET_WINDOWS)
719 CEnvironment::setenv("OS", "win32");
722 g_powerManager.Initialize();
724 // Load the AudioEngine before settings as they need to query the engine
725 if (!CAEFactory::LoadEngine())
727 CLog::Log(LOGFATAL, "CApplication::Create: Failed to load an AudioEngine");
731 // Initialize default Settings - don't move
732 CLog::Log(LOGNOTICE, "load settings...");
733 if (!CSettings::Get().Initialize())
736 g_powerManager.SetDefaults();
738 // load the actual values
739 if (!CSettings::Get().Load())
741 CLog::Log(LOGFATAL, "unable to load settings");
744 CSettings::Get().SetLoaded();
746 CLog::Log(LOGINFO, "creating subdirectories");
747 CLog::Log(LOGINFO, "userdata folder: %s", CProfilesManager::Get().GetProfileUserDataFolder().c_str());
748 CLog::Log(LOGINFO, "recording folder: %s", CSettings::Get().GetString("audiocds.recordingpath").c_str());
749 CLog::Log(LOGINFO, "screenshots folder: %s", CSettings::Get().GetString("debug.screenshotpath").c_str());
750 CDirectory::Create(CProfilesManager::Get().GetUserDataFolder());
751 CDirectory::Create(CProfilesManager::Get().GetProfileUserDataFolder());
752 CProfilesManager::Get().CreateProfileFolders();
754 update_emu_environ();//apply the GUI settings
756 // initialize our charset converter
757 g_charsetConverter.reset();
759 // Load the langinfo to have user charset <-> utf-8 conversion
760 CStdString strLanguage = CSettings::Get().GetString("locale.language");
761 strLanguage[0] = toupper(strLanguage[0]);
763 CStdString strLangInfoPath;
764 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strLanguage.c_str());
766 CLog::Log(LOGINFO, "load language info file: %s", strLangInfoPath.c_str());
767 g_langInfo.Load(strLangInfoPath);
768 g_langInfo.SetAudioLanguage(CSettings::Get().GetString("locale.audiolanguage"));
769 g_langInfo.SetSubtitleLanguage(CSettings::Get().GetString("locale.subtitlelanguage"));
771 CStdString strLanguagePath = "special://xbmc/language/";
773 CLog::Log(LOGINFO, "load %s language file, from path: %s", strLanguage.c_str(), strLanguagePath.c_str());
774 if (!g_localizeStrings.Load(strLanguagePath, strLanguage))
776 CLog::Log(LOGFATAL, "%s: Failed to load %s language file, from path: %s", __FUNCTION__, strLanguage.c_str(), strLanguagePath.c_str());
780 // start the AudioEngine
781 if (!CAEFactory::StartEngine())
783 CLog::Log(LOGFATAL, "CApplication::Create: Failed to start the AudioEngine");
787 // restore AE's previous volume state
788 SetHardwareVolume(m_volumeLevel);
789 CAEFactory::SetMute (m_muted);
790 CAEFactory::SetSoundMode(CSettings::Get().GetInt("audiooutput.guisoundmode"));
792 // initialize m_replayGainSettings
793 m_replayGainSettings.iType = CSettings::Get().GetInt("musicplayer.replaygaintype");
794 m_replayGainSettings.iPreAmp = CSettings::Get().GetInt("musicplayer.replaygainpreamp");
795 m_replayGainSettings.iNoGainPreAmp = CSettings::Get().GetInt("musicplayer.replaygainnogainpreamp");
796 m_replayGainSettings.bAvoidClipping = CSettings::Get().GetBool("musicplayer.replaygainavoidclipping");
798 // initialize the addon database (must be before the addon manager is init'd)
799 CDatabaseManager::Get().Initialize(true);
802 CScriptInvocationManager::Get().RegisterLanguageInvocationHandler(&g_pythonParser, ".py");
805 // start-up Addons Framework
806 // currently bails out if either cpluff Dll is unavailable or system dir can not be scanned
807 if (!CAddonMgr::Get().Init())
809 CLog::Log(LOGFATAL, "CApplication::Create: Unable to start CAddonMgr");
813 // set logging from debug add-on
815 CAddonMgr::Get().GetAddon("xbmc.debug", addon);
817 g_advancedSettings.SetExtraLogsFromAddon(addon.get());
819 g_peripherals.Initialise();
821 // Create the Mouse, Keyboard, Remote, and Joystick devices
822 // Initialize after loading settings to get joystick deadzone setting
823 g_Mouse.Initialize();
824 g_Mouse.SetEnabled(CSettings::Get().GetBool("input.enablemouse"));
826 g_Keyboard.Initialize();
827 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
828 g_RemoteControl.Initialize();
831 #if defined(TARGET_DARWIN_OSX)
832 // Configure and possible manually start the helper.
833 XBMCHelper::GetInstance().Configure();
836 CUtil::InitRandomSeed();
838 g_mediaManager.Initialize();
840 m_lastFrameTime = XbmcThreads::SystemClockMillis();
841 m_lastRenderTime = m_lastFrameTime;
845 bool CApplication::CreateGUI()
849 CLog::Log(LOGNOTICE, "Setup SDL");
851 /* Clean up on exit, exit on window close and interrupt */
854 uint32_t sdlFlags = 0;
856 #if defined(HAS_SDL_OPENGL) || (HAS_GLES == 2)
857 sdlFlags |= SDL_INIT_VIDEO;
860 #if defined(HAS_SDL_JOYSTICK) && !defined(TARGET_WINDOWS)
861 sdlFlags |= SDL_INIT_JOYSTICK;
864 //depending on how it's compiled, SDL periodically calls XResetScreenSaver when it's fullscreen
865 //this might bring the monitor out of standby, so we have to disable it explicitly
866 //by passing 0 for overwrite to setsenv, the user can still override this by setting the environment variable
867 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
868 setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
874 // for nvidia cards - vsync currently ALWAYS enabled.
875 // the reason is that after screen has been setup changing this env var will make no difference.
876 setenv("__GL_SYNC_TO_VBLANK", "1", 0);
877 setenv("__GL_YIELD", "USLEEP", 0);
880 m_bSystemScreenSaverEnable = g_Windowing.IsSystemScreenSaverEnabled();
881 g_Windowing.EnableSystemScreenSaver(false);
884 if (SDL_Init(sdlFlags) != 0)
886 CLog::Log(LOGFATAL, "XBAppEx: Unable to initialize SDL: %s", SDL_GetError());
889 #if defined(TARGET_DARWIN)
890 // SDL_Init will install a handler for segfaults, restore the default handler.
891 signal(SIGSEGV, SIG_DFL);
895 // Initialize core peripheral port support. Note: If these parameters
896 // are 0 and NULL, respectively, then the default number and types of
897 // controllers will be initialized.
898 if (!g_Windowing.InitWindowSystem())
900 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init windowing system");
904 // Retrieve the matching resolution based on GUI settings
905 CDisplaySettings::Get().SetCurrentResolution(CDisplaySettings::Get().GetDisplayResolution());
906 CLog::Log(LOGNOTICE, "Checking resolution %i", CDisplaySettings::Get().GetCurrentResolution());
907 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
909 CLog::Log(LOGNOTICE, "Setting safe mode %i", RES_DESKTOP);
910 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP, true);
913 // update the window resolution
914 g_Windowing.SetWindowResolution(CSettings::Get().GetInt("window.width"), CSettings::Get().GetInt("window.height"));
916 if (g_advancedSettings.m_startFullScreen && CDisplaySettings::Get().GetCurrentResolution() == RES_WINDOW)
917 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
919 if (!g_graphicsContext.IsValidResolution(CDisplaySettings::Get().GetCurrentResolution()))
921 // Oh uh - doesn't look good for starting in their wanted screenmode
922 CLog::Log(LOGERROR, "The screen resolution requested is not valid, resetting to a valid mode");
923 CDisplaySettings::Get().SetCurrentResolution(RES_DESKTOP);
930 if (g_advancedSettings.m_splashImage)
932 CStdString strUserSplash = "special://home/media/Splash.png";
933 if (CFile::Exists(strUserSplash))
935 CLog::Log(LOGINFO, "load user splash image: %s", CSpecialProtocol::TranslatePath(strUserSplash).c_str());
936 m_splash = new CSplash(strUserSplash);
940 CLog::Log(LOGINFO, "load default splash image: %s", CSpecialProtocol::TranslatePath("special://xbmc/media/Splash.png").c_str());
941 m_splash = new CSplash("special://xbmc/media/Splash.png");
946 // The key mappings may already have been loaded by a peripheral
947 CLog::Log(LOGINFO, "load keymapping");
948 if (!CButtonTranslator::GetInstance().Load())
951 RESOLUTION_INFO info = g_graphicsContext.GetResInfo();
952 CLog::Log(LOGINFO, "GUI format %ix%i, Display %s",
955 info.strMode.c_str());
956 g_windowManager.Initialize();
961 bool CApplication::InitWindow()
963 #ifdef TARGET_DARWIN_OSX
964 // force initial window creation to be windowed, if fullscreen, it will switch to it below
965 // fixes the white screen of death if starting fullscreen and switching to windowed.
966 bool bFullScreen = false;
967 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetResolutionInfo(RES_WINDOW), OnEvent))
969 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
973 bool bFullScreen = CDisplaySettings::Get().GetCurrentResolution() != RES_WINDOW;
974 if (!g_Windowing.CreateNewWindow("XBMC", bFullScreen, CDisplaySettings::Get().GetCurrentResolutionInfo(), OnEvent))
976 CLog::Log(LOGFATAL, "CApplication::Create: Unable to create window");
981 if (!g_Windowing.InitRenderSystem())
983 CLog::Log(LOGFATAL, "CApplication::Create: Unable to init rendering system");
986 // set GUI res and force the clear of the screen
987 g_graphicsContext.SetVideoResolution(CDisplaySettings::Get().GetCurrentResolution());
988 g_fontManager.ReloadTTFFonts();
992 bool CApplication::DestroyWindow()
994 g_fontManager.UnloadTTFFonts();
995 return g_Windowing.DestroyWindow();
998 bool CApplication::InitDirectoriesLinux()
1001 The following is the directory mapping for Platform Specific Mode:
1003 special://xbmc/ => [read-only] system directory (/usr/share/xbmc)
1004 special://home/ => [read-write] user's directory that will override special://xbmc/ system-wide
1005 installations like skins, screensavers, etc.
1007 NOTE: XBMC will look in both special://xbmc/addons and special://home/addons for addons.
1008 special://masterprofile/ => [read-write] userdata of master profile. It will by default be
1009 mapped to special://home/userdata ($HOME/.xbmc/userdata)
1010 special://profile/ => [read-write] current profile's userdata directory.
1011 Generally special://masterprofile for the master profile or
1012 special://masterprofile/profiles/<profile_name> for other profiles.
1014 NOTE: All these root directories are lowercase. Some of the sub-directories
1015 might be mixed case.
1018 #if defined(TARGET_POSIX) && !defined(TARGET_DARWIN)
1019 CStdString userName;
1021 userName = getenv("USER");
1025 CStdString userHome;
1027 userHome = getenv("HOME");
1031 CStdString xbmcBinPath, xbmcPath;
1032 CUtil::GetHomePath(xbmcBinPath, "XBMC_BIN_HOME");
1033 xbmcPath = getenv("XBMC_HOME");
1035 if (xbmcPath.IsEmpty())
1037 xbmcPath = xbmcBinPath;
1038 /* Check if xbmc binaries and arch independent data files are being kept in
1039 * separate locations. */
1040 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1042 /* Attempt to locate arch independent data files. */
1043 CUtil::GetHomePath(xbmcPath);
1044 if (!CFile::Exists(URIUtils::AddFileToFolder(xbmcPath, "language")))
1046 fprintf(stderr, "Unable to find path to XBMC data files!\n");
1052 /* Set some environment variables */
1053 setenv("XBMC_BIN_HOME", xbmcBinPath.c_str(), 0);
1054 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1056 if (m_bPlatformDirectories)
1058 // map our special drives
1059 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1060 CSpecialProtocol::SetXBMCPath(xbmcPath);
1061 CSpecialProtocol::SetHomePath(userHome + "/.xbmc");
1062 CSpecialProtocol::SetMasterProfilePath(userHome + "/.xbmc/userdata");
1064 CStdString strTempPath = userHome;
1065 strTempPath = URIUtils::AddFileToFolder(strTempPath, ".xbmc/temp");
1066 if (getenv("XBMC_TEMP"))
1067 strTempPath = getenv("XBMC_TEMP");
1068 CSpecialProtocol::SetTempPath(strTempPath);
1070 URIUtils::AddSlashAtEnd(strTempPath);
1071 g_advancedSettings.m_logFolder = strTempPath;
1078 URIUtils::AddSlashAtEnd(xbmcPath);
1079 g_advancedSettings.m_logFolder = xbmcPath;
1081 CSpecialProtocol::SetXBMCBinPath(xbmcBinPath);
1082 CSpecialProtocol::SetXBMCPath(xbmcPath);
1083 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1084 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1086 CStdString strTempPath = xbmcPath;
1087 strTempPath = URIUtils::AddFileToFolder(strTempPath, "portable_data/temp");
1088 if (getenv("XBMC_TEMP"))
1089 strTempPath = getenv("XBMC_TEMP");
1090 CSpecialProtocol::SetTempPath(strTempPath);
1093 URIUtils::AddSlashAtEnd(strTempPath);
1094 g_advancedSettings.m_logFolder = strTempPath;
1103 bool CApplication::InitDirectoriesOSX()
1105 #if defined(TARGET_DARWIN)
1106 CStdString userName;
1108 userName = getenv("USER");
1112 CStdString userHome;
1114 userHome = getenv("HOME");
1118 CStdString xbmcPath;
1119 CUtil::GetHomePath(xbmcPath);
1120 setenv("XBMC_HOME", xbmcPath.c_str(), 0);
1122 #if defined(TARGET_DARWIN_IOS)
1123 CStdString fontconfigPath;
1124 fontconfigPath = xbmcPath + "/system/players/dvdplayer/etc/fonts/fonts.conf";
1125 setenv("FONTCONFIG_FILE", fontconfigPath.c_str(), 0);
1128 // setup path to our internal dylibs so loader can find them
1129 CStdString frameworksPath = CUtil::GetFrameworksPath();
1130 CSpecialProtocol::SetXBMCFrameworksPath(frameworksPath);
1132 // OSX always runs with m_bPlatformDirectories == true
1133 if (m_bPlatformDirectories)
1135 // map our special drives
1136 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1137 CSpecialProtocol::SetXBMCPath(xbmcPath);
1138 #if defined(TARGET_DARWIN_IOS)
1139 CSpecialProtocol::SetHomePath(userHome + "/Library/Preferences/XBMC");
1140 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Preferences/XBMC/userdata");
1142 CSpecialProtocol::SetHomePath(userHome + "/Library/Application Support/XBMC");
1143 CSpecialProtocol::SetMasterProfilePath(userHome + "/Library/Application Support/XBMC/userdata");
1146 // location for temp files
1147 #if defined(TARGET_DARWIN_IOS)
1148 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, "Library/Preferences/XBMC/temp");
1150 CStdString strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/");
1151 CDirectory::Create(strTempPath);
1152 strTempPath = URIUtils::AddFileToFolder(userHome, ".xbmc/temp");
1154 CSpecialProtocol::SetTempPath(strTempPath);
1156 // xbmc.log file location
1157 #if defined(TARGET_DARWIN_IOS)
1158 strTempPath = userHome + "/Library/Preferences";
1160 strTempPath = userHome + "/Library/Logs";
1162 URIUtils::AddSlashAtEnd(strTempPath);
1163 g_advancedSettings.m_logFolder = strTempPath;
1169 URIUtils::AddSlashAtEnd(xbmcPath);
1170 g_advancedSettings.m_logFolder = xbmcPath;
1172 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1173 CSpecialProtocol::SetXBMCPath(xbmcPath);
1174 CSpecialProtocol::SetHomePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data"));
1175 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(xbmcPath, "portable_data/userdata"));
1177 CStdString strTempPath = URIUtils::AddFileToFolder(xbmcPath, "portable_data/temp");
1178 CSpecialProtocol::SetTempPath(strTempPath);
1180 URIUtils::AddSlashAtEnd(strTempPath);
1181 g_advancedSettings.m_logFolder = strTempPath;
1190 bool CApplication::InitDirectoriesWin32()
1192 #ifdef TARGET_WINDOWS
1193 CStdString xbmcPath;
1195 CUtil::GetHomePath(xbmcPath);
1196 CEnvironment::setenv("XBMC_HOME", xbmcPath);
1197 CSpecialProtocol::SetXBMCBinPath(xbmcPath);
1198 CSpecialProtocol::SetXBMCPath(xbmcPath);
1200 CStdString strWin32UserFolder = CWIN32Util::GetProfilePath();
1202 g_advancedSettings.m_logFolder = strWin32UserFolder;
1203 CSpecialProtocol::SetHomePath(strWin32UserFolder);
1204 CSpecialProtocol::SetMasterProfilePath(URIUtils::AddFileToFolder(strWin32UserFolder, "userdata"));
1205 CSpecialProtocol::SetTempPath(URIUtils::AddFileToFolder(strWin32UserFolder,"cache"));
1207 CEnvironment::setenv("XBMC_PROFILE_USERDATA", CSpecialProtocol::TranslatePath("special://masterprofile/"));
1211 // Expand the DLL search path with our directories
1212 CWIN32Util::ExtendDllPath();
1220 void CApplication::CreateUserDirs()
1222 CDirectory::Create("special://home/");
1223 CDirectory::Create("special://home/addons");
1224 CDirectory::Create("special://home/addons/packages");
1225 CDirectory::Create("special://home/media");
1226 CDirectory::Create("special://home/sounds");
1227 CDirectory::Create("special://home/system");
1228 CDirectory::Create("special://masterprofile/");
1229 CDirectory::Create("special://temp/");
1230 CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
1233 bool CApplication::Initialize()
1235 #if defined(HAS_DVD_DRIVE) && !defined(TARGET_WINDOWS) // somehow this throws an "unresolved external symbol" on win32
1236 // turn off cdio logging
1237 cdio_loglevel_default = CDIO_LOG_ERROR;
1240 #ifdef TARGET_POSIX // TODO: Win32 has no special://home/ mapping by default, so we
1241 // must create these here. Ideally this should be using special://home/ and
1242 // be platform agnostic (i.e. unify the InitDirectories*() functions)
1243 if (!m_bPlatformDirectories)
1246 CDirectory::Create("special://xbmc/language");
1247 CDirectory::Create("special://xbmc/addons");
1248 CDirectory::Create("special://xbmc/sounds");
1251 // Load curl so curl_global_init gets called before any service threads
1252 // are started. Unloading will have no effect as curl is never fully unloaded.
1253 // To quote man curl_global_init:
1254 // "This function is not thread safe. You must not call it when any other
1255 // thread in the program (i.e. a thread sharing the same memory) is running.
1256 // This doesn't just mean no other thread that is using libcurl. Because
1257 // curl_global_init() calls functions of other libraries that are similarly
1258 // thread unsafe, it could conflict with any other thread that
1259 // uses these other libraries."
1260 g_curlInterface.Load();
1261 g_curlInterface.Unload();
1263 // initialize (and update as needed) our databases
1264 CDatabaseManager::Get().Initialize();
1268 // Init DPMS, before creating the corresponding setting control.
1269 m_dpms = new DPMSSupport();
1270 if (g_windowManager.Initialized())
1272 CSettings::Get().GetSetting("powermanagement.displaysoff")->SetRequirementsMet(m_dpms->IsSupported());
1274 g_windowManager.Add(new CGUIWindowHome);
1275 g_windowManager.Add(new CGUIWindowPrograms);
1276 g_windowManager.Add(new CGUIWindowPictures);
1277 g_windowManager.Add(new CGUIWindowFileManager);
1278 g_windowManager.Add(new CGUIWindowSettings);
1279 g_windowManager.Add(new CGUIWindowSystemInfo);
1281 g_windowManager.Add(new CGUIWindowTestPatternGL);
1284 g_windowManager.Add(new CGUIWindowTestPatternDX);
1286 g_windowManager.Add(new CGUIWindowSettingsScreenCalibration);
1287 g_windowManager.Add(new CGUIWindowSettingsCategory);
1288 g_windowManager.Add(new CGUIWindowVideoNav);
1289 g_windowManager.Add(new CGUIWindowVideoPlaylist);
1290 g_windowManager.Add(new CGUIWindowLoginScreen);
1291 g_windowManager.Add(new CGUIWindowSettingsProfile);
1292 g_windowManager.Add(new CGUIWindow(WINDOW_SKIN_SETTINGS, "SkinSettings.xml"));
1293 g_windowManager.Add(new CGUIWindowAddonBrowser);
1294 g_windowManager.Add(new CGUIWindowScreensaverDim);
1295 g_windowManager.Add(new CGUIWindowDebugInfo);
1296 g_windowManager.Add(new CGUIWindowPointer);
1297 g_windowManager.Add(new CGUIDialogYesNo);
1298 g_windowManager.Add(new CGUIDialogProgress);
1299 g_windowManager.Add(new CGUIDialogExtendedProgressBar);
1300 g_windowManager.Add(new CGUIDialogKeyboardGeneric);
1301 g_windowManager.Add(new CGUIDialogVolumeBar);
1302 g_windowManager.Add(new CGUIDialogSeekBar);
1303 g_windowManager.Add(new CGUIDialogSubMenu);
1304 g_windowManager.Add(new CGUIDialogContextMenu);
1305 g_windowManager.Add(new CGUIDialogKaiToast);
1306 g_windowManager.Add(new CGUIDialogNumeric);
1307 g_windowManager.Add(new CGUIDialogGamepad);
1308 g_windowManager.Add(new CGUIDialogButtonMenu);
1309 g_windowManager.Add(new CGUIDialogMuteBug);
1310 g_windowManager.Add(new CGUIDialogPlayerControls);
1312 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorSmall);
1313 g_windowManager.Add(new CGUIDialogKaraokeSongSelectorLarge);
1315 g_windowManager.Add(new CGUIDialogSlider);
1316 g_windowManager.Add(new CGUIDialogMusicOSD);
1317 g_windowManager.Add(new CGUIDialogVisualisationPresetList);
1318 g_windowManager.Add(new CGUIDialogVideoSettings);
1319 g_windowManager.Add(new CGUIDialogAudioSubtitleSettings);
1320 g_windowManager.Add(new CGUIDialogVideoBookmarks);
1321 // Don't add the filebrowser dialog - it's created and added when it's needed
1322 g_windowManager.Add(new CGUIDialogNetworkSetup);
1323 g_windowManager.Add(new CGUIDialogMediaSource);
1324 g_windowManager.Add(new CGUIDialogProfileSettings);
1325 g_windowManager.Add(new CGUIDialogFavourites);
1326 g_windowManager.Add(new CGUIDialogSongInfo);
1327 g_windowManager.Add(new CGUIDialogSmartPlaylistEditor);
1328 g_windowManager.Add(new CGUIDialogSmartPlaylistRule);
1329 g_windowManager.Add(new CGUIDialogBusy);
1330 g_windowManager.Add(new CGUIDialogPictureInfo);
1331 g_windowManager.Add(new CGUIDialogAddonInfo);
1332 g_windowManager.Add(new CGUIDialogAddonSettings);
1333 #ifdef HAS_LINUX_NETWORK
1334 g_windowManager.Add(new CGUIDialogAccessPoints);
1337 g_windowManager.Add(new CGUIDialogLockSettings);
1339 g_windowManager.Add(new CGUIDialogContentSettings);
1341 g_windowManager.Add(new CGUIDialogPlayEject);
1343 g_windowManager.Add(new CGUIDialogPeripheralManager);
1344 g_windowManager.Add(new CGUIDialogPeripheralSettings);
1346 g_windowManager.Add(new CGUIDialogMediaFilter);
1348 g_windowManager.Add(new CGUIWindowMusicPlayList);
1349 g_windowManager.Add(new CGUIWindowMusicSongs);
1350 g_windowManager.Add(new CGUIWindowMusicNav);
1351 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor);
1353 /* Load PVR related Windows and Dialogs */
1354 g_windowManager.Add(new CGUIDialogTeletext);
1355 g_windowManager.Add(new CGUIWindowPVR);
1356 g_windowManager.Add(new CGUIDialogPVRGuideInfo);
1357 g_windowManager.Add(new CGUIDialogPVRRecordingInfo);
1358 g_windowManager.Add(new CGUIDialogPVRTimerSettings);
1359 g_windowManager.Add(new CGUIDialogPVRGroupManager);
1360 g_windowManager.Add(new CGUIDialogPVRChannelManager);
1361 g_windowManager.Add(new CGUIDialogPVRGuideSearch);
1362 g_windowManager.Add(new CGUIDialogPVRChannelsOSD);
1363 g_windowManager.Add(new CGUIDialogPVRGuideOSD);
1364 g_windowManager.Add(new CGUIDialogPVRDirectorOSD);
1365 g_windowManager.Add(new CGUIDialogPVRCutterOSD);
1367 g_windowManager.Add(new CGUIDialogSelect);
1368 g_windowManager.Add(new CGUIDialogMusicInfo);
1369 g_windowManager.Add(new CGUIDialogOK);
1370 g_windowManager.Add(new CGUIDialogVideoInfo);
1371 g_windowManager.Add(new CGUIDialogTextViewer);
1372 g_windowManager.Add(new CGUIWindowFullScreen);
1373 g_windowManager.Add(new CGUIWindowVisualisation);
1374 g_windowManager.Add(new CGUIWindowSlideShow);
1375 g_windowManager.Add(new CGUIDialogFileStacking);
1377 g_windowManager.Add(new CGUIWindowKaraokeLyrics);
1380 g_windowManager.Add(new CGUIDialogVideoOSD);
1381 g_windowManager.Add(new CGUIDialogMusicOverlay);
1382 g_windowManager.Add(new CGUIDialogVideoOverlay);
1383 g_windowManager.Add(new CGUIWindowScreensaver);
1384 g_windowManager.Add(new CGUIWindowWeather);
1385 g_windowManager.Add(new CGUIWindowStartup);
1387 /* window id's 3000 - 3100 are reserved for python */
1389 // Make sure we have at least the default skin
1390 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1391 if (!LoadSkin(CSettings::Get().GetString("lookandfeel.skin")) && !LoadSkin(defaultSkin))
1393 CLog::Log(LOGERROR, "Default skin '%s' not found! Terminating..", defaultSkin.c_str());
1397 if (g_advancedSettings.m_splashImage)
1398 SAFE_DELETE(m_splash);
1400 if (CSettings::Get().GetBool("masterlock.startuplock") &&
1401 CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1402 !CProfilesManager::Get().GetMasterProfile().getLockCode().IsEmpty())
1404 g_passwordManager.CheckStartUpLock();
1407 // check if we should use the login screen
1408 if (CProfilesManager::Get().UsingLoginScreen())
1409 g_windowManager.ActivateWindow(WINDOW_LOGIN_SCREEN);
1413 CJSONRPC::Initialize();
1415 ADDON::CAddonMgr::Get().StartServices(false);
1416 if (g_SkinInfo->GetFirstWindow() == WINDOW_PVR)
1418 g_windowManager.ActivateWindow(WINDOW_HOME);
1419 StartPVRManager(true);
1423 StartPVRManager(false);
1424 g_windowManager.ActivateWindow(g_SkinInfo->GetFirstWindow());
1427 CStereoscopicsManager::Get().Initialize();
1431 else //No GUI Created
1434 CJSONRPC::Initialize();
1436 ADDON::CAddonMgr::Get().StartServices(false);
1439 g_sysinfo.Refresh();
1441 CLog::Log(LOGINFO, "removing tempfiles");
1442 CUtil::RemoveTempFiles();
1444 if (!CProfilesManager::Get().UsingLoginScreen())
1450 m_slowTimer.StartZero();
1452 #if defined(HAVE_LIBCRYSTALHD)
1453 CCrystalHD::GetInstance();
1456 CAddonMgr::Get().StartServices(true);
1458 CLog::Log(LOGNOTICE, "initialize done");
1460 m_bInitializing = false;
1462 // reset our screensaver (starts timers etc.)
1465 #ifdef HAS_SDL_JOYSTICK
1466 g_Joystick.SetEnabled(CSettings::Get().GetBool("input.enablejoystick") &&
1467 CPeripheralImon::GetCountOfImonsConflictWithDInput() == 0 );
1473 bool CApplication::StartServer(enum ESERVERS eServer, bool bStart, bool bWait/* = false*/)
1479 // the callback will take care of starting/stopping webserver
1480 ret = CSettings::Get().SetBool("services.webserver", bStart);
1483 case ES_AIRPLAYSERVER:
1484 // the callback will take care of starting/stopping airplay
1485 ret = CSettings::Get().SetBool("services.airplay", bStart);
1488 case ES_JSONRPCSERVER:
1489 // the callback will take care of starting/stopping jsonrpc server
1490 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1494 // the callback will take care of starting/stopping upnp server
1495 ret = CSettings::Get().SetBool("services.upnpserver", bStart);
1498 case ES_UPNPRENDERER:
1499 // the callback will take care of starting/stopping upnp renderer
1500 ret = CSettings::Get().SetBool("services.upnprenderer", bStart);
1503 case ES_EVENTSERVER:
1504 // the callback will take care of starting/stopping event server
1505 ret = CSettings::Get().SetBool("services.esenabled", bStart);
1509 // the callback will take care of starting/stopping zeroconf
1510 ret = CSettings::Get().SetBool("services.zeroconf", bStart);
1517 CSettings::Get().Save();
1522 void CApplication::StartPVRManager(bool bOpenPVRWindow /* = false */)
1524 if (CSettings::Get().GetBool("pvrmanager.enabled"))
1525 g_PVRManager.Start(true, bOpenPVRWindow);
1528 void CApplication::StopPVRManager()
1530 CLog::Log(LOGINFO, "stopping PVRManager");
1531 if (g_PVRManager.IsPlaying())
1533 g_PVRManager.Stop();
1534 g_EpgContainer.Stop();
1537 void CApplication::StartServices()
1539 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1540 // Start Thread for DVD Mediatype detection
1541 CLog::Log(LOGNOTICE, "start dvd mediatype detection");
1542 m_DetectDVDType.Create(false, THREAD_MINSTACKSIZE);
1545 CLog::Log(LOGNOTICE, "initializing playlistplayer");
1546 g_playlistPlayer.SetRepeat(PLAYLIST_MUSIC, CMediaSettings::Get().DoesMusicPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1547 g_playlistPlayer.SetShuffle(PLAYLIST_MUSIC, CMediaSettings::Get().IsMusicPlaylistShuffled());
1548 g_playlistPlayer.SetRepeat(PLAYLIST_VIDEO, CMediaSettings::Get().DoesVideoPlaylistRepeat() ? PLAYLIST::REPEAT_ALL : PLAYLIST::REPEAT_NONE);
1549 g_playlistPlayer.SetShuffle(PLAYLIST_VIDEO, CMediaSettings::Get().IsVideoPlaylistShuffled());
1550 CLog::Log(LOGNOTICE, "DONE initializing playlistplayer");
1553 void CApplication::StopServices()
1555 m_network->NetworkMessage(CNetwork::SERVICES_DOWN, 0);
1557 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE)
1558 CLog::Log(LOGNOTICE, "stop dvd detect media");
1559 m_DetectDVDType.StopThread();
1562 g_peripherals.Clear();
1565 void CApplication::OnSettingChanged(const CSetting *setting)
1567 if (setting == NULL)
1570 const std::string &settingId = setting->GetId();
1571 if (settingId == "lookandfeel.skin" ||
1572 settingId == "lookandfeel.font" ||
1573 settingId == "lookandfeel.skincolors")
1574 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1575 else if (settingId == "lookandfeel.skintheme")
1577 // also set the default color theme
1578 string colorTheme = URIUtils::ReplaceExtension(((CSettingString*)setting)->GetValue(), ".xml");
1579 if (StringUtils::EqualsNoCase(colorTheme, "Textures.xml"))
1580 colorTheme = "defaults.xml";
1582 // check if we have to change the skin color
1583 // if yes, it will trigger a call to ReloadSkin() in
1584 // it's OnSettingChanged() callback
1585 // if no we have to call ReloadSkin() ourselves
1586 if (!StringUtils::EqualsNoCase(colorTheme, CSettings::Get().GetString("lookandfeel.skincolors")))
1587 CSettings::Get().SetString("lookandfeel.skincolors", colorTheme);
1589 CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin");
1591 else if (settingId == "lookandfeel.skinzoom")
1592 g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
1593 else if (StringUtils::StartsWithNoCase(settingId, "audiooutput."))
1595 if (settingId == "audiooutput.guisoundmode")
1597 CAEFactory::SetSoundMode(((CSettingInt*)setting)->GetValue());
1599 // this tells player whether to open an audio stream passthrough or PCM
1600 // if this is changed, audio stream has to be reopened
1601 else if (settingId == "audiooutput.mode")
1603 CApplicationMessenger::Get().MediaRestart(false);
1607 CAEFactory::OnSettingsChange(settingId);
1609 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygaintype"))
1610 m_replayGainSettings.iType = ((CSettingInt*)setting)->GetValue();
1611 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainpreamp"))
1612 m_replayGainSettings.iPreAmp = ((CSettingInt*)setting)->GetValue();
1613 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainnogainpreamp"))
1614 m_replayGainSettings.iNoGainPreAmp = ((CSettingInt*)setting)->GetValue();
1615 else if (StringUtils::EqualsNoCase(settingId, "musicplayer.replaygainavoidclipping"))
1616 m_replayGainSettings.bAvoidClipping = ((CSettingBool*)setting)->GetValue();
1619 void CApplication::OnSettingAction(const CSetting *setting)
1621 if (setting == NULL)
1624 const std::string &settingId = setting->GetId();
1625 if (settingId == "lookandfeel.skinsettings")
1626 g_windowManager.ActivateWindow(WINDOW_SKIN_SETTINGS);
1627 else if (settingId == "screensaver.preview")
1628 ActivateScreenSaver(true);
1629 else if (settingId == "screensaver.settings")
1632 if (CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), addon, ADDON_SCREENSAVER))
1633 CGUIDialogAddonSettings::ShowAndGetInput(addon);
1635 else if (settingId == "videoscreen.guicalibration")
1636 g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
1637 else if (settingId == "videoscreen.testpattern")
1638 g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
1641 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
1643 if (setting == NULL)
1646 const std::string &settingId = setting->GetId();
1647 if (settingId == "audiooutput.channels")
1649 // check if this is an update from Eden
1650 if (oldSettingId != NULL && oldSettingNode != NULL &&
1651 StringUtils::EqualsNoCase(oldSettingId, "audiooutput.channellayout"))
1654 CSettingInt* channels = (CSettingInt*)setting;
1655 if (channels->FromString(oldSettingNode->FirstChild()->ValueStr()) && channels->GetValue() < AE_CH_LAYOUT_MAX - 1)
1656 ret = channels->SetValue(channels->GetValue() + 1);
1658 // let's just reset the audiodevice settings as well
1659 std::string audiodevice = CSettings::Get().GetString("audiooutput.audiodevice");
1660 CAEFactory::VerifyOutputDevice(audiodevice, false);
1661 ret |= CSettings::Get().SetString("audiooutput.audiodevice", audiodevice.c_str());
1666 else if (settingId == "screensaver.mode")
1668 CSettingString *screensaverMode = (CSettingString*)setting;
1669 // we no longer ship the built-in slideshow screensaver, replace it if it's still in use
1670 if (StringUtils::EqualsNoCase(screensaverMode->GetValue(), "screensaver.xbmc.builtin.slideshow"))
1671 return screensaverMode->SetValue("screensaver.xbmc.builtin.dim");
1673 else if (settingId == "scrapers.musicvideosdefault")
1675 CSettingAddon *musicvideoScraper = (CSettingAddon*)setting;
1676 if (StringUtils::EqualsNoCase(musicvideoScraper->GetValue(), "metadata.musicvideos.last.fm"))
1678 musicvideoScraper->Reset();
1686 bool CApplication::OnSettingsSaving() const
1688 // don't save settings when we're busy stopping the application
1689 // a lot of screens try to save settings on deinit and deinit is
1690 // called for every screen when the application is stopping
1697 void CApplication::ReloadSkin()
1699 m_skinReloading = false;
1700 CGUIMessage msg(GUI_MSG_LOAD_SKIN, -1, g_windowManager.GetActiveWindow());
1701 g_windowManager.SendMessage(msg);
1703 // Reload the skin, restoring the previously focused control. We need this as
1704 // the window unload will reset all control states.
1706 CGUIWindow* pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1708 iCtrlID = pWindow->GetFocusedControlID();
1710 g_application.LoadSkin(CSettings::Get().GetString("lookandfeel.skin"));
1714 pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow());
1715 if (pWindow && pWindow->HasSaveLastControl())
1717 CGUIMessage msg3(GUI_MSG_SETFOCUS, g_windowManager.GetActiveWindow(), iCtrlID, 0);
1718 pWindow->OnMessage(msg3);
1723 bool CApplication::Load(const TiXmlNode *settings)
1725 if (settings == NULL)
1728 const TiXmlElement *audioElement = settings->FirstChildElement("audio");
1729 if (audioElement != NULL)
1731 XMLUtils::GetBoolean(audioElement, "mute", m_muted);
1732 if (!XMLUtils::GetFloat(audioElement, "fvolumelevel", m_volumeLevel, VOLUME_MINIMUM, VOLUME_MAXIMUM))
1733 m_volumeLevel = VOLUME_MAXIMUM;
1739 bool CApplication::Save(TiXmlNode *settings) const
1741 if (settings == NULL)
1744 TiXmlElement volumeNode("audio");
1745 TiXmlNode *audioNode = settings->InsertEndChild(volumeNode);
1746 if (audioNode == NULL)
1749 XMLUtils::SetBoolean(audioNode, "mute", m_muted);
1750 XMLUtils::SetFloat(audioNode, "fvolumelevel", m_volumeLevel);
1755 bool CApplication::LoadSkin(const CStdString& skinID)
1757 if (m_skinReloading)
1761 if (CAddonMgr::Get().GetAddon(skinID, addon, ADDON_SKIN))
1763 LoadSkin(boost::dynamic_pointer_cast<ADDON::CSkinInfo>(addon));
1769 void CApplication::LoadSkin(const SkinPtr& skin)
1771 string defaultSkin = ((const CSettingString*)CSettings::Get().GetSetting("lookandfeel.skin"))->GetDefault();
1774 CLog::Log(LOGERROR, "failed to load requested skin, fallback to \"%s\" skin", defaultSkin.c_str());
1775 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1780 if (!skin->HasSkinFile("Home.xml"))
1782 // failed to find home.xml
1783 // fallback to default skin
1784 if (strcmpi(skin->ID().c_str(), defaultSkin.c_str()) != 0)
1786 CLog::Log(LOGERROR, "home.xml doesn't exist in skin: %s, fallback to \"%s\" skin", skin->ID().c_str(), defaultSkin.c_str());
1787 CSettings::Get().GetSetting("lookandfeel.skin")->Reset();
1788 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(24102), g_localizeStrings.Get(24103));
1793 bool bPreviousPlayingState=false;
1794 bool bPreviousRenderingState=false;
1795 if (g_application.m_pPlayer->IsPlayingVideo())
1797 bPreviousPlayingState = !g_application.m_pPlayer->IsPausedPlayback();
1798 if (bPreviousPlayingState)
1799 g_application.m_pPlayer->Pause();
1800 #ifdef HAS_VIDEO_PLAYBACK
1801 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
1803 g_windowManager.ActivateWindow(WINDOW_HOME);
1804 bPreviousRenderingState = true;
1808 // close the music and video overlays (they're re-opened automatically later)
1809 CSingleLock lock(g_graphicsContext);
1811 // save the current window details
1812 int currentWindow = g_windowManager.GetActiveWindow();
1813 vector<int> currentModelessWindows;
1814 g_windowManager.GetActiveModelessWindows(currentModelessWindows);
1818 CLog::Log(LOGINFO, " load skin from: %s (version: %s)", skin->Path().c_str(), skin->Version().c_str());
1820 g_SkinInfo->Start();
1822 CLog::Log(LOGINFO, " load fonts for skin...");
1823 g_graphicsContext.SetMediaDir(skin->Path());
1824 g_directoryCache.ClearSubPaths(skin->Path());
1825 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode(CSettings::Get().GetString("lookandfeel.font")))
1827 CLog::Log(LOGINFO, " language needs a ttf font, loading first ttf font available");
1828 CStdString strFontSet;
1829 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
1831 CLog::Log(LOGINFO, " new font is '%s'", strFontSet.c_str());
1832 CSettings::Get().SetString("lookandfeel.font", strFontSet);
1833 CSettings::Get().Save();
1836 CLog::Log(LOGERROR, " no ttf font found, but needed for the language %s.", CSettings::Get().GetString("locale.language").c_str());
1838 g_colorManager.Load(CSettings::Get().GetString("lookandfeel.skincolors"));
1840 g_fontManager.LoadFonts(CSettings::Get().GetString("lookandfeel.font"));
1842 // load in the skin strings
1843 CStdString langPath = URIUtils::AddFileToFolder(skin->Path(), "language");
1844 URIUtils::AddSlashAtEnd(langPath);
1846 g_localizeStrings.LoadSkinStrings(langPath, CSettings::Get().GetString("locale.language"));
1848 g_SkinInfo->LoadIncludes();
1851 start = CurrentHostCounter();
1853 CLog::Log(LOGINFO, " load new skin...");
1855 // Load the user windows
1859 end = CurrentHostCounter();
1860 freq = CurrentHostFrequency();
1861 CLog::Log(LOGDEBUG,"Load Skin XML: %.2fms", 1000.f * (end - start) / freq);
1863 CLog::Log(LOGINFO, " initialize new skin...");
1864 g_windowManager.AddMsgTarget(this);
1865 g_windowManager.AddMsgTarget(&g_playlistPlayer);
1866 g_windowManager.AddMsgTarget(&g_infoManager);
1867 g_windowManager.AddMsgTarget(&g_fontManager);
1868 g_windowManager.AddMsgTarget(&CStereoscopicsManager::Get());
1869 g_windowManager.SetCallback(*this);
1870 g_windowManager.Initialize();
1871 CTextureCache::Get().Initialize();
1872 g_audioManager.Enable(true);
1873 g_audioManager.Load();
1875 if (g_SkinInfo->HasSkinFile("DialogFullScreenInfo.xml"))
1876 g_windowManager.Add(new CGUIDialogFullScreenInfo);
1878 { // we can't register visible condition in dialog's ctor because infomanager is cleared when unloading skin
1879 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
1880 if (overlay) overlay->SetVisibleCondition("skin.hasvideooverlay");
1881 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
1882 if (overlay) overlay->SetVisibleCondition("skin.hasmusicoverlay");
1885 CLog::Log(LOGINFO, " skin loaded...");
1887 // leave the graphics lock
1891 if (currentWindow != WINDOW_INVALID)
1893 g_windowManager.ActivateWindow(currentWindow);
1894 for (unsigned int i = 0; i < currentModelessWindows.size(); i++)
1896 CGUIDialog *dialog = (CGUIDialog *)g_windowManager.GetWindow(currentModelessWindows[i]);
1897 if (dialog) dialog->Show();
1901 if (g_application.m_pPlayer->IsPlayingVideo())
1903 if (bPreviousPlayingState)
1904 g_application.m_pPlayer->Pause();
1905 if (bPreviousRenderingState)
1906 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
1910 void CApplication::UnloadSkin(bool forReload /* = false */)
1912 m_skinReloading = forReload;
1914 CLog::Log(LOGINFO, "Unloading old skin %s...", forReload ? "for reload " : "");
1916 g_audioManager.Enable(false);
1918 g_windowManager.DeInitialize();
1919 CTextureCache::Get().Deinitialize();
1921 // remove the skin-dependent window
1922 g_windowManager.Delete(WINDOW_DIALOG_FULLSCREEN_INFO);
1924 g_TextureManager.Cleanup();
1925 g_largeTextureManager.CleanupUnusedImages(true);
1927 g_fontManager.Clear();
1929 g_colorManager.Clear();
1931 g_charsetConverter.reset();
1933 g_infoManager.Clear();
1935 // The g_SkinInfo boost shared_ptr ought to be reset here
1936 // but there are too many places it's used without checking for NULL
1937 // and as a result a race condition on exit can cause a crash.
1940 bool CApplication::LoadUserWindows()
1942 // Start from wherever home.xml is
1943 std::vector<CStdString> vecSkinPath;
1944 g_SkinInfo->GetSkinPaths(vecSkinPath);
1945 for (unsigned int i = 0;i < vecSkinPath.size();++i)
1947 CLog::Log(LOGINFO, "Loading user windows, path %s", vecSkinPath[i].c_str());
1948 CFileItemList items;
1949 if (CDirectory::GetDirectory(vecSkinPath[i], items, ".xml", DIR_FLAG_NO_FILE_DIRS))
1951 for (int i = 0; i < items.Size(); ++i)
1953 if (items[i]->m_bIsFolder)
1955 CStdString skinFile = URIUtils::GetFileName(items[i]->GetPath());
1956 if (skinFile.Left(6).CompareNoCase("custom") == 0)
1958 CXBMCTinyXML xmlDoc;
1959 if (!xmlDoc.LoadFile(items[i]->GetPath()))
1961 CLog::Log(LOGERROR, "unable to load: %s, Line %d\n%s", items[i]->GetPath().c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
1965 // Root element should be <window>
1966 TiXmlElement* pRootElement = xmlDoc.RootElement();
1967 CStdString strValue = pRootElement->Value();
1968 if (!strValue.Equals("window"))
1970 CLog::Log(LOGERROR, "file: %s doesnt contain <window>", skinFile.c_str());
1974 // Read the <type> element to get the window type to create
1975 // If no type is specified, create a CGUIWindow as default
1976 CGUIWindow* pWindow = NULL;
1978 if (pRootElement->Attribute("type"))
1979 strType = pRootElement->Attribute("type");
1982 const TiXmlNode *pType = pRootElement->FirstChild("type");
1983 if (pType && pType->FirstChild())
1984 strType = pType->FirstChild()->Value();
1986 int id = WINDOW_INVALID;
1987 if (!pRootElement->Attribute("id", &id))
1989 const TiXmlNode *pType = pRootElement->FirstChild("id");
1990 if (pType && pType->FirstChild())
1991 id = atol(pType->FirstChild()->Value());
1993 CStdString visibleCondition;
1994 CGUIControlFactory::GetConditionalVisibility(pRootElement, visibleCondition);
1996 if (strType.Equals("dialog"))
1997 pWindow = new CGUIDialog(id + WINDOW_HOME, skinFile);
1998 else if (strType.Equals("submenu"))
1999 pWindow = new CGUIDialogSubMenu(id + WINDOW_HOME, skinFile);
2000 else if (strType.Equals("buttonmenu"))
2001 pWindow = new CGUIDialogButtonMenu(id + WINDOW_HOME, skinFile);
2003 pWindow = new CGUIWindow(id + WINDOW_HOME, skinFile);
2005 // Check to make sure the pointer isn't still null
2006 if (pWindow == NULL)
2008 CLog::Log(LOGERROR, "Out of memory / Failed to create new object in LoadUserWindows");
2011 if (id == WINDOW_INVALID || g_windowManager.GetWindow(WINDOW_HOME + id))
2016 pWindow->SetVisibleCondition(visibleCondition);
2017 pWindow->SetLoadType(CGUIWindow::KEEP_IN_MEMORY);
2018 g_windowManager.AddCustomWindow(pWindow);
2026 bool CApplication::RenderNoPresent()
2030 // DXMERGE: This may have been important?
2031 // g_graphicsContext.AcquireCurrentContext();
2033 g_graphicsContext.Lock();
2035 // dont show GUI when playing full screen video
2036 if (g_graphicsContext.IsFullScreenVideo())
2038 g_renderManager.Render(true, 0, 255);
2040 // close window overlays
2041 CGUIDialog *overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OVERLAY);
2042 if (overlay) overlay->Close(true);
2043 overlay = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_OVERLAY);
2044 if (overlay) overlay->Close(true);
2048 bool hasRendered = g_windowManager.Render();
2050 g_graphicsContext.Unlock();
2055 float CApplication::GetDimScreenSaverLevel() const
2057 if (!m_bScreenSave || !m_screenSaver ||
2058 (m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" &&
2059 m_screenSaver->ID() != "screensaver.xbmc.builtin.black" &&
2060 !m_screenSaver->ID().empty()))
2063 if (!m_screenSaver->GetSetting("level").IsEmpty())
2064 return 100.0f - (float)atof(m_screenSaver->GetSetting("level"));
2068 void CApplication::Render()
2070 // do not render if we are stopped or in background
2071 if (m_bStop || m_bInBackground)
2076 int vsync_mode = CSettings::Get().GetInt("videoscreen.vsync");
2078 bool hasRendered = false;
2079 bool limitFrames = false;
2080 unsigned int singleFrameTime = 10; // default limit 100 fps
2084 bool lowfps = m_dpmsIsActive || g_Windowing.EnableFrameLimiter();
2085 // Whether externalplayer is playing and we're unfocused
2086 bool extPlayerActive = m_pPlayer->GetCurrentPlayer() == EPC_EXTPLAYER && m_pPlayer->IsPlaying() && !m_AppFocused;
2088 m_bPresentFrame = false;
2089 if (!extPlayerActive && g_graphicsContext.IsFullScreenVideo() && !m_pPlayer->IsPausedPlayback() && g_renderManager.RendererHandlesPresent())
2091 m_bPresentFrame = g_renderManager.FrameWait(100);
2096 // engage the frame limiter as needed
2097 limitFrames = lowfps || extPlayerActive;
2098 // DXMERGE - we checked for g_videoConfig.GetVSyncMode() before this
2099 // perhaps allowing it to be set differently than the UI option??
2100 if (vsync_mode == VSYNC_DISABLED || vsync_mode == VSYNC_VIDEO)
2101 limitFrames = true; // not using vsync.
2102 else if ((g_infoManager.GetFPS() > g_graphicsContext.GetFPS() + 10) && g_infoManager.GetFPS() > 1000 / singleFrameTime)
2103 limitFrames = true; // using vsync, but it isn't working.
2107 if (extPlayerActive)
2109 ResetScreenSaver(); // Prevent screensaver dimming the screen
2110 singleFrameTime = 1000; // 1 fps, high wakeup latency but v.low CPU usage
2113 singleFrameTime = 200; // 5 fps, <=200 ms latency to wake up
2119 CSingleLock lock(g_graphicsContext);
2120 g_infoManager.UpdateFPS();
2122 if (g_graphicsContext.IsFullScreenVideo() && m_pPlayer->IsPlaying() && vsync_mode == VSYNC_VIDEO)
2123 g_Windowing.SetVSync(true);
2124 else if (vsync_mode == VSYNC_ALWAYS)
2125 g_Windowing.SetVSync(true);
2126 else if (vsync_mode != VSYNC_DRIVER)
2127 g_Windowing.SetVSync(false);
2129 if (m_bPresentFrame && m_pPlayer->IsPlaying() && !m_pPlayer->IsPaused())
2132 if(!g_Windowing.BeginRender())
2135 g_renderManager.FrameMove();
2137 CDirtyRegionList dirtyRegions = g_windowManager.GetDirty();
2138 if(g_graphicsContext.GetStereoMode())
2140 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_LEFT);
2141 if(RenderNoPresent())
2144 if(g_graphicsContext.GetStereoMode() != RENDER_STEREO_MODE_MONO)
2146 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_RIGHT);
2147 if(RenderNoPresent())
2150 g_graphicsContext.SetStereoView(RENDER_STEREO_VIEW_OFF);
2154 if(RenderNoPresent())
2158 g_renderManager.FrameFinish();
2160 g_Windowing.EndRender();
2162 // execute post rendering actions (finalize window closing)
2163 g_windowManager.AfterRender();
2165 // reset our info cache - we do this at the end of Render so that it is
2166 // fresh for the next process(), or after a windowclose animation (where process()
2168 g_infoManager.ResetCache();
2171 unsigned int now = XbmcThreads::SystemClockMillis();
2173 m_lastRenderTime = now;
2175 //when nothing has been rendered for m_guiDirtyRegionNoFlipTimeout milliseconds,
2176 //we don't call g_graphicsContext.Flip() anymore, this saves gpu and cpu usage
2178 if (g_advancedSettings.m_guiDirtyRegionNoFlipTimeout >= 0)
2179 flip = hasRendered || (now - m_lastRenderTime) < (unsigned int)g_advancedSettings.m_guiDirtyRegionNoFlipTimeout;
2183 //fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
2184 if (limitFrames || !flip)
2187 singleFrameTime = 40; //if not flipping, loop at 25 fps
2189 unsigned int frameTime = now - m_lastFrameTime;
2190 if (frameTime < singleFrameTime)
2191 Sleep(singleFrameTime - frameTime);
2193 m_lastFrameTime = XbmcThreads::SystemClockMillis();
2196 g_graphicsContext.Flip(dirtyRegions);
2197 CTimeUtils::UpdateFrameTime(flip);
2199 g_renderManager.UpdateResolution();
2200 g_renderManager.ManageCaptures();
2203 void CApplication::SetStandAlone(bool value)
2205 g_advancedSettings.m_handleMounting = m_bStandalone = value;
2208 // OnKey() translates the key into a CAction which is sent on to our Window Manager.
2209 // The window manager will return true if the event is processed, false otherwise.
2210 // If not already processed, this routine handles global keypresses. It returns
2211 // true if the key has been processed, false otherwise.
2213 bool CApplication::OnKey(const CKey& key)
2216 // Turn the mouse off, as we've just got a keypress from controller or remote
2217 g_Mouse.SetActive(false);
2219 // get the current active window
2220 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2222 // this will be checked for certain keycodes that need
2223 // special handling if the screensaver is active
2224 CAction action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2226 // a key has been pressed.
2228 m_idleTimer.StartZero();
2229 bool processKey = AlwaysProcess(action);
2231 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState") || StringUtils::StartsWithNoCase(action.GetName(),"CECStandby"))
2235 CLog::Log(LOGDEBUG, "%s: action %s [%d], toggling state of playing device", __FUNCTION__, action.GetName().c_str(), action.GetID());
2236 // do not wake up the screensaver right after switching off the playing device
2237 if (StringUtils::StartsWithNoCase(action.GetName(),"CECToggleState"))
2238 ret = CApplicationMessenger::Get().CECToggleState();
2240 ret = CApplicationMessenger::Get().CECStandby();
2241 if (!ret) /* display is switched off */
2247 // allow some keys to be processed while the screensaver is active
2248 if (WakeUpScreenSaverAndDPMS(processKey) && !processKey)
2250 CLog::Log(LOGDEBUG, "%s: %s pressed, screen saver/dpms woken up", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str());
2254 // change this if we have a dialog up
2255 if (g_windowManager.HasModalDialog())
2257 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
2259 if (iWin == WINDOW_DIALOG_FULLSCREEN_INFO)
2260 { // fullscreen info dialog - special case
2261 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2263 if (!key.IsAnalogButton())
2264 CLog::Log(LOGDEBUG, "%s: %s pressed, trying fullscreen info action %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2266 if (OnAction(action))
2269 // fallthrough to the main window
2270 iWin = WINDOW_FULLSCREEN_VIDEO;
2272 if (iWin == WINDOW_FULLSCREEN_VIDEO)
2274 // current active window is full screen video.
2275 if (g_application.m_pPlayer->IsInMenu())
2277 // if player is in some sort of menu, (ie DVDMENU) map buttons differently
2278 action = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_MENU, key);
2280 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
2282 // check for PVR specific keymaps in FULLSCREEN_VIDEO window
2283 action = CButtonTranslator::GetInstance().GetAction(WINDOW_FULLSCREEN_LIVETV, key, false);
2285 // if no PVR specific action/mapping is found, fall back to default
2286 if (action.GetID() == 0)
2287 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2291 // in any other case use the fullscreen window section of keymap.xml to map key->action
2292 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2297 // current active window isnt the fullscreen window
2298 // just use corresponding section from keymap.xml
2299 // to map key->action
2301 // first determine if we should use keyboard input directly
2302 bool useKeyboard = key.FromKeyboard() && (iWin == WINDOW_DIALOG_KEYBOARD || iWin == WINDOW_DIALOG_NUMERIC);
2303 CGUIWindow *window = g_windowManager.GetWindow(iWin);
2306 CGUIControl *control = window->GetFocusedControl();
2309 // If this is an edit control set usekeyboard to true. This causes the
2310 // keypress to be processed directly not through the key mappings.
2311 if (control->GetControlType() == CGUIControl::GUICONTROL_EDIT)
2314 // If the key pressed is shift-A to shift-Z set usekeyboard to true.
2315 // This causes the keypress to be used for list navigation.
2316 if (control->IsContainer() && key.GetModifiers() == CKey::MODIFIER_SHIFT && key.GetVKey() >= XBMCVK_A && key.GetVKey() <= XBMCVK_Z)
2322 action = CAction(0); // reset our action
2323 if (CSettings::Get().GetBool("input.remoteaskeyboard"))
2325 // users remote is executing keyboard commands, so use the virtualkeyboard section of keymap.xml
2326 // and send those rather than actual keyboard presses. Only for navigation-type commands though
2327 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key);
2328 if (!(action.GetID() == ACTION_MOVE_LEFT ||
2329 action.GetID() == ACTION_MOVE_RIGHT ||
2330 action.GetID() == ACTION_MOVE_UP ||
2331 action.GetID() == ACTION_MOVE_DOWN ||
2332 action.GetID() == ACTION_SELECT_ITEM ||
2333 action.GetID() == ACTION_ENTER ||
2334 action.GetID() == ACTION_PREVIOUS_MENU ||
2335 action.GetID() == ACTION_NAV_BACK))
2337 // the action isn't plain navigation - check for a keyboard-specific keymap
2338 action = CButtonTranslator::GetInstance().GetAction(WINDOW_DIALOG_KEYBOARD, key, false);
2339 if (!(action.GetID() >= REMOTE_0 && action.GetID() <= REMOTE_9) ||
2340 action.GetID() == ACTION_BACKSPACE ||
2341 action.GetID() == ACTION_SHIFT ||
2342 action.GetID() == ACTION_SYMBOLS ||
2343 action.GetID() == ACTION_CURSOR_LEFT ||
2344 action.GetID() == ACTION_CURSOR_RIGHT)
2345 action = CAction(0); // don't bother with this action
2348 if (!action.GetID())
2350 // keyboard entry - pass the keys through directly
2351 if (key.GetFromService())
2352 action = CAction(key.GetButtonCode() != KEY_INVALID ? key.GetButtonCode() : 0, key.GetUnicode());
2355 // Check for paste keypress
2356 #ifdef TARGET_WINDOWS
2357 // In Windows paste is ctrl-V
2358 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2359 #elif defined(TARGET_LINUX)
2360 // In Linux paste is ctrl-V
2361 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_CTRL)
2362 #elif defined(TARGET_DARWIN_OSX)
2363 // In OSX paste is cmd-V
2364 if (key.GetVKey() == XBMCVK_V && key.GetModifiers() == CKey::MODIFIER_META)
2366 // Placeholder for other operating systems
2369 action = CAction(ACTION_PASTE);
2370 // If the unicode is non-zero the keypress is a non-printing character
2371 else if (key.GetUnicode())
2372 action = CAction(key.GetAscii() | KEY_ASCII, key.GetUnicode());
2373 // The keypress is a non-printing character
2375 action = CAction(key.GetVKey() | KEY_VKEY);
2379 CLog::Log(LOGDEBUG, "%s: %s pressed, trying keyboard action %x", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetID());
2381 if (OnAction(action))
2383 // failed to handle the keyboard action, drop down through to standard action
2385 if (key.GetFromService())
2387 if (key.GetButtonCode() != KEY_INVALID)
2388 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2391 action = CButtonTranslator::GetInstance().GetAction(iWin, key);
2393 if (!key.IsAnalogButton())
2394 CLog::Log(LOGDEBUG, "%s: %s pressed, action is %s", __FUNCTION__, g_Keyboard.GetKeyName((int) key.GetButtonCode()).c_str(), action.GetName().c_str());
2396 return ExecuteInputAction(action);
2399 // OnAppCommand is called in response to a XBMC_APPCOMMAND event.
2400 // This needs to return true if it processed the appcommand or false if it didn't
2401 bool CApplication::OnAppCommand(const CAction &action)
2403 // Reset the screen saver
2406 // If we were currently in the screen saver wake up and don't process the appcommand
2407 if (WakeUpScreenSaverAndDPMS())
2410 // The action ID is the APPCOMMAND code. We need to retrieve the action
2411 // associated with this appcommand from the mapping table.
2412 uint32_t appcmd = action.GetID();
2413 CKey key(appcmd | KEY_APPCOMMAND, (unsigned int) 0);
2414 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
2415 CAction appcmdaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2417 // If we couldn't find an action return false to indicate we have not
2418 // handled this appcommand
2419 if (!appcmdaction.GetID())
2421 CLog::Log(LOGDEBUG, "%s: unknown appcommand %d", __FUNCTION__, appcmd);
2425 // Process the appcommand
2426 CLog::Log(LOGDEBUG, "%s: appcommand %d, trying action %s", __FUNCTION__, appcmd, appcmdaction.GetName().c_str());
2427 OnAction(appcmdaction);
2429 // Always return true regardless of whether the action succeeded or not.
2430 // This stops Windows handling the appcommand itself.
2434 bool CApplication::OnAction(const CAction &action)
2436 // special case for switching between GUI & fullscreen mode.
2437 if (action.GetID() == ACTION_SHOW_GUI)
2438 { // Switch to fullscreen mode if we can
2439 if (SwitchToFullScreen())
2441 m_navigationTimer.StartZero();
2446 if (action.GetID() == ACTION_TOGGLE_FULLSCREEN)
2448 g_graphicsContext.ToggleFullScreenRoot();
2452 if (action.IsMouse())
2453 g_Mouse.SetActive(true);
2456 if (action.GetID() == ACTION_CREATE_EPISODE_BOOKMARK)
2458 CGUIDialogVideoBookmarks::OnAddEpisodeBookmark();
2460 if (action.GetID() == ACTION_CREATE_BOOKMARK)
2462 CGUIDialogVideoBookmarks::OnAddBookmark();
2465 // The action PLAYPAUSE behaves as ACTION_PAUSE if we are currently
2466 // playing or ACTION_PLAYER_PLAY if we are not playing.
2467 if (action.GetID() == ACTION_PLAYER_PLAYPAUSE)
2469 if (m_pPlayer->IsPlaying())
2470 return OnAction(CAction(ACTION_PAUSE));
2472 return OnAction(CAction(ACTION_PLAYER_PLAY));
2475 //if the action would start or stop inertial scrolling
2476 //by gesture - bypass the normal OnAction handler of current window
2477 if( !m_pInertialScrollingHandler->CheckForInertialScrolling(&action) )
2480 // just pass the action to the current window and let it handle it
2481 if (g_windowManager.OnAction(action))
2483 m_navigationTimer.StartZero();
2488 // handle extra global presses
2490 // screenshot : take a screenshot :)
2491 if (action.GetID() == ACTION_TAKE_SCREENSHOT)
2493 CScreenShot::TakeScreenshot();
2496 // built in functions : execute the built-in
2497 if (action.GetID() == ACTION_BUILT_IN_FUNCTION)
2499 CBuiltins::Execute(action.GetName());
2500 m_navigationTimer.StartZero();
2505 if (action.GetID() == ACTION_RELOAD_KEYMAPS)
2507 CButtonTranslator::GetInstance().Clear();
2508 CButtonTranslator::GetInstance().Load();
2511 // show info : Shows the current video or song information
2512 if (action.GetID() == ACTION_SHOW_INFO)
2514 g_infoManager.ToggleShowInfo();
2518 // codec info : Shows the current song, video or picture codec information
2519 if (action.GetID() == ACTION_SHOW_CODEC)
2521 g_infoManager.ToggleShowCodec();
2525 if ((action.GetID() == ACTION_INCREASE_RATING || action.GetID() == ACTION_DECREASE_RATING) && m_pPlayer->IsPlayingAudio())
2527 const CMusicInfoTag *tag = g_infoManager.GetCurrentSongTag();
2530 *m_itemCurrentFile->GetMusicInfoTag() = *tag;
2531 char rating = tag->GetRating();
2532 bool needsUpdate(false);
2533 if (rating > '0' && action.GetID() == ACTION_DECREASE_RATING)
2535 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating - 1);
2538 else if (rating < '5' && action.GetID() == ACTION_INCREASE_RATING)
2540 m_itemCurrentFile->GetMusicInfoTag()->SetRating(rating + 1);
2546 if (db.Open()) // OpenForWrite() ?
2548 db.SetSongRating(m_itemCurrentFile->GetPath(), m_itemCurrentFile->GetMusicInfoTag()->GetRating());
2551 // send a message to all windows to tell them to update the fileitem (eg playlistplayer, media windows)
2552 CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE_ITEM, 0, m_itemCurrentFile);
2553 g_windowManager.SendMessage(msg);
2559 // Now check with the playlist player if action can be handled.
2560 // 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.
2561 if (!(action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek() && GetTime() > 3) )
2563 if (g_playlistPlayer.OnAction(action))
2567 // Now check with the player if action can be handled.
2568 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
2569 (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)))
2571 if (m_pPlayer->OnAction(action))
2575 // stop : stops playing current audio song
2576 if (action.GetID() == ACTION_STOP)
2582 // In case the playlist player nor the player didn't handle PREV_ITEM, because we are past the 3 secs limit.
2583 // If so, we just jump to the start of the track.
2584 if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
2587 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2591 // forward action to g_PVRManager and break if it was able to handle it
2592 if (g_PVRManager.OnAction(action))
2595 // forward action to graphic context and see if it can handle it
2596 if (CStereoscopicsManager::Get().OnAction(action))
2599 if (m_pPlayer->IsPlaying())
2601 // forward channel switches to the player - he knows what to do
2602 if (action.GetID() == ACTION_CHANNEL_UP || action.GetID() == ACTION_CHANNEL_DOWN)
2604 m_pPlayer->OnAction(action);
2608 // pause : pauses current audio song
2609 if (action.GetID() == ACTION_PAUSE && m_pPlayer->GetPlaySpeed() == 1)
2613 m_pKaraokeMgr->SetPaused( m_pPlayer->IsPaused() );
2615 if (!m_pPlayer->IsPaused())
2616 { // unpaused - set the playspeed back to normal
2617 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2619 g_audioManager.Enable(m_pPlayer->IsPaused());
2622 if (!m_pPlayer->IsPaused())
2624 // if we do a FF/RW in my music then map PLAY action togo back to normal speed
2625 // if we are playing at normal speed, then allow play to pause
2626 if (action.GetID() == ACTION_PLAYER_PLAY || action.GetID() == ACTION_PAUSE)
2628 if (m_pPlayer->GetPlaySpeed() != 1)
2630 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2638 if (action.GetID() == ACTION_PLAYER_FORWARD || action.GetID() == ACTION_PLAYER_REWIND)
2640 int iPlaySpeed = m_pPlayer->GetPlaySpeed();
2641 if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed == 1) // Enables Rewinding
2643 else if (action.GetID() == ACTION_PLAYER_REWIND && iPlaySpeed > 1) //goes down a notch if you're FFing
2645 else if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed < 1) //goes up a notch if you're RWing
2650 if (action.GetID() == ACTION_PLAYER_FORWARD && iPlaySpeed == -1) //sets iSpeed back to 1 if -1 (didn't plan for a -1)
2652 if (iPlaySpeed > 32 || iPlaySpeed < -32)
2655 m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
2658 else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
2660 // calculate the speed based on the amount the button is held down
2661 int iPower = (int)(action.GetAmount() * MAX_FFWD_SPEED + 0.5f);
2662 // returns 0 -> MAX_FFWD_SPEED
2663 int iSpeed = 1 << iPower;
2664 if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
2666 g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
2668 CLog::Log(LOGDEBUG,"Resetting playspeed");
2672 // allow play to unpause
2675 if (action.GetID() == ACTION_PLAYER_PLAY)
2677 // unpause, and set the playspeed back to normal
2679 g_audioManager.Enable(m_pPlayer->IsPaused());
2681 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
2686 if (m_playerController->OnAction(action))
2691 if (action.GetID() == ACTION_SWITCH_PLAYER)
2693 if(m_pPlayer->IsPlaying())
2695 VECPLAYERCORES cores;
2696 CFileItem item(*m_itemCurrentFile.get());
2697 CPlayerCoreFactory::Get().GetPlayers(item, cores);
2698 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2699 if(core != EPC_NONE)
2701 g_application.m_eForcedNextPlayer = core;
2702 item.m_lStartOffset = (int)(GetTime() * 75);
2703 PlayFile(item, true);
2708 VECPLAYERCORES cores;
2709 CPlayerCoreFactory::Get().GetRemotePlayers(cores);
2710 PLAYERCOREID core = CPlayerCoreFactory::Get().SelectPlayerDialog(cores);
2711 if(core != EPC_NONE)
2714 g_application.m_eForcedNextPlayer = core;
2715 PlayFile(item, false);
2720 if (g_peripherals.OnAction(action))
2723 if (action.GetID() == ACTION_MUTE)
2729 if (action.GetID() == ACTION_TOGGLE_DIGITAL_ANALOG)
2732 // revisit after new audio settings page have been implemented
2733 // makes no sense toggling a mode when you have three different settings
2734 int mode = CSettings::Get().GetInt("audiooutput.mode");
2737 CSettings::Get().SetInt("audiooutput.mode", mode);
2739 if (g_windowManager.GetActiveWindow() == WINDOW_SETTINGS_SYSTEM)
2741 CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0,0,WINDOW_INVALID,g_windowManager.GetActiveWindow());
2742 g_windowManager.SendMessage(msg);
2747 // Check for global volume control
2748 if (action.GetAmount() && (action.GetID() == ACTION_VOLUME_UP || action.GetID() == ACTION_VOLUME_DOWN))
2750 if (!m_pPlayer->IsPassthrough())
2754 float volume = m_volumeLevel;
2755 // Android has steps based on the max available volume level
2756 #if defined(TARGET_ANDROID)
2757 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
2759 float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
2761 if (action.GetRepeat())
2762 step *= action.GetRepeat() * 50; // 50 fps
2764 if (action.GetID() == ACTION_VOLUME_UP)
2765 volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2767 volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2768 SetVolume(volume, false);
2770 // show visual feedback of volume change...
2771 ShowVolumeBar(&action);
2774 // Check for global seek control
2775 if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
2777 if (!m_pPlayer->CanSeek()) return false;
2778 m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
2781 if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
2783 CGUIControlProfiler::Instance().SetOutputFile(CSpecialProtocol::TranslatePath("special://home/guiprofiler.xml"));
2784 CGUIControlProfiler::Instance().Start();
2787 if (action.GetID() == ACTION_SHOW_PLAYLIST)
2789 int iPlaylist = g_playlistPlayer.GetCurrentPlaylist();
2790 if (iPlaylist == PLAYLIST_VIDEO && g_windowManager.GetActiveWindow() != WINDOW_VIDEO_PLAYLIST)
2791 g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
2792 else if (iPlaylist == PLAYLIST_MUSIC && g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST)
2793 g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
2799 void CApplication::FrameMove(bool processEvents, bool processGUI)
2805 // currently we calculate the repeat time (ie time from last similar keypress) just global as fps
2806 float frameTime = m_frameTime.GetElapsedSeconds();
2807 m_frameTime.StartZero();
2808 // never set a frametime less than 2 fps to avoid problems when debuggin and on breaks
2809 if( frameTime > 0.5 ) frameTime = 0.5;
2811 if (processGUI && m_renderGUI)
2813 g_graphicsContext.Lock();
2814 // check if there are notifications to display
2815 CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST);
2816 if (toast && toast->DoWork())
2818 if (!toast->IsDialogRunning())
2823 g_graphicsContext.Unlock();
2825 CWinEvents::MessagePump();
2827 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2828 // Read the input from a remote
2829 g_RemoteControl.Update();
2832 // process input actions
2833 ProcessRemote(frameTime);
2834 ProcessGamepad(frameTime);
2835 ProcessEventServer(frameTime);
2836 ProcessPeripherals(frameTime);
2837 if (processGUI && m_renderGUI)
2839 m_pInertialScrollingHandler->ProcessInertialScroll(frameTime);
2840 m_seekHandler->Process();
2843 if (processGUI && m_renderGUI)
2846 g_windowManager.Process(CTimeUtils::GetFrameTime());
2847 g_windowManager.FrameMove();
2851 bool CApplication::ProcessGamepad(float frameTime)
2853 #ifdef HAS_SDL_JOYSTICK
2857 int iWin = GetActiveWindowID();
2859 g_Joystick.Update();
2860 if (g_Joystick.GetButton(bid))
2863 m_idleTimer.StartZero();
2866 if (WakeUpScreenSaverAndDPMS())
2868 g_Joystick.Reset(true);
2873 CStdString actionName;
2875 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_BUTTON, actionID, actionName, fullrange))
2877 CAction action(actionID, 1.0f, 0.0f, actionName);
2879 g_Mouse.SetActive(false);
2880 return ExecuteInputAction(action);
2887 if (g_Joystick.GetAxis(bid))
2889 if (g_Joystick.GetAmount() < 0)
2895 CStdString actionName;
2897 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_AXIS, actionID, actionName, fullrange))
2900 if (WakeUpScreenSaverAndDPMS())
2905 CAction action(actionID, fullrange ? (g_Joystick.GetAmount() + 1.0f)/2.0f : fabs(g_Joystick.GetAmount()), 0.0f, actionName);
2907 g_Mouse.SetActive(false);
2908 return ExecuteInputAction(action);
2912 g_Joystick.ResetAxis(abs(bid));
2916 if (g_Joystick.GetHat(bid, position))
2919 m_idleTimer.StartZero();
2922 if (WakeUpScreenSaverAndDPMS())
2929 CStdString actionName;
2932 bid = position<<16|bid;
2934 if (bid && CButtonTranslator::GetInstance().TranslateJoystickString(iWin, g_Joystick.GetJoystick().c_str(), bid, JACTIVE_HAT, actionID, actionName, fullrange))
2936 CAction action(actionID, 1.0f, 0.0f, actionName);
2938 g_Mouse.SetActive(false);
2939 return ExecuteInputAction(action);
2946 bool CApplication::ProcessRemote(float frameTime)
2948 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
2949 if (g_RemoteControl.GetButton())
2951 CKey key(g_RemoteControl.GetButton(), g_RemoteControl.GetHoldTime());
2952 g_RemoteControl.Reset();
2959 bool CApplication::ProcessPeripherals(float frameTime)
2962 if (g_peripherals.GetNextKeypress(frameTime, key))
2967 bool CApplication::ProcessMouse()
2971 if (!g_Mouse.IsActive() || !m_AppFocused)
2974 // Get the mouse command ID
2975 uint32_t mousecommand = g_Mouse.GetAction();
2976 if (mousecommand == ACTION_NOOP)
2979 // Reset the screensaver and idle timers
2980 m_idleTimer.StartZero();
2982 if (WakeUpScreenSaverAndDPMS())
2985 // Retrieve the corresponding action
2986 int iWin = GetActiveWindowID();
2987 CKey key(mousecommand | KEY_MOUSE, (unsigned int) 0);
2988 CAction mouseaction = CButtonTranslator::GetInstance().GetAction(iWin, key);
2990 // Deactivate mouse if non-mouse action
2991 if (!mouseaction.IsMouse())
2992 g_Mouse.SetActive(false);
2994 // Consume ACTION_NOOP.
2995 // Some views or dialogs gets closed after any ACTION and
2996 // a sensitive mouse might cause problems.
2997 if (mouseaction.GetID() == ACTION_NOOP)
3000 // If we couldn't find an action return false to indicate we have not
3001 // handled this mouse action
3002 if (!mouseaction.GetID())
3004 CLog::Log(LOGDEBUG, "%s: unknown mouse command %d", __FUNCTION__, mousecommand);
3008 // Log mouse actions except for move and noop
3009 if (mouseaction.GetID() != ACTION_MOUSE_MOVE && mouseaction.GetID() != ACTION_NOOP)
3010 CLog::Log(LOGDEBUG, "%s: trying mouse action %s", __FUNCTION__, mouseaction.GetName().c_str());
3012 // The action might not be a mouse action. For example wheel moves might
3013 // be mapped to volume up/down in mouse.xml. In this case we do not want
3014 // the mouse position saved in the action.
3015 if (!mouseaction.IsMouse())
3016 return OnAction(mouseaction);
3018 // This is a mouse action so we need to record the mouse position
3019 return OnAction(CAction(mouseaction.GetID(),
3020 g_Mouse.GetHold(MOUSE_LEFT_BUTTON),
3021 (float)g_Mouse.GetX(),
3022 (float)g_Mouse.GetY(),
3023 (float)g_Mouse.GetDX(),
3024 (float)g_Mouse.GetDY(),
3025 mouseaction.GetName()));
3028 bool CApplication::ProcessEventServer(float frameTime)
3030 #ifdef HAS_EVENT_SERVER
3031 CEventServer* es = CEventServer::GetInstance();
3032 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3035 // process any queued up actions
3036 if (es->ExecuteNextAction())
3038 // reset idle timers
3039 m_idleTimer.StartZero();
3041 WakeUpScreenSaverAndDPMS();
3044 // now handle any buttons or axis
3045 std::string joystickName;
3046 bool isAxis = false;
3047 float fAmount = 0.0;
3049 // es->ExecuteNextAction() invalidates the ref to the CEventServer instance
3050 // when the action exits XBMC
3051 es = CEventServer::GetInstance();
3052 if (!es || !es->Running() || es->GetNumberOfClients()==0)
3054 unsigned int wKeyID = es->GetButtonCode(joystickName, isAxis, fAmount);
3058 if (joystickName.length() > 0)
3062 if (fabs(fAmount) >= 0.08)
3063 m_lastAxisMap[joystickName][wKeyID] = fAmount;
3065 m_lastAxisMap[joystickName].erase(wKeyID);
3068 return ProcessJoystickEvent(joystickName, wKeyID, isAxis, fAmount);
3073 if (wKeyID & ES_FLAG_UNICODE)
3075 key = CKey((uint8_t)0, wKeyID & ~ES_FLAG_UNICODE, 0, 0, 0);
3079 if(wKeyID == KEY_BUTTON_LEFT_ANALOG_TRIGGER)
3080 key = CKey(wKeyID, (BYTE)(255*fAmount), 0, 0.0, 0.0, 0.0, 0.0, frameTime);
3081 else if(wKeyID == KEY_BUTTON_RIGHT_ANALOG_TRIGGER)
3082 key = CKey(wKeyID, 0, (BYTE)(255*fAmount), 0.0, 0.0, 0.0, 0.0, frameTime);
3083 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_LEFT)
3084 key = CKey(wKeyID, 0, 0, -fAmount, 0.0, 0.0, 0.0, frameTime);
3085 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_RIGHT)
3086 key = CKey(wKeyID, 0, 0, fAmount, 0.0, 0.0, 0.0, frameTime);
3087 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_UP)
3088 key = CKey(wKeyID, 0, 0, 0.0, fAmount, 0.0, 0.0, frameTime);
3089 else if(wKeyID == KEY_BUTTON_LEFT_THUMB_STICK_DOWN)
3090 key = CKey(wKeyID, 0, 0, 0.0, -fAmount, 0.0, 0.0, frameTime);
3091 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_LEFT)
3092 key = CKey(wKeyID, 0, 0, 0.0, 0.0, -fAmount, 0.0, frameTime);
3093 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_RIGHT)
3094 key = CKey(wKeyID, 0, 0, 0.0, 0.0, fAmount, 0.0, frameTime);
3095 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_UP)
3096 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, fAmount, frameTime);
3097 else if(wKeyID == KEY_BUTTON_RIGHT_THUMB_STICK_DOWN)
3098 key = CKey(wKeyID, 0, 0, 0.0, 0.0, 0.0, -fAmount, frameTime);
3101 key.SetFromService(true);
3106 if (m_lastAxisMap.size() > 0)
3108 // Process all the stored axis.
3109 for (map<std::string, map<int, float> >::iterator iter = m_lastAxisMap.begin(); iter != m_lastAxisMap.end(); ++iter)
3111 for (map<int, float>::iterator iterAxis = (*iter).second.begin(); iterAxis != (*iter).second.end(); ++iterAxis)
3112 ProcessJoystickEvent((*iter).first, (*iterAxis).first, true, (*iterAxis).second);
3118 if (es->GetMousePos(pos.x, pos.y) && g_Mouse.IsEnabled())
3119 return OnAction(CAction(ACTION_MOUSE_MOVE, pos.x, pos.y));
3125 bool CApplication::ProcessJoystickEvent(const std::string& joystickName, int wKeyID, bool isAxis, float fAmount, unsigned int holdTime /*=0*/)
3127 #if defined(HAS_EVENT_SERVER)
3128 m_idleTimer.StartZero();
3130 // Make sure to reset screen saver, mouse.
3132 if (WakeUpScreenSaverAndDPMS())
3135 #ifdef HAS_SDL_JOYSTICK
3138 g_Mouse.SetActive(false);
3140 int iWin = GetActiveWindowID();
3142 CStdString actionName;
3143 bool fullRange = false;
3145 // Translate using regular joystick translator.
3146 if (CButtonTranslator::GetInstance().TranslateJoystickString(iWin, joystickName.c_str(), wKeyID, isAxis ? JACTIVE_AXIS : JACTIVE_BUTTON, actionID, actionName, fullRange))
3147 return ExecuteInputAction( CAction(actionID, fAmount, 0.0f, actionName, holdTime) );
3149 CLog::Log(LOGDEBUG, "ERROR mapping joystick action. Joystick: %s %i",joystickName.c_str(), wKeyID);
3155 bool CApplication::ExecuteInputAction(const CAction &action)
3157 bool bResult = false;
3159 // play sound before the action unless the button is held,
3160 // where we execute after the action as held actions aren't fired every time.
3161 if(action.GetHoldTime())
3163 bResult = OnAction(action);
3165 g_audioManager.PlayActionSound(action);
3169 g_audioManager.PlayActionSound(action);
3170 bResult = OnAction(action);
3175 int CApplication::GetActiveWindowID(void)
3177 // Get the currently active window
3178 int iWin = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
3180 // If there is a dialog active get the dialog id instead
3181 if (g_windowManager.HasModalDialog())
3182 iWin = g_windowManager.GetTopMostModalDialogID() & WINDOW_ID_MASK;
3184 // If the window is FullScreenVideo check for special cases
3185 if (iWin == WINDOW_FULLSCREEN_VIDEO)
3187 // check if we're in a DVD menu
3188 if(g_application.m_pPlayer->IsInMenu())
3189 iWin = WINDOW_VIDEO_MENU;
3190 // check for LiveTV and switch to it's virtual window
3191 else if (g_PVRManager.IsStarted() && g_application.CurrentFileItem().HasPVRChannelInfoTag())
3192 iWin = WINDOW_FULLSCREEN_LIVETV;
3195 // Return the window id
3199 bool CApplication::Cleanup()
3203 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST);
3204 g_windowManager.Delete(WINDOW_MUSIC_PLAYLIST_EDITOR);
3205 g_windowManager.Delete(WINDOW_MUSIC_FILES);
3206 g_windowManager.Delete(WINDOW_MUSIC_NAV);
3207 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_INFO);
3208 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_INFO);
3209 g_windowManager.Delete(WINDOW_VIDEO_FILES);
3210 g_windowManager.Delete(WINDOW_VIDEO_PLAYLIST);
3211 g_windowManager.Delete(WINDOW_VIDEO_NAV);
3212 g_windowManager.Delete(WINDOW_FILES);
3213 g_windowManager.Delete(WINDOW_DIALOG_YES_NO);
3214 g_windowManager.Delete(WINDOW_DIALOG_PROGRESS);
3215 g_windowManager.Delete(WINDOW_DIALOG_NUMERIC);
3216 g_windowManager.Delete(WINDOW_DIALOG_GAMEPAD);
3217 g_windowManager.Delete(WINDOW_DIALOG_SUB_MENU);
3218 g_windowManager.Delete(WINDOW_DIALOG_BUTTON_MENU);
3219 g_windowManager.Delete(WINDOW_DIALOG_CONTEXT_MENU);
3220 g_windowManager.Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
3221 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
3222 g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
3223 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
3224 g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
3225 g_windowManager.Delete(WINDOW_DIALOG_SELECT);
3226 g_windowManager.Delete(WINDOW_DIALOG_OK);
3227 g_windowManager.Delete(WINDOW_DIALOG_FILESTACKING);
3228 g_windowManager.Delete(WINDOW_DIALOG_KEYBOARD);
3229 g_windowManager.Delete(WINDOW_FULLSCREEN_VIDEO);
3230 g_windowManager.Delete(WINDOW_DIALOG_PROFILE_SETTINGS);
3231 g_windowManager.Delete(WINDOW_DIALOG_LOCK_SETTINGS);
3232 g_windowManager.Delete(WINDOW_DIALOG_NETWORK_SETUP);
3233 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_SOURCE);
3234 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
3235 g_windowManager.Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
3236 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
3237 g_windowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS);
3238 g_windowManager.Delete(WINDOW_DIALOG_FAVOURITES);
3239 g_windowManager.Delete(WINDOW_DIALOG_SONG_INFO);
3240 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
3241 g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
3242 g_windowManager.Delete(WINDOW_DIALOG_BUSY);
3243 g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
3244 g_windowManager.Delete(WINDOW_DIALOG_ADDON_INFO);
3245 g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
3246 g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
3247 g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
3248 g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
3250 /* Delete PVR related windows and dialogs */
3251 g_windowManager.Delete(WINDOW_PVR);
3252 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO);
3253 g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO);
3254 g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING);
3255 g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER);
3256 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER);
3257 g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH);
3258 g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN);
3259 g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS);
3260 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS);
3261 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE);
3262 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
3263 g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER);
3264 g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT);
3266 g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER);
3267 g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT);
3268 g_windowManager.Delete(WINDOW_STARTUP_ANIM);
3269 g_windowManager.Delete(WINDOW_LOGIN_SCREEN);
3270 g_windowManager.Delete(WINDOW_VISUALISATION);
3271 g_windowManager.Delete(WINDOW_KARAOKELYRICS);
3272 g_windowManager.Delete(WINDOW_SETTINGS_MENU);
3273 g_windowManager.Delete(WINDOW_SETTINGS_PROFILES);
3274 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES); // all the settings categories
3275 g_windowManager.Delete(WINDOW_TEST_PATTERN);
3276 g_windowManager.Delete(WINDOW_SCREEN_CALIBRATION);
3277 g_windowManager.Delete(WINDOW_SYSTEM_INFORMATION);
3278 g_windowManager.Delete(WINDOW_SCREENSAVER);
3279 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OSD);
3280 g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY);
3281 g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY);
3282 g_windowManager.Delete(WINDOW_SLIDESHOW);
3283 g_windowManager.Delete(WINDOW_ADDON_BROWSER);
3284 g_windowManager.Delete(WINDOW_SKIN_SETTINGS);
3286 g_windowManager.Delete(WINDOW_HOME);
3287 g_windowManager.Delete(WINDOW_PROGRAMS);
3288 g_windowManager.Delete(WINDOW_PICTURES);
3289 g_windowManager.Delete(WINDOW_WEATHER);
3291 g_windowManager.Delete(WINDOW_SETTINGS_MYPICTURES);
3292 g_windowManager.Remove(WINDOW_SETTINGS_MYPROGRAMS);
3293 g_windowManager.Remove(WINDOW_SETTINGS_MYWEATHER);
3294 g_windowManager.Remove(WINDOW_SETTINGS_MYMUSIC);
3295 g_windowManager.Remove(WINDOW_SETTINGS_SYSTEM);
3296 g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS);
3297 g_windowManager.Remove(WINDOW_SETTINGS_SERVICE);
3298 g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE);
3299 g_windowManager.Remove(WINDOW_SETTINGS_MYPVR);
3300 g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST);
3302 g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR);
3303 g_windowManager.Remove(WINDOW_DIALOG_VOLUME_BAR);
3305 CAddonMgr::Get().DeInit();
3307 #if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
3308 CLog::Log(LOGNOTICE, "closing down remote control service");
3309 g_RemoteControl.Disconnect();
3312 CLog::Log(LOGNOTICE, "unload sections");
3314 #ifdef HAS_PERFORMANCE_SAMPLE
3315 CLog::Log(LOGNOTICE, "performance statistics");
3316 m_perfStats.DumpStats();
3319 // Shutdown as much as possible of the
3320 // application, to reduce the leaks dumped
3321 // to the vc output window before calling
3322 // _CrtDumpMemoryLeaks(). Most of the leaks
3323 // shown are no real leaks, as parts of the app
3324 // are still allocated.
3326 g_localizeStrings.Clear();
3327 g_LangCodeExpander.Clear();
3328 g_charsetConverter.clear();
3329 g_directoryCache.Clear();
3330 CButtonTranslator::GetInstance().Clear();
3331 #ifdef HAS_EVENT_SERVER
3332 CEventServer::RemoveInstance();
3334 DllLoaderContainer::Clear();
3335 g_playlistPlayer.Clear();
3336 CSettings::Get().Uninitialize();
3337 g_advancedSettings.Clear();
3340 CXHandle::DumpObjectTracker();
3342 #ifdef HAS_DVD_DRIVE
3343 CLibcdio::ReleaseInstance();
3346 #if defined(TARGET_ANDROID)
3347 // enable for all platforms once it's safe
3348 g_sectionLoader.UnloadAll();
3350 #ifdef _CRTDBG_MAP_ALLOC
3351 _CrtDumpMemoryLeaks();
3352 while(1); // execution ends
3362 CLog::Log(LOGERROR, "Exception in CApplication::Cleanup()");
3367 void CApplication::Stop(int exitCode)
3371 CVariant vExitCode(exitCode);
3372 CAnnouncementManager::Announce(System, "xbmc", "OnQuit", vExitCode);
3374 SaveFileState(true);
3376 g_alarmClock.StopThread();
3378 if( m_bSystemScreenSaverEnable )
3379 g_Windowing.EnableSystemScreenSaver(true);
3381 CLog::Log(LOGNOTICE, "Storing total System Uptime");
3382 g_sysinfo.SetTotalUptime(g_sysinfo.GetTotalUptime() + (int)(CTimeUtils::GetFrameTime() / 60000));
3384 // Update the settings information (volume, uptime etc. need saving)
3385 if (CFile::Exists(CProfilesManager::Get().GetSettingsFile()))
3387 CLog::Log(LOGNOTICE, "Saving settings");
3388 CSettings::Get().Save();
3391 CLog::Log(LOGNOTICE, "Not saving settings (settings.xml is not present)");
3394 m_AppFocused = false;
3395 m_ExitCode = exitCode;
3396 CLog::Log(LOGNOTICE, "stop all");
3398 // cancel any jobs from the jobmanager
3399 CJobManager::GetInstance().CancelJobs();
3401 // stop scanning before we kill the network and so on
3402 if (m_musicInfoScanner->IsScanning())
3403 m_musicInfoScanner->Stop();
3405 if (m_videoInfoScanner->IsScanning())
3406 m_videoInfoScanner->Stop();
3408 CApplicationMessenger::Get().Cleanup();
3414 CLog::Log(LOGNOTICE, "stop player");
3415 m_pPlayer->ClosePlayer();
3417 #if HAS_FILESYTEM_DAAP
3418 CLog::Log(LOGNOTICE, "stop daap clients");
3419 g_DaapClient.Release();
3421 #ifdef HAS_FILESYSTEM_SAP
3422 CLog::Log(LOGNOTICE, "stop sap announcement listener");
3423 g_sapsessions.StopThread();
3426 if(CZeroconfBrowser::IsInstantiated())
3428 CLog::Log(LOGNOTICE, "stop zeroconf browser");
3429 CZeroconfBrowser::GetInstance()->Stop();
3430 CZeroconfBrowser::ReleaseInstance();
3434 CLog::Log(LOGNOTICE, "clean cached files!");
3435 #ifdef HAS_FILESYSTEM_RAR
3436 g_RarManager.ClearCache(true);
3439 #ifdef HAS_FILESYSTEM_SFTP
3440 CSFTPSessionManager::DisconnectAllSessions();
3443 CLog::Log(LOGNOTICE, "unload skin");
3446 #if defined(TARGET_DARWIN_OSX)
3447 if (XBMCHelper::GetInstance().IsAlwaysOn() == false)
3448 XBMCHelper::GetInstance().Stop();
3451 #if defined(HAVE_LIBCRYSTALHD)
3452 CCrystalHD::RemoveInstance();
3455 g_mediaManager.Stop();
3457 // Stop services before unloading Python
3458 CAddonMgr::Get().StopServices(false);
3460 // stop all remaining scripts; must be done after skin has been unloaded,
3461 // not before some windows still need it when deinitializing during skin
3463 CScriptInvocationManager::Get().Uninitialize();
3465 g_Windowing.DestroyRenderSystem();
3466 g_Windowing.DestroyWindow();
3467 g_Windowing.DestroyWindowSystem();
3469 // shutdown the AudioEngine
3470 CAEFactory::Shutdown();
3471 CAEFactory::UnLoadEngine();
3473 CLog::Log(LOGNOTICE, "stopped");
3477 CLog::Log(LOGERROR, "Exception in CApplication::Stop()");
3480 // we may not get to finish the run cycle but exit immediately after a call to g_application.Stop()
3481 // so we may never get to Destroy() in CXBApplicationEx::Run(), we call it here.
3488 bool CApplication::PlayMedia(const CFileItem& item, int iPlaylist)
3490 //If item is a plugin, expand out now and run ourselves again
3491 if (item.IsPlugin())
3493 CFileItem item_new(item);
3494 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3495 return PlayMedia(item_new, iPlaylist);
3498 if (item.IsSmartPlayList())
3500 CFileItemList items;
3501 CUtil::GetRecursiveListing(item.GetPath(), items, "");
3504 CSmartPlaylist smartpl;
3505 //get name and type of smartplaylist, this will always succeed as GetDirectory also did this.
3506 smartpl.OpenAndReadName(item.GetPath());
3508 playlist.Add(items);
3509 return ProcessAndStartPlaylist(smartpl.GetName(), playlist, (smartpl.GetType() == "songs" || smartpl.GetType() == "albums") ? PLAYLIST_MUSIC:PLAYLIST_VIDEO);
3512 else if (item.IsPlayList() || item.IsInternetStream())
3514 CGUIDialogCache* dlgCache = new CGUIDialogCache(5000, g_localizeStrings.Get(10214), item.GetLabel());
3516 //is or could be a playlist
3517 auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(item));
3518 bool gotPlayList = (pPlayList.get() && pPlayList->Load(item.GetPath()));
3523 if (dlgCache->IsCanceled())
3530 if (iPlaylist != PLAYLIST_NONE)
3533 if (item.HasProperty("playlist_starting_track"))
3534 track = (int)item.GetProperty("playlist_starting_track").asInteger();
3535 return ProcessAndStartPlaylist(item.GetPath(), *pPlayList, iPlaylist, track);
3539 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());
3540 if(pPlayList->size())
3541 return PlayFile(*(*pPlayList)[0], false) == PLAYBACK_OK;
3546 //nothing special just play
3547 return PlayFile(item, false) == PLAYBACK_OK;
3551 // For playing a multi-file video. Particularly inefficient
3552 // on startup, as we are required to calculate the length
3553 // of each video, so we open + close each one in turn.
3554 // A faster calculation of video time would improve this
3556 // return value: same with PlayFile()
3557 PlayBackRet CApplication::PlayStack(const CFileItem& item, bool bRestart)
3559 if (!item.IsStack())
3560 return PLAYBACK_FAIL;
3564 // case 1: stacked ISOs
3565 if (CFileItem(CStackDirectory::GetFirstStackedFile(item.GetPath()),false).IsDVDImage())
3567 CStackDirectory dir;
3568 CFileItemList movieList;
3569 dir.GetDirectory(item.GetPath(), movieList);
3571 // first assume values passed to the stack
3572 int selectedFile = item.m_lStartPartNumber;
3573 int startoffset = item.m_lStartOffset;
3575 // check if we instructed the stack to resume from default
3576 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3581 if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
3583 startoffset = (int)(bookmark.timeInSeconds*75);
3584 selectedFile = bookmark.partNumber;
3589 CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3592 // make sure that the selected part is within the boundaries
3593 if (selectedFile <= 0)
3595 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part 1", __FUNCTION__, selectedFile);
3598 else if (selectedFile > movieList.Size())
3600 CLog::Log(LOGWARNING, "%s - Selected part %d out of range, playing part %d", __FUNCTION__, selectedFile, movieList.Size());
3601 selectedFile = movieList.Size();
3604 // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3605 movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
3606 movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
3607 *m_stackFileItemToUpdate = item;
3608 return PlayFile(*(movieList[selectedFile - 1]));
3610 // case 2: all other stacks
3613 // see if we have the info in the database
3614 // TODO: If user changes the time speed (FPS via framerate conversion stuff)
3615 // then these times will be wrong.
3616 // Also, this is really just a hack for the slow load up times we have
3617 // A much better solution is a fast reader of FPS and fileLength
3618 // that we can use on a file to get it's time.
3620 bool haveTimes(false);
3624 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3625 haveTimes = dbs.GetStackTimes(item.GetPath(), times);
3630 // calculate the total time of the stack
3631 CStackDirectory dir;
3632 dir.GetDirectory(item.GetPath(), *m_currentStack);
3634 for (int i = 0; i < m_currentStack->Size(); i++)
3637 (*m_currentStack)[i]->m_lEndOffset = times[i];
3641 if (!CDVDFileInfo::GetFileDuration((*m_currentStack)[i]->GetPath(), duration))
3643 m_currentStack->Clear();
3644 return PLAYBACK_FAIL;
3646 totalTime += duration / 1000;
3647 (*m_currentStack)[i]->m_lEndOffset = totalTime;
3648 times.push_back(totalTime);
3652 double seconds = item.m_lStartOffset / 75.0;
3654 if (!haveTimes || item.m_lStartOffset == STARTOFFSET_RESUME )
3655 { // have our times now, so update the dB
3659 dbs.SetStackTimes(item.GetPath(), times);
3661 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3663 // can only resume seek here, not dvdstate
3665 if( dbs.GetResumeBookMark(item.GetPath(), bookmark) )
3666 seconds = bookmark.timeInSeconds;
3674 *m_itemCurrentFile = item;
3675 m_currentStackPosition = 0;
3676 m_pPlayer->ResetPlayer(); // must be reset on initial play otherwise last player will be used
3680 // work out where to seek to
3681 for (int i = 0; i < m_currentStack->Size(); i++)
3683 if (seconds < (*m_currentStack)[i]->m_lEndOffset)
3685 CFileItem item(*(*m_currentStack)[i]);
3686 long start = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
3687 item.m_lStartOffset = (long)(seconds - start) * 75;
3688 m_currentStackPosition = i;
3689 return PlayFile(item, true);
3694 return PlayFile(*(*m_currentStack)[0], true);
3696 return PLAYBACK_FAIL;
3699 PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
3701 // Ensure the MIME type has been retrieved for http:// and shout:// streams
3702 if (item.GetMimeType().empty())
3703 const_cast<CFileItem&>(item).FillInMimeType();
3707 SaveCurrentFileSettings();
3709 OutputDebugString("new file set audiostream:0\n");
3710 // Switch to default options
3711 CMediaSettings::Get().GetCurrentVideoSettings() = CMediaSettings::Get().GetDefaultVideoSettings();
3712 // see if we have saved options in the database
3714 m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
3715 m_pPlayer->m_iPlaySpeed = 1; // Reset both CApp's & Player's speed else we'll get confused
3717 *m_itemCurrentFile = item;
3718 m_nextPlaylistItem = -1;
3719 m_currentStackPosition = 0;
3720 m_currentStack->Clear();
3723 CUtil::ClearSubtitles();
3726 if (item.IsDiscStub())
3728 #ifdef HAS_DVD_DRIVE
3729 // Display the Play Eject dialog if there is any optical disc drive
3730 if (g_mediaManager.HasOpticalDrive())
3732 if (CGUIDialogPlayEject::ShowAndGetInput(item))
3733 // PlayDiscAskResume takes path to disc. No parameter means default DVD drive.
3734 // Can't do better as CGUIDialogPlayEject calls CMediaManager::IsDiscInDrive, which assumes default DVD drive anyway
3735 return MEDIA_DETECT::CAutorun::PlayDiscAskResume() ? PLAYBACK_OK : PLAYBACK_FAIL;
3739 CGUIDialogOK::ShowAndGetInput(435, 0, 436, 0);
3744 if (item.IsPlayList())
3745 return PLAYBACK_FAIL;
3747 if (item.IsPlugin())
3748 { // we modify the item so that it becomes a real URL
3749 CFileItem item_new(item);
3750 if (XFILE::CPluginDirectory::GetPluginResult(item.GetPath(), item_new))
3751 return PlayFile(item_new, false);
3752 return PLAYBACK_FAIL;
3756 if (URIUtils::IsUPnP(item.GetPath()))
3758 CFileItem item_new(item);
3759 if (XFILE::CUPnPDirectory::GetResource(item.GetPath(), item_new))
3760 return PlayFile(item_new, false);
3761 return PLAYBACK_FAIL;
3765 // if we have a stacked set of files, we need to setup our stack routines for
3766 // "seamless" seeking and total time of the movie etc.
3767 // will recall with restart set to true
3769 return PlayStack(item, bRestart);
3771 //Is TuxBox, this should probably be moved to CTuxBoxFile
3774 CLog::Log(LOGDEBUG, "%s - TuxBox URL Detected %s",__FUNCTION__, item.GetPath().c_str());
3776 if(g_tuxboxService.IsRunning())
3777 g_tuxboxService.Stop();
3779 PlayBackRet ret = PLAYBACK_FAIL;
3781 if(g_tuxbox.CreateNewItem(item, item_new))
3784 // Make sure it doesn't have a player
3785 // so we actually select one normally
3786 m_pPlayer->ResetPlayer();
3788 // keep the tuxbox:// url as playing url
3789 // and give the new url to the player
3790 ret = PlayFile(item_new, true);
3791 if(ret == PLAYBACK_OK)
3793 if(!g_tuxboxService.IsRunning())
3794 g_tuxboxService.Start();
3800 CPlayerOptions options;
3802 if( item.HasProperty("StartPercent") )
3804 double fallback = 0.0f;
3805 if(item.GetProperty("StartPercent").isString())
3806 fallback = (double)atof(item.GetProperty("StartPercent").asString().c_str());
3807 options.startpercent = item.GetProperty("StartPercent").asDouble(fallback);
3810 PLAYERCOREID eNewCore = EPC_NONE;
3813 // have to be set here due to playstack using this for starting the file
3814 options.starttime = item.m_lStartOffset / 75.0;
3815 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_itemCurrentFile->m_lStartOffset != 0)
3816 m_itemCurrentFile->m_lStartOffset = STARTOFFSET_RESUME; // to force fullscreen switching
3818 if( m_eForcedNextPlayer != EPC_NONE )
3819 eNewCore = m_eForcedNextPlayer;
3820 else if( m_pPlayer->GetCurrentPlayer() == EPC_NONE )
3821 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3823 eNewCore = m_pPlayer->GetCurrentPlayer();
3827 options.starttime = item.m_lStartOffset / 75.0;
3831 // open the d/b and retrieve the bookmarks for the current movie
3834 dbs.GetVideoSettings(item.GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
3836 if( item.m_lStartOffset == STARTOFFSET_RESUME )
3838 options.starttime = 0.0f;
3840 CStdString path = item.GetPath();
3841 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_strFileNameAndPath.Find("removable://") == 0)
3842 path = item.GetVideoInfoTag()->m_strFileNameAndPath;
3843 else if (item.HasProperty("original_listitem_url") && URIUtils::IsPlugin(item.GetProperty("original_listitem_url").asString()))
3844 path = item.GetProperty("original_listitem_url").asString();
3845 if(dbs.GetResumeBookMark(path, bookmark))
3847 options.starttime = bookmark.timeInSeconds;
3848 options.state = bookmark.playerState;
3851 override with information from the actual item if available. We do this as the VFS (eg plugins)
3852 may set the resume point to override whatever XBMC has stored, yet we ignore it until now so that,
3853 should the playerState be required, it is fetched from the database.
3854 See the note in CGUIWindowVideoBase::ShowResumeMenu.
3856 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
3857 options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
3859 else if (item.HasVideoInfoTag())
3861 const CVideoInfoTag *tag = item.GetVideoInfoTag();
3863 if (tag->m_iBookmarkId != -1 && tag->m_iBookmarkId != 0)
3866 dbs.GetBookMarkForEpisode(*tag, bookmark);
3867 options.starttime = bookmark.timeInSeconds;
3868 options.state = bookmark.playerState;
3875 if (m_eForcedNextPlayer != EPC_NONE)
3876 eNewCore = m_eForcedNextPlayer;
3878 eNewCore = CPlayerCoreFactory::Get().GetDefaultPlayer(item);
3881 // this really aught to be inside !bRestart, but since PlayStack
3882 // uses that to init playback, we have to keep it outside
3883 int playlist = g_playlistPlayer.GetCurrentPlaylist();
3884 if (item.IsVideo() && g_playlistPlayer.GetPlaylist(playlist).size() > 1)
3885 { // playing from a playlist by the looks
3886 // don't switch to fullscreen if we are not playing the first item...
3887 options.fullscreen = !g_playlistPlayer.HasPlayedFirstFile() && g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3889 else if(m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
3891 // TODO - this will fail if user seeks back to first file in stack
3892 if(m_currentStackPosition == 0 || m_itemCurrentFile->m_lStartOffset == STARTOFFSET_RESUME)
3893 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3895 options.fullscreen = false;
3896 // reset this so we don't think we are resuming on seek
3897 m_itemCurrentFile->m_lStartOffset = 0;
3900 options.fullscreen = g_advancedSettings.m_fullScreenOnMovieStart && !CMediaSettings::Get().DoesVideoStartWindowed();
3902 // reset VideoStartWindowed as it's a temp setting
3903 CMediaSettings::Get().SetVideoStartWindowed(false);
3906 //We have to stop parsing a cdg before mplayer is deallocated
3907 // WHY do we have to do this????
3909 m_pKaraokeMgr->Stop();
3913 CSingleLock lock(m_playStateMutex);
3914 // tell system we are starting a file
3915 m_bPlaybackStarting = true;
3917 // for playing a new item, previous playing item's callback may already
3918 // pushed some delay message into the threadmessage list, they are not
3919 // expected be processed after or during the new item playback starting.
3920 // so we clean up previous playing item's playback callback delay messages here.
3921 int previousMsgsIgnoredByNewPlaying[] = {
3922 GUI_MSG_PLAYBACK_STARTED,
3923 GUI_MSG_PLAYBACK_ENDED,
3924 GUI_MSG_PLAYBACK_STOPPED,
3925 GUI_MSG_PLAYLIST_CHANGED,
3926 GUI_MSG_PLAYLISTPLAYER_STOPPED,
3927 GUI_MSG_PLAYLISTPLAYER_STARTED,
3928 GUI_MSG_PLAYLISTPLAYER_CHANGED,
3929 GUI_MSG_QUEUE_NEXT_ITEM,
3932 int dMsgCount = g_windowManager.RemoveThreadMessageByMessageIds(&previousMsgsIgnoredByNewPlaying[0]);
3934 CLog::Log(LOGDEBUG,"%s : Ignored %d playback thread messages", __FUNCTION__, dMsgCount);
3937 // We should restart the player, unless the previous and next tracks are using
3938 // one of the players that allows gapless playback (paplayer, dvdplayer)
3939 m_pPlayer->ClosePlayerGapless(eNewCore);
3941 // now reset play state to starting, since we already stopped the previous playing item if there is.
3942 // and from now there should be no playback callback from previous playing item be called.
3943 m_ePlayState = PLAY_STATE_STARTING;
3945 m_pPlayer->CreatePlayer(eNewCore, *this);
3947 PlayBackRet iResult;
3948 if (m_pPlayer->HasPlayer())
3950 /* When playing video pause any low priority jobs, they will be unpaused when playback stops.
3951 * This should speed up player startup for files on internet filesystems (eg. webdav) and
3952 * increase performance on low powered systems (Atom/ARM).
3956 CJobManager::GetInstance().Pause(CJob::PRIORITY_LOW); // Pause any low priority jobs
3959 // don't hold graphicscontext here since player
3960 // may wait on another thread, that requires gfx
3961 CSingleExit ex(g_graphicsContext);
3963 iResult = m_pPlayer->OpenFile(item, options);
3967 CLog::Log(LOGERROR, "Error creating player for item %s (File doesn't exist?)", item.GetPath().c_str());
3968 iResult = PLAYBACK_FAIL;
3971 if(iResult == PLAYBACK_OK)
3973 if (m_pPlayer->GetPlaySpeed() != 1)
3975 int iSpeed = m_pPlayer->GetPlaySpeed();
3976 m_pPlayer->m_iPlaySpeed = 1;
3977 m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
3980 // if player has volume control, set it.
3981 if (m_pPlayer->ControlsVolume())
3983 m_pPlayer->SetVolume(m_volumeLevel);
3984 m_pPlayer->SetMute(m_muted);
3987 if( m_pPlayer->IsPlayingAudio() )
3989 if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
3990 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
3993 #ifdef HAS_VIDEO_PLAYBACK
3994 else if( m_pPlayer->IsPlayingVideo() )
3996 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
3997 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
3999 // if player didn't manange to switch to fullscreen by itself do it here
4000 if( options.fullscreen && g_renderManager.IsStarted()
4001 && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO )
4002 SwitchToFullScreen();
4007 if (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4008 || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4009 g_windowManager.PreviousWindow();
4013 #if !defined(TARGET_POSIX)
4014 g_audioManager.Enable(false);
4017 if (item.HasPVRChannelInfoTag())
4018 g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
4021 CSingleLock lock(m_playStateMutex);
4022 m_bPlaybackStarting = false;
4024 if (iResult == PLAYBACK_OK)
4026 // play state: none, starting; playing; stopped; ended.
4027 // last 3 states are set by playback callback, they are all ignored during starting,
4028 // but we recorded the state, here we can make up the callback for the state.
4029 CLog::Log(LOGDEBUG,"%s : OpenFile succeed, play state %d", __FUNCTION__, m_ePlayState);
4030 switch (m_ePlayState)
4032 case PLAY_STATE_PLAYING:
4033 OnPlayBackStarted();
4035 // FIXME: it seems no meaning to callback started here if there was an started callback
4036 // before this stopped/ended callback we recorded. if we callback started here
4037 // first, it will delay send OnPlay announce, but then we callback stopped/ended
4038 // which will send OnStop announce at once, so currently, just call stopped/ended.
4039 case PLAY_STATE_ENDED:
4042 case PLAY_STATE_STOPPED:
4043 OnPlayBackStopped();
4045 case PLAY_STATE_STARTING:
4046 // neither started nor stopped/ended callback be called, that means the item still
4047 // not started, we need not make up any callback, just leave this and
4048 // let the player callback do its work.
4054 else if (iResult == PLAYBACK_FAIL)
4056 // we send this if it isn't playlistplayer that is doing this
4057 int next = g_playlistPlayer.GetNextSong();
4058 int size = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist()).size();
4061 OnPlayBackStopped();
4062 m_ePlayState = PLAY_STATE_NONE;
4068 void CApplication::OnPlayBackEnded()
4070 CSingleLock lock(m_playStateMutex);
4071 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4072 m_ePlayState = PLAY_STATE_ENDED;
4073 if(m_bPlaybackStarting)
4076 // informs python script currently running playback has ended
4077 // (does nothing if python is not loaded)
4079 g_pythonParser.OnPlayBackEnded();
4082 CVariant data(CVariant::VariantTypeObject);
4084 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4086 CGUIMessage msg(GUI_MSG_PLAYBACK_ENDED, 0, 0);
4087 g_windowManager.SendThreadMessage(msg);
4090 void CApplication::OnPlayBackStarted()
4092 CSingleLock lock(m_playStateMutex);
4093 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4094 m_ePlayState = PLAY_STATE_PLAYING;
4095 if(m_bPlaybackStarting)
4099 // informs python script currently running playback has started
4100 // (does nothing if python is not loaded)
4101 g_pythonParser.OnPlayBackStarted();
4104 CGUIMessage msg(GUI_MSG_PLAYBACK_STARTED, 0, 0);
4105 g_windowManager.SendThreadMessage(msg);
4108 void CApplication::OnQueueNextItem()
4110 CSingleLock lock(m_playStateMutex);
4111 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4112 if(m_bPlaybackStarting)
4114 // informs python script currently running that we are requesting the next track
4115 // (does nothing if python is not loaded)
4117 g_pythonParser.OnQueueNextItem(); // currently unimplemented
4120 CGUIMessage msg(GUI_MSG_QUEUE_NEXT_ITEM, 0, 0);
4121 g_windowManager.SendThreadMessage(msg);
4124 void CApplication::OnPlayBackStopped()
4126 CSingleLock lock(m_playStateMutex);
4127 CLog::Log(LOGDEBUG,"%s : play state was %d, starting %d", __FUNCTION__, m_ePlayState, m_bPlaybackStarting);
4128 m_ePlayState = PLAY_STATE_STOPPED;
4129 if(m_bPlaybackStarting)
4132 // informs python script currently running playback has ended
4133 // (does nothing if python is not loaded)
4135 g_pythonParser.OnPlayBackStopped();
4138 CVariant data(CVariant::VariantTypeObject);
4139 data["end"] = false;
4140 CAnnouncementManager::Announce(Player, "xbmc", "OnStop", m_itemCurrentFile, data);
4142 CGUIMessage msg( GUI_MSG_PLAYBACK_STOPPED, 0, 0 );
4143 g_windowManager.SendThreadMessage(msg);
4146 void CApplication::OnPlayBackPaused()
4149 g_pythonParser.OnPlayBackPaused();
4153 param["player"]["speed"] = 0;
4154 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4155 CAnnouncementManager::Announce(Player, "xbmc", "OnPause", m_itemCurrentFile, param);
4158 void CApplication::OnPlayBackResumed()
4161 g_pythonParser.OnPlayBackResumed();
4165 param["player"]["speed"] = 1;
4166 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4167 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4170 void CApplication::OnPlayBackSpeedChanged(int iSpeed)
4173 g_pythonParser.OnPlayBackSpeedChanged(iSpeed);
4177 param["player"]["speed"] = iSpeed;
4178 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4179 CAnnouncementManager::Announce(Player, "xbmc", "OnSpeedChanged", m_itemCurrentFile, param);
4182 void CApplication::OnPlayBackSeek(int iTime, int seekOffset)
4185 g_pythonParser.OnPlayBackSeek(iTime, seekOffset);
4189 CJSONUtils::MillisecondsToTimeObject(iTime, param["player"]["time"]);
4190 CJSONUtils::MillisecondsToTimeObject(seekOffset, param["player"]["seekoffset"]);;
4191 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4192 param["player"]["speed"] = m_pPlayer->GetPlaySpeed();
4193 CAnnouncementManager::Announce(Player, "xbmc", "OnSeek", m_itemCurrentFile, param);
4194 g_infoManager.SetDisplayAfterSeek(2500, seekOffset/1000);
4197 void CApplication::OnPlayBackSeekChapter(int iChapter)
4200 g_pythonParser.OnPlayBackSeekChapter(iChapter);
4204 bool CApplication::IsPlayingFullScreenVideo() const
4206 return m_pPlayer->IsPlayingVideo() && g_graphicsContext.IsFullScreenVideo();
4209 bool CApplication::IsFullScreen()
4211 return IsPlayingFullScreenVideo() ||
4212 (g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) ||
4213 g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW;
4216 void CApplication::SaveFileState(bool bForeground /* = false */)
4218 if (m_progressTrackingItem->IsPVRChannel() || !CProfilesManager::Get().GetCurrentProfile().canWriteDatabases())
4223 CSaveFileStateJob job(*m_progressTrackingItem,
4224 *m_stackFileItemToUpdate,
4225 m_progressTrackingVideoResumeBookmark,
4226 m_progressTrackingPlayCountUpdate);
4228 // Run job in the foreground to make sure it finishes
4233 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
4234 *m_stackFileItemToUpdate,
4235 m_progressTrackingVideoResumeBookmark,
4236 m_progressTrackingPlayCountUpdate);
4237 CJobManager::GetInstance().AddJob(job, NULL, CJob::PRIORITY_NORMAL);
4241 void CApplication::UpdateFileState()
4243 // Did the file change?
4244 if (m_progressTrackingItem->GetPath() != "" && m_progressTrackingItem->GetPath() != CurrentFile())
4248 // Reset tracking item
4249 m_progressTrackingItem->Reset();
4253 if (m_pPlayer->IsPlaying())
4255 if (m_progressTrackingItem->GetPath() == "")
4258 *m_progressTrackingItem = CurrentFileItem();
4259 m_progressTrackingPlayCountUpdate = false;
4262 if ((m_progressTrackingItem->IsAudio() && g_advancedSettings.m_audioPlayCountMinimumPercent > 0 &&
4263 GetPercentage() >= g_advancedSettings.m_audioPlayCountMinimumPercent) ||
4264 (m_progressTrackingItem->IsVideo() && g_advancedSettings.m_videoPlayCountMinimumPercent > 0 &&
4265 GetPercentage() >= g_advancedSettings.m_videoPlayCountMinimumPercent))
4267 m_progressTrackingPlayCountUpdate = true;
4270 // Check whether we're *really* playing video else we may race when getting eg. stream details
4271 if (m_pPlayer->IsPlayingVideo())
4273 /* Always update streamdetails, except for DVDs where we only update
4274 streamdetails if title length > 15m (Should yield more correct info) */
4275 if (!(m_progressTrackingItem->IsDVDImage() || m_progressTrackingItem->IsDVDFile()) || m_pPlayer->GetTotalTime() > 15*60*1000)
4277 CStreamDetails details;
4278 // Update with stream details from player, if any
4279 if (m_pPlayer->GetStreamDetails(details))
4280 m_progressTrackingItem->GetVideoInfoTag()->m_streamDetails = details;
4283 // Update bookmark for save
4284 m_progressTrackingVideoResumeBookmark.player = CPlayerCoreFactory::Get().GetPlayerName(m_pPlayer->GetCurrentPlayer());
4285 m_progressTrackingVideoResumeBookmark.playerState = m_pPlayer->GetPlayerState();
4286 m_progressTrackingVideoResumeBookmark.thumbNailImage.Empty();
4288 if (g_advancedSettings.m_videoIgnorePercentAtEnd > 0 &&
4289 GetTotalTime() - GetTime() < 0.01f * g_advancedSettings.m_videoIgnorePercentAtEnd * GetTotalTime())
4291 // Delete the bookmark
4292 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4295 if (GetTime() > g_advancedSettings.m_videoIgnoreSecondsAtStart)
4297 // Update the bookmark
4298 m_progressTrackingVideoResumeBookmark.timeInSeconds = GetTime();
4299 m_progressTrackingVideoResumeBookmark.totalTimeInSeconds = GetTotalTime();
4304 m_progressTrackingVideoResumeBookmark.timeInSeconds = 0.0f;
4311 void CApplication::StopPlaying()
4313 int iWin = g_windowManager.GetActiveWindow();
4314 if ( m_pPlayer->IsPlaying() )
4318 m_pKaraokeMgr->Stop();
4321 if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio())
4322 g_PVRManager.SaveCurrentChannelSettings();
4324 m_pPlayer->CloseFile();
4326 // turn off visualisation window when stopping
4327 if ((iWin == WINDOW_VISUALISATION
4328 || iWin == WINDOW_FULLSCREEN_VIDEO)
4330 g_windowManager.PreviousWindow();
4332 g_partyModeManager.Disable();
4336 void CApplication::ResetSystemIdleTimer()
4338 // reset system idle timer
4339 m_idleTimer.StartZero();
4342 void CApplication::ResetScreenSaver()
4345 m_shutdownTimer.StartZero();
4347 // screen saver timer is reset only if we're not already in screensaver or
4349 if ((!m_bScreenSave && m_iScreenSaveLock == 0) && !m_dpmsIsActive)
4350 ResetScreenSaverTimer();
4353 void CApplication::ResetScreenSaverTimer()
4355 m_screenSaverTimer.StartZero();
4358 void CApplication::StopScreenSaverTimer()
4360 m_screenSaverTimer.Stop();
4363 bool CApplication::ToggleDPMS(bool manual)
4365 if (manual || (m_dpmsIsManual == manual))
4369 m_dpmsIsActive = false;
4370 m_dpmsIsManual = false;
4371 return m_dpms->DisablePowerSaving();
4375 if (m_dpms->EnablePowerSaving(m_dpms->GetSupportedModes()[0]))
4377 m_dpmsIsActive = true;
4378 m_dpmsIsManual = manual;
4386 bool CApplication::WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed /* = false */)
4390 // First reset DPMS, if active
4395 // TODO: if screensaver lock is specified but screensaver is not active
4396 // (DPMS came first), activate screensaver now.
4398 ResetScreenSaverTimer();
4399 result = !m_bScreenSave || WakeUpScreenSaver(bPowerOffKeyPressed);
4402 result = WakeUpScreenSaver(bPowerOffKeyPressed);
4406 // allow listeners to ignore the deactivation if it preceeds a powerdown/suspend etc
4407 CVariant data(bPowerOffKeyPressed);
4408 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverDeactivated", data);
4414 bool CApplication::WakeUpScreenSaver(bool bPowerOffKeyPressed /* = false */)
4416 if (m_iScreenSaveLock == 2)
4419 // if Screen saver is active
4420 if (m_bScreenSave && m_screenSaver)
4422 if (m_iScreenSaveLock == 0)
4423 if (CProfilesManager::Get().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4424 (CProfilesManager::Get().UsingLoginScreen() || CSettings::Get().GetBool("masterlock.startuplock")) &&
4425 CProfilesManager::Get().GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
4426 m_screenSaver->ID() != "screensaver.xbmc.builtin.dim" && m_screenSaver->ID() != "screensaver.xbmc.builtin.black" && !m_screenSaver->ID().empty() && m_screenSaver->ID() != "visualization")
4428 m_iScreenSaveLock = 2;
4429 CGUIMessage msg(GUI_MSG_CHECK_LOCK,0,0);
4431 CGUIWindow* pWindow = g_windowManager.GetWindow(WINDOW_SCREENSAVER);
4433 pWindow->OnMessage(msg);
4435 if (m_iScreenSaveLock == -1)
4437 m_iScreenSaveLock = 0;
4441 // disable screensaver
4442 m_bScreenSave = false;
4443 m_iScreenSaveLock = 0;
4444 ResetScreenSaverTimer();
4446 if (m_screenSaver->ID() == "visualization")
4448 // we can just continue as usual from vis mode
4451 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID() == "screensaver.xbmc.builtin.black" || m_screenSaver->ID().empty())
4453 else if (!m_screenSaver->ID().IsEmpty())
4454 { // we're in screensaver window
4455 if (g_windowManager.GetActiveWindow() == WINDOW_SCREENSAVER)
4456 g_windowManager.PreviousWindow(); // show the previous window
4457 if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
4458 CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP), WINDOW_SLIDESHOW);
4466 void CApplication::CheckScreenSaverAndDPMS()
4468 if (m_bInBackground)
4470 if (!m_dpmsIsActive)
4471 g_Windowing.ResetOSScreensaver();
4473 bool maybeScreensaver =
4474 !m_dpmsIsActive && !m_bScreenSave
4475 && !CSettings::Get().GetString("screensaver.mode").empty();
4477 !m_dpmsIsActive && m_dpms->IsSupported()
4478 && CSettings::Get().GetInt("powermanagement.displaysoff") > 0;
4480 // Has the screen saver window become active?
4481 if (maybeScreensaver && g_windowManager.IsWindowActive(WINDOW_SCREENSAVER))
4483 m_bScreenSave = true;
4484 maybeScreensaver = false;
4487 if (m_bScreenSave && m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4489 WakeUpScreenSaverAndDPMS();
4493 if (!maybeScreensaver && !maybeDPMS) return; // Nothing to do.
4495 // See if we need to reset timer.
4496 // * Are we playing a video and it is not paused?
4497 if ((m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPaused())
4498 // * Are we playing some music in fullscreen vis?
4499 || (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION
4500 && !CSettings::Get().GetString("musicplayer.visualisation").empty()))
4502 ResetScreenSaverTimer();
4506 float elapsed = m_screenSaverTimer.GetElapsedSeconds();
4508 // DPMS has priority (it makes the screensaver not needed)
4510 && elapsed > CSettings::Get().GetInt("powermanagement.displaysoff") * 60)
4513 WakeUpScreenSaver();
4515 else if (maybeScreensaver
4516 && elapsed > CSettings::Get().GetInt("screensaver.time") * 60)
4518 ActivateScreenSaver();
4522 // activate the screensaver.
4523 // if forceType is true, we ignore the various conditions that can alter
4524 // the type of screensaver displayed
4525 void CApplication::ActivateScreenSaver(bool forceType /*= false */)
4527 m_bScreenSave = true;
4529 // Get Screensaver Mode
4530 m_screenSaver.reset();
4531 if (!CAddonMgr::Get().GetAddon(CSettings::Get().GetString("screensaver.mode"), m_screenSaver))
4532 m_screenSaver.reset(new CScreenSaver(""));
4534 CAnnouncementManager::Announce(GUI, "xbmc", "OnScreensaverActivated");
4536 // disable screensaver lock from the login screen
4537 m_iScreenSaveLock = g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN ? 1 : 0;
4540 // set to Dim in the case of a dialog on screen or playing video
4541 if (g_windowManager.HasModalDialog() || (m_pPlayer->IsPlayingVideo() && CSettings::Get().GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan())
4543 if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver))
4544 m_screenSaver.reset(new CScreenSaver(""));
4546 // Check if we are Playing Audio and Vis instead Screensaver!
4547 else if (m_pPlayer->IsPlayingAudio() && CSettings::Get().GetBool("screensaver.usemusicvisinstead") && !CSettings::Get().GetString("musicplayer.visualisation").empty())
4548 { // activate the visualisation
4549 m_screenSaver.reset(new CScreenSaver("visualization"));
4550 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
4554 if (m_screenSaver->ID() == "screensaver.xbmc.builtin.dim" || m_screenSaver->ID().empty())
4556 else if (m_screenSaver->ID() == "screensaver.xbmc.builtin.black")
4558 else if (!m_screenSaver->ID().IsEmpty())
4559 g_windowManager.ActivateWindow(WINDOW_SCREENSAVER);
4562 void CApplication::SetInBackground(bool background)
4566 ResetScreenSaverTimer();
4568 m_bInBackground = background;
4571 void CApplication::CheckShutdown()
4573 // first check if we should reset the timer
4574 bool resetTimer = m_bInhibitIdleShutdown;
4576 if (m_pPlayer->IsPlaying() || m_pPlayer->IsPausedPlayback()) // is something playing?
4579 if (m_musicInfoScanner->IsScanning())
4582 if (m_videoInfoScanner->IsScanning())
4585 if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen
4588 if (CSettings::Get().GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle())
4593 m_shutdownTimer.StartZero();
4597 if ( m_shutdownTimer.GetElapsedSeconds() > CSettings::Get().GetInt("powermanagement.shutdowntime") * 60 )
4599 // Since it is a sleep instead of a shutdown, let's set everything to reset when we wake up.
4600 m_shutdownTimer.Stop();
4603 CApplicationMessenger::Get().Shutdown();
4607 void CApplication::InhibitIdleShutdown(bool inhibit)
4609 m_bInhibitIdleShutdown = inhibit;
4612 bool CApplication::IsIdleShutdownInhibited() const
4614 return m_bInhibitIdleShutdown;
4617 bool CApplication::OnMessage(CGUIMessage& message)
4619 switch ( message.GetMessage() )
4621 case GUI_MSG_NOTIFY_ALL:
4623 if (message.GetParam1()==GUI_MSG_REMOVED_MEDIA)
4625 // Update general playlist: Remove DVD playlist items
4626 int nRemoved = g_playlistPlayer.RemoveDVDItems();
4629 CGUIMessage msg( GUI_MSG_PLAYLIST_CHANGED, 0, 0 );
4630 g_windowManager.SendMessage( msg );
4632 // stop the file if it's on dvd (will set the resume point etc)
4633 if (m_itemCurrentFile->IsOnDVD())
4639 case GUI_MSG_PLAYBACK_STARTED:
4641 #ifdef TARGET_DARWIN
4642 DarwinSetScheduling(message.GetMessage());
4644 // reset the seek handler
4645 m_seekHandler->Reset();
4646 CPlayList playList = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4648 // Update our infoManager with the new details etc.
4649 if (m_nextPlaylistItem >= 0)
4651 // playing an item which is not in the list - player might be stopped already
4653 if (playList.size() <= m_nextPlaylistItem)
4656 // we've started a previously queued item
4657 CFileItemPtr item = playList[m_nextPlaylistItem];
4658 // update the playlist manager
4659 int currentSong = g_playlistPlayer.GetCurrentSong();
4660 int param = ((currentSong & 0xffff) << 16) | (m_nextPlaylistItem & 0xffff);
4661 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_CHANGED, 0, 0, g_playlistPlayer.GetCurrentPlaylist(), param, item);
4662 g_windowManager.SendThreadMessage(msg);
4663 g_playlistPlayer.SetCurrentSong(m_nextPlaylistItem);
4664 *m_itemCurrentFile = *item;
4666 g_infoManager.SetCurrentItem(*m_itemCurrentFile);
4667 g_partyModeManager.OnSongChange(true);
4670 param["player"]["speed"] = 1;
4671 param["player"]["playerid"] = g_playlistPlayer.GetCurrentPlaylist();
4672 CAnnouncementManager::Announce(Player, "xbmc", "OnPlay", m_itemCurrentFile, param);
4674 if (m_pPlayer->IsPlayingAudio())
4676 // Start our cdg parser as appropriate
4678 if (m_pKaraokeMgr && CSettings::Get().GetBool("karaoke.enabled") && !m_itemCurrentFile->IsInternetStream())
4680 m_pKaraokeMgr->Stop();
4681 if (m_itemCurrentFile->IsMusicDb())
4683 if (!m_itemCurrentFile->HasMusicInfoTag() || !m_itemCurrentFile->GetMusicInfoTag()->Loaded())
4685 IMusicInfoTagLoader* tagloader = CMusicInfoTagLoaderFactory::CreateLoader(m_itemCurrentFile->GetPath());
4686 tagloader->Load(m_itemCurrentFile->GetPath(),*m_itemCurrentFile->GetMusicInfoTag());
4689 m_pKaraokeMgr->Start(m_itemCurrentFile->GetMusicInfoTag()->GetURL());
4692 m_pKaraokeMgr->Start(m_itemCurrentFile->GetPath());
4701 case GUI_MSG_QUEUE_NEXT_ITEM:
4703 // Check to see if our playlist player has a new item for us,
4704 // and if so, we check whether our current player wants the file
4705 int iNext = g_playlistPlayer.GetNextSong();
4706 CPlayList& playlist = g_playlistPlayer.GetPlaylist(g_playlistPlayer.GetCurrentPlaylist());
4707 if (iNext < 0 || iNext >= playlist.size())
4709 m_pPlayer->OnNothingToQueueNotify();
4710 return true; // nothing to do
4713 // ok, grab the next song
4714 CFileItem file(*playlist[iNext]);
4716 CURL url(file.GetPath());
4717 if (url.GetProtocol() == "plugin")
4718 XFILE::CPluginDirectory::GetPluginResult(url.Get(), file);
4721 if (URIUtils::IsUPnP(file.GetPath()))
4723 if (!XFILE::CUPnPDirectory::GetResource(file.GetPath(), file))
4728 // ok - send the file to the player, if it accepts it
4729 if (m_pPlayer->QueueNextFile(file))
4731 // player accepted the next file
4732 m_nextPlaylistItem = iNext;
4736 /* Player didn't accept next file: *ALWAYS* advance playlist in this case so the player can
4737 queue the next (if it wants to) and it doesn't keep looping on this song */
4738 g_playlistPlayer.SetCurrentSong(iNext);
4745 case GUI_MSG_PLAYBACK_STOPPED:
4746 case GUI_MSG_PLAYBACK_ENDED:
4747 case GUI_MSG_PLAYLISTPLAYER_STOPPED:
4751 m_pKaraokeMgr->Stop();
4753 #ifdef TARGET_DARWIN
4754 DarwinSetScheduling(message.GetMessage());
4756 // first check if we still have items in the stack to play
4757 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4759 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0 && m_currentStackPosition < m_currentStack->Size() - 1)
4760 { // just play the next item in the stack
4761 PlayFile(*(*m_currentStack)[++m_currentStackPosition], true);
4766 // In case playback ended due to user eg. skipping over the end, clear
4767 // our resume bookmark here
4768 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED && m_progressTrackingPlayCountUpdate && g_advancedSettings.m_videoIgnorePercentAtEnd > 0)
4770 // Delete the bookmark
4771 m_progressTrackingVideoResumeBookmark.timeInSeconds = -1.0f;
4774 // reset the current playing file
4775 m_itemCurrentFile->Reset();
4776 g_infoManager.ResetCurrentItem();
4777 m_currentStack->Clear();
4779 if (message.GetMessage() == GUI_MSG_PLAYBACK_ENDED)
4781 g_playlistPlayer.PlayNext(1, true);
4785 // reset any forced player
4786 m_eForcedNextPlayer = EPC_NONE;
4788 m_pPlayer->ClosePlayer();
4791 m_pPlayer->m_iPlaySpeed = 1;
4794 if (!m_pPlayer->IsPlaying())
4796 g_audioManager.Enable(true);
4799 if (!m_pPlayer->IsPlayingVideo())
4801 if(g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO)
4803 g_windowManager.PreviousWindow();
4807 CSingleLock lock(g_graphicsContext);
4808 // resets to res_desktop or look&feel resolution (including refreshrate)
4809 g_graphicsContext.SetFullScreenVideo(false);
4813 if (!m_pPlayer->IsPlayingAudio() && g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_NONE && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4815 CSettings::Get().Save(); // save vis settings
4816 WakeUpScreenSaverAndDPMS();
4817 g_windowManager.PreviousWindow();
4820 // DVD ejected while playing in vis ?
4821 if (!m_pPlayer->IsPlayingAudio() && (m_itemCurrentFile->IsCDDA() || m_itemCurrentFile->IsOnDVD()) && !g_mediaManager.IsDiscInDrive() && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)
4824 CSettings::Get().Save(); // save vis settings
4825 WakeUpScreenSaverAndDPMS();
4826 g_windowManager.PreviousWindow();
4829 if (IsEnableTestMode())
4830 CApplicationMessenger::Get().Quit();
4835 case GUI_MSG_PLAYLISTPLAYER_STARTED:
4836 case GUI_MSG_PLAYLISTPLAYER_CHANGED:
4841 case GUI_MSG_FULLSCREEN:
4842 { // Switch to fullscreen, if we can
4843 SwitchToFullScreen();
4847 case GUI_MSG_EXECUTE:
4848 if (message.GetNumStringParams())
4849 return ExecuteXBMCAction(message.GetStringParam());
4855 bool CApplication::ExecuteXBMCAction(std::string actionStr)
4857 // see if it is a user set string
4858 CLog::Log(LOGDEBUG,"%s : Translating %s", __FUNCTION__, actionStr.c_str());
4859 CGUIInfoLabel info(actionStr, "");
4860 actionStr = info.GetLabel(0);
4861 CLog::Log(LOGDEBUG,"%s : To %s", __FUNCTION__, actionStr.c_str());
4863 // user has asked for something to be executed
4864 if (CBuiltins::HasCommand(actionStr))
4865 CBuiltins::Execute(actionStr);
4868 // try translating the action from our ButtonTranslator
4870 if (CButtonTranslator::TranslateActionString(actionStr.c_str(), actionID))
4872 OnAction(CAction(actionID));
4875 CFileItem item(actionStr, false);
4877 if (item.IsPythonScript())
4878 { // a python script
4879 CScriptInvocationManager::Get().Execute(item.GetPath());
4883 if (item.IsAudio() || item.IsVideo())
4884 { // an audio or video file
4893 void CApplication::Process()
4897 // dispatch the messages generated by python or other threads to the current window
4898 g_windowManager.DispatchThreadMessages();
4900 // process messages which have to be send to the gui
4901 // (this can only be done after g_windowManager.Render())
4902 CApplicationMessenger::Get().ProcessWindowMessages();
4906 m_loggingIn = false;
4908 // autoexec.py - profile
4909 CStdString strAutoExecPy = CSpecialProtocol::TranslatePath("special://profile/autoexec.py");
4911 if (XFILE::CFile::Exists(strAutoExecPy))
4912 CScriptInvocationManager::Get().Execute(strAutoExecPy);
4914 CLog::Log(LOGDEBUG, "no profile autoexec.py (%s) found, skipping", strAutoExecPy.c_str());
4917 // handle any active scripts
4918 CScriptInvocationManager::Get().Process();
4920 // process messages, even if a movie is playing
4921 CApplicationMessenger::Get().ProcessMessages();
4922 if (g_application.m_bStop) return; //we're done, everything has been unloaded
4924 // check how far we are through playing the current item
4925 // and do anything that needs doing (playcount updates etc)
4926 CheckPlayingProgress();
4929 m_pPlayer->DoAudioWork();
4931 // do any processing that isn't needed on each run
4932 if( m_slowTimer.GetElapsedMilliseconds() > 500 )
4934 m_slowTimer.Reset();
4938 g_cpuInfo.getUsedPercentage(); // must call it to recalculate pct values
4941 // We get called every 500ms
4942 void CApplication::ProcessSlow()
4944 g_powerManager.ProcessEvents();
4946 #if defined(TARGET_DARWIN_OSX)
4947 // There is an issue on OS X that several system services ask the cursor to become visible
4948 // during their startup routines. Given that we can't control this, we hack it in by
4950 if (g_Windowing.IsFullScreen())
4951 { // SDL thinks it's hidden
4956 // Resume low priority jobs when current item is not video
4957 if (!CurrentFileItem().IsVideo())
4959 CJobManager::GetInstance().UnPause(CJob::PRIORITY_LOW);
4962 // Store our file state for use on close()
4965 // Check if we need to activate the screensaver / DPMS.
4966 CheckScreenSaverAndDPMS();
4968 // Check if we need to shutdown (if enabled).
4969 #if defined(TARGET_DARWIN)
4970 if (CSettings::Get().GetInt("powermanagement.shutdowntime") && g_advancedSettings.m_fullScreen)
4972 if (CSettings::Get().GetInt("powermanagement.shutdowntime"))
4978 // check if we should restart the player
4979 CheckDelayedPlayerRestart();
4981 // check if we can unload any unreferenced dlls or sections
4982 if (!m_pPlayer->IsPlayingVideo())
4983 CSectionLoader::UnloadDelayed();
4985 // check for any idle curl connections
4986 g_curlInterface.CheckIdle();
4988 // check for any idle myth sessions
4989 CMythSession::CheckIdle();
4991 #ifdef HAS_FILESYSTEM_HTSP
4992 // check for any idle htsp sessions
4993 HTSP::CHTSPDirectorySession::CheckIdle();
4997 if ( m_pKaraokeMgr )
4998 m_pKaraokeMgr->ProcessSlow();
5001 if (!m_pPlayer->IsPlayingVideo())
5002 g_largeTextureManager.CleanupUnusedImages();
5004 g_TextureManager.FreeUnusedTextures(5000);
5006 #ifdef HAS_DVD_DRIVE
5007 // checks whats in the DVD drive and tries to autostart the content (xbox games, dvd, cdda, avi files...)
5008 if (!m_pPlayer->IsPlayingVideo())
5009 m_Autorun->HandleAutorun();
5012 // update upnp server/renderer states
5014 if(UPNP::CUPnP::IsInstantiated())
5015 UPNP::CUPnP::GetInstance()->UpdateState();
5018 #if defined(TARGET_POSIX) && defined(HAS_FILESYSTEM_SMB)
5022 #ifdef HAS_FILESYSTEM_NFS
5023 gNfsConnection.CheckIfIdle();
5026 #ifdef HAS_FILESYSTEM_AFP
5027 gAfpConnection.CheckIfIdle();
5030 #ifdef HAS_FILESYSTEM_SFTP
5031 CSFTPSessionManager::ClearOutIdleSessions();
5034 g_mediaManager.ProcessEvents();
5037 if (g_RemoteControl.IsInUse() && !g_RemoteControl.IsInitialized())
5038 g_RemoteControl.Initialize();
5041 if (!m_pPlayer->IsPlayingVideo())
5042 CAddonInstaller::Get().UpdateRepos();
5044 CAEFactory::GarbageCollect();
5047 // Global Idle Time in Seconds
5048 // idle time will be resetet if on any OnKey()
5049 // int return: system Idle time in seconds! 0 is no idle!
5050 int CApplication::GlobalIdleTime()
5052 if(!m_idleTimer.IsRunning())
5055 m_idleTimer.StartZero();
5057 return (int)m_idleTimer.GetElapsedSeconds();
5060 float CApplication::NavigationIdleTime()
5062 if (!m_navigationTimer.IsRunning())
5064 m_navigationTimer.Stop();
5065 m_navigationTimer.StartZero();
5067 return m_navigationTimer.GetElapsedSeconds();
5070 void CApplication::DelayedPlayerRestart()
5072 m_restartPlayerTimer.StartZero();
5075 void CApplication::CheckDelayedPlayerRestart()
5077 if (m_restartPlayerTimer.GetElapsedSeconds() > 3)
5079 m_restartPlayerTimer.Stop();
5080 m_restartPlayerTimer.Reset();
5085 void CApplication::Restart(bool bSamePosition)
5087 // this function gets called when the user changes a setting (like noninterleaved)
5088 // and which means we gotta close & reopen the current playing file
5090 // first check if we're playing a file
5091 if ( !m_pPlayer->IsPlayingVideo() && !m_pPlayer->IsPlayingAudio())
5094 if( !m_pPlayer->HasPlayer() )
5099 // do we want to return to the current position in the file
5100 if (false == bSamePosition)
5102 // no, then just reopen the file and start at the beginning
5103 PlayFile(*m_itemCurrentFile, true);
5107 // else get current position
5108 double time = GetTime();
5110 // get player state, needed for dvd's
5111 CStdString state = m_pPlayer->GetPlayerState();
5113 // set the requested starttime
5114 m_itemCurrentFile->m_lStartOffset = (long)(time * 75.0);
5117 if ( PlayFile(*m_itemCurrentFile, true) == PLAYBACK_OK )
5118 m_pPlayer->SetPlayerState(state);
5121 const CStdString& CApplication::CurrentFile()
5123 return m_itemCurrentFile->GetPath();
5126 CFileItem& CApplication::CurrentFileItem()
5128 return *m_itemCurrentFile;
5131 void CApplication::ShowVolumeBar(const CAction *action)
5133 CGUIDialog *volumeBar = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VOLUME_BAR);
5138 volumeBar->OnAction(*action);
5142 bool CApplication::IsMuted() const
5144 if (g_peripherals.IsMuted())
5146 return CAEFactory::IsMuted();
5149 void CApplication::ToggleMute(void)
5157 void CApplication::SetMute(bool mute)
5159 if (m_muted != mute)
5166 void CApplication::Mute()
5168 if (g_peripherals.Mute())
5171 CAEFactory::SetMute(true);
5176 void CApplication::UnMute()
5178 if (g_peripherals.UnMute())
5181 CAEFactory::SetMute(false);
5186 void CApplication::SetVolume(float iValue, bool isPercentage/*=true*/)
5188 float hardwareVolume = iValue;
5191 hardwareVolume /= 100.0f;
5193 SetHardwareVolume(hardwareVolume);
5197 void CApplication::SetHardwareVolume(float hardwareVolume)
5199 hardwareVolume = std::max(VOLUME_MINIMUM, std::min(VOLUME_MAXIMUM, hardwareVolume));
5200 m_volumeLevel = hardwareVolume;
5203 if (hardwareVolume > VOLUME_MINIMUM)
5205 float dB = CAEUtil::PercentToGain(hardwareVolume);
5206 value = CAEUtil::GainToScale(dB);
5211 CAEFactory::SetVolume(value);
5214 float CApplication::GetVolume(bool percentage /* = true */) const
5218 // converts the hardware volume to a percentage
5219 return m_volumeLevel * 100.0f;
5222 return m_volumeLevel;
5225 void CApplication::VolumeChanged() const
5227 CVariant data(CVariant::VariantTypeObject);
5228 data["volume"] = GetVolume();
5229 data["muted"] = m_muted;
5230 CAnnouncementManager::Announce(Application, "xbmc", "OnVolumeChanged", data);
5232 // if player has volume control, set it.
5233 if (m_pPlayer->ControlsVolume())
5235 m_pPlayer->SetVolume(m_volumeLevel);
5236 m_pPlayer->SetMute(m_muted);
5240 int CApplication::GetSubtitleDelay() const
5242 // converts subtitle delay to a percentage
5243 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay + g_advancedSettings.m_videoSubsDelayRange)) / (2 * g_advancedSettings.m_videoSubsDelayRange)*100.0f + 0.5f);
5246 int CApplication::GetAudioDelay() const
5248 // converts audio delay to a percentage
5249 return int(((float)(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay + g_advancedSettings.m_videoAudioDelayRange)) / (2 * g_advancedSettings.m_videoAudioDelayRange)*100.0f + 0.5f);
5252 // Returns the total time in seconds of the current media. Fractional
5253 // portions of a second are possible - but not necessarily supported by the
5254 // player class. This returns a double to be consistent with GetTime() and
5256 double CApplication::GetTotalTime() const
5260 if (m_pPlayer->IsPlaying())
5262 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5263 rc = (*m_currentStack)[m_currentStack->Size() - 1]->m_lEndOffset;
5265 rc = static_cast<double>(m_pPlayer->GetTotalTime() * 0.001f);
5271 void CApplication::StopShutdownTimer()
5273 if (m_shutdownTimer.IsRunning())
5274 m_shutdownTimer.Stop();
5277 void CApplication::ResetShutdownTimers()
5279 // reset system shutdown timer
5280 m_shutdownTimer.StartZero();
5282 // delete custom shutdown timer
5283 if (g_alarmClock.HasAlarm("shutdowntimer"))
5284 g_alarmClock.Stop("shutdowntimer", true);
5287 // Returns the current time in seconds of the currently playing media.
5288 // Fractional portions of a second are possible. This returns a double to
5289 // be consistent with GetTotalTime() and SeekTime().
5290 double CApplication::GetTime() const
5294 if (m_pPlayer->IsPlaying())
5296 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5298 long startOfCurrentFile = (m_currentStackPosition > 0) ? (*m_currentStack)[m_currentStackPosition-1]->m_lEndOffset : 0;
5299 rc = (double)startOfCurrentFile + m_pPlayer->GetTime() * 0.001;
5302 rc = static_cast<double>(m_pPlayer->GetTime() * 0.001f);
5308 // Sets the current position of the currently playing media to the specified
5309 // time in seconds. Fractional portions of a second are valid. The passed
5310 // time is the time offset from the beginning of the file as opposed to a
5311 // delta from the current position. This method accepts a double to be
5312 // consistent with GetTime() and GetTotalTime().
5313 void CApplication::SeekTime( double dTime )
5315 if (m_pPlayer->IsPlaying() && (dTime >= 0.0))
5317 if (!m_pPlayer->CanSeek()) return;
5318 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5320 // find the item in the stack we are seeking to, and load the new
5321 // file if necessary, and calculate the correct seek within the new
5322 // file. Otherwise, just fall through to the usual routine if the
5323 // time is higher than our total time.
5324 for (int i = 0; i < m_currentStack->Size(); i++)
5326 if ((*m_currentStack)[i]->m_lEndOffset > dTime)
5328 long startOfNewFile = (i > 0) ? (*m_currentStack)[i-1]->m_lEndOffset : 0;
5329 if (m_currentStackPosition == i)
5330 m_pPlayer->SeekTime((int64_t)((dTime - startOfNewFile) * 1000.0));
5332 { // seeking to a new file
5333 m_currentStackPosition = i;
5334 CFileItem item(*(*m_currentStack)[i]);
5335 item.m_lStartOffset = (long)((dTime - startOfNewFile) * 75.0);
5336 // don't just call "PlayFile" here, as we are quite likely called from the
5337 // player thread, so we won't be able to delete ourselves.
5338 CApplicationMessenger::Get().PlayFile(item, true);
5344 // convert to milliseconds and perform seek
5345 m_pPlayer->SeekTime( static_cast<int64_t>( dTime * 1000.0 ) );
5349 float CApplication::GetPercentage() const
5351 if (m_pPlayer->IsPlaying())
5353 if (m_pPlayer->GetTotalTime() == 0 && m_pPlayer->IsPlayingAudio() && m_itemCurrentFile->HasMusicInfoTag())
5355 const CMusicInfoTag& tag = *m_itemCurrentFile->GetMusicInfoTag();
5356 if (tag.GetDuration() > 0)
5357 return (float)(GetTime() / tag.GetDuration() * 100);
5360 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5362 double totalTime = GetTotalTime();
5363 if (totalTime > 0.0f)
5364 return (float)(GetTime() / totalTime * 100);
5367 return m_pPlayer->GetPercentage();
5372 float CApplication::GetCachePercentage() const
5374 if (m_pPlayer->IsPlaying())
5376 // Note that the player returns a relative cache percentage and we want an absolute percentage
5377 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5379 float stackedTotalTime = (float) GetTotalTime();
5380 // We need to take into account the stack's total time vs. currently playing file's total time
5381 if (stackedTotalTime > 0.0f)
5382 return min( 100.0f, GetPercentage() + (m_pPlayer->GetCachePercentage() * m_pPlayer->GetTotalTime() * 0.001f / stackedTotalTime ) );
5385 return min( 100.0f, m_pPlayer->GetPercentage() + m_pPlayer->GetCachePercentage() );
5390 void CApplication::SeekPercentage(float percent)
5392 if (m_pPlayer->IsPlaying() && (percent >= 0.0))
5394 if (!m_pPlayer->CanSeek()) return;
5395 if (m_itemCurrentFile->IsStack() && m_currentStack->Size() > 0)
5396 SeekTime(percent * 0.01 * GetTotalTime());
5398 m_pPlayer->SeekPercentage(percent);
5402 // SwitchToFullScreen() returns true if a switch is made, else returns false
5403 bool CApplication::SwitchToFullScreen()
5405 // if playing from the video info window, close it first!
5406 if (g_windowManager.HasModalDialog() && g_windowManager.GetTopMostModalDialogID() == WINDOW_DIALOG_VIDEO_INFO)
5408 CGUIDialogVideoInfo* pDialog = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
5409 if (pDialog) pDialog->Close(true);
5412 // don't switch if there is a dialog on screen or the slideshow is active
5413 if (/*g_windowManager.HasModalDialog() ||*/ g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW)
5416 // See if we're playing a video, and are in GUI mode
5417 if ( m_pPlayer->IsPlayingVideo() && g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO)
5419 // then switch to fullscreen mode
5420 g_windowManager.ActivateWindow(WINDOW_FULLSCREEN_VIDEO);
5423 // special case for switching between GUI & visualisation mode. (only if we're playing an audio song)
5424 if (m_pPlayer->IsPlayingAudio() && g_windowManager.GetActiveWindow() != WINDOW_VISUALISATION)
5425 { // then switch to visualisation
5426 g_windowManager.ActivateWindow(WINDOW_VISUALISATION);
5432 void CApplication::Minimize()
5434 g_Windowing.Minimize();
5437 PLAYERCOREID CApplication::GetCurrentPlayer()
5439 return m_pPlayer->GetCurrentPlayer();
5442 void CApplication::UpdateLibraries()
5444 if (CSettings::Get().GetBool("videolibrary.updateonstartup"))
5446 CLog::Log(LOGNOTICE, "%s - Starting video library startup scan", __FUNCTION__);
5450 if (CSettings::Get().GetBool("musiclibrary.updateonstartup"))
5452 CLog::Log(LOGNOTICE, "%s - Starting music library startup scan", __FUNCTION__);
5457 bool CApplication::IsVideoScanning() const
5459 return m_videoInfoScanner->IsScanning();
5462 bool CApplication::IsMusicScanning() const
5464 return m_musicInfoScanner->IsScanning();
5467 void CApplication::StopVideoScan()
5469 if (m_videoInfoScanner->IsScanning())
5470 m_videoInfoScanner->Stop();
5473 void CApplication::StopMusicScan()
5475 if (m_musicInfoScanner->IsScanning())
5476 m_musicInfoScanner->Stop();
5479 void CApplication::StartVideoCleanup()
5481 if (m_videoInfoScanner->IsScanning())
5484 m_videoInfoScanner->CleanDatabase();
5487 void CApplication::StartVideoScan(const CStdString &strDirectory, bool scanAll)
5489 if (m_videoInfoScanner->IsScanning())
5492 m_videoInfoScanner->ShowDialog(true);
5494 m_videoInfoScanner->Start(strDirectory,scanAll);
5497 void CApplication::StartMusicScan(const CStdString &strDirectory, int flags)
5499 if (m_musicInfoScanner->IsScanning())
5503 { // setup default flags
5504 if (CSettings::Get().GetBool("musiclibrary.downloadinfo"))
5505 flags |= CMusicInfoScanner::SCAN_ONLINE;
5506 if (CSettings::Get().GetBool("musiclibrary.backgroundupdate"))
5507 flags |= CMusicInfoScanner::SCAN_BACKGROUND;
5510 if (!(flags & CMusicInfoScanner::SCAN_BACKGROUND))
5511 m_musicInfoScanner->ShowDialog(true);
5513 m_musicInfoScanner->Start(strDirectory, flags);
5516 void CApplication::StartMusicAlbumScan(const CStdString& strDirectory,
5519 if (m_musicInfoScanner->IsScanning())
5522 m_musicInfoScanner->ShowDialog(true);
5524 m_musicInfoScanner->FetchAlbumInfo(strDirectory,refresh);
5527 void CApplication::StartMusicArtistScan(const CStdString& strDirectory,
5530 if (m_musicInfoScanner->IsScanning())
5533 m_musicInfoScanner->ShowDialog(true);
5535 m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
5538 void CApplication::CheckPlayingProgress()
5540 // check if we haven't rewound past the start of the file
5541 if (m_pPlayer->IsPlaying())
5543 int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
5553 if (g_infoManager.GetPlayTime() / 1000 < iPower)
5555 g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
5556 g_application.SeekTime(0);
5562 bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayList& playlist, int iPlaylist, int track)
5564 CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
5566 // initial exit conditions
5567 // no songs in playlist just return
5568 if (playlist.size() == 0)
5572 if (iPlaylist < PLAYLIST_MUSIC || iPlaylist > PLAYLIST_VIDEO)
5575 // setup correct playlist
5576 g_playlistPlayer.ClearPlaylist(iPlaylist);
5578 // if the playlist contains an internet stream, this file will be used
5579 // to generate a thumbnail for musicplayer.cover
5580 g_application.m_strPlayListFile = strPlayList;
5582 // add the items to the playlist player
5583 g_playlistPlayer.Add(iPlaylist, playlist);
5585 // if we have a playlist
5586 if (g_playlistPlayer.GetPlaylist(iPlaylist).size())
5589 g_playlistPlayer.SetCurrentPlaylist(iPlaylist);
5590 g_playlistPlayer.Reset();
5591 g_playlistPlayer.Play(track);
5597 void CApplication::SaveCurrentFileSettings()
5599 // don't store settings for PVR in video database
5600 if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel())
5602 // save video settings
5603 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
5607 dbs.SetVideoSettings(m_itemCurrentFile->GetPath(), CMediaSettings::Get().GetCurrentVideoSettings());
5611 else if (m_itemCurrentFile->IsPVRChannel())
5613 g_PVRManager.SaveCurrentChannelSettings();
5617 bool CApplication::AlwaysProcess(const CAction& action)
5619 // check if this button is mapped to a built-in function
5620 if (!action.GetName().IsEmpty())
5622 CStdString builtInFunction;
5623 vector<CStdString> params;
5624 CUtil::SplitExecFunction(action.GetName(), builtInFunction, params);
5625 builtInFunction.ToLower();
5627 // should this button be handled normally or just cancel the screensaver?
5628 if ( builtInFunction.Equals("powerdown")
5629 || builtInFunction.Equals("reboot")
5630 || builtInFunction.Equals("restart")
5631 || builtInFunction.Equals("restartapp")
5632 || builtInFunction.Equals("suspend")
5633 || builtInFunction.Equals("hibernate")
5634 || builtInFunction.Equals("quit")
5635 || builtInFunction.Equals("shutdown"))
5644 bool CApplication::IsCurrentThread() const
5646 return CThread::IsCurrentThread(m_threadID);
5649 void CApplication::SetRenderGUI(bool renderGUI)
5651 if (renderGUI && ! m_renderGUI)
5652 g_windowManager.MarkDirty();
5653 m_renderGUI = renderGUI;
5656 CNetwork& CApplication::getNetwork()
5660 #ifdef HAS_PERFORMANCE_SAMPLE
5661 CPerformanceStats &CApplication::GetPerformanceStats()
5667 bool CApplication::SetLanguage(const CStdString &strLanguage)
5669 CStdString strPreviousLanguage = CSettings::Get().GetString("locale.language");
5670 CStdString strNewLanguage = strLanguage;
5671 if (strNewLanguage != strPreviousLanguage)
5673 CStdString strLangInfoPath;
5674 strLangInfoPath.Format("special://xbmc/language/%s/langinfo.xml", strNewLanguage.c_str());
5675 if (!g_langInfo.Load(strLangInfoPath))
5678 if (g_langInfo.ForceUnicodeFont() && !g_fontManager.IsFontSetUnicode())
5680 CLog::Log(LOGINFO, "Language needs a ttf font, loading first ttf font available");
5681 CStdString strFontSet;
5682 if (g_fontManager.GetFirstFontSetUnicode(strFontSet))
5683 strNewLanguage = strFontSet;
5685 CLog::Log(LOGERROR, "No ttf font found but needed: %s", strFontSet.c_str());
5687 CSettings::Get().SetString("locale.language", strNewLanguage);
5689 g_charsetConverter.reset();
5691 if (!g_localizeStrings.Load("special://xbmc/language/", strNewLanguage))
5694 // also tell our weather and skin to reload as these are localized
5695 g_weatherManager.Refresh();
5696 g_PVRManager.LocalizationChanged();
5703 void CApplication::CloseNetworkShares()
5705 CLog::Log(LOGDEBUG,"CApplication::CloseNetworkShares: Closing all network shares");
5707 #if defined(HAS_FILESYSTEM_SMB) && !defined(TARGET_WINDOWS)
5711 #ifdef HAS_FILESYSTEM_NFS
5712 gNfsConnection.Deinit();
5715 #ifdef HAS_FILESYSTEM_AFP
5716 gAfpConnection.Deinit();
5719 #ifdef HAS_FILESYSTEM_SFTP
5720 CSFTPSessionManager::DisconnectAllSessions();