1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

The day of a timer is now stored as a full date in ISO notation

This commit is contained in:
Klaus Schmidinger 2005-03-19 15:38:43 +01:00
parent ae5ee879d0
commit ccc7c4a2d8
9 changed files with 235 additions and 238 deletions

View File

@ -1296,3 +1296,6 @@ Luca Olivetti <luca@ventoso.org>
Mikko Salo <mikko.salo@ppe.inet.fi> Mikko Salo <mikko.salo@ppe.inet.fi>
for suggesting to make the setup option "DVB/Video display format" available only for suggesting to make the setup option "DVB/Video display format" available only
if "Video format" is set to "4:3" if "Video format" is set to "4:3"
Roman Krenický <free-rtk@gmx.de>
for a patch that was used a a basis for changing a timer's day handling to full date

View File

@ -3444,7 +3444,7 @@ Video Disk Recorder Revision History
- Fixed handling repeated kAudio keys. - Fixed handling repeated kAudio keys.
- Improved displaying the the current audio track in the ST:TNG channel display. - Improved displaying the the current audio track in the ST:TNG channel display.
2005-03-13: Version 1.3.23 2005-03-19: Version 1.3.23
- The setup option "DVB/Video display format" is now only available if "Video format" - The setup option "DVB/Video display format" is now only available if "Video format"
is set to "4:3" (suggested by Mikko Salo). is set to "4:3" (suggested by Mikko Salo).
@ -3461,3 +3461,6 @@ Video Disk Recorder Revision History
- The running status of a VPS event is now only taken seriously if that event has been - The running status of a VPS event is now only taken seriously if that event has been
seen within the last 30 seconds - otherwise recording is done as if no VPS was seen within the last 30 seconds - otherwise recording is done as if no VPS was
available. available.
- The day of a timer is now stored as a full date in ISO notation ("YYYY-MM-DD") in
'timers.conf' and for the result of the SVDRP command LSTT (based in parts on a
patch by Roman Krenický).

10
MANUAL
View File

@ -381,10 +381,9 @@ Version 1.2
Any changes made in the "Channels" list (like renaming or Any changes made in the "Channels" list (like renaming or
reordering channels) will be automatically reflected in the reordering channels) will be automatically reflected in the
timers settings. timers settings.
Day: The day on which this timer shall start. This can be either a Day: The day on which this timer shall start. This can be a
"day of month" (1..31), which allows programming a "single shot" date (like 2005-03-19), which allows programming a "single shot"
timer that hits once and is deleted after it ends. Single shot timer that hits once and is deleted after it ends.
timers can be programmed up to one month into the future.
Another option here are "repeating timers" which are defined Another option here are "repeating timers" which are defined
by listing the days of the week on which they shall record. by listing the days of the week on which they shall record.
For example, a timer that shall record every monday and wednesday For example, a timer that shall record every monday and wednesday
@ -392,6 +391,9 @@ Version 1.2
The '0' key toggles between a single shot and a repeating timer. The '0' key toggles between a single shot and a repeating timer.
If "Day" indicates a repeating timer, the keys '1'...'7' can be If "Day" indicates a repeating timer, the keys '1'...'7' can be
used to toggle the individual days ('1' is monday). used to toggle the individual days ('1' is monday).
You can also switch to a set of predefined repeating timer settings
by pressing the "Left" key when the day is the present day. To return
to the single shot mode just press "Right" until a date is displayed.
Start: The start time of the timer in hh:mm as 24 hour ("military") time. Start: The start time of the timer in hh:mm as 24 hour ("military") time.
Stop: The stop time of the timer. Stop: The stop time of the timer.
VPS: Defines whether the timer shall use VPS (if available). If this VPS: Defines whether the timer shall use VPS (if available). If this

