To avoid problems with very short events, non-VPS pattern timers now spawn timers for all matching events that would start while the first one is still recording

This commit is contained in:
Klaus Schmidinger 2021-04-13 13:54:00 +02:00
parent cd834c79ba
commit b2fb654bb3
4 changed files with 35 additions and 26 deletions

View File

@ -9652,3 +9652,5 @@ Video Disk Recorder Revision History
was "remote").
- Now adjusting spawned timers before setting events to timers.
- Fixed dropping outdated events.
- To avoid problems with very short events, non-VPS pattern timers now spawn timers for all
matching events that would start while the first one is still recording.

6
MANUAL
View File

@ -540,9 +540,9 @@ The following rules apply to pattern timers:
with the given start/stop time. Overlapping events are recorded in full,
even if they extend outside the given start/stop interval.
- In order to actually record an event, a pattern timer "spawns" a separate timer
that does the recording. At most two timers are spawned from a pattern timer at
any given time, one for the next upcoming matching event, and one for
the event immediately following that one, in case it also matches.
that does the recording. If there are matching events that would start while
the first spawned timer is still recording (due to the start/stop margins), timers
for those events are also spawned.
- Spawned timers are marked with the flag tfSpawned.
- Spawned timers take the Priority, Lifetime and VPS settings from the pattern timer.
- The special pattern "*" matches every event. So a timer with

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 5.11 2021/04/10 11:32:50 kls Exp $
* $Id: timers.c 5.12 2021/04/13 13:54:00 kls Exp $
*/
#include "timers.h"
@ -708,7 +708,7 @@ void cTimer::SetId(int Id)
id = Id;
}
void cTimer::SpawnPatternTimer(const cEvent *Event, cTimers *Timers)
cTimer *cTimer::SpawnPatternTimer(const cEvent *Event, cTimers *Timers)
{
cString FileName = MakePatternFileName(Pattern(), Event->Title(), Event->ShortText(), File());
isyslog("spawning timer %s for event %s", *ToDescr(), *Event->ToDescr());
@ -718,6 +718,7 @@ void cTimer::SpawnPatternTimer(const cEvent *Event, cTimers *Timers)
t->SetFlags(tfAvoid);
Timers->Add(t);
HandleRemoteTimerModifications(t);
return t;
}
bool cTimer::SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers)
@ -727,30 +728,36 @@ bool cTimer::SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers)
if (Schedule && Schedule->Events()->First()) {
if (Schedule->Modified(scheduleStateSpawn)) {
time_t Now = time(NULL);
// Find the first event that matches this pattern timer and either already has a spawned
// timer, or has not yet ended:
for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) {
if (Matches(e) != tmNone) {
bool CheckThis = false;
bool CheckNext = false;
if (Timers->GetTimerForEvent(e, tfSpawned)) // a matching event that already has a spawned timer
CheckNext = true;
else if (e->EndTime() > Now) { // only look at events that have not yet ended
CheckThis = true;
CheckNext = true;
}
if (CheckThis) {
SpawnPatternTimer(e, Timers);
const cTimer *Timer = Timers->GetTimerForEvent(e, tfSpawned); // a matching event that already has a spawned timer
if (!Timer && e->EndTime() > Now) { // only look at events that have not yet ended
Timer = SpawnPatternTimer(e, Timers);
TimersSpawned = true;
}
if (CheckNext) {
// We also check the event immediately following this one:
e = Schedule->Events()->Next(e);
if (e && !Timers->GetTimerForEvent(e, tfSpawned) && Matches(e) != tmNone) {
SpawnPatternTimer(e, Timers);
TimersSpawned = true;
}
}
if (CheckThis || CheckNext)
if (Timer) {
// Check all following matching events that would start while the first timer
// is still recording:
bool UseVps = Timer->HasFlags(tfVps);
time_t Limit = Timer->StopTime() + EXPIRELATENCY;
if (!UseVps)
Limit += Setup.MarginStart * 60;
for (e = Schedule->Events()->Next(e); e; e = Schedule->Events()->Next(e)) {
if (e->StartTime() <= Limit) {
if (!Timers->GetTimerForEvent(e, tfSpawned) && Matches(e) != tmNone) {
SpawnPatternTimer(e, Timers);
TimersSpawned = true;
}
if (UseVps)
break; // with VPS we only need to check the event immediately following the first one
}
else
break; // no need to check events that are too far in the future
}
break;
}
}
}
}

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 5.5 2021/04/10 10:09:50 kls Exp $
* $Id: timers.h 5.6 2021/04/13 13:54:00 kls Exp $
*/
#ifndef __TIMERS_H
@ -99,7 +99,7 @@ public:
time_t StartTime(void) const;
time_t StopTime(void) const;
void SetId(int Id);
void SpawnPatternTimer(const cEvent *Event, cTimers *Timers);
cTimer *SpawnPatternTimer(const cEvent *Event, cTimers *Timers);
bool SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers);
bool AdjustSpawnedTimer(void);
void TriggerRespawn(void);