Reading 'epg.data' at startup

This commit is contained in:
Klaus Schmidinger 2002-02-23 17:11:19 +01:00
parent db7f6ee619
commit 430284a8a7
5 changed files with 167 additions and 12 deletions

34
FORMATS
View File

@ -180,3 +180,37 @@ Video Disk Recorder File Formats
for audio 2 (if available). Dolby Digital data is stored in packets with
ids 0xBD.
* epg.data
This file contains the EPG data in an easily parsable format. The first
character of each line defines what kind of data this line contains.
The following tag characters are defined:
C <service id> <channel name>
E <event id> <start time> <duration> <table id>
T <title>
S <subtitle>
D <description>
e
c
Lowercase characters mark the end of a sequence that was started by the
corresponding uppercase character. The outer frame consists of a sequence
of one or more 'C'...'c' (Channel) entries. Inside these any number of
'E'...'e' (Event) entries are allowed. The 'T', 'S' and 'D' entries are
optional (although every event should at least have a 'T' entry).
<service id> is the "program number" as defined in 'channels.conf'
<channel name> is the "name" as in 'channels.conf' (for information only)
<start time> is the time (as a time_t integer) in UTC when this event starts
<duration> is the time (in seconds) that this event will take
<table id> is a hex number that indicates the table this event is contained
in (if this is left empty or 0 this event will not be overwritten
or modified by data that comes from the DVB stream)
<title> is the title of the event
<subtitle> is the subtitle (typically the name of the episode etc.)
<description> is the description of the event
This file will be read at program startup in order to restore the results of
previous EPG scans.

View File

@ -997,7 +997,7 @@ Video Disk Recorder Revision History
- If a recording has no episode title, the trailing '~' is no longer shown in
the progress display.
2002-02-17: Version 1.0.0pre1
2002-02-23: Version 1.0.0pre1
- Added scanning for EPG data for another 4 days on channels that support this
(thanks to Oleg Assovski).
@ -1020,3 +1020,6 @@ Video Disk Recorder Revision History
"instant" recording (see FORMATS for details).
- Fixed the SVDRP GRAB command in case the video device can't be opened (thanks
to Adrian Stabiszewski).
- At startup the data written into 'epg.data' is now read into the EPG data
structures. In order for this to work, the 'E' record has been extended to
(optionally) contain the 'table ID' (see FORMATS for details).

