43 time_t t = time(NULL);
45 struct tm *now = localtime_r(&t, &tm_r);
48 start = now->tm_hour * 100 + now->tm_min;
53 if (
const cEvent *
Event = Schedule->GetPresentEvent()) {
64 tstart -= MarginStart;
68 struct tm *time = localtime_r(&tstart, &tm_r);
69 start = time->tm_hour * 100 + time->tm_min;
70 time = localtime_r(&tstop, &tm_r);
71 stop = time->tm_hour * 100 + time->tm_min;
94 if (strcmp(Pattern,
"*") == 0) {
109 nt.
Set(
const_cast<char *
>(Pattern + strlen(Pattern) - 1));
110 if (AnchorBegin && AnchorEnd) {
111 if (strcmp(Title, Pattern) == 0) {
121 else if (AnchorBegin) {
122 if (strstr(Title, Pattern) == Title) {
128 *After =
cString(Title + strlen(Pattern));
132 else if (AnchorEnd) {
135 *Before =
cString(Title, Title + strlen(Title) - strlen(Pattern));
143 else if (
const char *p = strstr(Title, Pattern)) {
149 *After =
cString(p + strlen(Pattern));
158 if (!Pattern || !Title || !File)
163 if (
MatchPattern(Pattern, Title, &Before, &Match, &After)) {
164 char *Result = strdup(File);
201 tstart -= MarginStart;
205 struct tm *time = localtime_r(&tstart, &tm_r);
208 start = time->tm_hour * 100 + time->tm_min;
209 time = localtime_r(&tstop, &tm_r);
210 stop = time->tm_hour * 100 + time->tm_min;
235 event->DecNumTimers();
242 if (&Timer !=
this) {
261 aux = Timer.
aux ? strdup(Timer.
aux) : NULL;
265 event->DecNumTimers();
280 MarginStart =
max(0,
min(MarginStart, e->Duration() - 60));
282 MarginStop =
max(0,
min(MarginStop, e->Duration() - 60));
315 cString buffer =
cString::sprintf(
"%u:%s:%s:%04d:%04d:%d:%d:%s:%s",
flags, UseChannelID ? *
Channel()->GetChannelID().ToString() : *
itoa(
Channel()->Number()), *
PrintDay(
day,
weekdays,
true),
start,
stop,
priority,
lifetime, *
PatternAndFile(),
aux ?
aux :
"");
328 return (t / 100 * 60 + t % 100) * 60;
345 const char *a = strchr(s,
'@');
346 const char *d = a ? a + 1 : isdigit(*s) ? s : NULL;
348 if (strlen(d) == 10) {
350 if (3 == sscanf(d,
"%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
351 tm_r.tm_year -= 1900;
353 tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
363 int day = strtol(d, &tail, 10);
364 if (tail && *tail || day < 1 || day > 31)
366 time_t t = time(NULL);
367 int DaysToCheck = 61;
368 for (
int i = -1; i <= DaysToCheck; i++) {
377 if (a || !isdigit(*s)) {
378 if ((a && a - s == 7) || strlen(s) == 7) {
379 for (
const char *p = s + 6; p >= s; p--) {
392#define DAYBUFFERSIZE 64
397 const char *w =
trNOOP(
"MTWTFSS");
398 if (!SingleByteChars)
403 for (
int i = 0; i < sl; i++)
417 localtime_r(&
Day, &tm_r);
418 b += strftime(b,
DAYBUFFERSIZE - (b - buffer),
"%Y-%m-%d", &tm_r);
436 char *channelbuffer = NULL;
437 char *daybuffer = NULL;
438 char *filebuffer = NULL;
449 while (l2 > 0 && isspace(s[l2 - 1]))
451 if (s[l2 - 1] ==
':') {
452 s2 =
MALLOC(
char, l2 + 3);
453 strcat(
strn0cpy(s2, s, l2 + 1),
" \n");
457 if (8 <= sscanf(s,
"%u :%m[^:]:%m[^:]:%d :%d :%d :%d :%m[^:\n]:%m[^\n]", &
flags, &channelbuffer, &daybuffer, &
start, &
stop, &
priority, &
lifetime, &filebuffer, &
aux)) {
464 char *fb = filebuffer;
466 if (
char *p = strchr(fb,
'}')) {
479 channel = Channels->GetByNumber(atoi(channelbuffer));
483 esyslog(
"ERROR: channel %s not defined", channelbuffer);
497 return fprintf(f,
"%s\n", *
ToText(
true)) > 0;
509 return localtime_r(&t, &tm_r)->tm_mday;
515 int weekday = localtime_r(&t, &tm_r)->tm_wday;
516 return weekday == 0 ? 6 : weekday - 1;
527 tm tm = *localtime_r(&t, &tm_r);
539 tm tm = *localtime_r(&t, &tm_r);
540 tm.tm_hour = SecondsFromMidnight / 3600;
541 tm.tm_min = (SecondsFromMidnight % 3600) / 60;
542 tm.tm_sec = SecondsFromMidnight % 60;
558#define EITPRESENTFOLLOWINGRATE 10
568 int length = end - begin;
579 for (
int i = -1; i <= 7; i++) {
586 if ((!
day || a >=
day) && t < b) {
610 if (Margin || !Directly) {
615 return event->IsRunning(
true);
622 if (!Margin && !Directly) {
636#define FULLMATCH 1000
692#define EXPIRELATENCY 60
700 return ExpireTime <= time(NULL);
723 return event->StartTime();
734 return event->EndTime();
741#define EPGLIMITBEFORE (1 * 3600)
742#define EPGLIMITAFTER (1 * 3600)
764 bool TimersSpawned =
false;
768 time_t Now = time(NULL);
774 if (!Timer && e->EndTime() > Now) {
776 TimersSpawned =
true;
788 if (e->StartTime() <= Limit) {
791 TimersSpawned =
true;
805 return TimersSpawned;
819 tstart -= MarginStart;
828 struct tm *time = localtime_r(&tstart, &tm_r);
830 SetStart(time->tm_hour * 100 + time->tm_min);
831 time = localtime_r(&tstop, &tm_r);
832 SetStop(time->tm_hour * 100 + time->tm_min);
851 const_cast<cSchedule *
>(Schedule)->SetModified();
868 if (e->StartTime()) {
886 if (e->EndTime() < TimeFrameBegin)
888 if (e->StartTime() > TimeFrameEnd)
892 if (overlap && overlap >= Overlap) {
910 event->DecNumTimers();
1054 Timers->SetExplicitModify();
1059 Timers->SetModified();
1074 if (ti->Id() == Id) {
1075 if (!Remote && !ti->Remote() || Remote && ti->Remote() && strcmp(Remote, ti->Remote()) == 0)
1085 if (!ti->Remote() &&
1086 ti->Channel() == Timer->
Channel() &&
1087 (ti->WeekDays() && ti->WeekDays() == Timer->
WeekDays() || !ti->WeekDays() && ti->Day() == Timer->
Day()) &&
1088 ti->Start() == Timer->
Start() &&
1089 ti->Stop() == Timer->
Stop())
1097 static int LastPending = -1;
1100 if (!ti->Remote() && !ti->Recording() && ti->Matches(t)) {
1101 if (ti->Pending()) {
1102 if (ti->Index() > LastPending) {
1103 LastPending = ti->
Index();
1138 if (ti->Event() == Event && ti->Local() && ti->HasFlags(Flags))
1149 if (!ti->Remote() && ti->Recording())
1150 n =
max(n, ti->Priority());
1159 if (!ti->Remote() && !ti->IsPatternTimer()) {
1161 if ((ti->HasFlags(
tfActive)) && (!t0 || ti->
StopTime() > time(NULL) && ti->Compare(*t0) < 0))
1201 if (Timer->Channel() == Channel)
1209 bool TimersModified =
false;
1211 if (!ti->IsPatternTimer())
1214 return TimersModified;
1219 bool TimersModified =
false;
1221 if (ti->IsPatternTimer() && ti->Local()) {
1223 TimersModified |= ti->SpawnPatternTimers(Schedules,
this);
1226 return TimersModified;
1231 bool TimersModified =
false;
1235 TimersModified |= ti->AdjustSpawnedTimer();
1238 return TimersModified;
1241#define DELETE_EXPIRED_TIMEOUT 30
1247 bool TimersModified =
false;
1256 TimersModified =
true;
1261 return TimersModified;
1266 bool Result =
false;
1267 if (!ServerName || !RemoteTimers || RemoteTimers->
Size() == 0) {
1272 if (Timer->
Remote() && (!ServerName || strcmp(Timer->
Remote(), ServerName) == 0)) {
1283 if (ti->Remote() && strcmp(ti->Remote(), ServerName) == 0)
1291 int sr = RemoteTimers->
Size();
1296 int nl = atoi(tl[il]);
1299 int nr = atoi((*RemoteTimers)[ir]);
1301 AddTimer = DelTimer = nl;
1311 AddTimer = atoi((*RemoteTimers)[ir]);
1313 esyslog(
"ERROR: %s: error in timer settings: %s", ServerName, (*RemoteTimers)[ir]);
1320 if (AddTimer && DelTimer) {
1321 if (strcmp(tl[il], (*RemoteTimers)[ir]) != 0) {
1323 char *v = (*RemoteTimers)[ir];
1324 while (*v && *v !=
' ')
1335 esyslog(
"ERROR: %d@%s: error in timer settings: %s", DelTimer, ServerName, v);
1343 else if (AddTimer) {
1344 char *v = (*RemoteTimers)[ir];
1345 while (*v && *v !=
' ')
1348 if (Timer->
Parse(v)) {
1350 Timer->
SetId(AddTimer);
1355 esyslog(
"ERROR: %s: error in timer settings: %s", ServerName, v);
1360 else if (DelTimer) {
1368 esyslog(
"ERROR: oops while storing remote timers!");
1387 if (OldTimer->
Remote() && OldTimer->
Id()) {
1394 else if (!OldTimer || OldTimer->
Local() || !OldTimer->
Id()) {
1395 if (NewTimer->
Local()) {
1396 if (OldTimer && OldTimer->
Id())
1404 int RemoteId = atoi(
SVDRPValue(Response[0]));
1407 NewTimer->
SetId(RemoteId);
1408 if (OldTimer && OldTimer->
Id()) {
1415 else if (NewTimer->
Local()) {
1422 else if (strcmp(OldTimer->
Remote(), NewTimer->
Remote()) == 0) {
1430 int RemoteId = atoi(
SVDRPValue(Response[0]));
1433 NewTimer->
SetId(RemoteId);
1445 return (*(
const cTimer **)a)->Compare(**(
const cTimer **)b);
1451 for (
const cTimer *Timer = Timers->
First(); Timer; Timer = Timers->
Next(Timer))
#define LOCK_CHANNELS_READ
const char * Name(void) const
tChannelID GetChannelID(void) const
const char * FileName(void)
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
bool Contains(const char *Title) const
const char * ShortText(void) const
cString ToDescr(void) const
time_t EndTime(void) const
int RunningStatus(void) const
bool IsRunning(bool OrAboutToStart=false) const
void IncNumTimers(void) const
time_t StartTime(void) const
tChannelID ChannelID(void) const
const char * Title(void) const
const cSchedule * Schedule(void) const
bool HasTimer(void) const
void Ins(cListObject *Object, cListObject *Before=NULL)
void Del(cListObject *Object, bool DeleteObject=true)
bool Lock(cStateKey &StateKey, bool Write=false, int TimeoutMs=0) const
Tries to get a lock on this list and returns true if successful.
void Add(cListObject *Object, cListObject *After=NULL)
cListObject * Prev(void) const
cListObject * Next(void) const
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
bool Modified(int &State) const
bool PresentSeenWithin(int Seconds) const
const cList< cEvent > * Events(void) const
const cSchedule * GetSchedule(tChannelID ChannelID) const
char NameInstantRecord[NAME_MAX+1]
cSortedTimers(const cTimers *Timers)
static void MsgTimerChange(const cTimer *Timer, eTimerChange Change)
void SortNumerically(void)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void SetAux(const char *Aux)
time_t stopTime
the time_t value calculated from 'day', 'start' and 'stop'
const char * Aux(void) const
void SetLifetime(int Lifetime)
const char * File(void) const
cString PrintFirstDay(void) const
time_t day
midnight of the day this timer shall hit, or of the first day it shall hit in case of a repeating tim...
int weekdays
bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
bool IsSingleEvent(void) const
void SetPending(bool Pending)
cTimer(bool Instant=false, bool Pause=false, const cChannel *Channel=NULL)
time_t StopTime(void) const
the stop time as given by the user
cString PatternAndFile(void) const
bool Recording(void) const
static time_t SetTime(time_t t, int SecondsFromMidnight)
void ClrFlags(uint Flags)
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater",...
void SetFile(const char *File)
void SetFlags(uint Flags)
int start
the start and stop time of this timer as given by the user,
void SetPriority(int Priority)
void SetDeferred(int Seconds)
time_t StopTimeEvent(void) const
or by the user (for normal timers)
bool AdjustSpawnedTimer(void)
void SetInVpsMargin(bool InVpsMargin)
bool IsPatternTimer(void) const
static int GetWDay(time_t t)
const char * Pattern(void) const
static cString PrintDay(time_t Day, int WeekDays, bool SingleByteChars)
void TriggerRespawn(void)
bool DayMatches(time_t t) const
void SetRemote(const char *Remote)
bool InVpsMargin(void) const
bool SetEvent(const cEvent *Event)
void InvFlags(uint Flags)
int stop
in the form hhmm, with hh (00..23) and mm (00..59) added as hh*100+mm
const cEvent * Event(void) const
static bool ParseDay(const char *s, time_t &Day, int &WeekDays)
cTimer * SpawnPatternTimer(const cEvent *Event, cTimers *Timers)
time_t StartTime(void) const
the start time as given by the user
const cChannel * Channel(void) const
void CalcMargins(int &MarginStart, int &MarginStop, const cEvent *Event)
cString ToDescr(void) const
bool SetEventFromSchedule(const cSchedules *Schedules)
void SetRecording(bool Recording)
time_t StartTimeEvent(void) const
the start/stop times as given by the event (for VPS timers), by event plus margins (for spawned non-V...
void SetPattern(const char *Pattern)
char pattern[NAME_MAX *2+1]
static int TimeToInt(int t)
time_t deferred
Matches(time_t, ...) will return false if the current time is before this value.
static int GetMDay(time_t t)
bool HasFlags(uint Flags) const
const char * Remote(void) const
cTimer & operator=(const cTimer &Timer)
void SetWeekDays(int WeekDays)
bool Matches(time_t t=0, bool Directly=false, int Margin=0) const
bool Parse(const char *s)
cString ToText(bool UseChannelID=false) const
static time_t IncDay(time_t t, int Days)
bool SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers)
static bool Load(const char *FileName)
int GetMaxPriority(void) const
Returns the maximum priority of all local timers that are currently recording.
const cTimer * UsesChannel(const cChannel *Channel) const
bool StoreRemoteTimers(const char *ServerName=NULL, const cStringList *RemoteTimers=NULL)
Stores the given list of RemoteTimers, which come from the VDR ServerName, in this list.
const cTimer * GetById(int Id, const char *Remote=NULL) const
void Add(cTimer *Timer, cTimer *After=NULL)
static cTimers * GetTimersWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for write access.
void Del(cTimer *Timer, bool DeleteObject=true)
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
const cTimer * GetTimer(const cTimer *Timer) const
const cTimer * GetMatch(time_t t) const
const cTimer * GetTimerForEvent(const cEvent *Event, eTimerFlags Flags=tfNone) const
void Ins(cTimer *Timer, cTimer *Before=NULL)
bool SpawnPatternTimers(const cSchedules *Schedules)
const cTimer * GetNextActiveTimer(void) const
bool DeleteExpired(bool Force)
bool SetEvents(const cSchedules *Schedules)
bool AdjustSpawnedTimers(void)
static int NewTimerId(void)
void Sort(__compar_fn_t Compare)
virtual void Append(T Data)
#define TIMERPATTERN_BEGIN
#define TIMERMACRO_BEFORE
#define TIMERMACRO_EPISODE
#define TIMERPATTERN_AVOID
#define LOCK_SCHEDULES_READ
#define LOCK_SCHEDULES_WRITE
@ RunningStatusNotRunning
cDoneRecordings DoneRecordingsPattern
static tChannelID FromString(const char *s)
bool ExecSVDRPCommand(const char *ServerName, const char *Command, cStringList *Response)
Sends the given SVDRP Command string to the remote VDR identified by ServerName and collects all of t...
const char * SVDRPValue(const char *s)
Returns the actual value of the given SVDRP response string, skipping the three digit reply code and ...
int SVDRPCode(const char *s)
Returns the value of the three digit reply code of the given SVDRP response string.
#define DELETE_EXPIRED_TIMEOUT
static bool RemoteTimerError(const cTimer *Timer, cString *Msg)
static cString MakePatternFileName(const char *Pattern, const char *Title, const char *Episode, const char *File)
static bool MatchPattern(const char *Pattern, const char *Title, cString *Before=NULL, cString *Match=NULL, cString *After=NULL)
#define EITPRESENTFOLLOWINGRATE
static int CompareTimers(const void *a, const void *b)
bool HandleRemoteTimerModifications(cTimer *NewTimer, cTimer *OldTimer, cString *Msg)
Performs any operations necessary to synchronize changes to a timer between peer VDR machines.
#define LOCK_TIMERS_WRITE
bool HandleRemoteTimerModifications(cTimer *NewTimer, cTimer *OldTimer=NULL, cString *Msg=NULL)
Performs any operations necessary to synchronize changes to a timer between peer VDR machines.