1 /* 2 * Copyright (C) 2005-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 #include "XBApplicationEx.h" 12 13 #include "guilib/IMsgTargetCallback.h" 14 #include "windowing/Resolution.h" 15 #include "utils/GlobalsHandling.h" 16 #include "messaging/IMessageTarget.h" 17 #include "ServiceManager.h" 18 #include "ApplicationStackHelper.h" 19 20 #include <atomic> 21 #include <deque> 22 #include <map> 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include "cores/IPlayerCallback.h" 28 #include "settings/lib/ISettingsHandler.h" 29 #include "settings/lib/ISettingCallback.h" 30 #include "settings/ISubSettings.h" 31 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE) 32 #include "storage/DetectDVDType.h" 33 #endif 34 #ifdef TARGET_WINDOWS 35 #include "powermanagement/WinIdleTimer.h" 36 #endif 37 #include "utils/Stopwatch.h" 38 #include "windowing/OSScreenSaver.h" 39 #include "windowing/XBMC_events.h" 40 #include "threads/SystemClock.h" 41 #include "threads/Thread.h" 42 43 #include "ApplicationPlayer.h" 44 45 class CAction; 46 class CFileItem; 47 class CFileItemList; 48 class CKey; 49 class CSeekHandler; 50 class CInertialScrollingHandler; 51 class CSplash; 52 class CBookmark; 53 class IActionListener; 54 class CGUIComponent; 55 class CAppInboundProtocol; 56 class CSettingsComponent; 57 58 namespace ADDON 59 { 60 class CSkinInfo; 61 class IAddon; 62 typedef std::shared_ptr<IAddon> AddonPtr; 63 } 64 65 namespace ANNOUNCEMENT 66 { 67 class CAnnouncementManager; 68 } 69 70 namespace MEDIA_DETECT 71 { 72 class CAutorun; 73 } 74 75 namespace PLAYLIST 76 { 77 class CPlayList; 78 } 79 80 namespace ActiveAE 81 { 82 class CActiveAE; 83 } 84 85 namespace VIDEO 86 { 87 class CVideoInfoScanner; 88 } 89 90 namespace MUSIC_INFO 91 { 92 class CMusicInfoScanner; 93 } 94 95 #define VOLUME_MINIMUM 0.0f // -60dB 96 #define VOLUME_MAXIMUM 1.0f // 0dB 97 #define VOLUME_DYNAMIC_RANGE 90.0f // 60dB 98 99 // replay gain settings struct for quick access by the player multiple 100 // times per second (saves doing settings lookup) 101 struct ReplayGainSettings 102 { 103 int iPreAmp; 104 int iNoGainPreAmp; 105 int iType; 106 bool bAvoidClipping; 107 }; 108 109 enum StartupAction 110 { 111 STARTUP_ACTION_NONE = 0, 112 STARTUP_ACTION_PLAY_TV, 113 STARTUP_ACTION_PLAY_RADIO 114 }; 115 116 class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMsgTargetCallback, 117 public ISettingCallback, public ISettingsHandler, public ISubSettings, 118 public KODI::MESSAGING::IMessageTarget 119 { 120 friend class CAppInboundProtocol; 121 122 public: 123 124 // If playback time of current item is greater than this value, ACTION_PREV_ITEM will seek to start 125 // of currently playing item, otherwise it will seek to start of the previous item in playlist 126 static const unsigned int ACTION_PREV_ITEM_THRESHOLD = 3; // seconds; 127 128 enum ESERVERS 129 { 130 ES_WEBSERVER = 1, 131 ES_AIRPLAYSERVER, 132 ES_JSONRPCSERVER, 133 ES_UPNPRENDERER, 134 ES_UPNPSERVER, 135 ES_EVENTSERVER, 136 ES_ZEROCONF 137 }; 138 139 CApplication(void); 140 ~CApplication(void) override; 141 bool Initialize() override; 142 void FrameMove(bool processEvents, bool processGUI = true) override; 143 void Render() override; 144 virtual void Preflight(); 145 bool Create(const CAppParamParser ¶ms); 146 bool Cleanup() override; 147 IsInitialized()148 bool IsInitialized() const { return !m_bInitializing; } IsStopping()149 bool IsStopping() const { return m_bStop; } 150 151 bool CreateGUI(); 152 bool InitWindow(RESOLUTION res = RES_INVALID); 153 void StartServices(); 154 void StopServices(); 155 156 bool StartServer(enum ESERVERS eServer, bool bStart, bool bWait = false); 157 158 bool IsCurrentThread() const; 159 void Stop(int exitCode); 160 void UnloadSkin(); 161 bool LoadCustomWindows(); 162 void ReloadSkin(bool confirm = false); 163 const std::string& CurrentFile(); 164 CFileItem& CurrentFileItem(); 165 std::shared_ptr<CFileItem> CurrentFileItemPtr(); 166 CFileItem& CurrentUnstackedItem(); 167 bool OnMessage(CGUIMessage& message) override; 168 CApplicationPlayer& GetAppPlayer(); 169 std::string GetCurrentPlayer(); 170 CApplicationStackHelper& GetAppStackHelper(); 171 void OnPlayBackEnded() override; 172 void OnPlayBackStarted(const CFileItem &file) override; 173 void OnPlayerCloseFile(const CFileItem &file, const CBookmark &bookmark) override; 174 void OnPlayBackPaused() override; 175 void OnPlayBackResumed() override; 176 void OnPlayBackStopped() override; 177 void OnPlayBackError() override; 178 void OnQueueNextItem() override; 179 void OnPlayBackSeek(int64_t iTime, int64_t seekOffset) override; 180 void OnPlayBackSeekChapter(int iChapter) override; 181 void OnPlayBackSpeedChanged(int iSpeed) override; 182 void OnAVChange() override; 183 void OnAVStarted(const CFileItem &file) override; 184 void RequestVideoSettings(const CFileItem &fileItem) override; 185 void StoreVideoSettings(const CFileItem &fileItem, CVideoSettings vs) override; 186 187 int GetMessageMask() override; 188 void OnApplicationMessage(KODI::MESSAGING::ThreadMessage* pMsg) override; 189 190 bool PlayMedia(CFileItem& item, const std::string &player, int iPlaylist); 191 bool ProcessAndStartPlaylist(const std::string& strPlayList, PLAYLIST::CPlayList& playlist, int iPlaylist, int track=0); 192 bool PlayFile(CFileItem item, const std::string& player, bool bRestart = false); 193 void StopPlaying(); 194 void Restart(bool bSamePosition = true); 195 void DelayedPlayerRestart(); 196 void CheckDelayedPlayerRestart(); 197 bool IsPlayingFullScreenVideo() const; 198 bool IsFullScreen(); 199 bool OnAction(const CAction &action); 200 void CheckShutdown(); 201 void InhibitIdleShutdown(bool inhibit); 202 bool IsIdleShutdownInhibited() const; 203 void InhibitScreenSaver(bool inhibit); 204 bool IsScreenSaverInhibited() const; 205 // Checks whether the screensaver and / or DPMS should become active. 206 void CheckScreenSaverAndDPMS(); 207 void ActivateScreenSaver(bool forceType = false); 208 void CloseNetworkShares(); 209 210 void ConfigureAndEnableAddons(); 211 void ShowAppMigrationMessage(); 212 void Process() override; 213 void ProcessSlow(); 214 void ResetScreenSaver(); 215 float GetVolumePercent() const; 216 float GetVolumeRatio() const; 217 void SetVolume(float iValue, bool isPercentage = true); 218 bool IsMuted() const; IsMutedInternal()219 bool IsMutedInternal() const { return m_muted; } 220 void ToggleMute(void); 221 void SetMute(bool mute); 222 void ShowVolumeBar(const CAction *action = NULL); 223 int GetSubtitleDelay(); 224 int GetAudioDelay(); 225 void ResetSystemIdleTimer(); 226 void ResetScreenSaverTimer(); 227 void StopScreenSaverTimer(); 228 // Wakes up from the screensaver and / or DPMS. Returns true if woken up. 229 bool WakeUpScreenSaverAndDPMS(bool bPowerOffKeyPressed = false); 230 bool WakeUpScreenSaver(bool bPowerOffKeyPressed = false); 231 /*! 232 \brief Returns the total time in fractional seconds of the currently playing media 233 234 Beware that this method returns fractional seconds whereas IPlayer::GetTotalTime() returns milliseconds. 235 */ 236 double GetTotalTime() const; 237 /*! 238 \brief Returns the current time in fractional seconds of the currently playing media 239 240 Beware that this method returns fractional seconds whereas IPlayer::GetTime() returns milliseconds. 241 */ 242 double GetTime() const; 243 float GetPercentage() const; 244 245 // Get the percentage of data currently cached/buffered (aq/vq + FileCache) from the input stream if applicable. 246 float GetCachePercentage() const; 247 248 void SeekPercentage(float percent); 249 void SeekTime( double dTime = 0.0 ); 250 251 void StopShutdownTimer(); 252 void ResetShutdownTimers(); 253 254 void StopVideoScan(); 255 void StopMusicScan(); 256 bool IsMusicScanning() const; 257 bool IsVideoScanning() const; 258 259 /*! 260 \brief Starts a video library cleanup. 261 \param userInitiated Whether the action was initiated by the user (either via GUI or any other method) or not. It is meant to hide or show dialogs. 262 \param content Content type to clean, blank for everything 263 \param strDirectory The path to clean or "" (empty string) for a global clean. 264 */ 265 void StartVideoCleanup(bool userInitiated = true, const std::string& content = "", const std::string& strDirectory = ""); 266 267 /*! 268 \brief Starts a video library update. 269 \param path The path to scan or "" (empty string) for a global scan. 270 \param userInitiated Whether the action was initiated by the user (either via GUI or any other method) or not. It is meant to hide or show dialogs. 271 \param scanAll Whether to scan everything not already scanned (regardless of whether the user normally doesn't want a folder scanned). 272 */ 273 void StartVideoScan(const std::string &path, bool userInitiated = true, bool scanAll = false); 274 275 /*! 276 \brief Starts a music library cleanup. 277 \param userInitiated Whether the action was initiated by the user (either via GUI or any other method) or not. It is meant to hide or show dialogs. 278 */ 279 void StartMusicCleanup(bool userInitiated = true); 280 281 /*! 282 \brief Starts a music library update. 283 \param path The path to scan or "" (empty string) for a global scan. 284 \param userInitiated Whether the action was initiated by the user (either via GUI or any other method) or not. It is meant to hide or show dialogs. 285 \param flags Flags for controlling the scanning process. See xbmc/music/infoscanner/MusicInfoScanner.h for possible values. 286 */ 287 void StartMusicScan(const std::string &path, bool userInitiated = true, int flags = 0); 288 void StartMusicAlbumScan(const std::string& strDirectory, bool refresh = false); 289 void StartMusicArtistScan(const std::string& strDirectory, bool refresh = false); 290 291 void UpdateLibraries(); 292 293 void UpdateCurrentPlayArt(); 294 295 bool ExecuteXBMCAction(std::string action, const CGUIListItemPtr &item = NULL); 296 297 #ifdef HAS_DVD_DRIVE 298 std::unique_ptr<MEDIA_DETECT::CAutorun> m_Autorun; 299 #endif 300 301 #if !defined(TARGET_WINDOWS) && defined(HAS_DVD_DRIVE) 302 MEDIA_DETECT::CDetectDVDMedia m_DetectDVDType; 303 #endif 304 IsInScreenSaver()305 inline bool IsInScreenSaver() { return m_screensaverActive; }; ScreensaverIdInUse()306 inline std::string ScreensaverIdInUse() { return m_screensaverIdInUse; } 307 IsDPMSActive()308 inline bool IsDPMSActive() { return m_dpmsIsActive; }; 309 int m_iScreenSaveLock = 0; // spiff: are we checking for a lock? if so, ignore the screensaver state, if -1 we have failed to input locks 310 311 std::string m_strPlayListFile; 312 313 int GlobalIdleTime(); 314 PlatformDirectoriesEnabled()315 bool PlatformDirectoriesEnabled() { return m_bPlatformDirectories; } IsStandAlone()316 bool IsStandAlone() { return m_bStandalone; } IsEnableTestMode()317 bool IsEnableTestMode() { return m_bTestMode; } 318 IsAppFocused()319 bool IsAppFocused() const { return m_AppFocused; } 320 321 void Minimize(); 322 bool ToggleDPMS(bool manual); 323 324 bool SwitchToFullScreen(bool force = false); 325 GetRenderGUI()326 bool GetRenderGUI() const override { return m_renderGUI; }; 327 328 bool SetLanguage(const std::string &strLanguage); 329 bool LoadLanguage(bool reload); 330 GetReplayGainSettings()331 ReplayGainSettings& GetReplayGainSettings() { return m_replayGainSettings; } 332 333 void SetLoggingIn(bool switchingProfiles); 334 335 /*! 336 \brief Register an action listener. 337 \param listener The listener to register 338 */ 339 void RegisterActionListener(IActionListener *listener); 340 /*! 341 \brief Unregister an action listener. 342 \param listener The listener to unregister 343 */ 344 void UnregisterActionListener(IActionListener *listener); 345 346 std::unique_ptr<CServiceManager> m_ServiceManager; 347 348 /*! 349 \brief Locks calls from outside kodi (e.g. python) until framemove is processed. 350 */ 351 void LockFrameMoveGuard(); 352 353 /*! 354 \brief Unlocks calls from outside kodi (e.g. python). 355 */ 356 void UnlockFrameMoveGuard(); 357 358 void SetRenderGUI(bool renderGUI); 359 360 protected: 361 bool OnSettingsSaving() const override; 362 bool Load(const TiXmlNode *settings) override; 363 bool Save(TiXmlNode *settings) const override; 364 void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override; 365 void OnSettingAction(const std::shared_ptr<const CSetting>& setting) override; 366 bool OnSettingUpdate(const std::shared_ptr<CSetting>& setting, 367 const char* oldSettingId, 368 const TiXmlNode* oldSettingNode) override; 369 370 bool LoadSkin(const std::string& skinID); 371 372 void CheckOSScreenSaverInhibitionSetting(); 373 void PlaybackCleanup(); 374 375 // inbound protocol 376 bool OnEvent(XBMC_Event& newEvent); 377 378 /*! 379 \brief Delegates the action to all registered action handlers. 380 \param action The action 381 \return true, if the action was taken by one of the action listener. 382 */ 383 bool NotifyActionListeners(const CAction &action) const; 384 385 std::shared_ptr<ANNOUNCEMENT::CAnnouncementManager> m_pAnnouncementManager; 386 std::unique_ptr<CSettingsComponent> m_pSettingsComponent; 387 std::unique_ptr<CGUIComponent> m_pGUI; 388 std::unique_ptr<CWinSystemBase> m_pWinSystem; 389 std::unique_ptr<ActiveAE::CActiveAE> m_pActiveAE; 390 std::shared_ptr<CAppInboundProtocol> m_pAppPort; 391 std::deque<XBMC_Event> m_portEvents; 392 CCriticalSection m_portSection; 393 394 bool m_confirmSkinChange = true; 395 bool m_ignoreSkinSettingChanges = false; 396 397 bool m_saveSkinOnUnloading = true; 398 399 #if defined(TARGET_DARWIN_IOS) 400 friend class CWinEventsIOS; 401 #endif 402 #if defined(TARGET_DARWIN_TVOS) 403 friend class CWinEventsTVOS; 404 #endif 405 #if defined(TARGET_ANDROID) 406 friend class CWinEventsAndroid; 407 #endif 408 // screensaver 409 bool m_screensaverActive = false; 410 std::string m_screensaverIdInUse; 411 ADDON::AddonPtr m_pythonScreenSaver; // @warning: Fallback for Python interface, for binaries not needed! 412 // OS screen saver inhibitor that is always active if user selected a Kodi screen saver 413 KODI::WINDOWING::COSScreenSaverInhibitor m_globalScreensaverInhibitor; 414 // Inhibitor that is active e.g. during video playback 415 KODI::WINDOWING::COSScreenSaverInhibitor m_screensaverInhibitor; 416 417 // timer information 418 #ifdef TARGET_WINDOWS 419 CWinIdleTimer m_idleTimer; 420 CWinIdleTimer m_screenSaverTimer; 421 #else 422 CStopWatch m_idleTimer; 423 CStopWatch m_screenSaverTimer; 424 #endif 425 CStopWatch m_restartPlayerTimer; 426 CStopWatch m_frameTime; 427 CStopWatch m_navigationTimer; 428 CStopWatch m_slowTimer; 429 CStopWatch m_shutdownTimer; 430 XbmcThreads::EndTime m_guiRefreshTimer; 431 432 bool m_bInhibitIdleShutdown = false; 433 bool m_bInhibitScreenSaver = false; 434 435 bool m_dpmsIsActive = false; 436 bool m_dpmsIsManual = false; 437 438 CFileItemPtr m_itemCurrentFile; 439 440 std::string m_prevMedia; 441 std::thread::id m_threadID; // application thread ID. Used in applicationMessenger to know where we are firing a thread with delay from. 442 bool m_bInitializing = true; 443 bool m_bPlatformDirectories = true; 444 445 int m_nextPlaylistItem = -1; 446 447 unsigned int m_lastRenderTime = 0; 448 bool m_skipGuiRender = false; 449 450 bool m_bStandalone = false; 451 bool m_bTestMode = false; 452 bool m_bSystemScreenSaverEnable = false; 453 454 std::unique_ptr<MUSIC_INFO::CMusicInfoScanner> m_musicInfoScanner; 455 456 bool m_muted = false; 457 float m_volumeLevel = VOLUME_MAXIMUM; 458 459 void Mute(); 460 void UnMute(); 461 462 void SetHardwareVolume(float hardwareVolume); 463 464 void VolumeChanged(); 465 466 bool PlayStack(CFileItem& item, bool bRestart); 467 468 float NavigationIdleTime(); 469 void HandlePortEvents(); 470 471 /*! \brief Helper method to determine how to handle TMSG_SHUTDOWN 472 */ 473 void HandleShutdownMessage(); 474 475 CInertialScrollingHandler *m_pInertialScrollingHandler; 476 477 ReplayGainSettings m_replayGainSettings; 478 std::vector<IActionListener *> m_actionListeners; 479 std::vector<ADDON::AddonInfoPtr> 480 m_incompatibleAddons; /*!< Result of addon migration (incompatible addon infos) */ 481 482 private: 483 void ResetCurrentItem(); 484 485 mutable CCriticalSection m_critSection; /*!< critical section for all changes to this class, except for changes to triggers */ 486 487 CCriticalSection m_frameMoveGuard; /*!< critical section for synchronizing GUI actions from inside and outside (python) */ 488 std::atomic_uint m_WaitingExternalCalls; /*!< counts threads wich are waiting to be processed in FrameMove */ 489 unsigned int m_ProcessedExternalCalls = 0; /*!< counts calls wich are processed during one "door open" cycle in FrameMove */ 490 unsigned int m_ProcessedExternalDecay = 0; /*!< counts to close door after a few frames of no python activity */ 491 CApplicationPlayer m_appPlayer; 492 CEvent m_playerEvent; 493 CApplicationStackHelper m_stackHelper; 494 std::string m_windowing; 495 }; 496 497 XBMC_GLOBAL_REF(CApplication,g_application); 498 #define g_application XBMC_GLOBAL_USE(CApplication) 499