mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Timers now have unique ids
This commit is contained in:
parent
50d268538e
commit
04edd69b7a
5
HISTORY
5
HISTORY
@ -8784,3 +8784,8 @@ Video Disk Recorder Revision History
|
||||
communication printed to the console for debugging.
|
||||
- Added a missing 'const' to cReceiver::Receive(), to protect the given Data from
|
||||
being modified.
|
||||
- The SVDRP commands that deal with timers (DELT, LSTT, MODT, NEWT, NEXT and UPDT)
|
||||
as well as any log messages that refer to timers, now use a unique id for each
|
||||
timer, which remains valid as long as this instance of VDR is running. This means
|
||||
that timers are no longer continuously numbered from 1 to N in LSTT. There may be
|
||||
gaps in the sequence, in case timers have been deleted.
|
||||
|
70
svdrp.c
70
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 4.3 2015/09/01 10:34:34 kls Exp $
|
||||
* $Id: svdrp.c 4.4 2015/09/06 09:14:53 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -1226,7 +1226,7 @@ void cSVDRPServer::CmdDELC(const char *Option)
|
||||
Channels->SetExplicitModify();
|
||||
if (cChannel *Channel = Channels->GetByNumber(strtol(Option, NULL, 10))) {
|
||||
if (const cTimer *Timer = Timers->UsesChannel(Channel)) {
|
||||
Reply(550, "Channel \"%s\" is in use by timer %d", Option, Timer->Index() + 1);
|
||||
Reply(550, "Channel \"%s\" is in use by timer %s", Option, *Timer->ToDescr());
|
||||
return;
|
||||
}
|
||||
int CurrentChannelNr = cDevice::CurrentChannel();
|
||||
@ -1265,7 +1265,7 @@ static cString RecordingInUseMessage(int Reason, const char *RecordingId, cRecor
|
||||
{
|
||||
cRecordControl *rc;
|
||||
if ((Reason & ruTimer) != 0 && (rc = cRecordControls::GetRecordControl(Recording->FileName())) != NULL)
|
||||
return cString::sprintf("Recording \"%s\" is in use by timer %d", RecordingId, rc->Timer()->Index() + 1);
|
||||
return cString::sprintf("Recording \"%s\" is in use by timer %d", RecordingId, rc->Timer()->Id());
|
||||
else if ((Reason & ruReplay) != 0)
|
||||
return cString::sprintf("Recording \"%s\" is being replayed", RecordingId);
|
||||
else if ((Reason & ruCut) != 0)
|
||||
@ -1312,12 +1312,12 @@ void cSVDRPServer::CmdDELT(const char *Option)
|
||||
if (isnumber(Option)) {
|
||||
LOCK_TIMERS_WRITE;
|
||||
Timers->SetExplicitModify();
|
||||
cTimer *Timer = Timers->Get(strtol(Option, NULL, 10) - 1);
|
||||
cTimer *Timer = Timers->GetById(strtol(Option, NULL, 10));
|
||||
if (Timer && !Timer->Remote()) {
|
||||
if (!Timer->Recording()) {
|
||||
isyslog("SVDRP < %s deleting timer %s", *connection, *Timer->ToDescr());
|
||||
Timers->Del(Timer);
|
||||
Timers->SetModified();
|
||||
isyslog("SVDRP < %s deleted timer %s", *connection, *Timer->ToDescr());
|
||||
Reply(250, "Timer \"%s\" deleted", Option);
|
||||
}
|
||||
else
|
||||
@ -1745,8 +1745,8 @@ void cSVDRPServer::CmdLSTR(const char *Option)
|
||||
|
||||
void cSVDRPServer::CmdLSTT(const char *Option)
|
||||
{
|
||||
int Number = 0;
|
||||
bool Id = false;
|
||||
int Id = 0;
|
||||
bool UseChannelId = false;
|
||||
if (*Option) {
|
||||
char buf[strlen(Option) + 1];
|
||||
strcpy(buf, Option);
|
||||
@ -1755,9 +1755,9 @@ void cSVDRPServer::CmdLSTT(const char *Option)
|
||||
char *p = strtok_r(buf, delim, &strtok_next);
|
||||
while (p) {
|
||||
if (isnumber(p))
|
||||
Number = strtol(p, NULL, 10);
|
||||
Id = strtol(p, NULL, 10);
|
||||
else if (strcasecmp(p, "ID") == 0)
|
||||
Id = true;
|
||||
UseChannelId = true;
|
||||
else {
|
||||
Reply(501, "Unknown option: \"%s\"", p);
|
||||
return;
|
||||
@ -1766,11 +1766,11 @@ void cSVDRPServer::CmdLSTT(const char *Option)
|
||||
}
|
||||
}
|
||||
LOCK_TIMERS_READ;
|
||||
if (Number) {
|
||||
if (Id) {
|
||||
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
|
||||
if (!Timer->Remote()) {
|
||||
if (Timer->Index() + 1 == Number) {
|
||||
Reply(250, "%d %s", Timer->Index() + 1, *Timer->ToText(Id));
|
||||
if (Timer->Id() == Id) {
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(UseChannelId));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1779,15 +1779,19 @@ void cSVDRPServer::CmdLSTT(const char *Option)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
cVector<const cTimer *> LocalTimers;
|
||||
const cTimer *LastLocalTimer = Timers->Last();
|
||||
while (LastLocalTimer) {
|
||||
if (LastLocalTimer->Remote())
|
||||
LastLocalTimer = Timers->Prev(LastLocalTimer);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (LastLocalTimer) {
|
||||
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
|
||||
if (!Timer->Remote())
|
||||
LocalTimers.Append(Timer);
|
||||
}
|
||||
if (LocalTimers.Size()) {
|
||||
for (int i = 0; i < LocalTimers.Size(); i++) {
|
||||
const cTimer *Timer = LocalTimers[i];
|
||||
Reply(i < LocalTimers.Size() - 1 ? -250 : 250, "%d %s", Timer->Index() + 1, *Timer->ToText(Id));
|
||||
Reply(Timer != LastLocalTimer ? -250 : 250, "%d %s", Timer->Id(), *Timer->ToText(UseChannelId));
|
||||
if (Timer == LastLocalTimer)
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1846,12 +1850,12 @@ void cSVDRPServer::CmdMODT(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
char *tail;
|
||||
int n = strtol(Option, &tail, 10);
|
||||
int Id = strtol(Option, &tail, 10);
|
||||
if (tail && tail != Option) {
|
||||
tail = skipspace(tail);
|
||||
LOCK_TIMERS_WRITE;
|
||||
Timers->SetExplicitModify();
|
||||
if (cTimer *Timer = Timers->Get(n - 1)) {
|
||||
if (cTimer *Timer = Timers->GetById(Id)) {
|
||||
cTimer t = *Timer;
|
||||
if (strcasecmp(tail, "ON") == 0)
|
||||
t.SetFlags(tfActive);
|
||||
@ -1863,11 +1867,11 @@ void cSVDRPServer::CmdMODT(const char *Option)
|
||||
}
|
||||
*Timer = t;
|
||||
Timers->SetModified();
|
||||
isyslog("SVDRP < %s timer %s modified (%s)", *connection, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
Reply(250, "%d %s", Timer->Index() + 1, *Timer->ToText());
|
||||
isyslog("SVDRP < %s modified timer %s (%s)", *connection, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText());
|
||||
}
|
||||
else
|
||||
Reply(501, "Timer \"%d\" not defined", n);
|
||||
Reply(501, "Timer \"%d\" not defined", Id);
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in timer number");
|
||||
@ -2007,8 +2011,8 @@ void cSVDRPServer::CmdNEWT(const char *Option)
|
||||
if (Timer->Parse(Option)) {
|
||||
LOCK_TIMERS_WRITE;
|
||||
Timers->Add(Timer);
|
||||
isyslog("SVDRP < %s timer %s added", *connection, *Timer->ToDescr());
|
||||
Reply(250, "%d %s", Timer->Index() + 1, *Timer->ToText());
|
||||
isyslog("SVDRP < %s added timer %s", *connection, *Timer->ToDescr());
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText());
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -2024,13 +2028,13 @@ void cSVDRPServer::CmdNEXT(const char *Option)
|
||||
LOCK_TIMERS_READ;
|
||||
if (const cTimer *t = Timers->GetNextActiveTimer()) {
|
||||
time_t Start = t->StartTime();
|
||||
int Number = t->Index() + 1;
|
||||
int Id = t->Id();
|
||||
if (!*Option)
|
||||
Reply(250, "%d %s", Number, *TimeToString(Start));
|
||||
Reply(250, "%d %s", Id, *TimeToString(Start));
|
||||
else if (strcasecmp(Option, "ABS") == 0)
|
||||
Reply(250, "%d %ld", Number, Start);
|
||||
Reply(250, "%d %ld", Id, Start);
|
||||
else if (strcasecmp(Option, "REL") == 0)
|
||||
Reply(250, "%d %ld", Number, Start - time(NULL));
|
||||
Reply(250, "%d %ld", Id, Start - time(NULL));
|
||||
else
|
||||
Reply(501, "Unknown option: \"%s\"", Option);
|
||||
}
|
||||
@ -2261,13 +2265,13 @@ void cSVDRPServer::CmdUPDT(const char *Option)
|
||||
t->Parse(Option);
|
||||
delete Timer;
|
||||
Timer = t;
|
||||
isyslog("SVDRP < %s timer %s updated", *connection, *Timer->ToDescr());
|
||||
isyslog("SVDRP < %s updated timer %s", *connection, *Timer->ToDescr());
|
||||
}
|
||||
else {
|
||||
Timers->Add(Timer);
|
||||
isyslog("SVDRP < %s timer %s added", *connection, *Timer->ToDescr());
|
||||
isyslog("SVDRP < %s added timer %s", *connection, *Timer->ToDescr());
|
||||
}
|
||||
Reply(250, "%d %s", Timer->Index() + 1, *Timer->ToText());
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText());
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
29
timers.c
29
timers.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.c 4.1 2015/08/31 10:45:13 kls Exp $
|
||||
* $Id: timers.c 4.2 2015/09/05 14:42:50 kls Exp $
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
|
||||
{
|
||||
id = 0;
|
||||
startTime = stopTime = 0;
|
||||
scheduleState = -1;
|
||||
deferred = 0;
|
||||
@ -82,6 +83,7 @@ cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
|
||||
|
||||
cTimer::cTimer(const cEvent *Event)
|
||||
{
|
||||
id = 0;
|
||||
startTime = stopTime = 0;
|
||||
scheduleState = -1;
|
||||
deferred = 0;
|
||||
@ -139,6 +141,7 @@ cTimer::~cTimer()
|
||||
cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
{
|
||||
if (&Timer != this) {
|
||||
id = Timer.id;
|
||||
uint OldFlags = flags & tfRecording;
|
||||
startTime = Timer.startTime;
|
||||
stopTime = Timer.stopTime;
|
||||
@ -189,7 +192,7 @@ cString cTimer::ToText(bool UseChannelID) const
|
||||
|
||||
cString cTimer::ToDescr(void) const
|
||||
{
|
||||
return cString::sprintf("%d%s%s (%d %04d-%04d %s'%s')", Index() + 1, remote ? "@" : "", remote ? remote : "", Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
|
||||
return cString::sprintf("%d%s%s (%d %04d-%04d %s'%s')", Id(), remote ? "@" : "", remote ? remote : "", Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
|
||||
}
|
||||
|
||||
int cTimer::TimeToInt(int t)
|
||||
@ -522,6 +525,11 @@ time_t cTimer::StopTime(void) const
|
||||
#define EPGLIMITBEFORE (1 * 3600) // Time in seconds before a timer's start time and
|
||||
#define EPGLIMITAFTER (1 * 3600) // after its stop time within which EPG events will be taken into consideration.
|
||||
|
||||
void cTimer::SetId(int Id)
|
||||
{
|
||||
id = Id;
|
||||
}
|
||||
|
||||
bool cTimer::SetEventFromSchedule(const cSchedules *Schedules)
|
||||
{
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel());
|
||||
@ -704,6 +712,7 @@ void cTimer::OnOff(void)
|
||||
// --- cTimers ---------------------------------------------------------------
|
||||
|
||||
cTimers cTimers::timers;
|
||||
int cTimers::lastTimerId = 0;
|
||||
|
||||
cTimers::cTimers(void)
|
||||
:cConfig<cTimer>("Timers")
|
||||
@ -717,6 +726,7 @@ bool cTimers::Load(const char *FileName)
|
||||
Timers->SetExplicitModify();
|
||||
if (timers.cConfig<cTimer>::Load(FileName)) {
|
||||
for (cTimer *ti = timers.First(); ti; ti = timers.Next(ti)) {
|
||||
ti->SetId(++lastTimerId);
|
||||
ti->ClrFlags(tfRecording);
|
||||
Timers->SetModified();
|
||||
}
|
||||
@ -725,6 +735,15 @@ bool cTimers::Load(const char *FileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
const cTimer *cTimers::GetById(int Id) const
|
||||
{
|
||||
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->Remote() && ti->Id() == Id)
|
||||
return ti;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cTimer *cTimers::GetTimer(cTimer *Timer)
|
||||
{
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
@ -804,6 +823,8 @@ cTimers *cTimers::GetTimersWrite(cStateKey &StateKey, int TimeoutMs)
|
||||
|
||||
void cTimers::Add(cTimer *Timer, cTimer *After)
|
||||
{
|
||||
if (!Timer->Remote())
|
||||
Timer->SetId(++lastTimerId);
|
||||
cConfig<cTimer>::Add(Timer, After);
|
||||
cStatus::MsgTimerChange(Timer, tcAdd);
|
||||
}
|
||||
@ -868,11 +889,13 @@ bool cTimers::GetRemoteTimers(const char *ServerName)
|
||||
int Code = Cmd.Code(s);
|
||||
if (Code == 250) {
|
||||
if (const char *v = Cmd.Value(s)) {
|
||||
int Id = atoi(v);
|
||||
while (*v && *v != ' ')
|
||||
v++; // skip number
|
||||
v++; // skip id
|
||||
cTimer *Timer = new cTimer;
|
||||
if (Timer->Parse(v)) {
|
||||
Timer->SetRemote(ServerName);
|
||||
Timer->SetId(Id);
|
||||
Add(Timer);
|
||||
Result = true;
|
||||
}
|
||||
|
8
timers.h
8
timers.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.h 4.1 2015/08/31 10:42:53 kls Exp $
|
||||
* $Id: timers.h 4.2 2015/09/05 13:51:33 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TIMERS_H
|
||||
@ -27,6 +27,7 @@ enum eTimerMatch { tmNone, tmPartial, tmFull };
|
||||
class cTimer : public cListObject {
|
||||
friend class cMenuEditTimer;
|
||||
private:
|
||||
int id;
|
||||
mutable time_t startTime, stopTime;
|
||||
int scheduleState;
|
||||
mutable time_t deferred; ///< Matches(time_t, ...) will return false if the current time is before this value
|
||||
@ -50,6 +51,7 @@ public:
|
||||
virtual ~cTimer();
|
||||
cTimer& operator= (const cTimer &Timer);
|
||||
virtual int Compare(const cListObject &ListObject) const;
|
||||
int Id(void) const { return id; }
|
||||
bool Recording(void) const { return HasFlags(tfRecording); }
|
||||
bool Pending(void) const { return pending; }
|
||||
bool InVpsMargin(void) const { return inVpsMargin; }
|
||||
@ -83,6 +85,7 @@ public:
|
||||
bool Expired(void) const;
|
||||
time_t StartTime(void) const;
|
||||
time_t StopTime(void) const;
|
||||
void SetId(int Id);
|
||||
bool SetEventFromSchedule(const cSchedules *Schedules);
|
||||
bool SetEvent(const cEvent *Event);
|
||||
void SetRecording(bool Recording);
|
||||
@ -112,6 +115,7 @@ public:
|
||||
class cTimers : public cConfig<cTimer> {
|
||||
private:
|
||||
static cTimers timers;
|
||||
static int lastTimerId;
|
||||
time_t lastDeleteExpired;
|
||||
public:
|
||||
cTimers(void);
|
||||
@ -162,6 +166,8 @@ public:
|
||||
///< StateKey.Remove();
|
||||
///< }
|
||||
static bool Load(const char *FileName);
|
||||
const cTimer *GetById(int Id) const;
|
||||
cTimer *GetById(int Id) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetById(Id)); };
|
||||
cTimer *GetTimer(cTimer *Timer);
|
||||
const cTimer *GetMatch(time_t t) const;
|
||||
cTimer *GetMatch(time_t t) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetMatch(t)); };
|
||||
|
Loading…
Reference in New Issue
Block a user