9
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.343 2005/03/05 15:43:10 kls Exp $ * $Id: menu.c 1.344 2005/03/19 14:23:43 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -632,7 +632,7 @@ cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
channel = data.Channel()->Number(); channel = data.Channel()->Number();
Add(new cMenuEditBitItem( tr("Active"), &data.flags, tfActive)); Add(new cMenuEditBitItem( tr("Active"), &data.flags, tfActive));
Add(new cMenuEditChanItem(tr("Channel"), &channel)); Add(new cMenuEditChanItem(tr("Channel"), &channel));
Add(new cMenuEditDayItem( tr("Day"), &data.day)); Add(new cMenuEditDateItem(tr("Day"), &data.day, &data.weekdays));
Add(new cMenuEditTimeItem(tr("Start"), &data.start)); Add(new cMenuEditTimeItem(tr("Start"), &data.start));
Add(new cMenuEditTimeItem(tr("Stop"), &data.stop)); Add(new cMenuEditTimeItem(tr("Stop"), &data.stop));
Add(new cMenuEditBitItem( tr("VPS"), &data.flags, tfVps)); Add(new cMenuEditBitItem( tr("VPS"), &data.flags, tfVps));
@ -654,13 +654,12 @@ cMenuEditTimer::~cMenuEditTimer()
void cMenuEditTimer::SetFirstDayItem(void) void cMenuEditTimer::SetFirstDayItem(void)
{ {
if (!firstday && !data.IsSingleEvent()) { if (!firstday && !data.IsSingleEvent()) {
Add(firstday = new cMenuEditDateItem(tr("First day"), &data.firstday)); Add(firstday = new cMenuEditDateItem(tr("First day"), &data.day));
Display(); Display();
} }
else if (firstday && data.IsSingleEvent()) { else if (firstday && data.IsSingleEvent()) {
Del(firstday->Index()); Del(firstday->Index());
firstday = NULL; firstday = NULL;
data.firstday = 0;
Display(); Display();
} }
} }
@ -739,7 +738,7 @@ void cMenuTimerItem::Set(void)
timer->Channel()->Number(), timer->Channel()->Number(),
timer->IsSingleEvent() ? *WeekDayName(timer->StartTime()) : "", timer->IsSingleEvent() ? *WeekDayName(timer->StartTime()) : "",
timer->IsSingleEvent() ? " " : "", timer->IsSingleEvent() ? " " : "",
*timer->PrintDay(timer->Day()), *timer->PrintDay(timer->Day(), timer->WeekDays()),
timer->Start() / 100, timer->Start() / 100,
timer->Start() % 100, timer->Start() % 100,
timer->Stop() / 100, timer->Stop() / 100,

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menuitems.c 1.21 2004/11/21 13:24:10 kls Exp $ * $Id: menuitems.c 1.22 2005/03/19 15:33:34 kls Exp $
*/ */
#include "menuitems.h" #include "menuitems.h"
@ -535,117 +535,35 @@ eOSState cMenuEditTranItem::ProcessKey(eKeys Key)
return state; return state;
} }
// --- cMenuEditDayItem ------------------------------------------------------
int cMenuEditDayItem::days[] ={ cTimer::ParseDay("M------"),
cTimer::ParseDay("-T-----"),
cTimer::ParseDay("--W----"),
cTimer::ParseDay("---T---"),
cTimer::ParseDay("----F--"),
cTimer::ParseDay("-----S-"),
cTimer::ParseDay("------S"),
cTimer::ParseDay("MTWTF--"),
cTimer::ParseDay("MTWTFS-"),
cTimer::ParseDay("MTWTFSS"),
cTimer::ParseDay("-----SS"),
0 };
cMenuEditDayItem::cMenuEditDayItem(const char *Name, int *Value)
:cMenuEditIntItem(Name, Value, -INT_MAX, 31)
{
d = -1;
md = 0;
if (*value < 0) {
int n = 0;
while (days[n]) {
if (days[n] == *value) {
d = n;
break;
}
n++;
}
}
Set();
}
void cMenuEditDayItem::Set(void)
{
SetValue(cTimer::PrintDay(*value));
}
eOSState cMenuEditDayItem::ProcessKey(eKeys Key)
{
switch (Key) {
case kLeft|k_Repeat:
case kLeft: if (d > 0)
*value = days[--d];
else if (d == 0) {
*value = 31;
d = -1;
}
else if (*value == 1) {
d = sizeof(days) / sizeof(int) - 2;
*value = days[d];
}
else
return cMenuEditIntItem::ProcessKey(Key);
Set();
break;
case kRight|k_Repeat:
case kRight: if (d >= 0) {
*value = days[++d];
if (*value == 0) {
*value = 1;
d = -1;
}
}
else if (*value == 31) {
d = 0;
*value = days[d];
}
else
return cMenuEditIntItem::ProcessKey(Key);
Set();
break;
default: {
if (d >= 0) {
if (k1 <= Key && Key <= k7) {
int v = *value ^ (1 << (Key - k1));
if ((v & 0xFF) != 0) {
*value = v; // can't let this become all 0
Set();
}
break;
}
}
int v = *value;
eOSState result = cMenuEditIntItem::ProcessKey(Key);
if (result == osContinue && Key == k0) {
if (d >= 0) {
*value = md ? md : cTimer::GetMDay(time(NULL));
md = 0;
d = -1;
Set();
}
else if (*value == 0 || *value == v) {
md = v;
d = cTimer::GetWDayFromMDay(v);
*value = days[d];
Set();
}
}
return result;
}
}
return osContinue;
}
// --- cMenuEditDateItem ----------------------------------------------------- // --- cMenuEditDateItem -----------------------------------------------------
cMenuEditDateItem::cMenuEditDateItem(const char *Name, time_t *Value) static int ParseWeekDays(const char *s)
{
time_t day;
int weekdays;
return cTimer::ParseDay(s, day, weekdays) ? weekdays : 0;
}
int cMenuEditDateItem::days[] = { ParseWeekDays("M------"),
ParseWeekDays("-T-----"),
ParseWeekDays("--W----"),
ParseWeekDays("---T---"),
ParseWeekDays("----F--"),
ParseWeekDays("-----S-"),
ParseWeekDays("------S"),
ParseWeekDays("MTWTF--"),
ParseWeekDays("MTWTFS-"),
ParseWeekDays("MTWTFSS"),
ParseWeekDays("-----SS"),
0 };
cMenuEditDateItem::cMenuEditDateItem(const char *Name, time_t *Value, int *WeekDays)
:cMenuEditItem(Name) :cMenuEditItem(Name)
{ {
value = Value; value = Value;
weekdays = WeekDays;
oldvalue = 0;
dayindex = 0;
Set(); Set();
} }
@ -653,7 +571,11 @@ void cMenuEditDateItem::Set(void)
{ {
#define DATEBUFFERSIZE 32 #define DATEBUFFERSIZE 32
char buf[DATEBUFFERSIZE]; char buf[DATEBUFFERSIZE];
if (*value) { if (weekdays && *weekdays) {
SetValue(cTimer::PrintDay(0, *weekdays));
return;
}
else if (*value) {
struct tm tm_r; struct tm tm_r;
localtime_r(value, &tm_r); localtime_r(value, &tm_r);
strftime(buf, DATEBUFFERSIZE, "%Y-%m-%d ", &tm_r); strftime(buf, DATEBUFFERSIZE, "%Y-%m-%d ", &tm_r);
@ -669,15 +591,73 @@ eOSState cMenuEditDateItem::ProcessKey(eKeys Key)
eOSState state = cMenuEditItem::ProcessKey(Key); eOSState state = cMenuEditItem::ProcessKey(Key);
if (state == osUnknown) { if (state == osUnknown) {
time_t now = time(NULL);
if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly? if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
*value -= SECSINDAY; if (!weekdays || !*weekdays) {
if (*value < time(NULL)) // Decrement single day:
*value = 0; time_t v = *value;
v -= SECSINDAY;
if (v < now) {
if (now <= v + SECSINDAY) { // switched from tomorrow to today
if (!weekdays)
v = 0;
}
else if (weekdays) { // switched from today to yesterday, so enter weekdays mode
v = 0;
dayindex = sizeof(days) / sizeof(int) - 2;
*weekdays = days[dayindex];
}
else // don't go before today
v = *value;
}
*value = v;
}
else {
// Decrement weekday index:
if (dayindex > 0)
*weekdays = days[--dayindex];
}
} }
else if (NORMALKEY(Key) == kRight) { else if (NORMALKEY(Key) == kRight) {
if (!*value) if (!weekdays || !*weekdays) {
*value = cTimer::SetTime(time(NULL), 0); // Increment single day:
*value += SECSINDAY; if (!*value)
*value = cTimer::SetTime(now, 0);
*value += SECSINDAY;
}
else {
// Increment weekday index:
*weekdays = days[++dayindex];
if (!*weekdays) { // was last weekday entry, so switch to today
*value = cTimer::SetTime(now, 0);
dayindex = 0;
}
}
}
else if (weekdays) {
if (Key == k0) {
// Toggle between weekdays and single day:
if (*weekdays) {
*value = cTimer::SetTime(oldvalue ? oldvalue : now, 0);
oldvalue = 0;
*weekdays = 0;
}
else {
*weekdays = days[cTimer::GetWDay(*value)];
oldvalue = *value;
*value = 0;
}
}
else if (k1 <= Key && Key <= k7) {
// Toggle individual weekdays:
if (*weekdays) {
int v = *weekdays ^ (1 << (Key - k1));
if (v != 0)
*weekdays = v; // can't let this become all 0
}
}
else
return state;
} }
else else
return state; return state;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menuitems.h 1.10 2004/11/21 13:23:00 kls Exp $ * $Id: menuitems.h 1.11 2005/03/19 15:02:57 kls Exp $
*/ */
#ifndef __MENUITEMS_H #ifndef __MENUITEMS_H
@ -118,24 +118,16 @@ public:
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };
class cMenuEditDayItem : public cMenuEditIntItem { class cMenuEditDateItem : public cMenuEditItem {
private: private:
static int days[]; static int days[];
int d;
int md;
protected:
virtual void Set(void);
public:
cMenuEditDayItem(const char *Name, int *Value);
virtual eOSState ProcessKey(eKeys Key);
};
class cMenuEditDateItem : public cMenuEditItem {
protected:
time_t *value; time_t *value;
int *weekdays;
time_t oldvalue;
int dayindex;
virtual void Set(void); virtual void Set(void);
public: public:
cMenuEditDateItem(const char *Name, time_t *Value); cMenuEditDateItem(const char *Name, time_t *Value, int *WeekDays = NULL);
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };

188
timers.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: timers.c 1.24 2005/03/13 12:53:51 kls Exp $ * $Id: timers.c 1.25 2005/03/19 15:20:58 kls Exp $
*/ */
#include "timers.h" #include "timers.h"
@ -30,7 +30,8 @@ cTimer::cTimer(bool Instant, bool Pause)
time_t t = time(NULL); time_t t = time(NULL);
struct tm tm_r; struct tm tm_r;
struct tm *now = localtime_r(&t, &tm_r); struct tm *now = localtime_r(&t, &tm_r);
day = now->tm_mday; day = SetTime(t, 0);
weekdays = 0;
start = now->tm_hour * 100 + now->tm_min; start = now->tm_hour * 100 + now->tm_min;
stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime; stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
stop = (stop / 60) * 100 + (stop % 60); stop = (stop / 60) * 100 + (stop % 60);
@ -39,7 +40,6 @@ cTimer::cTimer(bool Instant, bool Pause)
priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; priority = Pause ? Setup.PausePriority : Setup.DefaultPriority;
lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime;
*file = 0; *file = 0;
firstday = 0;
summary = NULL; summary = NULL;
event = NULL; event = NULL;
if (Instant && channel) if (Instant && channel)
@ -62,7 +62,8 @@ cTimer::cTimer(const cEvent *Event)
} }
struct tm tm_r; struct tm tm_r;
struct tm *time = localtime_r(&tstart, &tm_r); struct tm *time = localtime_r(&tstart, &tm_r);
day = time->tm_mday; day = SetTime(tstart, 0);
weekdays = 0;
start = time->tm_hour * 100 + time->tm_min; start = time->tm_hour * 100 + time->tm_min;
time = localtime_r(&tstop, &tm_r); time = localtime_r(&tstop, &tm_r);
stop = time->tm_hour * 100 + time->tm_min; stop = time->tm_hour * 100 + time->tm_min;
@ -74,7 +75,6 @@ cTimer::cTimer(const cEvent *Event)
const char *Title = Event->Title(); const char *Title = Event->Title();
if (!isempty(Title)) if (!isempty(Title))
strn0cpy(file, Event->Title(), sizeof(file)); strn0cpy(file, Event->Title(), sizeof(file));
firstday = 0;
summary = NULL; summary = NULL;
event = Event; event = Event;
} }
@ -109,7 +109,7 @@ cString cTimer::ToText(bool UseChannelID)
char *buffer; char *buffer;
strreplace(file, ':', '|'); strreplace(file, ':', '|');
strreplace(summary, '\n', '|'); strreplace(summary, '\n', '|');
asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : ""); asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, summary ? summary : "");
strreplace(summary, '|', '\n'); strreplace(summary, '|', '\n');
strreplace(file, '|', ':'); strreplace(file, '|', ':');
return cString(buffer, true); return cString(buffer, true);
@ -120,74 +120,93 @@ int cTimer::TimeToInt(int t)
return (t / 100 * 60 + t % 100) * 60; return (t / 100 * 60 + t % 100) * 60;
} }
int cTimer::ParseDay(const char *s, time_t *FirstDay) bool cTimer::ParseDay(const char *s, time_t &Day, int &WeekDays)
{ {
char *tail; // possible formats are:
int d = strtol(s, &tail, 10); // 19
if (FirstDay) // 2005-03-19
*FirstDay = 0; // MTWTFSS
if (tail && *tail) { // MTWTFSS@19
d = 0; // MTWTFSS@2005-03-19
if (tail == s) {
const char *first = strchr(s, '@'); Day = 0;
int l = first ? first - s : strlen(s); WeekDays = 0;
if (l == 7) { s = skipspace(s);
for (const char *p = s + 6; p >= s; p--) { if (!*s)
d <<= 1; return false;
d |= (*p != '-'); const char *a = strchr(s, '@');
const char *d = a ? a + 1 : isdigit(*s) ? s : NULL;
if (d) {
if (strlen(d) == 10) {
struct tm tm_r;
if (3 == sscanf(d, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
tm_r.tm_year -= 1900;
tm_r.tm_mon--;
tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
Day = mktime(&tm_r);
}
else
return false;
}
else {
// handle "day of month" for compatibility with older versions:
char *tail = NULL;
int day = strtol(s, &tail, 10);
if (tail && *tail || day < 1 || day > 31)
return false;
time_t t = time(NULL);
int DaysToCheck = 61; // 61 to handle months with 31/30/31
for (int i = -1; i <= DaysToCheck; i++) {
time_t t0 = IncDay(t, i);
if (GetMDay(t0) == day) {
Day = SetTime(t0, 0);
break;
} }
d |= 0x80000000; }
}
if (FirstDay && first) {
++first;
if (strlen(first) == 10) {
struct tm tm_r;
if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
tm_r.tm_year -= 1900;
tm_r.tm_mon--;
tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
*FirstDay = mktime(&tm_r);
}
}
else
d = 0;
}
} }
} }
else if (d < 1 || d > 31) if (a || !isdigit(*s)) {
d = 0; if ((a && a - s == 7) || strlen(s) == 7) {
return d; for (const char *p = s + 6; p >= s; p--) {
WeekDays <<= 1;
WeekDays |= (*p != '-');
}
}
else
return false;
}
return true;
} }
cString cTimer::PrintDay(int d, time_t FirstDay) cString cTimer::PrintDay(time_t Day, int WeekDays)
{ {
#define DAYBUFFERSIZE 32 #define DAYBUFFERSIZE 32
char buffer[DAYBUFFERSIZE]; char buffer[DAYBUFFERSIZE];
if ((d & 0x80000000) != 0) { char *b = buffer;
char *b = buffer; if (WeekDays) {
const char *w = tr("MTWTFSS"); const char *w = tr("MTWTFSS");
while (*w) { while (*w) {
*b++ = (d & 1) ? *w : '-'; *b++ = (WeekDays & 1) ? *w : '-';
d >>= 1; WeekDays >>= 1;
w++; w++;
} }
if (FirstDay) { if (Day)
struct tm tm_r; *b++ = '@';
localtime_r(&FirstDay, &tm_r);
b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
}
*b = 0;
} }
else if (Day) {
sprintf(buffer, "%d", d); struct tm tm_r;
localtime_r(&Day, &tm_r);
b += strftime(b, DAYBUFFERSIZE - (b - buffer), "%Y-%m-%d", &tm_r);
}
*b = 0;
return buffer; return buffer;
} }
cString cTimer::PrintFirstDay(void) cString cTimer::PrintFirstDay(void)
{ {
if (firstday) { if (weekdays) {
cString s = PrintDay(day, firstday); cString s = PrintDay(day, weekdays);
if (strlen(s) == 18) if (strlen(s) == 18)
return *s + 8; return *s + 8;
} }
@ -223,8 +242,7 @@ bool cTimer::Parse(const char *s)
summary = NULL; summary = NULL;
} }
//TODO add more plausibility checks //TODO add more plausibility checks
day = ParseDay(daybuffer, &firstday); result = ParseDay(daybuffer, day, weekdays);
result = day != 0;
strn0cpy(file, filebuffer, MaxFileName); strn0cpy(file, filebuffer, MaxFileName);
strreplace(file, '|', ':'); strreplace(file, '|', ':');
strreplace(summary, '|', '\n'); strreplace(summary, '|', '\n');
@ -251,7 +269,7 @@ bool cTimer::Save(FILE *f)
bool cTimer::IsSingleEvent(void) const bool cTimer::IsSingleEvent(void) const
{ {
return (day & 0x80000000) == 0; return !weekdays;
} }
int cTimer::GetMDay(time_t t) int cTimer::GetMDay(time_t t)
@ -267,20 +285,9 @@ int cTimer::GetWDay(time_t t)
return weekday == 0 ? 6 : weekday - 1; // we start with monday==0! return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
} }
int cTimer::GetWDayFromMDay(int MDay)
{
time_t now = time(NULL);
for (int i = -1; i <= 28; i++) { // looking 4 weeks into the future should be enough
time_t t0 = IncDay(now, i);
if (GetMDay(t0) == MDay)
return GetWDay(t0);
}
return GetWDay(now); // just to return something
}
bool cTimer::DayMatches(time_t t) const bool cTimer::DayMatches(time_t t) const
{ {
return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0; return IsSingleEvent() ? SetTime(t, 0) == day : (weekdays & (1 << GetWDay(t))) != 0;
} }
time_t cTimer::IncDay(time_t t, int Days) time_t cTimer::IncDay(time_t t, int Days)
@ -324,23 +331,28 @@ bool cTimer::Matches(time_t t, bool Directly) const
if (length < 0) if (length < 0)
length += SECSINDAY; length += SECSINDAY;
int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31 if (IsSingleEvent()) {
for (int i = -1; i <= DaysToCheck; i++) { startTime = SetTime(day, begin);
time_t t0 = IncDay(t, i); stopTime = startTime + length;
if (DayMatches(t0)) { }
time_t a = SetTime(t0, begin); else {
time_t b = a + length; for (int i = -1; i <= 7; i++) {
if ((!firstday || a >= firstday) && t <= b) { time_t t0 = IncDay(t, i);
startTime = a; if (DayMatches(t0)) {
stopTime = b; time_t a = SetTime(t0, begin);
break; time_t b = a + length;
if ((!day || a >= day) && t <= b) {
startTime = a;
stopTime = b;
break;
}
} }
} }
} if (!startTime)
if (!startTime) startTime = day; // just to have something that's more than a week in the future
startTime = firstday; // just to have something that's more than a week in the future else if (!Directly && (t > startTime || t > day + SECSINDAY + 3600)) // +3600 in case of DST change
else if (!Directly && (t > startTime || t > firstday + SECSINDAY + 3600)) // +3600 in case of DST change day = 0;
firstday = 0; }
if (HasFlags(tfActive)) { if (HasFlags(tfActive)) {
if (HasFlags(tfVps) && !Directly && event && event->Vps() && event->SeenWithin(30)) { if (HasFlags(tfVps) && !Directly && event && event->Vps() && event->SeenWithin(30)) {
@ -446,7 +458,7 @@ bool cTimer::HasFlags(int Flags) const
void cTimer::Skip(void) void cTimer::Skip(void)
{ {
firstday = IncDay(SetTime(StartTime(), 0), 1); day = IncDay(SetTime(StartTime(), 0), 1);
event = NULL; event = NULL;
} }
@ -454,8 +466,8 @@ void cTimer::OnOff(void)
{ {
if (IsSingleEvent()) if (IsSingleEvent())
InvFlags(tfActive); InvFlags(tfActive);
else if (firstday) { else if (day) {
firstday = 0; day = 0;
ClrFlags(tfActive); ClrFlags(tfActive);
} }
else if (HasFlags(tfActive)) else if (HasFlags(tfActive))

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: timers.h 1.14 2005/03/12 16:27:36 kls Exp $ * $Id: timers.h 1.15 2005/03/19 14:22:11 kls Exp $
*/ */
#ifndef __TIMERS_H #ifndef __TIMERS_H
@ -30,13 +30,13 @@ private:
bool recording, pending, inVpsMargin; bool recording, pending, inVpsMargin;
int flags; int flags;
cChannel *channel; cChannel *channel;
int day; mutable time_t day; /// midnight of the day this timer shall hit, or of the first day it shall hit in case of a repeating timer
int weekdays; /// bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
int start; int start;
int stop; int stop;
int priority; int priority;
int lifetime; int lifetime;
char file[MaxFileName]; char file[MaxFileName];
mutable time_t firstday;
char *summary; char *summary;
const cEvent *event; const cEvent *event;
public: public:
@ -50,13 +50,14 @@ public:
bool InVpsMargin(void) { return inVpsMargin; } bool InVpsMargin(void) { return inVpsMargin; }
int Flags(void) { return flags; } int Flags(void) { return flags; }
const cChannel *Channel(void) { return channel; } const cChannel *Channel(void) { return channel; }
int Day(void) { return day; } time_t Day(void) { return day; }
int WeekDays(void) { return weekdays; }
int Start(void) { return start; } int Start(void) { return start; }
int Stop(void) { return stop; } int Stop(void) { return stop; }
int Priority(void) { return priority; } int Priority(void) { return priority; }
int Lifetime(void) { return lifetime; } int Lifetime(void) { return lifetime; }
const char *File(void) { return file; } const char *File(void) { return file; }
time_t FirstDay(void) { return firstday; } time_t FirstDay(void) { return weekdays ? day : 0; }
const char *Summary(void) { return summary; } const char *Summary(void) { return summary; }
cString ToText(bool UseChannelID = false); cString ToText(bool UseChannelID = false);
const cEvent *Event(void) { return event; } const cEvent *Event(void) { return event; }
@ -65,7 +66,6 @@ public:
bool IsSingleEvent(void) const; bool IsSingleEvent(void) const;
static int GetMDay(time_t t); static int GetMDay(time_t t);
static int GetWDay(time_t t); static int GetWDay(time_t t);
static int GetWDayFromMDay(int MDay);
bool DayMatches(time_t t) const; bool DayMatches(time_t t) const;
static time_t IncDay(time_t t, int Days); static time_t IncDay(time_t t, int Days);
static time_t SetTime(time_t t, int SecondsFromMidnight); static time_t SetTime(time_t t, int SecondsFromMidnight);
@ -86,8 +86,8 @@ public:
void OnOff(void); void OnOff(void);
cString PrintFirstDay(void); cString PrintFirstDay(void);
static int TimeToInt(int t); static int TimeToInt(int t);
static int ParseDay(const char *s, time_t *FirstDay = NULL); static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
static cString PrintDay(int d, time_t FirstDay = 0); static cString PrintDay(time_t Day, int WeekDays);
}; };
class cTimers : public cConfig<cTimer> { class cTimers : public cConfig<cTimer> {

14
vdr.5
View File

@ -8,9 +8,9 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 1.34 2005/01/23 13:31:40 kls Exp $ .\" $Id: vdr.5 1.35 2005/03/19 15:20:47 kls Exp $
.\" .\"
.TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files" .TH vdr 5 "19 Mar 2005" "1.3.23" "Video Disk Recorder Files"
.SH NAME .SH NAME
vdr file formats - the Video Disk Recorder Files vdr file formats - the Video Disk Recorder Files
.SH DESCRIPTION .SH DESCRIPTION
@ -231,8 +231,13 @@ commands, the channels are given as numbers.
.B Day .B Day
The day when this timer shall record. The day when this timer shall record.
If this is a `single-shot' timer, this is the day of month on which this If this is a `single-shot' timer, this is the date on which this
timer shall record. This must be in the range \fB1...31\fR. timer shall record, given in ISO notation (\fBYYYY-MM-DD\fR), as in:
.B 2005-03-19
For compatibility with earlier versions of VDR this may also be just the day of month
on which this timer shall record (must be in the range \fB1...31\fR).
In case of a `repeating' timer this is a string consisting of exactly seven In case of a `repeating' timer this is a string consisting of exactly seven
characters, where each character position corresponds to one day of the week characters, where each character position corresponds to one day of the week
@ -245,6 +250,7 @@ cause the timer to record on that day. Example:
will define a timer that records on Monday thru Friday and does not record will define a timer that records on Monday thru Friday and does not record
on weekends. The same result could be achieved with \fBABCDE\-\-\fR (this is on weekends. The same result could be achieved with \fBABCDE\-\-\fR (this is
used to allow setting the days with language specific characters). used to allow setting the days with language specific characters).
Note that only letters may be used here, no digits.
The day definition of a `repeating' timer may be followed by the date when that The day definition of a `repeating' timer may be followed by the date when that
timer shall hit for the first time. The format for this is \fB@YYYY\-MM\-DD\fR, timer shall hit for the first time. The format for this is \fB@YYYY\-MM\-DD\fR,