diff options
Diffstat (limited to 'timers.c')
-rw-r--r-- | timers.c | 133 |
1 files changed, 71 insertions, 62 deletions
@@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.46 2006/02/03 15:20:14 kls Exp $ + * $Id: timers.c 1.50 2006/02/26 10:50:47 kls Exp $ */ #include "timers.h" @@ -23,6 +23,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) { startTime = stopTime = 0; + lastSetEvent = 0; recording = pending = inVpsMargin = false; flags = tfNone; if (Instant) @@ -41,7 +42,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; *file = 0; - summary = NULL; + aux = NULL; event = NULL; if (Instant && channel) snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); @@ -50,6 +51,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) cTimer::cTimer(const cEvent *Event) { startTime = stopTime = 0; + lastSetEvent = 0; recording = pending = inVpsMargin = false; flags = tfActive; if (Event->Vps() && Setup.UseVps) @@ -76,21 +78,22 @@ cTimer::cTimer(const cEvent *Event) const char *Title = Event->Title(); if (!isempty(Title)) strn0cpy(file, Event->Title(), sizeof(file)); - summary = NULL; - event = Event; + aux = NULL; + event = NULL; // let SetEvent() be called to get a log message } cTimer::~cTimer() { - free(summary); + free(aux); } cTimer& cTimer::operator= (const cTimer &Timer) { memcpy(this, &Timer, sizeof(*this)); - if (summary) - summary = strdup(summary); + if (aux) + aux = strdup(aux); event = NULL; + lastSetEvent = 0; return *this; } @@ -109,9 +112,7 @@ cString cTimer::ToText(bool UseChannelID) { char *buffer; strreplace(file, ':', '|'); - strreplace(summary, '\n', '|'); - asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, summary ? summary : ""); - strreplace(summary, '|', '\n'); + asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, aux ? aux : ""); strreplace(file, '|', ':'); return cString(buffer, true); } @@ -226,8 +227,8 @@ bool cTimer::Parse(const char *s) char *channelbuffer = NULL; char *daybuffer = NULL; char *filebuffer = NULL; - free(summary); - summary = NULL; + free(aux); + aux = NULL; //XXX Apparently sscanf() doesn't work correctly if the last %a argument //XXX results in an empty string (this first occured when the EIT gathering //XXX was put into a separate thread - don't know why this happens... @@ -244,17 +245,16 @@ bool cTimer::Parse(const char *s) s = s2; } bool result = false; - if (8 <= sscanf(s, "%u :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &summary)) { + if (8 <= sscanf(s, "%u :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &aux)) { ClrFlags(tfRecording); - if (summary && !*skipspace(summary)) { - free(summary); - summary = NULL; + if (aux && !*skipspace(aux)) { + free(aux); + aux = NULL; } //TODO add more plausibility checks result = ParseDay(daybuffer, day, weekdays); strn0cpy(file, filebuffer, MaxFileName); strreplace(file, '|', ':'); - strreplace(summary, '|', '\n'); if (isnumber(channelbuffer)) channel = Channels.GetByNumber(atoi(channelbuffer)); else @@ -426,6 +426,55 @@ time_t cTimer::StopTime(void) const return stopTime; } +#define EPGLIMITPAST (2 * 3600) // time in seconds in the past within which EPG events will be taken into consideration + +void cTimer::SetEventFromSchedule(const cSchedules *Schedules) +{ + cSchedulesLock SchedulesLock; + if (!Schedules) { + lastSetEvent = 0; // forces setting the event, even if the schedule hasn't been modified + if (!(Schedules = cSchedules::Schedules(SchedulesLock))) + return; + } + const cSchedule *Schedule = Schedules->GetSchedule(Channel()); + if (Schedule) { + if (!lastSetEvent || Schedule->Modified() >= lastSetEvent) { + const cEvent *Event = NULL; + int Overlap = 0; + int Distance = INT_MIN; + time_t now = time(NULL); + for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { + if (e->EndTime() < now - EPGLIMITPAST) + continue; // skip old events + int overlap = 0; + Matches(e, &overlap); + if (overlap && overlap >= Overlap) { + int distance = 0; + if (now < e->StartTime()) + distance = e->StartTime() - now; + else if (now > e->EndTime()) + distance = e->EndTime() - now; + if (Event && overlap == Overlap) { + if (Overlap > FULLMATCH) { // this means VPS + if (abs(Distance) < abs(distance)) + break; // we've already found the closest VPS event + } + else if (e->Duration() <= Event->Duration()) + continue; // if overlap is the same, we take the longer event + } + Overlap = overlap; + Distance = distance; + Event = e; + } + } + if (Event && Event->EndTime() < now - EXPIRELATENCY && Overlap > FULLMATCH && !Event->IsRunning()) + Event = NULL; + SetEvent(Event); + } + } + lastSetEvent = time(NULL); +} + void cTimer::SetEvent(const cEvent *Event) { if (event != Event) { //XXX TODO check event data, too??? @@ -491,7 +540,7 @@ bool cTimer::HasFlags(uint Flags) const void cTimer::Skip(void) { day = IncDay(SetTime(StartTime(), 0), 1); - event = NULL; + SetEvent(NULL); } void cTimer::OnOff(void) @@ -506,7 +555,7 @@ void cTimer::OnOff(void) Skip(); else SetFlags(tfActive); - event = NULL; + SetEvent(NULL); Matches(); // refresh start and end time } @@ -594,9 +643,6 @@ bool cTimers::Modified(int &State) return Result; } -#define EPGLIMITPAST (2 * 3600) // time in seconds around now, within which EPG events will be taken into consideration -#define EPGLIMITFUTURE (4 * 3600) - void cTimers::SetEvents(void) { if (time(NULL) - lastSetEvents < 5) @@ -606,46 +652,9 @@ void cTimers::SetEvents(void) if (Schedules) { if (!lastSetEvents || Schedules->Modified() >= lastSetEvents) { for (cTimer *ti = First(); ti; ti = Next(ti)) { - const cSchedule *Schedule = Schedules->GetSchedule(ti->Channel()); - if (Schedule) { - if (!lastSetEvents || Schedule->Modified() >= lastSetEvents) { - const cEvent *Event = NULL; - int Overlap = 0; - int Distance = INT_MIN; - time_t now = time(NULL); - for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { - if (cRemote::HasKeys()) - return; // react immediately on user input - if (e->EndTime() < now - EPGLIMITPAST) - continue; // skip old events - if (e->StartTime() > now + EPGLIMITFUTURE) - break; // no need to process events too far in the future - int overlap = 0; - ti->Matches(e, &overlap); - if (overlap && overlap >= Overlap) { - int distance = 0; - if (now < e->StartTime()) - distance = e->StartTime() - now; - else if (now > e->EndTime()) - distance = e->EndTime() - now; - if (Event && overlap == Overlap) { - if (Overlap > FULLMATCH) { // this means VPS - if (abs(Distance) < abs(distance)) - break; // we've already found the closest VPS event - } - else if (e->Duration() <= Event->Duration()) - continue; // if overlap is the same, we take the longer event - } - Overlap = overlap; - Distance = distance; - Event = e; - } - } - if (Event && Event->EndTime() < now - EXPIRELATENCY && !Event->IsRunning()) - Event = NULL; - ti->SetEvent(Event); - } - } + if (cRemote::HasKeys()) + return; // react immediately on user input + ti->SetEventFromSchedule(Schedules); } } } |