diff options
author | Kai Sommerfeld <kai.sommerfeld@gmx.com> | 2022-09-08 10:34:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-08 10:34:53 +0200 |
commit | 95bd109ce09e2443f146d08b56ecd558216b844a (patch) | |
tree | 37182f5138395eac0cc4d07666292c3013e8c5bc | |
parent | 6686f0cd587a68c90a4567f585f04012d57481d5 (diff) | |
parent | 8a73af967e341413dc6cffc530fd8639073e47a7 (diff) |
Merge pull request #21811 from ksooo/pvr-refactor-clients-code
[PVR] Refactor PVR Clients Code
-rw-r--r-- | xbmc/pvr/PVRManager.cpp | 9 | ||||
-rw-r--r-- | xbmc/pvr/addons/CMakeLists.txt | 4 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClient.cpp | 111 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClient.h | 278 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClientCapabilities.cpp | 85 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClientCapabilities.h | 277 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClientUID.cpp | 33 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClientUID.h | 42 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClients.cpp | 336 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClients.h | 82 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroup.cpp | 5 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroups.cpp | 6 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelsPath.cpp | 14 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelsPath.h | 6 | ||||
-rw-r--r-- | xbmc/pvr/channels/test/TestPVRChannelsPath.cpp | 32 | ||||
-rw-r--r-- | xbmc/pvr/dialogs/GUIDialogPVRClientPriorities.cpp | 2 | ||||
-rw-r--r-- | xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp | 3 | ||||
-rw-r--r-- | xbmc/pvr/guilib/PVRGUIActions.cpp | 3 | ||||
-rw-r--r-- | xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp | 12 |
19 files changed, 716 insertions, 624 deletions
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp index 20d90d480a..35ced6e03a 100644 --- a/xbmc/pvr/PVRManager.cpp +++ b/xbmc/pvr/PVRManager.cpp @@ -304,11 +304,7 @@ std::shared_ptr<CPVRClient> CPVRManager::GetClient(const CFileItem& item) const std::shared_ptr<CPVRClient> CPVRManager::GetClient(int iClientId) const { - std::shared_ptr<CPVRClient> client; - if (iClientId != PVR_INVALID_CLIENT_ID) - m_addons->GetCreatedClient(iClientId, client); - - return client; + return m_addons->GetCreatedClient(iClientId); } std::shared_ptr<CPVRGUIActions> CPVRManager::GUIActions() const @@ -682,8 +678,7 @@ bool CPVRManager::UpdateComponents(ManagerState stateToCheck, const std::unique_ptr<CPVRGUIProgressHandler>& progressHandler) { // find clients which appeared since last check and update them - CPVRClientMap clientMap; - m_addons->GetCreatedClients(clientMap); + const CPVRClientMap clientMap = m_addons->GetCreatedClients(); if (clientMap.empty()) { CLog::LogFC(LOGDEBUG, LOGPVR, "All created PVR clients gone!"); diff --git a/xbmc/pvr/addons/CMakeLists.txt b/xbmc/pvr/addons/CMakeLists.txt index 67d6b8445e..e8a0a5129e 100644 --- a/xbmc/pvr/addons/CMakeLists.txt +++ b/xbmc/pvr/addons/CMakeLists.txt @@ -1,9 +1,13 @@ set(SOURCES PVRClient.cpp + PVRClientCapabilities.cpp PVRClientMenuHooks.cpp + PVRClientUID.cpp PVRClients.cpp) set(HEADERS PVRClient.h + PVRClientCapabilities.h PVRClientMenuHooks.h + PVRClientUID.h PVRClients.h) core_add_library(pvr_addons) diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp index c3aff4f636..31328c0693 100644 --- a/xbmc/pvr/addons/PVRClient.cpp +++ b/xbmc/pvr/addons/PVRClient.cpp @@ -9,9 +9,9 @@ #include "PVRClient.h" #include "ServiceBroker.h" -#include "addons/kodi-dev-kit/include/kodi/addon-instance/PVR.h" // added for compile test on related sources only! +#include "addons/AddonManager.h" #include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h" -#include "dialogs/GUIDialogKaiToast.h" +#include "dialogs/GUIDialogKaiToast.h" //! @todo get rid of GUI in core #include "events/EventLog.h" #include "events/NotificationEvent.h" #include "filesystem/SpecialProtocol.h" @@ -42,8 +42,6 @@ #include "utils/StringUtils.h" #include "utils/log.h" -#include <algorithm> -#include <iterator> #include <map> #include <memory> #include <mutex> @@ -62,8 +60,10 @@ namespace PVR #define DEFAULT_INFO_STRING_VALUE "unknown" -CPVRClient::CPVRClient(const ADDON::AddonInfoPtr& addonInfo, ADDON::AddonInstanceId instanceId) - : IAddonInstanceHandler(ADDON_INSTANCE_PVR, addonInfo, instanceId) +CPVRClient::CPVRClient(const ADDON::AddonInfoPtr& addonInfo, + ADDON::AddonInstanceId instanceId, + int clientId) + : IAddonInstanceHandler(ADDON_INSTANCE_PVR, addonInfo, instanceId), m_iClientId(clientId) { // Create all interface parts independent to make API changes easier if // something is added @@ -92,7 +92,7 @@ void CPVRClient::StopRunningInstance() { // stop the pvr manager and stop and unload the running pvr addon. pvr manager will be restarted on demand. CServiceBroker::GetPVRManager().Stop(); - CServiceBroker::GetPVRManager().Clients()->StopClient(ID(), InstanceId(), false); + CServiceBroker::GetPVRManager().Clients()->StopClient(m_iClientId, false); } void CPVRClient::OnPreInstall() @@ -106,7 +106,7 @@ void CPVRClient::OnPreUnInstall() StopRunningInstance(); } -void CPVRClient::ResetProperties(int iClientId /* = PVR_INVALID_CLIENT_ID */) +void CPVRClient::ResetProperties() { std::unique_lock<CCriticalSection> lock(m_critSection); @@ -120,7 +120,6 @@ void CPVRClient::ResetProperties(int iClientId /* = PVR_INVALID_CLIENT_ID */) m_connectionState = PVR_CONNECTION_STATE_UNKNOWN; m_prevConnectionState = PVR_CONNECTION_STATE_UNKNOWN; m_ignoreClient = false; - m_iClientId = iClientId; m_iPriority = 0; m_bPriorityFetched = false; m_strBackendVersion = DEFAULT_INFO_STRING_VALUE; @@ -165,13 +164,11 @@ void CPVRClient::ResetProperties(int iClientId /* = PVR_INVALID_CLIENT_ID */) memset(m_ifc.pvr->toAddon, 0, sizeof(KodiToAddonFuncTable_PVR)); } -ADDON_STATUS CPVRClient::Create(int iClientId) +ADDON_STATUS CPVRClient::Create() { ADDON_STATUS status(ADDON_STATUS_UNKNOWN); - if (iClientId <= PVR_INVALID_CLIENT_ID) - return status; - ResetProperties(iClientId); + ResetProperties(); /* initialise the add-on */ CLog::LogFC(LOGDEBUG, LOGPVR, "Creating PVR add-on instance '{}'", ID()); @@ -222,11 +219,8 @@ void CPVRClient::Continue() void CPVRClient::ReCreate() { - int iClientID(m_iClientId); Destroy(); - - /* recreate the instance */ - Create(iClientID); + Create(); } bool CPVRClient::ReadyToUse() const @@ -273,6 +267,21 @@ bool CPVRClient::IgnoreClient() const return m_ignoreClient; } +bool CPVRClient::IsEnabled() const +{ + if (InstanceId() == ADDON_SINGLETON_INSTANCE_ID) + { + return !CServiceBroker::GetAddonMgr().IsAddonDisabled(ID()); + } + else + { + bool instanceEnabled{false}; + Addon()->ReloadSettings(InstanceId()); + Addon()->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, instanceEnabled, InstanceId()); + return instanceEnabled; + } +} + int CPVRClient::GetID() const { return m_iClientId; @@ -2134,72 +2143,4 @@ PVR_CODEC CPVRClient::cb_get_codec_by_name(const void* kodiInstance, const char* return result; } -CPVRClientCapabilities::CPVRClientCapabilities(const CPVRClientCapabilities& other) -{ - if (other.m_addonCapabilities) - m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(*other.m_addonCapabilities)); - InitRecordingsLifetimeValues(); -} - -const CPVRClientCapabilities& CPVRClientCapabilities::operator=(const CPVRClientCapabilities& other) -{ - if (other.m_addonCapabilities) - m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(*other.m_addonCapabilities)); - InitRecordingsLifetimeValues(); - return *this; -} - -const CPVRClientCapabilities& CPVRClientCapabilities::operator=( - const PVR_ADDON_CAPABILITIES& addonCapabilities) -{ - m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(addonCapabilities)); - InitRecordingsLifetimeValues(); - return *this; -} - -void CPVRClientCapabilities::clear() -{ - m_recordingsLifetimeValues.clear(); - m_addonCapabilities.reset(); -} - -void CPVRClientCapabilities::InitRecordingsLifetimeValues() -{ - m_recordingsLifetimeValues.clear(); - if (m_addonCapabilities && m_addonCapabilities->iRecordingsLifetimesSize > 0) - { - for (unsigned int i = 0; i < m_addonCapabilities->iRecordingsLifetimesSize; ++i) - { - int iValue = m_addonCapabilities->recordingsLifetimeValues[i].iValue; - std::string strDescr(m_addonCapabilities->recordingsLifetimeValues[i].strDescription); - if (strDescr.empty()) - { - // No description given by addon. Create one from value. - strDescr = std::to_string(iValue); - } - m_recordingsLifetimeValues.emplace_back(strDescr, iValue); - } - } - else if (SupportsRecordingsLifetimeChange()) - { - // No values given by addon, but lifetime supported. Use default values 1..365 - for (int i = 1; i < 366; ++i) - { - m_recordingsLifetimeValues.emplace_back(StringUtils::Format(g_localizeStrings.Get(17999), i), - i); // "{} days" - } - } - else - { - // No lifetime supported. - } -} - -void CPVRClientCapabilities::GetRecordingsLifetimeValues( - std::vector<std::pair<std::string, int>>& list) const -{ - std::copy(m_recordingsLifetimeValues.cbegin(), m_recordingsLifetimeValues.cend(), - std::back_inserter(list)); -} - } // namespace PVR diff --git a/xbmc/pvr/addons/PVRClient.h b/xbmc/pvr/addons/PVRClient.h index 572d505272..ef411657e7 100644 --- a/xbmc/pvr/addons/PVRClient.h +++ b/xbmc/pvr/addons/PVRClient.h @@ -10,6 +10,7 @@ #include "addons/binary-addons/AddonInstanceHandler.h" #include "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr.h" +#include "pvr/addons/PVRClientCapabilities.h" #include "threads/Event.h" #include <atomic> @@ -41,262 +42,6 @@ class CPVRTimersContainer; #define PVR_INVALID_CLIENT_ID (-2) -class CPVRClientCapabilities -{ -public: - CPVRClientCapabilities() = default; - virtual ~CPVRClientCapabilities() = default; - - CPVRClientCapabilities(const CPVRClientCapabilities& other); - const CPVRClientCapabilities& operator=(const CPVRClientCapabilities& other); - - const CPVRClientCapabilities& operator=(const PVR_ADDON_CAPABILITIES& addonCapabilities); - - void clear(); - - ///////////////////////////////////////////////////////////////////////////////// - // - // Channels - // - ///////////////////////////////////////////////////////////////////////////////// - - /*! - * @brief Check whether this add-on supports TV channels. - * @return True if supported, false otherwise. - */ - bool SupportsTV() const { return m_addonCapabilities && m_addonCapabilities->bSupportsTV; } - - /*! - * @brief Check whether this add-on supports radio channels. - * @return True if supported, false otherwise. - */ - bool SupportsRadio() const { return m_addonCapabilities && m_addonCapabilities->bSupportsRadio; } - - /*! - * @brief Check whether this add-on supports providers. - * @return True if supported, false otherwise. - */ - bool SupportsProviders() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsProviders; - } - - /*! - * @brief Check whether this add-on supports channel groups. - * @return True if supported, false otherwise. - */ - bool SupportsChannelGroups() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsChannelGroups; - } - - /*! - * @brief Check whether this add-on supports scanning for new channels on the backend. - * @return True if supported, false otherwise. - */ - bool SupportsChannelScan() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsChannelScan; - } - - /*! - * @brief Check whether this add-on supports the following functions: - * DeleteChannel, RenameChannel, DialogChannelSettings and DialogAddChannel. - * - * @return True if supported, false otherwise. - */ - bool SupportsChannelSettings() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsChannelSettings; - } - - /*! - * @brief Check whether this add-on supports descramble information for playing channels. - * @return True if supported, false otherwise. - */ - bool SupportsDescrambleInfo() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsDescrambleInfo; - } - - ///////////////////////////////////////////////////////////////////////////////// - // - // EPG - // - ///////////////////////////////////////////////////////////////////////////////// - - /*! - * @brief Check whether this add-on provides EPG information. - * @return True if supported, false otherwise. - */ - bool SupportsEPG() const { return m_addonCapabilities && m_addonCapabilities->bSupportsEPG; } - - /*! - * @brief Check whether this add-on supports asynchronous transfer of epg events. - * @return True if supported, false otherwise. - */ - bool SupportsAsyncEPGTransfer() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsAsyncEPGTransfer; - } - - ///////////////////////////////////////////////////////////////////////////////// - // - // Timers - // - ///////////////////////////////////////////////////////////////////////////////// - - /*! - * @brief Check whether this add-on supports the creation and editing of timers. - * @return True if supported, false otherwise. - */ - bool SupportsTimers() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsTimers; - } - - ///////////////////////////////////////////////////////////////////////////////// - // - // Recordings - // - ///////////////////////////////////////////////////////////////////////////////// - - /*! - * @brief Check whether this add-on supports recordings. - * @return True if supported, false otherwise. - */ - bool SupportsRecordings() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings; - } - - /*! - * @brief Check whether this add-on supports undelete of deleted recordings. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsUndelete() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingsUndelete; - } - - /*! - * @brief Check whether this add-on supports play count for recordings. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsPlayCount() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingPlayCount; - } - - /*! - * @brief Check whether this add-on supports store/retrieve of last played position for recordings.. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsLastPlayedPosition() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsLastPlayedPosition; - } - - /*! - * @brief Check whether this add-on supports retrieving an edit decision list for recordings. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsEdl() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingEdl; - } - - /*! - * @brief Check whether this add-on supports retrieving an edit decision list for epg tags. - * @return True if supported, false otherwise. - */ - bool SupportsEpgTagEdl() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsEPG && - m_addonCapabilities->bSupportsEPGEdl; - } - - /*! - * @brief Check whether this add-on supports renaming recordings.. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsRename() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingsRename; - } - - /*! - * @brief Check whether this add-on supports changing lifetime of recording. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsLifetimeChange() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingsLifetimeChange; - } - - /*! - * @brief Obtain a list with all possible values for recordings lifetime. - * @param list out, the list with the values or an empty list, if lifetime is not supported. - */ - void GetRecordingsLifetimeValues(std::vector<std::pair<std::string, int>>& list) const; - - /*! - * @brief Check whether this add-on supports retrieving the size recordings.. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsSize() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingSize; - } - - /*! - * @brief Check whether this add-on supports deleting recordings. - * @return True if supported, false otherwise. - */ - bool SupportsRecordingsDelete() const - { - return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && - m_addonCapabilities->bSupportsRecordingsDelete; - } - - ///////////////////////////////////////////////////////////////////////////////// - // - // Streams - // - ///////////////////////////////////////////////////////////////////////////////// - - /*! - * @brief Check whether this add-on provides an input stream. false if Kodi handles the stream. - * @return True if supported, false otherwise. - */ - bool HandlesInputStream() const - { - return m_addonCapabilities && m_addonCapabilities->bHandlesInputStream; - } - - /*! - * @brief Check whether this add-on demultiplexes packets. - * @return True if supported, false otherwise. - */ - bool HandlesDemuxing() const - { - return m_addonCapabilities && m_addonCapabilities->bHandlesDemuxing; - } - -private: - void InitRecordingsLifetimeValues(); - - std::unique_ptr<PVR_ADDON_CAPABILITIES> m_addonCapabilities; - std::vector<std::pair<std::string, int>> m_recordingsLifetimeValues; -}; - /*! * Interface from Kodi to a PVR add-on. * @@ -305,7 +50,7 @@ private: class CPVRClient : public ADDON::IAddonInstanceHandler { public: - CPVRClient(const ADDON::AddonInfoPtr& addonInfo, ADDON::AddonInstanceId instanceId); + CPVRClient(const ADDON::AddonInfoPtr& addonInfo, ADDON::AddonInstanceId instanceId, int clientId); ~CPVRClient() override; void OnPreInstall() override; @@ -316,9 +61,8 @@ public: /*! * @brief Initialise the instance of this add-on. - * @param iClientId The ID of this add-on. */ - ADDON_STATUS Create(int iClientId); + ADDON_STATUS Create(); /*! * @brief Stop this add-on instance. No more client add-on access after this call. @@ -364,12 +108,18 @@ public: PVR_CONNECTION_STATE GetPreviousConnectionState() const; /*! - * @brief signal to PVRManager this client should be ignored - * @return true if this client should be ignored + * @brief Check whether this client should be ignored. + * @return True if this client should be ignored, false otherwise. */ bool IgnoreClient() const; /*! + * @brief Check whether this client is enabled, according to its instance/add-on configuration. + * @return True if this client is enabled, false otherwise. + */ + bool IsEnabled() const; + + /*! * @return The ID of this instance. */ int GetID() const; @@ -1039,9 +789,9 @@ public: private: /*! - * @brief Resets all class members to their defaults. Called by the constructors. + * @brief Resets all class members to their defaults, accept the client id. */ - void ResetProperties(int iClientId = PVR_INVALID_CLIENT_ID); + void ResetProperties(); /*! * @brief reads the client's properties. @@ -1303,6 +1053,7 @@ private: static PVR_CODEC cb_get_codec_by_name(const void* kodiInstance, const char* strCodecName); //@} + const int m_iClientId; /*!< unique ID of the client */ std::atomic<bool> m_bReadyToUse; /*!< true if this add-on is initialised (ADDON_Create returned true), false otherwise */ std::atomic<bool> m_bBlockAddonCalls; /*!< true if no add-on API calls are allowed */ @@ -1314,7 +1065,6 @@ private: m_ignoreClient; /*!< signals to PVRManager to ignore this client until it has been connected */ std::vector<std::shared_ptr<CPVRTimerType>> m_timertypes; /*!< timer types supported by this backend */ - int m_iClientId; /*!< unique ID of the client */ mutable int m_iPriority; /*!< priority of the client */ mutable bool m_bPriorityFetched; diff --git a/xbmc/pvr/addons/PVRClientCapabilities.cpp b/xbmc/pvr/addons/PVRClientCapabilities.cpp new file mode 100644 index 0000000000..8650465ce8 --- /dev/null +++ b/xbmc/pvr/addons/PVRClientCapabilities.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "PVRClientCapabilities.h" + +#include "guilib/LocalizeStrings.h" +#include "utils/StringUtils.h" + +#include <algorithm> +#include <iterator> + +using namespace PVR; + +CPVRClientCapabilities::CPVRClientCapabilities(const CPVRClientCapabilities& other) +{ + if (other.m_addonCapabilities) + m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(*other.m_addonCapabilities)); + InitRecordingsLifetimeValues(); +} + +const CPVRClientCapabilities& CPVRClientCapabilities::operator=(const CPVRClientCapabilities& other) +{ + if (other.m_addonCapabilities) + m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(*other.m_addonCapabilities)); + InitRecordingsLifetimeValues(); + return *this; +} + +const CPVRClientCapabilities& CPVRClientCapabilities::operator=( + const PVR_ADDON_CAPABILITIES& addonCapabilities) +{ + m_addonCapabilities.reset(new PVR_ADDON_CAPABILITIES(addonCapabilities)); + InitRecordingsLifetimeValues(); + return *this; +} + +void CPVRClientCapabilities::clear() +{ + m_recordingsLifetimeValues.clear(); + m_addonCapabilities.reset(); +} + +void CPVRClientCapabilities::InitRecordingsLifetimeValues() +{ + m_recordingsLifetimeValues.clear(); + if (m_addonCapabilities && m_addonCapabilities->iRecordingsLifetimesSize > 0) + { + for (unsigned int i = 0; i < m_addonCapabilities->iRecordingsLifetimesSize; ++i) + { + int iValue = m_addonCapabilities->recordingsLifetimeValues[i].iValue; + std::string strDescr(m_addonCapabilities->recordingsLifetimeValues[i].strDescription); + if (strDescr.empty()) + { + // No description given by addon. Create one from value. + strDescr = std::to_string(iValue); + } + m_recordingsLifetimeValues.emplace_back(strDescr, iValue); + } + } + else if (SupportsRecordingsLifetimeChange()) + { + // No values given by addon, but lifetime supported. Use default values 1..365 + for (int i = 1; i < 366; ++i) + { + m_recordingsLifetimeValues.emplace_back(StringUtils::Format(g_localizeStrings.Get(17999), i), + i); // "{} days" + } + } + else + { + // No lifetime supported. + } +} + +void CPVRClientCapabilities::GetRecordingsLifetimeValues( + std::vector<std::pair<std::string, int>>& list) const +{ + std::copy(m_recordingsLifetimeValues.cbegin(), m_recordingsLifetimeValues.cend(), + std::back_inserter(list)); +} diff --git a/xbmc/pvr/addons/PVRClientCapabilities.h b/xbmc/pvr/addons/PVRClientCapabilities.h new file mode 100644 index 0000000000..edf20900a0 --- /dev/null +++ b/xbmc/pvr/addons/PVRClientCapabilities.h @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr.h" + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace PVR +{ + +class CPVRClientCapabilities +{ +public: + CPVRClientCapabilities() = default; + virtual ~CPVRClientCapabilities() = default; + + CPVRClientCapabilities(const CPVRClientCapabilities& other); + const CPVRClientCapabilities& operator=(const CPVRClientCapabilities& other); + + const CPVRClientCapabilities& operator=(const PVR_ADDON_CAPABILITIES& addonCapabilities); + + void clear(); + + ///////////////////////////////////////////////////////////////////////////////// + // + // Channels + // + ///////////////////////////////////////////////////////////////////////////////// + + /*! + * @brief Check whether this add-on supports TV channels. + * @return True if supported, false otherwise. + */ + bool SupportsTV() const { return m_addonCapabilities && m_addonCapabilities->bSupportsTV; } + + /*! + * @brief Check whether this add-on supports radio channels. + * @return True if supported, false otherwise. + */ + bool SupportsRadio() const { return m_addonCapabilities && m_addonCapabilities->bSupportsRadio; } + + /*! + * @brief Check whether this add-on supports providers. + * @return True if supported, false otherwise. + */ + bool SupportsProviders() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsProviders; + } + + /*! + * @brief Check whether this add-on supports channel groups. + * @return True if supported, false otherwise. + */ + bool SupportsChannelGroups() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsChannelGroups; + } + + /*! + * @brief Check whether this add-on supports scanning for new channels on the backend. + * @return True if supported, false otherwise. + */ + bool SupportsChannelScan() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsChannelScan; + } + + /*! + * @brief Check whether this add-on supports the following functions: + * DeleteChannel, RenameChannel, DialogChannelSettings and DialogAddChannel. + * + * @return True if supported, false otherwise. + */ + bool SupportsChannelSettings() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsChannelSettings; + } + + /*! + * @brief Check whether this add-on supports descramble information for playing channels. + * @return True if supported, false otherwise. + */ + bool SupportsDescrambleInfo() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsDescrambleInfo; + } + + ///////////////////////////////////////////////////////////////////////////////// + // + // EPG + // + ///////////////////////////////////////////////////////////////////////////////// + + /*! + * @brief Check whether this add-on provides EPG information. + * @return True if supported, false otherwise. + */ + bool SupportsEPG() const { return m_addonCapabilities && m_addonCapabilities->bSupportsEPG; } + + /*! + * @brief Check whether this add-on supports asynchronous transfer of epg events. + * @return True if supported, false otherwise. + */ + bool SupportsAsyncEPGTransfer() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsAsyncEPGTransfer; + } + + ///////////////////////////////////////////////////////////////////////////////// + // + // Timers + // + ///////////////////////////////////////////////////////////////////////////////// + + /*! + * @brief Check whether this add-on supports the creation and editing of timers. + * @return True if supported, false otherwise. + */ + bool SupportsTimers() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsTimers; + } + + ///////////////////////////////////////////////////////////////////////////////// + // + // Recordings + // + ///////////////////////////////////////////////////////////////////////////////// + + /*! + * @brief Check whether this add-on supports recordings. + * @return True if supported, false otherwise. + */ + bool SupportsRecordings() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings; + } + + /*! + * @brief Check whether this add-on supports undelete of deleted recordings. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsUndelete() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingsUndelete; + } + + /*! + * @brief Check whether this add-on supports play count for recordings. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsPlayCount() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingPlayCount; + } + + /*! + * @brief Check whether this add-on supports store/retrieve of last played position for recordings.. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsLastPlayedPosition() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsLastPlayedPosition; + } + + /*! + * @brief Check whether this add-on supports retrieving an edit decision list for recordings. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsEdl() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingEdl; + } + + /*! + * @brief Check whether this add-on supports retrieving an edit decision list for epg tags. + * @return True if supported, false otherwise. + */ + bool SupportsEpgTagEdl() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsEPG && + m_addonCapabilities->bSupportsEPGEdl; + } + + /*! + * @brief Check whether this add-on supports renaming recordings.. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsRename() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingsRename; + } + + /*! + * @brief Check whether this add-on supports changing lifetime of recording. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsLifetimeChange() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingsLifetimeChange; + } + + /*! + * @brief Obtain a list with all possible values for recordings lifetime. + * @param list out, the list with the values or an empty list, if lifetime is not supported. + */ + void GetRecordingsLifetimeValues(std::vector<std::pair<std::string, int>>& list) const; + + /*! + * @brief Check whether this add-on supports retrieving the size recordings.. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsSize() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingSize; + } + + /*! + * @brief Check whether this add-on supports deleting recordings. + * @return True if supported, false otherwise. + */ + bool SupportsRecordingsDelete() const + { + return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings && + m_addonCapabilities->bSupportsRecordingsDelete; + } + + ///////////////////////////////////////////////////////////////////////////////// + // + // Streams + // + ///////////////////////////////////////////////////////////////////////////////// + + /*! + * @brief Check whether this add-on provides an input stream. false if Kodi handles the stream. + * @return True if supported, false otherwise. + */ + bool HandlesInputStream() const + { + return m_addonCapabilities && m_addonCapabilities->bHandlesInputStream; + } + + /*! + * @brief Check whether this add-on demultiplexes packets. + * @return True if supported, false otherwise. + */ + bool HandlesDemuxing() const + { + return m_addonCapabilities && m_addonCapabilities->bHandlesDemuxing; + } + +private: + void InitRecordingsLifetimeValues(); + + std::unique_ptr<PVR_ADDON_CAPABILITIES> m_addonCapabilities; + std::vector<std::pair<std::string, int>> m_recordingsLifetimeValues; +}; + +} // namespace PVR diff --git a/xbmc/pvr/addons/PVRClientUID.cpp b/xbmc/pvr/addons/PVRClientUID.cpp new file mode 100644 index 0000000000..87883851ea --- /dev/null +++ b/xbmc/pvr/addons/PVRClientUID.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012-2022 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "PVRClientUID.h" + +#include <functional> + +using namespace PVR; + +int CPVRClientUID::GetUID() const +{ + if (!m_uidCreated) + { + std::hash<std::string> hasher; + + // Note: For database backwards compatibility reasons the hash of the first instance + // must be calculated just from the addonId, not from addonId and instanceId. + m_uid = static_cast<int>(hasher( + (m_instanceID > ADDON::ADDON_FIRST_INSTANCE_ID ? std::to_string(m_instanceID) + "@" : "") + + m_addonID)); + if (m_uid < 0) + m_uid = -m_uid; + + m_uidCreated = true; + } + + return m_uid; +} diff --git a/xbmc/pvr/addons/PVRClientUID.h b/xbmc/pvr/addons/PVRClientUID.h new file mode 100644 index 0000000000..5b5d1c0507 --- /dev/null +++ b/xbmc/pvr/addons/PVRClientUID.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012-2022 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "addons/IAddon.h" + +#include <string> + +namespace PVR +{ +class CPVRClientUID final +{ +public: + CPVRClientUID(const std::string& addonID, ADDON::AddonInstanceId instanceID) + : m_addonID(addonID), m_instanceID(instanceID) + { + } + + virtual ~CPVRClientUID() = default; + + /*! + * @brief Return the numeric UID. + * @return The numeric UID. + */ + int GetUID() const; + +private: + CPVRClientUID() = delete; + + std::string m_addonID; + ADDON::AddonInstanceId m_instanceID{ADDON::ADDON_SINGLETON_INSTANCE_ID}; + + mutable bool m_uidCreated{false}; + mutable int m_uid{0}; +}; +} // namespace PVR diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp index 121bd1df02..2af39feeea 100644 --- a/xbmc/pvr/addons/PVRClients.cpp +++ b/xbmc/pvr/addons/PVRClients.cpp @@ -15,6 +15,7 @@ #include "pvr/PVRManager.h" #include "pvr/PVRPlaybackState.h" #include "pvr/addons/PVRClient.h" +#include "pvr/addons/PVRClientUID.h" #include "pvr/channels/PVRChannelGroupInternal.h" #include "pvr/guilib/PVRGUIProgressHandler.h" #include "utils/JobManager.h" @@ -31,23 +32,6 @@ using namespace ADDON; using namespace PVR; -namespace -{ -int ClientIdFromAddonIdAndInstanceId(const std::string& addonID, ADDON::AddonInstanceId instanceID) -{ - std::hash<std::string> hasher; - - // Note: For database backwards compatibility reasons the hash of the first instance - // must be calculated just from the addonId, not from addonId and instanceId. - int iClientId = static_cast<int>( - hasher((instanceID > ADDON::ADDON_FIRST_INSTANCE_ID ? std::to_string(instanceID) + "@" : "") + - addonID)); - if (iClientId < 0) - iClientId = -iClientId; - return iClientId; -} -} // unnamed namespace - CPVRClients::CPVRClients() { CServiceBroker::GetAddonMgr().RegisterAddonMgrCallback(ADDON_PVRDLL, this); @@ -67,7 +51,7 @@ CPVRClients::~CPVRClients() void CPVRClients::Start() { - UpdateAddons(); + UpdateClients(); } void CPVRClients::Stop() @@ -88,77 +72,43 @@ void CPVRClients::Continue() } } -void CPVRClients::UpdateAddons(const std::string& changedAddonId /*= ""*/, - ADDON::AddonInstanceId changedInstanceId /*= 0*/) +void CPVRClients::UpdateClients( + const std::string& changedAddonId /* = "" */, + ADDON::AddonInstanceId changedInstanceId /* = ADDON::ADDON_SINGLETON_INSTANCE_ID */) { - std::vector<AddonInfoPtr> addons; - CServiceBroker::GetAddonMgr().GetAddonInfos(addons, false, ADDON_PVRDLL); - - if (addons.empty()) - return; - - bool bFoundChangedAddon = changedAddonId.empty(); std::vector<std::pair<AddonInfoPtr, bool>> addonsWithStatus; - for (const auto& addon : addons) - { - bool bEnabled = !CServiceBroker::GetAddonMgr().IsAddonDisabled(addon->ID()); - addonsWithStatus.emplace_back(std::make_pair(addon, bEnabled)); - - if (!bFoundChangedAddon && addon->ID() == changedAddonId) - bFoundChangedAddon = true; - } - - if (!bFoundChangedAddon) - return; // changed addon is not a known pvr client addon, so nothing to update - - addons.clear(); + if (!GetAddonsWithStatus(changedAddonId, addonsWithStatus)) + return; - std::vector<std::pair<std::shared_ptr<CPVRClient>, int>> addonsToCreate; - std::vector<std::pair<AddonInfoPtr, ADDON::AddonInstanceId>> addonsToReCreate; - std::vector<std::pair<AddonInfoPtr, ADDON::AddonInstanceId>> addonsToDestroy; + std::vector<std::shared_ptr<CPVRClient>> clientsToCreate; // client + std::vector<std::pair<int, std::string>> clientsToReCreate; // client id, addon name + std::vector<int> clientsToDestroy; // client id { std::unique_lock<CCriticalSection> lock(m_critSection); for (const auto& addonWithStatus : addonsWithStatus) { - AddonInfoPtr addon = addonWithStatus.first; - bool bEnabled = addonWithStatus.second; + const AddonInfoPtr addon = addonWithStatus.first; + const std::vector<std::pair<ADDON::AddonInstanceId, bool>> instanceIdsWithStatus = + GetInstanceIdsWithStatus(addon, addonWithStatus.second); - std::vector<std::pair<ADDON::AddonInstanceId, bool>> instanceIdsWithStatus; + for (const auto& instanceIdWithStatus : instanceIdsWithStatus) { - std::vector<ADDON::AddonInstanceId> instanceIds = addon->GetKnownInstanceIds(); - std::transform(instanceIds.cbegin(), instanceIds.cend(), - std::back_inserter(instanceIdsWithStatus), [bEnabled](const auto& id) { - return std::pair<ADDON::AddonInstanceId, bool>(id, bEnabled); - }); - if (changedInstanceId != ADDON_SINGLETON_INSTANCE_ID && changedAddonId == addon->ID() && - std::find(instanceIds.begin(), instanceIds.end(), changedInstanceId) == - instanceIds.end()) - { - // instance was removed - instanceIdsWithStatus.emplace_back( - std::pair<ADDON::AddonInstanceId, bool>(changedInstanceId, false)); - } - } - - for (const auto& instanceInfo : instanceIdsWithStatus) - { - const ADDON::AddonInstanceId instanceId = instanceInfo.first; - bool instanceEnabled = instanceInfo.second; + const ADDON::AddonInstanceId instanceId = instanceIdWithStatus.first; + bool instanceEnabled = instanceIdWithStatus.second; + const CPVRClientUID clientUID(addon->ID(), instanceId); + const int clientId = clientUID.GetUID(); - if (instanceEnabled && - (!IsKnownClient(addon->ID(), instanceId) || !IsCreatedClient(addon->ID(), instanceId))) + if (instanceEnabled && (!IsKnownClient(clientId) || !IsCreatedClient(clientId))) { - int iClientId = ClientIdFromAddonIdAndInstanceId(addon->ID(), instanceId); - std::shared_ptr<CPVRClient> client; - if (IsKnownClient(addon->ID(), instanceId)) + if (IsKnownClient(clientId)) { - GetClient(iClientId, client); + client = GetClient(clientId); } else { - client = std::make_shared<CPVRClient>(addon, instanceId); + client = std::make_shared<CPVRClient>(addon, instanceId, clientId); if (!client) { CLog::LogF(LOGERROR, "Severe error, incorrect add-on type"); @@ -168,41 +118,32 @@ void CPVRClients::UpdateAddons(const std::string& changedAddonId /*= ""*/, // determine actual enabled state of instance if (instanceId != ADDON_SINGLETON_INSTANCE_ID) - client->Addon()->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, instanceEnabled, - instanceId); + instanceEnabled = client->IsEnabled(); if (instanceEnabled) - addonsToCreate.emplace_back(std::make_pair(client, iClientId)); + clientsToCreate.emplace_back(client); else - addonsToDestroy.emplace_back(addon, instanceId); + clientsToDestroy.emplace_back(clientId); } - else if (IsCreatedClient(addon->ID(), instanceId)) + else if (IsCreatedClient(clientId)) { // determine actual enabled state of instance if (instanceEnabled && instanceId != ADDON_SINGLETON_INSTANCE_ID) { - std::shared_ptr<CPVRClient> client; - GetClient(GetClientId(addon->ID(), instanceId), client); - if (client) - { - client->Addon()->ReloadSettings(instanceId); - client->Addon()->GetSettingBool(ADDON_SETTING_INSTANCE_ENABLED_VALUE, instanceEnabled, - instanceId); - } - else - instanceEnabled = false; + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + instanceEnabled = client ? client->IsEnabled() : false; } if (instanceEnabled) - addonsToReCreate.emplace_back(addon, instanceId); + clientsToReCreate.emplace_back(clientId, addon->Name()); else - addonsToDestroy.emplace_back(addon, instanceId); + clientsToDestroy.emplace_back(clientId); } } } } - if (!addonsToCreate.empty() || !addonsToReCreate.empty() || !addonsToDestroy.empty()) + if (!clientsToCreate.empty() || !clientsToReCreate.empty() || !clientsToDestroy.empty()) { CServiceBroker::GetPVRManager().Stop(); @@ -210,54 +151,54 @@ void CPVRClients::UpdateAddons(const std::string& changedAddonId /*= ""*/, g_localizeStrings.Get(19239)); // Creating PVR clients unsigned int i = 0; - for (const auto& addon : addonsToCreate) + for (const auto& client : clientsToCreate) { - progressHandler->UpdateProgress(addon.first->Name(), i++, - addonsToCreate.size() + addonsToReCreate.size()); + progressHandler->UpdateProgress(client->Name(), i++, + clientsToCreate.size() + clientsToReCreate.size()); - ADDON_STATUS status = addon.first->Create(addon.second); + const ADDON_STATUS status = client->Create(); if (status != ADDON_STATUS_OK) { - CLog::LogF(LOGERROR, "Failed to create add-on {}, status = {}", addon.first->ID(), status); + CLog::LogF(LOGERROR, "Failed to create add-on {}, status = {}", client->ID(), status); if (status == ADDON_STATUS_PERMANENT_FAILURE) { - CServiceBroker::GetAddonMgr().DisableAddon(addon.first->ID(), + CServiceBroker::GetAddonMgr().DisableAddon(client->ID(), AddonDisabledReason::PERMANENT_FAILURE); - CServiceBroker::GetJobManager()->AddJob( - new CPVREventLogJob(true, true, addon.first->Name(), g_localizeStrings.Get(24070), - addon.first->Icon()), - nullptr); + CServiceBroker::GetJobManager()->AddJob(new CPVREventLogJob(true, true, client->Name(), + g_localizeStrings.Get(24070), + client->Icon()), + nullptr); } } } - for (const auto& addon : addonsToReCreate) + for (const auto& clientInfo : clientsToReCreate) { - progressHandler->UpdateProgress(addon.first->Name(), i++, - addonsToCreate.size() + addonsToReCreate.size()); + progressHandler->UpdateProgress(clientInfo.second, i++, + clientsToCreate.size() + clientsToReCreate.size()); - // recreate client - StopClient(addon.first->ID(), addon.second, true); + // stop and recreate client + StopClient(clientInfo.first, true /* restart */); } progressHandler.reset(); - for (const auto& addon : addonsToDestroy) + for (const auto& client : clientsToDestroy) { // destroy client - StopClient(addon.first->ID(), addon.second, false); + StopClient(client, false /* no restart */); } - if (!addonsToCreate.empty()) + if (!clientsToCreate.empty()) { // update created clients map std::unique_lock<CCriticalSection> lock(m_critSection); - for (const auto& addon : addonsToCreate) + for (const auto& client : clientsToCreate) { - if (m_clientMap.find(addon.second) == m_clientMap.end()) + if (m_clientMap.find(client->GetID()) == m_clientMap.end()) { - m_clientMap.insert(std::make_pair(addon.second, addon.first)); + m_clientMap.insert({client->GetID(), client}); } } } @@ -271,15 +212,13 @@ bool CPVRClients::RequestRestart(const std::string& addonId, bool bDataChanged) { CServiceBroker::GetJobManager()->Submit([this, addonId, instanceId] { - UpdateAddons(addonId, instanceId); + UpdateClients(addonId, instanceId); return true; }); return true; } -bool CPVRClients::StopClient(const std::string& addonId, - ADDON::AddonInstanceId instanceId, - bool bRestart) +bool CPVRClients::StopClient(int clientId, bool restart) { // stop playback if needed if (CServiceBroker::GetPVRManager().PlaybackState()->IsPlaying()) @@ -287,21 +226,20 @@ bool CPVRClients::StopClient(const std::string& addonId, std::unique_lock<CCriticalSection> lock(m_critSection); - int iId = GetClientId(addonId, instanceId); - std::shared_ptr<CPVRClient> mappedClient; - if (GetClient(iId, mappedClient)) + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client) { - if (bRestart) + if (restart) { - mappedClient->ReCreate(); + client->ReCreate(); } else { - const auto it = m_clientMap.find(iId); + const auto it = m_clientMap.find(clientId); if (it != m_clientMap.end()) m_clientMap.erase(it); - mappedClient->Destroy(); + client->Destroy(); } return true; } @@ -324,7 +262,7 @@ void CPVRClients::OnAddonEvent(const AddonEvent& event) if (CServiceBroker::GetAddonMgr().HasType(addonId, ADDON_PVRDLL)) { CServiceBroker::GetJobManager()->Submit([this, addonId, instanceId] { - UpdateAddons(addonId, instanceId); + UpdateClients(addonId, instanceId); return true; }); } @@ -335,31 +273,17 @@ void CPVRClients::OnAddonEvent(const AddonEvent& event) // client access //////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool CPVRClients::GetClient(int iClientId, std::shared_ptr<CPVRClient>& addon) const +std::shared_ptr<CPVRClient> CPVRClients::GetClient(int clientId) const { - bool bReturn = false; - if (iClientId <= PVR_INVALID_CLIENT_ID) - return bReturn; + if (clientId <= PVR_INVALID_CLIENT_ID) + return {}; std::unique_lock<CCriticalSection> lock(m_critSection); - const auto& itr = m_clientMap.find(iClientId); - if (itr != m_clientMap.end()) - { - addon = itr->second; - bReturn = true; - } + const auto it = m_clientMap.find(clientId); + if (it != m_clientMap.end()) + return it->second; - return bReturn; -} - -int CPVRClients::GetClientId(const std::string& addonId, ADDON::AddonInstanceId instanceId) const -{ - std::unique_lock<CCriticalSection> lock(m_critSection); - const auto it = std::find_if( - m_clientMap.cbegin(), m_clientMap.cend(), [&addonId, instanceId](const auto& entry) { - return entry.second->ID() == addonId && entry.second->InstanceId() == instanceId; - }); - return it != m_clientMap.cend() ? (*it).first : -1; + return {}; } int CPVRClients::CreatedClientAmount() const @@ -376,40 +300,32 @@ bool CPVRClients::HasCreatedClients() const [](const auto& client) { return client.second->ReadyToUse(); }); } -bool CPVRClients::IsKnownClient(const std::string& addonId, ADDON::AddonInstanceId instanceId) const +bool CPVRClients::IsKnownClient(int clientId) const { + std::unique_lock<CCriticalSection> lock(m_critSection); + // valid client IDs start at 1 - return GetClientId(addonId, instanceId) > 0; + const auto it = m_clientMap.find(clientId); + return (it != m_clientMap.end() && (*it).second->GetID() > 0); } bool CPVRClients::IsCreatedClient(int iClientId) const { - std::shared_ptr<CPVRClient> client; - return GetCreatedClient(iClientId, client); + return GetCreatedClient(iClientId) != nullptr; } -bool CPVRClients::IsCreatedClient(const std::string& addonId, - ADDON::AddonInstanceId instanceId) const +std::shared_ptr<CPVRClient> CPVRClients::GetCreatedClient(int clientId) const { - std::unique_lock<CCriticalSection> lock(m_critSection); - const auto it = std::find_if( - m_clientMap.cbegin(), m_clientMap.cend(), [&addonId, instanceId](const auto& client) { - return client.second->ID() == addonId && client.second->InstanceId() == instanceId; - }); - return it != m_clientMap.cend() ? (*it).second->ReadyToUse() : false; -} - -bool CPVRClients::GetCreatedClient(int iClientId, std::shared_ptr<CPVRClient>& addon) const -{ - if (GetClient(iClientId, addon)) - return addon->ReadyToUse(); + const std::shared_ptr<CPVRClient> client = GetClient(clientId); + if (client && client->ReadyToUse()) + return client; - return false; + return {}; } -int CPVRClients::GetCreatedClients(CPVRClientMap& clients) const +CPVRClientMap CPVRClients::GetCreatedClients() const { - int iReturn = 0; + CPVRClientMap clients; std::unique_lock<CCriticalSection> lock(m_critSection); for (const auto& client : m_clientMap) @@ -417,11 +333,10 @@ int CPVRClients::GetCreatedClients(CPVRClientMap& clients) const if (client.second->ReadyToUse()) { clients.insert(std::make_pair(client.second->GetID(), client.second)); - ++iReturn; } } - return iReturn; + return clients; } std::vector<CVariant> CPVRClients::GetClientProviderInfos() const @@ -439,11 +354,7 @@ std::vector<CVariant> CPVRClients::GetClientProviderInfos() const for (const auto& instanceId : instanceIds) { CVariant clientProviderInfo(CVariant::VariantTypeObject); - if (IsKnownClient(addonInfo->ID(), instanceId)) - clientProviderInfo["clientid"] = GetClientId(addonInfo->ID(), instanceId); - else - clientProviderInfo["clientid"] = - ClientIdFromAddonIdAndInstanceId(addonInfo->ID(), instanceId); + clientProviderInfo["clientid"] = CPVRClientUID(addonInfo->ID(), instanceId).GetUID(); clientProviderInfo["addonid"] = addonInfo->ID(); clientProviderInfo["instanceid"] = instanceId; clientProviderInfo["enabled"] = @@ -483,17 +394,16 @@ PVR_ERROR CPVRClients::GetCallableClients(CPVRClientMap& clientsReady, std::vector<ADDON::AddonInstanceId> instanceIds = addon->GetKnownInstanceIds(); for (const auto& instanceId : instanceIds) { - int iClientId = ClientIdFromAddonIdAndInstanceId(addon->ID(), instanceId); - std::shared_ptr<CPVRClient> client; - GetClient(iClientId, client); + const int clientId = CPVRClientUID(addon->ID(), instanceId).GetUID(); + const std::shared_ptr<CPVRClient> client = GetClient(clientId); if (client && client->ReadyToUse() && !client->IgnoreClient()) { - clientsReady.insert(std::make_pair(iClientId, client)); + clientsReady.insert(std::make_pair(clientId, client)); } else { - clientsNotReady.emplace_back(iClientId); + clientsNotReady.emplace_back(clientId); } } } @@ -517,8 +427,7 @@ int CPVRClients::EnabledClientAmount() const bool CPVRClients::IsEnabledClient(int clientId) const { - std::shared_ptr<CPVRClient> client; - GetClient(clientId, client); + const std::shared_ptr<CPVRClient> client = GetClient(clientId); return client && !CServiceBroker::GetAddonMgr().IsAddonDisabled(client->ID()); } @@ -569,6 +478,70 @@ bool CPVRClients::HasIgnoredClients() const [](const auto& client) { return client.second->IgnoreClient(); }); } +std::vector<ADDON::AddonInstanceId> CPVRClients::GetKnownInstanceIds( + const std::string& addonID) const +{ + std::vector<ADDON::AddonInstanceId> instanceIds; + + std::unique_lock<CCriticalSection> lock(m_critSection); + for (const auto& entry : m_clientMap) + { + if (entry.second->ID() == addonID) + instanceIds.emplace_back(entry.second->InstanceId()); + } + + return instanceIds; +} + +bool CPVRClients::GetAddonsWithStatus( + const std::string& changedAddonId, + std::vector<std::pair<AddonInfoPtr, bool>>& addonsWithStatus) const +{ + std::vector<AddonInfoPtr> addons; + CServiceBroker::GetAddonMgr().GetAddonInfos(addons, false, ADDON_PVRDLL); + + if (addons.empty()) + return false; + + bool foundChangedAddon = changedAddonId.empty(); + for (const auto& addon : addons) + { + bool enabled = !CServiceBroker::GetAddonMgr().IsAddonDisabled(addon->ID()); + addonsWithStatus.emplace_back(std::make_pair(addon, enabled)); + + if (!foundChangedAddon && addon->ID() == changedAddonId) + foundChangedAddon = true; + } + + return foundChangedAddon; +} + +std::vector<std::pair<ADDON::AddonInstanceId, bool>> CPVRClients::GetInstanceIdsWithStatus( + const AddonInfoPtr& addon, bool addonIsEnabled) const +{ + std::vector<std::pair<ADDON::AddonInstanceId, bool>> instanceIdsWithStatus; + + std::vector<ADDON::AddonInstanceId> instanceIds = addon->GetKnownInstanceIds(); + std::transform(instanceIds.cbegin(), instanceIds.cend(), + std::back_inserter(instanceIdsWithStatus), [addonIsEnabled](const auto& id) { + return std::pair<ADDON::AddonInstanceId, bool>(id, addonIsEnabled); + }); + + // find removed instances + const std::vector<ADDON::AddonInstanceId> knownInstanceIds = GetKnownInstanceIds(addon->ID()); + for (const auto& knownInstanceId : knownInstanceIds) + { + if (std::find(instanceIds.begin(), instanceIds.end(), knownInstanceId) == instanceIds.end()) + { + // instance was removed + instanceIdsWithStatus.emplace_back( + std::pair<ADDON::AddonInstanceId, bool>(knownInstanceId, false)); + } + } + + return instanceIdsWithStatus; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // client API calls //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -916,11 +889,10 @@ PVR_ERROR CPVRClients::ForCreatedClients(const char* strFunctionName, if (!failedClients.empty()) { + std::shared_ptr<CPVRClient> client; for (int id : failedClients) { - std::shared_ptr<CPVRClient> client; - GetClient(id, client); - + client = GetClient(id); if (client) LogClientWarning(strFunctionName, client); } diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h index 316c2461e4..8603688d36 100644 --- a/xbmc/pvr/addons/PVRClients.h +++ b/xbmc/pvr/addons/PVRClients.h @@ -77,12 +77,13 @@ namespace PVR void Continue(); /*! - * @brief Update add-ons from the AddonManager + * @brief Update all clients, sync with Addon Manager state (start, restart, shutdown clients). * @param changedAddonId The id of the changed addon, empty string denotes 'any addon'. * @param changedInstanceId The Identifier of the changed add-on instance */ - void UpdateAddons(const std::string& changedAddonId = "", - ADDON::AddonInstanceId changedInstanceId = 0); + void UpdateClients( + const std::string& changedAddonId = "", + ADDON::AddonInstanceId changedInstanceId = ADDON::ADDON_SINGLETON_INSTANCE_ID); /*! * @brief Restart a single client add-on. @@ -97,12 +98,11 @@ namespace PVR /*! * @brief Stop a client. - * @param addonId The client to stop. - * @param instance Identifier of the add-on instance. - * @param bRestart If true, restart the client. + * @param clientId The id of the client to stop. + * @param restart If true, restart the client. * @return True if the client was found, false otherwise. */ - bool StopClient(const std::string& addonId, ADDON::AddonInstanceId instance, bool bRestart); + bool StopClient(int clientId, bool restart); /*! * @brief Handle addon events (enable, disable, ...). @@ -111,14 +111,6 @@ namespace PVR void OnAddonEvent(const ADDON::AddonEvent& event); /*! - * @brief Get a client's numeric ID given its string ID. - * @param addonId The string ID. - * @param instance Identifier of the add-on instance. - * @return The numeric ID matching the given string ID, -1 on error. - */ - int GetClientId(const std::string& addonId, ADDON::AddonInstanceId instance) const; - - /*! * @brief Get the number of created clients. * @return The amount of created clients. */ @@ -138,25 +130,17 @@ namespace PVR bool IsCreatedClient(int iClientId) const; /*! - * @brief Get the instance of the client, if it's created. - * @param iClientId The ID of the client to get. - * @param addon Will be filled with requested client on success, null otherwise. - * @return True on success, false otherwise. - */ - bool GetCreatedClient(int iClientId, std::shared_ptr<CPVRClient>& addon) const; - - /*! - * @brief Get info required for providers. Include both enabled and disabled PVR add-ons - * @return A list containing the information required to create client providers. + * @brief Get the the client for the given client id, if it is created. + * @param clientId The ID of the client to get. + * @return The client if found, nullptr otherwise. */ - std::vector<CVariant> GetClientProviderInfos() const; + std::shared_ptr<CPVRClient> GetCreatedClient(int clientId) const; /*! * @brief Get all created clients. - * @param clients All created clients will be added to this map. - * @return The amount of clients added to the map. + * @return All created clients. */ - int GetCreatedClients(CPVRClientMap& clients) const; + CPVRClientMap GetCreatedClients() const; /*! * @brief Get the ID of the first created client. @@ -189,6 +173,12 @@ namespace PVR */ std::vector<CVariant> GetEnabledClientInfos() const; + /*! + * @brief Get info required for providers. Include both enabled and disabled PVR add-ons + * @return A list containing the information required to create client providers. + */ + std::vector<CVariant> GetClientProviderInfos() const; + //@} /*! @name general methods */ @@ -413,28 +403,32 @@ namespace PVR private: /*! - * @brief Get the client instance for a given client id. - * @param iClientId The id of the client to get. - * @param addon The client. - * @return True if the client was found, false otherwise. + * @brief Get the known instance ids for a given addon id. + * @param addonID The addon id. + * @return The list of known instance ids. */ - bool GetClient(int iClientId, std::shared_ptr<CPVRClient>& addon) const; + std::vector<ADDON::AddonInstanceId> GetKnownInstanceIds(const std::string& addonID) const; + + bool GetAddonsWithStatus( + const std::string& changedAddonId, + std::vector<std::pair<ADDON::AddonInfoPtr, bool>>& addonsWithStatus) const; + + std::vector<std::pair<ADDON::AddonInstanceId, bool>> GetInstanceIdsWithStatus( + const ADDON::AddonInfoPtr& addon, bool addonIsEnabled) const; /*! - * @brief Check whether a client is known. - * @param addonId The add-on id to check. - * @param instance Identifier of the add-on instance. - * @return True if this client is known, false otherwise. + * @brief Get the client instance for a given client id. + * @param clientId The id of the client to get. + * @return The client if found, nullptr otherwise. */ - bool IsKnownClient(const std::string& addonId, ADDON::AddonInstanceId instance) const; + std::shared_ptr<CPVRClient> GetClient(int clientId) const; /*! - * @brief Check whether an given addon instance is a created pvr client. - * @param addonId The add-on id. - * @param instance Identifier of the add-on instance. - * @return True if the the addon represents a created client, false otherwise. + * @brief Check whether a client is known. + * @param iClientId The id of the client to check. + * @return True if this client is known, false otherwise. */ - bool IsCreatedClient(const std::string& addonId, ADDON::AddonInstanceId instance) const; + bool IsKnownClient(int iClientId) const; /*! * @brief Get all created clients and clients not (yet) ready to use. diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index 0aa5c8781c..06674f8cdb 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -246,8 +246,9 @@ bool CPVRChannelGroup::UpdateClientPriorities() if (bUseBackendChannelOrder) { - std::shared_ptr<CPVRClient> client; - if (!clients->GetCreatedClient(member->Channel()->ClientID(), client)) + const std::shared_ptr<CPVRClient> client = + clients->GetCreatedClient(member->Channel()->ClientID()); + if (!client) continue; iNewPriority = client->GetPriority(); diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp index 75f42be14c..77cc2b543f 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.cpp +++ b/xbmc/pvr/channels/PVRChannelGroups.cpp @@ -13,6 +13,7 @@ #include "pvr/PVRDatabase.h" #include "pvr/PVRManager.h" #include "pvr/addons/PVRClient.h" +#include "pvr/addons/PVRClientUID.h" #include "pvr/addons/PVRClients.h" #include "pvr/channels/PVRChannel.h" #include "pvr/channels/PVRChannelGroupInternal.h" @@ -134,9 +135,8 @@ std::shared_ptr<CPVRChannelGroupMember> CPVRChannelGroups::GetChannelGroupMember { const std::shared_ptr<CPVRChannelGroup> group = GetByName(path.GetGroupName()); if (group) - return group->GetByUniqueID({CServiceBroker::GetPVRManager().Clients()->GetClientId( - path.GetClientID(), path.GetInstanceID()), - path.GetChannelUID()}); + return group->GetByUniqueID( + {CPVRClientUID(path.GetAddonID(), path.GetInstanceID()).GetUID(), path.GetChannelUID()}); } return {}; diff --git a/xbmc/pvr/channels/PVRChannelsPath.cpp b/xbmc/pvr/channels/PVRChannelsPath.cpp index 5fcb0fcf00..4ae2e28b00 100644 --- a/xbmc/pvr/channels/PVRChannelsPath.cpp +++ b/xbmc/pvr/channels/PVRChannelsPath.cpp @@ -73,12 +73,12 @@ CPVRChannelsPath::CPVRChannelsPath(const std::string& strPath) if (instance.size() == 2) { m_instanceID = std::atoi(instance[0].c_str()); - m_clientID = instance[1]; + m_addonID = instance[1]; } else { m_instanceID = ADDON::ADDON_SINGLETON_INSTANCE_ID; - m_clientID = tokens[0]; + m_addonID = tokens[0]; } tokens = StringUtils::Split(tokens[1], "."); @@ -90,7 +90,7 @@ CPVRChannelsPath::CPVRChannelsPath(const std::string& strPath) } } - if (!m_clientID.empty() && m_iChannelUID >= 0) + if (!m_addonID.empty() && m_iChannelUID >= 0) { m_kind = Kind:: CHANNEL; // pvr://channels/(tv|radio)/<groupname>/<instanceid>@<addonid>_<channeluid>.pvr @@ -155,20 +155,20 @@ CPVRChannelsPath::CPVRChannelsPath(bool bRadio, const std::string& strGroupName) CPVRChannelsPath::CPVRChannelsPath(bool bRadio, const std::string& strGroupName, - const std::string& strClientID, + const std::string& strAddonID, ADDON::AddonInstanceId instanceID, int iChannelUID) : m_bRadio(bRadio) { - if (!strGroupName.empty() && !strClientID.empty() && iChannelUID >= 0) + if (!strGroupName.empty() && !strAddonID.empty() && iChannelUID >= 0) { m_kind = Kind::CHANNEL; m_group = strGroupName; - m_clientID = strClientID; + m_addonID = strAddonID; m_instanceID = instanceID; m_iChannelUID = iChannelUID; m_path = StringUtils::Format("pvr://channels/{}/{}/{}@{}_{}.pvr", bRadio ? "radio" : "tv", - CURL::Encode(m_group), m_instanceID, m_clientID, m_iChannelUID); + CURL::Encode(m_group), m_instanceID, m_addonID, m_iChannelUID); } } diff --git a/xbmc/pvr/channels/PVRChannelsPath.h b/xbmc/pvr/channels/PVRChannelsPath.h index 4f6d8a3058..7b825c19e0 100644 --- a/xbmc/pvr/channels/PVRChannelsPath.h +++ b/xbmc/pvr/channels/PVRChannelsPath.h @@ -25,7 +25,7 @@ namespace PVR CPVRChannelsPath(bool bRadio, bool bHidden, const std::string& strGroupName); CPVRChannelsPath(bool bRadio, const std::string& strGroupName, - const std::string& strClientID, + const std::string& strAddonID, ADDON::AddonInstanceId instanceID, int iChannelUID); @@ -45,7 +45,7 @@ namespace PVR bool IsRadio() const { return m_bRadio; } const std::string& GetGroupName() const { return m_group; } - const std::string& GetClientID() const { return m_clientID; } + const std::string& GetAddonID() const { return m_addonID; } ADDON::AddonInstanceId GetInstanceID() const { return m_instanceID; } int GetChannelUID() const { return m_iChannelUID; } @@ -66,7 +66,7 @@ namespace PVR bool m_bRadio = false;; std::string m_path; std::string m_group; - std::string m_clientID; + std::string m_addonID; ADDON::AddonInstanceId m_instanceID{ADDON::ADDON_SINGLETON_INSTANCE_ID}; int m_iChannelUID = -1; }; diff --git a/xbmc/pvr/channels/test/TestPVRChannelsPath.cpp b/xbmc/pvr/channels/test/TestPVRChannelsPath.cpp index b9239466bc..c7232dbdcf 100644 --- a/xbmc/pvr/channels/test/TestPVRChannelsPath.cpp +++ b/xbmc/pvr/channels/test/TestPVRChannelsPath.cpp @@ -56,7 +56,7 @@ TEST(TestPVRChannelsPath, Parse_TV_Root_1) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ""); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -73,7 +73,7 @@ TEST(TestPVRChannelsPath, Parse_TV_Root_2) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ""); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -90,7 +90,7 @@ TEST(TestPVRChannelsPath, Parse_Radio_Root_1) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ""); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -107,7 +107,7 @@ TEST(TestPVRChannelsPath, Parse_Radio_Root_2) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ""); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -131,7 +131,7 @@ TEST(TestPVRChannelsPath, Parse_TV_Group_1) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -148,7 +148,7 @@ TEST(TestPVRChannelsPath, Parse_TV_Group_2) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -165,7 +165,7 @@ TEST(TestPVRChannelsPath, Parse_Hidden_TV_Group) EXPECT_TRUE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ".hidden"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -182,7 +182,7 @@ TEST(TestPVRChannelsPath, Parse_Special_TV_Group) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "foo/bar baz"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -207,7 +207,7 @@ TEST(TestPVRChannelsPath, Parse_Radio_Group) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -224,7 +224,7 @@ TEST(TestPVRChannelsPath, Parse_TV_Channel) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_TRUE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), "pvr.demo"); + EXPECT_EQ(path.GetAddonID(), "pvr.demo"); EXPECT_EQ(path.GetInstanceID(), 5); EXPECT_EQ(path.GetChannelUID(), 4711); } @@ -306,7 +306,7 @@ TEST(TestPVRChannelsPath, TV_Channelgroup) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -323,7 +323,7 @@ TEST(TestPVRChannelsPath, Radio_Channelgroup) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -340,7 +340,7 @@ TEST(TestPVRChannelsPath, Hidden_TV_Channelgroup) EXPECT_TRUE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ".hidden"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -357,7 +357,7 @@ TEST(TestPVRChannelsPath, Hidden_Radio_Channelgroup) EXPECT_TRUE(path.IsHiddenChannelGroup()); EXPECT_FALSE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), ".hidden"); - EXPECT_EQ(path.GetClientID(), ""); + EXPECT_EQ(path.GetAddonID(), ""); EXPECT_EQ(path.GetChannelUID(), -1); } @@ -374,7 +374,7 @@ TEST(TestPVRChannelsPath, TV_Channel) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_TRUE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), "pvr.demo"); + EXPECT_EQ(path.GetAddonID(), "pvr.demo"); EXPECT_EQ(path.GetChannelUID(), 4711); } @@ -391,7 +391,7 @@ TEST(TestPVRChannelsPath, Radio_Channel) EXPECT_FALSE(path.IsHiddenChannelGroup()); EXPECT_TRUE(path.IsChannel()); EXPECT_EQ(path.GetGroupName(), "Group1"); - EXPECT_EQ(path.GetClientID(), "pvr.demo"); + EXPECT_EQ(path.GetAddonID(), "pvr.demo"); EXPECT_EQ(path.GetChannelUID(), 4711); } diff --git a/xbmc/pvr/dialogs/GUIDialogPVRClientPriorities.cpp b/xbmc/pvr/dialogs/GUIDialogPVRClientPriorities.cpp index 0770efbf8a..ca83ba1298 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRClientPriorities.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRClientPriorities.cpp @@ -67,7 +67,7 @@ void CGUIDialogPVRClientPriorities::InitializeSettings() return; } - CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(m_clients); + m_clients = CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(); for (const auto& client : m_clients) { AddEdit(group, std::to_string(client.second->GetID()), 13205 /* Unknown */, SettingLevel::Basic, diff --git a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp index 9c5046d00a..39c1b35975 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp @@ -820,8 +820,7 @@ void CGUIDialogPVRTimerSettings::InitializeChannelsList() int index = 0; // Add special "any channel" entries - one for every client (used for epg-based timer rules). - CPVRClientMap clients; - CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(clients); + const CPVRClientMap clients = CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(); for (const auto& client : clients) { m_channelEntries.insert({index, ChannelDescriptor(PVR_CHANNEL_INVALID_UID, diff --git a/xbmc/pvr/guilib/PVRGUIActions.cpp b/xbmc/pvr/guilib/PVRGUIActions.cpp index 05ab2b160d..76dc2c9c4a 100644 --- a/xbmc/pvr/guilib/PVRGUIActions.cpp +++ b/xbmc/pvr/guilib/PVRGUIActions.cpp @@ -1698,8 +1698,7 @@ namespace PVR bool CPVRGUIActions::ProcessSettingsMenuHooks() { - CPVRClientMap clients; - CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(clients); + const CPVRClientMap clients = CServiceBroker::GetPVRManager().Clients()->GetCreatedClients(); std::vector<std::pair<std::shared_ptr<CPVRClient>, CPVRClientMenuHook>> settingsHooks; for (const auto& client : clients) diff --git a/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp index 5e2a867ae0..d023a001a7 100644 --- a/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp +++ b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp @@ -215,9 +215,9 @@ void CPVRGUIInfo::UpdateQualityData() const int channelUid = playbackState->GetPlayingChannelUniqueID(); if (channelUid > 0) { - std::shared_ptr<CPVRClient> client; - CServiceBroker::GetPVRManager().Clients()->GetCreatedClient(playbackState->GetPlayingClientID(), - client); + const std::shared_ptr<CPVRClient> client = + CServiceBroker::GetPVRManager().Clients()->GetCreatedClient( + playbackState->GetPlayingClientID()); if (client) client->SignalQuality(channelUid, qualityInfo); } @@ -239,9 +239,9 @@ void CPVRGUIInfo::UpdateDescrambleData() const int channelUid = playbackState->GetPlayingChannelUniqueID(); if (channelUid > 0) { - std::shared_ptr<CPVRClient> client; - CServiceBroker::GetPVRManager().Clients()->GetCreatedClient(playbackState->GetPlayingClientID(), - client); + const std::shared_ptr<CPVRClient> client = + CServiceBroker::GetPVRManager().Clients()->GetCreatedClient( + playbackState->GetPlayingClientID()); if (client) client->GetDescrambleInfo(channelUid, descrambleInfo); } |