Go to the documentation of this file.
42 time_t t = time(NULL);
44 struct tm *now = localtime_r(&t, &tm_r);
47 start = now->tm_hour * 100 + now->tm_min;
52 if (
const cEvent *
Event = Schedule->GetPresentEvent()) {
64 struct tm *time = localtime_r(&tstart, &tm_r);
65 start = time->tm_hour * 100 + time->tm_min;
66 time = localtime_r(&tstop, &tm_r);
67 stop = time->tm_hour * 100 + time->tm_min;
107 struct tm *time = localtime_r(&tstart, &tm_r);
110 start = time->tm_hour * 100 + time->tm_min;
111 time = localtime_r(&tstop, &tm_r);
112 stop = time->tm_hour * 100 + time->tm_min;
136 event->DecNumTimers();
143 if (&Timer !=
this) {
161 aux = Timer.
aux ? strdup(Timer.
aux) : NULL;
165 event->DecNumTimers();
187 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,
file,
aux ?
aux :
"");
199 return (t / 100 * 60 + t % 100) * 60;
216 const char *a = strchr(s,
'@');
217 const char *d = a ? a + 1 : isdigit(*s) ? s : NULL;
219 if (strlen(d) == 10) {
221 if (3 == sscanf(d,
"%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
222 tm_r.tm_year -= 1900;
224 tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
234 int day = strtol(d, &tail, 10);
235 if (tail && *tail || day < 1 || day > 31)
237 time_t t = time(NULL);
238 int DaysToCheck = 61;
239 for (
int i = -1; i <= DaysToCheck; i++) {
248 if (a || !isdigit(*s)) {
249 if ((a && a - s == 7) || strlen(s) == 7) {
250 for (
const char *p = s + 6; p >= s; p--) {
263 #define DAYBUFFERSIZE 64
268 const char *w =
trNOOP(
"MTWTFSS");
269 if (!SingleByteChars)
274 for (
int i = 0; i < sl; i++)
288 localtime_r(&
Day, &tm_r);
289 b += strftime(b,
DAYBUFFERSIZE - (b - buffer),
"%Y-%m-%d", &tm_r);
307 char *channelbuffer = NULL;
308 char *daybuffer = NULL;
309 char *filebuffer = NULL;
320 while (l2 > 0 && isspace(s[l2 - 1]))
322 if (s[l2 - 1] ==
':') {
323 s2 =
MALLOC(
char, l2 + 3);
324 strcat(
strn0cpy(s2, s, l2 + 1),
" \n");
328 if (8 <= sscanf(s,
"%u :%m[^:]:%m[^:]:%d :%d :%d :%d :%m[^:\n]:%m[^\n]", &
flags, &channelbuffer, &daybuffer, &
start, &
stop, &
priority, &
lifetime, &filebuffer, &
aux)) {
339 channel = Channels->GetByNumber(atoi(channelbuffer));
343 esyslog(
"ERROR: channel %s not defined", channelbuffer);
357 return fprintf(f,
"%s\n", *
ToText(
true)) > 0;
369 return localtime_r(&t, &tm_r)->tm_mday;
375 int weekday = localtime_r(&t, &tm_r)->tm_wday;
376 return weekday == 0 ? 6 : weekday - 1;
387 tm tm = *localtime_r(&t, &tm_r);
399 tm tm = *localtime_r(&t, &tm_r);
400 tm.tm_hour = SecondsFromMidnight / 3600;
401 tm.tm_min = (SecondsFromMidnight % 3600) / 60;
402 tm.tm_sec = SecondsFromMidnight % 60;
413 #define EITPRESENTFOLLOWINGRATE 10 // max. seconds between two occurrences of the "EIT present/following table for the actual multiplex" (2s by the standard, using some more for safety)
423 int length = end - begin;
434 for (
int i = -1; i <= 7; i++) {
441 if ((!
day || a >=
day) && t < b) {
460 if (Margin || !Directly) {
465 return event->IsRunning(
true);
475 #define FULLMATCH 1000
513 #define EXPIRELATENCY 60 // seconds (just in case there's a short glitch in the VPS signal)
537 #define EPGLIMITBEFORE (1 * 3600) // Time in seconds before a timer's start time and
538 #define EPGLIMITAFTER (1 * 3600) // after its stop time within which EPG events will be taken into consideration.
548 if (Schedule && Schedule->
Events()->First()) {
554 if (e->StartTime()) {
572 if (e->EndTime() < TimeFrameBegin)
574 if (e->StartTime() > TimeFrameEnd)
578 if (overlap && overlap >= Overlap) {
596 event->DecNumTimers();
738 Timers->SetExplicitModify();
743 Timers->SetModified();
757 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
758 if (ti->Id() == Id) {
759 if (!Remote && !ti->Remote() || Remote && ti->Remote() && strcmp(Remote, ti->Remote()) == 0)
768 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
770 ti->Channel() == Timer->
Channel() &&
771 (ti->WeekDays() && ti->WeekDays() == Timer->
WeekDays() || !ti->WeekDays() && ti->Day() == Timer->
Day()) &&
772 ti->Start() == Timer->
Start() &&
773 ti->Stop() == Timer->
Stop())
781 static int LastPending = -1;
783 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
784 if (!ti->Remote() && !ti->Recording() && ti->Matches(t)) {
786 if (ti->Index() > LastPending) {
787 LastPending = ti->
Index();
806 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
808 if (tm > m || tm ==
tmFull && ti->Local()) {
811 if (m ==
tmFull && ti->Local())
823 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
824 if (!ti->Remote() && ti->Recording())
825 n =
max(n, ti->Priority());
833 for (
const cTimer *ti = First(); ti; ti =
Next(ti)) {
836 if ((ti->HasFlags(
tfActive)) && (!t0 || ti->
StopTime() > time(NULL) && ti->Compare(*t0) < 0))
875 for (
const cTimer *Timer = First(); Timer; Timer =
Next(Timer)) {
876 if (Timer->Channel() == Channel)
884 bool TimersModified =
false;
886 TimersModified |= ti->SetEventFromSchedule(Schedules);
887 return TimersModified;
894 bool TimersModified =
false;
901 TimersModified =
true;
906 return TimersModified;
912 if (!ServerName || !RemoteTimers || RemoteTimers->
Size() == 0) {
917 if (Timer->
Remote() && (!ServerName || strcmp(Timer->
Remote(), ServerName) == 0)) {
927 for (
cTimer *ti = First(); ti; ti =
Next(ti)) {
928 if (ti->Remote() && strcmp(ti->Remote(), ServerName) == 0)
936 int sr = RemoteTimers->
Size();
941 int nl = atoi(tl[il]);
944 int nr = atoi((*RemoteTimers)[ir]);
946 AddTimer = DelTimer = nl;
956 AddTimer = atoi((*RemoteTimers)[ir]);
958 esyslog(
"ERROR: %s: error in timer settings: %s", ServerName, (*RemoteTimers)[ir]);
965 if (AddTimer && DelTimer) {
966 if (strcmp(tl[il], (*RemoteTimers)[ir]) != 0) {
968 char *v = (*RemoteTimers)[ir];
969 while (*v && *v !=
' ')
980 esyslog(
"ERROR: %d@%s: error in timer settings: %s", DelTimer, ServerName, v);
989 char *v = (*RemoteTimers)[ir];
990 while (*v && *v !=
' ')
993 if (Timer->
Parse(v)) {
995 Timer->
SetId(AddTimer);
1000 esyslog(
"ERROR: %s: error in timer settings: %s", ServerName, v);
1005 else if (DelTimer) {
1013 esyslog(
"ERROR: oops while storing remote timers!");
1032 if (OldTimer->
Remote() && OldTimer->
Id()) {
1039 else if (!OldTimer || OldTimer->
Local() || !OldTimer->
Id()) {
1040 if (NewTimer->
Local()) {
1041 if (OldTimer && OldTimer->
Id())
1049 int RemoteId = atoi(SVDRPValue(Response[0]));
1052 NewTimer->
SetId(RemoteId);
1053 if (OldTimer && OldTimer->
Id()) {
1060 else if (NewTimer->
Local()) {
1067 else if (strcmp(OldTimer->
Remote(), NewTimer->
Remote()) == 0) {
1075 int RemoteId = atoi(SVDRPValue(Response[0]));
1078 NewTimer->
SetId(RemoteId);
1090 return (*(
const cTimer **)a)->Compare(**(
const cTimer **)b);
1096 for (
const cTimer *Timer = Timers->First(); Timer; Timer = Timers->
Next(Timer))
void SetAux(const char *Aux)
cTimer & operator=(const cTimer &Timer)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void SetPending(bool Pending)
void SetPriority(int Priority)
const cChannel * Channel(void) const
int weekdays
bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
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...
void SetFile(const char *File)
const char * Name(void) const
const cTimer * GetMatch(time_t t) const
const cTimer * GetById(int Id, const char *Remote=NULL) const
static time_t IncDay(time_t t, int Days)
#define LOCK_CHANNELS_READ
time_t deferred
Matches(time_t, ...) will return false if the current time is before this value.
static int NewTimerId(void)
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.
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
const cTimer * UsesChannel(const cChannel *Channel) const
bool PresentSeenWithin(int Seconds) const
#define LOCK_SCHEDULES_READ
bool HandleRemoteTimerModifications(cTimer *NewTimer, cTimer *OldTimer, cString *Msg)
Performs any operations necessary to synchronize changes to a timer between peer VDR machines.
const cTimer * GetTimer(const cTimer *Timer) const
const char * FileName(void)
void SetFlags(uint Flags)
bool SetEvents(const cSchedules *Schedules)
static bool ParseDay(const char *s, time_t &Day, int &WeekDays)
static bool RemoteTimerError(const cTimer *Timer, cString *Msg)
void Add(cListObject *Object, cListObject *After=NULL)
const char * Title(void) const
char NameInstantRecord[NAME_MAX+1]
cString ToText(bool UseChannelID=false) const
bool DayMatches(time_t t) const
const cSchedule * Schedule(void) const
void SetRecording(bool Recording)
time_t EndTime(void) const
const cSchedule * GetSchedule(tChannelID ChannelID) const
cString ToDescr(void) const
void Add(cTimer *Timer, cTimer *After=NULL)
void ClrFlags(uint Flags)
static bool Load(const char *FileName)
bool IsSingleEvent(void) const
const cTimer * GetNextActiveTimer(void) const
const cList< cEvent > * Events(void) const
void Del(cListObject *Object, bool DeleteObject=true)
bool SetEventFromSchedule(const cSchedules *Schedules)
void Ins(cListObject *Object, cListObject *Before=NULL)
#define EITPRESENTFOLLOWINGRATE
static cString PrintDay(time_t Day, int WeekDays, bool SingleByteChars)
tChannelID ChannelID(void) const
void SetInVpsMargin(bool InVpsMargin)
cSortedTimers(const cTimers *Timers)
@ RunningStatusNotRunning
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 Sort(__compar_fn_t Compare)
time_t StartTime(void) const
bool Recording(void) const
const char * Remote(void) const
time_t StartTime(void) const
const char * File(void) const
const cEvent * Event(void) const
const char * Aux(void) const
cString PrintFirstDay(void) const
static int TimeToInt(int t)
bool HasFlags(uint Flags) const
void IncNumTimers(void) const
bool SetEvent(const cEvent *Event)
void Del(cTimer *Timer, bool DeleteObject=true)
cString ToDescr(void) const
virtual int Compare(const cListObject &ListObject) const
static int Utf8CharLen(const char *s)
static int CompareTimers(const void *a, const void *b)
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...
tChannelID GetChannelID(void) const
static cTimers * GetTimersWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for write access.
bool Parse(const char *s)
static void MsgTimerChange(const cTimer *Timer, eTimerChange Change)
void SortNumerically(void)
static time_t SetTime(time_t t, int SecondsFromMidnight)
static int GetWDay(time_t t)
int RunningStatus(void) const
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 IsRunning(bool OrAboutToStart=false) const
cTimer(bool Instant=false, bool Pause=false, const cChannel *Channel=NULL)
virtual void Append(T Data)
bool InVpsMargin(void) const
void InvFlags(uint Flags)
void SetWeekDays(int WeekDays)
void Ins(cTimer *Timer, cTimer *Before=NULL)
time_t StopTime(void) const
bool Modified(int &State) const
static tChannelID FromString(const char *s)
void SetRemote(const char *Remote)
static int GetMDay(time_t t)
void SetDeferred(int Seconds)
bool Matches(time_t t=0, bool Directly=false, int Margin=0) const
void SetLifetime(int Lifetime)
int GetMaxPriority(void) const
Returns the maximum priority of all local timers that are currently recording.
#define LOCK_TIMERS_WRITE