aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Sommerfeld <kai.sommerfeld@gmx.com>2015-10-20 23:12:41 +0200
committerKai Sommerfeld <kai.sommerfeld@gmx.com>2015-10-20 23:12:41 +0200
commitba2a353b343266b491667acefefc6e3c2c715cd3 (patch)
treea278ad2cae488c4611533e3ba8fea24215362ae0
parent182945b6c9276e969309623b63510d7607577b90 (diff)
parent2e20677765f50dd4be35fa3f0ce5eff2404e5be5 (diff)
Merge pull request #8240 from janbar/improve_epg_associations
[PVR] Improve epg association by broadcast ID
-rw-r--r--xbmc/epg/Epg.cpp25
-rw-r--r--xbmc/epg/Epg.h17
-rw-r--r--xbmc/epg/EpgContainer.cpp74
-rw-r--r--xbmc/epg/EpgContainer.h11
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*/
};
}