From 2d09701ddfd168cc4b58d857a4aaa0f6e839f422 Mon Sep 17 00:00:00 2001 From: janbar Date: Sat, 17 Oct 2015 14:08:06 +0200 Subject: [PVR] Improve epg association by broadcast ID Using a new map 'm_epgEvents' which is updated when receiving a new event and for new scanned EPG. --- xbmc/epg/Epg.cpp | 14 +++++++++ xbmc/epg/Epg.h | 7 +++++ xbmc/epg/EpgContainer.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++-- xbmc/epg/EpgContainer.h | 11 +++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp index 0e20c98099..b43862f511 100644 --- a/xbmc/epg/Epg.cpp +++ b/xbmc/epg/Epg.cpp @@ -402,6 +402,7 @@ bool CEpg::UpdateEntries(const CEpg &epg, bool bStoreInDb /* = true */) m_lastScanTime = CDateTime::GetCurrentDateTime().GetAsUTCDateTime(); m_bUpdateLastScanTime = true; + SetChanged(true); NotifyObservers(ObservableMessageEpg); return true; @@ -864,3 +865,16 @@ bool CEpg::IsValid(void) const return m_pvrChannel != NULL; return true; } + +std::vector CEpg::GetAllEventsWithBroadcastId() const +{ + CSingleLock lock(m_critSection); + std::vector events; + events.reserve(m_tags.size()); + for (const auto &infoTag : m_tags) + { + if (infoTag.second->UniqueBroadcastID()) + events.push_back(infoTag.second); + } + return events; +} diff --git a/xbmc/epg/Epg.h b/xbmc/epg/Epg.h index 9fa0505ec0..7665cb4ab4 100644 --- a/xbmc/epg/Epg.h +++ b/xbmc/epg/Epg.h @@ -309,6 +309,13 @@ namespace EPG * @return True when this EPG is valid and can be updated, false otherwise. */ bool IsValid(void) const; + + /*! + * @brief Get all events with a valid broadcast Id + * @return the table of events + */ + std::vector GetAllEventsWithBroadcastId() const; + protected: CEpg(void); diff --git a/xbmc/epg/EpgContainer.cpp b/xbmc/epg/EpgContainer.cpp index a25238f935..e32759c9ef 100644 --- a/xbmc/epg/EpgContainer.cpp +++ b/xbmc/epg/EpgContainer.cpp @@ -109,6 +109,8 @@ void CEpgContainer::Clear(bool bClearDb /* = false */) { epgEntry.second->UnregisterObserver(this); } + m_epgEvents.clear(); + m_epgScans.clear(); m_epgs.clear(); m_iNextEpgUpdate = 0; m_bStarted = false; @@ -207,6 +209,8 @@ bool CEpgContainer::Stop(void) void CEpgContainer::Notify(const Observable &obs, const ObservableMessage msg) { + if (msg == ObservableMessageEpg) + UpdateEpgEvents(); SetChanged(); NotifyObservers(msg); } @@ -389,8 +393,9 @@ CEpgInfoTagPtr CEpgContainer::GetTagById(unsigned int iBroadcastId) const { CEpgInfoTagPtr retval; CSingleLock lock(m_critSection); - for (EPGMAP::const_iterator it = m_epgs.begin(); !retval && it != m_epgs.end(); ++it) - retval = it->second->GetTag(iBroadcastId); + const auto &infoTag = m_epgEvents.find(iBroadcastId); + if (infoTag != m_epgEvents.end()) + retval = infoTag->second; return retval; } @@ -513,6 +518,7 @@ bool CEpgContainer::DeleteEpg(const CEpg &epg, bool bDeleteFromDatabase /* = fal m_database.Delete(*epgEntry->second); epgEntry->second->UnregisterObserver(this); + CleanupEpgEvents(epgEntry->second); m_epgs.erase(epgEntry); return true; @@ -811,3 +817,67 @@ void CEpgContainer::UpdateRequest(int clientID, unsigned int channelID) request.channelID = channelID; m_updateRequests.push_back(request); } + +void CEpgContainer::UpdateEpgEvents() +{ + CLog::Log(LOGDEBUG, "EPGContainer - %s", __FUNCTION__); + CSingleLock lock(m_critSection); + CDateTime now = CDateTime::GetUTCDateTime(); + int count = 0; + + // Purge old events from the map with daily frequency and in according with EPG setting 'LingerTime' + if (!m_lastEpgEventPurge.IsValid() || m_lastEpgEventPurge < (now - CDateTimeSpan(1,0,0,0))) + { + CDateTime purgeTime = now - CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0); + for (auto event = m_epgEvents.begin(); event != m_epgEvents.end(); ++event) + { + if (event->second->EndAsUTC() < purgeTime) + { + m_epgEvents.erase(event); + ++count; + } + } + m_lastEpgEventPurge = now; + CLog::Log(LOGDEBUG, "EPGContainer - %s - %d item(s) purged", __FUNCTION__, count); + } + + // Fill updated entries + count = 0; + for (const auto &epgEntry : m_epgs) + { + if (!epgEntry.second->IsValid()) + continue; + + int epgId = epgEntry.second->EpgID(); + CDateTime epgScanTime = epgEntry.second->GetLastScanTime(); + + const auto &scan = m_epgScans.find(epgId); + if (scan != m_epgScans.end() && scan->second == epgScanTime) + continue; + + if (scan == m_epgScans.end()) + m_epgScans.insert(std::make_pair(epgId, epgScanTime)); + else + scan->second = epgScanTime; + + auto events = epgEntry.second->GetAllEventsWithBroadcastId(); + for (const auto &infoTag : events) + { + m_epgEvents[infoTag->UniqueBroadcastID()] = infoTag; + ++count; + } + } + CLog::Log(LOGDEBUG, "EPGContainer - %s - %d item(s) updated", __FUNCTION__, count); +} + +void CEpgContainer::CleanupEpgEvents(const CEpgPtr& epg) +{ + CSingleLock lock(m_critSection); + if (epg) + { + m_epgScans.erase(epg->EpgID()); + auto events = epg->GetAllEventsWithBroadcastId(); + for (const auto &infoTag : events) + m_epgEvents.erase(infoTag->UniqueBroadcastID()); + } +} diff --git a/xbmc/epg/EpgContainer.h b/xbmc/epg/EpgContainer.h index 7c0c9c4249..43dc44dc5b 100644 --- a/xbmc/epg/EpgContainer.h +++ b/xbmc/epg/EpgContainer.h @@ -292,6 +292,13 @@ namespace EPG void InsertFromDatabase(int iEpgID, const std::string &strName, const std::string &strScraperName); + /*! + * @brief Update map of epg events + */ + void UpdateEpgEvents(); + + void CleanupEpgEvents(const CEpgPtr& epg); + CEpgDatabase m_database; /*!< the EPG database */ /** @name Configuration */ @@ -323,5 +330,9 @@ namespace EPG std::list m_updateRequests; /*!< list of update requests triggered by addon*/ CCriticalSection m_updateRequestsLock; /*!< protect update requests*/ + + std::map m_epgEvents; /*!< map of EPG events by unique broadcast Id*/ + std::map m_epgScans; /*!< map of last scan time by EPG Id*/ + CDateTime m_lastEpgEventPurge; /*!< when the last purge has been processed*/ }; } -- cgit v1.2.3 From 2e20677765f50dd4be35fa3f0ce5eff2404e5be5 Mon Sep 17 00:00:00 2001 From: janbar Date: Mon, 19 Oct 2015 12:42:43 +0200 Subject: [PVR] Remove unused and inefficient function CEpg::GetTag(iUniqueId) This function has been obsoleted by CEpgContainer::GetTagById(iBroadcastId). --- xbmc/epg/Epg.cpp | 11 ----------- xbmc/epg/Epg.h | 10 ---------- 2 files changed, 21 deletions(-) diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp index b43862f511..c4d781f0d4 100644 --- a/xbmc/epg/Epg.cpp +++ b/xbmc/epg/Epg.cpp @@ -264,17 +264,6 @@ CEpgInfoTagPtr CEpg::GetTag(const CDateTime &StartTime) const return CEpgInfoTagPtr(); } -CEpgInfoTagPtr CEpg::GetTag(unsigned int uniqueID) const -{ - CEpgInfoTagPtr retval; - CSingleLock lock(m_critSection); - for (std::map::const_iterator it = m_tags.begin(); !retval && it != m_tags.end(); ++it) - if (it->second->UniqueBroadcastID() == uniqueID) - retval = it->second; - - return retval; -} - CEpgInfoTagPtr CEpg::GetTagBetween(const CDateTime &beginTime, const CDateTime &endTime) const { CSingleLock lock(m_critSection); diff --git a/xbmc/epg/Epg.h b/xbmc/epg/Epg.h index 7665cb4ab4..51bf728fa5 100644 --- a/xbmc/epg/Epg.h +++ b/xbmc/epg/Epg.h @@ -204,16 +204,6 @@ namespace EPG * @return The found tag or an empty tag if it wasn't found. */ CEpgInfoTagPtr GetTag(const CDateTime &beginTime) const; - /*! - * @brief Get the infotag with the given ID. - * - * Get the infotag with the given ID. - * If it wasn't found, try finding the event with the given start time - * - * @param uniqueID The unique ID of the event to find. - * @return The found tag or an empty tag if it wasn't found. - */ - CEpgInfoTagPtr GetTag(unsigned int uniqueID) const; /*! * @brief Update an entry in this EPG. -- cgit v1.2.3