diff options
author | Kai Sommerfeld <kai.sommerfeld@gmx.com> | 2015-10-20 23:12:41 +0200 |
---|---|---|
committer | Kai Sommerfeld <kai.sommerfeld@gmx.com> | 2015-10-20 23:12:41 +0200 |
commit | ba2a353b343266b491667acefefc6e3c2c715cd3 (patch) | |
tree | a278ad2cae488c4611533e3ba8fea24215362ae0 | |
parent | 182945b6c9276e969309623b63510d7607577b90 (diff) | |
parent | 2e20677765f50dd4be35fa3f0ce5eff2404e5be5 (diff) |
Merge pull request #8240 from janbar/improve_epg_associations
[PVR] Improve epg association by broadcast ID
-rw-r--r-- | xbmc/epg/Epg.cpp | 25 | ||||
-rw-r--r-- | xbmc/epg/Epg.h | 17 | ||||
-rw-r--r-- | xbmc/epg/EpgContainer.cpp | 74 | ||||
-rw-r--r-- | xbmc/epg/EpgContainer.h | 11 |
4 files changed, 104 insertions, 23 deletions
diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp index 0e20c98099..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<CDateTime, CEpgInfoTagPtr>::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); @@ -402,6 +391,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 +854,16 @@ bool CEpg::IsValid(void) const return m_pvrChannel != NULL; return true; } + +std::vector<CEpgInfoTagPtr> CEpg::GetAllEventsWithBroadcastId() const +{ + CSingleLock lock(m_critSection); + std::vector<CEpgInfoTagPtr> 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..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. @@ -309,6 +299,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<CEpgInfoTagPtr> 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<SUpdateRequest> m_updateRequests; /*!< list of update requests triggered by addon*/ CCriticalSection m_updateRequestsLock; /*!< protect update requests*/ + + std::map<unsigned int, CEpgInfoTagPtr> m_epgEvents; /*!< map of EPG events by unique broadcast Id*/ + std::map<unsigned int, CDateTime> m_epgScans; /*!< map of last scan time by EPG Id*/ + CDateTime m_lastEpgEventPurge; /*!< when the last purge has been processed*/ }; } |