125
eit.c
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.36 2002/02/23 13:53:53 kls Exp $
* $Id: eit.c 1.37 2002/02/23 17:11:19 kls Exp $
***************************************************************************/
#include "eit.h"
@ -341,7 +341,7 @@ unsigned short cEventInfo::GetServiceID() const
void cEventInfo::Dump(FILE *f, const char *Prefix) const
{
if (tTime + lDuration >= time(NULL)) {
fprintf(f, "%sE %u %ld %ld\n", Prefix, uEventID, tTime, lDuration);
fprintf(f, "%sE %u %ld %ld %X\n", Prefix, uEventID, tTime, lDuration, uTableID);
if (!isempty(pTitle))
fprintf(f, "%sT %s\n", Prefix, pTitle);
if (!isempty(pSubtitle))
@ -352,6 +352,54 @@ void cEventInfo::Dump(FILE *f, const char *Prefix) const
}
}
bool cEventInfo::Read(FILE *f, cSchedule *Schedule)
{
if (Schedule) {
cEventInfo *pEvent = NULL;
char *s;
while ((s = readline(f)) != NULL) {
char *t = skipspace(s + 1);
switch (*s) {
case 'E': if (!pEvent) {
unsigned int uEventID;
time_t tTime;
long lDuration;
unsigned int uTableID = 0;
int n = sscanf(t, "%u %ld %ld %X", &uEventID, &tTime, &lDuration, &uTableID);
if (n == 3 || n == 4) {
pEvent = (cEventInfo *)Schedule->GetEvent(uEventID, tTime);
if (!pEvent)
pEvent = Schedule->AddEvent(new cEventInfo(Schedule->GetServiceID(), uEventID));
if (pEvent) {
pEvent->SetTableID(uTableID);
pEvent->SetTime(tTime);
pEvent->SetDuration(lDuration);
}
}
}
break;
case 'T': if (pEvent)
pEvent->SetTitle(t);
break;
case 'S': if (pEvent)
pEvent->SetSubtitle(t);
break;
case 'D': if (pEvent)
pEvent->SetExtendedDescription(t);
break;
case 'e': pEvent = NULL;
break;
case 'c': // to keep things simple we react on 'c' here
return false;
default: esyslog(LOG_ERR, "ERROR: unexpected tag while reading EPG data: %s", s);
return false;
}
}
return true;
}
return false;
}
#define MAXEPGBUGFIXSTATS 5
#define MAXEPGBUGFIXCHANS 50
struct tEpgBugFixStats {
@ -545,6 +593,13 @@ cSchedule::cSchedule(unsigned short servid)
cSchedule::~cSchedule()
{
}
cEventInfo *cSchedule::AddEvent(cEventInfo *EventInfo)
{
Events.Add(EventInfo);
return EventInfo;
}
/** */
const cEventInfo * cSchedule::GetPresentEvent() const
{
@ -689,6 +744,31 @@ void cSchedule::Dump(FILE *f, const char *Prefix) const
}
}
bool cSchedule::Read(FILE *f, cSchedules *Schedules)
{
if (Schedules) {
char *s;
while ((s = readline(f)) != NULL) {
if (*s == 'C') {
unsigned int uServiceID;
if (1 == sscanf(s + 1, "%u", &uServiceID)) {
cSchedule *p = (cSchedule *)Schedules->SetCurrentServiceID(uServiceID);
if (p) {
while (cEventInfo::Read(f, p))
; // loop stops after having read the closing 'c'
}
}
}
else {
esyslog(LOG_ERR, "ERROR: unexpected tag while reading EPG data: %s", s);
return false;
}
}
return true;
}
return false;
}
// --- cSchedules ------------------------------------------------------------
cSchedules::cSchedules()
@ -701,7 +781,7 @@ cSchedules::~cSchedules()
{
}
/** */
bool cSchedules::SetCurrentServiceID(unsigned short servid)
const cSchedule *cSchedules::SetCurrentServiceID(unsigned short servid)
{
pCurrentSchedule = GetSchedule(servid);
if (pCurrentSchedule == NULL)
@ -709,12 +789,12 @@ bool cSchedules::SetCurrentServiceID(unsigned short servid)
Add(new cSchedule(servid));
pCurrentSchedule = GetSchedule(servid);
if (pCurrentSchedule == NULL)
return false;
return NULL;
}
uCurrentServiceID = servid;
return true;
return pCurrentSchedule;
}
/** */
const cSchedule * cSchedules::GetSchedule() const
@ -757,6 +837,13 @@ void cSchedules::Dump(FILE *f, const char *Prefix) const
p->Dump(f, Prefix);
}
/** */
bool cSchedules::Read(FILE *f)
{
cMutexLock MutexLock;
return cSchedule::Read(f, (cSchedules *)cSIProcessor::Schedules(MutexLock));
}
// --- cEIT ------------------------------------------------------------------
class cEIT {
@ -822,16 +909,19 @@ int cEIT::ProcessEIT(unsigned char *buffer)
if (!pEvent) {
// If we don't have that event ID yet, we create a new one.
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
pSchedule->Events.Add(new cEventInfo(VdrProgramInfo->ServiceID, VdrProgramInfo->EventID));
pEvent = (cEventInfo *)pSchedule->GetEvent((unsigned short)VdrProgramInfo->EventID);
pEvent = pSchedule->AddEvent(new cEventInfo(VdrProgramInfo->ServiceID, VdrProgramInfo->EventID));
if (!pEvent)
break;
pEvent->SetTableID(tid);
}
else {
// We have found an existing event, either through its event ID or its start time.
// If the existing event has a zero table ID it was defined externally and shall
// not be overwritten.
if (pEvent->GetTableID() == 0x00)
continue;
// If the new event comes from a table that belongs to an "other TS" and the existing
// one comes from a "actual TS" table, lets skip it.
// one comes from an "actual TS" table, lets skip it.
if ((tid == 0x4F || tid == 0x60 || tid == 0x61) && (pEvent->GetTableID() == 0x4E || pEvent->GetTableID() == 0x50 || pEvent->GetTableID() == 0x51))
continue;
}
@ -920,6 +1010,25 @@ const cSchedules *cSIProcessor::Schedules(cMutexLock &MutexLock)
return NULL;
}
bool cSIProcessor::Read(FILE *f)
{
bool OwnFile = f == NULL;
if (OwnFile) {
const char *FileName = GetEpgDataFileName();
if (access(FileName, R_OK) == 0) {
dsyslog(LOG_INFO, "reading EPG data from %s", FileName);
if ((f = fopen(FileName, "r")) == NULL) {
LOG_ERROR;
return false;
}
}
}
bool result = cSchedules::Read(f);
if (OwnFile)
fclose(f);
return result;
}
void cSIProcessor::SetEpgDataFileName(const char *FileName)
{
epgDataFileName = NULL;

10
eit.h
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.h 1.14 2002/02/23 13:51:31 kls Exp $
* $Id: eit.h 1.15 2002/02/23 15:30:25 kls Exp $
***************************************************************************/
#ifndef __EIT_H
@ -72,6 +72,7 @@ public:
int GetChannelNumber(void) const { return nChannelNumber; }
void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
void Dump(FILE *f, const char *Prefix = "") const;
static bool Read(FILE *f, cSchedule *Schedule);
void FixEpgBugs(void);
};
@ -92,6 +93,7 @@ protected:
cSchedule(unsigned short servid = 0);
public:
~cSchedule();
cEventInfo *AddEvent(cEventInfo *EventInfo);
const cEventInfo *GetPresentEvent(void) const;
const cEventInfo *GetFollowingEvent(void) const;
unsigned short GetServiceID(void) const;
@ -100,15 +102,17 @@ public:
const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
int NumEvents(void) const { return Events.Count(); }
void Dump(FILE *f, const char *Prefix = "") const;
static bool Read(FILE *f, cSchedules *Schedules);
};
class cSchedules : public cList<cSchedule> {
friend class cSchedule;
friend class cSIProcessor;
private:
const cSchedule *pCurrentSchedule;
unsigned short uCurrentServiceID;
protected:
bool SetCurrentServiceID(unsigned short servid);
const cSchedule *SetCurrentServiceID(unsigned short servid);
void Cleanup();
public:
cSchedules(void);
@ -116,6 +120,7 @@ public:
const cSchedule *GetSchedule(unsigned short servid) const;
const cSchedule *GetSchedule(void) const;
void Dump(FILE *f, const char *Prefix = "") const;
static bool Read(FILE *f);
};
typedef struct sip_filter {
@ -150,6 +155,7 @@ public:
// Caller must provide a cMutexLock which has to survive the entire
// time the returned cSchedules is accessed. Once the cSchedules is no
// longer used, the cMutexLock must be destroyed.
static bool Read(FILE *f = NULL);
void SetStatus(bool On);
bool SetUseTSTime(bool use);
bool SetCurrentServiceID(unsigned short servid);

5
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.95 2002/02/10 15:12:43 kls Exp $
* $Id: vdr.c 1.96 2002/02/23 16:35:36 kls Exp $
*/
#include <getopt.h>
@ -35,6 +35,7 @@
#ifdef DVDSUPPORT
#include "dvd.h"
#endif //DVDSUPPORT
#include "eit.h"
#include "i18n.h"
#include "interface.h"
#include "menu.h"
@ -286,6 +287,8 @@ int main(int argc, char *argv[])
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB);
cSIProcessor::Read();
Channels.SwitchTo(Setup.CurrentChannel);
cDvbApi::PrimaryDvbApi->SetVolume(Setup.CurrentVolume, true);