summaryrefslogtreecommitdiff
path: root/epg.c
diff options
context:
space:
mode:
Diffstat (limited to 'epg.c')
-rw-r--r--epg.c159
1 files changed, 116 insertions, 43 deletions
diff --git a/epg.c b/epg.c
index 19f1c7f..88d9ee3 100644
--- a/epg.c
+++ b/epg.c
@@ -7,10 +7,12 @@
* Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
*
- * $Id: epg.c 1.4 2004/01/09 15:22:18 kls Exp $
+ * $Id: epg.c 1.13 2004/02/22 14:41:37 kls Exp kls $
*/
#include "epg.h"
+#include "libsi/si.h"
+#include "timers.h"
#include <ctype.h>
#include <time.h>
@@ -22,13 +24,13 @@ cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID)
eventID = EventID;
tableID = 0;
version = 0xFF; // actual version numbers are 0..31
- isPresent = isFollowing = false;
+ runningStatus = 0;
title = NULL;
shortText = NULL;
description = NULL;
startTime = 0;
duration = 0;
- channelNumber = 0;
+ vps = 0;
}
cEvent::~cEvent()
@@ -38,6 +40,12 @@ cEvent::~cEvent()
free(description);
}
+bool cEvent::operator< (const cListObject &ListObject)
+{
+ cEvent *e = (cEvent *)&ListObject;
+ return startTime < e->startTime;
+}
+
void cEvent::SetEventID(u_int16_t EventID)
{
eventID = EventID;
@@ -53,14 +61,9 @@ void cEvent::SetVersion(uchar Version)
version = Version;
}
-void cEvent::SetIsPresent(bool IsPresent)
+void cEvent::SetRunningStatus(int RunningStatus)
{
- isPresent = IsPresent;
-}
-
-void cEvent::SetIsFollowing(bool IsFollowing)
-{
- isFollowing = IsFollowing;
+ runningStatus = RunningStatus;
}
void cEvent::SetTitle(const char *Title)
@@ -88,6 +91,20 @@ void cEvent::SetDuration(int Duration)
duration = Duration;
}
+void cEvent::SetVps(time_t Vps)
+{
+ vps = Vps;
+}
+
+bool cEvent::HasTimer(void) const
+{
+ for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
+ if (t->Event() == this)
+ return true;
+ }
+ return false;
+}
+
const char *cEvent::GetDateString(void) const
{
static char buf[25];
@@ -113,6 +130,14 @@ const char *cEvent::GetEndTimeString(void) const
return buf;
}
+const char *cEvent::GetVpsString(void) const
+{
+ static char buf[25];
+ struct tm tm_r;
+ strftime(buf, sizeof(buf), "%d.%m %R", localtime_r(&vps, &tm_r));
+ return buf;
+}
+
void cEvent::Dump(FILE *f, const char *Prefix) const
{
if (startTime + duration >= time(NULL)) {
@@ -123,6 +148,8 @@ void cEvent::Dump(FILE *f, const char *Prefix) const
fprintf(f, "%sS %s\n", Prefix, shortText);
if (!isempty(description))
fprintf(f, "%sD %s\n", Prefix, description);
+ if (vps)
+ fprintf(f, "%sV %ld\n", Prefix, vps);
fprintf(f, "%se\n", Prefix);
}
}
@@ -162,6 +189,9 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
case 'D': if (Event)
Event->SetDescription(t);
break;
+ case 'V': if (Event)
+ Event->SetVps(atoi(t));
+ break;
case 'e': Event = NULL;
break;
case 'c': // to keep things simple we react on 'c' here
@@ -175,7 +205,7 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
return false;
}
-#define MAXEPGBUGFIXSTATS 7
+#define MAXEPGBUGFIXSTATS 8
#define MAXEPGBUGFIXCHANS 100
struct tEpgBugFixStats {
int hits;
@@ -257,6 +287,13 @@ void cEvent::FixEpgBugs(void)
strreplace(title, '\n', ' ');
strreplace(shortText, '\n', ' ');
strreplace(description, '\n', ' ');
+ // Same for control characters:
+ strreplace(title, '\x86', ' ');
+ strreplace(title, '\x87', ' ');
+ strreplace(shortText, '\x86', ' ');
+ strreplace(shortText, '\x87', ' ');
+ strreplace(description, '\x86', ' ');
+ strreplace(description, '\x87', ' ');
if (Setup.EPGBugfixLevel == 0)
return;
@@ -397,6 +434,20 @@ void cEvent::FixEpgBugs(void)
}
}
+ // Some channels put the same information into ShortText and Description.
+ // In that case we delete one of them:
+ if (shortText && description && strcmp(shortText, description) == 0) {
+ if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) {
+ free(shortText);
+ shortText = NULL;
+ }
+ else {
+ free(description);
+ description = NULL;
+ }
+ EpgBugFixStat(7, ChannelID());
+ }
+
// Some channels use the ` ("backtick") character, where a ' (single quote)
// would be normally used. Actually, "backticks" in normal text don't make
// much sense, so let's replace them:
@@ -411,7 +462,6 @@ void cEvent::FixEpgBugs(void)
cSchedule::cSchedule(tChannelID ChannelID)
{
channelID = ChannelID;
- present = following = NULL;
}
cEvent *cSchedule::AddEvent(cEvent *Event)
@@ -420,26 +470,30 @@ cEvent *cSchedule::AddEvent(cEvent *Event)
return Event;
}
-const cEvent *cSchedule::GetPresentEvent(void) const
-{
- return GetEventAround(time(NULL));
-}
-
-const cEvent *cSchedule::GetFollowingEvent(void) const
+const cEvent *cSchedule::GetPresentEvent(bool CheckRunningStatus) const
{
const cEvent *pe = NULL;
time_t now = time(NULL);
- time_t delta = INT_MAX;
for (cEvent *p = events.First(); p; p = events.Next(p)) {
- time_t dt = p->StartTime() - now;
- if (dt > 0 && dt < delta) {
- delta = dt;
+ if (p->StartTime() <= now && now < p->StartTime() + p->Duration()) {
pe = p;
+ if (!CheckRunningStatus)
+ break;
}
+ if (CheckRunningStatus && p->RunningStatus() >= SI::RunningStatusPausing)
+ return p;
}
return pe;
}
+const cEvent *cSchedule::GetFollowingEvent(bool CheckRunningStatus) const
+{
+ const cEvent *p = GetPresentEvent(CheckRunningStatus);
+ if (p)
+ p = events.Next(p);
+ return p;
+}
+
const cEvent *cSchedule::GetEvent(u_int16_t EventID, time_t StartTime) const
{
// Returns either the event info with the given EventID or, if that one can't
@@ -468,22 +522,14 @@ const cEvent *cSchedule::GetEventAround(time_t Time) const
return pe;
}
-bool cSchedule::SetPresentEvent(cEvent *Event)
-{
- if (present)
- present->SetIsPresent(false);
- present = Event;
- present->SetIsPresent(true);
- return true;
-}
-
-bool cSchedule::SetFollowingEvent(cEvent *Event)
+void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus)
{
- if (following)
- following->SetIsFollowing(false);
- following = Event;
- following->SetIsFollowing(true);
- return true;
+ for (cEvent *p = events.First(); p; p = events.Next(p)) {
+ if (p == Event)
+ p->SetRunningStatus(RunningStatus);
+ else if (RunningStatus >= SI::RunningStatusPausing && p->RunningStatus() > SI::RunningStatusNotRunning)
+ p->SetRunningStatus(SI::RunningStatusNotRunning);
+ }
}
void cSchedule::ResetVersions(void)
@@ -492,6 +538,11 @@ void cSchedule::ResetVersions(void)
p->SetVersion(0xFF);
}
+void cSchedule::Sort(void)
+{
+ events.Sort();
+}
+
void cSchedule::Cleanup(void)
{
Cleanup(time(NULL));
@@ -504,20 +555,41 @@ void cSchedule::Cleanup(time_t Time)
Event = events.Get(a);
if (!Event)
break;
- if (Event->StartTime() + Event->Duration() + 3600 < Time) { // adding one hour for safety
+ if (!Event->HasTimer() && Event->StartTime() + Event->Duration() + Setup.EPGLinger * 60 + 3600 < Time) { // adding one hour for safety
events.Del(Event);
a--;
}
}
}
-void cSchedule::Dump(FILE *f, const char *Prefix) const
+void cSchedule::Dump(FILE *f, const char *Prefix, eDumpMode DumpMode, time_t AtTime) const
{
cChannel *channel = Channels.GetByChannelID(channelID, true);
if (channel) {
fprintf(f, "%sC %s %s\n", Prefix, channel->GetChannelID().ToString(), channel->Name());
- for (cEvent *p = events.First(); p; p = events.Next(p))
- p->Dump(f, Prefix);
+ const cEvent *p;
+ switch (DumpMode) {
+ case dmAll: {
+ for (p = events.First(); p; p = events.Next(p))
+ p->Dump(f, Prefix);
+ }
+ break;
+ case dmPresent: {
+ if ((p = GetPresentEvent()) != NULL)
+ p->Dump(f, Prefix);
+ }
+ break;
+ case dmFollowing: {
+ if ((p = GetFollowingEvent()) != NULL)
+ p->Dump(f, Prefix);
+ }
+ break;
+ case dmAtTime: {
+ if ((p = GetEventAround(AtTime)) != NULL)
+ p->Dump(f, Prefix);
+ }
+ break;
+ }
fprintf(f, "%sc\n", Prefix);
}
}
@@ -539,6 +611,7 @@ bool cSchedule::Read(FILE *f, cSchedules *Schedules)
if (p) {
if (!cEvent::Read(f, p))
return false;
+ p->Sort();
}
}
else {
@@ -640,13 +713,13 @@ bool cSchedules::ClearAll(void)
return false;
}
-bool cSchedules::Dump(FILE *f, const char *Prefix)
+bool cSchedules::Dump(FILE *f, const char *Prefix, eDumpMode DumpMode, time_t AtTime)
{
cSchedulesLock SchedulesLock;
cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
if (s) {
for (cSchedule *p = s->First(); p; p = s->Next(p))
- p->Dump(f, Prefix);
+ p->Dump(f, Prefix, DumpMode, AtTime);
return true;
}
return false;