Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

RFC: Incremental EPG updates #497

Closed
wants to merge 1 commit into from

4 participants

@manio

As you requested - I am opening pull request for the changes discussed in issue #316. Please comment.

@manio

Lars, as you can see I've added new argument to GetEPGForChannel function. Do you think it would be a better idea to add additional API function, called eg GetEPGSince and also add a new addon capability (eg: bSupportsIncrementalEPGUpdates)?

@opdenkamp
Owner

I'll review it in more detail as soon as I got time. thanks.

@opdenkamp opdenkamp was assigned
@opdenkamp
Owner

I'll incorporate these changes in the external-addons branch, since I'm already working on some interface changes in there.

@manio

btw: I think that similar timestamping would also be great when doing channel updates. I did not mention about it yet, but if you're making an api changes - it would be great to have similar thing in channel updates (update only changed channels since last update in one bulk process and not asking if every single one has changed).

@schumi2004

@adamsutton is your tvheadend repository the latest up-to-date version of tvheadend? It's for testing purpose.

@adamsutton

It depends what you mean by up to date ;)

My epg-rewrite branch contains my rewrite of the TVH EPG code. But it's still in flux as I'm adding new features. Although things are beginning to stabilise.

However I've not yet included any of the stuff related to this particular feature, simply because I've been busy getting other bits to work and I think we need to agree on what is required in the API etc.. That being said because of the way I've organised the code it should be a relatively trivial feature to add (famous last words).

If you want to have a chat about this, I'm on IRC (adamsutton). And I'm usually lurking around in #hts and/or #xbmc-pvr.

Adam

@opdenkamp
Owner

Now that PVR support has been merged into mainline XBMC, every pull request must be sent as a pull request to mainline XBMC too: https://github.com/xbmc/xbmc/pulls

That's why I am closing this one. Sorry for the trouble.

@opdenkamp opdenkamp closed this
@manio manio referenced this pull request in xbmc/xbmc
Closed

[pvr] add support for incremental epg updates #1459

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 2, 2012
  1. @manio

    RFC: Incremental EPG updates

    manio authored
