diff options
-rw-r--r-- | event.cpp | 120 | ||||
-rw-r--r-- | event.h | 6 | ||||
-rw-r--r-- | import.cpp | 55 | ||||
-rw-r--r-- | parse.cpp | 67 |
4 files changed, 183 insertions, 65 deletions
@@ -283,9 +283,43 @@ void cXMLTVEvent::AddCredits(const char *CreditType, const char *Credit, const c credits.Sort(); } -const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *ChannelID) +void cXMLTVEvent::CreateEventID(time_t StartTime) { - if (sql) free(sql); + if (eventid) return; + // create own 16bit eventid + struct tm tm; + if (!localtime_r(&StartTime,&tm)) return; + + // this id cycles every 31 days, so if we have + // 4 weeks programme in advance the id will + // occupy already existing entries + // till now, i'm only aware of 2 weeks + // programme in advance + int newid=((tm.tm_mday) & 0x1F)<<11; + newid|=((tm.tm_hour & 0x1F)<<6); + newid|=(tm.tm_min & 0x3F); + + eventid=newid & 0xFFFF; +} + +void cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *ChannelID, char **Insert, char **Update) +{ + if (sql_insert) + { + free(sql_insert); + sql_insert=NULL; + } + if (sql_update) + { + free(sql_update); + sql_update=NULL; + } + + if (!Insert) return; + if (!Update) return; + + *Insert=NULL; + *Update=NULL; const char *cr=credits.toString(); const char *ca=category.toString(); @@ -295,20 +329,15 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan const char *vi=video.toString(); const char *pi=pics.toString(); - if (!eventid) eventid=starttime; // that's very weak! - - if (asprintf(&sql,"INSERT OR IGNORE INTO epg (src,channelid,eventid,starttime,duration,"\ + if (!eventid) return; + + if (asprintf(&sql_insert, + "INSERT OR FAIL INTO epg (src,channelid,eventid,starttime,duration,"\ "title,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^,%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, "\ - "episodeoverall=%i,pics=^%s^,srcidx=%i " \ - " where changes()=0 and src=^%s^ and channelid=^%s^ and eventid=%u" + "^%s^,^%s^,^%s^,^%s^,^%s^,%i,%i,%i,^%s^,%i);" , Source,ChannelID,eventid,starttime,duration,title, origtitle ? origtitle : "NULL", @@ -318,8 +347,20 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan year, cr,ca,re,ra,sr,vi, audio ? audio : "NULL", - season, episode, episodeoverall, pi, SrcIdx, + season, episode, episodeoverall, pi, SrcIdx + )==-1) + { + sql_insert=NULL; + return; + } + if (asprintf(&sql_update, + "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, "\ + "episodeoverall=%i,pics=^%s^,srcidx=%i " \ + " where src=^%s^ and channelid=^%s^ and eventid=%u" + , duration,starttime,title, origtitle ? origtitle : "NULL", shorttext ? shorttext : "NULL", @@ -329,23 +370,36 @@ const char *cXMLTVEvent::GetSQL(const char *Source, int SrcIdx, const char *Chan cr,ca,re,ra,sr,vi, audio ? audio : "NULL", season, episode, episodeoverall, pi, SrcIdx, - Source,ChannelID,eventid + )==-1) + { + sql_update=NULL; + return; + } - )==-1) return NULL; - - string s=sql; - - int reps; - reps=pcrecpp::RE("'").GlobalReplace("''",&s); - reps+=pcrecpp::RE("\\^").GlobalReplace("'",&s); - reps+=pcrecpp::RE("'NULL'").GlobalReplace("NULL",&s); - if (reps) + string si=sql_insert; + int ireps; + ireps=pcrecpp::RE("'").GlobalReplace("''",&si); + ireps+=pcrecpp::RE("\\^").GlobalReplace("'",&si); + ireps+=pcrecpp::RE("'NULL'").GlobalReplace("NULL",&si); + if (ireps) { - sql=(char *) realloc(sql,s.size()+1); - strcpy(sql,s.c_str()); + sql_insert=(char *) realloc(sql_insert,si.size()+1); + strcpy(sql_insert,si.c_str()); } - return sql; + *Insert=sql_insert; + + string su=sql_update; + int ureps; + ureps=pcrecpp::RE("'").GlobalReplace("''",&su); + ureps+=pcrecpp::RE("\\^").GlobalReplace("'",&su); + ureps+=pcrecpp::RE("'NULL'").GlobalReplace("NULL",&su); + if (ureps) + { + sql_update=(char *) realloc(sql_update,su.size()+1); + strcpy(sql_update,su.c_str()); + } + *Update=sql_update; } void cXMLTVEvent::Clear() @@ -355,10 +409,15 @@ void cXMLTVEvent::Clear() free(source); source=NULL; } - if (sql) + if (sql_insert) + { + free(sql_insert); + sql_insert=NULL; + } + if (sql_update) { - free(sql); - sql=NULL; + free(sql_update); + sql_update=NULL; } if (title) { @@ -420,7 +479,8 @@ void cXMLTVEvent::Clear() cXMLTVEvent::cXMLTVEvent() { - sql=NULL; + sql_insert=NULL; + sql_update=NULL; source=NULL; channelid=NULL; title=NULL; @@ -39,7 +39,8 @@ private: char *country; char *origtitle; char *audio; - char *sql; + char *sql_insert; + char *sql_update; char *channelid; char *source; int year; @@ -86,7 +87,8 @@ public: 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); + void CreateEventID(time_t StartTime); + void GetSQL(const char *Source, int SrcIdx, const char *ChannelID, char **Insert, char **Update); cXMLTVStringList *Credits() { return &credits; @@ -406,6 +406,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, int changed=CHANGED_NOTHING; bool append=false; bool retcode=false; + bool added=false; if ((Flags & OPT_APPEND)==OPT_APPEND) append=true; @@ -474,6 +475,14 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, } } } + else + { + // no next event, check for gaps + if (prev->EndTime()!=start) + { + tsyslogs(Source,"detected gap of %lis",(long int)(start-prev->EndTime())); + } + } if (prev->EndTime()>start) { @@ -519,6 +528,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, Event->SetTableID(0); Schedule->AddEvent(Event); Schedule->Sort(); + added=true; if (xEvent->Pics()->Size() && Source->UsePics()) { /* here's a good place to link pictures! */ @@ -530,7 +540,8 @@ 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); - tsyslogs(Source,"adding '%s'@%s-%s",xEvent->Title(),from,till); + tsyslogs(Source,"{%5i} adding '%s'/'%s'@%s-%s",xEvent->EventID(),xEvent->Title(), + xEvent->ShortText(),from,till); } retcode=true; } @@ -901,7 +912,7 @@ bool cImport::PutEvent(cEPGSource *Source, sqlite3 *Db, cSchedule* Schedule, event->SetTableID(0); // prevent EIT EPG to update this event #endif - if (!append && changed) + if (!added && changed) { if (((changed & CHANGED_SHORTTEXT)==CHANGED_SHORTTEXT) && (WasChanged(Event)==false)) @@ -1114,18 +1125,32 @@ cXMLTVEvent *cImport::AddXMLTVEvent(cEPGSource *Source,sqlite3 *Db, const char * return NULL; } - const char *sql=xevent->GetSQL(Source->Name(),99,ChannelID); - char *errmsg; - if (sqlite3_exec(Db,sql,NULL,NULL,&errmsg)!=SQLITE_OK) - { - esyslogs(Source,"%s",errmsg); - sqlite3_free(errmsg); - delete xevent; - xevent=NULL; - } - else + char *isql,*usql; + xevent->GetSQL(Source->Name(),99,ChannelID,&isql,&usql); + if (isql && usql) { - tsyslogs(Source,"{%5i} adding '%s'/'%s' to db",xevent->EventID(),xevent->Title(),xevent->ShortText()); + char *errmsg; + int ret=sqlite3_exec(Db,isql,NULL,NULL,&errmsg); + if (ret!=SQLITE_OK) + { + if (ret==SQLITE_CONSTRAINT) + { + sqlite3_free(errmsg); + ret=sqlite3_exec(Db,usql,NULL,NULL,&errmsg); + } + if (ret!=SQLITE_OK) + { + esyslogs(Source,"sqlite3: %s",errmsg); + sqlite3_free(errmsg); + delete xevent; + return NULL; + } + } + if (ret==SQLITE_OK) + { + tsyslogs(Source,"{%5i} adding '%s'/'%s' to db",xevent->EventID(), + xevent->Title(),xevent->ShortText()); + } } return xevent; } @@ -1257,7 +1282,8 @@ cXMLTVEvent *cImport::SearchXMLTVEvent(sqlite3 **Db,const char *ChannelID, const int eventTimeDiff=0; if (Event->Duration()) eventTimeDiff=Event->Duration()/4; - if (eventTimeDiff<780) eventTimeDiff=780; + if (eventTimeDiff<100) eventTimeDiff=100; + if (eventTimeDiff>780) eventTimeDiff=780; char *sqltitle=strdup(Event->Title()); if (!sqltitle) @@ -1453,7 +1479,6 @@ int cImport::Process(cEPGSource *Source, cEPGExecutor &myExecutor) if (addevents && event && (event->EventID() != xevent.EventID())) { - xevent.SetEITEventID(event->EventID()); // that's only a guess! tsyslogs(Source,"{%5i} changing existing eventid to {%5i}",event->EventID(),xevent.EventID()); event->SetEventID(xevent.EventID()); event->SetVersion(0); @@ -685,11 +685,10 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) "episodeoverall int, pics text, srcidx int," \ "PRIMARY KEY(src, channelid, eventid)" \ ");" \ - "CREATE UNIQUE INDEX IF NOT EXISTS idx1 on epg (eventid, src); " \ - "CREATE UNIQUE INDEX IF NOT EXISTS idx2 on epg (eventid, channelid); " \ - "CREATE UNIQUE INDEX IF NOT EXISTS idx3 on epg (eventid, channelid, src); " \ - "CREATE INDEX IF NOT EXISTS idx4 on epg (starttime, title, channelid); " \ - "CREATE INDEX IF NOT EXISTS idx5 on epg (starttime, src); " \ + "CREATE INDEX IF NOT EXISTS idx1 on epg (eventid, channelid); " \ + "CREATE INDEX IF NOT EXISTS idx2 on epg (eventid, src); " \ + "CREATE INDEX IF NOT EXISTS idx3 on epg (starttime, title, channelid); " \ + "CREATE INDEX IF NOT EXISTS idx4 on epg (starttime, src); " \ "BEGIN"; char *errmsg; @@ -748,7 +747,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) lastchannelid=xmlStrdup(channelid); xmlFree(channelid); - xmlChar *start,*stop; + xmlChar *start=NULL,*stop=NULL; time_t starttime=(time_t) 0; time_t stoptime=(time_t) 0; start=xmlGetProp(node,(const xmlChar *) "start"); @@ -761,10 +760,8 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (stop) { stoptime=ConvertXMLTVTime2UnixTime((char *) stop); - xmlFree(stop); } } - xmlFree(start); } if (!starttime) @@ -774,18 +771,38 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) lerr=PARSE_XMLTVERR; node=node->next; skipped++; + if (start) xmlFree(start); + if (stop) xmlFree(stop); continue; } if (starttime<begin) { node=node->next; - skipped++; + if (start) xmlFree(start); + if (stop) xmlFree(stop); continue; } xevent.Clear(); xevent.SetStartTime(starttime); - if (stoptime) xevent.SetDuration(stoptime-starttime); + if (stoptime) + { + if (stoptime<starttime) + { + if (lerr!=PARSE_XMLTVERR) + esyslogs(source,"stoptime (%s) < starttime(%s), check xmltv file", stop, start); + lerr=PARSE_XMLTVERR; + node=node->next; + skipped++; + if (start) xmlFree(start); + if (stop) xmlFree(stop); + continue; + } + xevent.SetDuration(stoptime-starttime); + } + + if (start) xmlFree(start); + if (stop) xmlFree(stop); if (!FetchEvent(node,(map->Flags() & OPT_SEASON_SHORTTEXT)==OPT_SEASON_SHORTTEXT)) // sets xevent { @@ -807,18 +824,32 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize) if (lweak!=PARSE_NOEVENTID) isyslogs(source,"event without id, using starttime as id (weak)!"); lweak=PARSE_NOEVENTID; + xevent.CreateEventID(xevent.StartTime()); } for (int i=0; i<map->NumChannelIDs(); i++) { - const char *sql=xevent.GetSQL(source->Name(),source->Index(),map->ChannelIDs()[i].ToString()); - if (sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK) - { - if (lerr!=PARSE_SQLERR) - esyslogs(source,"sqlite3: %s",errmsg); - lerr=PARSE_SQLERR; - sqlite3_free(errmsg); - break; + char *isql,*usql; + xevent.GetSQL(source->Name(),source->Index(),map->ChannelIDs()[i].ToString(),&isql,&usql); + if (isql && usql) + { + int ret=sqlite3_exec(db,isql,NULL,NULL,&errmsg); + if (ret!=SQLITE_OK) + { + if (ret==SQLITE_CONSTRAINT) + { + sqlite3_free(errmsg); + ret=sqlite3_exec(db,usql,NULL,NULL,&errmsg); + } + if (ret!=SQLITE_OK) + { + if (lerr!=PARSE_SQLERR) + esyslogs(source,"sqlite3: %s",errmsg); + lerr=PARSE_SQLERR; + sqlite3_free(errmsg); + break; + } + } } } node=node->next; |