diff options
-rw-r--r-- | Makefile_ | 14 | ||||
-rw-r--r-- | import.cpp | 73 | ||||
-rw-r--r-- | import.h | 3 | ||||
-rw-r--r-- | parse.cpp | 21 | ||||
-rw-r--r-- | source.cpp | 31 | ||||
-rw-r--r-- | source.h | 17 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 121 | ||||
-rw-r--r-- | xmltv2vdr.h | 7 |
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 @@ -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; @@ -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); @@ -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"))) { @@ -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; } } @@ -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) { |