This page is out of date. Refresh to see the latest.
View
12 xbmc/addons/AddonCallbacksPVR.cpp
@@ -122,13 +122,21 @@ void CAddonCallbacksPVR::PVRTransferEpgEntry(void *addonData, const PVR_HANDLE h
return;
}
- CEpg *xbmcEpg = (CEpg*) handle->dataAddress;
+ CPVRClient* client = (CPVRClient*) handle->callerAddress;
+ CPVRChannel *channel = (CPVRChannel *) g_PVRChannelGroups->GetByUniqueID(epgentry->iClientChannelUid, client->GetClientID());
+
+ if (channel == NULL)
+ {
+ CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - cannot find channel %d on client %d",
+ __FUNCTION__, epgentry->iClientChannelUid, client->GetClientID());
+ return;
+ }
EPG_TAG *epgentry2 = (EPG_TAG*) epgentry;
bool bUpdateDatabase = handle->dataIdentifier == 1;
/* transfer this entry to the epg */
- xbmcEpg->UpdateEntry(epgentry2, bUpdateDatabase);
+ channel->GetEPG()->UpdateEntry(epgentry2, bUpdateDatabase);
}
void CAddonCallbacksPVR::PVRTransferChannelEntry(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL *channel)
View
2  xbmc/addons/include/xbmc_pvr_dll.h
@@ -94,7 +94,7 @@ extern "C"
* @param iEnd The end time to use.
* @return PVR_ERROR_NO_ERROR if the table has been fetched successfully.
*/
- PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd);
+ PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince);
//@}
/** @name PVR channel group methods */
View
3  xbmc/addons/include/xbmc_pvr_types.h
@@ -251,6 +251,7 @@ extern "C" {
unsigned int iUniqueBroadcastId; /*!< @brief (required) identifier for this event */
const char * strTitle; /*!< @brief (required) this event's title */
unsigned int iChannelNumber; /*!< @brief (required) the number of the channel this event occurs on */
+ int iClientChannelUid; /*!< @brief (required) unique identifier of the channel that will be updated */
time_t startTime; /*!< @brief (required) start time in UTC */
time_t endTime; /*!< @brief (required) end time in UTC */
const char * strPlotOutline; /*!< @brief (optional) plot outline */
@@ -331,7 +332,7 @@ extern "C" {
/** @name PVR EPG methods */
//@{
- PVR_ERROR (__cdecl* GetEpg)(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd);
+ PVR_ERROR (__cdecl* GetEpg)(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince);
//@}
/** @name PVR channel group methods */
View
14 xbmc/epg/Epg.cpp
@@ -474,7 +474,7 @@ CDateTime CEpg::GetLastScanTime(void)
return m_lastScanTime;
}
-bool CEpg::Update(const time_t start, const time_t end, int iUpdateTime)
+bool CEpg::Update(const time_t start, const time_t end, const time_t since, int iUpdateTime)
{
bool bGrabSuccess(true);
bool bUpdate(false);
@@ -498,7 +498,7 @@ bool CEpg::Update(const time_t start, const time_t end, int iUpdateTime)
bUpdate = (iNow > iLastUpdate + iUpdateTime);
if (bUpdate)
- bGrabSuccess = LoadFromClients(start, end);
+ bGrabSuccess = LoadFromClients(start, end, since);
if (bGrabSuccess)
{
@@ -732,7 +732,7 @@ bool CEpg::FixOverlappingEvents(bool bUpdateDb /* = false */)
return bReturn;
}
-bool CEpg::UpdateFromScraper(time_t start, time_t end)
+bool CEpg::UpdateFromScraper(time_t start, time_t end, time_t since)
{
bool bGrabSuccess = false;
if (ScraperName() == "client")
@@ -748,7 +748,7 @@ bool CEpg::UpdateFromScraper(time_t start, time_t end)
{
CLog::Log(LOGINFO, "%s - updating EPG for channel '%s' from client '%i'", __FUNCTION__, channel->ChannelName().c_str(), channel->ClientID());
PVR_ERROR error;
- g_PVRClients->GetEPGForChannel(*channel, this, start, end, &error);
+ g_PVRClients->GetEPGForChannel(*channel, this, start, end, since, &error);
bGrabSuccess = error == PVR_ERROR_NO_ERROR;
}
}
@@ -875,20 +875,20 @@ bool CEpg::IsRemovableTag(const CEpgInfoTag *tag) const
return (!tag || !tag->HasTimer());
}
-bool CEpg::LoadFromClients(time_t start, time_t end)
+bool CEpg::LoadFromClients(time_t start, time_t end, time_t since)
{
bool bReturn(false);
CPVRChannel *channel = Channel();
if (channel)
{
CEpg tmpEpg(channel);
- if (tmpEpg.UpdateFromScraper(start, end))
+ if (tmpEpg.UpdateFromScraper(start, end, since))
bReturn = UpdateEntries(tmpEpg, !g_guiSettings.GetBool("epg.ignoredbforclient"));
}
else
{
CEpg tmpEpg(m_iEpgID, m_strName, m_strScraperName);
- if (tmpEpg.UpdateFromScraper(start, end))
+ if (tmpEpg.UpdateFromScraper(start, end, since))
bReturn = UpdateEntries(tmpEpg, !g_guiSettings.GetBool("epg.ignoredbforclient"));
}
View
6 xbmc/epg/Epg.h
@@ -208,7 +208,7 @@ namespace EPG
* @param iUpdateTime Update the table after the given amount of time has passed.
* @return True if the update was successful, false otherwise.
*/
- virtual bool Update(const time_t start, const time_t end, int iUpdateTime);
+ virtual bool Update(const time_t start, const time_t end, const time_t since, int iUpdateTime);
/*!
* @brief Get all EPG entries.
@@ -290,7 +290,7 @@ namespace EPG
* @param end Get entries with an end date before this time.
* @return True if the update was successful, false otherwise.
*/
- virtual bool UpdateFromScraper(time_t start, time_t end);
+ virtual bool UpdateFromScraper(time_t start, time_t end, time_t since);
/*!
* @brief Persist all tags in this container.
@@ -317,7 +317,7 @@ namespace EPG
* @param end Only get entries before this end time. Use 0 to get all entries after "begin". If both "begin" and "end" are 0, all entries will be updated.
* @return True if the update was successful, false otherwise.
*/
- virtual bool LoadFromClients(time_t start, time_t end);
+ virtual bool LoadFromClients(time_t start, time_t end, time_t since);
/*!
* @brief Update the contents of this table with the contents provided in "epg"
View
13 xbmc/epg/EpgContainer.cpp
@@ -54,6 +54,7 @@ CEpgContainer::CEpgContainer(void) :
m_bPreventUpdates = false;
m_updateEvent.Reset();
m_bLoaded = false;
+ m_iLastEpgUpdate = 0;
m_database.Open();
}
@@ -423,6 +424,7 @@ bool CEpgContainer::UpdateEPG()
/* set start and end time */
time_t start;
time_t end;
+ time_t iStarted;
CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(start);
end = start + m_iDisplayTime;
start -= g_advancedSettings.m_iEpgLingerTime * 60;
@@ -448,6 +450,7 @@ bool CEpgContainer::UpdateEPG()
/* load or update all EPG tables */
CEpg *epg;
unsigned int iCounter(0);
+ unsigned int iUpdateStarted = XbmcThreads::SystemClockMillis();
for (map<unsigned int, CEpg *>::iterator it = m_epgs.begin(); it != m_epgs.end(); it++)
{
if (InterruptUpdate())
@@ -463,9 +466,17 @@ bool CEpgContainer::UpdateEPG()
if (bShowProgress)
UpdateProgressDialog(++iCounter, m_epgs.size(), epg->Name());
- if (epg->Update(start, end, m_iUpdateTime))
+ CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(iStarted);
+ if (epg->Update(start, end, m_iLastEpgUpdate, m_iUpdateTime))
+ {
++iUpdatedTables;
+ m_iLastEpgUpdate = iStarted;
+ }
+
+ //we have to break it here because one request gives a bulk epg reply from client
+ break;
}
+ CLog::Log(LOGDEBUG, "%s: EPG update took %d ms", __FUNCTION__, XbmcThreads::SystemClockMillis() - iUpdateStarted);
if (!bInterrupted)
{
View
1  xbmc/epg/EpgContainer.h
@@ -275,6 +275,7 @@ namespace EPG
bool m_bLoaded; /*!< true after epg data is initially loaded from the database */
bool m_bPreventUpdates; /*!< true to prevent EPG updates */
time_t m_iLastEpgCleanup; /*!< the time the EPG was cleaned up */
+ time_t m_iLastEpgUpdate; /*!< the time the EPG was last updated */
time_t m_iNextEpgUpdate; /*!< the time the EPG will be updated */
time_t m_iNextEpgActiveTagCheck; /*!< the time the EPG will be checked for active tag updates */
unsigned int m_iNextEpgId; /*!< the next epg ID that will be given to a new table when the db isn't being used */
View
5 xbmc/pvr/addons/PVRClient.cpp
@@ -366,7 +366,7 @@ void CPVRClient::CallMenuHook(const PVR_MENUHOOK &hook)
}
}
-PVR_ERROR CPVRClient::GetEPGForChannel(const CPVRChannel &channel, CEpg *epg, time_t start /* = 0 */, time_t end /* = 0 */, bool bSaveInDb /* = false*/)
+PVR_ERROR CPVRClient::GetEPGForChannel(const CPVRChannel &channel, CEpg *epg, time_t start /* = 0 */, time_t end /* = 0 */, time_t since /* = 0 */, bool bSaveInDb /* = false*/)
{
PVR_ERROR retVal = PVR_ERROR_UNKNOWN;
if (!m_bReadyToUse)
@@ -387,7 +387,8 @@ PVR_ERROR CPVRClient::GetEPGForChannel(const CPVRChannel &channel, CEpg *epg, ti
retVal = m_pStruct->GetEpg(&handle,
addonChannel,
start ? start - g_advancedSettings.m_iPVRTimeCorrection : 0,
- end ? end - g_advancedSettings.m_iPVRTimeCorrection : 0);
+ end ? end - g_advancedSettings.m_iPVRTimeCorrection : 0,
+ since);
LogError(retVal, __FUNCTION__);
}
View
2  xbmc/pvr/addons/PVRClient.h
@@ -184,7 +184,7 @@ namespace PVR
* @param bSaveInDb If true, tell the callback method to save any new entry in the database or not. see CAddonCallbacksPVR::PVRTransferEpgEntry()
* @return PVR_ERROR_NO_ERROR if the table has been fetched successfully.
*/
- PVR_ERROR GetEPGForChannel(const CPVRChannel &channel, EPG::CEpg *epg, time_t start = 0, time_t end = 0, bool bSaveInDb = false);
+ PVR_ERROR GetEPGForChannel(const CPVRChannel &channel, EPG::CEpg *epg, time_t start = 0, time_t end = 0, time_t since = 0, bool bSaveInDb = false);
//@}
/** @name PVR channel group methods */
View
4 xbmc/pvr/addons/PVRClients.cpp
@@ -817,12 +817,12 @@ bool CPVRClients::HasEPGSupport(int iClientId)
return IsConnectedClient(iClientId) && m_clientMap[iClientId]->GetAddonCapabilities().bSupportsEPG;
}
-bool CPVRClients::GetEPGForChannel(const CPVRChannel &channel, CEpg *epg, time_t start, time_t end, PVR_ERROR *error)
+bool CPVRClients::GetEPGForChannel(const CPVRChannel &channel, CEpg *epg, time_t start, time_t end, time_t since, PVR_ERROR *error)
{
*error = PVR_ERROR_UNKNOWN;
boost::shared_ptr<CPVRClient> client;
if (GetConnectedClient(channel.ClientID(), client) && client->GetAddonCapabilities().bSupportsEPG)
- *error = client->GetEPGForChannel(channel, epg, start, end);
+ *error = client->GetEPGForChannel(channel, epg, start, end, since);
else
CLog::Log(LOGERROR, "PVR - %s - client %d does not support EPG",__FUNCTION__, channel.ClientID());
View
2  xbmc/pvr/addons/PVRClients.h
@@ -497,7 +497,7 @@ namespace PVR
* @param error An error if it occured.
* @return True if the EPG was transfered successfully, false otherwise.
*/
- bool GetEPGForChannel(const CPVRChannel &channel, EPG::CEpg *epg, time_t start, time_t end, PVR_ERROR *error);
+ bool GetEPGForChannel(const CPVRChannel &channel, EPG::CEpg *epg, time_t start, time_t end, time_t since, PVR_ERROR *error);
//@}
View
2  xbmc/pvrclients/MediaPortal/client.cpp
@@ -477,7 +477,7 @@ PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook)
/*******************************************/
/** PVR EPG Functions **/
-PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince)
{
if (!g_client)
return PVR_ERROR_SERVER_ERROR;
View
2  xbmc/pvrclients/MediaPortal/pvrclient-mediaportal.cpp
@@ -441,7 +441,7 @@ PVR_ERROR cPVRClientMediaPortal::GetBackendTime(time_t *localTime, int *gmtOffse
/************************************************************/
/** EPG handling */
-PVR_ERROR cPVRClientMediaPortal::GetEpg(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR cPVRClientMediaPortal::GetEpg(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince)
{
vector<string> lines;
char command[256];
View
2  xbmc/pvrclients/MediaPortal/pvrclient-mediaportal.h
@@ -52,7 +52,7 @@ class cPVRClientMediaPortal
PVR_ERROR GetBackendTime(time_t *localTime, int *gmtOffset);
/* EPG handling */
- PVR_ERROR GetEpg(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart = NULL, time_t iEnd = NULL);
+ PVR_ERROR GetEpg(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart = NULL, time_t iEnd = NULL, time_t iSince = NULL);
/* Channel handling */
int GetNumChannels(void);
View
2  xbmc/pvrclients/mythtv/client.cpp
@@ -281,7 +281,7 @@ PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook)
/*******************************************/
/** PVR EPG Functions **/
-PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t Since)
{
if (MythXmlApi == NULL)
return PVR_ERROR_SERVER_ERROR;
View
2  xbmc/pvrclients/pvr-demo/client.cpp
@@ -161,7 +161,7 @@ PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed)
return PVR_ERROR_NO_ERROR;
}
-PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince)
{
if (m_data)
return m_data->GetEPGForChannel(handle, channel, iStart, iEnd);
View
2  xbmc/pvrclients/tvheadend/client.cpp
@@ -333,7 +333,7 @@ PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed)
return PVR_ERROR_SERVER_ERROR;
}
-PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince)
{
if (!HTSPData || !HTSPData->IsConnected())
return PVR_ERROR_SERVER_ERROR;
View
2  xbmc/pvrclients/vdr-vnsi/client.cpp
@@ -361,7 +361,7 @@ PVR_ERROR DialogChannelScan(void)
/*******************************************/
/** PVR EPG Functions **/
-PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd)
+PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd, time_t iSince)
{
if (!VNSIData)
return PVR_ERROR_SERVER_ERROR;
Something went wrong with that request. Please try again.