summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile_14
-rw-r--r--import.cpp73
-rw-r--r--import.h3
-rw-r--r--parse.cpp21
-rw-r--r--source.cpp31
-rw-r--r--source.h17
-rw-r--r--xmltv2vdr.cpp121
-rw-r--r--xmltv2vdr.h7
8 files changed, 182 insertions, 105 deletions
diff --git a/Makefile_ b/Makefile_
deleted file mode 100644
index 72424e7..0000000
--- a/Makefile_
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile
-#
-#
-DIRS=dist/epgdata2xmltv .
-
-all:
- for i in $(DIRS); do $(MAKE) -C $$i; done
-
-install:
- for i in $(DIRS); do $(MAKE) -C $$i install; done
-
-clean:
- for i in $(DIRS); do $(MAKE) -C $$i clean; done
diff --git a/import.cpp b/import.cpp
index e4b0271..b802c81 100644
--- a/import.cpp
+++ b/import.cpp
@@ -428,6 +428,17 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule,
if (!Event) return false;
+ if (!append)
+ {
+ const char *eitdescription=Event->Description();
+ if (WasChanged(Event)) eitdescription=NULL; // we cannot use Event->Description() - it is already changed!
+ if (!xEvent->EITEventID() || eitdescription)
+ {
+ UpdateXMLTVEvent(Source,Db,Event,xEvent,eitdescription);
+ }
+ if (!eitdescription && !xEvent->EITDescription()) return false;
+ }
+
if (((Flags & USE_SHORTTEXT)==USE_SHORTTEXT) || (append))
{
if (xEvent->ShortText() && (strlen(xEvent->ShortText())>0))
@@ -450,7 +461,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule,
}
char *description=NULL;
- if (((Flags & USE_LONGTEXT)==USE_LONGTEXT) || ((Flags & OPT_APPEND)==OPT_APPEND))
+ if (((Flags & USE_LONGTEXT)==USE_LONGTEXT) || (append))
{
if (xEvent->Description() && (strlen(xEvent->Description())>0))
{
@@ -463,13 +474,6 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule,
description=strdup(xEvent->EITDescription());
}
- if (!description && Event->Description() && (strlen(Event->Description())>0))
- {
- if (WasChanged(Event)) return false;
- UpdateXMLTVEvent(Source,Db,Event,xEvent);
- description=strdup(Event->Description());
- }
-
if (description) description=Add2Description(description,"\n");
if ((Flags & USE_CREDITS)==USE_CREDITS)
@@ -791,11 +795,11 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule,
switch (changed)
{
case CHANGED_SHORTTEXT:
- tsyslogs(Source,"{%i} changing shorttext (%s) of '%s'@%s-%s",Event->EventID(),
+ tsyslogs(Source,"{%i} changing stext (%s) of '%s'@%s-%s",Event->EventID(),
Event->ShortText(),Event->Title(),from,till);
break;
case CHANGED_DESCRIPTION:
- tsyslogs(Source,"{%i} changing description of '%s'@%s-%s",Event->EventID(),
+ tsyslogs(Source,"{%i} changing descr of '%s'@%s-%s",Event->EventID(),
Event->Title(),from,till);
break;
case CHANGED_ALL:
@@ -961,7 +965,7 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char *
if (!cParse::FetchSeasonEpisode(conv,epdir,Event->Title(),
Event->ShortText(),season,episode))
{
- tsyslogs(Source,"no season/episode found for '%s'/'%s'",Event->Title(),Event->ShortText());
+ //tsyslogs(Source,"no season/episode found for '%s'/'%s'",Event->Title(),Event->ShortText());
free(epdir);
iconv_close(conv);
return NULL;
@@ -1009,25 +1013,34 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char *
return xevent;
}
-bool cImport::UpdateXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const cEvent *Event, cXMLTVEvent *xEvent)
+bool cImport::UpdateXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const cEvent *Event, cXMLTVEvent *xEvent,
+ const char *Description)
{
if (!Source) return false;
if (!Db) return false;
if (!Event) return false;
if (!xEvent) return false;
- if (Event->Description())
+ // prevent unnecessary updates
+ if (!Description && (xEvent->EITEventID()==Event->EventID())) return false;
+
+ if (Description)
+ {
+ xEvent->SetEITDescription(Description);
+ }
+ bool eventid=false;
+ if (!xEvent->EITEventID())
{
- xEvent->SetEITDescription(Event->Description());
+ xEvent->SetEITEventID(Event->EventID());
+ eventid=true;
}
- xEvent->SetEITEventID(Event->EventID());
if (!Begin(Source,Db)) return false;
char *sql=NULL;
- if (Event->Description())
+ if (Description)
{
- char *eitdescription=strdup(Event->Description());
+ char *eitdescription=strdup(Description);
if (!eitdescription)
{
esyslogs(Source,"out of memory");
@@ -1067,19 +1080,19 @@ bool cImport::UpdateXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const cEvent *Ev
if (Source->Trace())
{
- struct tm tm;
- char from[80];
- char till[80];
- time_t start,end;
- start=Event->StartTime();
- end=Event->EndTime();
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- tsyslogs(Source,"{%i} updating %s of '%s'@%s-%s in db",Event->EventID(),
- Event->Description() ? "eitdescription/eiteventid" :
- "eiteventid",Event->Title(),from,till);
+ char buf[80]="";
+ if (Description)
+ {
+ strcat(buf,"eitdescription");
+ if (eventid) strcat(buf,"/");
+ }
+ if (eventid)
+ {
+ strcat(buf,"eiteventid");
+ }
+
+ tsyslogs(Source,"{%i} updating %s of '%s' in db",Event->EventID(),buf,
+ Event->Title());
}
char *errmsg;
diff --git a/import.h b/import.h
index 7864412..747fcbd 100644
--- a/import.h
+++ b/import.h
@@ -63,7 +63,8 @@ public:
bool DBExists();
bool PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, cEvent *Event,
cXMLTVEvent *xEvent, int Flags);
- bool UpdateXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const cEvent *Event, cXMLTVEvent *xEvent);
+ bool UpdateXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const cEvent *Event, cXMLTVEvent *xEvent,
+ const char *Description);
cXMLTVEvent *SearchXMLTVEvent(sqlite3 **Db, const char *ChannelID, const cEvent *Event);
cXMLTVEvent *AddXMLTVEvent(cEPGSource *Source, sqlite3 *Db, const char *ChannelID,
const cEvent *Event, const char *EITDescription);
diff --git a/parse.cpp b/parse.cpp
index e48ea43..26c14fe 100644
--- a/parse.cpp
+++ b/parse.cpp
@@ -500,8 +500,25 @@ bool cParse::FetchEvent(xmlNodePtr enode)
}
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "icon")))
{
- // http-link inside -> just ignore
- xevent.SetPicExists();
+ xmlChar *src=xmlGetProp(node,(const xmlChar *) "src");
+ if (src)
+ {
+ const xmlChar *f=xmlStrstr(src,(const xmlChar *) "://");
+ if (f)
+ {
+ // url: skip scheme and scheme-specific-part
+ f+=3;
+ }
+ else
+ {
+ // just try it
+ f=src;
+ }
+ struct stat statbuf;
+ if (stat((const char *) f,&statbuf)!=-1) xevent.SetPicExists();
+ xmlFree(src);
+ }
+
}
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "length")))
{
diff --git a/source.cpp b/source.cpp
index 2a7c031..cf7d539 100644
--- a/source.cpp
+++ b/source.cpp
@@ -37,6 +37,8 @@ int cEPGChannel::Compare(const cListObject &ListObject) const
cEPGExecutor::cEPGExecutor(cEPGSources *Sources) : cThread("xmltv2vdr importer")
{
sources=Sources;
+ forcedownload=false;
+ forceimportsrc=-1;
}
void cEPGExecutor::Action()
@@ -51,7 +53,7 @@ void cEPGExecutor::Action()
for (cEPGSource *epgs=sources->First(); epgs; epgs=sources->Next(epgs))
{
- if (epgs->RunItNow())
+ if (epgs->RunItNow(forcedownload))
{
int retries=0;
while (retries<=2)
@@ -83,15 +85,25 @@ void cEPGExecutor::Action()
}
int ret=1;
- for (cEPGSource *epgs=sources->First(); epgs; epgs=sources->Next(epgs))
+ if (forceimportsrc>=0)
{
- if (!epgs->LastRetCode())
+ cEPGSource *epgs=sources->Get(forceimportsrc);
+ if (epgs) ret=epgs->Import(*this);
+ }
+ else
+ {
+ for (cEPGSource *epgs=sources->First(); epgs; epgs=sources->Next(epgs))
{
- ret=epgs->Import(*this);
- break; // only import from the first successful source!
+ if (!epgs->LastRetCode())
+ {
+ ret=epgs->Import(*this);
+ break; // only import from the first successful source!
+ }
}
}
if (!ret) cSchedules::Cleanup(true);
+ forceimportsrc=-1;
+ forcedownload=false;
}
// -------------------------------------------------------------
@@ -169,13 +181,19 @@ time_t cEPGSource::NextRunTime(time_t Now)
return t;
}
-bool cEPGSource::RunItNow()
+bool cEPGSource::RunItNow(bool ForceDownload)
{
if (disabled) return false;
struct stat statbuf;
if (stat(epgfile,&statbuf)==-1) return true; // no database? -> execute immediately
if (!statbuf.st_size) return true; // no database? -> execute immediately
+ if (ForceDownload)
+ {
+ tsyslogs(this,"download forced");
+ return true;
+ }
+
time_t t=(time(NULL)/60)*60;
time_t nrt=NextRunTime(t);
if (!nrt) return false;
@@ -820,6 +838,7 @@ time_t cEPGSources::NextRunTime()
time_t nrt=Get(i)->NextRunTime();
if (nrt)
{
+ if (next==(time_t) -1) next=nrt;
if (nrt<next) next=nrt;
}
}
diff --git a/source.h b/source.h
index d78a5f2..751752d 100644
--- a/source.h
+++ b/source.h
@@ -79,7 +79,7 @@ public:
}
int Execute(cEPGExecutor &myExecutor);
int Import(cEPGExecutor &myExecutor);
- bool RunItNow();
+ bool RunItNow(bool ForceDownload=false);
time_t NextRunTime(time_t Now=(time_t) 0);
void Store(void);
void ChangeChannelSelection(int *Selection);
@@ -162,6 +162,7 @@ public:
time_t NextRunTime();
bool Exists(const char *Name);
cEPGSource *GetSource(const char *Name);
+ cEPGSource *GetSourceDB(const char *EpgFile);
int GetSourceIdx(const char *Name);
void Remove();
};
@@ -172,6 +173,8 @@ class cEPGExecutor : public cThread
{
private:
cEPGSources *sources;
+ bool forcedownload;
+ int forceimportsrc;
public:
cEPGExecutor(cEPGSources *Sources);
bool StillRunning()
@@ -182,6 +185,18 @@ public:
{
Cancel(3);
}
+ void SetForceDownload()
+ {
+ forcedownload=true;
+ }
+ void SetForceImport(int SourceIdx)
+ {
+ forceimportsrc=-1;
+ if (!sources) return;
+ if (SourceIdx>sources->Count()) return;
+ if (SourceIdx<0) return;
+ forceimportsrc=SourceIdx;
+ }
virtual void Action();
};
diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp
index ad2a218..740438f 100644
--- a/xmltv2vdr.cpp
+++ b/xmltv2vdr.cpp
@@ -128,10 +128,12 @@ cEPGHandler::cEPGHandler(const char *EpgFile, cEPGSources *Sources,
maps=Maps;
sources=Sources;
db=NULL;
+ now=time(NULL);
}
bool cEPGHandler::IgnoreChannel(const cChannel* Channel)
{
+ now=time(NULL);
if (!maps) return false;
if (!Channel) return false;
return maps->IgnoreChannel(Channel);
@@ -139,16 +141,17 @@ bool cEPGHandler::IgnoreChannel(const cChannel* Channel)
bool cEPGHandler::check4proc(cEvent *event, bool &spth)
{
+ spth=false;
if (!event) return false;
/*
if (import.WasChanged(event)) {
tsyslog("{%i} already seen %s",Event->EventID(),Event->Title());
}
*/
+ if (now>(event->StartTime()+event->Duration())) return false; // event in the past?
if (!maps) return false;
if (!import.DBExists()) return false;
- spth=false;
if (!maps->ProcessChannel(event->ChannelID()))
{
if (!epall) return false;
@@ -211,7 +214,7 @@ bool cEPGHandler::SetDescription(cEvent* Event, const char* Description)
bool cEPGHandler::HandleEvent(cEvent* Event)
{
- bool special_epall_timer_handling=false;
+ bool special_epall_timer_handling;
if (!check4proc(Event,special_epall_timer_handling)) return false;
int Flags=0;
@@ -269,21 +272,9 @@ bool cEPGHandler::HandleEvent(cEvent* Event)
return false;
}
- bool update=false;
-
- if (!xevent->EITEventID()) update=true;
- if (!xevent->EITDescription() && Event->Description()) update=true;
- if (xevent->EITDescription() && Event->Description() && !import.WasChanged(Event) &&
- strcasecmp(xevent->EITDescription(),Event->Description())) update=true;
-
- if (update)
- {
- import.UpdateXMLTVEvent(source,db,Event,xevent); // ignore errors
- }
-
import.PutEvent(source,db,(cSchedule *) Event->Schedule(),Event,xevent,Flags);
delete xevent;
- return false; // let VDR fix the bugs!
+ return false; // let other handlers change this event
}
bool cEPGHandler::SortSchedule(cSchedule* UNUSED(Schedule))
@@ -301,19 +292,15 @@ bool cEPGHandler::SortSchedule(cSchedule* UNUSED(Schedule))
// -------------------------------------------------------------
cEPGTimer::cEPGTimer(const char *EpgFile, cEPGSources *Sources, cEPGMappings *Maps,
- cTEXTMappings *Texts) : cThread("xmltv2vdr timer")
+ cTEXTMappings *Texts) : cThread("xmltv2vdr timer"),import(EpgFile,Maps,Texts)
{
- epgfile=EpgFile;
sources=Sources;
maps=Maps;
- import = new cImport(EpgFile,Maps,Texts);
}
void cEPGTimer::Action()
{
- struct stat statbuf;
- if (stat(epgfile,&statbuf)==-1) return; // no database? -> exit immediately
- if (!statbuf.st_size) return; // no database? -> exit immediately
+ if (!import.DBExists()) return; // no database? -> exit immediately
if (Timers.BeingEdited()) return;
Timers.IncBeingEdited();
SetPriority(19);
@@ -347,10 +334,10 @@ void cEPGTimer::Action()
if (!chan) continue;
const char *ChannelID=strdup(*event->ChannelID().ToString());
- cXMLTVEvent *xevent=import->SearchXMLTVEvent(&db,ChannelID,event);
+ cXMLTVEvent *xevent=import.SearchXMLTVEvent(&db,ChannelID,event);
if (!xevent)
{
- xevent=import->AddXMLTVEvent(source,db,ChannelID,event,event->Description());
+ xevent=import.AddXMLTVEvent(source,db,ChannelID,event,event->Description());
if (!xevent)
{
free((void*)ChannelID);
@@ -362,13 +349,13 @@ void cEPGTimer::Action()
cSchedule* schedule = (cSchedule *) schedules->GetSchedule(chan,false);
if (schedule)
{
- import->PutEvent(source,db,schedule,event,xevent,USE_SEASON);
+ import.PutEvent(source,db,schedule,event,xevent,USE_SEASON);
}
delete xevent;
}
if (db)
{
- import->Commit(source,db);
+ import.Commit(source,db);
sqlite3_close(db);
}
Timers.DecBeingEdited();
@@ -440,7 +427,6 @@ cPluginXmltv2vdr::cPluginXmltv2vdr(void) : epgexecutor(&epgsources)
last_housetime_t=0;
last_maintime_t=0;
last_epcheck_t=0;
- nextruntime=0;
wakeup=0;
insetup=false;
SetEPAll(false);
@@ -478,6 +464,33 @@ cPluginXmltv2vdr::~cPluginXmltv2vdr()
#endif
}
+int cPluginXmltv2vdr::GetLastImportSource()
+{
+ sqlite3 *db=NULL;
+ if (sqlite3_open_v2(epgfile,&db,SQLITE_OPEN_READWRITE,NULL)!=SQLITE_OK) return -1;
+
+ char sql[]="select srcidx from epg where srcidx<>99 order by starttime desc limit 1";
+ sqlite3_stmt *stmt;
+ if (sqlite3_prepare_v2(db,sql,strlen(sql),&stmt,NULL)!=SQLITE_OK)
+ {
+ sqlite3_close(db);
+ tsyslog("failed to prepare %s",sql);
+ return -1;
+ }
+
+ int idx=-1;
+ if (sqlite3_step(stmt)==SQLITE_ROW)
+ {
+ idx=sqlite3_column_int(stmt,0);
+ }
+ sqlite3_finalize(stmt);
+ sqlite3_close(db);
+ tsyslog("lastimportsource=%i",idx);
+ return idx;
+}
+
+
+
bool cPluginXmltv2vdr::EPGSourceMove(int From, int To)
{
if (From==To) return false;
@@ -573,7 +586,7 @@ bool cPluginXmltv2vdr::Start(void)
epghandler = new cEPGHandler(epgfile,&epgsources,&epgmappings,&textmappings);
epgtimer = new cEPGTimer(epgfile,&epgsources,&epgmappings,&textmappings);
housekeeping = new cHouseKeeping(epgfile);
-
+
if (sqlite3_threadsafe()==0) esyslog("sqlite3 not threadsafe!");
return true;
}
@@ -583,20 +596,17 @@ void cPluginXmltv2vdr::Stop(void)
// Stop any background activities the plugin is performing.
cSchedules::Cleanup(true);
epgtimer->Stop();
- if (epgtimer) {
- delete epgtimer;
- epgtimer=NULL;
- }
- if (housekeeping) {
- delete housekeeping;
- housekeeping=NULL;
+ if (epgtimer)
+ {
+ delete epgtimer;
+ epgtimer=NULL;
}
- epgexecutor.Stop();
- if (wakeup)
+ if (housekeeping)
{
- nextruntime=epgsources.NextRunTime();
- if (nextruntime) nextruntime-=(time_t) 180;
+ delete housekeeping;
+ housekeeping=NULL;
}
+ epgexecutor.Stop();
epgsources.Remove();
epgmappings.Remove();
textmappings.Remove();
@@ -681,7 +691,8 @@ time_t cPluginXmltv2vdr::WakeupTime(void)
{
// Return custom wakeup time for shutdown script
if (!wakeup) return (time_t) 0;
- if (!nextruntime) return (time_t) 0;
+ time_t nextruntime=epgsources.NextRunTime();
+ if (nextruntime) nextruntime-=(time_t) 180;
tsyslog("reporting wakeuptime %s",ctime(&nextruntime));
return nextruntime;
}
@@ -752,14 +763,14 @@ const char **cPluginXmltv2vdr::SVDRPHelpPages(void)
// Returns help text
static const char *HelpPages[]=
{
- "UPDT\n"
- " Start epg update",
+ "UPDT [force]\n"
+ " Start epg update from db, with force download data before",
NULL
};
return HelpPages;
}
-cString cPluginXmltv2vdr::SVDRPCommand(const char *Command, const char *UNUSED(Option), int &ReplyCode)
+cString cPluginXmltv2vdr::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
{
// Process SVDRP commands
@@ -773,15 +784,31 @@ cString cPluginXmltv2vdr::SVDRPCommand(const char *Command, const char *UNUSED(O
}
else
{
- if (epgexecutor.Start())
+ if (epgexecutor.Active())
{
- ReplyCode=250;
- output="Update started\n";
+ ReplyCode=550;
+ output="Update already running\n";
}
else
{
- ReplyCode=550;
- output="Update already running\n";
+ if (Option && strstr(Option,"force"))
+ {
+ epgexecutor.SetForceDownload();
+ }
+ else
+ {
+ epgexecutor.SetForceImport(GetLastImportSource());
+ }
+ if (epgexecutor.Start())
+ {
+ ReplyCode=250;
+ output="Update started\n";
+ }
+ else
+ {
+ ReplyCode=550;
+ output="Failed to start update\n";
+ }
}
}
}
diff --git a/xmltv2vdr.h b/xmltv2vdr.h
index 4731dde..6210d98 100644
--- a/xmltv2vdr.h
+++ b/xmltv2vdr.h
@@ -67,7 +67,7 @@ private:
cImport import;
bool epall;
sqlite3 *db;
- void closedb(void);
+ time_t now;
bool check4proc(cEvent *event, bool &spth);
public:
cEPGHandler(const char *EpgFile, cEPGSources *Sources,
@@ -90,10 +90,9 @@ public:
class cEPGTimer : public cThread
{
private:
- const char *epgfile;
cEPGSources *sources;
cEPGMappings *maps;
- cImport *import;
+ cImport import;
public:
cEPGTimer(const char *EpgFile, cEPGSources *Sources, cEPGMappings *Maps,cTEXTMappings *Texts);
bool StillRunning()
@@ -129,13 +128,13 @@ private:
time_t last_housetime_t;
time_t last_maintime_t;
time_t last_epcheck_t;
- time_t nextruntime;
char *confdir;
char *epgfile;
char *srcorder;
bool epall;
bool wakeup;
bool insetup;
+ int GetLastImportSource();
public:
void SetSetupState(bool Value)
{