summaryrefslogtreecommitdiff
path: root/parse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'parse.cpp')
-rw-r--r--parse.cpp1179
1 files changed, 231 insertions, 948 deletions
diff --git a/parse.cpp b/parse.cpp
index 01d5701..b7e348b 100644
--- a/parse.cpp
+++ b/parse.cpp
@@ -15,195 +15,14 @@
#include <langinfo.h>
#include <time.h>
#include <pwd.h>
+#include <iconv.h>
#include <vdr/timers.h>
+#include <vdr/tools.h>
+#include <sqlite3.h>
#include "xmltv2vdr.h"
#include "parse.h"
-extern char *strcatrealloc(char *dest, const char *src);
-#define TEXTMapping(a) TEXTMapping_(a,texts)
-
-void cXMLTVEvent::SetTitle(const char *Title)
-{
- title = strcpyrealloc(title, Title);
- if (title)
- {
- title = compactspace(title);
- }
-}
-
-void cXMLTVEvent::SetOrigTitle(const char *OrigTitle)
-{
- origtitle = strcpyrealloc(origtitle, OrigTitle);
-}
-
-void cXMLTVEvent::SetShortText(const char *ShortText)
-{
- shorttext=strcpyrealloc(shorttext,ShortText);
- if (shorttext) shorttext=compactspace(shorttext);
-}
-
-void cXMLTVEvent::SetDescription(const char *Description)
-{
- description = strcpyrealloc(description, Description);
- if (description)
- {
- description = compactspace(description);
- if (description[strlen(description)-1]!='\n')
- description=strcatrealloc(description,"\n");
- }
-}
-
-bool cXMLTVEvent::RemoveLastCharFromDescription()
-{
- if (!description) return false;
- int len=strlen(description);
- if (!len) return true;
- description[len-1]=0;
- return true;
-}
-
-bool cXMLTVEvent::Add2Description(const char *Value)
-{
- description = strcatrealloc(description,Value);
- return (description!=NULL);
-}
-
-
-bool cXMLTVEvent::Add2Description(const char *Name, const char *Value)
-{
- description = strcatrealloc(description,Name);
- description = strcatrealloc(description,": ");
- description = strcatrealloc(description,Value);
- description = strcatrealloc(description,"\n");
- return (description!=NULL);
-}
-
-bool cXMLTVEvent::Add2Description(const char *Name, int Value)
-{
- char *value=NULL;
- if (asprintf(&value,"%i",Value)==-1) return false;
- description = strcatrealloc(description,Name);
- description = strcatrealloc(description,": ");
- description = strcatrealloc(description,value);
- description = strcatrealloc(description,"\n");
- free(value);
- return (description!=NULL);
-}
-
-void cXMLTVEvent::SetCountry(const char *Country)
-{
- country=strcpyrealloc(country, Country);
- if (country) country=compactspace(country);
-}
-
-void cXMLTVEvent::SetReview(const char *Review)
-{
- review=strcpyrealloc(review, Review);
- if (review) review=compactspace(review);
-}
-
-void cXMLTVEvent::SetRating(const char *System, const char *Rating)
-{
- system=strcpyrealloc(system, System);
- if (system) system=compactspace(system);
-
- rating=strcpyrealloc(rating, Rating);
- if (rating) rating=compactspace(rating);
-}
-
-void cXMLTVEvent::AddCategory(const char *Category)
-{
- categories.Append(compactspace(strdup(Category)));
- categories.Sort();
-}
-
-void cXMLTVEvent::AddCredits(const char *CreditType, const char *Credit, const char *Addendum)
-{
- char *value=NULL;
- if (Addendum)
- {
- if (asprintf(&value,"%s|%s (%s)",CreditType,Credit,Addendum)==-1) return;
- }
- else
- {
- if (asprintf(&value,"%s|%s",CreditType,Credit)==-1) return;
- }
- credits.Append(value);
- credits.Sort();
-}
-
-void cXMLTVEvent::Clear()
-{
- if (title)
- {
- free(title);
- title=NULL;
- }
- if (shorttext)
- {
- free(shorttext);
- shorttext=NULL;
- }
- if (description)
- {
- free(description);
- description=NULL;
- }
- if (country)
- {
- free(country);
- country=NULL;
- }
- if (system)
- {
- free(system);
- system=NULL;
- }
- if (review)
- {
- free(review);
- review=NULL;
- }
- if (rating)
- {
- free(rating);
- rating=NULL;
- }
- if (origtitle)
- {
- free(origtitle);
- origtitle=NULL;
- }
- year=0;
- starttime = 0;
- duration = 0;
- vps= (time_t) 0;
- eventid=0;
- credits.Clear();
- categories.Clear();
- season=0;
- episode=0;
-}
-
-cXMLTVEvent::cXMLTVEvent()
-{
- title=NULL;
- shorttext=NULL;
- description=NULL;
- country=NULL;
- system=NULL;
- review=NULL;
- rating=NULL;
- origtitle=NULL;
- Clear();
-}
-
-cXMLTVEvent::~cXMLTVEvent()
-{
- Clear();
-}
-
// -------------------------------------------------------
time_t cParse::ConvertXMLTVTime2UnixTime(char *xmltvtime)
@@ -277,283 +96,57 @@ time_t cParse::ConvertXMLTVTime2UnixTime(char *xmltvtime)
return ret;
}
-struct cParse::split cParse::split(char *in, char delim)
+void cParse::RemoveNonAlphaNumeric(char *String)
{
- struct split sp;
- sp.count=1;
- sp.pointers[0]=in;
- while (*++in)
- {
- if (*in==delim)
- {
- *in=0;
- sp.pointers[sp.count++]=in+1;
- }
- }
- return sp;
-}
+ if (!String) return;
+ int len=strlen(String);
+ char *p=String;
+ int pos=0;
-char *cParse::RemoveNonASCII(const char *src)
-{
- if (!src) return NULL;
- int len=strlen(src);
- if (!len) return NULL;
- char *dst=(char *) malloc(len+1);
- if (!dst) return NULL;
- char *tmp=dst;
- bool lspc=false;
- while (*src)
+ while (*p)
{
- // 0x20,0x30-0x39,0x41-0x5A,0x61-0x7A
- if ((*src==0x20) && (!lspc))
- {
- *tmp++=0x20;
- lspc=true;
- }
- if (*src==':')
- {
- *tmp++=0x20;
- lspc=true;
- }
- if ((*src>=0x30) && (*src<=0x39))
+ // 0x30 - 0x39
+ // 0x41 - 0x5A
+ // 0x61 - 0x7A
+ if ((*p<0x30) || (*p>0x7a) || (*p>0x39 && *p<0x41) || (*p>0x5A && *p< 0x61))
{
- *tmp++=*src;
- lspc=false;
- }
- if ((*src>=0x41) && (*src<=0x5A))
- {
- *tmp++=tolower(*src);
- lspc=false;
- }
- if ((*src>=0x61) && (*src<=0x7A))
- {
- *tmp++=*src;
- lspc=false;
- }
- src++;
- }
- *tmp=0;
- return dst;
-}
-
-cEvent *cParse::SearchEvent(cSchedule* schedule, cXMLTVEvent *xevent)
-{
- if (!xevent) return NULL;
- if (!xevent->StartTime()) return NULL;
- if (!xevent->Title()) return NULL;
- cEvent *f=NULL;
-
- time_t start=xevent->StartTime();
- if (!xevent->EventID())
- {
- xevent->SetEventID(DoSum((u_long) start,xevent->Title(),strlen(xevent->Title())));
- }
-
- // try to find an event,
- // 1st with our own EventID
- if (xevent->EventID()) f=(cEvent *) schedule->GetEvent((tEventID) xevent->EventID());
- if (f) return f;
- // 2nd with StartTime
- f=(cEvent *) schedule->GetEvent((tEventID) 0,start);
- if (f)
- {
- if (!strcmp(f->Title(),xevent->Title()))
- {
- return f;
- }
- }
- // 3rd with StartTime +/- WaitTime
- int maxdiff=INT_MAX;
- int eventTimeDiff=0;
- if (xevent->Duration()) eventTimeDiff=xevent->Duration()/4;
- if (eventTimeDiff<780) eventTimeDiff=780;
-
- for (cEvent *p = schedule->Events()->First(); p; p = schedule->Events()->Next(p))
- {
- int diff=abs((int) difftime(p->StartTime(),start));
- if (diff<=eventTimeDiff)
- {
- // found event with exact the same title
- if (!strcmp(p->Title(),xevent->Title()))
- {
- if (diff<=maxdiff)
- {
- f=p;
- maxdiff=diff;
- }
- }
- else
- {
- if (f) continue; // we already have an event!
- // cut both titles into pieces and check
- // if we have at least one match with
- // minimum length of 4 characters
-
- // first remove all non ascii characters
- // we just want the following codes
- // 0x20,0x30-0x39,0x41-0x5A,0x61-0x7A
- int wfound=0;
- char *s1=RemoveNonASCII(p->Title());
- char *s2=RemoveNonASCII(xevent->Title());
- if (s1 && s2)
- {
- if (!strcmp(s1,s2))
- {
- wfound++;
- }
- else
- {
- struct split w1 = split(s1,' ');
- struct split w2 = split(s2,' ');
- if ((w1.count) && (w2.count))
- {
- for (int i1=0; i1<w1.count; i1++)
- {
- for (int i2=0; i2<w2.count; i2++)
- {
- if (!strcmp(w1.pointers[i1],w2.pointers[i2]))
- {
- if (strlen(w1.pointers[i1])>3) wfound++;
- }
- }
- }
- }
- }
- }
- if (s1) free(s1);
- if (s2) free(s2);
-
- if (wfound)
- {
- if (diff<=maxdiff)
- {
- if (p->TableID()!=0)
- source->Dlog("found '%s' for '%s'",p->Title(),xevent->Title());
- f=p;
- maxdiff=diff;
- }
- }
- }
+ memmove(p,p+1,len-pos);
+ len--;
+ continue;
}
+ p++;
+ pos++;
}
- return f;
-}
-cEvent *cParse::GetEventBefore(cSchedule* schedule, time_t start)
-{
- if (!schedule) return NULL;
- if (!schedule->Events()) return NULL;
- if (!schedule->Events()->Count()) return NULL;
- cEvent *last=schedule->Events()->Last();
- if ((last) && (last->StartTime()<start)) return last;
- for (cEvent *p=schedule->Events()->First(); p; p=schedule->Events()->Next(p))
+ // remove leading numbers
+ len=strlen(String);
+ p=String;
+ while (*p)
{
- if (p->StartTime()>start)
+ // 0x30 - 0x39
+ if ((*p>=0x30) && (*p<=0x39))
{
- return (cEvent *) p->Prev();
+ memmove(p,p+1,len);
+ len--;
+ continue;
}
- }
- if (last) return last;
- return NULL;
-}
-
-bool cParse::AddSeasonEpisode2TimerChannels(const char *epdir, cTEXTMappings *texts)
-{
- if (!epdir) return false;
- if (!texts) return false;
-
- const cSchedules *schedules=NULL;
- cSchedulesLock schedulesLock(true,60000); // wait up to 60 secs for lock!
- schedules = cSchedules::Schedules(schedulesLock);
- if (!schedules)
- {
- esyslog("cannot get schedules now, trying later");
- return false;
- }
-
- time_t start=time(NULL);
- time_t stop=start+86400;
-
- for (cTimer *Timer = Timers.First(); Timer; Timer=Timers.Next(Timer))
- {
- if (!Timer->Channel()) continue;
-
- cSchedule* schedule = (cSchedule *) schedules->GetSchedule(Timer->Channel());
- if (!schedule) continue;
-
- for (cEvent *p = schedule->Events()->First(); p; p = schedule->Events()->Next(p))
+ else
{
- if (p->StartTime()>=start && p->StartTime()<=stop && p->TableID() && p->ShortText())
- {
- int season,episode;
- if (FetchSeasonEpisode(epdir,p->Title(), p->ShortText(), season, episode))
- {
- if ((season) || (episode))
- {
- char *description=NULL;
- if (p->Description()) description=strdup(p->Description());
- description = strcatrealloc(description,"\n");
- if (season)
- {
- cTEXTMapping *text=TEXTMapping("season");
- if (text)
- {
- char *value=NULL;
- if (asprintf(&value,"%i",season)!=-1)
- {
- description = strcatrealloc(description,text->Value());
- description = strcatrealloc(description,": ");
- description = strcatrealloc(description,value);
- description = strcatrealloc(description,"\n");
- free(value);
- }
- }
- }
- if (episode)
- {
- cTEXTMapping *text=TEXTMapping("episode");
- if (text)
- {
- char *value=NULL;
- if (asprintf(&value,"%i",episode)!=-1)
- {
- description = strcatrealloc(description,text->Value());
- description = strcatrealloc(description,": ");
- description = strcatrealloc(description,value);
- description = strcatrealloc(description,"\n");
- free(value);
- }
- }
- }
- p->SetDescription(description);
- p->SetTableID(0);
- free(description);
- }
- }
- }
+ break;
}
}
- return true;
+ return;
}
-bool cParse::FetchSeasonEpisode(const char *epdir, const char *title, const char *shorttext, int &season, int &episode)
+bool cParse::FetchSeasonEpisode(iconv_t Conv, const char *EPDir, const char *Title,
+ const char *ShortText, int &Season, int &Episode)
{
- if (!epdir) return false;
- if (!shorttext) return false;
- if (!title) return false;
-
- /*
- char *epfile=NULL;
- if (asprintf(&epfile,"%s/%s.episodes",epdir,title)==-1) return false;
+ if (!EPDir) return false;
+ if (!ShortText) return false;
+ if (!Title) return false;
+ if (Conv==(iconv_t) -1) return false;
- struct stat statbuf;
- if (stat(epfile,&statbuf)==-1)
- {
- free(epfile);
- return false;
- }
- */
- DIR *dir=opendir(epdir);
+ DIR *dir=opendir(EPDir);
if (!dir) return false;
struct dirent dirent_buf,*dirent;
bool found=false;
@@ -564,7 +157,7 @@ bool cParse::FetchSeasonEpisode(const char *epdir, const char *title, const char
if (dirent->d_name[0]=='.') continue;
char *pt=strrchr(dirent->d_name,'.');
if (pt) *pt=0;
- if (!strncasecmp(dirent->d_name,title,strlen(dirent->d_name)))
+ if (!strncasecmp(dirent->d_name,Title,strlen(dirent->d_name)))
{
found=true;
break;
@@ -574,7 +167,7 @@ bool cParse::FetchSeasonEpisode(const char *epdir, const char *title, const char
if (!found) return false;
char *epfile=NULL;
- if (asprintf(&epfile,"%s/%s.episodes",epdir,dirent->d_name)==-1) return false;
+ if (asprintf(&epfile,"%s/%s.episodes",EPDir,dirent->d_name)==-1) return false;
FILE *f=fopen(epfile,"r");
if (!f)
@@ -583,365 +176,67 @@ bool cParse::FetchSeasonEpisode(const char *epdir, const char *title, const char
return false;
}
- char *line=NULL;
- size_t length;
- found=false;
- while (getline(&line,&length,f)!=-1)
+ size_t slen=strlen(ShortText);
+ size_t dlen=4*slen;
+ char *dshorttext=(char *) calloc(dlen,1);
+ if (!dshorttext)
{
- if (line[0]=='#') continue;
- char epshorttext[256]="";
- if (sscanf(line,"%d\t%d\t%*d\t%255c",&season,&episode,epshorttext)==3)
- {
- char *lf=strchr(epshorttext,'\n');
- if (lf) *lf=0;
- if (!strncasecmp(shorttext,epshorttext,strlen(epshorttext)))
- {
- found=true;
- break;
- }
- }
+ fclose(f);
+ free(epfile);
+ return false;
}
- if (line) free(line);
- fclose(f);
-
- free(epfile);
- return found;
-}
+ char *FromPtr=(char *) ShortText;
+ char *ToPtr=(char *) dshorttext;
-bool cParse::PutEvent(cSchedule* schedule, cEvent *event, cXMLTVEvent *xevent, cEPGMapping *map)
-{
- if (!schedule) return false;
- if (!xevent) return false;
- if (!map) return false;
-
- struct tm tm;
- char from[80];
- char till[80];
- time_t start,end;
- if (!event)
+ if (iconv(Conv,&FromPtr,&slen,&ToPtr,&dlen)==(size_t) -1)
{
- if ((map->Flags() & OPT_APPEND)==OPT_APPEND)
- {
- start=xevent->StartTime();
- end=start+xevent->Duration();
-
- /* checking the "space" for our new event */
- cEvent *prev=GetEventBefore(schedule,start);
- if (prev)
- {
- if (cEvent *next=(cEvent *) prev->Next())
- {
- if (prev->EndTime()==next->StartTime())
- {
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till);
-
- time_t pstart=prev->StartTime();
- time_t pstop=prev->EndTime();
- localtime_r(&pstart,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&pstop,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("found '%s'@%s-%s",prev->Title(),from,till);
-
- time_t nstart=next->StartTime();
- time_t nstop=next->EndTime();
- localtime_r(&nstart,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&nstop,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("found '%s'@%s-%s",next->Title(),from,till);
- return false;
- }
-
- if (end>next->StartTime())
- {
- int diff=(int) difftime(prev->EndTime(),start);
- if (diff>300)
- {
-
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till);
-
- time_t nstart=next->StartTime();
- time_t nstop=next->EndTime();
- localtime_r(&nstart,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&nstop,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("found '%s'@%s-%s",next->Title(),from,till);
- return false;
- }
- else
- {
- xevent->SetDuration(xevent->Duration()-diff);
- }
- }
- }
-
- if (prev->EndTime()>start)
- {
- int diff=(int) difftime(prev->EndTime(),start);
- if (diff>300)
- {
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("cannot add '%s'@%s-%s",xevent->Title(),from,till);
-
- time_t pstart=prev->StartTime();
- time_t pstop=prev->EndTime();
- localtime_r(&pstart,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&pstop,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Elog("found '%s'@%s-%s",prev->Title(),from,till);
- return false;
- }
- else
- {
- prev->SetDuration(prev->Duration()-diff);
- }
- }
-
- if (!xevent->Duration())
- {
- if (!prev->Duration())
- {
- prev->SetDuration(start-prev->StartTime());
- }
- }
- }
- /* add event */
- event=new cEvent(xevent->EventID());
- if (!event) return false;
- event->SetStartTime(start);
- event->SetDuration(xevent->Duration());
- event->SetTitle(xevent->Title());
- event->SetShortText(xevent->ShortText());
- event->SetDescription(xevent->Description());
- event->SetVersion(0);
- schedule->AddEvent(event);
- schedule->Sort();
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Dlog("adding '%s'@%s-%s",xevent->Title(),from,till);
- }
- else
- {
- return true;
- }
+ free(dshorttext);
+ fclose(f);
+ free(epfile);
+ return false;
}
- if ((map->Flags() & USE_SHORTTEXT)==USE_SHORTTEXT)
- {
- if (xevent->ShortText() && (strlen(xevent->ShortText())>0))
- {
- if (!strcmp(xevent->ShortText(),event->Title()))
- {
- source->Dlog("title and subtitle equal, clearing subtitle");
- event->SetShortText("");
- }
- else
- {
- event->SetShortText(xevent->ShortText());
- }
- }
- }
+ RemoveNonAlphaNumeric(dshorttext);
- if (epdir && xevent->ShortText() && (strlen(xevent->ShortText())>0) && ((map->Flags() & USE_SEASON)==USE_SEASON))
- {
- // Try to fetch season and episode from eplist
- int season,episode;
- if (FetchSeasonEpisode(epdir,xevent->Title(),xevent->ShortText(),season,episode))
- {
- xevent->SetSeason(season);
- xevent->SetEpisode(episode);
- }
- }
- if ((map->Flags() & USE_LONGTEXT)==USE_LONGTEXT)
- {
- if (xevent->Description() && (strlen(xevent->Description())>0))
- {
- event->SetDescription(xevent->Description());
- }
- else
- {
- xevent->SetDescription(event->Description());
- }
- }
- else
- {
- xevent->SetDescription(event->Description());
- }
- bool addExt=false;
- if ((map->Flags() & USE_CREDITS)==USE_CREDITS)
+ char *line=NULL;
+ size_t length;
+ found=false;
+ while (getline(&line,&length,f)!=-1)
{
- cStringList *credits=xevent->Credits();
- if (credits->Size())
+ if (line[0]=='#') continue;
+ char epshorttext[256]="";
+ char depshorttext[1024]="";
+ if (sscanf(line,"%d\t%d\t%*d\t%255c",&Season,&Episode,epshorttext)==3)
{
- cTEXTMapping *oldtext=NULL;
- for (int i=0; i<credits->Size(); i++)
- {
- char *ctype=strdup((*credits)[i]);
- if (ctype)
+ char *lf=strchr(epshorttext,'\n');
+ if (lf) *lf=0;
+ slen=strlen(epshorttext);
+ dlen=sizeof(depshorttext);
+ FromPtr=(char *) epshorttext;
+ ToPtr=(char *) depshorttext;
+ if (iconv(Conv,&FromPtr,&slen,&ToPtr,&dlen)!=(size_t) -1)
+ {
+ RemoveNonAlphaNumeric(depshorttext);
+ if (!strncasecmp(dshorttext,depshorttext,strlen(depshorttext)))
{
- char *cval=strchr(ctype,'|');
- if (cval)
- {
- *cval=0;
- cval++;
- bool add=true;
- if (((map->Flags() & CREDITS_ACTORS)!=CREDITS_ACTORS) &&
- (!strcasecmp(ctype,"actor"))) add=false;
- if (((map->Flags() & CREDITS_DIRECTORS)!=CREDITS_DIRECTORS) &&
- (!strcasecmp(ctype,"director"))) add=false;
- if (((map->Flags() & CREDITS_OTHERS)!=CREDITS_OTHERS) &&
- (add) && (strcasecmp(ctype,"actor")) &&
- (strcasecmp(ctype,"director"))) add=false;
- if (add)
- {
- cTEXTMapping *text=TEXTMapping(ctype);
- if ((map->Flags() & CREDITS_LIST)==CREDITS_LIST)
- {
- if (oldtext!=text)
- {
- if (oldtext)
- {
- addExt=xevent->RemoveLastCharFromDescription();
- addExt=xevent->RemoveLastCharFromDescription();
- addExt=xevent->Add2Description("\n");
- }
- addExt=xevent->Add2Description(text->Value());
- addExt=xevent->Add2Description(": ");
- }
- addExt=xevent->Add2Description(cval);
- addExt=xevent->Add2Description(", ");
- }
- else
- {
- if (text)
- {
- addExt=xevent->Add2Description(text->Value(),cval);
- }
- }
- oldtext=text;
- }
- }
- free(ctype);
+ found=true;
+ break;
}
}
- if ((oldtext) && ((map->Flags() & CREDITS_LIST)==CREDITS_LIST))
- {
- addExt=xevent->RemoveLastCharFromDescription();
- addExt=xevent->RemoveLastCharFromDescription();
- addExt=xevent->Add2Description("\n");
- }
- }
- }
-
- if ((map->Flags() & USE_COUNTRYDATE)==USE_COUNTRYDATE)
- {
- if (xevent->Country())
- {
- cTEXTMapping *text=TEXTMapping("country");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->Country());
- }
-
- if (xevent->Year())
- {
- cTEXTMapping *text=TEXTMapping("date");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->Year());
- }
- }
- if ((map->Flags() & USE_SEASON)==USE_SEASON)
- {
- if (xevent->Season())
- {
- cTEXTMapping *text=TEXTMapping("season");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->Season());
- }
-
- if (xevent->Episode())
- {
- cTEXTMapping *text=TEXTMapping("episode");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->Episode());
- }
- }
-
- if (((map->Flags() & USE_ORIGTITLE)==USE_ORIGTITLE) && (xevent->OrigTitle()))
- {
- cTEXTMapping *text=TEXTMapping("originaltitle");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->OrigTitle());
- }
- if (((map->Flags() & USE_CATEGORIES)==USE_CATEGORIES) && (xevent->Categories()->Size()))
- {
- cTEXTMapping *text=TEXTMapping("category");
- if (text)
- {
- cStringList *categories=xevent->Categories();
- addExt=xevent->Add2Description(text->Value(),(*categories)[0]);
- for (int i=1; i<categories->Size(); i++)
- {
- // prevent duplicates
- if (strcasecmp((*categories)[i],(*categories)[i-1]))
- addExt=xevent->Add2Description(text->Value(),(*categories)[i]);
- }
}
}
- if (((map->Flags() & USE_RATING)==USE_RATING) && (xevent->Rating()) && (xevent->RatingSystem()))
- {
- addExt=xevent->Add2Description(xevent->RatingSystem(),xevent->Rating());
- }
- if (((map->Flags() & USE_REVIEW)==USE_REVIEW) && (xevent->Review()))
- {
- cTEXTMapping *text=TEXTMapping("review");
- if (text) addExt=xevent->Add2Description(text->Value(),xevent->Review());
- }
- if (event->TableID()==0) return true;
- if ((map->Flags() & OPT_APPEND)!=OPT_APPEND)
- {
- start=event->StartTime();
- end=event->EndTime();
- localtime_r(&start,&tm);
- strftime(from,sizeof(from)-1,"%b %d %H:%M",&tm);
- localtime_r(&end,&tm);
- strftime(till,sizeof(till)-1,"%b %d %H:%M",&tm);
- source->Dlog("changing '%s'@%s-%s",event->Title(),from,till);
- }
- if (addExt) event->SetDescription(xevent->Description());
- event->SetTableID(0); // prevent EIT EPG to update this event
- return true;
-}
-u_long cParse::DoSum(u_long sum, const char *buf, int nBytes)
-{
- int nleft=nBytes;
- u_short *w = (u_short*)buf;
-
- while (nleft > 1)
+ if (!found)
{
- sum += *w++;
- nleft -= 2;
+ isyslog("xmltv2vdr: failed to find '%s' for '%s' in eplists",ShortText,Title);
}
+ if (line) free(line);
+ fclose(f);
- if (nleft == 1)
- {
- u_short answer = 0;
- *(u_char*)(&answer) = *(u_char*)w;
- sum += answer;
- }
- return sum;
+ free(dshorttext);
+ free(epfile);
+ return found;
}
bool cParse::FetchEvent(xmlNodePtr enode)
@@ -960,17 +255,17 @@ bool cParse::FetchEvent(xmlNodePtr enode)
{
if (lang && slang && !xmlStrncasecmp(lang, (const xmlChar *) slang,2))
{
- xevent.SetTitle(conv->Convert((const char *) content));
+ xevent.SetTitle((const char *) content);
}
else
{
- if (!xevent.Title())
+ if (!xevent.HasTitle())
{
- xevent.SetTitle(conv->Convert((const char *) content));
+ xevent.SetTitle((const char *) content);
}
else
{
- xevent.SetOrigTitle(conv->Convert((const char *) content));
+ xevent.SetOrigTitle((const char *) content);
}
}
xmlFree(content);
@@ -983,7 +278,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(node->doc,node->xmlChildrenNode,1);
if (content)
{
- xevent.SetShortText(conv->Convert((const char *) content));
+ xevent.SetShortText((const char *) content);
xmlFree(content);
}
}
@@ -993,7 +288,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(node->doc,node->xmlChildrenNode,1);
if (content)
{
- xevent.SetDescription(conv->Convert((const char *) content));
+ xevent.SetDescription((const char *) content);
xmlFree(content);
}
}
@@ -1009,15 +304,9 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
if (content)
{
- const char *role=NULL;
xmlChar *arole=xmlGetProp(node,(const xmlChar *) "actor role");
- if (arole)
- {
- role=strdup(conv->Convert((const char *) arole));
- xmlFree(arole);
- }
- xevent.AddCredits((const char *) vnode->name,conv->Convert((const char *) content),role);
- if (role) free((void *) role);
+ xevent.AddCredits((const char *) vnode->name,(const char *) content,(const char *) arole);
+ if (arole) xmlFree(arole);
xmlFree(content);
}
}
@@ -1026,7 +315,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
if (content)
{
- xevent.AddCredits((const char *) vnode->name,conv->Convert((const char *) content));
+ xevent.AddCredits((const char *) vnode->name,(const char *) content);
xmlFree(content);
}
}
@@ -1055,7 +344,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
}
else
{
- xevent.AddCategory(conv->Convert((const char *) content));
+ xevent.AddCategory((const char *) content);
}
xmlFree(content);
}
@@ -1065,15 +354,69 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(node->doc,node->xmlChildrenNode,1);
if (content)
{
- xevent.SetCountry(conv->Convert((const char *) content));
+ xevent.SetCountry((const char *) content);
xmlFree(content);
}
}
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "video")))
{
+ xmlNodePtr vnode=node->xmlChildrenNode;
+ while (vnode)
+ {
+ if (vnode->type==XML_ELEMENT_NODE)
+ {
+ if ((!xmlStrcasecmp(vnode->name, (const xmlChar *) "colour")))
+ {
+ xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
+ if (content)
+ {
+ xevent.AddVideo("colour",(const char *) content);
+ xmlFree(content);
+ }
+ }
+ if ((!xmlStrcasecmp(vnode->name, (const xmlChar *) "aspect")))
+ {
+ xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
+ if (content)
+ {
+ xevent.AddVideo("aspect",(const char *) content);
+ xmlFree(content);
+ }
+ }
+ if ((!xmlStrcasecmp(vnode->name, (const xmlChar *) "quality")))
+ {
+ xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
+ if (content)
+ {
+ xevent.AddVideo("quality",(const char *) content);
+ xmlFree(content);
+ }
+ }
+
+ }
+ vnode=vnode->next;
+ }
}
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "audio")))
{
+ xmlNodePtr vnode=node->xmlChildrenNode;
+ while (vnode)
+ {
+ if (vnode->type==XML_ELEMENT_NODE)
+ {
+ if ((!xmlStrcasecmp(vnode->name, (const xmlChar *) "stereo")))
+ {
+ xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
+ if (content)
+ {
+ content=(xmlChar*)strreplace((char *)content," ","");
+ xevent.SetAudio((const char *) content);
+ xmlFree(content);
+ }
+ }
+ }
+ vnode=vnode->next;
+ }
}
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "rating")))
{
@@ -1090,11 +433,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
if (content)
{
- const char *crating=strdup(conv->Convert((const char *) content));
- const char *csystem=strdup(conv->Convert((const char *) system));
- xevent.SetRating(csystem,crating);
- if (crating) free((void *) crating);
- if (csystem) free((void *) csystem);
+ xevent.AddRating((const char *) system,(const char *) content);
xmlFree(content);
}
}
@@ -1104,6 +443,28 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlFree(system);
}
}
+ else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "star-rating")))
+ {
+ xmlChar *system=xmlGetProp(node,(const xmlChar *) "system");
+ xmlNodePtr vnode=node->xmlChildrenNode;
+ while (vnode)
+ {
+ if (vnode->type==XML_ELEMENT_NODE)
+ {
+ if ((!xmlStrcasecmp(vnode->name, (const xmlChar *) "value")))
+ {
+ xmlChar *content=xmlNodeListGetString(vnode->doc,vnode->xmlChildrenNode,1);
+ if (content)
+ {
+ xevent.AddStarRating((const char *) system,(const char *) content);
+ xmlFree(content);
+ }
+ }
+ }
+ vnode=vnode->next;
+ }
+ if (system) xmlFree(system);
+ }
else if ((!xmlStrcasecmp(node->name, (const xmlChar *) "review")))
{
xmlChar *type=xmlGetProp(node,(const xmlChar *) "type");
@@ -1112,7 +473,7 @@ bool cParse::FetchEvent(xmlNodePtr enode)
xmlChar *content=xmlNodeListGetString(node->doc,node->xmlChildrenNode,1);
if (content)
{
- xevent.SetReview(conv->Convert((const char *) content));
+ xevent.AddReview((const char *) content);
xmlFree(content);
}
xmlFree(type);
@@ -1137,27 +498,15 @@ bool cParse::FetchEvent(xmlNodePtr enode)
}
node=node->next;
}
- return (xevent.Title()!=NULL);
-}
-cTEXTMapping *cParse::TEXTMapping_(const char *Name, cTEXTMappings *texts)
-{
- if (!texts->Count()) return NULL;
- for (cTEXTMapping *textmap=texts->First(); textmap; textmap=texts->Next(textmap))
+ int season,episode;
+ if (FetchSeasonEpisode(conv,epdir,xevent.Title(),xevent.ShortText(),season,episode))
{
- if (!strcmp(textmap->Name(),Name)) return textmap;
+ xevent.SetSeason(season);
+ xevent.SetEpisode(episode);
}
- return NULL;
-}
-cEPGMapping *cParse::EPGMapping(const char *ChannelName)
-{
- if (!maps->Count()) return NULL;
- for (cEPGMapping *map=maps->First(); map; map=maps->Next(map))
- {
- if (!strcmp(map->ChannelName(),ChannelName)) return map;
- }
- return NULL;
+ return xevent.HasTitle();
}
int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize)
@@ -1181,30 +530,38 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize)
return 141;
}
- const cSchedules *schedules=NULL;
- int l=0;
- while (l<300)
+ sqlite3 *db=NULL;
+ if (sqlite3_open(source->EPGFile(),&db)!=SQLITE_OK)
{
- cSchedulesLock schedulesLock(true,200); // wait up to 60 secs for lock!
- schedules = cSchedules::Schedules(schedulesLock);
- if (!myExecutor.StillRunning())
- {
- source->Ilog("request to stop from vdr");
- return 0;
- }
- if (schedules) break;
- l++;
+ source->Elog("failed to open or create %s",source->EPGFile());
+ xmlFreeDoc(xmltv);
+ return 141;
}
- if (!schedules)
+ 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, " \
+ "credits text, category text, review text, rating text, " \
+ "starrating text, video text, audio text, season int, episode int, mixing int," \
+ "srcidx int," \
+ "PRIMARY KEY(src, channelid, eventid)" \
+ ")";
+
+ char *errmsg;
+ if (sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
{
- source->Elog("cannot get schedules now, trying later");
- return 1;
+ source->Elog("createdb: %s",errmsg);
+ sqlite3_free(errmsg);
+ sqlite3_close(db);
+ xmlFreeDoc(xmltv);
+ return 141;
}
- time_t begin=time(NULL);
+ time_t begin=time(NULL)-7200;
xmlNodePtr node=rootnode->xmlChildrenNode;
- cEPGMapping *oldmap=NULL;
+
int lerr=0;
while (node)
{
@@ -1227,7 +584,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize)
node=node->next;
continue;
}
- cEPGMapping *map=EPGMapping((const char *) channelid);
+ cEPGMapping *map=maps->GetMap((const char *) channelid);
if (!map)
{
if (lerr!=PARSE_NOMAPPING)
@@ -1237,9 +594,7 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize)
node=node->next;
continue;
}
- int days=map->Days();
- if ((map->Flags() & OPT_APPEND)!=OPT_APPEND) days=1; // only one day with merge
- time_t end=begin+(86000*days)+3600; // 1 hour overlap
+
xmlChar *start,*stop;
time_t starttime=(time_t) 0;
time_t stoptime=(time_t) 0;
@@ -1262,115 +617,53 @@ int cParse::Process(cEPGExecutor &myExecutor,char *buffer, int bufsize)
if (!starttime)
{
if (lerr!=PARSE_XMLTVERR)
- source->Elog("xmltv2vdr: '%s' no starttime, check xmltv file");
+ source->Elog("no starttime, check xmltv file");
lerr=PARSE_XMLTVERR;
xmlFree(channelid);
node=node->next;
continue;
}
- if ((starttime<begin) || (starttime>end))
+ if (starttime<begin)
{
xmlFree(channelid);
node=node->next;
continue;
}
xevent.Clear();
-
- if (oldmap!=map)
- {
- source->Dlog("processing '%s'",channelid);
- source->Dlog("from %s",ctime_r(&begin,(char *) &cbuf));
- source->Dlog("till %s",ctime_r(&end,(char *) &cbuf));
- }
- oldmap=map;
- xmlFree(channelid);
-
- if ((map->Flags() & OPT_VPS)==OPT_VPS)
- {
- xmlChar *vpsstart=xmlGetProp(node,(const xmlChar *) "vps-start");
- if (vpsstart)
- {
- time_t vps=ConvertXMLTVTime2UnixTime((char *) vpsstart);
- xevent.SetVps(vps);
- xmlFree(vpsstart);
- }
- }
-
xevent.SetStartTime(starttime);
if (stoptime) xevent.SetDuration(stoptime-starttime);
+
+ if ((map->Flags() & OPT_APPEND)!=OPT_APPEND) xevent.SetMixing();
+
if (!FetchEvent(node)) // sets xevent
{
source->Dlog("failed to fetch event");
node=node->next;
+ xmlFree(channelid);
continue;
}
- for (int i=0; i<map->NumChannelIDs(); i++)
- {
- bool addevents=false;
- if ((map->Flags() & OPT_APPEND)==OPT_APPEND) addevents=true;
- cChannel *channel=Channels.GetByChannelID(map->ChannelIDs()[i]);
- if (!channel)
- {
- if (lerr!=PARSE_NOCHANNEL)
- source->Elog("channel %s not found in channels.conf",
- *map->ChannelIDs()[i].ToString());
- lerr=PARSE_NOCHANNEL;
- continue;
- }
- cSchedule* schedule = (cSchedule *) schedules->GetSchedule(channel,addevents);
- if (!schedule)
- {
- if (lerr!=PARSE_NOSCHEDULE)
- source->Elog("cannot get schedule for channel %s%s",
- channel->Name(),addevents ? "" : " - try add option");
- lerr=PARSE_NOSCHEDULE;
- continue;
- }
- if (addevents)
- {
- cEvent *event=SearchEvent(schedule,&xevent);
- if (!event)
- PutEvent(schedule,event,&xevent,map);
- }
- else
- {
- if (!schedule->Events()->Count())
- {
- if (lerr!=PARSE_EMPTYSCHEDULE)
- source->Elog("cannot merge into empty epg (%s) - try add option",
- channel->Name());
- lerr=PARSE_EMPTYSCHEDULE;
- }
- else
- {
- cEvent *event=schedule->Events()->Last();
- if (event->StartTime()>xevent.StartTime())
- {
- if ((event=SearchEvent(schedule,&xevent)))
- {
- PutEvent(schedule,event,&xevent,map);
- }
- else
- {
- time_t start=xevent.StartTime();
- source->Elog("no event in epg for %s@%s (%s)",
- xevent.Title(),ctime_r(&start,(char *) &cbuf),
- channel->Name());
- }
- }
- }
- }
+ char *errmsg;
+ const char *sql=xevent.GetSQL(source->Name(),source->Index(),(const char *) channelid);
+ if (sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
+ {
+ source->Elog("sqlite3: %s",errmsg);
+ sqlite3_free(errmsg);
+ xmlFree(channelid);
+ break;
}
+ xmlFree(channelid);
+
node=node->next;
if (!myExecutor.StillRunning())
{
- xmlFreeDoc(xmltv);
source->Ilog("request to stop from vdr");
- return 0;
+ break;
}
}
+ sqlite3_close(db);
+
xmlFreeDoc(xmltv);
return 0;
}
@@ -1385,27 +678,10 @@ void cParse::CleanupLibXML()
xmlCleanupParser();
}
-cParse::cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts)
+cParse::cParse(cEPGSource *Source, cEPGMappings *Maps)
{
source=Source;
maps=Maps;
- texts=Texts;
-
- char *CodeSet=NULL;
- if (setlocale(LC_CTYPE,""))
- CodeSet=nl_langinfo(CODESET);
- else
- {
- char *LangEnv=getenv("LANG");
- if (LangEnv)
- {
- CodeSet=strchr(LangEnv,'.');
- if (CodeSet)
- CodeSet++;
- }
- }
- source->Dlog("vdr codeset is '%s'",CodeSet ? CodeSet : "US-ASCII//TRANSLIT");
- conv = new cCharSetConv("UTF-8",CodeSet ? CodeSet : "US-ASCII//TRANSLIT");
struct passwd pwd,*pwdbuf;
char buf[1024];
@@ -1419,6 +695,10 @@ cParse::cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts)
free(epdir);
epdir=NULL;
}
+ else
+ {
+ conv=iconv_open("US-ASCII//TRANSLIT","UTF-8");
+ }
}
else
{
@@ -1429,6 +709,9 @@ cParse::cParse(cEPGSource *Source, cEPGMappings *Maps, cTEXTMappings *Texts)
cParse::~cParse()
{
- if (epdir) free(epdir);
- delete conv;
+ if (epdir)
+ {
+ free(epdir);
+ iconv_close(conv);
+ }
}