Improved setting events to timers

This commit is contained in:
Klaus Schmidinger 2006-02-25 15:57:56 +01:00
parent 8650649b18
commit 8dec381664
4 changed files with 71 additions and 49 deletions

View File

@ -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.

6
menu.c
View File

@ -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();

104
timers.c
View File

@ -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);
}
}
}

View File

@ -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);