diff options
-rw-r--r-- | dist/epgdata2xmltv/epgdata2xmltv.xsl | 16 | ||||
-rw-r--r-- | extpipe.cpp | 117 | ||||
-rw-r--r-- | extpipe.h | 13 | ||||
-rw-r--r-- | parse.cpp | 40 | ||||
-rw-r--r-- | parse.h | 16 | ||||
-rw-r--r-- | po/de_DE.po | 9 | ||||
-rw-r--r-- | po/it_IT.po | 7 | ||||
-rw-r--r-- | setup.cpp | 2 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 181 | ||||
-rw-r--r-- | xmltv2vdr.h | 3 |
10 files changed, 243 insertions, 161 deletions
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.xsl b/dist/epgdata2xmltv/epgdata2xmltv.xsl index a85e0c2..4f68091 100644 --- a/dist/epgdata2xmltv/epgdata2xmltv.xsl +++ b/dist/epgdata2xmltv/epgdata2xmltv.xsl @@ -7,21 +7,7 @@ <xsl:template match="/"> <xsl:for-each select="//data[d2=$channelnum]"> - -<!-- -<xsl:variable name="start_xmltv"> -<xsl:value-of select="d4"/> -</xsl:variable> - -<xsl:variable name="stop_xmltv"> -<xsl:value-of select="d5"/> -</xsl:variable> - -<xsl:variable name="vps_xmltv"> -<xsl:value-of select="d8"/> -</xsl:variable> ---> - +<xsl:sort select="d4"/> <xsl:variable name="EVENTID"> <xsl:value-of select="d0"/> </xsl:variable> diff --git a/extpipe.cpp b/extpipe.cpp index c596226..4ce2c80 100644 --- a/extpipe.cpp +++ b/extpipe.cpp @@ -12,7 +12,8 @@ cExtPipe::cExtPipe(void) { pid = -1; - f = NULL; + f_stderr = -1; + f_stdout= -1; } cExtPipe::~cExtPipe() @@ -21,68 +22,100 @@ cExtPipe::~cExtPipe() Close(status); } -bool cExtPipe::Open(const char *Command, const char *Mode) +bool cExtPipe::Open(const char *Command) { - int fd[2]; + int fd_stdout[2]; + int fd_stderr[2]; - if (pipe(fd) < 0) + if (pipe(fd_stdout) < 0) { LOG_ERROR; return false; } - if ((pid = fork()) < 0) // fork failed + if (pipe(fd_stderr) < 0) { + close(fd_stdout[0]); + close(fd_stdout[1]); LOG_ERROR; - close(fd[0]); - close(fd[1]); return false; } - const char *mode = "w"; - int iopipe = 0; + if ((pid = fork()) < 0) // fork failed + { + LOG_ERROR; + close(fd_stdout[0]); + close(fd_stdout[1]); + close(fd_stderr[0]); + close(fd_stderr[1]); + return false; + } if (pid > 0) // parent process { - if (strcmp(Mode, "r") == 0) - { - mode = "r"; - iopipe = 1; + close(fd_stdout[1]); // close write fd, we need only read fd + close(fd_stderr[1]); // close write fd, we need only read fd + int flags=fcntl(fd_stdout[0],F_GETFL,0); + if (flags==-1) { + LOG_ERROR; + close(fd_stdout[0]); + close(fd_stderr[0]); + return false; } - close(fd[iopipe]); - if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) - { + flags|=O_NONBLOCK; + if (fcntl(fd_stdout[0],F_SETFL,flags)==-1) { + LOG_ERROR; + close(fd_stdout[0]); + close(fd_stderr[0]); + return false; + } + flags=fcntl(fd_stderr[0],F_GETFL,0); + if (flags==-1) { LOG_ERROR; - close(fd[1 - iopipe]); + close(fd_stdout[0]); + close(fd_stderr[0]); + return false; + } - return f != NULL; + if (fcntl(fd_stderr[0],F_SETFL,flags)==-1) { + LOG_ERROR; + close(fd_stdout[0]); + close(fd_stderr[0]); + return false; + } + f_stdout = fd_stdout[0]; + f_stderr = fd_stderr[0]; + return true; } else // child process { - int iofd = STDOUT_FILENO; - if (strcmp(Mode, "w") == 0) + close(fd_stdout[0]); // close read fd, we need only write fd + close(fd_stderr[0]); // close read fd, we need only write fd + + if (dup2(fd_stdout[1], STDOUT_FILENO) == -1) // now redirect { - mode = "r"; - iopipe = 1; - iofd = STDIN_FILENO; + LOG_ERROR; + close(fd_stderr[1]); + close(fd_stdout[1]); + _exit(-1); } - close(fd[iopipe]); - if (dup2(fd[1 - iopipe], iofd) == -1) // now redirect + + if (dup2(fd_stderr[1], STDERR_FILENO) == -1) // now redirect { LOG_ERROR; - close(fd[1 - iopipe]); + close(fd_stderr[1]); + close(fd_stdout[1]); _exit(-1); } - else + + int MaxPossibleFileDescriptors = getdtablesize(); + for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) + close(i); //close all dup'ed filedescriptors + if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1) { - int MaxPossibleFileDescriptors = getdtablesize(); - for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++) - close(i); //close all dup'ed filedescriptors - if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1) - { - LOG_ERROR_STR(Command); - close(fd[1 - iopipe]); - _exit(-1); - } + LOG_ERROR_STR(Command); + close(fd_stderr[1]); + close(fd_stdout[1]); + _exit(-1); } _exit(0); } @@ -92,10 +125,16 @@ int cExtPipe::Close(int &status) { int ret = -1; - if (f) + if (f_stderr!=-1) + { + close(f_stderr); + f_stderr = -1; + } + + if (f_stdout!=-1) { - fclose(f); - f = NULL; + close(f_stdout); + f_stdout=-1; } if (pid > 0) @@ -8,19 +8,20 @@ class cExtPipe { private: pid_t pid; - FILE *f; + int f_stdout; + int f_stderr; public: cExtPipe(void); ~cExtPipe(); - FILE *Out() + int Out() const { - return f; + return f_stdout; } - operator FILE* () const + int Err() const { - return f; + return f_stderr; } - bool Open(const char *Command, const char *Mode); + bool Open(const char *Command); int Close(int &status); }; @@ -21,7 +21,9 @@ extern char *strcatrealloc(char *dest, const char *src); void cXMLTVEvent::SetTitle(const char *Title) { title = strcpyrealloc(title, Title); - if (title) title = compactspace(title); + if (title) { + title = compactspace(title); + } } void cXMLTVEvent::SetOrigTitle(const char *OrigTitle) @@ -420,7 +422,8 @@ cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent) return f; } -bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map) +bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map, + int mapindex) { if (!schedule) return false; if (!xevent) return false; @@ -441,9 +444,11 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c { esyslog("xmltv2vdr: '%s' ERROR xmltv data overlaps:",name); time_t lstart=last->StartTime(); - esyslog("xmltv2vdr: '%s' ERROR last event '%s' @%s", name,last->Title(), + esyslog("xmltv2vdr: '%s' ERROR last event '%s' (%s) @%s", name, + *schedule->ChannelID().ToString(),last->Title(), ctime(&lstart)); - esyslog("xmltv2vdr: '%s' ERROR next event '%s' @%s", name,xevent->Title(), + esyslog("xmltv2vdr: '%s' ERROR next event '%s' (%s) @%s", name, + *map->ChannelIDs()[mapindex].ToString(),xevent->Title(), ctime(&start)); return false; } @@ -466,6 +471,7 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c event->SetDescription(xevent->Description()); event->SetVersion(0); schedule->AddEvent(event); + schedule->Sort(); dsyslog("xmltv2vdr: '%s' adding event '%s' @%s",name,xevent->Title(),ctime(&start)); } else @@ -867,6 +873,14 @@ bool cParse::Process(char *buffer, int bufsize) return false; } + cSchedulesLock schedulesLock(true,25000); // wait up to 25 secs for lock! + const cSchedules *schedules = cSchedules::Schedules(schedulesLock); + if (!schedules) + { + esyslog("xmltv2vdr: '%s' cannot get schedules, try later",name); + return false; + } + time_t begin=time(NULL); xmlNodePtr node=rootnode->xmlChildrenNode; cEPGMapping *oldmap=NULL; @@ -964,16 +978,7 @@ bool cParse::Process(char *buffer, int bufsize) if (stoptime) xevent.SetDuration(stoptime-starttime); if (!FetchEvent(node)) // sets xevent { - node=node->next; - continue; - } - cSchedulesLock *schedulesLock = new cSchedulesLock(true,5000); // to be safe ;) - const cSchedules *schedules = cSchedules::Schedules(*schedulesLock); - if (!schedules) - { - if (lerr!=PARSE_NOSCHEDULES) - esyslog("xmltv2vdr: '%s' ERROR cannot get schedules",name); - lerr=PARSE_NOSCHEDULES; + dsyslog("xmltv2vdr: '%s' failed to fetch event",name); node=node->next; continue; } @@ -1003,14 +1008,14 @@ bool cParse::Process(char *buffer, int bufsize) if (addevents) { cEvent *event=SearchEvent(schedule,&xevent); - PutEvent(schedule,event,&xevent,map); + PutEvent(schedule,event,&xevent,map,i); } else { if (!schedule->Index()) { if (lerr!=PARSE_EMPTYSCHEDULE) - esyslog("xmltv2vdr: '%s' ERROR cannot merge into empty epg (%s) - try add optiopn", + esyslog("xmltv2vdr: '%s' ERROR cannot merge into empty epg (%s) - try add option", name,channel->Name()); lerr=PARSE_EMPTYSCHEDULE; } @@ -1021,7 +1026,7 @@ bool cParse::Process(char *buffer, int bufsize) { if ((event=SearchEvent(schedule,&xevent))) { - PutEvent(schedule,event,&xevent,map); + PutEvent(schedule,event,&xevent,map,i); } else { @@ -1033,7 +1038,6 @@ bool cParse::Process(char *buffer, int bufsize) } } } - delete schedulesLock; node=node->next; } xmlFreeDoc(xmltv); @@ -147,13 +147,12 @@ class cParse enum { PARSE_NOERROR=0, - PARSE_NOSCHEDULE=1, - PARSE_NOCHANNEL=2, - PARSE_NOSCHEDULES=3, - PARSE_XMLTVERR=4, - PARSE_NOMAPPING=5, - PARSE_NOCHANNELID=6, - PARSE_EMPTYSCHEDULE=7 + PARSE_NOSCHEDULE, + PARSE_NOCHANNEL, + PARSE_XMLTVERR, + PARSE_NOMAPPING, + PARSE_NOCHANNELID, + PARSE_EMPTYSCHEDULE }; private: @@ -170,7 +169,8 @@ private: bool FetchEvent(xmlNodePtr node); cEPGMapping *EPGMapping(const char *ChannelName); cTEXTMapping *TEXTMapping(const char *Name); - bool PutEvent(cSchedule* schedule,cEvent *event,cXMLTVEvent *xevent, cEPGMapping *map); + bool PutEvent(cSchedule* schedule,cEvent *event,cXMLTVEvent *xevent, cEPGMapping *map, + int mapindex); public: cParse(const char *Name, cEPGMappings *Maps, cTEXTMappings *Texts); ~cParse(); diff --git a/po/de_DE.po b/po/de_DE.po index 29db134..728c8ea 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-07-28 17:56+0200\n" +"POT-Creation-Date: 2011-08-01 00:24+0200\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" @@ -187,12 +187,11 @@ msgstr "entfernen" msgid "Button$Map" msgstr "hinzufügen" -msgid "Copy settings to all channels?" -msgstr "" +msgid "Copy to all mapped channels?" +msgstr "Auf zugewiesene Kanäle kopieren?" -#, fuzzy msgid "Reset all channel settings?" -msgstr "EPG Quellkanal Optionen" +msgstr "Kanaleinstellungen zurücksetzen?" msgid "Button$Choose" msgstr "auswählen" diff --git a/po/it_IT.po b/po/it_IT.po index 1c0d2e6..e9c0dac 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-07-28 17:56+0200\n" +"POT-Creation-Date: 2011-08-01 00:24+0200\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" @@ -190,12 +190,11 @@ msgstr "Non mappare" msgid "Button$Map" msgstr "Mappare" -msgid "Copy settings to all channels?" +msgid "Copy to all mapped channels?" msgstr "" -#, fuzzy msgid "Reset all channel settings?" -msgstr "Opzioni canali sorgente EPG" +msgstr "" msgid "Button$Choose" msgstr "Scegli" @@ -976,7 +976,7 @@ eOSState cMenuSetupXmltv2vdrChannelMap::ProcessKey (eKeys Key) case kBlue: // copy if ((Current()<cm) && (baseplugin)) { - if (Skins.Message(mtInfo,tr("Copy settings to all channels?"))==kOk) + if (Skins.Message(mtInfo,tr("Copy to all mapped channels?"))==kOk) { const char *oldchannel=channel; cEPGMapping *tmap=map; diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp index bc52e8b..533bf2c 100644 --- a/xmltv2vdr.cpp +++ b/xmltv2vdr.cpp @@ -80,7 +80,7 @@ cEPGSource::cEPGSource(const char *Name, const char *ConfDir, cEPGMappings *Maps name=strdup(Name); confdir=strdup(ConfDir); pin=NULL; - pipe=false; + usepipe=false; needpin=false; daysinadvance=0; ready2parse=ReadConfig(); @@ -123,12 +123,12 @@ bool cEPGSource::ReadConfig() if (!strncmp(line,"pipe",4)) { dsyslog("xmltv2vdr: '%s' is providing data through a pipe",name); - pipe=true; + usepipe=true; } else { dsyslog("xmltv2vdr: '%s' is providing data through a file",name); - pipe=false; + usepipe=false; } char *ndt=strchr(line,';'); if (ndt) @@ -262,15 +262,66 @@ bool cEPGSource::ReadConfig() return true; } +int cEPGSource::ReadOutput(char *&result, size_t &l) +{ + int ret=0; + char *fname=NULL; + if (asprintf(&fname,"%s/%s.xmltv",EPGSOURCES,name)==-1) + { + esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + return 134; + } + dsyslog("xmltv2vdr: '%s' reading from '%s'",name,fname); + + int fd=open(fname,O_RDONLY); + if (fd==-1) + { + esyslog("xmltv2vdr: '%s' ERROR failed to open '%s'",name,fname); + free(fname); + return 157; + } + + struct stat statbuf; + if (fstat(fd,&statbuf)==-1) + { + esyslog("xmltv2vdr: '%s' ERROR failed to stat '%s'",name,fname); + close(fd); + free(fname); + return 157; + } + l=statbuf.st_size; + result=(char *) malloc(l+1); + if (!result) + { + close(fd); + free(fname); + esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + return 134; + } + if (read(fd,result,statbuf.st_size)==statbuf.st_size) + { + } + else + { + esyslog("xmltv2vdr: '%s' ERROR failed to read '%s'",name,fname); + ret=149; + } + free(result); + close(fd); + free(fname); + return ret; +} + int cEPGSource::Execute() { if (!ready2parse) return false; if (!parse) return false; - char *result=NULL; - int l=0; + char *r_out=NULL; + char *r_err=NULL; + int l_out=0; + int l_err=0; int ret=0; - cExtPipe p; char *cmd=NULL; if (asprintf(&cmd,"%s %i '%s'",name,daysinadvance,pin ? pin : "")==-1) @@ -298,8 +349,9 @@ int cEPGSource::Execute() strcat(cmd," "); } } - dsyslog("xmltv2vdr: '%s' %s",name,cmd); - if (!p.Open(cmd,"r")) + //dsyslog("xmltv2vdr: '%s' %s",name,cmd); + cExtPipe p; + if (!p.Open(cmd)) { free(cmd); esyslog("xmltv2vdr: '%s' ERROR failed to open pipe",name); @@ -307,23 +359,55 @@ int cEPGSource::Execute() } free(cmd); dsyslog("xmltv2vdr: '%s' executing epgsource",name); - if (pipe) - { - int c; - while ((c=fgetc(p.Out()))!=EOF) - { - if (l%20==0) result=(char *) realloc(result, l+21); - result[l++]=c; + + int fdsopen=2; + while (fdsopen>0) { + struct pollfd fds[2]; + fds[0].fd=p.Out(); + fds[0].events=POLLIN; + fds[1].fd=p.Err(); + fds[1].events=POLLIN; + if (poll(fds,2,500)>=0) { + if (fds[0].revents & POLLIN) { + unsigned char c; + if (read(p.Out(),&c,1)==1) + { + if (l_out%20==0) r_out=(char *) realloc(r_out, l_out+21); + r_out[l_out++]=c; + } + } + if (fds[1].revents & POLLIN) { + unsigned char c; + if (read(p.Err(),&c,1)==1) + { + if (l_err%20==0) r_err=(char *) realloc(r_err, l_err+21); + r_err[l_err++]=c; + } + } + if (fds[0].revents & POLLHUP) { + fdsopen--; + } + if (fds[1].revents & POLLHUP) { + fdsopen--; + } + } else { + esyslog("xmltv2vdr: '%s' ERROR polling",name); + break; } + } + if (r_out) r_out[l_out]=0; + if (r_err) r_err[l_err]=0; + + if (usepipe) + { int status; if (p.Close(status)>0) { int returncode=WEXITSTATUS(status); - if ((!returncode) && (result)) + if ((!returncode) && (r_out)) { dsyslog("xmltv2vdr: '%s' parsing output",name); - result[l]=0; - if (!parse->Process(result,l)) + if (!parse->Process(r_out,l_out)) { esyslog("xmltv2vdr: '%s' ERROR failed to parse output",name); ret=141; @@ -340,67 +424,26 @@ int cEPGSource::Execute() esyslog("xmltv2vdr: '%s' ERROR failed to execute",name); ret=126; } - if (result) free(result); } else { - while ((fgetc(p.Out()))!=EOF) { } - int status; if (p.Close(status)>0) { int returncode=WEXITSTATUS(status); if (!returncode) { - char *fname=NULL; - if (asprintf(&fname,"%s/%s.xmltv",EPGSOURCES,name)==-1) - { - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); - return 134; - } - dsyslog("xmltv2vdr: '%s' reading from '%s'",name,fname); - - int fd=open(fname,O_RDONLY); - if (fd==-1) - { - esyslog("xmltv2vdr: '%s' ERROR failed to open '%s'",name,fname); - free(fname); - return 157; - } - - struct stat statbuf; - if (fstat(fd,&statbuf)==-1) - { - esyslog("xmltv2vdr: '%s' ERROR failed to stat '%s'",name,fname); - close(fd); - free(fname); - return 157; - } - l=statbuf.st_size; - result=(char *) malloc(l+1); - if (!result) - { - close(fd); - free(fname); - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); - return 134; - } - if (read(fd,result,statbuf.st_size)==statbuf.st_size) - { + size_t l; + char *result=NULL; + ret=ReadOutput(result,l); + if ((!ret) && (result)) { if (!parse->Process(result,l)) { esyslog("xmltv2vdr: '%s' failed to parse output",name); ret=149; } } - else - { - esyslog("xmltv2vdr: '%s' ERROR failed to read '%s'",name,fname); - ret=149; - } - free(result); - close(fd); - free(fname); + if (result) free(result); } else { @@ -409,6 +452,16 @@ int cEPGSource::Execute() } } } + if (r_out) free(r_out); + if (r_err) { + char *pch=strtok(r_err,"\n"); + while (pch) { + esyslog("xmltv2vdr: '%s' ERROR %s",name,pch); + pch=strtok(NULL,"\n"); + } + free(r_err); + } + return ret; } diff --git a/xmltv2vdr.h b/xmltv2vdr.h index 1b63eab..1d05782 100644 --- a/xmltv2vdr.h +++ b/xmltv2vdr.h @@ -50,11 +50,12 @@ private: const char *pin; cParse *parse; bool ready2parse; - bool pipe; + bool usepipe; bool needpin; int daysinadvance; int daysmax; bool ReadConfig(); + int ReadOutput(char *&result, size_t &l); cEPGChannels channels; public: cEPGSource(const char *Name,const char *ConfDir,cEPGMappings *Maps,cTEXTMappings *Texts); |