diff options
-rw-r--r-- | xbmc/FileItem.cpp | 4 | ||||
-rw-r--r-- | xbmc/pvr/PVRDatabase.cpp | 4 | ||||
-rw-r--r-- | xbmc/pvr/PVRGUIDirectory.cpp | 137 | ||||
-rw-r--r-- | xbmc/pvr/channels/CMakeLists.txt | 6 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannel.cpp | 8 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannel.h | 4 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroup.cpp | 148 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroup.h | 33 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroupInternal.cpp | 26 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroups.cpp | 52 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroups.h | 2 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroupsContainer.cpp | 11 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelsPath.cpp | 169 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelsPath.h | 67 | ||||
-rw-r--r-- | xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp | 2 | ||||
-rw-r--r-- | xbmc/pvr/windows/GUIWindowPVRChannels.cpp | 7 | ||||
-rw-r--r-- | xbmc/utils/URIUtils.cpp | 12 | ||||
-rw-r--r-- | xbmc/utils/URIUtils.h | 1 |
18 files changed, 439 insertions, 254 deletions
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index d1b4127ebc..34e72b8056 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -851,9 +851,7 @@ bool CFileItem::IsPVRChannel() const bool CFileItem::IsPVRChannelGroup() const { - return !StringUtils::EndsWithNoCase(m_strPath, ".pvr") && - (StringUtils::StartsWithNoCase(m_strPath, "pvr://channels/tv/") || - StringUtils::StartsWithNoCase(m_strPath, "pvr://channels/radio/")); + return URIUtils::IsPVRChannelGroup(m_strPath); } bool CFileItem::IsPVRRecording() const diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp index 8be567884d..3404ca0205 100644 --- a/xbmc/pvr/PVRDatabase.cpp +++ b/xbmc/pvr/PVRDatabase.cpp @@ -573,7 +573,9 @@ bool CPVRDatabase::Get(CPVRChannelGroups &results) { while (!m_pDS->eof()) { - CPVRChannelGroup data(m_pDS->fv("bIsRadio").get_asBool(), m_pDS->fv("idGroup").get_asInt(), m_pDS->fv("sName").get_asString(), results.GetGroupAll()); + CPVRChannelGroup data(CPVRChannelsPath(m_pDS->fv("bIsRadio").get_asBool(), m_pDS->fv("sName").get_asString()), + m_pDS->fv("idGroup").get_asInt(), + results.GetGroupAll()); data.SetGroupType(m_pDS->fv("iGroupType").get_asInt()); data.SetLastWatched(static_cast<time_t>(m_pDS->fv("iLastWatched").get_asInt())); data.SetHidden(m_pDS->fv("bIsHidden").get_asBool()); diff --git a/xbmc/pvr/PVRGUIDirectory.cpp b/xbmc/pvr/PVRGUIDirectory.cpp index 6a54b54954..16ba93f31e 100644 --- a/xbmc/pvr/PVRGUIDirectory.cpp +++ b/xbmc/pvr/PVRGUIDirectory.cpp @@ -16,6 +16,7 @@ #include "pvr/channels/PVRChannelGroup.h" #include "pvr/channels/PVRChannelGroups.h" #include "pvr/channels/PVRChannelGroupsContainer.h" +#include "pvr/channels/PVRChannelsPath.h" #include "pvr/recordings/PVRRecording.h" #include "pvr/recordings/PVRRecordings.h" #include "pvr/recordings/PVRRecordingsPath.h" @@ -69,17 +70,17 @@ bool CPVRGUIDirectory::GetDirectory(CFileItemList& results) const std::shared_ptr<CFileItem> item; item.reset(new CFileItem(base + "channels/", true)); - item->SetLabel(g_localizeStrings.Get(19019)); + item->SetLabel(g_localizeStrings.Get(19019)); // Channels item->SetLabelPreformatted(true); results.Add(item); item.reset(new CFileItem(base + "recordings/active/", true)); - item->SetLabel(g_localizeStrings.Get(19017)); // TV Recordings + item->SetLabel(g_localizeStrings.Get(19017)); // Recordings item->SetLabelPreformatted(true); results.Add(item); item.reset(new CFileItem(base + "recordings/deleted/", true)); - item->SetLabel(g_localizeStrings.Get(19108)); // Deleted TV Recordings + item->SetLabel(g_localizeStrings.Get(19184)); // Deleted recordings item->SetLabelPreformatted(true); results.Add(item); @@ -327,103 +328,67 @@ bool CPVRGUIDirectory::GetChannelGroupsDirectory(bool bRadio, bool bExcludeHidde bool CPVRGUIDirectory::GetChannelsDirectory(CFileItemList& results) const { - std::string base = m_url.Get(); - URIUtils::RemoveSlashAtEnd(base); - - std::string fileName = m_url.GetFileName(); - URIUtils::RemoveSlashAtEnd(fileName); - - if (fileName == "channels") - { - std::shared_ptr<CFileItem> item; - - // all tv channels - item.reset(new CFileItem(base + "/tv/", true)); - item->SetLabel(g_localizeStrings.Get(19020)); - item->SetLabelPreformatted(true); - results.Add(item); - - // all radio channels - item.reset(new CFileItem(base + "/radio/", true)); - item->SetLabel(g_localizeStrings.Get(19021)); - item->SetLabelPreformatted(true); - results.Add(item); - - return true; - } - else if (fileName == "channels/tv") - { - return GetChannelGroupsDirectory(false, false, results); - } - else if (fileName == "channels/radio") - { - return GetChannelGroupsDirectory(true, false, results); - } - else if (StringUtils::StartsWith(fileName, "channels/tv/")) + const CPVRChannelsPath path(m_url.GetWithoutOptions()); + if (path.IsValid()) { - std::string strGroupName = fileName.substr(12); - URIUtils::RemoveSlashAtEnd(strGroupName); + if (path.IsEmpty()) + { + std::shared_ptr<CFileItem> item; - std::shared_ptr<CPVRChannelGroup> group; - bool bShowHiddenChannels = StringUtils::EndsWithNoCase(fileName, ".hidden"); - if (bShowHiddenChannels || strGroupName == "*") // all channels - group = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAllTV(); - else - group = CServiceBroker::GetPVRManager().ChannelGroups()->GetTV()->GetByName(strGroupName); + // all tv channels + item.reset(new CFileItem(CPVRChannelsPath::PATH_TV_CHANNELS, true)); + item->SetLabel(g_localizeStrings.Get(19020)); // TV + item->SetLabelPreformatted(true); + results.Add(item); - if (group) - { - const std::vector<PVRChannelGroupMember> groupMembers = group->GetMembers(); - for (const auto& groupMember : groupMembers) - { - if (bShowHiddenChannels != groupMember.channel->IsHidden()) - continue; + // all radio channels + item.reset(new CFileItem(CPVRChannelsPath::PATH_RADIO_CHANNELS, true)); + item->SetLabel(g_localizeStrings.Get(19021)); // Radio + item->SetLabelPreformatted(true); + results.Add(item); - results.Add(std::make_shared<CFileItem>(groupMember.channel)); - } + return true; } - else + else if (path.IsChannelsRoot()) { - CLog::LogF(LOGERROR, "Unable to obtain members of channel group '%s'", strGroupName.c_str()); - return false; + return GetChannelGroupsDirectory(path.IsRadio(), false, results); } + else if (path.IsChannelGroup()) + { + const std::string& strGroupName = path.GetGroupName(); + bool bShowHiddenChannels = path.IsHiddenChannelGroup(); - FilterDirectory(results); - return true; - } - else if (StringUtils::StartsWith(fileName, "channels/radio/")) - { - std::string strGroupName = fileName.substr(15); - URIUtils::RemoveSlashAtEnd(strGroupName); - - std::shared_ptr<CPVRChannelGroup> group; - bool bShowHiddenChannels = StringUtils::EndsWithNoCase(fileName, ".hidden"); - if (bShowHiddenChannels || strGroupName == "*") // all channels - group = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAllRadio(); - else - group = CServiceBroker::GetPVRManager().ChannelGroups()->GetRadio()->GetByName(strGroupName); + std::shared_ptr<CPVRChannelGroup> group; + if (bShowHiddenChannels || strGroupName == "*") // all channels + { + group = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(path.IsRadio()); + } + else + { + group = CServiceBroker::GetPVRManager().ChannelGroups()->Get(path.IsRadio())->GetByName(strGroupName); + } - if (group) - { - const std::vector<PVRChannelGroupMember> groupMembers = group->GetMembers(); - for (const auto& groupMember : groupMembers) + if (group) { - if (bShowHiddenChannels != groupMember.channel->IsHidden()) - continue; + const std::vector<PVRChannelGroupMember> groupMembers = group->GetMembers(); + for (const auto& groupMember : groupMembers) + { + if (bShowHiddenChannels != groupMember.channel->IsHidden()) + continue; - results.Add(std::make_shared<CFileItem>(groupMember.channel)); + results.Add(std::make_shared<CFileItem>(groupMember.channel)); + } + } + else + { + CLog::LogF(LOGERROR, "Unable to obtain members of channel group '%s'", strGroupName.c_str()); + return false; } - } - else - { - CLog::LogF(LOGERROR, "Unable to obtain members of channel group '%s'", strGroupName.c_str()); - return false; - } - FilterDirectory(results); - return true; + FilterDirectory(results); + return true; + } } - return false; } diff --git a/xbmc/pvr/channels/CMakeLists.txt b/xbmc/pvr/channels/CMakeLists.txt index f8f9f06dfa..39aa18f37f 100644 --- a/xbmc/pvr/channels/CMakeLists.txt +++ b/xbmc/pvr/channels/CMakeLists.txt @@ -4,7 +4,8 @@ set(SOURCES PVRChannel.cpp PVRChannelGroups.cpp PVRChannelGroupsContainer.cpp PVRChannelNumber.cpp - PVRRadioRDSInfoTag.cpp) + PVRRadioRDSInfoTag.cpp + PVRChannelsPath.cpp) set(HEADERS PVRChannel.h PVRChannelGroup.h @@ -12,6 +13,7 @@ set(HEADERS PVRChannel.h PVRChannelGroups.h PVRChannelGroupsContainer.h PVRChannelNumber.h - PVRRadioRDSInfoTag.h) + PVRRadioRDSInfoTag.h + PVRChannelsPath.h) core_add_library(pvr_channels) diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp index 764fbaa869..f906b6a7de 100644 --- a/xbmc/pvr/channels/PVRChannel.cpp +++ b/xbmc/pvr/channels/PVRChannel.cpp @@ -14,6 +14,7 @@ #include "guilib/LocalizeStrings.h" #include "pvr/PVRDatabase.h" #include "pvr/PVRManager.h" +#include "pvr/channels/PVRChannelsPath.h" #include "pvr/epg/Epg.h" #include "pvr/epg/EpgChannelData.h" #include "pvr/epg/EpgContainer.h" @@ -414,16 +415,13 @@ bool CPVRChannel::SetClientID(int iClientId) return false; } -void CPVRChannel::UpdatePath(const std::string& groupPath) +void CPVRChannel::UpdatePath(const std::string& channelGroup) { const CPVRClientPtr client = CServiceBroker::GetPVRManager().GetClient(m_iClientId); if (client) { CSingleLock lock(m_critSection); - const std::string strFileNameAndPath = StringUtils::Format("%s%s_%d.pvr", - groupPath, - client->ID().c_str(), - m_iUniqueId); + const std::string strFileNameAndPath = CPVRChannelsPath(m_bIsRadio, channelGroup, client->ID(), m_iUniqueId); if (m_strFileNameAndPath != strFileNameAndPath) { m_strFileNameAndPath = strFileNameAndPath; diff --git a/xbmc/pvr/channels/PVRChannel.h b/xbmc/pvr/channels/PVRChannel.h index 93c9e30f07..22f2adc39d 100644 --- a/xbmc/pvr/channels/PVRChannel.h +++ b/xbmc/pvr/channels/PVRChannel.h @@ -275,9 +275,9 @@ namespace PVR /*! * @brief Update the channel path - * @param groupPath The new path of the group this channel belongs to + * @param channelGroup The (new) name of the group this channel belongs to */ - void UpdatePath(const std::string& groupPath); + void UpdatePath(const std::string& channelGroup); /*! * @return Storage id for this channel in CPVRChannelGroup diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index 5025d62c76..5fc561937c 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -17,6 +17,7 @@ #include "pvr/PVRManager.h" #include "pvr/addons/PVRClients.h" #include "pvr/channels/PVRChannel.h" +#include "pvr/channels/PVRChannelsPath.h" #include "pvr/epg/Epg.h" #include "pvr/epg/EpgChannelData.h" #include "pvr/epg/EpgInfoTag.h" @@ -35,53 +36,43 @@ using namespace PVR; -CPVRChannelGroup::CPVRChannelGroup() -{ - OnInit(); -} - -CPVRChannelGroup::CPVRChannelGroup(bool bRadio, - int iGroupId, - const std::string& strGroupName, - const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup) : - m_bRadio(bRadio), - m_iGroupId(iGroupId), - m_strGroupName(strGroupName), - m_allChannelsGroup(allChannelsGroup) +CPVRChannelGroup::CPVRChannelGroup(const CPVRChannelsPath& path, + int iGroupId /* = INVALID_GROUP_ID */, + const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup /* = {} */) + : m_iGroupId(iGroupId) + , m_allChannelsGroup(allChannelsGroup) + , m_path(path) { OnInit(); } CPVRChannelGroup::CPVRChannelGroup(const PVR_CHANNEL_GROUP& group, - const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup) : - m_bRadio(group.bIsRadio), - m_strGroupName(group.strGroupName), - m_iPosition(group.iPosition), - m_allChannelsGroup(allChannelsGroup) + const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup) + : m_iPosition(group.iPosition) + , m_allChannelsGroup(allChannelsGroup) + , m_path(group.bIsRadio, group.strGroupName) { OnInit(); } -CPVRChannelGroup::CPVRChannelGroup(const CPVRChannelGroup &group) : - m_strGroupName(group.m_strGroupName) -{ - m_bRadio = group.m_bRadio; - m_iGroupType = group.m_iGroupType; - m_iGroupId = group.m_iGroupId; - m_bLoaded = group.m_bLoaded; - m_bChanged = group.m_bChanged; - m_bUsingBackendChannelOrder = group.m_bUsingBackendChannelOrder; - m_bUsingBackendChannelNumbers = group.m_bUsingBackendChannelNumbers; - m_iLastWatched = group.m_iLastWatched; - m_bHidden = group.m_bHidden; - m_bPreventSortAndRenumber = group.m_bPreventSortAndRenumber; - m_members = group.m_members; - m_sortedMembers = group.m_sortedMembers; - m_iPosition = group.m_iPosition; - m_failedClientsForChannels = group.m_failedClientsForChannels; - m_failedClientsForChannelGroupMembers = group.m_failedClientsForChannelGroupMembers; - m_allChannelsGroup = group.m_allChannelsGroup; - +CPVRChannelGroup::CPVRChannelGroup(const CPVRChannelGroup& group) + : m_iGroupType(group.m_iGroupType) + , m_iGroupId(group.m_iGroupId) + , m_bLoaded(group.m_bLoaded) + , m_bChanged(group.m_bChanged) + , m_bUsingBackendChannelOrder(group.m_bUsingBackendChannelOrder) + , m_bUsingBackendChannelNumbers(group.m_bUsingBackendChannelNumbers) + , m_bPreventSortAndRenumber(group.m_bPreventSortAndRenumber) + , m_iLastWatched(group.m_iLastWatched) + , m_bHidden(group.m_bHidden) + , m_iPosition(group.m_iPosition) + , m_sortedMembers(group.m_sortedMembers) + , m_members(group.m_members) + , m_failedClientsForChannels(group.m_failedClientsForChannels) + , m_failedClientsForChannelGroupMembers(group.m_failedClientsForChannelGroupMembers) + , m_allChannelsGroup(group.m_allChannelsGroup) + , m_path(group.m_path) +{ OnInit(); } @@ -93,11 +84,10 @@ CPVRChannelGroup::~CPVRChannelGroup(void) bool CPVRChannelGroup::operator==(const CPVRChannelGroup& right) const { - return (m_bRadio == right.m_bRadio && - m_iGroupType == right.m_iGroupType && - m_iGroupId == right.m_iGroupId && - m_strGroupName == right.m_strGroupName && - m_iPosition == right.m_iPosition); + return (m_iGroupType == right.m_iGroupType && + m_iGroupId == right.m_iGroupId && + m_iPosition == right.m_iPosition && + m_path == right.m_path); } bool CPVRChannelGroup::operator!=(const CPVRChannelGroup &right) const @@ -125,18 +115,18 @@ bool CPVRChannelGroup::Load(std::vector<std::shared_ptr<CPVRChannel>>& channelsT m_bUsingBackendChannelNumbers = settings->GetBool(CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERS); int iChannelCount = m_iGroupId > 0 ? LoadFromDb() : 0; - CLog::LogFC(LOGDEBUG, LOGPVR, "%d channels loaded from the database for group '%s'", iChannelCount, m_strGroupName.c_str()); + CLog::LogFC(LOGDEBUG, LOGPVR, "%d channels loaded from the database for group '%s'", iChannelCount, GroupName().c_str()); if (!Update(channelsToRemove)) { - CLog::LogF(LOGERROR, "Failed to update channels for group '%s', m_strGroupName.c_str()"); + CLog::LogF(LOGERROR, "Failed to update channels for group '%s'", GroupName().c_str()); return false; } if (Size() - iChannelCount > 0) { CLog::LogFC(LOGDEBUG, LOGPVR, "%d channels added from clients to group '%s'", - static_cast<int>(Size() - iChannelCount), m_strGroupName.c_str()); + static_cast<int>(Size() - iChannelCount), GroupName().c_str()); } SortAndRenumber(); @@ -161,16 +151,28 @@ bool CPVRChannelGroup::Update(std::vector<std::shared_ptr<CPVRChannel>>& channel !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_PVRMANAGER_SYNCCHANNELGROUPS)) return true; - CPVRChannelGroup PVRChannels_tmp(m_bRadio, m_iGroupId, m_strGroupName, m_allChannelsGroup); + CPVRChannelGroup PVRChannels_tmp(m_path, m_iGroupId, m_allChannelsGroup); PVRChannels_tmp.SetPreventSortAndRenumber(); PVRChannels_tmp.LoadFromClients(); m_failedClientsForChannelGroupMembers = PVRChannels_tmp.m_failedClientsForChannelGroupMembers; return UpdateGroupEntries(PVRChannels_tmp, channelsToRemove); } -std::string CPVRChannelGroup::GetPath() const +const CPVRChannelsPath& CPVRChannelGroup::GetPath() const +{ + CSingleLock lock(m_critSection); + return m_path; +} + +void CPVRChannelGroup::SetPath(const CPVRChannelsPath& path) { - return StringUtils::Format("pvr://channels/%s/%s/", m_bRadio ? "radio" : "tv", GroupName().c_str()); + CSingleLock lock(m_critSection); + if (m_path != path) + { + m_path = path; + m_bChanged = true; + Persist(); + } } bool CPVRChannelGroup::SetChannelNumber(const CPVRChannelPtr &channel, const CPVRChannelNumber &channelNumber) @@ -499,7 +501,7 @@ bool CPVRChannelGroup::AddAndUpdateChannels(const CPVRChannelGroup &channels, bo bReturn = true; CLog::Log(LOGINFO,"Added %s channel '%s' to group '%s'", - m_bRadio ? "radio" : "TV", existingChannel.channel->ChannelName().c_str(), GroupName().c_str()); + IsRadio() ? "radio" : "TV", existingChannel.channel->ChannelName().c_str(), GroupName().c_str()); } } @@ -535,7 +537,7 @@ std::vector<CPVRChannelPtr> CPVRChannelGroup::RemoveDeletedChannels(const CPVRCh { /* channel was not found */ CLog::Log(LOGINFO,"Deleted %s channel '%s' from group '%s'", - m_bRadio ? "radio" : "TV", channel->ChannelName().c_str(), GroupName().c_str()); + IsRadio() ? "radio" : "TV", channel->ChannelName().c_str(), GroupName().c_str()); removedChannels.emplace_back(channel); @@ -671,28 +673,6 @@ bool CPVRChannelGroup::IsGroupMember(int iChannelId) const return bReturn; } -bool CPVRChannelGroup::SetGroupName(const std::string &strGroupName, bool bSaveInDb /* = false */) -{ - bool bReturn(false); - CSingleLock lock(m_critSection); - - if (m_strGroupName != strGroupName) - { - /* update the name */ - m_strGroupName = strGroupName; - m_bChanged = true; -// SetChanged(); - - /* persist the changes */ - if (bSaveInDb) - Persist(); - - bReturn = true; - } - - return bReturn; -} - bool CPVRChannelGroup::Persist(void) { bool bReturn(true); @@ -830,7 +810,7 @@ void CPVRChannelGroup::OnSettingChanged(std::shared_ptr<const CSetting> setting) if (bChannelOrderChanged || bChannelNumbersChanged) { CLog::LogFC(LOGDEBUG, LOGPVR, "Renumbering channel group '%s' to use the backend channel order and/or numbers", - m_strGroupName.c_str()); + GroupName().c_str()); if (bChannelOrderChanged) UpdateClientPriorities(); @@ -948,8 +928,24 @@ int CPVRChannelGroup::GroupType(void) const std::string CPVRChannelGroup::GroupName(void) const { CSingleLock lock(m_critSection); - std::string strReturn(m_strGroupName); - return strReturn; + return m_path.GetGroupName(); +} + +void CPVRChannelGroup::SetGroupName(const std::string& strGroupName) +{ + CSingleLock lock(m_critSection); + if (m_path.GetGroupName() != strGroupName) + { + m_path = CPVRChannelsPath(m_path.IsRadio(), strGroupName); + m_bChanged = true; + Persist(); + } +} + +bool CPVRChannelGroup::IsRadio() const +{ + CSingleLock lock(m_critSection); + return m_path.IsRadio(); } time_t CPVRChannelGroup::LastWatched(void) const diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h index 878eafe856..4f05b2d70e 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.h +++ b/xbmc/pvr/channels/PVRChannelGroup.h @@ -11,6 +11,7 @@ #include "XBDateTime.h" #include "pvr/PVRTypes.h" #include "pvr/channels/PVRChannelNumber.h" +#include "pvr/channels/PVRChannelsPath.h" #include "settings/lib/ISettingCallback.h" #include "utils/Observer.h" @@ -61,12 +62,13 @@ namespace PVR /*! * @brief Create a new channel group instance. - * @param bRadio True if this group holds radio channels. + * @param path The channel group path. * @param iGroupId The database ID of this group or INVALID_GROUP_ID if the group was not yet stored in the database. - * @param strGroupName The name of this group. * @param allChannelsGroup The channel group containing all TV or radio channels. */ - CPVRChannelGroup(bool bRadio, int iGroupId, const std::string& strGroupName, const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup); + CPVRChannelGroup(const CPVRChannelsPath& path, + int iGroupId = INVALID_GROUP_ID, + const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup = {}); /*! * @brief Create a new channel group instance from a channel group provided by an add-on. @@ -113,7 +115,13 @@ namespace PVR * @brief Get the path of this group. * @return the path. */ - std::string GetPath() const; + const CPVRChannelsPath& GetPath() const; + + /*! + * @brief Set the path of this group. + * @param the path. + */ + void SetPath(const CPVRChannelsPath& path); /*! * @brief Change the channelnumber of a group. Used by CGUIDialogPVRChannelManager. Call SortByChannelNumber() and Renumber() after all changes are done. @@ -141,10 +149,8 @@ namespace PVR /*! * @brief Change the name of this group. * @param strGroupName The new group name. - * @param bSaveInDb Save in the database or not. - * @return True if the something changed, false otherwise. */ - bool SetGroupName(const std::string &strGroupName, bool bSaveInDb = false); + void SetGroupName(const std::string& strGroupName); /*! * @brief Persist changed or new data. @@ -176,13 +182,7 @@ namespace PVR * @brief True if this group holds radio channels, false if it holds TV channels. * @return True if this group holds radio channels, false if it holds TV channels. */ - bool IsRadio(void) const { return m_bRadio; } - - /*! - * @brief Set 'radio' property of this group. - * @param bIsRadio The new value for the 'radio' property. - */ - void SetRadio(bool bIsRadio) { m_bRadio = bIsRadio; } + bool IsRadio() const; /*! * @brief True if sorting should be prevented when adding/updating channels to the group. @@ -439,8 +439,6 @@ namespace PVR bool IsMissingChannelsFromClient(int iClientId) const; protected: - CPVRChannelGroup(); - /*! * @brief Init class */ @@ -506,10 +504,8 @@ namespace PVR */ bool UpdateClientPriorities(); - bool m_bRadio = false; /*!< true if this container holds radio channels, false if it holds TV channels */ int m_iGroupType = PVR_GROUP_TYPE_DEFAULT; /*!< The type of this group */ int m_iGroupId = INVALID_GROUP_ID; /*!< The ID of this group in the database */ - std::string m_strGroupName; /*!< The name of this group */ bool m_bLoaded = false; /*!< True if this container is loaded, false otherwise */ bool m_bChanged = false; /*!< true if anything changed in this group that hasn't been persisted, false otherwise */ bool m_bUsingBackendChannelOrder = false; /*!< true to use the channel order from backends, false otherwise */ @@ -528,5 +524,6 @@ namespace PVR CDateTime GetEPGDate(EpgDateType epgDateType) const; std::shared_ptr<CPVRChannelGroup> m_allChannelsGroup; + CPVRChannelsPath m_path; }; } diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp index b540bab79e..103c7f5c53 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp @@ -26,12 +26,10 @@ using namespace PVR; using namespace KODI::MESSAGING; -CPVRChannelGroupInternal::CPVRChannelGroupInternal(bool bRadio) : - m_iHiddenChannels(0) +CPVRChannelGroupInternal::CPVRChannelGroupInternal(bool bRadio) +: CPVRChannelGroup(CPVRChannelsPath(bRadio, g_localizeStrings.Get(19287)), PVR_GROUP_TYPE_INTERNAL) +, m_iHiddenChannels(0) { - m_iGroupType = PVR_GROUP_TYPE_INTERNAL; - m_bRadio = bRadio; - m_strGroupName = g_localizeStrings.Get(19287); } CPVRChannelGroupInternal::CPVRChannelGroupInternal(const CPVRChannelGroup &group) : @@ -64,10 +62,10 @@ void CPVRChannelGroupInternal::CheckGroupName(void) CSingleLock lock(m_critSection); /* check whether the group name is still correct, or channels will fail to load after the language setting changed */ - std::string strNewGroupName = g_localizeStrings.Get(19287); - if (m_strGroupName != strNewGroupName) + const std::string strNewGroupName = g_localizeStrings.Get(19287); + if (GroupName() != strNewGroupName) { - SetGroupName(strNewGroupName, true); + SetGroupName(strNewGroupName); UpdateChannelPaths(); } } @@ -81,7 +79,7 @@ void CPVRChannelGroupInternal::UpdateChannelPaths(void) if (it->second.channel->IsHidden()) ++m_iHiddenChannels; else - it->second.channel->UpdatePath(GetPath()); + it->second.channel->UpdatePath(GroupName()); } } @@ -101,7 +99,7 @@ CPVRChannelPtr CPVRChannelGroupInternal::UpdateFromClient(const CPVRChannelPtr & iChannelNumber = static_cast<int>(m_sortedMembers.size()) + 1; PVRChannelGroupMember newMember(channel, CPVRChannelNumber(iChannelNumber, channelNumber.GetSubChannelNumber()), 0); - channel->UpdatePath(GetPath()); + channel->UpdatePath(GroupName()); m_sortedMembers.push_back(newMember); m_members.insert(std::make_pair(channel->StorageId(), newMember)); m_bChanged = true; @@ -113,7 +111,7 @@ CPVRChannelPtr CPVRChannelGroupInternal::UpdateFromClient(const CPVRChannelPtr & bool CPVRChannelGroupInternal::Update(std::vector<std::shared_ptr<CPVRChannel>>& channelsToRemove) { - CPVRChannelGroupInternal PVRChannels_tmp(m_bRadio); + CPVRChannelGroupInternal PVRChannels_tmp(IsRadio()); PVRChannels_tmp.SetPreventSortAndRenumber(); PVRChannels_tmp.LoadFromClients(); m_failedClientsForChannels = PVRChannels_tmp.m_failedClientsForChannels; @@ -243,7 +241,7 @@ bool CPVRChannelGroupInternal::AddAndUpdateChannels(const CPVRChannelGroup &chan if (existingChannel.channel->UpdateFromClient(it->second.channel)) { bReturn = true; - CLog::LogFC(LOGDEBUG, LOGPVR, "Updated {} channel '{}' from PVR client", m_bRadio ? "radio" : "TV", it->second.channel->ChannelName()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Updated {} channel '{}' from PVR client", IsRadio() ? "radio" : "TV", it->second.channel->ChannelName()); } } else @@ -252,10 +250,10 @@ bool CPVRChannelGroupInternal::AddAndUpdateChannels(const CPVRChannelGroup &chan UpdateFromClient(it->second.channel, bUseBackendChannelNumbers ? it->second.channel->ClientChannelNumber() : CPVRChannelNumber()); if (it->second.channel->CreateEPG()) { - CLog::LogFC(LOGDEBUG, LOGPVR, "Created EPG for {} channel '{}' from PVR client", m_bRadio ? "radio" : "TV", it->second.channel->ChannelName()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Created EPG for {} channel '{}' from PVR client", IsRadio() ? "radio" : "TV", it->second.channel->ChannelName()); } bReturn = true; - CLog::LogFC(LOGDEBUG, LOGPVR, "Added {} channel '{}' from PVR client", m_bRadio ? "radio" : "TV", it->second.channel->ChannelName()); + CLog::LogFC(LOGDEBUG, LOGPVR, "Added {} channel '{}' from PVR client", IsRadio() ? "radio" : "TV", it->second.channel->ChannelName()); } } diff --git a/xbmc/pvr/channels/PVRChannelGroups.cpp b/xbmc/pvr/channels/PVRChannelGroups.cpp index d5e2ccd400..4a3030521d 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.cpp +++ b/xbmc/pvr/channels/PVRChannelGroups.cpp @@ -13,6 +13,7 @@ #include "pvr/PVRManager.h" #include "pvr/addons/PVRClients.h" #include "pvr/channels/PVRChannelGroupInternal.h" +#include "pvr/channels/PVRChannelsPath.h" #include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" @@ -77,13 +78,12 @@ bool CPVRChannelGroups::Update(const CPVRChannelGroup &group, bool bUpdateFromCl { // create a new group if none was found. Copy the properties immediately // so the group doesn't get flagged as "changed" further down. - updateGroup.reset(new CPVRChannelGroup(group.IsRadio(), group.GroupID(), group.GroupName(), GetGroupAll())); + updateGroup.reset(new CPVRChannelGroup(CPVRChannelsPath(group.IsRadio(), group.GroupName()), group.GroupID(), GetGroupAll())); m_groups.push_back(updateGroup); } - updateGroup->SetRadio(group.IsRadio()); + updateGroup->SetPath(group.GetPath()); updateGroup->SetGroupID(group.GroupID()); - updateGroup->SetGroupName(group.GroupName()); updateGroup->SetGroupType(group.GroupType()); updateGroup->SetPosition(group.GetPosition()); @@ -123,31 +123,16 @@ void CPVRChannelGroups::SortGroups() } } -std::shared_ptr<CPVRChannel> CPVRChannelGroups::GetByPath(const std::string& strInPath) const +std::shared_ptr<CPVRChannel> CPVRChannelGroups::GetByPath(const CPVRChannelsPath& path) const { - std::string strPath = strInPath; - URIUtils::RemoveSlashAtEnd(strPath); - std::string strCheckPath; - - CSingleLock lock(m_critSection); - for (const auto& group : m_groups) + if (path.IsChannel()) { - // check if the path matches - strCheckPath = group->GetPath(); - if (URIUtils::PathHasParent(strPath, strCheckPath)) - { - strPath.erase(0, strCheckPath.size()); - std::vector<std::string> split(StringUtils::Split(strPath, '_', 2)); - if (split.size() == 2) - { - const CPVRChannelPtr channel = group->GetByUniqueID(atoi(split[1].c_str()), CServiceBroker::GetPVRManager().Clients()->GetClientId(split[0])); - if (channel) - return channel; - } - } + const std::shared_ptr<CPVRChannelGroup> group = GetByName(path.GetGroupName()); + if (group) + return group->GetByUniqueID(path.GetChannelUID(), + CServiceBroker::GetPVRManager().Clients()->GetClientId(path.GetClientID())); } - // no match return {}; } @@ -179,16 +164,15 @@ std::vector<CPVRChannelGroupPtr> CPVRChannelGroups::GetGroupsByChannel(const CPV std::shared_ptr<CPVRChannelGroup> CPVRChannelGroups::GetGroupByPath(const std::string& strInPath) const { - // group paths returned by CPVRChannelGroup::GetPath() are always terminated by a "/" - std::string strPath = strInPath; - if (!strPath.empty() && strPath[strPath.size() - 1] != '/') - strPath += '/'; - - CSingleLock lock(m_critSection); - for (const auto& group : m_groups) + const CPVRChannelsPath path(strInPath); + if (path.IsChannelGroup()) { - if (group->GetPath() == strPath) - return group; + CSingleLock lock(m_critSection); + for (const auto& group : m_groups) + { + if (group->GetPath() == path) + return group; + } } return {}; } @@ -503,7 +487,7 @@ bool CPVRChannelGroups::AddGroup(const std::string &strName) if (!group) { // create a new group - group.reset(new CPVRChannelGroup(m_bRadio, CPVRChannelGroup::INVALID_GROUP_ID, strName, GetGroupAll())); + group.reset(new CPVRChannelGroup(CPVRChannelsPath(m_bRadio, strName), CPVRChannelGroup::INVALID_GROUP_ID, GetGroupAll())); m_groups.push_back(group); bPersist = true; diff --git a/xbmc/pvr/channels/PVRChannelGroups.h b/xbmc/pvr/channels/PVRChannelGroups.h index b8221252de..0f2b88a238 100644 --- a/xbmc/pvr/channels/PVRChannelGroups.h +++ b/xbmc/pvr/channels/PVRChannelGroups.h @@ -69,7 +69,7 @@ namespace PVR * @param strPath The path to the channel * @return The channel, or nullptr if not found */ - std::shared_ptr<CPVRChannel> GetByPath(const std::string& strPath) const; + std::shared_ptr<CPVRChannel> GetByPath(const CPVRChannelsPath& path) const; /*! * @brief Get a pointer to a channel group given its ID. diff --git a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp index 8cf93af1c7..cf1701afa3 100644 --- a/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupsContainer.cpp @@ -110,17 +110,16 @@ std::shared_ptr<CPVRChannel> CPVRChannelGroupsContainer::GetChannelForEpgTag(con if (!epgTag) return {}; - const CPVRChannelGroups* groups = epgTag->IsRadio() ? m_groupsRadio : m_groupsTV; - return groups->GetGroupAll()->GetByUniqueID(epgTag->UniqueChannelID(), epgTag->ClientID()); + return Get(epgTag->IsRadio())->GetGroupAll()->GetByUniqueID(epgTag->UniqueChannelID(), epgTag->ClientID()); } std::shared_ptr<CPVRChannel> CPVRChannelGroupsContainer::GetByPath(const std::string& strPath) const { - const std::shared_ptr<CPVRChannel> channel = m_groupsTV->GetByPath(strPath); - if (channel) - return channel; + const CPVRChannelsPath path(strPath); + if (path.IsValid()) + return Get(path.IsRadio())->GetByPath(path); - return m_groupsRadio->GetByPath(strPath); + return {}; } CPVRChannelGroupPtr CPVRChannelGroupsContainer::GetSelectedGroup(bool bRadio) const diff --git a/xbmc/pvr/channels/PVRChannelsPath.cpp b/xbmc/pvr/channels/PVRChannelsPath.cpp new file mode 100644 index 0000000000..c73b3916d5 --- /dev/null +++ b/xbmc/pvr/channels/PVRChannelsPath.cpp @@ -0,0 +1,169 @@ +/* + * 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 "PVRChannelsPath.h" + +#include "URL.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/log.h" + +#include <string> +#include <vector> + +using namespace PVR; + +const std::string CPVRChannelsPath::PATH_TV_CHANNELS = "pvr://channels/tv/"; +const std::string CPVRChannelsPath::PATH_RADIO_CHANNELS = "pvr://channels/radio/"; + + +CPVRChannelsPath::CPVRChannelsPath(const std::string& strPath) +{ + std::string strVarPath = TrimSlashes(strPath); + const std::vector<std::string> segments = URIUtils::SplitPath(strVarPath); + + for (const std::string& segment : segments) + { + switch (m_kind) + { + case Kind::INVALID: + if (segment == "pvr://") + m_kind = Kind::PROTO; // pvr:// followed by something => go on + else if (segment == "pvr:" && segments.size() == 1) // just pvr:// => invalid + strVarPath = "pvr:/"; + break; + + case Kind::PROTO: + if (segment == "channels") + m_kind = Kind::EMPTY; // pvr://channels + else + m_kind = Kind::INVALID; + break; + + case Kind::EMPTY: + if (segment == "tv" || segment == "radio") + { + m_kind = Kind::ROOT; // pvr://channels/(tv|radio) + m_bRadio = (segment == "radio"); + } + else + { + CLog::LogF(LOGERROR, "Invalid channels path '%s' - channel root segment syntax error.", strPath.c_str()); + m_kind = Kind::INVALID; + } + break; + + case Kind::ROOT: + m_kind = Kind::GROUP; // pvr://channels/(tv|radio)/<groupname> + m_group = CURL::Decode(segment); + break; + + case Kind::GROUP: + { + std::vector<std::string> tokens = StringUtils::Split(segment, "_"); + if (tokens.size() == 2) + { + m_clientID = tokens[0]; + tokens = StringUtils::Split(tokens[1], "."); + if (tokens.size() == 2 && tokens[1] == "pvr") + { + std::string channelUID = tokens[0]; + if (!channelUID.empty() && channelUID.find_first_not_of("0123456789") == std::string::npos) + m_iChannelUID = std::atoi(channelUID.c_str()); + } + } + + if (!m_clientID.empty() && m_iChannelUID >= 0) + { + m_kind = Kind::CHANNEL; // pvr://channels/(tv|radio)/<groupname>/<addonid>_<channeluid>.pvr + } + else + { + CLog::LogF(LOGERROR, "Invalid channels path '%s' - channel segment syntax error.", strPath.c_str()); + m_kind = Kind::INVALID; + } + break; + } + + case Kind::CHANNEL: + CLog::LogF(LOGERROR, "Invalid channels path '%s' - too many path segments.", strPath.c_str()); + m_kind = Kind::INVALID; // too many segments + break; + } + + if (m_kind == Kind::INVALID) + break; + } + + // append slash to all folders + if (m_kind < Kind::CHANNEL) + strVarPath.append("/"); + + m_path = strVarPath; +} + +CPVRChannelsPath::CPVRChannelsPath(bool bRadio, bool bHidden, const std::string& strGroupName) + : m_bRadio(bRadio) +{ + if (!bHidden && strGroupName.empty()) + m_kind = Kind::EMPTY; + else + m_kind = Kind::GROUP; + + m_group = bHidden ? ".hidden" : strGroupName; + m_path = StringUtils::Format("pvr://channels/%s/%s", bRadio ? "radio" : "tv", CURL::Encode(m_group).c_str()); + + if (!m_group.empty()) + m_path.append("/"); +} + +CPVRChannelsPath::CPVRChannelsPath(bool bRadio, const std::string& strGroupName) + : m_bRadio(bRadio) +{ + if (strGroupName.empty()) + m_kind = Kind::EMPTY; + else + m_kind = Kind::GROUP; + + m_group = strGroupName; + m_path = StringUtils::Format("pvr://channels/%s/%s", bRadio ? "radio" : "tv", CURL::Encode(m_group).c_str()); + + if (!m_group.empty()) + m_path.append("/"); +} + +CPVRChannelsPath::CPVRChannelsPath(bool bRadio, const std::string& strGroupName, const std::string& strClientID, int iChannelUID) + : m_bRadio(bRadio) +{ + if (!strGroupName.empty() && !strClientID.empty() && iChannelUID >= 0) + { + m_kind = Kind::CHANNEL; + m_group = strGroupName; + m_clientID = strClientID; + m_iChannelUID = iChannelUID; + m_path = StringUtils::Format("pvr://channels/%s/%s/%s_%d.pvr", + bRadio ? "radio" : "tv", CURL::Encode(m_group).c_str(), m_clientID.c_str(), m_iChannelUID); + } +} + +bool CPVRChannelsPath::IsHiddenChannelGroup() const +{ + return m_kind == Kind::GROUP && m_group == ".hidden"; +} + +std::string CPVRChannelsPath::TrimSlashes(const std::string& strString) +{ + std::string strTrimmed = strString; + while (!strTrimmed.empty() && strTrimmed.front() == '/') + strTrimmed.erase(0, 1); + + while (!strTrimmed.empty() && strTrimmed.back() == '/') + strTrimmed.pop_back(); + + return strTrimmed; +} diff --git a/xbmc/pvr/channels/PVRChannelsPath.h b/xbmc/pvr/channels/PVRChannelsPath.h new file mode 100644 index 0000000000..19e0a64ce6 --- /dev/null +++ b/xbmc/pvr/channels/PVRChannelsPath.h @@ -0,0 +1,67 @@ +/* + * 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 <string> + +class CDateTime; + +namespace PVR +{ + class CPVRChannelsPath + { + public: + static const std::string PATH_TV_CHANNELS; + static const std::string PATH_RADIO_CHANNELS; + + explicit CPVRChannelsPath(const std::string& strPath); + CPVRChannelsPath(bool bRadio, const std::string& strGroupName); + CPVRChannelsPath(bool bRadio, bool bHidden, const std::string& strGroupName); + CPVRChannelsPath(bool bRadio, const std::string& strGroupName, const std::string& strClientID, int iChannelUID); + + operator std::string() const { return m_path; } + bool operator ==(const CPVRChannelsPath& right) const { return m_path == right.m_path; } + bool operator !=(const CPVRChannelsPath& right) const { return !(*this == right); } + + bool IsValid() const { return m_kind > Kind::PROTO; } + + bool IsEmpty() const { return m_kind == Kind::EMPTY; } + bool IsChannelsRoot() const { return m_kind == Kind::ROOT; } + bool IsChannelGroup() const { return m_kind == Kind::GROUP; } + bool IsChannel() const { return m_kind == Kind::CHANNEL; } + + bool IsHiddenChannelGroup() const; + + bool IsRadio() const { return m_bRadio; } + + const std::string& GetGroupName() const { return m_group; } + const std::string& GetClientID() const { return m_clientID; } + int GetChannelUID() const { return m_iChannelUID; } + + private: + static std::string TrimSlashes(const std::string& strString); + + enum class Kind + { + INVALID, + PROTO, + EMPTY, + ROOT, + GROUP, + CHANNEL, + }; + + Kind m_kind = Kind::INVALID; + bool m_bRadio = false;; + std::string m_path; + std::string m_group; + std::string m_clientID; + int m_iChannelUID = -1; + }; +} diff --git a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp index 857902d67b..d6aa404e14 100644 --- a/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp +++ b/xbmc/pvr/dialogs/GUIDialogPVRGroupManager.cpp @@ -170,7 +170,7 @@ bool CGUIDialogPVRGroupManager::ActionButtonRenameGroup(CGUIMessage &message) if (!strGroupName.empty()) { ClearSelectedGroupsThumbnail(); - m_selectedGroup->SetGroupName(strGroupName, true); + m_selectedGroup->SetGroupName(strGroupName); Update(); } } diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp index 3398fc5b31..b97116fdf2 100644 --- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp @@ -27,6 +27,7 @@ #include "pvr/channels/PVRChannel.h" #include "pvr/channels/PVRChannelGroup.h" #include "pvr/channels/PVRChannelGroupsContainer.h" +#include "pvr/channels/PVRChannelsPath.h" #include "pvr/dialogs/GUIDialogPVRChannelManager.h" #include "pvr/dialogs/GUIDialogPVRGroupManager.h" #include "pvr/epg/Epg.h" @@ -351,8 +352,7 @@ CGUIWindowPVRTVChannels::CGUIWindowPVRTVChannels() std::string CGUIWindowPVRTVChannels::GetDirectoryPath() { - return StringUtils::Format("pvr://channels/tv/%s/", - m_bShowHiddenChannels ? ".hidden" : GetChannelGroup()->GroupName().c_str()); + return CPVRChannelsPath(false, m_bShowHiddenChannels, GetChannelGroup()->GroupName()); } CGUIWindowPVRRadioChannels::CGUIWindowPVRRadioChannels() @@ -362,6 +362,5 @@ CGUIWindowPVRRadioChannels::CGUIWindowPVRRadioChannels() std::string CGUIWindowPVRRadioChannels::GetDirectoryPath() { - return StringUtils::Format("pvr://channels/radio/%s/", - m_bShowHiddenChannels ? ".hidden" : GetChannelGroup()->GroupName().c_str()); + return CPVRChannelsPath(true, m_bShowHiddenChannels, GetChannelGroup()->GroupName()); } diff --git a/xbmc/utils/URIUtils.cpp b/xbmc/utils/URIUtils.cpp index 5bbef50794..f0f84e4517 100644 --- a/xbmc/utils/URIUtils.cpp +++ b/xbmc/utils/URIUtils.cpp @@ -13,6 +13,7 @@ #include "filesystem/SpecialProtocol.h" #include "filesystem/StackDirectory.h" #include "network/DNSNameCache.h" +#include "pvr/channels/PVRChannelsPath.h" #include "settings/AdvancedSettings.h" #include "URL.h" #include "utils/FileExtensionProvider.h" @@ -29,6 +30,7 @@ #include <netinet/in.h> #include <arpa/inet.h> +using namespace PVR; using namespace XFILE; const CAdvancedSettings* URIUtils::m_advancedSettings = nullptr; @@ -964,7 +966,15 @@ bool URIUtils::IsPVRChannel(const std::string& strFile) if (IsStack(strFile)) return IsPVRChannel(CStackDirectory::GetFirstStackedFile(strFile)); - return StringUtils::StartsWithNoCase(strFile, "pvr://channels"); + return IsProtocol(strFile, "pvr") && CPVRChannelsPath(strFile).IsChannel(); +} + +bool URIUtils::IsPVRChannelGroup(const std::string& strFile) +{ + if (IsStack(strFile)) + return IsPVRChannelGroup(CStackDirectory::GetFirstStackedFile(strFile)); + + return IsProtocol(strFile, "pvr") && CPVRChannelsPath(strFile).IsChannelGroup(); } bool URIUtils::IsPVRGuideItem(const std::string& strFile) diff --git a/xbmc/utils/URIUtils.h b/xbmc/utils/URIUtils.h index 5794149cd3..f10e4a2042 100644 --- a/xbmc/utils/URIUtils.h +++ b/xbmc/utils/URIUtils.h @@ -154,6 +154,7 @@ public: static bool IsLibraryContent(const std::string& strFile); static bool IsPVR(const std::string& strFile); static bool IsPVRChannel(const std::string& strFile); + static bool IsPVRChannelGroup(const std::string& strFile); static bool IsPVRGuideItem(const std::string& strFile); static bool IsUsingFastSwitch(const std::string& strFile); |