diff options
-rw-r--r-- | dist/epgdata2xmltv/epgdata2xmltv.cpp | 9 | ||||
-rw-r--r-- | parse.cpp | 184 | ||||
-rw-r--r-- | parse.h | 12 | ||||
-rw-r--r-- | po/de_DE.po | 6 | ||||
-rw-r--r-- | po/it_IT.po | 5 | ||||
-rw-r--r-- | setup.cpp | 30 | ||||
-rw-r--r-- | setup.h | 2 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 47 | ||||
-rw-r--r-- | xmltv2vdr.h | 16 |
9 files changed, 264 insertions, 47 deletions
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.cpp b/dist/epgdata2xmltv/epgdata2xmltv.cpp index 7515cb0..fcef073 100644 --- a/dist/epgdata2xmltv/epgdata2xmltv.cpp +++ b/dist/epgdata2xmltv/epgdata2xmltv.cpp @@ -115,7 +115,7 @@ int cepgdata2xmltv::DownloadData(const char *url) curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 0); // don't follow redirects curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); // Send all data to this function curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &data); // Pass our 'data' struct to the callback function - curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 20971520); // Set maximum file size to get (bytes) + curl_easy_setopt(curl_handle, CURLOPT_MAXFILESIZE, 45971520); // Set maximum file size to get (bytes) curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1); // No progress meter curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); // No signaling curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 240); // Set timeout to 240 seconds @@ -210,6 +210,11 @@ int cepgdata2xmltv::Fetch(const char *dest, const char *pin, int day) return 1; } + if (ret==-63) + { + esyslog("filesize exceeded, please report this!"); + return 1; + } return 0; } @@ -274,7 +279,7 @@ int cepgdata2xmltv::Process(int argc, char *argv[]) sprintf(vgl,"%04i%02i%02i",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday); char *dest=NULL; - if (asprintf(&dest,"/tmp/epgdata_%02i.zip",day)==-1) + if (asprintf(&dest,"/tmp/%s_epgdata.zip",vgl)==-1) { esyslog("failed to allocate string"); continue; @@ -15,11 +15,13 @@ #include <langinfo.h> #include <time.h> #include <pwd.h> +#include <vdr/timers.h> #include "xmltv2vdr.h" #include "parse.h" extern char *strcatrealloc(char *dest, const char *src); +#define TEXTMapping(a) TEXTMapping_(a,texts) void cXMLTVEvent::SetTitle(const char *Title) { @@ -455,45 +457,146 @@ cEvent *cParse::GetEventBefore(cSchedule* schedule, time_t start) return NULL; } -void cParse::FetchSeasonEpisode(cEvent *event) +bool cParse::AddSeasonEpisode2TimerChannels(const char *epdir, cTEXTMappings *texts) { - if (!epdir) return; - if (!event) return; - if (!event->ShortText()) return; - if (!event->Title()) return; - char *epfile=NULL; - if (asprintf(&epfile,"%s/.eplists/lists/%s.episodes",epdir,event->Title())==-1) return; + if (!epdir) return false; + if (!texts) return false; - struct stat statbuf; - if (stat(epfile,&statbuf)==-1) + const cSchedules *schedules=NULL; + cSchedulesLock schedulesLock(true,60000); // wait up to 60 secs for lock! + schedules = cSchedules::Schedules(schedulesLock); + if (!schedules) { - free(epfile); - return; + esyslog("cannot get schedules now, trying later"); + return false; + } + + time_t start=time(NULL); + time_t stop=start+86400; + + for (cTimer *Timer = Timers.First(); Timer; Timer=Timers.Next(Timer)) + { + if (!Timer->Channel()) continue; + + cSchedule* schedule = (cSchedule *) schedules->GetSchedule(Timer->Channel()); + if (!schedule) continue; + + for (cEvent *p = schedule->Events()->First(); p; p = schedule->Events()->Next(p)) + { + if (p->StartTime()>=start && p->StartTime()<=stop && p->TableID() && p->ShortText()) + { + int season,episode; + if (FetchSeasonEpisode(epdir,p->Title(), p->ShortText(), season, episode)) + { + if ((season) || (episode)) + { + char *description=NULL; + if (p->Description()) description=strdup(p->Description()); + description = strcatrealloc(description,"\n"); + if (season) + { + cTEXTMapping *text=TEXTMapping("season"); + if (text) + { + char *value=NULL; + if (asprintf(&value,"%i",season)!=-1) + { + description = strcatrealloc(description,text->Value()); + description = strcatrealloc(description,": "); + description = strcatrealloc(description,value); + description = strcatrealloc(description,"\n"); + free(value); + } + } + } + if (episode) + { + cTEXTMapping *text=TEXTMapping("episode"); + if (text) + { + char *value=NULL; + if (asprintf(&value,"%i",episode)!=-1) + { + description = strcatrealloc(description,text->Value()); + description = strcatrealloc(description,": "); + description = strcatrealloc(description,value); + description = strcatrealloc(description,"\n"); + free(value); + } + } + } + p->SetDescription(description); + p->SetTableID(0); + free(description); + } + } + } + } + } + return true; +} + +bool cParse::FetchSeasonEpisode(const char *epdir, const char *title, const char *shorttext, int &season, int &episode) +{ + if (!epdir) return false; + if (!shorttext) return false; + if (!title) return false; + + /* + char *epfile=NULL; + if (asprintf(&epfile,"%s/%s.episodes",epdir,title)==-1) return false; + + struct stat statbuf; + if (stat(epfile,&statbuf)==-1) + { + free(epfile); + return false; + } + */ + DIR *dir=opendir(epdir); + if (!dir) return false; + struct dirent dirent_buf,*dirent; + bool found=false; + for (;;) + { + if (readdir_r(dir,&dirent_buf,&dirent)!=0) break; + if (!dirent) break; + if (dirent->d_name[0]=='.') continue; + char *pt=strrchr(dirent->d_name,'.'); + if (pt) *pt=0; + if (!strncasecmp(dirent->d_name,title,strlen(dirent->d_name))) + { + found=true; + break; + } } + closedir(dir); + if (!found) return false; + + char *epfile=NULL; + if (asprintf(&epfile,"%s/%s.episodes",epdir,dirent->d_name)==-1) return false; FILE *f=fopen(epfile,"r"); if (!f) { free(epfile); - return; + return false; } char *line=NULL; size_t length; + found=false; while (getline(&line,&length,f)!=-1) { if (line[0]=='#') continue; - char title[256]=""; - int season; - int episode; - if (sscanf(line,"%i\t%i\t%*i\t%255c",&season,&episode,title)==3) + char epshorttext[256]=""; + if (sscanf(line,"%d\t%d\t%*d\t%255c",&season,&episode,epshorttext)==3) { - char *lf=strchr(title,'\n'); + char *lf=strchr(epshorttext,'\n'); if (lf) *lf=0; - if (!strncasecmp(event->ShortText(),title,strlen(title))) + if (!strncasecmp(shorttext,epshorttext,strlen(epshorttext))) { - xevent.SetSeason(season); - xevent.SetEpisode(episode); + found=true; break; } } @@ -502,7 +605,7 @@ void cParse::FetchSeasonEpisode(cEvent *event) fclose(f); free(epfile); - return; + return found; } bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map) @@ -655,10 +758,15 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c } } - if (event->ShortText() && (strlen(event->ShortText())>0) && ((map->Flags() & USE_SEASON)==USE_SEASON)) + if (epdir && xevent->ShortText() && (strlen(xevent->ShortText())>0) && ((map->Flags() & USE_SEASON)==USE_SEASON)) { // Try to fetch season and episode from eplist - FetchSeasonEpisode(event); + int season,episode; + if (FetchSeasonEpisode(epdir,xevent->Title(),xevent->ShortText(),season,episode)) + { + xevent->SetSeason(season); + xevent->SetEpisode(episode); + } } if ((map->Flags() & USE_LONGTEXT)==USE_LONGTEXT) @@ -1032,7 +1140,7 @@ bool cParse::FetchEvent(xmlNodePtr enode) return (xevent.Title()!=NULL); } -cTEXTMapping *cParse::TEXTMapping(const char *Name) +cTEXTMapping *cParse::TEXTMapping_(const char *Name, cTEXTMappings *texts) { if (!texts->Count()) return NULL; for (cTEXTMapping *textmap=texts->First(); textmap; textmap=texts->Next(textmap)) @@ -1247,8 +1355,9 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) else { time_t start=xevent.StartTime(); - source->Elog("cannot find existing event in epg.data for xmltv-event %s@%s", - xevent.Title(),ctime_r(&start,(char *) &cbuf)); + source->Elog("no event in epg for %s@%s (%s)", + xevent.Title(),ctime_r(&start,(char *) &cbuf), + channel->Name()); } } } @@ -1298,14 +1407,23 @@ cParse::cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts) source->Dlog("vdr codeset is '%s'",CodeSet ? CodeSet : "US-ASCII//TRANSLIT"); conv = new cCharSetConv("UTF-8",CodeSet ? CodeSet : "US-ASCII//TRANSLIT"); - struct passwd *pw=getpwuid(getuid()); - if (pw) - { - epdir=strdup(pw->pw_dir); - } - else + struct passwd pwd,*pwdbuf; + char buf[1024]; + getpwuid_r(getuid(),&pwd,buf,sizeof(buf),&pwdbuf); + if (pwdbuf) { - epdir=NULL; + if (asprintf(&epdir,"%s/.eplists/lists",pwdbuf->pw_dir)!=-1) + { + if (access(epdir,R_OK)) + { + free(epdir); + epdir=NULL; + } + } + else + { + epdir=NULL; + } } } @@ -189,18 +189,20 @@ private: u_long DoSum(u_long sum, const char *buf, int nBytes); cEvent *SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent); time_t ConvertXMLTVTime2UnixTime(char *xmltvtime); - bool FetchEvent(xmlNodePtr node); - void FetchSeasonEpisode(cEvent *event); + bool FetchEvent(xmlNodePtr node); + static bool FetchSeasonEpisode(const char *epdir, const char *title, const char *shorttext, + int &season, int &episode); cEPGMapping *EPGMapping(const char *ChannelName); - cTEXTMapping *TEXTMapping(const char *Name); + static cTEXTMapping *TEXTMapping_(const char *Name, cTEXTMappings *texts); bool PutEvent(cSchedule* schedule,cEvent *event,cXMLTVEvent *xevent, cEPGMapping *map); - cEvent *GetEventBefore(cSchedule *schedule, time_t start); + cEvent *GetEventBefore(cSchedule *schedule, time_t start); public: cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts); ~cParse(); int Process(cEPGExecutor &myExecutor, char *buffer, int bufsize); static void InitLibXML(); - static void CleanupLibXML(); + static void CleanupLibXML(); + static bool AddSeasonEpisode2TimerChannels(const char *epdir, cTEXTMappings *Texts); }; #endif diff --git a/po/de_DE.po b/po/de_DE.po index 1d894b8..bd66905 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2011-11-25 19:04+0100\n" +"POT-Creation-Date: 2012-01-13 14:04+0100\n" "PO-Revision-Date: 2010-12-23 23:59+0100\n" "Last-Translator: Jochen Dolze <vdr@dolze.de>\n" "Language-Team: <vdr@linuxtv.org>\n" @@ -31,6 +31,9 @@ msgstr "Ausführung um" msgid "automatic wakeup" msgstr "automatisch Aufwachen" +msgid "add season/episode on all timer channels" +msgstr "Staffel/Episode an alle Timerkanäle anhängen" + msgid "text mapping" msgstr "Textzuordnungen" @@ -240,3 +243,4 @@ msgstr "xmltv2vdr plugin ist noch aktiv" msgid "Imports xmltv epg into vdr" msgstr "Importiert xmltv epg in den VDR" + diff --git a/po/it_IT.po b/po/it_IT.po index 63df24b..56fdae0 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2011-11-25 19:04+0100\n" +"POT-Creation-Date: 2012-01-13 14:04+0100\n" "PO-Revision-Date: 2011-03-05 15:45+0100\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Language-Team: <vdr@linuxtv.org>\n" @@ -34,6 +34,9 @@ msgstr "Ora esecuzione" msgid "automatic wakeup" msgstr "Risveglio automatico" +msgid "add season/episode on all timer channels" +msgstr "" + msgid "text mapping" msgstr "Mappatura testo" @@ -60,6 +60,7 @@ cMenuSetupXmltv2vdr::cMenuSetupXmltv2vdr(cPluginXmltv2vdr *Plugin) sourcesBegin=sourcesEnd=mappingBegin=mappingEnd=mappingEntry=0; wakeup=(int) baseplugin->WakeUp; upstart=(int) baseplugin->UpStart; + epall=(int) baseplugin->EPAll(); exectime=baseplugin->ExecTime(); cs=NULL; cm=NULL; @@ -87,6 +88,22 @@ void cMenuSetupXmltv2vdr::Output(void) Add(new cMenuEditTimeItem(tr("update at"),&exectime),true); Add(new cMenuEditBoolItem(tr("automatic wakeup"),&wakeup),true); } + + epEntry=0; + struct passwd *pw=getpwuid(getuid()); + if (pw) + { + char *path=NULL; + if (asprintf(&path,"%s/.eplists/lists",pw->pw_dir)!=-1) + { + if (!access(path,R_OK)) + { + Add(new cMenuEditBoolItem(tr("add season/episode on all timer channels"),&epall),true); + } + free(path); + } + } + Add(new cOsdItem(tr("text mapping")),true); mappingEntry=Current(); Add(NewTitle(tr("epg sources")),true); @@ -178,10 +195,12 @@ void cMenuSetupXmltv2vdr::Store(void) SetupStore("options.exectime",exectime); SetupStore("options.wakeup",wakeup); SetupStore("options.upstart",upstart); + SetupStore("options.epall",epall); baseplugin->UpStart=upstart; baseplugin->WakeUp=wakeup; baseplugin->SetExecTime(exectime); + baseplugin->SetEPAll((bool) epall); } eOSState cMenuSetupXmltv2vdr::edit() @@ -215,6 +234,10 @@ eOSState cMenuSetupXmltv2vdr::ProcessKey(eKeys Key) { if (Current()==updateEntry) Output(); } + if ((Key==kLeft) || (Key==kRight) || (Key==kLeft|k_Repeat) || (Key==kRight|k_Repeat)) + { + if ((epEntry) && (Current()==epEntry)) Output(); + } if ((Key==kDown) || (Key==kUp) || (Key==kDown|k_Repeat) || (Key==kUp|k_Repeat)) { if ((Current()>=sourcesBegin) && (Current()<=sourcesEnd)) @@ -862,8 +885,13 @@ cMenuSetupXmltv2vdrChannelSource::cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2 SetSection(cString::sprintf("%s '%s' : %s",trVDR("Plugin"), baseplugin->Name(), epgsrc->Name())); + time_t day; + int weekday,start; + Add(NewTitle(tr("options"))); - days=epgsrc->DaysInAdvance(); + Add(new cMenuEditDateItem(trVDR("Day"),&day,&weekday)); + Add(new cMenuEditTimeItem(trVDR("Start"),&start)); + days=epgsrc->DaysInAdvance(); Add(new cMenuEditIntItem(tr("days in advance"),&days,1,epgsrc->DaysMax())); if (epgsrc->NeedPin()) { @@ -38,11 +38,13 @@ private: int sourcesBegin,sourcesEnd; int mappingEntry; int updateEntry; + int epEntry; eOSState edit(void); void generatesumchannellist(); int exectime; int wakeup; int upstart; + int epall; public: void Output(void); static cOsdItem *NewTitle(const char *s); diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp index 52aa814..9984422 100644 --- a/xmltv2vdr.cpp +++ b/xmltv2vdr.cpp @@ -11,6 +11,7 @@ #include <sys/wait.h> #include <sys/ioctl.h> #include <stdarg.h> +#include <pwd.h> #include "xmltv2vdr.h" #include "parse.h" #include "extpipe.h" @@ -46,6 +47,8 @@ int cEPGChannel::Compare(const cListObject &ListObject) const cEPGExecutor::cEPGExecutor(cEPGSources *Sources) : cThread("xmltv2vdr importer") { sources=Sources; + textmappings=NULL; + epall=false; } void cEPGExecutor::Action() @@ -85,9 +88,42 @@ void cEPGExecutor::Action() if (retries>=2) epgs->Elog("skipping after %i retries",retries); if (!ret) break; // TODO: check if we must execute second/third source! } + if (!ret && epall && textmappings) + { + struct passwd pwd,*pwdbuf; + char buf[1024]; + getpwuid_r(getuid(),&pwd,buf,sizeof(buf),&pwdbuf); + if (pwdbuf) + { + char *epdir; + if (asprintf(&epdir,"%s/.eplists/lists",pwdbuf->pw_dir)!=-1) + { + if (!access(epdir,R_OK)) + { + int retries=0; + while (retries<=2) + { + + if (!cParse::AddSeasonEpisode2TimerChannels(epdir,textmappings)) + { + dsyslog("waiting 60 seconds"); + retries++; + } + else + { + break; + } + } + } + free(epdir); + } + } + } if (!ret) cSchedules::Cleanup(true); } + + // ------------------------------------------------------------- cEPGSource::cEPGSource(const char *Name, const char *ConfDir, cEPGMappings *Maps, cTEXTMappings *Texts) @@ -342,7 +378,8 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) int l_err=0; int ret=0; - if ((Log) && (lastexec)) { + if ((Log) && (lastexec)) + { free(Log); Log=NULL; loglen=0; @@ -815,6 +852,7 @@ cPluginXmltv2vdr::cPluginXmltv2vdr(void) : epgexecutor(&epgsources) UpStart=1; last_exectime_t=0; exectime=200; + SetEPAll(false); SetExecTime(exectime); TEXTMappingAdd(new cTEXTMapping("country",tr("country"))); TEXTMappingAdd(new cTEXTMapping("date",tr("year"))); @@ -874,7 +912,8 @@ bool cPluginXmltv2vdr::Start(void) } else { - if (!exectime_t) { + if (!exectime_t) + { exectime_t=time(NULL)-60; last_exectime_t=exectime_t; } @@ -998,6 +1037,10 @@ bool cPluginXmltv2vdr::SetupParse(const char *Name, const char *Value) { UpStart=atoi(Value); } + else if (!strcasecmp(Name,"options.epall")) + { + SetEPAll((bool) atoi(Value)); + } else return false; return true; } diff --git a/xmltv2vdr.h b/xmltv2vdr.h index 8acfac2..aa173fd 100644 --- a/xmltv2vdr.h +++ b/xmltv2vdr.h @@ -14,7 +14,7 @@ #include "maps.h" #include "parse.h" -static const char *VERSION = "0.0.2"; +static const char *VERSION = "0.0.3pre"; static const char *DESCRIPTION = trNOOP("Imports xmltv epg into vdr"); class cEPGChannel : public cListObject @@ -121,7 +121,9 @@ class cEPGSources : public cList<cEPGSource> {}; class cEPGExecutor : public cThread { private: - cEPGSources *sources; + cEPGSources *sources; + cTEXTMappings *textmappings; + bool epall; public: cEPGExecutor(cEPGSources *Sources); bool StillRunning() @@ -132,6 +134,10 @@ public: { Cancel(3); } + void SetOptions(bool EPAll, cTEXTMappings *TextMappings) { + epall=EPAll; + textmappings=TextMappings; + } virtual void Action(); }; @@ -149,6 +155,7 @@ private: int exectime; time_t exectime_t,last_exectime_t; char *confdir; + bool epall; public: int ExecTime() { @@ -157,6 +164,11 @@ public: void SetExecTime(int ExecTime); bool UpStart; bool WakeUp; + void SetEPAll(bool Value) { + epall=Value; + epgexecutor.SetOptions(epall,&textmappings); + } + bool EPAll() { return epall; } void ReadInEPGSources(bool Reload=false); int EPGSourceCount() { |