summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--event.cpp120
-rw-r--r--event.h6
-rw-r--r--import.cpp55
-rw-r--r--parse.cpp67
4 files changed, 183 insertions, 65 deletions
diff --git a/event.cpp b/event.cpp
index bcc0b2b..49c6d7c 100644
--- a/event.cpp
+++ b/event.cpp
@@ -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;
diff --git a/event.h b/event.h
index f115c91..f93e591 100644
--- a/event.h
+++ b/event.h
@@ -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;
diff --git a/import.cpp b/import.cpp
index 4791ec1..b5076d1 100644
--- a/import.cpp
+++ b/import.cpp
@@ -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);
diff --git a/parse.cpp b/parse.cpp
index e7f3500..e8736bd 100644
--- a/parse.cpp
+++ b/parse.cpp
@@ -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;