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