diff --git a/HISTORY b/HISTORY index 45202255..ecbeb164 100644 --- a/HISTORY +++ b/HISTORY @@ -4395,3 +4395,9 @@ Video Disk Recorder Revision History - The "Blue" key in the "Timers" menu now displays the EPG info of the event the selected timer will record (if available). The "On/Off" function has been shifted to the "Red" button. Editing a timer is done by pressing "Ok". +- When determining which event a timer is going to record, all available events + in the future are now taken into account (no more limit to 4 hours in the + future). This has been done so that the event info is available in the "Timers" + menu when pressing the "Blue" button. In order to avoid unnecessary work, each + timer now has its own timestamp to control whether its schedule has changed + since the last time its event has been set. diff --git a/menu.c b/menu.c index ecc5225f..d15c017f 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.421 2006/02/25 15:00:09 kls Exp $ + * $Id: menu.c 1.422 2006/02/25 15:41:40 kls Exp $ */ #include "menu.h" @@ -691,6 +691,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key) if (addIfConfirmed) Timers.Add(timer); timer->Matches(); + timer->SetEventFromSchedule(); Timers.SetModified(); isyslog("timer %s %s (%s)", *timer->ToDescr(), addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive"); addIfConfirmed = false; @@ -828,6 +829,7 @@ eOSState cMenuTimers::OnOff(void) cTimer *timer = CurrentTimer(); if (timer) { timer->OnOff(); + timer->SetEventFromSchedule(); RefreshCurrent(); DisplayCurrent(true); if (timer->FirstDay()) @@ -896,7 +898,7 @@ eOSState cMenuTimers::ProcessKey(eKeys Key) if (state == osUnknown) { switch (Key) { case kOk: return Edit(); - case kRed: return OnOff(); + case kRed: state = OnOff(); break; // must go through SetHelpKeys()! case kGreen: return New(); case kYellow: return Delete(); case kBlue: return Info(); diff --git a/timers.c b/timers.c index ed5387de..b5e77cdb 100644 --- a/timers.c +++ b/timers.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.47 2006/02/25 10:44:50 kls Exp $ + * $Id: timers.c 1.48 2006/02/25 15:57:56 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) @@ -50,6 +51,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) cTimer::cTimer(const cEvent *Event) { startTime = stopTime = 0; + lastSetEvent = event->Schedule() ? event->Schedule()->Modified() : 0; recording = pending = inVpsMargin = false; flags = tfActive; if (Event->Vps() && Setup.UseVps) @@ -91,6 +93,7 @@ cTimer& cTimer::operator= (const cTimer &Timer) if (aux) aux = strdup(aux); event = NULL; + lastSetEvent = 0; return *this; } @@ -423,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 && !Event->IsRunning()) + Event = NULL; + SetEvent(Event); + } + } + lastSetEvent = time(NULL); +} + void cTimer::SetEvent(const cEvent *Event) { if (event != Event) { //XXX TODO check event data, too??? @@ -488,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) @@ -503,7 +555,7 @@ void cTimer::OnOff(void) Skip(); else SetFlags(tfActive); - event = NULL; + SetEvent(NULL); Matches(); // refresh start and end time } @@ -591,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) @@ -603,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); } } } diff --git a/timers.h b/timers.h index 7da77014..f49b48dd 100644 --- a/timers.h +++ b/timers.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.h 1.25 2006/02/25 10:42:10 kls Exp $ + * $Id: timers.h 1.26 2006/02/25 15:05:09 kls Exp $ */ #ifndef __TIMERS_H @@ -28,6 +28,7 @@ class cTimer : public cListObject { friend class cMenuEditTimer; private: mutable time_t startTime, stopTime; + time_t lastSetEvent; bool recording, pending, inVpsMargin; uint flags; cChannel *channel; @@ -77,6 +78,7 @@ public: bool Expired(void) const; time_t StartTime(void) const; time_t StopTime(void) const; + void SetEventFromSchedule(const cSchedules *Schedules = NULL); void SetEvent(const cEvent *Event); void SetRecording(bool Recording); void SetPending(bool Pending);