diff options
author | Jochen Dolze <vdr@dolze.de> | 2012-05-05 17:42:12 +0200 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2012-05-05 17:42:12 +0200 |
commit | 510d6a8c2690f4435ae2faafa64b896232ae8bbe (patch) | |
tree | fe809588b1109f675f4d5c8dbaf16aa9d9b7b03a | |
parent | 9706daedb3aeb2154e532d8a586f59b3166f8279 (diff) | |
download | vdr-plugin-xmltv2vdr-510d6a8c2690f4435ae2faafa64b896232ae8bbe.tar.gz vdr-plugin-xmltv2vdr-510d6a8c2690f4435ae2faafa64b896232ae8bbe.tar.bz2 |
Added option 'add shorttext/title from list'v0.1.1
Added cGlobal class for global variables
New version 0.1.1
-rw-r--r-- | event.cpp | 35 | ||||
-rw-r--r-- | event.h | 21 | ||||
-rw-r--r-- | import.cpp | 234 | ||||
-rw-r--r-- | import.h | 7 | ||||
-rw-r--r-- | maps.h | 6 | ||||
-rw-r--r-- | parse.cpp | 119 | ||||
-rw-r--r-- | parse.h | 15 | ||||
-rw-r--r-- | po/de_DE.po | 18 | ||||
-rw-r--r-- | po/it_IT.po | 17 | ||||
-rw-r--r-- | setup.cpp | 47 | ||||
-rw-r--r-- | setup.h | 6 | ||||
-rw-r--r-- | source.cpp | 43 | ||||
-rw-r--r-- | source.h | 23 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 431 | ||||
-rw-r--r-- | xmltv2vdr.h | 151 |
15 files changed, 804 insertions, 369 deletions
@@ -188,6 +188,22 @@ void cXMLTVEvent::SetVideo(const char *Video) free(c); } +void cXMLTVEvent::SetPics(const char* Pics) +{ + if (!Pics) return; + char *c=strdup(Pics); + if (!c) return; + char *sp,*tok; + char delim[]="@"; + tok=strtok_r(c,delim,&sp); + while (tok) + { + pics.Append(strdup(tok)); + tok=strtok_r(NULL,delim,&sp); + } + free(c); +} + void cXMLTVEvent::SetStarRating(const char *StarRating) { if (!StarRating) return; @@ -210,6 +226,11 @@ void cXMLTVEvent::AddReview(const char *Review) review.Append(compactspace(strdup(Review))); } +void cXMLTVEvent::AddPics(const char* Pic) +{ + pics.Append(compactspace(strdup(Pic))); +} + void cXMLTVEvent::AddVideo(const char *VType, const char *VContent) { char *value=NULL; @@ -272,18 +293,19 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan const char *ra=rating.toString(); const char *sr=starrating.toString(); const char *vi=video.toString(); + const char *pi=pics.toString(); if (asprintf(&sql,"INSERT OR IGNORE INTO epg (src,channelid,eventid,starttime,duration,"\ "title,origtitle,shorttext,description,country,year,credits,category,"\ - "review,rating,starrating,video,audio,season,episode,picexists,srcidx) "\ + "review,rating,starrating,video,audio,season,episode,episodeoverall,pics,srcidx) "\ "VALUES (^%s^,^%s^,%i,%li,%i,"\ "^%s^,^%s^,^%s^,^%s^,^%s^,%i,^%s^,^%s^,"\ - "^%s^,^%s^,^%s^,^%s^,^%s^,%i,%i,%i,%i);"\ + "^%s^,^%s^,^%s^,^%s^,^%s^,%i,%i,%i,^%s^,%i);"\ "UPDATE epg SET duration=%i,starttime=%li,title=^%s^,origtitle=^%s^,"\ "shorttext=^%s^,description=^%s^,country=^%s^,year=%i,credits=^%s^,category=^%s^,"\ "review=^%s^,rating=^%s^,starrating=^%s^,video=^%s^,audio=^%s^,season=%i,episode=%i, "\ - "picexists=%i,srcidx=%i " \ + "episodeoverall=%i,pics=^%s^,srcidx=%i " \ " where changes()=0 and src=^%s^ and channelid=^%s^ and eventid=%i" , Source,ChannelID,eventid,starttime,duration,title, @@ -294,7 +316,7 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan year, cr,ca,re,ra,sr,vi, audio ? audio : "NULL", - season, episode, picexists, SrcIdx, + season, episode, episodeoverall, pi, SrcIdx, duration,starttime,title, origtitle ? origtitle : "NULL", @@ -304,7 +326,7 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan year, cr,ca,re,ra,sr,vi, audio ? audio : "NULL", - season, episode, picexists, SrcIdx, + season, episode, episodeoverall, pi, SrcIdx, Source,ChannelID,eventid @@ -386,11 +408,12 @@ void cXMLTVEvent::Clear() review.Clear(); rating.Clear(); starrating.Clear(); + pics.Clear(); season=0; episode=0; + episodeoverall=0; parentalRating=0; memset(&contents,0,sizeof(contents)); - picexists=false; } cXMLTVEvent::cXMLTVEvent() @@ -42,12 +42,12 @@ private: char *sql; char *channelid; char *source; - bool picexists; int year; time_t starttime; int duration; int season; int episode; + int episodeoverall; tEventID eventid; tEventID eiteventid; cXMLTVStringList video; @@ -56,6 +56,7 @@ private: cXMLTVStringList review; cXMLTVStringList rating; cXMLTVStringList starrating; + cXMLTVStringList pics; int parentalRating; uchar contents[MaxEventContents]; public: @@ -77,12 +78,14 @@ public: void AddReview(const char *Review); void AddRating(const char *System, const char *Rating); void AddStarRating(const char *System, const char *Rating); + void AddPics(const char *Pic); void SetCredits(const char *Credits); void SetCategory(const char *Category); void SetReview(const char *Review); void SetRating(const char *Rating); void SetStarRating(const char *StarRating); void SetVideo(const char *Video); + void SetPics(const char *Pics); const char *GetSQL(const char *Source, int SrcIdx, const char *ChannelID); cXMLTVStringList *Credits() { @@ -108,6 +111,10 @@ public: { return &video; } + cXMLTVStringList *Pics() + { + return &pics; + } void SetSeason(int Season) { season=Season; @@ -116,6 +123,10 @@ public: { episode=Episode; } + void SetEpisodeOverall(int EpisodeOverall) + { + episodeoverall=EpisodeOverall; + } void SetYear(int Year) { year=Year; @@ -136,10 +147,6 @@ public: { eiteventid=EventID; } - void SetPicExists(void) - { - picexists=true; - } int ParentalRating() const { return parentalRating; @@ -212,9 +219,9 @@ public: { return episode; } - bool PicExists(void) + int EpisodeOverall(void) { - return picexists; + return episodeoverall; } }; @@ -275,18 +275,77 @@ bool cImport::WasChanged(cEvent* Event) return true; } +void cImport::LinkPictures(const char *Source, cXMLTVStringList *Pics, tEventID DestID) +{ + // source-pics are located in /var/lib/epgsources/%SOURCE%-img/ + // dest-pics are located in /var/cache/vdr/epgimages + + for (int i=0; i<Pics->Size(); i++) + { + char *pic=(*Pics)[i]; + char *src; + if (asprintf(&src,"/var/lib/epgsources/%s-img/%s",Source,pic)==-1) return; + + char *ext=strrchr(pic,'.'); + if (ext) + { + ext++; + char *dst; + int ret; + if (!i) + { + ret=asprintf(&dst,"%s/%i.%s",imgdir,DestID,ext); + } + else + { + ret=asprintf(&dst,"%s/%i_%i.%s",imgdir,DestID,i,ext); + } + if (ret==-1) + { + free(src); + return; + } + struct stat statbuf; + if (stat(dst,&statbuf)==-1) + { + if (symlink(src,dst)==-1) + { + if (!i) + { + tsyslog("failed to link %s to %i.%s",pic,DestID,ext); + } + else + { + tsyslog("failed to link %s to %i_%i.%s",pic,DestID,i,ext); + } + } + else + { + if (!i) + { + tsyslog("linked %s to %i.%s",pic,DestID,ext); + } + else + { + tsyslog("linked %s to %i_%i.%s",pic,DestID,i,ext); + } + } + } + } + } +} + bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, cEvent *Event, cXMLTVEvent *xEvent,int Flags) { if (!Source) return false; if (!Db) return false; - if (!Schedule) return false; if (!xEvent) return false; #define CHANGED_NOTHING 0 -#define CHANGED_SHORTTEXT 1 -#define CHANGED_DESCRIPTION 2 -#define CHANGED_ALL 3 +#define CHANGED_TITLE 1 +#define CHANGED_SHORTTEXT 2 +#define CHANGED_DESCRIPTION 4 struct tm tm; char from[80]; @@ -301,6 +360,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, if (append && !Event) { + if (!Schedule) return false; start=xEvent->StartTime(); end=start+xEvent->Duration(); @@ -431,9 +491,26 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, if (WasChanged(Event)) eitdescription=NULL; // we cannot use Event->Description() - it is already changed! if (!xEvent->EITEventID() || eitdescription) { + if (!xEvent->EITEventID() && xEvent->Pics()->Size() && Source->UsePics()) + { + /* here's a good place to link pictures! */ + LinkPictures(xEvent->Source(),xEvent->Pics(),Event->EventID()); + } UpdateXMLTVEvent(Source,Db,Event,xEvent,eitdescription); } - if (!eitdescription && !xEvent->EITDescription()) return false; + } + + if ((Flags & USE_TITLE)==USE_TITLE) + { + if (xEvent->Title() && (strlen(xEvent->Title())>0)) + { + const char *dp=conv->Convert(xEvent->Title()); + if (!Event->Title() || strcmp(Event->Title(),dp)) + { + Event->SetTitle(dp); + changed|=CHANGED_TITLE; // title really changed + } + } } if (((Flags & USE_SHORTTEXT)==USE_SHORTTEXT) || (append)) @@ -657,6 +734,12 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, cTEXTMapping *text=texts->GetMap("episode"); if (text) description=Add2Description(description,text->Value(),xEvent->Episode()); } + + if (xEvent->EpisodeOverall()) + { + cTEXTMapping *text=texts->GetMap("episodeoverall"); + if (text) description=Add2Description(description,text->Value(),xEvent->EpisodeOverall()); + } } if (((Flags & USE_RATING)==USE_RATING) && (xEvent->Rating()->Size())) @@ -769,7 +852,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, if (!append && changed) { - if ((changed==CHANGED_SHORTTEXT) && (WasChanged(Event)==false)) + if (((changed & CHANGED_SHORTTEXT)==CHANGED_SHORTTEXT) && (WasChanged(Event)==false)) { if (Event->Description()) description=strdup(Event->Description()); if (description) @@ -789,21 +872,17 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm); localtime_r(&end,&tm); strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm); - switch (changed) - { - case CHANGED_SHORTTEXT: - 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 descr of '%s'@%s-%s",Event->EventID(), - Event->Title(),from,till); - break; - case CHANGED_ALL: - tsyslogs(Source,"{%i} changing stext (%s)+descr of '%s'@%s-%s",Event->EventID(), - Event->ShortText(),Event->Title(),from,till); - break; - } + + char buf[256]=""; + if ((changed & CHANGED_TITLE)==CHANGED_TITLE) strcat(buf,"title,"); + if ((changed & CHANGED_SHORTTEXT)==CHANGED_SHORTTEXT) strcat(buf,"stext,"); + if ((changed & CHANGED_DESCRIPTION)==CHANGED_DESCRIPTION) strcat(buf,"descr,"); + int len=strlen(buf); + if (len>0) buf[len-1]=0; + + tsyslogs(Source,"{%i} changing %s of '%s'/'%s'@%s-%s",Event->EventID(), + buf,Event->Title(),Event->ShortText() ? Event->ShortText() : "", + from,till); } retcode=true; } @@ -878,15 +957,18 @@ bool cImport::FetchXMLTVEvent(sqlite3_stmt *stmt, cXMLTVEvent *xevent) xevent->SetEpisode(sqlite3_column_int(stmt,col)); break; case 19: - if (sqlite3_column_int(stmt,col)==1) xevent->SetPicExists(); + xevent->SetEpisodeOverall(sqlite3_column_int(stmt,col)); + break; + case 20: + xevent->SetPics((const char *) sqlite3_column_text(stmt,col)); break; - case 20: // source + case 21: // source xevent->SetSource((const char *) sqlite3_column_text(stmt,col)); break; - case 21: // eiteventid + case 22: // eiteventid xevent->SetEITEventID(sqlite3_column_int(stmt,col)); break; - case 22: // eitdescription + case 23: // eitdescription xevent->SetEITDescription((const char *) sqlite3_column_text(stmt,col)); break; } @@ -920,18 +1002,20 @@ cXMLTVEvent *cImport::PrepareAndReturn(sqlite3 *db, char *sql) } cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char *ChannelID, const cEvent *Event, - const char *EITDescription) + const char *EITDescription, bool UseEPText) { if (!Db) return NULL; if (!Source) return NULL; if (!ChannelID) return NULL; if (!Event) return NULL; - if (!EITDescription) return NULL; if (!epdir) return NULL; - int season,episode; + int season,episode,episodeoverall; + char *epshorttext=NULL,*eptitle=NULL; if (!cParse::FetchSeasonEpisode(cep2ascii,cutf2ascii,epdir,Event->Title(), - Event->ShortText(),season,episode)) + Event->ShortText(),Event->Description(), + season,episode,episodeoverall,&epshorttext, + &eptitle)) { #ifdef VDRDEBUG tsyslogs(Source,"no season/episode found for '%s'/'%s'",Event->Title(),Event->ShortText()); @@ -943,19 +1027,34 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * if (!xevent) { esyslogs(Source,"out of memory"); + free(epshorttext); + free(eptitle); return NULL; } - xevent->SetTitle(Event->Title()); + if (UseEPText) + { + if (eptitle) xevent->SetTitle(eptitle); + if (epshorttext) xevent->SetShortText(epshorttext); + } + else + { + xevent->SetTitle(Event->Title()); + xevent->SetShortText(Event->ShortText()); + } xevent->SetStartTime(Event->StartTime()); xevent->SetDuration(Event->Duration()); - xevent->SetShortText(Event->ShortText()); xevent->SetEventID(Event->EventID()); xevent->SetEITEventID(Event->EventID()); - xevent->SetDescription(EITDescription); - xevent->SetEITDescription(EITDescription); + if (EITDescription) + { + xevent->SetDescription(EITDescription); + xevent->SetEITDescription(EITDescription); + } xevent->SetSeason(season); xevent->SetEpisode(episode); + xevent->SetEpisodeOverall(episodeoverall); + free(epshorttext); if (!Begin(Source,Db)) { @@ -963,7 +1062,7 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * return NULL; } - const char *sql=xevent->GetSQL(Source->Name(),Source->Index(),ChannelID); + const char *sql=xevent->GetSQL(Source->Name(),99,ChannelID); char *errmsg; if (sqlite3_exec(Db,sql,NULL,NULL,&errmsg)!=SQLITE_OK) { @@ -972,6 +1071,10 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * delete xevent; xevent=NULL; } + else + { + tsyslogs(Source,"{%i} adding '%s'/'%s' to db",xevent->EventID(),xevent->Title(),xevent->ShortText()); + } return xevent; } @@ -1089,8 +1192,8 @@ cXMLTVEvent *cImport::SearchXMLTVEvent(sqlite3 **Db,const char *ChannelID, const char *sql=NULL; if (asprintf(&sql,"select channelid,eventid,starttime,duration,title,origtitle,shorttext,description," \ - "country,year,credits,category,review,rating,starrating,video,audio,season,episode," \ - "picexists,src,eiteventid,eitdescription from epg where eiteventid=%li and channelid='%s' " \ + "country,year,credits,category,review,rating,starrating,video,audio,season,episode,episodeoverall," \ + "pics,src,eiteventid,eitdescription from epg where eiteventid=%li and channelid='%s' " \ "order by srcidx asc limit 1;",(long int) Event->EventID(),ChannelID)==-1) { esyslog("out of memory"); @@ -1127,7 +1230,7 @@ cXMLTVEvent *cImport::SearchXMLTVEvent(sqlite3 **Db,const char *ChannelID, const if (asprintf(&sql,"select channelid,eventid,starttime,duration,title,origtitle,shorttext,description," \ "country,year,credits,category,review,rating,starrating,video,audio,season,episode," \ - "picexists,src,eiteventid,eitdescription,abs(starttime-%li) as diff from epg where " \ + "episodeoverall,pics,src,eiteventid,eitdescription,abs(starttime-%li) as diff from epg where " \ " (starttime>=%li and starttime<=%li) and title='%s' and channelid='%s' " \ " order by diff,srcidx asc limit 1;",Event->StartTime(),Event->StartTime()-eventTimeDiff, Event->StartTime()+eventTimeDiff,sqltitle,ChannelID)==-1) @@ -1228,8 +1331,8 @@ int cImport::Process(cEPGSource *Source, cEPGExecutor &myExecutor) char *sql; if (asprintf(&sql,"select channelid,eventid,starttime,duration,title,origtitle,shorttext,description," \ - "country,year,credits,category,review,rating,starrating,video,audio,season,episode," \ - "picexists,src,eiteventid,eitdescription from epg where (starttime > %li or " \ + "country,year,credits,category,review,rating,starrating,video,audio,season,episode,episodeoverall," \ + "pics,src,eiteventid,eitdescription from epg where (starttime > %li or " \ " (starttime + duration) > %li) and (starttime + duration) < %li "\ " and src='%s';",begin,begin,end,Source->Name())==-1) { @@ -1321,11 +1424,25 @@ int cImport::Process(cEPGSource *Source, cEPGExecutor &myExecutor) { if (cnt) { - dsyslogs(Source,"processed %i vdr events",cnt); + if (!lerr) + { + isyslogs(Source,"processed %i vdr events",cnt); + } + else + { + isyslogs(Source,"processed %i vdr events - see ERRORs above!",cnt); + } } else { - dsyslogs(Source,"processed no vdr events - all up to date?"); + if (!lerr) + { + isyslogs(Source,"processed no vdr events - all up to date?"); + } + else + { + isyslogs(Source,"processed no vdr events - see ERRORs above!"); + } } } @@ -1344,34 +1461,24 @@ bool cImport::DBExists() return true; } - -cImport::cImport(const char *EPGFile, const char *EPDir, const char *CodeSet, cEPGMappings* Maps, cTEXTMappings *Texts) +cImport::cImport(cGlobals *Global) { - maps=Maps; - texts=Texts; - pendingtransaction=false; - epgfile=EPGFile; - codeset=CodeSet; + maps=Global->EPGMappings(); + texts=Global->TEXTMappings(); + epgfile=Global->EPGFile(); + codeset=Global->Codeset(); + imgdir=Global->ImgDir(); + pendingtransaction=false; conv = new cCharSetConv("UTF-8",codeset); - if (EPDir) + epdir=Global->EPDir(); + if (epdir) { - epdir=strdup(EPDir); - if (!epdir) return; - char *charset=strchr((char *) epdir,','); - if (charset) - { - *charset=0; - } - else - { - charset=(char *) "UTF-8"; - } - cep2ascii=iconv_open(charset,"US-ASCII//TRANSLIT"); - cutf2ascii=iconv_open("UTF-8","US-ASCII//TRANSLIT"); + cep2ascii=iconv_open("ASCII//TRANSLIT",Global->EPCodeset()); + cutf2ascii=iconv_open("ASCII//TRANSLIT","UTF-8"); } else - { + { epdir=NULL; } } @@ -1380,7 +1487,6 @@ cImport::~cImport() { if (epdir) { - free((void *) epdir); iconv_close(cep2ascii); iconv_close(cutf2ascii); } @@ -18,6 +18,7 @@ class cEPGSource; class cEPGExecutor; +class cGlobals; class cImport { @@ -41,6 +42,7 @@ private: cTEXTMappings *texts; cCharSetConv *conv; const char *codeset; + const char *imgdir; iconv_t cep2ascii; iconv_t cutf2ascii; const char *epdir; @@ -58,8 +60,9 @@ private: char *RemoveNonASCII(const char *src); cXMLTVEvent *PrepareAndReturn(sqlite3 *db, char *sql); public: - cImport(const char *EPGFile, const char *EPDir, const char *CodeSet, cEPGMappings *Maps, cTEXTMappings *Texts); + cImport(cGlobals *Global); ~cImport(); + void LinkPictures(const char *Source, cXMLTVStringList *Pics, tEventID DestID); int Process(cEPGSource *Source, cEPGExecutor &myExecutor); bool Begin(cEPGSource *Source, sqlite3 *Db); bool Commit(cEPGSource *Source, sqlite3 *Db); @@ -70,7 +73,7 @@ public: 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); + const cEvent *Event, const char *EITDescription, bool UseEPText); bool WasChanged(cEvent *Event); }; @@ -31,6 +31,7 @@ #define USE_AUDIO 0x200 #define USE_SEASON 0x400 #define USE_STARRATING 0x800 +#define USE_TITLE 0x1000 #define CREDITS_ACTORS 0x100000 #define CREDITS_DIRECTORS 0x200000 @@ -39,9 +40,12 @@ #define OPT_RATING_TEXT 0x1000000 #define OPT_CATEGORIES_TEXT 0x2000000 - +#define OPT_SEASON_SHORTTEXT 0x4000000 #define OPT_APPEND 0x40000000 +#define EPLIST_USE_SEASON 0x1 +#define EPLIST_USE_TEXT 0x2 + class cTEXTMapping : public cListObject { private: @@ -150,12 +150,23 @@ void cParse::RemoveNonAlphaNumeric(char *String) } bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const char *EPDir, - const char *Title, const char *ShortText, int &Season, int &Episode) + const char *Title, const char *ShortText, const char *Description, + int &Season, int &Episode, int &EpisodeOverall, char **EPShortText, + char **EPTitle) { // Title and ShortText are always UTF8 ! if (!EPDir) return false; - if (!ShortText) return false; - size_t slen=strlen(ShortText); + if ((!ShortText) && (!Description)) return false; + size_t slen; + if (ShortText) + { + slen=strlen(ShortText); + } + else + { + slen=strlen(Description); + if (slen>40) slen=40; + } if (!slen) return false; if (!Title) return false; if (cEP2ASCII==(iconv_t) -1) return false; @@ -199,11 +210,12 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha free(epfile); return false; } - char *FromPtr=(char *) ShortText; + char *FromPtr=(char *)(ShortText ? ShortText : Description); char *ToPtr=(char *) dshorttext; if (iconv(cUTF2ASCII,&FromPtr,&slen,&ToPtr,&dlen)==(size_t) -1) { + tsyslog("failed to convert '%s'->'%s' (1)",ShortText,dshorttext); free(dshorttext); fclose(f); free(epfile); @@ -213,7 +225,7 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha RemoveNonAlphaNumeric(dshorttext); if (!strlen(dshorttext)) { - strcpy(dshorttext,ShortText); // ok lets try with the original text + strn0cpy(dshorttext,ShortText ? ShortText : Description,slen); // ok lets try with the original text } char *line=NULL; @@ -224,7 +236,7 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha if (line[0]=='#') continue; char epshorttext[256]=""; char depshorttext[1024]=""; - if (sscanf(line,"%3d\t%3d\t%*3d\t%255c",&Season,&Episode,epshorttext)==3) + if (sscanf(line,"%3d\t%3d\t%5d\t%255c",&Season,&Episode,&EpisodeOverall,epshorttext)==4) { char *lf=strchr(epshorttext,'\n'); if (lf) *lf=0; @@ -242,13 +254,23 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha if (!strncasecmp(dshorttext,depshorttext,strlen(depshorttext))) { found=true; + if (EPShortText) *EPShortText=strdup(epshorttext); + if (EPTitle) *EPTitle=strdup(dirent->d_name); break; } } + else + { + tsyslog("failed to convert '%s'->'%s' (2)",epshorttext,depshorttext); + } + } + else + { + tsyslog("failed to parse '%s' in '%s'",line,dirent->d_name); } } - if (!found) + if ((!found) && (ShortText)) { isyslog("failed to find '%s' for '%s' in eplists",ShortText,Title); } @@ -260,7 +282,7 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha return found; } -bool cParse::FetchEvent(xmlNodePtr enode) +bool cParse::FetchEvent(xmlNodePtr enode, bool useeptext) { char *slang=getenv("LANG"); xmlNodePtr node=enode->xmlChildrenNode; @@ -517,7 +539,15 @@ bool cParse::FetchEvent(xmlNodePtr enode) f=src; } struct stat statbuf; - if (stat((const char *) f,&statbuf)!=-1) xevent.SetPicExists(); + if (stat((const char *) f,&statbuf)!=-1) + { + char *file=strrchr((char *) f,'/'); + if (file) + { + file++; + xevent.AddPics(file); + } + } xmlFree(src); } @@ -542,11 +572,29 @@ bool cParse::FetchEvent(xmlNodePtr enode) node=node->next; } - int season,episode; - if (FetchSeasonEpisode(cep2ascii,cutf2ascii,epdir,xevent.Title(),xevent.ShortText(),season,episode)) + int season,episode,episodeoverall; + char *epshorttext=NULL; + char *eptitle=NULL; + if (FetchSeasonEpisode(cep2ascii,cutf2ascii,epdir,xevent.Title(),xevent.ShortText(), + xevent.Description(),season,episode,episodeoverall,&epshorttext, + &eptitle)) { xevent.SetSeason(season); xevent.SetEpisode(episode); + xevent.SetEpisodeOverall(episodeoverall); + if (useeptext) + { + if (epshorttext) + { + xevent.SetShortText(epshorttext); + free(epshorttext); + } + if (eptitle) + { + xevent.SetTitle(eptitle); + free(eptitle); + } + } } return xevent.HasTitle(); } @@ -610,8 +658,8 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) "shorttext nvarchar(255), description text, eitdescription text, " \ "country nvarchar(255), year int, " \ "credits text, category text, review text, rating text, " \ - "starrating text, video text, audio text, season int, episode int, picexists int," \ - "srcidx int," \ + "starrating text, video text, audio text, season int, episode int, " \ + "episodeoverall int, pics text, srcidx int," \ "PRIMARY KEY(src, channelid, eventid)" \ ");" \ "CREATE UNIQUE INDEX IF NOT EXISTS idx1 on epg (eventid, src); " \ @@ -707,9 +755,11 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) xevent.SetStartTime(starttime); if (stoptime) xevent.SetDuration(stoptime-starttime); - if (!FetchEvent(node)) // sets xevent + if (!FetchEvent(node,(map->Flags() & OPT_SEASON_SHORTTEXT)==OPT_SEASON_SHORTTEXT)) // sets xevent { - tsyslogs(source,"failed to fetch event"); + if (lerr!=PARSE_FETCHERR) + esyslogs(source,"failed to fetch event"); + lerr=PARSE_FETCHERR; node=node->next; continue; } @@ -718,7 +768,9 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) const char *sql=xevent.GetSQL(source->Name(),source->Index(),map->ChannelIDs()[i].ToString()); if (sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK) { - tsyslogs(source,"sqlite3: %s",errmsg); + if (lerr!=PARSE_SQLERR) + esyslogs(source,"sqlite3: %s",errmsg); + lerr=PARSE_SQLERR; sqlite3_free(errmsg); break; } @@ -733,7 +785,15 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) } } - dsyslogs(source,"processed %i xmltv events",cnt); + if (!lerr) + { + isyslogs(source,"processed %i xmltv events",cnt); + } + else + { + isyslogs(source,"processed %i xmltv events - see ERRORs above!",cnt); + + } if (sqlite3_exec(db,"COMMIT; ANALYZE epg;",NULL,NULL,&errmsg)!=SQLITE_OK) { @@ -758,26 +818,16 @@ void cParse::CleanupLibXML() xmlCleanupParser(); } -cParse::cParse(const char *EPGFile, const char *EPDir, cEPGSource *Source, cEPGMappings *Maps) +cParse::cParse(cEPGSource *Source, cGlobals *Global) { source=Source; - maps=Maps; - epgfile=EPGFile; - if (EPDir) + maps=Global->EPGMappings(); + epgfile=Global->EPGFile(); + epdir=Global->EPDir(); + if (epdir) { - epdir=strdup(EPDir); - if (!epdir) return; - char *charset=strchr((char *) epdir,','); - if (charset) - { - *charset=0; - } - else - { - charset=(char *) "UTF-8"; - } - cep2ascii=iconv_open(charset,"US-ASCII//TRANSLIT"); - cutf2ascii=iconv_open("UTF-8","US-ASCII//TRANSLIT"); + cep2ascii=iconv_open("ASCII//TRANSLIT",Global->EPCodeset()); + cutf2ascii=iconv_open("ASCII//TRANSLIT","UTF-8"); } else { @@ -789,7 +839,6 @@ cParse::~cParse() { if (epdir) { - free((void *) epdir); iconv_close(cep2ascii); iconv_close(cutf2ascii); } @@ -17,6 +17,8 @@ class cEPGExecutor; class cEPGSource; +class cEPGMappings; +class cGlobals; class cParse { @@ -25,7 +27,9 @@ class cParse PARSE_NOERROR=0, PARSE_XMLTVERR, PARSE_NOMAPPING, - PARSE_NOCHANNELID + PARSE_NOCHANNELID, + PARSE_FETCHERR, + PARSE_SQLERR }; private: @@ -37,15 +41,16 @@ private: cEPGMappings *maps; cXMLTVEvent xevent; time_t ConvertXMLTVTime2UnixTime(char *xmltvtime); - bool FetchEvent(xmlNodePtr node); + bool FetchEvent(xmlNodePtr node, bool useeptext); public: - cParse(const char *EPGFile, const char *EPDir, cEPGSource *Source, cEPGMappings *Maps); + cParse(cEPGSource *Source, cGlobals *Global); ~cParse(); int Process(cEPGExecutor &myExecutor, char *buffer, int bufsize); static void RemoveNonAlphaNumeric(char *String); static bool FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const char *EPDir, - const char *Title, const char *ShortText, int &Season, - int &Episode); + const char *Title, const char *ShortText, const char *Description, + int &Season, int &Episode, int &EpisodeOverall, char **EPShortText, + char **EPTitle); static void InitLibXML(); static void CleanupLibXML(); }; diff --git a/po/de_DE.po b/po/de_DE.po index bac9aa3..7651c4f 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: 2012-04-14 18:03+0200\n" +"POT-Creation-Date: 2012-05-04 18:58+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" @@ -19,6 +19,9 @@ msgstr "Optionen" msgid "add season/episode on all timers" msgstr "Staffel/Episode an alle Timer anhängen" +msgid " add shorttext/title from list" +msgstr " Kurztext/Titel von Liste übernehmen" + msgid "automatic wakeup" msgstr "automatisch Aufwachen" @@ -118,6 +121,9 @@ msgstr "Anzahl Tage" msgid "pin" msgstr "Pin" +msgid "download pics" +msgstr "" + msgid "channels provided" msgstr "Verfügbare Kanäle" @@ -148,9 +154,6 @@ msgstr "Kurztext" msgid "long text" msgstr "Langtext" -msgid " merge long texts" -msgstr " Langtexte zusammenführen" - msgid " actors" msgstr " Darsteller" @@ -181,6 +184,9 @@ msgstr "Video" msgid "audio" msgstr "Audio" +msgid " add shorttext from list" +msgstr " Kurztext von Liste übernehmen" + msgid "epg source channel mappings" msgstr "EPG Quellkanalzuordnungen" @@ -259,9 +265,11 @@ msgstr "Staffel" msgid "episode" msgstr "Episode" +msgid "episodeoverall" +msgstr "Folge" + msgid "xmltv2vdr plugin still working" 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 48c9f59..5468f97 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: 2012-04-14 18:03+0200\n" +"POT-Creation-Date: 2012-05-04 18:58+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" @@ -22,6 +22,9 @@ msgstr "Opzioni" msgid "add season/episode on all timers" msgstr "" +msgid " add shorttext/title from list" +msgstr "" + msgid "automatic wakeup" msgstr "Risveglio automatico" @@ -121,6 +124,9 @@ msgstr "Giorni in anticipo" msgid "pin" msgstr "Pin" +msgid "download pics" +msgstr "" + msgid "channels provided" msgstr "Canali forniti" @@ -151,9 +157,6 @@ msgstr "Testo breve" msgid "long text" msgstr "Testo completo" -msgid " merge long texts" -msgstr " Unisci testi completi" - msgid " actors" msgstr " Attore" @@ -184,6 +187,9 @@ msgstr "Video" msgid "audio" msgstr "Audio" +msgid " add shorttext from list" +msgstr "" + msgid "epg source channel mappings" msgstr "Mappature canali sorgente EPG" @@ -262,6 +268,9 @@ msgstr "" msgid "episode" msgstr "" +msgid "episodeoverall" +msgstr "" + msgid "xmltv2vdr plugin still working" msgstr "Plugin XMLTV2VDR ancora in esecuzione" @@ -59,7 +59,7 @@ cMenuSetupXmltv2vdr::cMenuSetupXmltv2vdr(cPluginXmltv2vdr *Plugin) baseplugin=Plugin; baseplugin->SetSetupState(true); sourcesBegin=sourcesEnd=mappingBegin=mappingEnd=mappingEntry=0; - epall=(int) baseplugin->EPAll(); + epall=(unsigned int) baseplugin->EPAll(); wakeup=(int) baseplugin->WakeUp(); cs=NULL; cm=NULL; @@ -84,7 +84,18 @@ void cMenuSetupXmltv2vdr::Output(void) epEntry=0; if (baseplugin->EPDir()) { - Add(new cMenuEditBoolItem(tr("add season/episode on all timers"),&epall),true); + Add(new cMyMenuEditBitItem(tr("add season/episode on all timers"), + &epall,EPLIST_USE_SEASON),true); + epEntry=Current(); + if ((epall & EPLIST_USE_SEASON)==EPLIST_USE_SEASON) + { + Add(new cMyMenuEditBitItem(tr(" add shorttext/title from list"), + &epall,EPLIST_USE_TEXT),true); + } + else + { + epall=0; + } } Add(new cMenuEditBoolItem(tr("automatic wakeup"),&wakeup),true); @@ -208,7 +219,7 @@ void cMenuSetupXmltv2vdr::Store(void) SetupStore("options.epall",epall); SetupStore("options.wakeup",wakeup); - baseplugin->SetEPAll((bool) epall); + baseplugin->SetEPAll(epall); baseplugin->SetWakeUp((bool) wakeup); } @@ -432,9 +443,10 @@ cMenuSetupXmltv2vdrTextMap::cMenuSetupXmltv2vdrTextMap(cPluginXmltv2vdr *Plugin) Add(NewTitle(tr("season and episode"))); settval(season); settval(episode); + settval(episodeoverall); Add(new cMenuEditStrItem("season",season,sizeof(season))); Add(new cMenuEditStrItem("episode",episode,sizeof(episode))); - + Add(new cMenuEditStrItem("episodeoverall",episodeoverall,sizeof(episodeoverall))); } void cMenuSetupXmltv2vdrTextMap::Store() @@ -473,6 +485,7 @@ void cMenuSetupXmltv2vdrTextMap::Store() savetval(starrating); savetval(season); savetval(episode); + savetval(episodeoverall); SetupStore("textmap.country",country); SetupStore("textmap.year",year); @@ -498,6 +511,7 @@ void cMenuSetupXmltv2vdrTextMap::Store() SetupStore("textmap.starrating",starrating); SetupStore("textmap.season",season); SetupStore("textmap.episode",episode); + SetupStore("textmap.episodeoverall",episodeoverall); } // -------------------------------------------------------------------------------------------------------- @@ -709,6 +723,7 @@ cMenuSetupXmltv2vdrChannelSource::cMenuSetupXmltv2vdrChannelSource(cPluginXmltv2 SetSection(cString::sprintf("%s '%s' : %s",trVDR("Plugin"), baseplugin->Name(), epgsrc->Name())); + usepics=epgsrc->UsePics(); weekday=epgsrc->ExecWeekDay(); start=epgsrc->ExecTime(); days=epgsrc->DaysInAdvance(); @@ -744,6 +759,10 @@ void cMenuSetupXmltv2vdrChannelSource::output(void) } Add(new cMenuEditStrItem(tr("pin"),pin,sizeof(pin))); } + if (epgsrc->HasPics()) + { + Add(new cMenuEditBoolItem(tr("download pics"),&usepics)); + } Add(NewTitle(tr("channels provided"))); cEPGChannels *channellist=epgsrc->ChannelList(); @@ -795,6 +814,8 @@ void cMenuSetupXmltv2vdrChannelSource::Store(void) epgsrc->ChangeDaysInAdvance(days); if (epgsrc->NeedPin()) epgsrc->ChangePin(pin); + if (epgsrc->HasPics()) + epgsrc->ChangePics(usepics); epgsrc->Store(); } @@ -827,7 +848,7 @@ cMenuSetupXmltv2vdrChannelMap::cMenuSetupXmltv2vdrChannelMap(cPluginXmltv2vdr *P SetTitle(title); flags=map->Flags(); - c1=c3=cm=0; + c1=c2=c3=c4=cm=0; SetHelp(NULL,NULL,tr("Button$Reset"),tr("Button$Copy")); output(); } @@ -900,13 +921,12 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) { Add(option(tr("short text"),true),true); Add(option(tr("long text"),true),true); - Add(option(tr(" merge long texts"),false),true); } Add(new cMyMenuEditBitItem(tr("country and date"),&flags,USE_COUNTRYDATE),true); Add(new cMyMenuEditBitItem(tr("original title"),&flags,USE_ORIGTITLE),true); Add(new cMyMenuEditBitItem(tr("category"),&flags,USE_CATEGORIES),true); Add(new cMyMenuEditBitItem(tr("credits"),&flags,USE_CREDITS),true); - c3=Current(); + c2=Current(); if ((flags & USE_CREDITS)==USE_CREDITS) { Add(new cMyMenuEditBitItem(tr(" actors"),&flags,CREDITS_ACTORS),true); @@ -917,7 +937,11 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) Add(new cMyMenuEditBitItem(tr("rating"),&flags,USE_RATING),true); #if VDRVERSNUM >= 10711 || EPGHANDLER - Add(new cMyMenuEditBitItem(tr(" rating in description"),&flags,OPT_RATING_TEXT),true); + c3=Current(); + if ((flags & USE_RATING)==USE_RATING) + { + Add(new cMyMenuEditBitItem(tr(" rating in description"),&flags,OPT_RATING_TEXT),true); + } #endif Add(new cMyMenuEditBitItem(tr("starrating"),&flags,USE_STARRATING),true); Add(new cMyMenuEditBitItem(tr("review"),&flags,USE_REVIEW),true); @@ -927,6 +951,11 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) if (baseplugin->EPDir()) { Add(new cMyMenuEditBitItem(tr("season and episode"),&flags,USE_SEASON),true); + c4=Current(); + if ((flags & USE_SEASON)==USE_SEASON) + { + Add(new cMyMenuEditBitItem(tr(" add shorttext from list"),&flags,OPT_SEASON_SHORTTEXT),true); + } } hasmaps=false; @@ -979,7 +1008,7 @@ eOSState cMenuSetupXmltv2vdrChannelMap::ProcessKey(eKeys Key) case kLeft|k_Repeat: case kRight: case kRight|k_Repeat: - if ((Current()==c1) || (Current()==c3)) output(); + if ((Current()==c1) || (Current()==c2) || (Current()==c3) || (Current()==c4)) output(); break; case kDown: case kDown|k_Repeat: @@ -40,7 +40,7 @@ private: int epEntry; eOSState edit(void); void generatesumchannellist(); - int epall; + unsigned int epall; int wakeup; public: void Output(void); @@ -85,6 +85,7 @@ private: char category[255]; char season[255]; char episode[255]; + char episodeoverall[255]; char starrating[255]; char audio[255]; char video[255]; @@ -108,6 +109,7 @@ private: time_t day; int weekday,start; int days; + int usepics; char pin[255]; void output(void); public: @@ -136,7 +138,7 @@ private: int getdaysmax(); cOsdItem *option(const char *s, bool yesno); void epgmappingreplace(cEPGMapping *newmapping); - int c1,c3,cm; + int c1,c2,c3,c4,cm; public: cMenuSetupXmltv2vdrChannelMap(cPluginXmltv2vdr *Plugin, cMenuSetupXmltv2vdr *Menu, int Index); ~cMenuSetupXmltv2vdrChannelMap(); @@ -108,23 +108,22 @@ void cEPGExecutor::Action() // ------------------------------------------------------------- -cEPGSource::cEPGSource(const char *Name, const char *ConfDir, const char *EPGFile, - const char *EPDir, const char *CodeSet, cEPGMappings *Maps, - cTEXTMappings *Texts) +cEPGSource::cEPGSource(const char *Name, cGlobals *Global) { if (strcmp(Name,EITSOURCE)) { dsyslog("'%s' added epgsource",Name); } name=strdup(Name); - confdir=ConfDir; - epgfile=EPGFile; + confdir=Global->ConfDir(); + epgfile=Global->EPGFile(); pin=NULL; Log=NULL; loglen=0; usepipe=false; needpin=false; running=false; + haspics=usepics=false; daysinadvance=1; exec_time=10; exec_weekday=127; // Mon->Sun @@ -133,8 +132,8 @@ cEPGSource::cEPGSource(const char *Name, const char *ConfDir, const char *EPGFil if (strcmp(Name,EITSOURCE)) { ready2parse=ReadConfig(); - parse=new cParse(EPGFile,EPDir,this, Maps); - import=new cImport(EPGFile,EPDir,CodeSet,Maps,Texts); + parse=new cParse(this,Global); + import=new cImport(Global); dsyslogs(this,"is%sready2parse",(ready2parse && parse) ? " " : " not "); } else @@ -265,6 +264,19 @@ bool cEPGSource::ReadConfig() dsyslogs(this,"is needing a pin"); needpin=true; } + + char *pics=strchr(pn,';'); + if (pics) + { + *pics=0; + pics++; + pics=compactspace(pics); + if (pics[0]=='1') + { + dsyslogs(this,"is providing pics"); + haspics=true; + } + } } } } @@ -347,9 +359,11 @@ bool cEPGSource::ReadConfig() } if (linenr==2) { - int reserve; - sscanf(line,"%2d;%1d;%3d;%10d",&daysinadvance,&reserve,&exec_weekday,&exec_time); + int l_usepics=0; + sscanf(line,"%2d;%1d;%3d;%10d",&daysinadvance,&l_usepics,&exec_weekday,&exec_time); + if (l_usepics==1) usepics=true; dsyslogs(this,"daysinadvance=%i",daysinadvance); + dsyslogs(this,"using pics=%i",l_usepics); dsyslogs(this,"weekdays=%s",*cTimer::PrintDay(0,exec_weekday,true)); time_t nrt=NextRunTime(); dsyslogs(this,"nextrun on %s",ctime(&nrt)); @@ -730,7 +744,7 @@ void cEPGSource::Store(void) { fprintf(w,"#no pin\n"); } - fprintf(w,"%i;%i;%i;%i\n",daysinadvance,0,exec_weekday,exec_time); + fprintf(w,"%i;%i;%i;%i\n",daysinadvance,usepics,exec_weekday,exec_time); for (int i=0; i<ChannelList()->Count(); i++) { if (ChannelList()->Get(i)->InUse()) @@ -847,9 +861,7 @@ time_t cEPGSources::NextRunTime() return next; } -void cEPGSources::ReadIn(const char *ConfDir, const char *EpgFile, const char *EPDir, - const char *CodeSet, cEPGMappings *EPGMappings, - cTEXTMappings *TextMappings, const char *SourceOrder, +void cEPGSources::ReadIn(cGlobals *Global, const char *SourceOrder, bool Reload) { if (Reload) Remove(); @@ -880,7 +892,7 @@ void cEPGSources::ReadIn(const char *ConfDir, const char *EpgFile, const char *E id[4]=0; if (!strcmp(id,"file") || !strcmp(id,"pipe")) { - Add(new cEPGSource(dirent->d_name,ConfDir,EpgFile,EPDir,CodeSet,EPGMappings,TextMappings)); + Add(new cEPGSource(dirent->d_name,Global)); } else { @@ -906,8 +918,7 @@ void cEPGSources::ReadIn(const char *ConfDir, const char *EpgFile, const char *E if (!Exists(EITSOURCE)) { - Add(new cEPGSource(EITSOURCE,ConfDir,EpgFile,EPDir,CodeSet, - EPGMappings,TextMappings)); + Add(new cEPGSource(EITSOURCE,Global)); } if (!SourceOrder) return; @@ -45,6 +45,7 @@ public: class cEPGChannels : public cList<cEPGChannel> {}; class cImport; +class cGlobals; class cEPGSource : public cListObject { @@ -61,6 +62,8 @@ private: bool needpin; bool running; bool disabled; + bool haspics; + bool usepics; int daysinadvance; int exec_weekday; int exec_time; @@ -70,9 +73,7 @@ private: int ReadOutput(char *&result, size_t &l); cEPGChannels channels; public: - cEPGSource(const char *Name,const char *ConfDir,const char *EPGFile, - const char *EPDir, const char *CodeSet, cEPGMappings *Maps, - cTEXTMappings *Texts); + cEPGSource(const char *Name, cGlobals *Global); ~cEPGSource(); bool Trace() { @@ -125,6 +126,14 @@ public: { return needpin; } + bool HasPics() + { + return haspics; + } + bool UsePics() + { + return usepics; + } const char *Name() { return name; @@ -147,6 +156,10 @@ public: if (pin) free((void *) pin); pin=strdup(NewPin); } + void ChangePics(bool NewVal) + { + usepics=NewVal; + } void Add2Log(struct tm *Tm, const char Prefix, const char *Line); bool Active() { @@ -157,9 +170,7 @@ public: class cEPGSources : public cList<cEPGSource> { public: - void ReadIn(const char *ConfDir, const char *EpgFile, const char *EPDir, - const char *CodeSet, cEPGMappings *EPGMappings, - cTEXTMappings *TextMappings, const char *SourceOrder, + void ReadIn(cGlobals *Global, const char *SourceOrder, bool Reload=false); bool RunItNow(); time_t NextRunTime(); diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp index da7916e..a13a3d3 100644 --- a/xmltv2vdr.cpp +++ b/xmltv2vdr.cpp @@ -13,6 +13,7 @@ #include <locale.h> #include <langinfo.h> #include <sqlite3.h> +#include <time.h> #include <sys/types.h> #include <pwd.h> @@ -126,14 +127,116 @@ void logger(cEPGSource *source, char logtype, const char* format, ...) // ------------------------------------------------------------- -cEPGHandler::cEPGHandler(const char *EpgFile, const char *EPDir, const char *CodeSet, cEPGSources *Sources, - cEPGMappings *Maps, cTEXTMappings *Texts) : import(EpgFile,EPDir,CodeSet,Maps,Texts) +cGlobals::cGlobals() { - epall=false; - maps=Maps; - sources=Sources; + confdir=NULL; + epgfile=NULL; + epdir=NULL; + epcodeset=NULL; + imgdir=NULL; + codeset=NULL; + + if (asprintf(&epgfile,"%s/epg.db",VideoDirectory)==-1) {}; + if (asprintf(&imgdir,"%s","/var/cache/vdr/epgimages")==-1) {}; + if (access(imgdir,R_OK|W_OK)==-1) + { + free(imgdir); + imgdir=NULL; + } + + if (setlocale(LC_CTYPE,"")) + codeset=strdup(nl_langinfo(CODESET)); + else + { + char *LangEnv=getenv("LANG"); + if (LangEnv) + { + codeset=strdup(strchr(LangEnv,'.')); + if (codeset) + codeset++; // skip dot + } + } + if (!codeset) + { + codeset=strdup("ASCII//TRANSLIT"); + } + + struct passwd pwd,*pwdbuf; + char buf[1024]; + getpwuid_r(getuid(),&pwd,buf,sizeof(buf),&pwdbuf); + if (pwdbuf) + { + if (asprintf(&epdir,"%s/.eplists/lists",pwdbuf->pw_dir)!=-1) + { + if (access(epdir,R_OK)) + { + free(epdir); + epdir=NULL; + } + else + { + epcodeset=codeset; + } + } + } +} + +cGlobals::~cGlobals() +{ + free(confdir); + free(epgfile); + free(epdir); + free(imgdir); + free(codeset); + epgsources.Remove(); + epgmappings.Remove(); + textmappings.Remove(); +} + +void cGlobals::SetImgDir(const char* ImgDir) +{ + if (!ImgDir) return; + if (access(ImgDir,R_OK|W_OK)==-1) + { + esyslog("cannot access %s",ImgDir); + return; + } + free(imgdir); + imgdir=strdup(ImgDir); +} + + +void cGlobals::SetEPDir(const char* EPDir) +{ + if (!EPDir) return; + if (access(EPDir,R_OK)==-1) + { + esyslog("cannot access %s",EPDir); + return; + } + free(epdir); + epdir=strdup(EPDir); + if (!epdir) return; + epcodeset=strchr((char *) epdir,','); + if (epcodeset) + { + *epcodeset=0; + } + else + { + epcodeset=(char *) codeset; + } +} + +// ------------------------------------------------------------- + +cEPGHandler::cEPGHandler(cGlobals* Global): import(Global) +{ + epall=0; + maps=Global->EPGMappings(); + sources=Global->EPGSources(); db=NULL; - now=time(NULL); + now=0; } bool cEPGHandler::IgnoreChannel(const cChannel* Channel) @@ -165,15 +268,34 @@ bool cEPGHandler::check4proc(cEvent *event, bool &spth, cEPGMapping **map) return true; } -bool cEPGHandler::SetShortText(cEvent* Event, const char* ShortText) +bool cEPGHandler::SetTitle(cEvent* Event, const char* UNUSED(Title)) { + if (!Event->Title()) return false; // no title? new event! let VDR handle this.. bool seth; if (!check4proc(Event,seth,NULL)) return false; if (import.WasChanged(Event)) { +#ifdef VDRDEBUG // ok we already changed this event! + tsyslog("{%i} %salready seen title '%s'",Event->EventID(),seth ? "*" : "", + Event->Title()); +#endif + return true; + } + return false; +} + + +bool cEPGHandler::SetShortText(cEvent* Event, const char* ShortText) +{ + bool seth; + if (!check4proc(Event,seth,NULL)) return false; + + if (import.WasChanged(Event)) + { #ifdef VDRDEBUG + // ok we already changed this event! tsyslog("{%i} %salready seen stext '%s'",Event->EventID(),seth ? "*" : "", Event->Title()); #endif @@ -200,6 +322,7 @@ bool cEPGHandler::SetDescription(cEvent* Event, const char* Description) // ok we already changed this event! if (!Description) return true; // prevent setting nothing to description int len=strlen(Description); + if (!len) return true; // prevent setting nothing to description if (strncasecmp(Event->Description(),Description,len)) { // eit description changed -> set it @@ -235,7 +358,7 @@ bool cEPGHandler::HandleEvent(cEvent* Event) } else { - // map is always set if seth is not set + // map is always set if seth==false Flags=map->Flags(); } @@ -255,7 +378,9 @@ bool cEPGHandler::HandleEvent(cEvent* Event) } source=sources->GetSource(EITSOURCE); if (!source) tsyslog("no source for %s",EITSOURCE); - xevent=import.AddXMLTVEvent(source,db,ChannelID,Event,Event->Description()); + bool useeptext=((epall & EPLIST_USE_TEXT)==EPLIST_USE_TEXT); + if (useeptext) Flags|=(USE_SHORTTEXT|USE_TITLE); + xevent=import.AddXMLTVEvent(source,db,ChannelID,Event,Event->Description(),useeptext); if (!xevent) { free((void*)ChannelID); @@ -274,7 +399,7 @@ bool cEPGHandler::HandleEvent(cEvent* Event) return false; } - import.PutEvent(source,db,(cSchedule *) Event->Schedule(),Event,xevent,Flags); + import.PutEvent(source,db,NULL,Event,xevent,Flags); delete xevent; return false; // let other handlers change this event } @@ -290,14 +415,14 @@ bool cEPGHandler::SortSchedule(cSchedule* UNUSED(Schedule)) return false; // we dont sort! } - // ------------------------------------------------------------- -cEPGTimer::cEPGTimer(const char *EpgFile, const char *EPDir, const char *CodeSet, cEPGSources *Sources, cEPGMappings *Maps, - cTEXTMappings *Texts) : cThread("xmltv2vdr timer"),import(EpgFile,EPDir,CodeSet,Maps,Texts) +cEPGTimer::cEPGTimer(cGlobals *Global) : + cThread("xmltv2vdr timer"),import(Global) { - sources=Sources; - maps=Maps; + sources=Global->EPGSources(); + maps=Global->EPGMappings(); + epall=0; } void cEPGTimer::Action() @@ -318,22 +443,27 @@ void cEPGTimer::Action() sqlite3 *db=NULL; cEPGSource *source=sources->GetSource(EITSOURCE); + bool useeptext=((epall & EPLIST_USE_TEXT)==EPLIST_USE_TEXT); + int Flags=USE_SEASON; + if (useeptext) Flags|=(USE_SHORTTEXT|USE_TITLE); + bool changed=false; for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) { + if (Timer->Recording()) continue; // to late ;) cEvent *event=(cEvent *) Timer->Event(); if (!event) continue; - if (!event->ShortText()) continue; // no short text -> no episode - if (!strlen(event->ShortText())) continue; // empty short text -> no episode + if (!event->ShortText() && !event->Description()) continue; // no text -> no episode + if (event->ShortText() && event->Description()) + { + if ((strlen(event->ShortText())+strlen(event->Description()))==0) continue; // no text -> no episode + } if (maps->ProcessChannel(event->ChannelID())) continue; // already processed by xmltv2vdr - cChannel *chan=Channels.GetByChannelID(event->ChannelID()); - if (!chan) continue; const char *ChannelID=strdup(*event->ChannelID().ToString()); - 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(),useeptext); if (!xevent) { free((void*)ChannelID); @@ -342,11 +472,7 @@ void cEPGTimer::Action() } free((void*)ChannelID); - cSchedule* schedule = (cSchedule *) schedules->GetSchedule(chan,false); - if (schedule) - { - import.PutEvent(source,db,schedule,event,xevent,USE_SEASON); - } + if (import.PutEvent(source,db,NULL,event,xevent,Flags)) changed=true; delete xevent; } if (db) @@ -355,14 +481,14 @@ void cEPGTimer::Action() sqlite3_close(db); } Timers.DecBeingEdited(); - cSchedules::Cleanup(true); + if (changed) cSchedules::Cleanup(true); } // ------------------------------------------------------------- -cHouseKeeping::cHouseKeeping(const char *EPGFile): cThread("xmltv2vdr housekeeping") +cHouseKeeping::cHouseKeeping(cGlobals *Global): cThread("xmltv2vdr housekeeping") { - epgfile=EPGFile; + epgfile=Global->EPGFile(); } void cHouseKeeping::Action() @@ -400,26 +526,33 @@ void cHouseKeeping::Action() // ------------------------------------------------------------- -cPluginXmltv2vdr::cPluginXmltv2vdr(void) : epgexecutor(&epgsources) +cEPGSeasonEpisode::cEPGSeasonEpisode(cGlobals *Global): cThread("xmltv2vdr seasonepisode") +{ + epgfile=Global->EPGFile(); +} + +void cEPGSeasonEpisode::Action() +{ + // TODO: update season, episode, episodeoverall fields in db +} + +// ------------------------------------------------------------- + +cPluginXmltv2vdr::cPluginXmltv2vdr(void) : housekeeping(&g),epgexecutor(g.EPGSources()) { // Initialize any member variables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! - confdir=NULL; - epgfile=NULL; logfile=NULL; srcorder=NULL; epghandler=NULL; epgtimer=NULL; - epdir=NULL; - housekeeping=NULL; - codeset=NULL; - last_housetime_t=0; + epgseasonepisode=NULL; last_maintime_t=0; - last_epcheck_t=0; + last_timer_t=last_epcheck_t=last_housetime_t=time(NULL); // start this threads later! wakeup=0; insetup=false; - SetEPAll(false); + SetEPAll(0); TEXTMappingAdd(new cTEXTMapping("country",tr("country"))); TEXTMappingAdd(new cTEXTMapping("year",tr("year"))); TEXTMappingAdd(new cTEXTMapping("originaltitle",tr("originaltitle"))); @@ -444,6 +577,7 @@ cPluginXmltv2vdr::cPluginXmltv2vdr(void) : epgexecutor(&epgsources) TEXTMappingAdd(new cTEXTMapping("starrating",tr("starrating"))); TEXTMappingAdd(new cTEXTMapping("season",tr("season"))); TEXTMappingAdd(new cTEXTMapping("episode",tr("episode"))); + TEXTMappingAdd(new cTEXTMapping("episodeoverall",tr("episodeoverall"))); } cPluginXmltv2vdr::~cPluginXmltv2vdr() @@ -457,15 +591,15 @@ cPluginXmltv2vdr::~cPluginXmltv2vdr() int cPluginXmltv2vdr::GetLastImportSource() { sqlite3 *db=NULL; - if (sqlite3_open_v2(epgfile,&db,SQLITE_OPEN_READWRITE,NULL)!=SQLITE_OK) return -1; + if (sqlite3_open_v2(g.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; - + int ret=sqlite3_prepare_v2(db,sql,strlen(sql),&stmt,NULL); if (ret!=SQLITE_OK) { - esyslog("%i %s (glis)",ret,sqlite3_errmsg(db)); + esyslog("%i %s (glis)",ret,sqlite3_errmsg(db)); sqlite3_close(db); return -1; } @@ -481,14 +615,12 @@ int cPluginXmltv2vdr::GetLastImportSource() return idx; } - - bool cPluginXmltv2vdr::EPGSourceMove(int From, int To) { if (From==To) return false; sqlite3 *db=NULL; - if (sqlite3_open_v2(epgfile,&db,SQLITE_OPEN_READWRITE,NULL)==SQLITE_OK) + if (sqlite3_open_v2(g.EPGFile(),&db,SQLITE_OPEN_READWRITE,NULL)==SQLITE_OK) { char *sql=NULL; if (asprintf(&sql,"BEGIN TRANSACTION;" \ @@ -508,8 +640,12 @@ bool cPluginXmltv2vdr::EPGSourceMove(int From, int To) } free(sql); } + else + { + return false; + } sqlite3_close(db); - epgsources.Move(From,To); + g.EPGSources()->Move(From,To); return true; } @@ -518,12 +654,14 @@ const char *cPluginXmltv2vdr::CommandLineHelp(void) { // Return a string that describes all known command line options. return " -e DIR, --episodes=DIR location of episode files: VDRSeriesTimer .episodes\n" - " or TheTVDB .xml (default is ~/.eplists/lists,UTF8)\n" + " or TheTVDB .xml (default is ~/.eplists/lists)\n" " Add UTF-8 or ISO8859-15 to the path to specify the\n" " charset used in the files, e.g. /vdr/myepisodes,UTF8\n" " -E FILE, --epgfile=FILE write the EPG data into the given FILE (default is\n" " 'epg.db' in the video directory) - best performance\n" " if located on a ramdisk\n" + " -i DIR --images=DIR location of epgimages\n" + " (default is /var/cache/vdr/epgimages)\n" " -l FILE --logfile=FILE write trace logs into the given FILE (default is\n" " no trace log\n"; @@ -536,43 +674,27 @@ bool cPluginXmltv2vdr::ProcessArgs(int argc, char *argv[]) { { "episodes", required_argument, NULL, 'e'}, { "epgfile", required_argument, NULL, 'E'}, + { "images", required_argument, NULL, 'i'}, { "logfile", required_argument, NULL, 'l'}, { 0,0,0,0 } }; int c; - char *comma=NULL; - while ((c = getopt_long(argc, argv, "l:e:E:", long_options, NULL)) != -1) + while ((c = getopt_long(argc, argv, "l:e:E:i:", long_options, NULL)) != -1) { switch (c) { case 'e': - if (epdir) free(epdir); - epdir=strdup(optarg); - if (!epdir) break; - comma=strchr(epdir,','); - if (comma) *comma=0; - if (access(epdir,R_OK)!=-1) - { - *comma=','; - } - else - { - free(epdir); - epdir=NULL; - } + g.SetEPDir(optarg); break; case 'E': - if (epgfile) free(epgfile); - epgfile=strdup(optarg); - if (!epgfile) break; -// isyslog("using file '%s' for epgdata",optarg); + g.SetEPGFile(optarg); break; + case 'i': + g.SetImgDir(optarg); case 'l': if (logfile) free(logfile); logfile=strdup(optarg); - if (!logfile) break; -// isyslog("using file '%s' for log",optarg); break; default: return false; @@ -590,73 +712,23 @@ bool cPluginXmltv2vdr::Initialize(void) bool cPluginXmltv2vdr::Start(void) { // Start any background activities the plugin shall perform. - if (confdir) free(confdir); - confdir=strdup(ConfigDirectory(PLUGIN_NAME_I18N)); // creates internally the confdir! - if (!epgfile) - { - if (asprintf(&epgfile,"%s/epg.db",VideoDirectory)==-1)return false; - } - isyslog("using file '%s' for epg database",epgfile); - if (!epdir) - { - struct passwd pwd,*pwdbuf; - char buf[1024]; - getpwuid_r(getuid(),&pwd,buf,sizeof(buf),&pwdbuf); - if (pwdbuf) - { - if (asprintf(&epdir,"%s/.eplists/lists",pwdbuf->pw_dir)!=-1) - { - if (access(epdir,R_OK)) - { - free(epdir); - epdir=NULL; - } - else - { - isyslog("using dir '%s' (UTF-8) for episodes",epdir); - } - } - } - } - else - { - char *cs=strchr(epdir,','); - if (cs) - { - *cs=0; - isyslog("using dir '%s' (%s) for episodes",epdir,cs+1); - *cs=','; - } - else - { - isyslog("using dir '%s' (UTF-8) for episodes",epdir); - } - } - if (setlocale(LC_CTYPE,"")) - codeset=strdup(nl_langinfo(CODESET)); - else - { - char *LangEnv=getenv("LANG"); - if (LangEnv) - { - codeset=strdup(strchr(LangEnv,'.')); - if (codeset) - codeset++; // skip dot - } - } - if (!codeset) + g.SetConfDir(ConfigDirectory(PLUGIN_NAME_I18N)); + + isyslog("using codeset '%s'",g.Codeset()); + isyslog("using file '%s' for epg database",g.EPGFile()); + if (g.EPDir()) { - codeset=strdup("US-ASCII//TRANSLIT"); + isyslog("using dir '%s' (%s) for episodes",g.EPDir(),g.EPCodeset()); + epgtimer = new cEPGTimer(&g); + epgseasonepisode = new cEPGSeasonEpisode(&g); } - isyslog("codeset is '%s'",codeset); + if (g.ImgDir()) isyslog("using dir '%s' for epgimages",g.ImgDir()); ReadInEPGSources(); - epghandler = new cEPGHandler(epgfile,epdir,codeset,&epgsources,&epgmappings,&textmappings); - epgtimer = new cEPGTimer(epgfile,epdir,codeset,&epgsources,&epgmappings,&textmappings); - housekeeping = new cHouseKeeping(epgfile); - + epghandler = new cEPGHandler(&g); if (sqlite3_threadsafe()==0) esyslog("sqlite3 not threadsafe!"); cParse::InitLibXML(); + SetEPAll(epall); return true; } @@ -664,37 +736,21 @@ void cPluginXmltv2vdr::Stop(void) { // Stop any background activities the plugin is performing. cSchedules::Cleanup(true); - epgtimer->Stop(); if (epgtimer) { + epgtimer->Stop(); delete epgtimer; epgtimer=NULL; } - if (housekeeping) + if (epgseasonepisode) { - delete housekeeping; - housekeeping=NULL; + epgseasonepisode->Stop(); + delete epgseasonepisode; + epgseasonepisode=NULL; } epgexecutor.Stop(); - epgsources.Remove(); - epgmappings.Remove(); - textmappings.Remove(); + housekeeping.Stop(); cParse::CleanupLibXML(); - if (confdir) - { - free(confdir); - confdir=NULL; - } - if (epgfile) - { - free(epgfile); - epgfile=NULL; - } - if (epdir) - { - free(epdir); - epdir=NULL; - } if (logfile) { free(logfile); @@ -705,11 +761,6 @@ void cPluginXmltv2vdr::Stop(void) free(srcorder); srcorder=NULL; } - if (codeset) - { - free(codeset); - codeset=NULL; - } } void cPluginXmltv2vdr::Housekeeping(void) @@ -718,14 +769,14 @@ void cPluginXmltv2vdr::Housekeeping(void) time_t now=time(NULL); if (now>(last_housetime_t+3600)) { - if (housekeeping) + if (!housekeeping.Active()) { struct stat statbuf; - if (stat(epgfile,&statbuf)!=-1) + if (stat(g.EPGFile(),&statbuf)!=-1) { if (statbuf.st_size) { - housekeeping->Start(); + housekeeping.Start(); } } } @@ -742,16 +793,26 @@ void cPluginXmltv2vdr::MainThreadHook(void) { if (!epgexecutor.Active()) { - if (epgsources.RunItNow()) epgexecutor.Start(); + if (g.EPGSources()->RunItNow()) epgexecutor.Start(); } last_maintime_t=(now/60)*60; } - if (epall) + if (g.EPDir()) { - if (now>=(last_epcheck_t+600)) + /* + if (now>=(last_epcheck_t+900)) + { + if (epgseasonepisode) epgseasonepisode->Start(); + last_epcheck_t=(now/900)*900; + } + */ + if (epall) { - epgtimer->Start(); - last_epcheck_t=(now/600)*600; + if (now>=(last_timer_t+600)) + { + if (epgtimer) epgtimer->Start(); + last_timer_t=(now/600)*600; + } } } } @@ -770,7 +831,7 @@ time_t cPluginXmltv2vdr::WakeupTime(void) { // Return custom wakeup time for shutdown script if (!wakeup) return (time_t) 0; - time_t nextruntime=epgsources.NextRunTime(); + time_t nextruntime=g.EPGSources()->NextRunTime(); if (nextruntime) nextruntime-=(time_t) 180; tsyslog("reporting wakeuptime %s",ctime(&nextruntime)); return nextruntime; @@ -800,7 +861,7 @@ bool cPluginXmltv2vdr::SetupParse(const char *Name, const char *Value) if (!strncasecmp(Name,"channel",7)) { if (strlen(Name)<10) return false; - epgmappings.Add(new cEPGMapping(&Name[8],Value)); + g.EPGMappings()->Add(new cEPGMapping(&Name[8],Value)); } else if (!strncasecmp(Name,"textmap",7)) { @@ -812,12 +873,12 @@ bool cPluginXmltv2vdr::SetupParse(const char *Name, const char *Value) } else { - textmappings.Add(new cTEXTMapping(&Name[8],Value)); + g.TEXTMappings()->Add(new cTEXTMapping(&Name[8],Value)); } } else if (!strcasecmp(Name,"options.epall")) { - SetEPAll((bool) atoi(Value)); + epall=atoi(Value); // set value later again in Start() } else if (!strcasecmp(Name,"options.wakeup")) { @@ -843,7 +904,9 @@ const char **cPluginXmltv2vdr::SVDRPHelpPages(void) static const char *HelpPages[]= { "UPDT [force]\n" - " Start epg update from db, with force download data before", + " Start epg update from db, with force download data before\n", + "DELD\n" + " Delete xmltv2vdr epg database (triggers update)\n", NULL }; return HelpPages; @@ -856,7 +919,7 @@ cString cPluginXmltv2vdr::SVDRPCommand(const char *Command, const char *Option, cString output; if (!strcasecmp(Command,"UPDT")) { - if (!epgsources.Count()) + if (!g.EPGSources()->Count()) { ReplyCode=550; output="No epg sources installed\n"; @@ -892,9 +955,31 @@ cString cPluginXmltv2vdr::SVDRPCommand(const char *Command, const char *Option, } } else - { - return NULL; - } + if (!strcasecmp(Command,"DELD")) + { + if (g.EPGFile()) + { + if (unlink(g.EPGFile())==-1) + { + ReplyCode=550; + output="failed to delete database\n"; + } + else + { + ReplyCode=250; + output="database deleted\n"; + } + } + else + { + ReplyCode=550; + output="epgfile parameter not set\n"; + } + } + else + { + return NULL; + } return output; } diff --git a/xmltv2vdr.h b/xmltv2vdr.h index 30b6354..e06c37b 100644 --- a/xmltv2vdr.h +++ b/xmltv2vdr.h @@ -21,11 +21,77 @@ #define UNUSED(x) x #endif -static const char *VERSION = "0.1.1pre"; +static const char *VERSION = "0.1.1"; static const char *DESCRIPTION = trNOOP("Imports xmltv epg into vdr"); int ioprio_set(int which, int who, int ioprio); +class cGlobals +{ +private: + char *confdir; + char *epgfile; + char *epdir; + char *epcodeset; + char *imgdir; + char *codeset; + cEPGMappings epgmappings; + cTEXTMappings textmappings; + cEPGSources epgsources; +public: + + cGlobals(); + ~cGlobals(); + cEPGMappings *EPGMappings() + { + return &epgmappings; + } + cTEXTMappings *TEXTMappings() + { + return &textmappings; + } + cEPGSources *EPGSources() + { + return &epgsources; + } + void SetConfDir(const char *ConfDir) + { + free(confdir); + confdir=strdup(ConfDir); + } + const char *ConfDir() + { + return confdir; + } + void SetEPGFile(const char *EPGFile) + { + free(epgfile); + epgfile=strdup(EPGFile); + } + const char *EPGFile() + { + return epgfile; + } + void SetEPDir(const char *EPDir); + const char *EPDir() + { + return epdir; + } + const char *EPCodeset() + { + return epcodeset; + } + const char *Codeset() + { + return codeset; + } + void SetImgDir(const char *ImgDir); + const char *ImgDir() + { + return imgdir; + } +}; + #if VDRVERSNUM < 10726 && !EPGHANDLER class cEpgHandler : public cListObject { @@ -36,6 +102,10 @@ public: { return false; } + virtual bool SetTitle(cEvent *UNUSED(Event), const char *UNUSED(Title)) + { + return false; + } virtual bool SetShortText(cEvent *UNUSED(Event),const char *UNUSED(ShortText)) { return false; @@ -65,14 +135,13 @@ private: cEPGMappings *maps; cEPGSources *sources; cImport import; - bool epall; + int epall; sqlite3 *db; time_t now; bool check4proc(cEvent *event, bool &spth, cEPGMapping **map); public: - cEPGHandler(const char *EpgFile, const char *EPDir, const char *CodeSet, - cEPGSources *Sources, cEPGMappings *Maps, cTEXTMappings *Texts); - void SetEPAll(bool Value) + cEPGHandler(cGlobals *Global); + void SetEPAll(int Value) { epall=Value; } @@ -81,6 +150,7 @@ public: return (db!=NULL); } virtual bool IgnoreChannel(const cChannel *Channel); + virtual bool SetTitle(cEvent *Event,const char *Title); virtual bool SetShortText(cEvent *Event,const char *ShortText); virtual bool SetDescription(cEvent *Event,const char *Description); virtual bool HandleEvent(cEvent *Event); @@ -93,13 +163,26 @@ private: cEPGSources *sources; cEPGMappings *maps; cImport import; + int epall; public: - cEPGTimer(const char *EpgFile, const char *EPDir, const char *CodeSet, - cEPGSources *Sources, cEPGMappings *Maps,cTEXTMappings *Texts); - bool StillRunning() + cEPGTimer(cGlobals *Global); + void Stop() { - return Running(); + Cancel(3); } + void SetEPAll(int Value) + { + epall=Value; + } + virtual void Action(); +}; + +class cHouseKeeping : public cThread +{ +private: + const char *epgfile; +public: + cHouseKeeping(cGlobals *Global); void Stop() { Cancel(3); @@ -107,34 +190,34 @@ public: virtual void Action(); }; -class cHouseKeeping : public cThread +class cEPGSeasonEpisode : public cThread { private: const char *epgfile; public: - cHouseKeeping(const char *EPGFile); + cEPGSeasonEpisode(cGlobals *Global); + void Stop() + { + Cancel(3); + } virtual void Action(); }; class cPluginXmltv2vdr : public cPlugin { private: + cGlobals g; cEPGHandler *epghandler; cEPGTimer *epgtimer; - cHouseKeeping *housekeeping; + cEPGSeasonEpisode *epgseasonepisode; + cHouseKeeping housekeeping; cEPGExecutor epgexecutor; - cEPGMappings epgmappings; - cEPGSources epgsources; - cTEXTMappings textmappings; time_t last_housetime_t; time_t last_maintime_t; + time_t last_timer_t; time_t last_epcheck_t; - char *confdir; - char *epgfile; - char *epdir; - char *codeset; char *srcorder; - bool epall; + int epall; bool wakeup; bool insetup; int GetLastImportSource(); @@ -143,12 +226,13 @@ public: { insetup=Value; } - void SetEPAll(bool Value) + void SetEPAll(int Value) { epall=Value; if (epghandler) epghandler->SetEPAll(Value); + if (epgtimer) epgtimer->SetEPAll(Value); } - bool EPAll() + int EPAll() { return epall; } @@ -162,46 +246,45 @@ public: } const char *EPDir() { - return epdir; + return g.EPDir(); } void ReadInEPGSources(bool Reload=false) { - epgsources.ReadIn(confdir,epgfile,epdir,codeset,&epgmappings, - &textmappings,srcorder,Reload); + g.EPGSources()->ReadIn(&g,srcorder,Reload); } bool EPGSourceMove(int From, int To); int EPGSourceCount() { - if (!epgsources.Count()) return 0; - return epgsources.Count()-1; + if (!g.EPGSources()->Count()) return 0; + return g.EPGSources()->Count()-1; } cEPGSource *EPGSource(int Index) { - return epgsources.Get(Index); + return g.EPGSources()->Get(Index); } int EPGMappingCount() { - return epgmappings.Count(); + return g.EPGMappings()->Count(); } cEPGMapping *EPGMapping(int Index) { - return epgmappings.Get(Index); + return g.EPGMappings()->Get(Index); } cEPGMapping *EPGMapping(const char *ChannelName) { - return epgmappings.GetMap(ChannelName); + return g.EPGMappings()->GetMap(ChannelName); } void EPGMappingAdd(cEPGMapping *Map) { - epgmappings.Add(Map); + g.EPGMappings()->Add(Map); } cTEXTMapping *TEXTMapping(const char *Name) { - return textmappings.GetMap(Name); + return g.TEXTMappings()->GetMap(Name); } void TEXTMappingAdd(cTEXTMapping *TextMap) { - textmappings.Add(TextMap); + g.TEXTMappings()->Add(TextMap); } cPluginXmltv2vdr(void); virtual ~cPluginXmltv2vdr(); |