diff options
author | Jochen Dolze <vdr@dolze.de> | 2012-07-14 17:39:18 +0200 |
---|---|---|
committer | Jochen Dolze <vdr@dolze.de> | 2012-07-14 17:39:18 +0200 |
commit | 296d7f6785053232c21c747138c2673be19ac6bd (patch) | |
tree | 40c8364e7a8687c1a9884209d5bf999ff2cc4e86 | |
parent | ade2efec3a2e857e56dfcd42b0068d1de3bcfae7 (diff) | |
download | vdr-plugin-xmltv2vdr-296d7f6785053232c21c747138c2673be19ac6bd.tar.gz vdr-plugin-xmltv2vdr-296d7f6785053232c21c747138c2673be19ac6bd.tar.bz2 |
Fixed bug which prevents some events to get updates
Added better handling of two titles
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | event.cpp | 50 | ||||
-rw-r--r-- | event.h | 12 | ||||
-rw-r--r-- | import.cpp | 282 | ||||
-rw-r--r-- | import.h | 12 | ||||
-rw-r--r-- | maps.h | 6 | ||||
-rw-r--r-- | parse.cpp | 99 | ||||
-rw-r--r-- | po/de_DE.po | 8 | ||||
-rw-r--r-- | po/it_IT.po | 5 | ||||
-rw-r--r-- | setup.cpp | 4 | ||||
-rw-r--r-- | soundex.cpp | 483 | ||||
-rw-r--r-- | xmltv2vdr.cpp | 26 |
12 files changed, 751 insertions, 238 deletions
@@ -58,7 +58,7 @@ LIBS += $(shell $(PKG-CONFIG) --libs $(PKG-LIBS)) ### The object files (add further files here): -OBJS = $(PLUGIN).o extpipe.o parse.o source.o import.o event.o setup.o maps.o +OBJS = $(PLUGIN).o soundex.o extpipe.o parse.o source.o import.o event.o setup.o maps.o ### The main target: @@ -79,19 +79,7 @@ void cXMLTVEvent::SetChannelID(const char *ChannelID) void cXMLTVEvent::SetTitle(const char *Title) { - if (title) - { - if (strncasecmp(Title,title,3)) - { - title=strcatrealloc(title,"|"); - title=strcatrealloc(title,Title); - } - } - else - { - title=strcpyrealloc(title, Title); - } - + title=strcpyrealloc(title, Title); if (title) { title=removechar(title,'\''); @@ -101,22 +89,16 @@ void cXMLTVEvent::SetTitle(const char *Title) } } -const char *cXMLTVEvent::Title(bool Second) +void cXMLTVEvent::SetAltTitle(const char *AltTitle) { - char *p=strchr(title,'|'); - if (!p && Second) return NULL; - if (!p) return title; - - if (!Second) + alttitle=strcpyrealloc(alttitle, AltTitle); + if (alttitle) { - return p++; + alttitle=removechar(alttitle,'\''); + alttitle=removechar(alttitle,'\n'); + alttitle=removechar(alttitle,'\r'); + alttitle=compactspace(alttitle); } - if (title2) free(title2); - title2=strdup(title); - if (!title2) return NULL; - p=strchr(title2,'|'); - if (p) *p=0; - return title2; } void cXMLTVEvent::SetOrigTitle(const char *OrigTitle) @@ -500,13 +482,14 @@ void cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *ChannelID, if (asprintf(&sql_insert, "INSERT OR FAIL INTO epg (src,channelid,eventid,starttime,duration,"\ - "title,origtitle,shorttext,description,country,year,credits,category,"\ + "title,alttitle,origtitle,shorttext,description,country,year,credits,category,"\ "review,rating,starrating,video,audio,season,episode,episodeoverall,pics,srcidx) "\ "VALUES (^%s^,^%s^,%u,%li,%i,"\ - "^%s^,^%s^,^%s^,^%s^,^%s^,%i,^%s^,^%s^,"\ + "^%s^,^%s^,^%s^,^%s^,^%s^,^%s^,%i,^%s^,^%s^,"\ "^%s^,^%s^,^%s^,^%s^,^%s^,%i,%i,%i,^%s^,%i);" , Source,ChannelID,eventid,starttime,duration,title, + alttitle ? alttitle : "NULL", origtitle ? origtitle : "NULL", shorttext ? shorttext : "NULL", description ? description : "NULL", @@ -522,13 +505,14 @@ void cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *ChannelID, } if (asprintf(&sql_update, - "UPDATE epg SET duration=%i,starttime=%li,title=^%s^,origtitle=^%s^,"\ + "UPDATE epg SET duration=%i,starttime=%li,title=^%s^,alttitle=^%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, "\ "episodeoverall=%i,pics=^%s^,srcidx=%i " \ " where src=^%s^ and channelid=^%s^ and eventid=%u" , duration,starttime,title, + alttitle ? alttitle : "NULL", origtitle ? origtitle : "NULL", shorttext ? shorttext : "NULL", description ? description : "NULL", @@ -591,10 +575,10 @@ void cXMLTVEvent::Clear() free(title); title=NULL; } - if (title2) + if (alttitle) { - free(title2); - title2=NULL; + free(alttitle); + alttitle=NULL; } if (shorttext) { @@ -657,7 +641,7 @@ cXMLTVEvent::cXMLTVEvent() source=NULL; channelid=NULL; title=NULL; - title2=NULL; + alttitle=NULL; shorttext=NULL; description=eitdescription=NULL; country=NULL; @@ -33,7 +33,7 @@ class cXMLTVEvent { private: char *title; - char *title2; + char *alttitle; char *shorttext; char *description; char *eitdescription; @@ -70,6 +70,7 @@ public: void SetSource(const char *Source); void SetChannelID(const char *ChannelID); void SetTitle(const char *Title); + void SetAltTitle(const char *AltTitle); void SetOrigTitle(const char *OrigTitle); void SetShortText(const char *ShortText); void SetDescription(const char *Description); @@ -181,7 +182,14 @@ public: { return source; } - const char *Title(bool Second=false); + const char *Title(void) const + { + return title; + } + const char *AltTitle(void) const + { + return alttitle; + } const char *ShortText(void) const { return shorttext; @@ -79,63 +79,33 @@ char *cImport::RemoveNonASCII(const char *src) return dst; } -cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVEvent *xevent, bool append, int hint) +cEvent *cImport::SearchVDREventByTitle(cEPGSource *source, cSchedule* schedule, const char *Title, time_t StartTime, + int Duration, int hint) { - if (!source) return NULL; - if (!schedule) return NULL; - if (!xevent) return NULL; - - cEvent *f=NULL; - - // try to find an event, - // 1st with our own EventID - if (xevent->EITEventID()) f=(cEvent *) schedule->GetEvent(xevent->EITEventID()); - if (f) - { - return f; - } - - if (xevent->EventID() && append) f=(cEvent *) schedule->GetEvent(xevent->EventID()); - if (f) - { - return f; - } - - char *cxTitle1=strdup(conv->Convert(xevent->Title())); - char *cxTitle2=NULL; - if (xevent->Title(true)) cxTitle2=strdup(conv->Convert(xevent->Title(true))); + const char *cxTitle=conv->Convert(Title); // 2nd with StartTime - f=(cEvent *) schedule->GetEvent((tEventID) 0,xevent->StartTime()+hint); + cEvent *f=(cEvent *) schedule->GetEvent((tEventID) 0,StartTime+hint); if (f) { - if (!strcasecmp(f->Title(),cxTitle1)) + if (!strcasecmp(f->Title(),cxTitle)) { - free((void *) cxTitle1); - if (cxTitle2) free((void *) cxTitle2); return f; } - if (cxTitle2 && (!strcasecmp(f->Title(),cxTitle2))) - { - free((void *) cxTitle1); - free((void *) cxTitle2); - return f; - } - } // 3rd with StartTime +/- TimeDiff int maxdiff=INT_MAX; int eventTimeDiff=720; - if (xevent->Duration() && eventTimeDiff>=xevent->Duration()) eventTimeDiff/=3; + if (Duration && eventTimeDiff>=Duration) eventTimeDiff/=3; if (eventTimeDiff<100) eventTimeDiff=100; for (cEvent *p = schedule->Events()->First(); p; p = schedule->Events()->Next(p)) { - int diff=abs((int) difftime(p->StartTime(),xevent->StartTime())); + int diff=abs((int) difftime(p->StartTime(),StartTime)); if (diff<=eventTimeDiff) { // found event with exact the same title - if (!strcasecmp(p->Title(),cxTitle1) || (cxTitle2 && !strcasecmp(p->Title(),cxTitle2))) + if (!strcasecmp(p->Title(),cxTitle)) { if (diff<=maxdiff) { @@ -155,7 +125,7 @@ cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVE // 0x20,0x30-0x39,0x41-0x5A,0x61-0x7A int wfound=0; char *s1=RemoveNonASCII(p->Title()); - char *s2=RemoveNonASCII(cxTitle1); + char *s2=RemoveNonASCII(cxTitle); if (s1 && s2) { if (!strcmp(s1,s2)) @@ -181,38 +151,8 @@ cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVE } } } - - char *s3=NULL; - if (cxTitle2) s3=RemoveNonASCII(cxTitle2); - if (s1 && s3 && !wfound) - { - if (!strcmp(s1,s3)) - { - wfound++; - } - else - { - struct split w1 = split(s1,' '); - struct split w3 = split(s3,' '); - if ((w1.count) && (w3.count)) - { - for (int i1=0; i1<w1.count; i1++) - { - for (int i3=0; i3<w3.count; i3++) - { - if (!strcmp(w1.pointers[i1],w3.pointers[i3])) - { - if (strlen(w1.pointers[i1])>3) wfound++; - } - } - } - } - } - } - if (s1) free(s1); if (s2) free(s2); - if (s3) free(s3); if (wfound) { @@ -220,14 +160,7 @@ cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVE { if (!WasChanged(p)) { - if (cxTitle2) - { - tsyslogs(source,"found '%s' for '%s' or '%s'",p->Title(),cxTitle1,cxTitle2); - } - else - { - tsyslogs(source,"found '%s' for '%s'",p->Title(),cxTitle1); - } + tsyslogs(source,"found '%s' for '%s'",p->Title(),cxTitle); } f=p; maxdiff=diff; @@ -237,12 +170,35 @@ cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVE } } - free((void *) cxTitle1); - if (cxTitle2) free((void *) cxTitle2); - return f; } +cEvent *cImport::SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVEvent *xevent, bool append, int hint) +{ + if (!source) return NULL; + if (!schedule) return NULL; + if (!xevent) return NULL; + + cEvent *f=NULL; + + // try to find an event, + // 1st with our own EventID + if (xevent->EITEventID()) f=(cEvent *) schedule->GetEvent(xevent->EITEventID()); + if (f) return f; + + if (xevent->EventID() && append) f=(cEvent *) schedule->GetEvent(xevent->EventID()); + if (f) return f; + + f=SearchVDREventByTitle(source, schedule, xevent->Title(), xevent->StartTime(), + xevent->Duration(), hint); + if (f) return f; + + if (!xevent->AltTitle()) return NULL; + + return SearchVDREventByTitle(source, schedule, xevent->AltTitle(), xevent->StartTime(), + xevent->Duration(), hint); +} + cEvent *cImport::GetEventBefore(cSchedule* schedule, time_t start) { if (!schedule) return NULL; @@ -312,13 +268,13 @@ char *cImport::AddEOT2Description(char *description, bool checkutf8) } else { - if (strncasecmp(g->Codeset(),"UTF-8",5) || strncasecmp(g->Codeset(),"UTF8",4)) + if (!strncasecmp(g->Codeset(),"UTF-8",5) || !strncasecmp(g->Codeset(),"UTF8",4)) { - description=strcatrealloc(description,nbsp); + description=strcatrealloc(description,nbspUTF8); } else { - description=strcatrealloc(description,nbspUTF8); + description=strcatrealloc(description,nbsp); } } } @@ -334,6 +290,13 @@ bool cImport::WasChanged(cEvent* Event) if (!Event) return false; if (!Event->Description()) return false; if (!strchr(Event->Description(),0xA0)) return false; + char *p=strchr((char *) Event->Description(),0xA0); + if (!p) return false; + if (!g->Codeset()) return false; + if (!strncasecmp(g->Codeset(),"UTF-8",5) || !strncasecmp(g->Codeset(),"UTF8",4)) + { + if ((unsigned char) p[-1]!=0xC2) return false; + } return true; } @@ -780,6 +743,11 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, bool retcode=false; bool added=false; + if (xEvent->EventID()==65234425) + { + dsyslog("!!!"); + } + if ((Flags & OPT_APPEND)==OPT_APPEND) append=true; if (append && !Event) @@ -921,26 +889,11 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, if (!Event) return false; - if (!append) + if ((Flags & OPT_SEASON_STEXTITLE)==OPT_SEASON_STEXTITLE) { - const char *eitdescription=Event->Description(); - if (WasChanged(Event)) eitdescription=NULL; // we cannot use Event->Description() - it is already changed! - if (!xEvent->EITEventID() || eitdescription) + if (xEvent->AltTitle() && (strlen(xEvent->AltTitle())>0)) { - if (!xEvent->EITEventID() && xEvent->Pics()->Size() && Source->UsePics()) - { - /* here's a good place to link pictures! */ - LinkPictures(xEvent->Source(),xEvent->Pics(),Event->EventID(),Event->ChannelID()); - } - UpdateXMLTVEvent(Source,Db,Event,xEvent,eitdescription); - } - } - - if ((Flags & USE_TITLE)==USE_TITLE) - { - if (xEvent->Title() && (strlen(xEvent->Title())>0)) - { - const char *dp=conv->Convert(xEvent->Title()); + const char *dp=conv->Convert(xEvent->AltTitle()); if (!Event->Title() || strcmp(Event->Title(),dp)) { Event->SetTitle(dp); @@ -970,6 +923,25 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, } } + if (!append) + { + const char *eitdescription=Event->Description(); + if (WasChanged(Event)) + { + eitdescription=NULL; // we cannot use Event->Description() - it was already changed! + if (!xEvent->EITDescription()) return false; // no eitdescription in db? -> cannot mix! + } + 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(),Event->ChannelID()); + } + UpdateXMLTVEvent(Source,Db,Event,xEvent,eitdescription); + } + } + char *description=NULL; const char *ot=g->Order(); @@ -1132,30 +1104,49 @@ bool cImport::FetchXMLTVEvent(sqlite3_stmt *stmt, cXMLTVEvent *xevent) case 20: xevent->SetPics((const char *) sqlite3_column_text(stmt,col)); break; - case 21: // source + case 21: xevent->SetSource((const char *) sqlite3_column_text(stmt,col)); break; - case 22: // eiteventid + case 22: xevent->SetEITEventID(sqlite3_column_int(stmt,col)); break; - case 23: // eitdescription + case 23: xevent->SetEITDescription((const char *) sqlite3_column_text(stmt,col)); break; + case 24: + xevent->SetAltTitle((const char *) sqlite3_column_text(stmt,col)); + break; } } return true; } -cXMLTVEvent *cImport::PrepareAndReturn(sqlite3 *db, char *sql) +cXMLTVEvent *cImport::PrepareAndReturn(sqlite3 **db, char *sql) { if (!db) return NULL; + if (!*db) return NULL; if (!sql) return NULL; sqlite3_stmt *stmt=NULL; - int ret=sqlite3_prepare_v2(db,sql,strlen(sql),&stmt,NULL); + int ret=sqlite3_prepare_v2(*db,sql,strlen(sql),&stmt,NULL); if (ret!=SQLITE_OK) { - esyslog("%i %s (par)",ret,sqlite3_errmsg(db)); + const char *errmsg=sqlite3_errmsg(*db); + if (errmsg) + { + if (strstr(errmsg,"no such column")) + { + esyslog("sqlite3: database schema changed, unlinking epg.db!"); + sqlite3_close(*db); + *db=NULL; + unlink(g->EPGFile()); + } + else + { + esyslog("sqlite3: %i %s (par)",ret,errmsg); + tsyslog("sqlite3: %s",sql); + } + } free(sql); return NULL; } @@ -1171,6 +1162,26 @@ cXMLTVEvent *cImport::PrepareAndReturn(sqlite3 *db, char *sql) return xevent; } +void cImport::AddShortTextFromEITDescription(cXMLTVEvent *xEvent, const char *EITDescription) +{ + if (!g->EPDir()) return; + int season,episode,episodeoverall; + char *epshorttext=NULL; + if (!cParse::FetchSeasonEpisode(cep2ascii,cutf2ascii,g->EPDir(),xEvent->Title(), + NULL,EITDescription, + season,episode,episodeoverall,&epshorttext, + NULL)) return; + + if (epshorttext) + { + xEvent->SetShortText(epshorttext); + free(epshorttext); + } + xEvent->SetSeason(season); + xEvent->SetEpisode(episode); + xEvent->SetEpisodeOverall(episodeoverall); +} + cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char *ChannelID, const cEvent *Event, const char *EITDescription, bool UseEPText) { @@ -1190,28 +1201,38 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * #ifdef VDRDEBUG tsyslogs(Source,"no season/episode found for '%s'/'%s'",Event->Title(),Event->ShortText()); #endif - return NULL; + if (!eptitle) + { + if (epshorttext) free(epshorttext); + return NULL; + } + if (!UseEPText) + { + if (epshorttext) free(epshorttext); + if (eptitle) free(eptitle); + return NULL; + } } cXMLTVEvent *xevent = new cXMLTVEvent(); if (!xevent) { esyslogs(Source,"out of memory"); - free(epshorttext); - free(eptitle); + if (epshorttext) free(epshorttext); + if (eptitle) free(eptitle); return NULL; } if (UseEPText) { - if (eptitle) xevent->SetTitle(eptitle); + if (eptitle) xevent->SetAltTitle(eptitle); if (epshorttext) xevent->SetShortText(epshorttext); } else { - xevent->SetTitle(Event->Title()); xevent->SetShortText(Event->ShortText()); } + xevent->SetTitle(Event->Title()); xevent->SetStartTime(Event->StartTime()); xevent->SetDuration(Event->Duration()); xevent->SetEventID(Event->EventID()); @@ -1224,7 +1245,8 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * xevent->SetSeason(season); xevent->SetEpisode(episode); xevent->SetEpisodeOverall(episodeoverall); - free(epshorttext); + if (epshorttext) free(epshorttext); + if (eptitle) free(eptitle); if (!Begin(Source,Db)) { @@ -1382,7 +1404,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," \ - "episodeoverall,pics,src,eiteventid,eitdescription,abs(starttime-%li) as diff from epg where " \ + "episodeoverall,pics,src,eiteventid,eitdescription,alttitle,abs(starttime-%li) as diff from epg where " \ " (starttime>=%li and starttime<=%li) and eiteventid=%u and channelid='%s' " \ " order by diff,srcidx asc limit 1;",Event->StartTime(),Event->StartTime()-eventTimeDiff, Event->StartTime()+eventTimeDiff,Event->EventID(),ChannelID)==-1) @@ -1391,44 +1413,28 @@ cXMLTVEvent *cImport::SearchXMLTVEvent(sqlite3 **Db,const char *ChannelID, const return NULL; } - xevent=PrepareAndReturn(*Db,sql); + xevent=PrepareAndReturn(Db,sql); if (xevent) return xevent; - char *sqltitle=strdup(Event->Title()); - if (!sqltitle) + char wstr[128]; + if (SoundEx((char *) &wstr,(char *) Event->Title(),0,1)==0) { - esyslog("out of memory"); + esyslog("soundex of '%s' failed",Event->Title()); return NULL; } - string st=sqltitle; - - int reps; - reps=pcrecpp::RE("'").GlobalReplace("''",&st); - if (reps) - { - char *tmp_sqltitle=(char *) realloc(sqltitle,st.size()+1); - if (tmp_sqltitle) - { - sqltitle=tmp_sqltitle; - strcpy(sqltitle,st.c_str()); - } - } - if (asprintf(&sql,"select channelid,eventid,starttime,duration,title,origtitle,shorttext,description," \ "country,year,credits,category,review,rating,starrating,video,audio,season,episode," \ - "episodeoverall,pics,src,eiteventid,eitdescription,abs(starttime-%li) as diff from epg where " \ - " (starttime>=%li and starttime<=%li) and title='%s' and channelid='%s' " \ + "episodeoverall,pics,src,eiteventid,eitdescription,alttitle,abs(starttime-%li) as diff from epg where " \ + " (starttime>=%li and starttime<=%li) and soundex(title)='%s' and channelid='%s' " \ " order by diff,srcidx asc limit 1;",Event->StartTime(),Event->StartTime()-eventTimeDiff, - Event->StartTime()+eventTimeDiff,sqltitle,ChannelID)==-1) + Event->StartTime()+eventTimeDiff,wstr,ChannelID)==-1) { - free(sqltitle); esyslog("out of memory"); return NULL; } - free(sqltitle); - xevent=PrepareAndReturn(*Db,sql); + xevent=PrepareAndReturn(Db,sql); if (xevent) return xevent; return NULL; @@ -47,19 +47,22 @@ private: char *Add2Description(char *description, const char *value); char *Add2Description(char *description, const char *name, const char *value); char *Add2Description(char *description, const char *name, int value); - char *Add2Description(char *description, cXMLTVEvent *xEvent, int Flags, int what); + char *Add2Description(char *description, cXMLTVEvent *xEvent, int Flags, int what); char *AddEOT2Description(char *description, bool checkutf8=false); struct split split(char *in, char delim); cEvent *GetEventBefore(cSchedule* schedule, time_t start); cEvent *SearchVDREvent(cEPGSource *source, cSchedule* schedule, cXMLTVEvent *event, bool append, int hint); + cEvent *SearchVDREventByTitle(cEPGSource *source, cSchedule* schedule, const char *Title, time_t StartTime, + int Duration, int hint); bool FetchXMLTVEvent(sqlite3_stmt *stmt, cXMLTVEvent *xevent); char *RemoveNonASCII(const char *src); - cXMLTVEvent *PrepareAndReturn(sqlite3 *db, char *sql); + cXMLTVEvent *PrepareAndReturn(sqlite3 **db, char *sql); + int SoundEx(char *SoundEx,char *WordString,int LengthOption,int CensusOption); public: cImport(cGlobals *Global); ~cImport(); - void LinkPictures(const char *Source, cXMLTVStringList *Pics, tEventID DestID, - tChannelID ChanID, bool MakeOld=true); + void LinkPictures(const char *Source, cXMLTVStringList *Pics, tEventID DestID, + tChannelID ChanID, bool MakeOld=true); int Process(cEPGSource *Source, cEPGExecutor &myExecutor); bool Begin(cEPGSource *Source, sqlite3 *Db); bool Commit(cEPGSource *Source, sqlite3 *Db); @@ -71,6 +74,7 @@ public: 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, bool UseEPText); + void AddShortTextFromEITDescription(cXMLTVEvent *xEvent, const char *EITDescription); bool WasChanged(cEvent *Event); }; @@ -31,7 +31,7 @@ #define USE_AUDIO 0x200 #define USE_SEASON 0x400 #define USE_STARRATING 0x800 -#define USE_TITLE 0x1000 +//#define USE_TITLE 0x1000 #define CREDITS_ACTORS 0x100000 #define CREDITS_DIRECTORS 0x200000 @@ -40,11 +40,11 @@ #define OPT_RATING_TEXT 0x1000000 #define OPT_CATEGORIES_TEXT 0x2000000 -#define OPT_SEASON_SHORTTEXT 0x4000000 +#define OPT_SEASON_STEXTITLE 0x4000000 #define OPT_APPEND 0x40000000 #define EPLIST_USE_SEASON 0x1 -#define EPLIST_USE_TEXT 0x2 +#define EPLIST_USE_STEXTITLE 0x2 class cTEXTMapping : public cListObject { @@ -135,13 +135,13 @@ void cParse::RemoveNonAlphaNumeric(char *String) pos++; } - // remove leading numbers + // remove leading numbers (inkl. roman numerals) len=strlen(String); p=String; while (*p) { // 0x30 - 0x39 - if ((*p>=0x30) && (*p<=0x39)) + if (((*p>=0x30) && (*p<=0x39)) || *p=='I' || *p=='V') { memmove(p,p+1,len); len--; @@ -163,18 +163,6 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha { // Title and ShortText are always UTF8 ! if (!EPDir) return false; - 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; if (cUTF2ASCII==(iconv_t) -1) return false; @@ -248,6 +236,29 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha if (dname[0]==0) strn0cpy(dname,dirent->d_name,sizeof(dname)-1); + if (EPTitle && strcasecmp(Title,dname)) *EPTitle=strdup(dname); + + if ((!ShortText) && (!Description)) { + fclose(f); + free(epfile); + return false; + } + size_t slen; + if (ShortText) + { + slen=strlen(ShortText); + } + else + { + slen=strlen(Description); + if (slen>40) slen=40; + } + if (!slen) { + fclose(f); + free(epfile); + return false; + } + size_t dlen=4*slen; char *dshorttext=(char *) calloc(dlen,1); if (!dshorttext) @@ -301,7 +312,6 @@ bool cParse::FetchSeasonEpisode(iconv_t cEP2ASCII, iconv_t cUTF2ASCII, const cha { found=true; if (EPShortText) *EPShortText=strdup(epshorttext); - if (EPTitle) *EPTitle=strdup(dname); break; } } @@ -691,6 +701,7 @@ bool cParse::FetchEvent(xmlNodePtr enode, bool useeptext) int season,episode,episodeoverall; char *epshorttext=NULL; char *eptitle=NULL; + if (FetchSeasonEpisode(cep2ascii,cutf2ascii,g->EPDir(),xevent.Title(),xevent.ShortText(), xevent.Description(),season,episode,episodeoverall,&epshorttext, &eptitle)) @@ -698,20 +709,17 @@ bool cParse::FetchEvent(xmlNodePtr enode, bool useeptext) xevent.SetSeason(season); xevent.SetEpisode(episode); xevent.SetEpisodeOverall(episodeoverall); - if (useeptext) + if (epshorttext) { - if (epshorttext) - { - xevent.SetShortText(epshorttext); - free(epshorttext); - } - if (eptitle) - { - xevent.SetTitle(eptitle); - free(eptitle); - } + if (useeptext) xevent.SetShortText(epshorttext); + free(epshorttext); } } + if (eptitle) + { + if (useeptext) xevent.SetAltTitle(eptitle); + free(eptitle); + } return xevent.HasTitle(); } @@ -748,9 +756,9 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) char sql[]="CREATE TABLE IF NOT EXISTS epg (" \ "src nvarchar(100), channelid nvarchar(255), eventid int, eiteventid int, "\ - "starttime datetime, duration int, title nvarchar(255),origtitle nvarchar(255), "\ - "shorttext nvarchar(255), description text, eitdescription text, " \ - "country nvarchar(255), year int, " \ + "starttime datetime, duration int, title nvarchar(255), alttitle nvarchar(255), "\ + "origtitle nvarchar(255), 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, " \ "episodeoverall int, pics text, srcidx int," \ @@ -777,6 +785,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) int lerr=0,lweak=0; xmlChar *lastchannelid=NULL; int skipped=0; + bool do_unlink=false; while (node) { if (node->type!=XML_ELEMENT_NODE) @@ -873,7 +882,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (start) xmlFree(start); if (stop) xmlFree(stop); - if (!FetchEvent(node,(map->Flags() & OPT_SEASON_SHORTTEXT)==OPT_SEASON_SHORTTEXT)) // sets xevent + if (!FetchEvent(node,(map->Flags() & OPT_SEASON_STEXTITLE)==OPT_SEASON_STEXTITLE)) // sets xevent { if (lerr!=PARSE_FETCHERR) esyslogs(source,"failed to fetch event"); @@ -905,26 +914,36 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) int ret=sqlite3_exec(db,isql,NULL,NULL,&errmsg); if (ret!=SQLITE_OK) { + bool update_issued=false; if (ret==SQLITE_CONSTRAINT) { sqlite3_free(errmsg); ret=sqlite3_exec(db,usql,NULL,NULL,&errmsg); + update_issued=true; } if (ret!=SQLITE_OK) { if (lerr!=PARSE_SQLERR) { - if (!xevent.WeakID()) + if (strstr(errmsg,"has no column named")) { - esyslogs(source,"sqlite3: %s (%u@%i)",errmsg,xevent.EventID(),node->line); - tsyslogs(source,"sqlite3: %s",isql); - tsyslogs(source,"sqlite3: %s",usql); + esyslogs(source,"sqlite3: database schema changed, unlinking epg.db!"); + do_unlink=true; } else { - esyslogs(source,"sqlite3: %s ('%s'@%i)",errmsg,xevent.Title(),node->line); - tsyslogs(source,"sqlite3: %s",isql); - tsyslogs(source,"sqlite3: %s",usql); + if (!xevent.WeakID()) + { + esyslogs(source,"sqlite3: %s (%u@%i)",errmsg,xevent.EventID(),node->line); + tsyslogs(source,"sqlite3: %s",isql); + if (update_issued) tsyslogs(source,"sqlite3: %s",usql); + } + else + { + esyslogs(source,"sqlite3: %s ('%s'@%i)",errmsg,xevent.Title(),node->line); + tsyslogs(source,"sqlite3: %s",isql); + if (update_issued) tsyslogs(source,"sqlite3: %s",usql); + } } } lerr=PARSE_SQLERR; @@ -941,6 +960,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) isyslogs(source,"request to stop from vdr"); break; } + if (do_unlink) break; } if (sqlite3_exec(db,"COMMIT",NULL,NULL,&errmsg)!=SQLITE_OK) @@ -951,7 +971,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) int cnt=sqlite3_total_changes(db); - if (skipped) + if ((skipped) && (!do_unlink)) isyslogs(source,"skipped %i xmltv events",skipped); if (!lerr) @@ -972,6 +992,9 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) sqlite3_close(db); xmlFreeDoc(xmltv); + + if (do_unlink) unlink(g->EPGFile()); + return 0; } diff --git a/po/de_DE.po b/po/de_DE.po index 4420931..aa5c7e0 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-06-04 17:24+0200\n" +"POT-Creation-Date: 2012-07-14 17:02+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" @@ -146,7 +146,7 @@ msgid "pin" msgstr "Pin" msgid "download pics" -msgstr "" +msgstr "Bilder herunterladen" msgid "channels provided" msgstr "Verfügbare Kanäle" @@ -196,9 +196,6 @@ msgstr "einzeilig" msgid " rating in description" msgstr " Freigabe im Text" -msgid " add shorttext from list" -msgstr " Kurztext von Liste übernehmen" - msgid "epg source channel mappings" msgstr "EPG Quellkanalzuordnungen" @@ -285,3 +282,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 c11af83..48eb687 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-06-04 17:24+0200\n" +"POT-Creation-Date: 2012-07-14 16:59+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" @@ -199,9 +199,6 @@ msgstr "" msgid " rating in description" msgstr "" -msgid " add shorttext from list" -msgstr "" - msgid "epg source channel mappings" msgstr "Mappature canali sorgente EPG" @@ -90,7 +90,7 @@ void cMenuSetupXmltv2vdr::Output(void) if ((epall & EPLIST_USE_SEASON)==EPLIST_USE_SEASON) { Add(new cMyMenuEditBitItem(tr(" add shorttext/title from list"), - &epall,EPLIST_USE_TEXT),true); + &epall,EPLIST_USE_STEXTITLE),true); } else { @@ -1114,7 +1114,7 @@ void cMenuSetupXmltv2vdrChannelMap::output(void) c4=Current(); if (((flags & USE_SEASON)==USE_SEASON) && (g->EPDir())) { - Add(new cMyMenuEditBitItem(tr(" add shorttext from list"),&flags,OPT_SEASON_SHORTTEXT),true); + Add(new cMyMenuEditBitItem(tr(" add shorttext/title from list"),&flags,OPT_SEASON_STEXTITLE),true); } hasmaps=false; diff --git a/soundex.cpp b/soundex.cpp new file mode 100644 index 0000000..3cb389b --- /dev/null +++ b/soundex.cpp @@ -0,0 +1,483 @@ +#include "import.h" + +/* + * v 1.0d TESTED-OK 20060308 + * ----------------------- + * + * The following SoundEx function is: + * + * (C) Copyright 2002 - 2006, Creativyst, Inc. + * ALL RIGHTS RESERVED + * + * For more information go to: + * http://www.Creativyst.com + * or email: + * Support@Creativyst.com + * + * Redistribution and use in source and binary + * forms, with or without modification, are + * permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must + * retain the above copyright notice, this + * list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must + * reproduce the above copyright notice, + * this list of conditions and the + * following disclaimer in the + * documentation and/or other materials + * provided with the distribution. + * + * 3. All advertising materials mentioning + * features or use of this software must + * display the following acknowledgement: + * This product includes software developed + * by Creativyst, Inc. + * + * 4. The name of Creativyst, Inc. may not be + * used to endorse or promote products + * derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CREATIVYST CORPORATION + *`AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * ------------------ + * ------------------ + * FUNCTION NOTES: + * 1. To avoid all possibility of overwrites make + * sure *SoundEx points to a buffer with at least + * 11 bytes of storage. + * + * 2. This function is for 7/8-bit ASCII characters. + * Modifications are required for UTF16/32, or for + * anything other than the first 7-bits of utf-8. + * + * 3. For those embedded guys who will understand this: + * This is a true library-grade (i.e. re-usable) function, + * meaning it has no dependencies on outside functions + * and requires no non-standard libraries be linked in + * order for it to work. In this case, since it doesn't + * even require the standard C library, it is what C99 + * (I think) calls a: strictly conforming freestanding + * function. + * + */ + +int cImport::SoundEx(char *SoundEx, + char *WordString, + int LengthOption, + int CensusOption) +{ + int InSz = 31; + char WordStr[32]; /* one bigger than InSz */ + int SoundExLen, WSLen, i; + char FirstLetter, *p, *p2; + + SoundExLen = WSLen = 0; + SoundEx[0] = 0; + + if (CensusOption) + { + LengthOption = 4; + } + + if (LengthOption) + { + SoundExLen = LengthOption; + } + if (SoundExLen > 10) + { + SoundExLen = 10; + } + if (SoundExLen < 4) + { + SoundExLen = 4; + } + + if (!WordString) + { + return(0); + } + + /* Copy WordString to WordStr + * without using funcs from other + * libraries. + */ + for (p = WordString,p2 = WordStr,i = 0;(*p);p++,p2++,i++) + { + if (i >= InSz) break; + (*p2) = (*p); + } + (*p2) = 0; + + + + /* Convert WordStr to + * upper-case, without using funcs + * from other libraries + */ + for (p = WordStr;(*p);p++) + { + if ((*p) >= 'a' && (*p) <= 'z') + { + (*p) -= 0x20; + } + } + + + /* convert all non-alpha + * chars to spaces + */ + for (p = WordStr;(*p);p++) + { + if ((*p) < 'A' || (*p) > 'Z') + { + (*p) = ' '; + } + } + + /* Remove leading spaces + */ + for (i = 0, p = p2 = WordStr;(*p);p++) + { + if (!i) + { + if ((*p) != ' ') + { + (*p2) = (*p); + p2++; + i++; + } + } + else + { + (*p2) = (*p); + p2++; + } + } + (*p2) = 0; + + /* Get length of WordStr + */ + for (i = 0,p = WordStr;(*p);p++) i++; + + + /* Remove trailing spaces + */ + for (;i;i--) + { + if (WordStr[i] == ' ') + { + WordStr[i] = 0; + } + else + { + break; + } + } + + /* Get length of WordStr + */ + for (WSLen = 0,p = WordStr;(*p);p++) WSLen++; + + if (!WSLen) + { + return(0); + } + + + + /* Perform our own multi-letter + * improvements + * + * underscore placeholders (_) will be + * removed below. + */ + if (!CensusOption) + { + if (WordStr[0] == 'P' && WordStr[1] == 'S') + { + WordStr[0] = '_'; + } + if (WordStr[0] == 'P' && WordStr[1] == 'F') + { + WordStr[0] = '_'; + } + + for (i = 0;i < WSLen;i++) + { + if (WordStr[i] == 'D' && WordStr[i+1] == 'G') + { + WordStr[i] = '_'; + i++; + continue; + } + if (WordStr[i] == 'G' && WordStr[i+1] == 'H') + { + WordStr[i] = '_'; + i++; + continue; + } + if (WordStr[i] == 'K' && WordStr[i+1] == 'N') + { + WordStr[i] = '_'; + i++; + continue; + } + if (WordStr[i] == 'G' && WordStr[i+1] == 'N') + { + WordStr[i] = '_'; + i++; + continue; + } + if (WordStr[i] == 'M' && WordStr[i+1] == 'B') + { + WordStr[i+1] = '_'; + i++; + continue; + } + + if (WordStr[i] == 'P' && WordStr[i+1] == 'H') + { + WordStr[i] = 'F'; + WordStr[i+1] = '_'; + i++; + continue; + } + if (WordStr[i] == 'T' && + WordStr[i+1] == 'C' && + WordStr[i+2] == 'H' + ) + { + + WordStr[i] = '_'; + i++; + i++; + continue; + } + if (WordStr[i] == 'M' && WordStr[i+1] == 'P' + && (WordStr[i+2] == 'S' || + WordStr[i+2] == 'T' || + WordStr[i+2] == 'Z') + ) + { + WordStr[i+1] = '_'; + i++; + } + } + } /* end if(!CensusOption) */ + + /* squeeze out underscore characters + * added as a byproduct of above process + * (only needed in c styled replace) + */ + for (p = p2 = WordStr;(*p);p++) + { + (*p2) = (*p); + if ((*p2) != '_') + { + p2++; + } + } + (*p2) = 0; + + /* This must be done AFTER our + * multi-letter replacements + * since they could change + * the first letter + */ + FirstLetter = WordStr[0]; + + /* In case we're in CensusOption + * 1 and the word starts with + * an 'H' or 'W' + * (v1.0c djr: add test for H or W) + */ + if (FirstLetter == 'H' || FirstLetter == 'W') + { + WordStr[0] = '-'; + } + + /* In properly done census + * SoundEx, the H and W will + * be squezed out before + * performing the test + * for adjacent digits + * (this differs from how + * 'real' vowels are handled) + */ + if (CensusOption == 1) + { + for (p = &(WordStr[1]);(*p);p++) + { + if ((*p) == 'H' || (*p) == 'W') + { + (*p) = '.'; + } + } + } + + /* Perform classic SoundEx + * replacements. + */ + for (p = WordStr;(*p);p++) + { + if ((*p) == 'A' || + (*p) == 'E' || + (*p) == 'I' || + (*p) == 'O' || + (*p) == 'U' || + (*p) == 'Y' || + (*p) == 'H' || + (*p) == 'W' + ) + { + (*p) = '0'; /* zero */ + } + if ((*p) == 'B' || + (*p) == 'P' || + (*p) == 'F' || + (*p) == 'V' + ) + { + (*p) = '1'; + } + if ((*p) == 'C' || + (*p) == 'S' || + (*p) == 'G' || + (*p) == 'J' || + (*p) == 'K' || + (*p) == 'Q' || + (*p) == 'X' || + (*p) == 'Z' + ) + { + (*p) = '2'; + } + if ((*p) == 'D' || + (*p) == 'T' + ) + { + (*p) = '3'; + } + if ((*p) == 'L') + { + (*p) = '4'; + } + + if ((*p) == 'M' || + (*p) == 'N' + ) + { + (*p) = '5'; + } + if ((*p) == 'R') + { + (*p) = '6'; + } + } + /* soundex replacement loop done */ + + /* In properly done census + * SoundEx, the H and W will + * be squezed out before + * performing the test + * for adjacent digits + * (this differs from how + * 'real' vowels are handled) + */ + if (CensusOption == 1) + { + /* squeeze out dots + */ + for (p = p2 = &WordStr[1];(*p);p++) + { + (*p2) = (*p); + if ((*p2) != '.') + { + p2++; + } + } + (*p2) = 0; + } + + /* squeeze out extra equal adjacent digits + * (don't include first letter) + * v1.0c djr (now includes first letter) + */ + for (p = p2 = &(WordStr[0]);(*p);p++) + { + (*p2) = (*p); + if ((*p2) != p[1]) + { + p2++; + } + } + (*p2) = 0; + + + + /* squeeze out spaces and zeros + * Leave the first letter code + * to be replaced below. + * (In case it made a zero) + */ + for (p = p2 = &WordStr[1];(*p);p++) + { + (*p2) = (*p); + if ((*p2) != ' ' && (*p2) != '0') + { + p2++; + } + } + (*p2) = 0; + + /* Get length of WordStr + */ + for (WSLen = 0,p = WordStr;(*p);p++) WSLen++; + + + /* Right pad with zero characters + */ + for (i = WSLen;i < SoundExLen;i++) + { + WordStr[i] = '0'; + } + + /* Size to taste + */ + WordStr[SoundExLen] = 0; + + /* Replace first digit with + * first letter. + */ + WordStr[0] = FirstLetter; + + /* Copy WordStr to SoundEx + */ + for (p2 = SoundEx,p = WordStr;(*p);p++,p2++) + { + (*p2) = (*p); + } + (*p2) = 0; + + return(SoundExLen); +} diff --git a/xmltv2vdr.cpp b/xmltv2vdr.cpp index d0cb078..45a76d7 100644 --- a/xmltv2vdr.cpp +++ b/xmltv2vdr.cpp @@ -519,8 +519,8 @@ bool cEPGHandler::HandleEvent(cEvent* Event) } source=sources->GetSource(EITSOURCE); if (!source) tsyslog("no source for %s",EITSOURCE); - bool useeptext=((epall & EPLIST_USE_TEXT)==EPLIST_USE_TEXT); - if (useeptext) Flags|=(USE_SHORTTEXT|USE_TITLE); + bool useeptext=((epall & EPLIST_USE_STEXTITLE)==EPLIST_USE_STEXTITLE); + if (useeptext) Flags|=(USE_SHORTTEXT|OPT_SEASON_STEXTITLE); xevent=import.AddXMLTVEvent(source,db,ChannelID,Event,Event->Description(),useeptext); if (!xevent) { @@ -584,20 +584,23 @@ void cEPGTimer::Action() sqlite3 *db=NULL; cEPGSource *source=sources->GetSource(EITSOURCE); - bool useeptext=((epall & EPLIST_USE_TEXT)==EPLIST_USE_TEXT); + bool useeptext=((epall & EPLIST_USE_STEXTITLE)==EPLIST_USE_STEXTITLE); int Flags=USE_SEASON; - if (useeptext) Flags|=(USE_SHORTTEXT|USE_TITLE); + if (useeptext) Flags|=(USE_SHORTTEXT|OPT_SEASON_STEXTITLE); 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() && !event->Description()) continue; // no text -> no episode - if (event->ShortText() && event->Description()) + if (!useeptext) { - if ((strlen(event->ShortText())+strlen(event->Description()))==0) continue; // no 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 + if (maps->ProcessChannel(event->ChannelID()) && event->ShortText()) continue; // already processed by xmltv2vdr const char *ChannelID=strdup(*event->ChannelID().ToString()); cXMLTVEvent *xevent=import.SearchXMLTVEvent(&db,ChannelID,event); @@ -610,6 +613,13 @@ void cEPGTimer::Action() continue; } } + else + { + if (!event->ShortText() && event->Description()) + { + import.AddShortTextFromEITDescription(xevent,event->Description()); + } + } free((void*)ChannelID); import.PutEvent(source,db,NULL,event,xevent,Flags); |