diff options
-rw-r--r-- | xbmc/pvr/epg/CMakeLists.txt | 2 | ||||
-rw-r--r-- | xbmc/pvr/epg/EpgContainer.cpp | 6 | ||||
-rw-r--r-- | xbmc/pvr/epg/EpgContainer.h | 4 | ||||
-rw-r--r-- | xbmc/pvr/epg/EpgSearch.cpp | 51 | ||||
-rw-r--r-- | xbmc/pvr/epg/EpgSearch.h | 48 | ||||
-rw-r--r-- | xbmc/pvr/filesystem/PVRGUIDirectory.cpp | 21 | ||||
-rw-r--r-- | xbmc/pvr/filesystem/PVRGUIDirectory.h | 1 | ||||
-rw-r--r-- | xbmc/pvr/windows/GUIWindowPVRSearch.cpp | 26 |
8 files changed, 134 insertions, 25 deletions
diff --git a/xbmc/pvr/epg/CMakeLists.txt b/xbmc/pvr/epg/CMakeLists.txt index 0ea75b702a..ee5e7f4015 100644 --- a/xbmc/pvr/epg/CMakeLists.txt +++ b/xbmc/pvr/epg/CMakeLists.txt @@ -2,6 +2,7 @@ set(SOURCES EpgContainer.cpp Epg.cpp EpgDatabase.cpp EpgInfoTag.cpp + EpgSearch.cpp EpgSearchFilter.cpp EpgSearchPath.cpp EpgChannelData.cpp @@ -12,6 +13,7 @@ set(HEADERS Epg.h EpgContainer.h EpgDatabase.h EpgInfoTag.h + EpgSearch.h EpgSearchData.h EpgSearchFilter.h EpgSearchPath.h diff --git a/xbmc/pvr/epg/EpgContainer.cpp b/xbmc/pvr/epg/EpgContainer.cpp index 4e20f790b1..72521d1593 100644 --- a/xbmc/pvr/epg/EpgContainer.cpp +++ b/xbmc/pvr/epg/EpgContainer.cpp @@ -953,7 +953,8 @@ int CPVREpgContainer::CleanupCachedImages() }); } -std::vector<std::shared_ptr<CPVREpgSearchFilter>> CPVREpgContainer::GetSavedSearches(bool bRadio) +std::vector<std::shared_ptr<CPVREpgSearchFilter>> CPVREpgContainer::GetSavedSearches( + bool bRadio) const { const std::shared_ptr<const CPVREpgDatabase> database = GetEpgDatabase(); if (!database) @@ -965,7 +966,8 @@ std::vector<std::shared_ptr<CPVREpgSearchFilter>> CPVREpgContainer::GetSavedSear return database->GetSavedSearches(bRadio); } -std::shared_ptr<CPVREpgSearchFilter> CPVREpgContainer::GetSavedSearchById(bool bRadio, int iId) +std::shared_ptr<CPVREpgSearchFilter> CPVREpgContainer::GetSavedSearchById(bool bRadio, + int iId) const { const std::shared_ptr<const CPVREpgDatabase> database = GetEpgDatabase(); if (!database) diff --git a/xbmc/pvr/epg/EpgContainer.h b/xbmc/pvr/epg/EpgContainer.h index 0b6c426b61..dbfb5acf6b 100644 --- a/xbmc/pvr/epg/EpgContainer.h +++ b/xbmc/pvr/epg/EpgContainer.h @@ -224,7 +224,7 @@ namespace PVR * @param bRadio Whether to fetch saved searches for radio or TV. * @return The searches. */ - std::vector<std::shared_ptr<CPVREpgSearchFilter>> GetSavedSearches(bool bRadio); + std::vector<std::shared_ptr<CPVREpgSearchFilter>> GetSavedSearches(bool bRadio) const; /*! * @brief Get the saved search matching the given id. @@ -232,7 +232,7 @@ namespace PVR * @param iId The id. * @return The saved search or nullptr if not found. */ - std::shared_ptr<CPVREpgSearchFilter> GetSavedSearchById(bool bRadio, int iId); + std::shared_ptr<CPVREpgSearchFilter> GetSavedSearchById(bool bRadio, int iId) const; /*! * @brief Persist a saved search in the database. diff --git a/xbmc/pvr/epg/EpgSearch.cpp b/xbmc/pvr/epg/EpgSearch.cpp new file mode 100644 index 0000000000..5981b87a47 --- /dev/null +++ b/xbmc/pvr/epg/EpgSearch.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 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 "EpgSearch.h" + +#include "ServiceBroker.h" +#include "pvr/PVRManager.h" +#include "pvr/epg/EpgContainer.h" +#include "pvr/epg/EpgSearchFilter.h" + +#include <algorithm> +#include <mutex> + +using namespace PVR; + +void CPVREpgSearch::Execute() +{ + std::unique_lock<CCriticalSection> lock(m_critSection); + + std::vector<std::shared_ptr<CPVREpgInfoTag>> tags{ + CServiceBroker::GetPVRManager().EpgContainer().GetTags(m_filter.GetEpgSearchData())}; + m_filter.SetEpgSearchDataFiltered(); + + // Tags can still contain false positives, for search criteria that cannot be handled via + // database. So, run extended search filters on what we got from the database. + for (auto it = tags.cbegin(); it != tags.cend();) + { + it = tags.erase(std::remove_if(tags.begin(), tags.end(), + [this](const std::shared_ptr<const CPVREpgInfoTag>& entry) + { return !m_filter.FilterEntry(entry); }), + tags.cend()); + } + + if (m_filter.ShouldRemoveDuplicates()) + m_filter.RemoveDuplicates(tags); + + m_filter.SetLastExecutedDateTime(CDateTime::GetUTCDateTime()); + + m_results = tags; +} + +const std::vector<std::shared_ptr<CPVREpgInfoTag>>& CPVREpgSearch::GetResults() const +{ + std::unique_lock<CCriticalSection> lock(m_critSection); + return m_results; +} diff --git a/xbmc/pvr/epg/EpgSearch.h b/xbmc/pvr/epg/EpgSearch.h new file mode 100644 index 0000000000..6dbbf89b29 --- /dev/null +++ b/xbmc/pvr/epg/EpgSearch.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 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 "threads/CriticalSection.h" + +#include <memory> +#include <vector> + +namespace PVR +{ +class CPVREpgInfoTag; +class CPVREpgSearchFilter; + +class CPVREpgSearch +{ +public: + CPVREpgSearch() = delete; + + /*! + * @brief ctor. + * @param filter The filter defining the search criteria. + */ + explicit CPVREpgSearch(CPVREpgSearchFilter& filter) : m_filter(filter) {} + + /*! + * @brief Execute the search. + */ + void Execute(); + + /*! + * @brief Get the last search results. + * @return the results. + */ + const std::vector<std::shared_ptr<CPVREpgInfoTag>>& GetResults() const; + +private: + mutable CCriticalSection m_critSection; + CPVREpgSearchFilter& m_filter; + std::vector<std::shared_ptr<CPVREpgInfoTag>> m_results; +}; +} // namespace PVR diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp index 63341bd707..290b2b8bce 100644 --- a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp +++ b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp @@ -23,6 +23,7 @@ #include "pvr/channels/PVRChannelGroupsContainer.h" #include "pvr/channels/PVRChannelsPath.h" #include "pvr/epg/EpgContainer.h" +#include "pvr/epg/EpgSearch.h" #include "pvr/epg/EpgSearchFilter.h" #include "pvr/epg/EpgSearchPath.h" #include "pvr/recordings/PVRRecording.h" @@ -224,6 +225,8 @@ bool CPVRGUIDirectory::GetDirectory(CFileItemList& results) const { if (path.IsSavedSearchesRoot()) return GetSavedSearchesDirectory(path.IsRadio(), results); + else if (path.IsSavedSearch()) + return GetSavedSearchResults(path.IsRadio(), path.GetId(), results); } return true; } @@ -435,6 +438,24 @@ bool CPVRGUIDirectory::GetSavedSearchesDirectory(bool bRadio, CFileItemList& res return true; } +bool CPVRGUIDirectory::GetSavedSearchResults(bool isRadio, int id, CFileItemList& results) const +{ + auto& epgContainer{CServiceBroker::GetPVRManager().EpgContainer()}; + const std::shared_ptr<CPVREpgSearchFilter> filter{epgContainer.GetSavedSearchById(isRadio, id)}; + if (filter) + { + CPVREpgSearch search(*filter); + search.Execute(); + const auto tags{search.GetResults()}; + for (const auto& tag : tags) + { + results.Add(std::make_shared<CFileItem>(tag)); + } + return true; + } + return false; +} + bool CPVRGUIDirectory::GetChannelGroupsDirectory(bool bRadio, bool bExcludeHidden, CFileItemList& results) diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.h b/xbmc/pvr/filesystem/PVRGUIDirectory.h index 462c55360c..31375ade32 100644 --- a/xbmc/pvr/filesystem/PVRGUIDirectory.h +++ b/xbmc/pvr/filesystem/PVRGUIDirectory.h @@ -100,6 +100,7 @@ private: bool GetTimersDirectory(CFileItemList& results) const; bool GetRecordingsDirectory(CFileItemList& results) const; bool GetSavedSearchesDirectory(bool bRadio, CFileItemList& results) const; + bool GetSavedSearchResults(bool isRadio, int id, CFileItemList& results) const; const CURL m_url; }; diff --git a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp index 4a9ad6b10e..356e65dcc0 100644 --- a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp +++ b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp @@ -26,6 +26,7 @@ #include "pvr/epg/Epg.h" #include "pvr/epg/EpgContainer.h" #include "pvr/epg/EpgInfoTag.h" +#include "pvr/epg/EpgSearch.h" #include "pvr/epg/EpgSearchFilter.h" #include "pvr/epg/EpgSearchPath.h" #include "pvr/guilib/PVRGUIActionsEPG.h" @@ -71,27 +72,10 @@ bool AsyncSearchAction::Execute() void AsyncSearchAction::Run() { - std::vector<std::shared_ptr<CPVREpgInfoTag>> results = - CServiceBroker::GetPVRManager().EpgContainer().GetTags(m_filter->GetEpgSearchData()); - m_filter->SetEpgSearchDataFiltered(); - - // Tags can still contain false positives, for search criteria that cannot be handled via - // database. So, run extended search filters on what we got from the database. - for (auto it = results.begin(); it != results.end();) - { - it = results.erase(std::remove_if(results.begin(), results.end(), - [this](const std::shared_ptr<CPVREpgInfoTag>& entry) { - return !m_filter->FilterEntry(entry); - }), - results.end()); - } - - if (m_filter->ShouldRemoveDuplicates()) - m_filter->RemoveDuplicates(results); - - m_filter->SetLastExecutedDateTime(CDateTime::GetUTCDateTime()); - - for (const auto& tag : results) + CPVREpgSearch search(*m_filter); + search.Execute(); + const auto tags{search.GetResults()}; + for (const auto& tag : tags) { m_items->Add(std::make_shared<CFileItem>(tag)); } |