diff options
-rw-r--r-- | dist/epgdata2xmltv/epgdata2xmltv.xsl | 2 | ||||
-rw-r--r-- | parse.cpp | 232 | ||||
-rw-r--r-- | parse.h | 10 | ||||
-rw-r--r-- | po/de_DE.po | 43 | ||||
-rw-r--r-- | po/it_IT.po | 43 | ||||
-rw-r--r-- | setup.cpp | 291 | ||||
-rw-r--r-- | setup.h | 35 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 264 | ||||
-rw-r--r-- | xmltv2vdr.h | 63 |
9 files changed, 756 insertions, 227 deletions
diff --git a/dist/epgdata2xmltv/epgdata2xmltv.xsl b/dist/epgdata2xmltv/epgdata2xmltv.xsl index 4f68091..7eac71b 100644 --- a/dist/epgdata2xmltv/epgdata2xmltv.xsl +++ b/dist/epgdata2xmltv/epgdata2xmltv.xsl @@ -7,7 +7,7 @@ <xsl:template match="/"> <xsl:for-each select="//data[d2=$channelnum]"> -<xsl:sort select="d4"/> +<!-- <xsl:sort select="d4"/> --> <xsl:variable name="EVENTID"> <xsl:value-of select="d0"/> </xsl:variable> @@ -13,6 +13,7 @@ #include <unistd.h> #include <locale.h> #include <langinfo.h> +#include <time.h> #include "xmltv2vdr.h" #include "parse.h" @@ -22,7 +23,8 @@ extern char *strcatrealloc(char *dest, const char *src); void cXMLTVEvent::SetTitle(const char *Title) { title = strcpyrealloc(title, Title); - if (title) { + if (title) + { title = compactspace(title); } } @@ -332,7 +334,6 @@ char *cParse::RemoveNonASCII(const char *src) cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent) { if (!xevent) return NULL; - if (!xevent->Duration()) return NULL; if (!xevent->StartTime()) return NULL; if (!xevent->Title()) return NULL; cEvent *f=NULL; @@ -352,7 +353,8 @@ cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent) if (f) return f; // 3rd with StartTime +/- WaitTime int maxdiff=INT_MAX; - int eventTimeDiff=xevent->Duration()/4; + int eventTimeDiff=0; + if (xevent->Duration()) eventTimeDiff=xevent->Duration()/4; if (eventTimeDiff<600) eventTimeDiff=600; for (cEvent *p = schedule->Events()->First(); p; p = schedule->Events()->Next(p)) { @@ -412,7 +414,7 @@ cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent) if (diff<=maxdiff) { if (p->TableID()!=0) - dsyslog("xmltv2vdr: '%s' found '%s' for '%s'",name,p->Title(),xevent->Title()); + source->Dlog("found '%s' for '%s'",p->Title(),xevent->Title()); f=p; maxdiff=diff; } @@ -423,43 +425,133 @@ cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent) return f; } -bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map, - int mapindex) +cEvent *cParse::GetEventBefore(cSchedule* schedule, time_t start) +{ + if (!schedule) return NULL; + if (!schedule->Events()) return NULL; + if (!schedule->Events()->Count()) return NULL; + cEvent *last=schedule->Events()->Last(); + if ((last) && (last->StartTime()<start)) return last; + for (cEvent *p=schedule->Events()->First(); p; p=schedule->Events()->Next(p)) + { + if (p->StartTime()>start) + { + return (cEvent *) p->Prev(); + } + } + if (last) return last; + return NULL; +} + +bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map) { if (!schedule) return false; if (!xevent) return false; if (!map) return false; - time_t start; + struct tm tm; + char from[80]; + char till[80]; + time_t start,end; if (!event) { if ((map->Flags() & OPT_APPEND)==OPT_APPEND) { start=xevent->StartTime(); - /* checking the event sequence */ - cEvent *last=NULL; - if (schedule->Index()) last=schedule->Events()->Last(); - if (last) + end=start+xevent->Duration(); + + /* checking the "space" for our new event */ + cEvent *prev=GetEventBefore(schedule,start); + if (prev) { - if (start<last->StartTime()) + if (cEvent *next=(cEvent *) prev->Next()) { - esyslog("xmltv2vdr: '%s' ERROR xmltv data overlaps:",name); - time_t lstart=last->StartTime(); - 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) @%s", name, - *map->ChannelIDs()[mapindex].ToString(),xevent->Title(), - ctime(&start)); - return false; + if (prev->EndTime()==next->StartTime()) + { + 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); + source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till); + + time_t pstart=prev->StartTime(); + time_t pstop=prev->EndTime(); + localtime_r(&pstart,&tm); + strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm); + localtime_r(&pstop,&tm); + strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm); + source->Elog("found '%s'@%s-%s",prev->Title(),from,till); + + time_t nstart=next->StartTime(); + time_t nstop=next->EndTime(); + localtime_r(&nstart,&tm); + strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm); + localtime_r(&nstop,&tm); + strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm); + source->Elog("found '%s'@%s-%s",next->Title(),from,till); + return false; + } + + if (end>next->StartTime()) + { + int diff=(int) difftime(prev->EndTime(),start); + if (diff>300) + { + + 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); + source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till); + + time_t nstart=next->StartTime(); + time_t nstop=next->EndTime(); + localtime_r(&nstart,&tm); + strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm); + localtime_r(&nstop,&tm); + strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm); + source->Elog("found '%s'@%s-%s",next->Title(),from,till); + return false; + } + else + { + xevent->SetDuration(xevent->Duration()-diff); + } + } } - /* set duration, if it doesn't exist */ - if (!last->Duration()) last->SetDuration((int) difftime(start, - last->StartTime())); - if (start!=last->EndTime()) + + if (prev->EndTime()>start) { - esyslog("xmltv2vdr: '%s' detected gap of %is between events",name, - (int) difftime(start,last->EndTime())); + int diff=(int) difftime(prev->EndTime(),start); + if (diff>300) + { + 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); + source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till); + + time_t pstart=prev->StartTime(); + time_t pstop=prev->EndTime(); + localtime_r(&pstart,&tm); + strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm); + localtime_r(&pstop,&tm); + strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm); + source->Elog("found '%s'@%s-%s",prev->Title(),from,till); + return false; + } + else + { + prev->SetDuration(prev->Duration()-diff); + } + } + + if (!xevent->Duration()) + { + if (!prev->Duration()) + { + prev->SetDuration(start-prev->StartTime()); + } } } /* add event */ @@ -473,7 +565,11 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c event->SetVersion(0); schedule->AddEvent(event); schedule->Sort(); - dsyslog("xmltv2vdr: '%s' adding event '%s' @%s",name,xevent->Title(),ctime(&start)); + 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); + source->Dlog("adding '%s'@%s-%s",xevent->Title(),from,till); } else { @@ -484,7 +580,12 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c { if (event->TableID()==0) return true; start=event->StartTime(); - dsyslog("xmltv2vdr: '%s' changing event '%s' @%s",name,event->Title(),ctime(&start)); + 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); + source->Dlog("changing '%s'@%s-%s",event->Title(),from,till); } if ((map->Flags() & USE_SHORTTEXT)==USE_SHORTTEXT) { @@ -492,7 +593,7 @@ bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, c { if (!strcmp(xevent->ShortText(),event->Title())) { - dsyslog("xmltv2vdr: '%s' title and subtitle equal, clearing subtitle",name); + source->Dlog("title and subtitle equal, clearing subtitle"); event->SetShortText(""); } else @@ -830,7 +931,7 @@ bool cParse::FetchEvent(xmlNodePtr enode) } else { - esyslog("xmltv2vdr: '%s' unknown element %s, please report!",name,node->name); + source->Elog("unknown element %s, please report!",node->name); } } node=node->next; @@ -865,26 +966,29 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) xmlDocPtr xmltv; xmltv=xmlReadMemory(buffer,bufsize,NULL,NULL,0); - if (!xmltv) { - esyslog("xmltv2vdr: '%s' ERROR failed to parse xmltv",name); + if (!xmltv) + { + source->Elog("failed to parse xmltv"); return 141; } xmlNodePtr rootnode=xmlDocGetRootElement(xmltv); if (!rootnode) { - esyslog("xmltv2vdr: '%s' ERROR no rootnode in xmltv",name); + source->Elog("no rootnode in xmltv"); xmlFreeDoc(xmltv); return 141; } const cSchedules *schedules=NULL; int l=0; - while (l<300) { + while (l<300) + { cSchedulesLock schedulesLock(true,200); // wait up to 60 secs for lock! schedules = cSchedules::Schedules(schedulesLock); - if (!myExecutor.StillRunning()) { - isyslog("xmltv2vdr: '%s' request to stop from vdr",name); + if (!myExecutor.StillRunning()) + { + source->Ilog("request to stop from vdr"); return 0; } if (schedules) break; @@ -893,7 +997,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!schedules) { - esyslog("xmltv2vdr: '%s' cannot get schedules now, trying later",name); + source->Elog("cannot get schedules now, trying later"); return 1; } @@ -917,7 +1021,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!channelid) { if (lerr!=PARSE_NOCHANNELID) - esyslog("xmltv2vdr: '%s' ERROR missing channelid in xmltv file",name); + source->Elog("missing channelid in xmltv file"); lerr=PARSE_NOCHANNELID; node=node->next; continue; @@ -926,7 +1030,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!map) { if (lerr!=PARSE_NOMAPPING) - esyslog("xmltv2vdr: '%s' ERROR no mapping for channelid %s",name,channelid); + source->Elog("no mapping for channelid %s",channelid); lerr=PARSE_NOMAPPING; xmlFree(channelid); node=node->next; @@ -957,7 +1061,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!starttime) { if (lerr!=PARSE_XMLTVERR) - esyslog("xmltv2vdr: ERROR '%s' no starttime, check xmltv file",name); + source->Elog("xmltv2vdr: '%s' no starttime, check xmltv file"); lerr=PARSE_XMLTVERR; xmlFree(channelid); node=node->next; @@ -974,9 +1078,9 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (oldmap!=map) { - dsyslog("xmltv2vdr: '%s' processing '%s'",name,channelid); - dsyslog("xmltv2vdr: '%s' from %s",name,ctime(&begin)); - dsyslog("xmltv2vdr: '%s' till %s",name,ctime(&end)); + source->Dlog("processing '%s'",channelid); + source->Dlog("from %s",ctime_r(&begin,(char *) &cbuf)); + source->Dlog("till %s",ctime_r(&end,(char *) &cbuf)); } oldmap=map; xmlFree(channelid); @@ -996,7 +1100,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (stoptime) xevent.SetDuration(stoptime-starttime); if (!FetchEvent(node)) // sets xevent { - dsyslog("xmltv2vdr: '%s' failed to fetch event",name); + source->Dlog("failed to fetch event"); node=node->next; continue; } @@ -1009,8 +1113,8 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!channel) { if (lerr!=PARSE_NOCHANNEL) - esyslog("xmltv2vdr: '%s' channel %s not found in channels.conf", - name,*map->ChannelIDs()[i].ToString()); + source->Elog("channel %s not found in channels.conf", + *map->ChannelIDs()[i].ToString()); lerr=PARSE_NOCHANNEL; continue; } @@ -1018,23 +1122,24 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (!schedule) { if (lerr!=PARSE_NOSCHEDULE) - esyslog("xmltv2vdr: '%s' ERROR cannot get schedule for channel %s%s", - name,channel->Name(),addevents ? "" : " - try add option"); + source->Elog("cannot get schedule for channel %s%s", + channel->Name(),addevents ? "" : " - try add option"); lerr=PARSE_NOSCHEDULE; continue; } if (addevents) { cEvent *event=SearchEvent(schedule,&xevent); - PutEvent(schedule,event,&xevent,map,i); + if (!event) + PutEvent(schedule,event,&xevent,map); } else { if (!schedule->Index()) { if (lerr!=PARSE_EMPTYSCHEDULE) - esyslog("xmltv2vdr: '%s' ERROR cannot merge into empty epg (%s) - try add option", - name,channel->Name()); + source->Elog("cannot merge into empty epg (%s) - try add option", + channel->Name()); lerr=PARSE_EMPTYSCHEDULE; } else @@ -1044,22 +1149,23 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) { if ((event=SearchEvent(schedule,&xevent))) { - PutEvent(schedule,event,&xevent,map,i); + PutEvent(schedule,event,&xevent,map); } else { time_t start=xevent.StartTime(); - esyslog("xmltv2vdr: '%s' cannot find existing event in epg.data for xmltv-event %s@%s", - name,xevent.Title(),ctime(&start)); + source->Elog("cannot find existing event in epg.data for xmltv-event %s@%s", + xevent.Title(),ctime_r(&start,(char *) &cbuf)); } } } } } node=node->next; - if (!myExecutor.StillRunning()) { + if (!myExecutor.StillRunning()) + { xmlFreeDoc(xmltv); - isyslog("xmltv2vdr: '%s' request to stop from vdr",name); + source->Ilog("request to stop from vdr"); return 0; } } @@ -1077,8 +1183,12 @@ void cParse::CleanupLibXML() xmlCleanupParser(); } -cParse::cParse(const char *Name, cEPGMappings *Maps, cTEXTMappings *Texts) +cParse::cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts) { + source=Source; + maps=Maps; + texts=Texts; + char *CodeSet=NULL; if (setlocale(LC_CTYPE,"")) CodeSet=nl_langinfo(CODESET); @@ -1092,15 +1202,11 @@ cParse::cParse(const char *Name, cEPGMappings *Maps, cTEXTMappings *Texts) CodeSet++; } } - dsyslog("xmltv2vdr: '%s' vdr codeset is '%s'",Name,CodeSet ? CodeSet : "US-ASCII//TRANSLIT"); + source->Dlog("vdr codeset is '%s'",CodeSet ? CodeSet : "US-ASCII//TRANSLIT"); conv = new cCharSetConv("UTF-8",CodeSet ? CodeSet : "US-ASCII//TRANSLIT"); - name=strdup(Name); - maps=Maps; - texts=Texts; } cParse::~cParse() { delete conv; - free(name); } @@ -16,6 +16,7 @@ #include "maps.h" class cEPGExecutor; +class cEPGSource; class cXMLTVEvent { @@ -158,11 +159,12 @@ class cParse }; private: - char *name; + cEPGSource *source; cEPGMappings *maps; cTEXTMappings *texts; cXMLTVEvent xevent; cCharSetConv *conv; + char cbuf[80]; char *RemoveNonASCII(const char *src); struct split split(char *in, char delim); u_long DoSum(u_long sum, const char *buf, int nBytes); @@ -171,10 +173,10 @@ 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, - int mapindex); + bool PutEvent(cSchedule* schedule,cEvent *event,cXMLTVEvent *xevent, cEPGMapping *map); + cEvent *GetEventBefore(cSchedule *schedule, time_t start); public: - cParse(const char *Name, cEPGMappings *Maps, cTEXTMappings *Texts); + cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts); ~cParse(); int Process(cEPGExecutor &myExecutor, char *buffer, int bufsize); static void InitLibXML(); diff --git a/po/de_DE.po b/po/de_DE.po index 728c8ea..6e9f045 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-08-01 00:24+0200\n" +"POT-Creation-Date: 2011-08-07 18:55+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" @@ -16,15 +16,21 @@ msgstr "" msgid "options" msgstr "Optionen" -msgid "update on start" -msgstr "ausführen beim Start" +msgid "update" +msgstr "Ausführung" -msgid "automatic wakeup" -msgstr "automatisch Aufwachen" +msgid "on time" +msgstr "Zeitpunkt" -msgid "execution time" +msgid "on start" +msgstr "beim Start" + +msgid "update at" msgstr "Ausführung um" +msgid "automatic wakeup" +msgstr "automatisch Aufwachen" + msgid "text mapping" msgstr "Textzuordnungen" @@ -46,6 +52,9 @@ msgstr "hoch" msgid "Button$Down" msgstr "runter" +msgid "Button$Log" +msgstr "Log" + msgid "Button$Edit" msgstr "editieren" @@ -106,6 +115,27 @@ msgstr "Originaltitel" msgid "credits" msgstr "Mitwirkende" +msgid "overview" +msgstr "Übersicht" + +msgid "last execution" +msgstr "Letzte Ausführung" + +msgid "active" +msgstr "aktiv" + +msgid "log" +msgstr "Logdatei" + +msgid "Button$Errors" +msgstr "Fehler" + +msgid "Button$Info" +msgstr "Info" + +msgid "Button$Debug" +msgstr "Debug" + msgid "days in advance" msgstr "Anzahl Tage" @@ -201,3 +231,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 e9c0dac..deb796c 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-08-01 00:24+0200\n" +"POT-Creation-Date: 2011-08-07 18:55+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" @@ -19,15 +19,21 @@ msgstr "" msgid "options" msgstr "Opzioni" -msgid "update on start" -msgstr "aggiorna all'avvio" +msgid "update" +msgstr "" -msgid "automatic wakeup" -msgstr "Risveglio automatico" +msgid "on time" +msgstr "" -msgid "execution time" +msgid "on start" +msgstr "" + +msgid "update at" msgstr "Ora esecuzione" +msgid "automatic wakeup" +msgstr "Risveglio automatico" + msgid "text mapping" msgstr "Mappatura testo" @@ -49,6 +55,9 @@ msgstr "Su" msgid "Button$Down" msgstr "Giu" +msgid "Button$Log" +msgstr "" + msgid "Button$Edit" msgstr "Modifica" @@ -109,6 +118,27 @@ msgstr "Titolo originale" msgid "credits" msgstr "Crediti" +msgid "overview" +msgstr "" + +msgid "last execution" +msgstr "" + +msgid "active" +msgstr "" + +msgid "log" +msgstr "" + +msgid "Button$Errors" +msgstr "" + +msgid "Button$Info" +msgstr "" + +msgid "Button$Debug" +msgstr "" + msgid "days in advance" msgstr "Giorni in anticipo" @@ -204,3 +234,4 @@ msgstr "Plugin XMLTV2VDR ancora in esecuzione" msgid "Imports xmltv epg into vdr" msgstr "Importa EPG di XMLTV in VDR" + @@ -8,9 +8,12 @@ #include "setup.h" #include <vdr/osdbase.h> +#include <time.h> #define CHNUMWIDTH (numdigits(Channels.MaxNumber())+1) +#define NewTitle(x) new cOsdItem(cString::sprintf("%s%s%s", "---- ",x," ----"),osUnknown,false) + char *strcatrealloc(char *dest, const char *src) { if (!src || !*src) @@ -54,8 +57,8 @@ cMenuSetupXmltv2vdr::cMenuSetupXmltv2vdr(cPluginXmltv2vdr *Plugin) { baseplugin=Plugin; sourcesBegin=sourcesEnd=mappingBegin=mappingEnd=mappingEntry=0; - wakeup=baseplugin->WakeUp; - upstart=baseplugin->UpStart; + wakeup=(int) baseplugin->WakeUp; + upstart=(int) baseplugin->UpStart; exectime=baseplugin->ExecTime(); cs=NULL; cm=NULL; @@ -73,14 +76,19 @@ void cMenuSetupXmltv2vdr::Output(void) if (!baseplugin) return; int current=Current(); Clear(); - cOsdItem *first=newtitle(tr("options")); + cOsdItem *first=NewTitle(tr("options")); Add(first,true); - Add(new cMenuEditBoolItem(tr("update on start"),&upstart),true); - Add(new cMenuEditBoolItem(tr("automatic wakeup"),&wakeup),true); - Add(new cMenuEditTimeItem(tr("execution time"),&exectime),true); + + Add(new cMenuEditBoolItem(tr("update"),&upstart,tr("on time"),tr("on start")),true); + updateEntry=Current(); + if (!upstart) + { + Add(new cMenuEditTimeItem(tr("update at"),&exectime),true); + Add(new cMenuEditBoolItem(tr("automatic wakeup"),&wakeup),true); + } Add(new cOsdItem(tr("text mapping")),true); mappingEntry=Current(); - Add(newtitle(tr("epg sources")),true); + Add(NewTitle(tr("epg sources")),true); if (!baseplugin->EPGSourceCount()) { @@ -103,7 +111,7 @@ void cMenuSetupXmltv2vdr::Output(void) } sourcesEnd=Current(); - Add(newtitle(tr("epg source channels")),true); + Add(NewTitle(tr("epg source channels")),true); generatesumchannellist(); mappingBegin=Current()+1; for (int i=0; i<channels.Size(); i++) @@ -114,8 +122,8 @@ void cMenuSetupXmltv2vdr::Output(void) { if (map->NumChannelIDs()) mapped=true; } - cString buffer = cString::sprintf ("%s:\t%s",channels[i],mapped ? tr("mapped") : ""); - Add (new cOsdItem (buffer),true); + cString buffer = cString::sprintf("%s:\t%s",channels[i],mapped ? tr("mapped") : ""); + Add(new cOsdItem(buffer),true); } mappingEnd=Current(); @@ -164,12 +172,6 @@ void cMenuSetupXmltv2vdr::generatesumchannellist() channels.Sort(); } -cOsdItem *cMenuSetupXmltv2vdr::newtitle(const char *s) -{ - cString buffer = cString::sprintf("---- %s ----", s); - return new cOsdItem (buffer,osUnknown,false); -} - void cMenuSetupXmltv2vdr::Store(void) { SetupStore("options.exectime",exectime); @@ -201,24 +203,28 @@ eOSState cMenuSetupXmltv2vdr::edit() return osUnknown; } -eOSState cMenuSetupXmltv2vdr::ProcessKey (eKeys Key) +eOSState cMenuSetupXmltv2vdr::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (HasSubMenu()) return osContinue; switch (state) { case osContinue: + if ((Key==kLeft) || (Key==kRight) || (Key==kLeft|k_Repeat) || (Key==kRight|k_Repeat)) + { + if (Current()==updateEntry) Output(); + } if ((Key==kDown) || (Key==kUp) || (Key==kDown|k_Repeat) || (Key==kUp|k_Repeat)) { if ((Current()>=sourcesBegin) && (Current()<=sourcesEnd)) { if ((sourcesEnd-sourcesBegin)>0) { - SetHelp(NULL,tr("Button$Up"),tr("Button$Down"),tr("Button$Edit")); + SetHelp(tr("Button$Up"),tr("Button$Down"),tr("Button$Log"),tr("Button$Edit")); } else { - SetHelp(NULL,NULL,NULL,tr("Button$Edit")); + SetHelp(NULL,NULL,tr("Button$Log"),tr("Button$Edit")); } } else if (Current()==mappingEntry) @@ -246,6 +252,17 @@ eOSState cMenuSetupXmltv2vdr::ProcessKey (eKeys Key) state=osBack; } } + if (Key==kYellow) + { + if ((Current()>=sourcesBegin) && (Current()<=sourcesEnd)) + { + cEPGSource *src=baseplugin->EPGSource(Current()-sourcesBegin); + if (src) + { + return AddSubMenu(new cMenuSetupXmltv2vdrLog(baseplugin,src)); + } + } + } break; default: @@ -259,8 +276,8 @@ eOSState cMenuSetupXmltv2vdr::ProcessKey (eKeys Key) cMenuSetupXmltv2vdrTextMap::cMenuSetupXmltv2vdrTextMap(cPluginXmltv2vdr *Plugin) { baseplugin=Plugin; - SetSection(cString::sprintf("%s '%s' : %s",trVDR("Plugin"), baseplugin->Name(), tr("texts"))); SetPlugin(baseplugin); + SetSection(cString::sprintf("%s '%s' : %s",trVDR("Plugin"), baseplugin->Name(), tr("texts"))); cTEXTMapping *textmap; @@ -414,17 +431,17 @@ cMenuSetupXmltv2vdrTextMap::cMenuSetupXmltv2vdrTextMap(cPluginXmltv2vdr *Plugin) strcpy(category,tr("category")); } - Add(newtitle(tr("country and date"))); + Add(NewTitle(tr("country and date"))); Add(new cMenuEditStrItem("country",country,sizeof(country))); Add(new cMenuEditStrItem("date",date,sizeof(date))); - Add(newtitle(tr("original title"))); + Add(NewTitle(tr("original title"))); Add(new cMenuEditStrItem("originaltitle",originaltitle,sizeof(originaltitle))); - Add(newtitle(tr("category"))); + Add(NewTitle(tr("category"))); Add(new cMenuEditStrItem("category",category,sizeof(category))); - Add(newtitle(tr("credits"))); + Add(NewTitle(tr("credits"))); Add(new cMenuEditStrItem("actor",actor,sizeof(actor))); Add(new cMenuEditStrItem("guest",guest,sizeof(guest))); Add(new cMenuEditStrItem("director",director,sizeof(director))); @@ -436,16 +453,10 @@ cMenuSetupXmltv2vdrTextMap::cMenuSetupXmltv2vdrTextMap(cPluginXmltv2vdr *Plugin) Add(new cMenuEditStrItem("commentator",commentator,sizeof(commentator))); Add(new cMenuEditStrItem("presenter",presenter,sizeof(presenter))); - Add(newtitle(tr("review"))); + Add(NewTitle(tr("review"))); Add(new cMenuEditStrItem("review",review,sizeof(review))); } -cOsdItem *cMenuSetupXmltv2vdrTextMap::newtitle(const char *s) -{ - cString buffer = cString::sprintf("---- %s ----", s); - return new cOsdItem (buffer,osUnknown,false); -} - void cMenuSetupXmltv2vdrTextMap::Store() { if (!baseplugin) return; @@ -605,6 +616,193 @@ void cMenuSetupXmltv2vdrTextMap::Store() // -------------------------------------------------------------------------------------------------------- +void cMenuSetupXmltv2vdrLog::output(void) +{ + int cur=Current(); + Clear(); + Add(NewTitle(tr("overview"))); + time_t lastexec=src->LastExecution(); + if (lastexec) + { + struct tm tm; + localtime_r(&lastexec,&tm); + strftime(lastexec_str,sizeof(lastexec_str)-1,"%d %b %H:%M:%S",&tm); + } + cString last; + if (src->Active()) + { + last=cString::sprintf("%s:\t%s",tr("last execution"), + tr("active")); + } + else + { + last=cString::sprintf("%s:\t%s",tr("last execution"), + lastexec ? lastexec_str : "-"); + } + Add(new cOsdItem(last,osUnknown,true)); + + int tlen=strlen(3+tr("log"))+strlen(tr("Button$Errors"))+strlen(tr("Button$Info"))+strlen(tr("Button$Debug")); + char *ntitle=(char *) malloc(tlen); + if (ntitle) + { + strcpy(ntitle,tr("log")); + strcat(ntitle," ("); + + switch (level) + { + case VIEW_ERROR: + strcat(ntitle,tr("Button$Errors")); + break; + case VIEW_INFO: + strcat(ntitle,tr("Button$Info")); + break; + case VIEW_DEBUG: + strcat(ntitle,tr("Button$Debug")); + break; + } + strcat(ntitle,")"); + Add(NewTitle(ntitle)); + free(ntitle); + + } + else + { + Add(NewTitle(tr("log"))); + } + + if (src && src->Log) + { + char *saveptr; + char *log=strdup(src->Log); + if (log) + { + char *pch=strtok_r(log,"\n",&saveptr); + while (pch) + { + bool outp=false; + if (level==VIEW_DEBUG) outp=true; + if ((level==VIEW_INFO) && ((pch[0]=='I') || (pch[0]=='E'))) outp=true; + if ((level==VIEW_ERROR) && (pch[0]=='E')) outp=true; + if (outp) + { + if (font->Width(pch+1)>width) + { + cTextWrapper wrap(pch+1,font,width); + for (int i=0; i<wrap.Lines();i++) + { + Add(new cOsdItem(wrap.GetLine(i),osUnknown,true)); + } + } + else + { + Add(new cOsdItem(pch+1,osUnknown,true)); + } + } + pch=strtok_r(NULL,"\n",&saveptr); + } + free(log); + } + } + if (cur>Count()) cur=Count(); + SetCurrent(Get(cur)); + Display(); +} + +cMenuSetupXmltv2vdrLog::cMenuSetupXmltv2vdrLog(cPluginXmltv2vdr *Plugin, cEPGSource *Source) + :cOsdMenu("",25) +{ + cString title=cString::sprintf("%s - %s '%s' : %s Log", + trVDR("Setup"),trVDR("Plugin"), + Plugin->Name(), Source->Name()); + SetTitle(title); + src=Source; + SetHelp(tr("Button$Info")); + + level=VIEW_ERROR; + width=0; + lastrefresh=(time_t) 0; + font=NULL; + cSkinDisplayMenu *disp=DisplayMenu(); + if (disp) + { + width=disp->GetTextAreaWidth(); + font=disp->GetTextAreaFont(false); + } + if (!width) width=Setup.OSDWidth; + if (!font) font=cFont::GetFont(fontOsd); + + output(); +} + +eOSState cMenuSetupXmltv2vdrLog::ProcessKey(eKeys Key) +{ + eOSState state = cOsdMenu::ProcessKey(Key); + if (HasSubMenu()) return osContinue; + if (state==osUnknown) + { + switch (Key) + { + case kRed: + switch (level) + { + case VIEW_ERROR: + level=VIEW_INFO; + SetHelp(tr("Button$Debug")); + break; + case VIEW_INFO: + level=VIEW_DEBUG; + SetHelp(tr("Button$Errors")); + break; + case VIEW_DEBUG: + level=VIEW_ERROR; + SetHelp(tr("Button$Info")); + break; + } + output(); + break; + case kGreen: + level = VIEW_INFO; + output(); + break; + case kBlue: + level = VIEW_DEBUG; + output(); + break; + case kNone: + if (src->Active()) + { + if (time(NULL)>(lastrefresh+5)) + { + output(); + lastrefresh=time(NULL); + } + } + else + { + if (lastrefresh) + { + if (time(NULL)>(lastrefresh+5)) + { + output(); + lastrefresh=(time_t) 0; + } + } + } + break; + case kBack: + case kOk: + state=osBack; + break; + default: + break; + } + } + return state; +} + + +// -------------------------------------------------------------------------------------------------------- + cMenuSetupXmltv2vdrChannelSource::cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2vdr *Plugin, cMenuSetupXmltv2vdr *Menu, int Index) { menu=Menu; @@ -618,7 +816,7 @@ cMenuSetupXmltv2vdrChannelSource::cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2 SetSection(cString::sprintf("%s '%s' : %s",trVDR("Plugin"), baseplugin->Name(), epgsrc->Name())); - Add(newtitle(tr("options"))); + Add(NewTitle(tr("options"))); days=epgsrc->DaysInAdvance(); Add(new cMenuEditIntItem(tr("days in advance"),&days,1,epgsrc->DaysMax())); if (epgsrc->NeedPin()) @@ -630,7 +828,7 @@ cMenuSetupXmltv2vdrChannelSource::cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2 } Add(new cMenuEditStrItem(tr("pin"),pin,sizeof(pin))); } - Add(newtitle(tr("channels provided"))); + Add(NewTitle(tr("channels provided"))); cEPGChannels *channellist=epgsrc->ChannelList(); if (!channellist) return; @@ -662,12 +860,6 @@ cMenuSetupXmltv2vdrChannelSource::~cMenuSetupXmltv2vdrChannelSource() if (sel) delete [] sel; } -cOsdItem *cMenuSetupXmltv2vdrChannelSource::newtitle(const char *s) -{ - cString buffer = cString::sprintf("---- %s ----", s); - return new cOsdItem (buffer,osUnknown,false); -} - void cMenuSetupXmltv2vdrChannelSource::Store(void) { if ((!baseplugin) || (!sel) || (!epgsrc)) return; @@ -803,13 +995,7 @@ cOsdItem *cMenuSetupXmltv2vdrChannelMap::optionN(const char *s, int num) cOsdItem *cMenuSetupXmltv2vdrChannelMap::option(const char *s, bool yesno) { cString buffer = cString::sprintf("%s:\t%s", s, yesno ? trVDR("yes") : trVDR("no")); - return new cOsdItem (buffer,osUnknown,false); -} - -cOsdItem *cMenuSetupXmltv2vdrChannelMap::newtitle(const char *s) -{ - cString buffer = cString::sprintf("---- %s ----", s); - return new cOsdItem (buffer,osUnknown,false); + return new cOsdItem(buffer,osUnknown,false); } void cMenuSetupXmltv2vdrChannelMap::output(void) @@ -819,7 +1005,7 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) int current=Current(); Clear(); - cOsdItem *first=newtitle(tr("epg source channel options")); + cOsdItem *first=NewTitle(tr("epg source channel options")); Add(first,true); Add(new cMyMenuEditBitItem(tr("type of processing"),&flags,OPT_APPEND,tr("merge"),tr("create")),true); @@ -862,7 +1048,7 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) Add(new cMyMenuEditBitItem(tr("vps"),&flags,OPT_VPS),true); hasmaps=false; - Add(newtitle(tr("epg source channel mappings")),true); + Add(NewTitle(tr("epg source channel mappings")),true); for (int i=0; i<map->NumChannelIDs(); i++) { cChannel *chan=Channels.GetByChannelID(map->ChannelIDs()[i]); @@ -872,7 +1058,9 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) Add(new cOsdItem(buffer),true); if (!hasmaps) cm=Current(); hasmaps=true; - } else { + } + else + { // invalid channelid? remove from list map->RemoveChannel(map->ChannelIDs()[i],true); } @@ -896,7 +1084,7 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) Display(); } -eOSState cMenuSetupXmltv2vdrChannelMap::ProcessKey (eKeys Key) +eOSState cMenuSetupXmltv2vdrChannelMap::ProcessKey(eKeys Key) { cOsdItem *item=NULL; eOSState state = cOsdMenu::ProcessKey(Key); @@ -1143,7 +1331,7 @@ bool cMenuSetupXmltv2vdrChannelsVDR::epgmappingexists(tChannelID channelid, cons return false; } -eOSState cMenuSetupXmltv2vdrChannelsVDR::ProcessKey (eKeys Key) +eOSState cMenuSetupXmltv2vdrChannelsVDR::ProcessKey(eKeys Key) { cOsdItem *item=NULL; eOSState state = cOsdMenu::ProcessKey(Key); @@ -1170,3 +1358,4 @@ eOSState cMenuSetupXmltv2vdrChannelsVDR::ProcessKey (eKeys Key) } return state; } + @@ -37,7 +37,7 @@ private: int mappingBegin,mappingEnd; int sourcesBegin,sourcesEnd; int mappingEntry; - cOsdItem *newtitle (const char *s); + int updateEntry; eOSState edit(void); void generatesumchannellist(); int exectime; @@ -45,6 +45,7 @@ private: int upstart; public: void Output(void); + static cOsdItem *NewTitle(const char *s); void ClearCS() { cs=NULL; @@ -83,7 +84,6 @@ private: char guest[255]; char review[255]; char category[255]; - cOsdItem *newtitle (const char *s); public: cMenuSetupXmltv2vdrTextMap(cPluginXmltv2vdr *Plugin); }; @@ -99,7 +99,6 @@ private: int *sel; int days; char pin[255]; - cOsdItem *newtitle (const char *s); public: cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2vdr *Plugin, cMenuSetupXmltv2vdr *Menu, int Index); ~cMenuSetupXmltv2vdrChannelSource(); @@ -125,7 +124,6 @@ private: cString title; const char *channel; int getdaysmax(); - cOsdItem *newtitle (const char *s); cOsdItem *optionN(const char *s, int num); cOsdItem *option(const char *s, bool yesno); void epgmappingreplace(cEPGMapping *newmapping); @@ -152,6 +150,35 @@ public: cMenuSetupXmltv2vdrChannelsVDR(cPluginXmltv2vdr *Plugin, cMenuSetupXmltv2vdrChannelMap *Map, const char *Channel, cString Title); virtual eOSState ProcessKey(eKeys Key); + virtual const char *MenuKind() + { + return "MenuChannels"; + } +}; + +class cMenuSetupXmltv2vdrLog : public cOsdMenu +{ +private: + enum + { + VIEW_ERROR=1, + VIEW_INFO, + VIEW_DEBUG + }; + int level; + cEPGSource *src; + char lastexec_str[30]; + void output(void); + int width; + time_t lastrefresh; + const cFont *font; +public: + cMenuSetupXmltv2vdrLog(cPluginXmltv2vdr *Plugin, cEPGSource *Source); + virtual const char *MenuKind() + { + return "MenuLog"; + } + virtual eOSState ProcessKey(eKeys Key); }; #endif diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp index 01e767b..64b79da 100644 --- a/xmltv2vdr.cpp +++ b/xmltv2vdr.cpp @@ -10,6 +10,7 @@ #include <time.h> #include <sys/wait.h> #include <sys/ioctl.h> +#include <stdarg.h> #include "xmltv2vdr.h" #include "parse.h" #include "extpipe.h" @@ -54,20 +55,22 @@ void cEPGExecutor::Action() for (cEPGSource *epgs=sources->First(); epgs; epgs=sources->Next(epgs)) { int retries=0; - while (retries<2) + while (retries<=2) { ret=epgs->Execute(*this); - if ((ret>0) && (ret<126)) + if ((ret>0) && (ret<126) && (retries<2)) { - dsyslog("xmltv2vdr: '%s' waiting 60 seconds",epgs->Name()); + epgs->Dlog("waiting 60 seconds"); int l=0; - while (l<300) { + while (l<300) + { struct timespec req; req.tv_sec=0; req.tv_nsec=200000000; // 200ms nanosleep(&req,NULL); - if (!Running()) { - isyslog("xmltv2vdr: '%s' request to stop from vdr",epgs->Name()); + if (!Running()) + { + epgs->Ilog("request to stop from vdr"); return; } l++; @@ -79,7 +82,7 @@ void cEPGExecutor::Action() break; } } - if (retries>=2) esyslog("xmltv2vdr: '%s' ERROR skipping after %i retries",epgs->Name(),retries); + if (retries>=2) epgs->Elog("skipping after %i retries",retries); if (!ret) break; // TODO: check if we must execute second/third source! } if (!ret) cSchedules::Cleanup(true); @@ -93,12 +96,16 @@ cEPGSource::cEPGSource(const char *Name, const char *ConfDir, cEPGMappings *Maps name=strdup(Name); confdir=strdup(ConfDir); pin=NULL; + Log=NULL; + loglen=0; usepipe=false; needpin=false; + running=false; daysinadvance=0; + lastexec=(time_t) 0; ready2parse=ReadConfig(); - parse=new cParse(Name, Maps, Texts); - dsyslog("xmltv2vdr: '%s' is%sready2parse",Name,(ready2parse && parse) ? " " : " not "); + parse=new cParse(this, Maps, Texts); + Dlog("is%sready2parse",(ready2parse && parse) ? " " : " not "); } cEPGSource::~cEPGSource() @@ -107,6 +114,7 @@ cEPGSource::~cEPGSource() free((void *) name); free((void *) confdir); if (pin) free((void *) pin); + if (Log) free((void *) Log); if (parse) delete parse; } @@ -115,17 +123,17 @@ bool cEPGSource::ReadConfig() char *fname=NULL; if (asprintf(&fname,"%s/%s",EPGSOURCES,name)==-1) { - esyslog("xmltv2vdr: '%s' out of memory",name); + Elog("out of memory"); return false; } FILE *f=fopen(fname,"r"); if (!f) { - esyslog("xmltv2vdr: '%s' ERROR cannot read config file %s",name,fname); + Elog("cannot read config file %s",fname); free(fname); return false; } - dsyslog("xmltv2vdr: '%s' reading source config",name); + Dlog("reading source config"); size_t lsize; char *line=NULL; int linenr=1; @@ -135,12 +143,12 @@ bool cEPGSource::ReadConfig() { if (!strncmp(line,"pipe",4)) { - dsyslog("xmltv2vdr: '%s' is providing data through a pipe",name); + Dlog("is providing data through a pipe"); usepipe=true; } else { - dsyslog("xmltv2vdr: '%s' is providing data through a file",name); + Dlog("is providing data through a file"); usepipe=false; } char *ndt=strchr(line,';'); @@ -156,14 +164,14 @@ bool cEPGSource::ReadConfig() } /* newdatatime=atoi(ndt); - if (!newdatatime) dsyslog("xmltv2vdr: '%s' updates source data @%02i:%02i",name,1,2); + if (!newdatatime) Dlog("updates source data @%02i:%02i",1,2); */ if (pn) { pn=compactspace(pn); if (pn[0]=='1') { - dsyslog("xmltv2vdr: '%s' is needing a pin",name); + Dlog("is needing a pin"); needpin=true; } } @@ -183,7 +191,7 @@ bool cEPGSource::ReadConfig() { daysmax=atoi(line); } - dsyslog("xmltv2vdr: '%s' daysmax=%i",name,daysmax); + Dlog("daysmax=%i",daysmax); } if (linenr>2) { @@ -198,7 +206,8 @@ bool cEPGSource::ReadConfig() // backward compatibility cname++; } - if (!strchr(cname,' ') && (strlen(cname)>0)) { + if (!strchr(cname,' ') && (strlen(cname)>0)) + { cEPGChannel *epgchannel= new cEPGChannel(cname,false); if (epgchannel) channels.Add(epgchannel); } @@ -214,7 +223,7 @@ bool cEPGSource::ReadConfig() if (asprintf(&fname,"%s/%s",confdir,name)==-1) { - esyslog("xmltv2vdr: '%s' out of memory",name); + Elog("out of memory"); return false; } f=fopen(fname,"r+"); @@ -222,7 +231,7 @@ bool cEPGSource::ReadConfig() { if (errno!=ENOENT) { - esyslog("xmltv2vdr: '%s' ERROR cannot read config file %s",name,fname); + Elog("cannot read config file %s",fname); free(fname); return true; } @@ -230,7 +239,7 @@ bool cEPGSource::ReadConfig() free(fname); return true; } - dsyslog("xmltv2vdr: '%s' reading plugin config",name); + Dlog("reading plugin config"); line=NULL; linenr=1; while (getline(&line,&lsize,f)!=-1) @@ -242,13 +251,13 @@ bool cEPGSource::ReadConfig() if (strcmp(line,"#no pin")) { ChangePin(line); - dsyslog("xmltv2vdr: '%s' pin set",name); + Dlog("pin set"); } } if (linenr==2) { daysinadvance=atoi(line); - dsyslog("xmltv2vdr: '%s' daysinadvance=%i",name,daysinadvance); + Dlog("daysinadvance=%i",daysinadvance); } if (linenr>2) { @@ -281,15 +290,15 @@ int cEPGSource::ReadOutput(char *&result, size_t &l) char *fname=NULL; if (asprintf(&fname,"%s/%s.xmltv",EPGSOURCES,name)==-1) { - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + Elog("out of memory"); return 134; } - dsyslog("xmltv2vdr: '%s' reading from '%s'",name,fname); + Dlog("reading from '%s'",fname); int fd=open(fname,O_RDONLY); if (fd==-1) { - esyslog("xmltv2vdr: '%s' ERROR failed to open '%s'",name,fname); + Elog("failed to open '%s'",fname); free(fname); return 157; } @@ -297,7 +306,7 @@ int cEPGSource::ReadOutput(char *&result, size_t &l) struct stat statbuf; if (fstat(fd,&statbuf)==-1) { - esyslog("xmltv2vdr: '%s' ERROR failed to stat '%s'",name,fname); + Elog("failed to stat '%s'",fname); close(fd); free(fname); return 157; @@ -308,7 +317,7 @@ int cEPGSource::ReadOutput(char *&result, size_t &l) { close(fd); free(fname); - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + Elog("out of memory"); return 134; } if (read(fd,result,statbuf.st_size)==statbuf.st_size) @@ -316,7 +325,7 @@ int cEPGSource::ReadOutput(char *&result, size_t &l) } else { - esyslog("xmltv2vdr: '%s' ERROR failed to read '%s'",name,fname); + Elog("failed to read '%s'",fname); ret=149; } free(result); @@ -327,20 +336,24 @@ int cEPGSource::ReadOutput(char *&result, size_t &l) int cEPGSource::Execute(cEPGExecutor &myExecutor) { - if (!ready2parse) return false; if (!parse) return false; char *r_out=NULL; char *r_err=NULL; int l_out=0; int l_err=0; - int ret=0; + if ((Log) && (lastexec)) { + free(Log); + Log=NULL; + loglen=0; + } + char *cmd=NULL; if (asprintf(&cmd,"%s %i '%s'",name,daysinadvance,pin ? pin : "")==-1) { - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + Elog("out of memory"); return 134; } @@ -354,7 +367,7 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) if (!ncmd) { free(cmd); - esyslog("xmltv2vdr: '%s' ERROR out of memory",name); + Elog("out of memory"); return 134; } cmd=ncmd; @@ -364,21 +377,37 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) } } char *pcmd=strdup(cmd); - if (pcmd) { + if (pcmd) + { char *pa=strchr(pcmd,'\''); char *pe=strchr(pa+1,'\''); - if (pa && pe) { + if (pa && pe) + { pa++; for (char *c=pa; c<pe; c++) { - if (c==pa) { + if (c==pa) + { *c='X'; - } else { + } + else + { *c='@'; } } - // TODO: strip @ - isyslog("xmltv2vdr: '%s' %s",name,pcmd); + pe=pcmd; + while (*pe) + { + if (*pe=='@') + { + memmove(pe,pe+1,strlen(pe)); + } + else + { + pe++; + } + } + Ilog("%s",pcmd); } free(pcmd); } @@ -386,23 +415,28 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) if (!p.Open(cmd)) { free(cmd); - esyslog("xmltv2vdr: '%s' ERROR failed to open pipe",name); + Elog("failed to open pipe"); return 141; } free(cmd); - dsyslog("xmltv2vdr: '%s' executing epgsource",name); + Dlog("executing epgsource"); + running=true; int fdsopen=2; - while (fdsopen>0) { + 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) { + if (poll(fds,2,500)>=0) + { + if (fds[0].revents & POLLIN) + { int n; - if (ioctl(p.Out(),FIONREAD,&n)<0) { + if (ioctl(p.Out(),FIONREAD,&n)<0) + { n=1; } r_out=(char *) realloc(r_out, l_out+n+1); @@ -412,34 +446,42 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) l_out+=l; } } - if (fds[1].revents & POLLIN) { + if (fds[1].revents & POLLIN) + { int n; - if (ioctl(p.Err(),FIONREAD,&n)<0) { + if (ioctl(p.Err(),FIONREAD,&n)<0) + { n=1; } r_err=(char *) realloc(r_err, l_err+n+1); int l=read(p.Err(),r_err+l_err,n); - if (l>0) { + if (l>0) + { l_err+=l; } } - if (fds[0].revents & POLLHUP) { + if (fds[0].revents & POLLHUP) + { fdsopen--; } - if (fds[1].revents & POLLHUP) { + if (fds[1].revents & POLLHUP) + { fdsopen--; } - if (!myExecutor.StillRunning()) { + if (!myExecutor.StillRunning()) + { int status; p.Close(status); if (r_out) free(r_out); if (r_err) free(r_err); - isyslog("xmltv2vdr: '%s' request to stop from vdr",name); + Ilog("request to stop from vdr"); + running=false; return 0; } - - } else { - esyslog("xmltv2vdr: '%s' ERROR polling",name); + } + else + { + Elog("failed polling"); break; } } @@ -454,18 +496,19 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) int returncode=WEXITSTATUS(status); if ((!returncode) && (r_out)) { - dsyslog("xmltv2vdr: '%s' parsing output",name); + //Dlog("xmltv2vdr: '%s' parsing output"); + Dlog("parsing output"); ret=parse->Process(myExecutor,r_out,l_out); } else { - esyslog("xmltv2vdr: '%s' ERROR epgsource returned %i",name,returncode); + Elog("epgsource returned %i",returncode); ret=returncode; } } else { - esyslog("xmltv2vdr: '%s' ERROR failed to execute",name); + Elog("failed to execute"); ret=126; } } @@ -480,28 +523,38 @@ int cEPGSource::Execute(cEPGExecutor &myExecutor) size_t l; char *result=NULL; ret=ReadOutput(result,l); - if ((!ret) && (result)) { + if ((!ret) && (result)) + { ret=parse->Process(myExecutor,result,l); } if (result) free(result); } else { - esyslog("xmltv2vdr: '%s' ERROR epgsource returned %i",name,returncode); + Elog("epgsource returned %i",returncode); ret=returncode; } } } 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"); + if (!ret) lastexec=time(NULL); + if (r_err) + { + char *saveptr; + char *pch=strtok_r(r_err,"\n",&saveptr); + char *last=(char *) ""; + while (pch) + { + if (strcmp(last,pch)) + { + Elog("%s",pch); + last=pch; + } + pch=strtok_r(NULL,"\n",&saveptr); } free(r_err); } - + running=false; return ret; } @@ -520,7 +573,7 @@ void cEPGSource::Store(void) if (asprintf(&fname1,"%s/%s",confdir,name)==-1) return; if (asprintf(&fname2,"%s/%s.new",confdir,name)==-1) { - esyslog("xmltv2vdr: '%s' out of memory",name); + Elog("out of memory"); free(fname1); return; } @@ -528,7 +581,7 @@ void cEPGSource::Store(void) FILE *w=fopen(fname2,"w+"); if (!w) { - esyslog("xmltv2vdr: '%s' cannot create %s",name,fname2); + Elog("cannot create %s",fname2); unlink(fname2); free(fname1); free(fname2); @@ -564,6 +617,75 @@ void cEPGSource::Store(void) free(fname2); } +void cEPGSource::add2Log(const char Prefix, const char *line) +{ + if (!line) return; + + struct tm tm; + time_t now=time(NULL); + localtime_r(&now,&tm); + char dt[30]; + strftime(dt,sizeof(dt)-1,"%H:%M ",&tm); + + loglen+=strlen(line)+3+strlen(dt); + char *nptr=(char *) realloc(Log,loglen); + if (nptr) + { + if (!Log) nptr[0]=0; + Log=nptr; + char prefix[2]; + prefix[0]=Prefix; + prefix[1]=0; + strcat(Log,prefix); + strcat(Log,dt); + strcat(Log,line); + strcat(Log,"\n"); + Log[loglen-1]=0; + } +} + +void cEPGSource::Elog(const char *format, ...) +{ + va_list ap; + char fmt[255]; + if (snprintf(fmt,sizeof(fmt),"xmltv2vdr '%s' ERROR %s",name,format)==-1) return; + va_start(ap, format); + char *ptr; + if (vasprintf(&ptr,fmt,ap)==-1) return; + va_end(ap); + esyslog(ptr); + add2Log('E',ptr+19+strlen(name)); + free(ptr); +} + +void cEPGSource::Dlog(const char *format, ...) +{ + va_list ap; + char fmt[255]; + if (snprintf(fmt,sizeof(fmt),"xmltv2vdr '%s' %s",name,format)==-1) return; + va_start(ap, format); + char *ptr; + if (vasprintf(&ptr,fmt,ap)==-1) return; + va_end(ap); + dsyslog(ptr); + add2Log('D',ptr+13+strlen(name)); + free(ptr); +} + +void cEPGSource::Ilog(const char *format, ...) +{ + va_list ap; + char fmt[255]; + if (snprintf(fmt,sizeof(fmt),"xmltv2vdr '%s' %s",name,format)==-1) return; + va_start(ap, format); + char *ptr; + if (vasprintf(&ptr,fmt,ap)==-1) return; + va_end(ap); + isyslog(ptr); + add2Log('I',ptr+13+strlen(name)); + free(ptr); +} + // ------------------------------------------------------------- bool cPluginXmltv2vdr::epgsourceexists(const char *name) @@ -692,7 +814,7 @@ cPluginXmltv2vdr::cPluginXmltv2vdr(void) : epgexecutor(&epgsources) // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! confdir=NULL; WakeUp=0; - UpStart=0; + UpStart=1; last_exectime_t=0; exectime=200; SetExecTime(exectime); @@ -745,6 +867,10 @@ bool cPluginXmltv2vdr::Start(void) if (UpStart) { exectime_t=time(NULL)+60; + struct tm tm; + localtime_r(&exectime_t,&tm); + // prevent from getting startet again + exectime=tm.tm_hour*100+tm.tm_min; } else { diff --git a/xmltv2vdr.h b/xmltv2vdr.h index 14bbf12..1067494 100644 --- a/xmltv2vdr.h +++ b/xmltv2vdr.h @@ -14,8 +14,8 @@ #include "maps.h" #include "parse.h" -static const char *VERSION = "0.0.1"; -static const char *DESCRIPTION = trNOOP ( "Imports xmltv epg into vdr" ); +static const char *VERSION = "0.0.2pre"; +static const char *DESCRIPTION = trNOOP("Imports xmltv epg into vdr"); class cEPGChannel : public cListObject { @@ -50,12 +50,16 @@ private: const char *name; const char *confdir; const char *pin; + int loglen; cParse *parse; bool ready2parse; bool usepipe; bool needpin; + bool running; int daysinadvance; int daysmax; + time_t lastexec; + void add2Log(const char prefix, const char *line); bool ReadConfig(); int ReadOutput(char *&result, size_t &l); cEPGChannels channels; @@ -65,6 +69,7 @@ public: int Execute(cEPGExecutor &myExecutor); void Store(void); void ChangeChannelSelection(int *Selection); + char *Log; cEPGChannels *ChannelList() { return &channels; @@ -98,6 +103,17 @@ public: if (pin) free((void *) pin); pin=strdup(NewPin); } + time_t LastExecution() + { + return lastexec; + } + void Dlog(const char *format, ...); + void Elog(const char *format, ...); + void Ilog(const char *format, ...); + bool Active() + { + return running; + } }; class cEPGSources : public cList<cEPGSource> {}; @@ -108,13 +124,14 @@ private: cEPGSources *sources; public: cEPGExecutor(cEPGSources *Sources); - bool StillRunning() { + bool StillRunning() + { return Running(); } void Stop() { Cancel(3); - } + } virtual void Action(); }; @@ -167,32 +184,32 @@ public: { textmappings.Add(TextMap); } - cPluginXmltv2vdr ( void ); + cPluginXmltv2vdr(void); virtual ~cPluginXmltv2vdr(); - virtual const char *Version ( void ) + virtual const char *Version(void) { return VERSION; } - virtual const char *Description ( void ) + virtual const char *Description(void) { return tr(DESCRIPTION); } - virtual const char *CommandLineHelp ( void ); - virtual bool ProcessArgs ( int argc, char *argv[] ); - virtual bool Initialize ( void ); - virtual bool Start ( void ); - virtual void Stop ( void ); - virtual void Housekeeping ( void ); - virtual void MainThreadHook ( void ); - virtual cString Active ( void ); - virtual time_t WakeupTime ( void ); - virtual const char *MainMenuEntry ( void ); - virtual cOsdObject *MainMenuAction ( void ); - virtual cMenuSetupPage *SetupMenu ( void ); - virtual bool SetupParse ( const char *Name, const char *Value ); - virtual bool Service ( const char *Id, void *Data = NULL ); - virtual const char **SVDRPHelpPages ( void ); - virtual cString SVDRPCommand ( const char *Command, const char *Option, int &ReplyCode ); + virtual const char *CommandLineHelp(void); + virtual bool ProcessArgs(int argc, char *argv[]); + virtual bool Initialize(void); + virtual bool Start(void); + virtual void Stop(void); + virtual void Housekeeping(void); + virtual void MainThreadHook(void); + virtual cString Active(void); + virtual time_t WakeupTime(void); + virtual const char *MainMenuEntry(void); + virtual cOsdObject *MainMenuAction(void); + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); + virtual bool Service(const char *Id, void *Data = NULL); + virtual const char **SVDRPHelpPages(void); + virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); }; #endif |