summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2015-09-10 10:39:45 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2015-09-10 10:39:45 +0200
commitbc0de5dbc56d5b4f373f09e92cf07ec773ccab4e (patch)
treef457a0f3a37f9f009ac5f242745b26d48c4a0935
parent4e3325b7f7e30d1013798d74b8e7e0b8471813b1 (diff)
downloadvdr-bc0de5dbc56d5b4f373f09e92cf07ec773ccab4e.tar.gz
vdr-bc0de5dbc56d5b4f373f09e92cf07ec773ccab4e.tar.bz2
Implemented full handling of remote timers
-rw-r--r--HISTORY16
-rw-r--r--MANUAL3
-rw-r--r--channels.c10
-rw-r--r--menu.c100
-rw-r--r--menu.h5
-rw-r--r--recording.c6
-rw-r--r--svdrp.c37
-rw-r--r--svdrp.h58
-rw-r--r--timers.c34
-rw-r--r--timers.h4
10 files changed, 173 insertions, 100 deletions
diff --git a/HISTORY b/HISTORY
index aa13be2c..387a7885 100644
--- a/HISTORY
+++ b/HISTORY
@@ -8669,8 +8669,10 @@ Video Disk Recorder Revision History
connections to keep them alive.
- The new function GetSVDRPServerNames() can be used to get a list of all VDRs
this VDR is connected to via SVDRP.
-- The new class cSVDRPCommand can be used to execute an SVDRP command on one of
- the servers this VDR is connected to, and retrieve the result.
+- The new function ExecSVDRPCommand() can be used to execute an SVDRP command on
+ one of the servers this VDR is connected to, and retrieve the result.
+ The helper functions SVDRPCode() and SVDRPValue() can be used to easily access
+ the codes and values returned by ExecSVDRPCommand().
- The cTimer class now has a new member named 'remote', which holds the name of the
remote server this timer will record on. If this is NULL, it is a local timer.
- Timers from other VDRs that are connected to this VDR via SVDRP are now
@@ -8795,3 +8797,13 @@ Video Disk Recorder Revision History
".../SVDRP default host" can be used to configure automatic peering between VDRs
in the same network. Peering is disabled by default and can be enabled by setting
"SVDRP peering" to "yes".
+- The function cTimer::ToText() no longer returns a newline character at the end of
+ the string. The newline is now added by the caller as necessary. This was changed
+ because cTimer::ToText() is now also needed in a context where the terminating
+ newline can't be used. Consequently, cChannel::ToText() and cMark::ToText() have
+ been modified accordingly.
+- The "Edit timer" menu now has a new parameter "Record on", which can be used to
+ select the VDR on which this timer shall record. Timers can be freely moved
+ between connected VDRs by simply selecting the desired machine in this field.
+- The SVDRP command DELT no longer checks whether the timer that shall be deleted
+ is currently recording.
diff --git a/MANUAL b/MANUAL
index e956c29e..d5d658ff 100644
--- a/MANUAL
+++ b/MANUAL
@@ -498,6 +498,9 @@ Version 2.2
the name of the recording.
First day: The date of the first day when this timer shall start recording
(only available for repeating timers).
+ Record on: The name of the remote VDR this timer shall record on (only available
+ if there are any remote VDRs connected to this VDR). If this field
+ is empty, the timer will record on the local VDR.
A timer can also be programmed by pressing the "Red" key on the "Schedule",
"Now", "Next" or "Event" menus.
diff --git a/channels.c b/channels.c
index 005f28c9..24fec5be 100644
--- a/channels.c
+++ b/channels.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.c 4.2 2015/08/29 12:16:24 kls Exp $
+ * $Id: channels.c 4.3 2015/09/09 10:21:22 kls Exp $
*/
#include "channels.h"
@@ -554,9 +554,9 @@ cString cChannel::ToText(const cChannel *Channel)
cString buffer;
if (Channel->groupSep) {
if (Channel->number)
- buffer = cString::sprintf(":@%d %s\n", Channel->number, FullName);
+ buffer = cString::sprintf(":@%d %s", Channel->number, FullName);
else
- buffer = cString::sprintf(":%s\n", FullName);
+ buffer = cString::sprintf(":%s", FullName);
}
else {
char vpidbuf[32];
@@ -588,7 +588,7 @@ cString cChannel::ToText(const cChannel *Channel)
q = caidbuf;
q += IntArrayToString(q, Channel->caids, 16);
*q = 0;
- buffer = cString::sprintf("%s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, *Channel->parameters, *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, tpidbuf, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
+ buffer = cString::sprintf("%s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d", FullName, Channel->frequency, *Channel->parameters, *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, tpidbuf, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
}
return buffer;
}
@@ -806,7 +806,7 @@ bool cChannel::Parse(const char *s)
bool cChannel::Save(FILE *f)
{
- return fprintf(f, "%s", *ToText()) > 0;
+ return fprintf(f, "%s\n", *ToText()) > 0;
}
// --- cChannelSorter --------------------------------------------------------
diff --git a/menu.c b/menu.c
index eb49c665..2aac2054 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 4.5 2015/09/08 11:02:52 kls Exp $
+ * $Id: menu.c 4.6 2015/09/10 10:34:45 kls Exp $
*/
#include "menu.h"
@@ -999,6 +999,15 @@ cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME));
Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file)));
SetFirstDayItem();
+ if (data.remote)
+ strn0cpy(remote, data.remote, sizeof(remote));
+ else
+ *remote = 0;
+ if (GetSVDRPServerNames(&svdrpServerNames)) {
+ svdrpServerNames.Sort(true);
+ svdrpServerNames.Insert(strdup(""));
+ Add(new cMenuEditStrlItem(tr("Record on"), remote, sizeof(remote), &svdrpServerNames));
+ }
}
SetHelpKeys();
}
@@ -1053,6 +1062,70 @@ eOSState cMenuEditTimer::SetFolder(void)
return CloseSubMenu();
}
+static bool RemoteTimerError(const cTimer *Timer)
+{
+ Skins.Message(mtError, cString::sprintf(tr("Error while accessing remote timer %d@%s!"), Timer->Id(), Timer->Remote()));
+ return false; // convenience return code
+}
+
+bool cMenuEditTimer::HandleRemoteModifications(cTimer *OldTimer, cTimer *NewTimer)
+{
+ cStringList Response;
+ if (OldTimer->Local()) {
+ if (NewTimer->Local()) { // timer stays local, nothing to do
+ }
+ else { // timer is moved from local to remote
+ if (!ExecSVDRPCommand(NewTimer->Remote(), cString::sprintf("NEWT %s", *NewTimer->ToText(true)), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(NewTimer);
+ int RemoteId = atoi(SVDRPValue(Response[0]));
+ if (RemoteId <= 0)
+ return RemoteTimerError(NewTimer);
+ NewTimer->SetId(RemoteId);
+ isyslog("moved timer %s to %d@%s", *OldTimer->ToDescr(), NewTimer->Id(), NewTimer->Remote());
+ }
+ }
+ else if (NewTimer->Local()) { // timer is moved from remote to local
+ if (OldTimer->Id()) { // its an existing timer
+ if (!ExecSVDRPCommand(OldTimer->Remote(), cString::sprintf("DELT %d", OldTimer->Id()), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(OldTimer);
+ }
+ NewTimer->SetId(cTimers::NewTimerId());
+ isyslog("moved timer %d@%s to %s", OldTimer->Id(), OldTimer->Remote(), *NewTimer->ToDescr());
+ }
+ else if (strcmp(OldTimer->Remote(), NewTimer->Remote()) == 0) { // timer stays remote on same machine
+ if (OldTimer->Id()) { // its an existing timer
+ if (!ExecSVDRPCommand(OldTimer->Remote(), cString::sprintf("MODT %d %s", OldTimer->Id(), *NewTimer->ToText(true)), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(NewTimer);
+ isyslog("modified timer %s", *NewTimer->ToDescr());
+ }
+ else { // its a new timer
+ if (!ExecSVDRPCommand(NewTimer->Remote(), cString::sprintf("NEWT %s", *NewTimer->ToText(true)), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(NewTimer);
+ int RemoteId = atoi(SVDRPValue(Response[0]));
+ if (RemoteId <= 0)
+ return RemoteTimerError(NewTimer);
+ NewTimer->SetId(RemoteId);
+ isyslog("added timer %s", *NewTimer->ToDescr());
+ }
+ }
+ else { // timer is moved from one remote machine to an other
+ if (!ExecSVDRPCommand(NewTimer->Remote(), cString::sprintf("NEWT %s", *NewTimer->ToText(true)), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(NewTimer);
+ int RemoteId = atoi(SVDRPValue(Response[0]));
+ if (RemoteId <= 0)
+ return RemoteTimerError(NewTimer);
+ NewTimer->SetId(RemoteId);
+ if (OldTimer->Id()) { // its an existing timer
+ if (!ExecSVDRPCommand(OldTimer->Remote(), cString::sprintf("DELT %d", OldTimer->Id()), &Response) || SVDRPCode(Response[0]) != 250)
+ return RemoteTimerError(OldTimer);
+ isyslog("moved timer %d@%s to %s", OldTimer->Id(), OldTimer->Remote(), *NewTimer->ToDescr());
+ }
+ else // its a new timer
+ isyslog("added timer %s", *NewTimer->ToDescr());
+ }
+ return true;
+}
+
eOSState cMenuEditTimer::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
@@ -1074,6 +1147,9 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
}
if (!*data.file)
strcpy(data.file, data.Channel()->ShortName(true));
+ data.SetRemote(*remote ? remote : NULL);
+ if (!HandleRemoteModifications(timer, &data))
+ return osContinue;
*timer = data;
if (addIfConfirmed) {
Timers->Add(timer);
@@ -1215,7 +1291,7 @@ void cMenuTimers::Set(void)
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
cMenuTimerItem *Item = new cMenuTimerItem(Timer);
Add(Item);
- if (Timer == CurrentTimer)
+ if (CurrentTimer && Timer->Id() == CurrentTimer->Id() && (!Timer->Remote() && !CurrentTimer->Remote() || Timer->Remote() && CurrentTimer->Remote() && strcmp(Timer->Remote(), CurrentTimer->Remote()) == 0))
CurrentItem = Item;
}
Sort();
@@ -1255,6 +1331,11 @@ eOSState cMenuTimers::OnOff(void)
cTimer *Timer = GetTimer();
if (Timer) {
Timer->OnOff();
+ if (Timer->Remote()) {
+ cStringList Response;
+ if (!ExecSVDRPCommand(Timer->Remote(), cString::sprintf("MODT %d %s", Timer->Id(), *Timer->ToText(true)), &Response) || SVDRPCode(Response[0]) != 250)
+ Skins.Message(mtError, cString::sprintf(tr("Error while accessing timer %d@%s!"), Timer->Id(), Timer->Remote()));
+ }
LOCK_SCHEDULES_READ;
Timer->SetEventFromSchedule(Schedules);
RefreshCurrent();
@@ -1272,7 +1353,6 @@ eOSState cMenuTimers::Edit(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
- isyslog("editing timer %s", *GetTimer()->ToDescr());
return AddSubMenu(new cMenuEditTimer(GetTimer()));
}
@@ -1292,17 +1372,24 @@ eOSState cMenuTimers::Delete(void)
if (Interface->Confirm(tr("Delete timer?"))) {
if (Timer->Recording()) {
if (Interface->Confirm(tr("Timer still recording - really delete?"))) {
- Timer->Skip();
- cRecordControls::Process(Timers, time(NULL));
+ if (!Timer->Remote()) {
+ Timer->Skip();
+ cRecordControls::Process(Timers, time(NULL));
+ }
}
else
Timer = NULL;
}
if (Timer) {
- isyslog("deleting timer %s", *Timer->ToDescr());
+ if (Timer->Remote()) {
+ cStringList Response;
+ if (!ExecSVDRPCommand(Timer->Remote(), cString::sprintf("DELT %d", Timer->Id()), &Response) || SVDRPCode(Response[0]) != 250)
+ Skins.Message(mtError, cString::sprintf(tr("Error while accessing timer %d@%s!"), Timer->Id(), Timer->Remote()));
+ }
Timers->Del(Timer);
cOsdMenu::Del(Current());
Display();
+ isyslog("deleted timer %s", *Timer->ToDescr());
}
}
}
@@ -3925,6 +4012,7 @@ void cMenuSetupMisc::Set(void)
Add(new cMenuEditStrItem( tr("Setup.Miscellaneous$SVDRP host name"), data.SVDRPHostName, sizeof(data.SVDRPHostName)));
if (GetSVDRPServerNames(&svdrpServerNames)) {
svdrpServerNames.Sort(true);
+ svdrpServerNames.Insert(strdup(""));
Add(new cMenuEditStrlItem(tr("Setup.Miscellaneous$SVDRP default host"), data.SVDRPDefaultHost, sizeof(data.SVDRPDefaultHost), &svdrpServerNames));
}
}
diff --git a/menu.h b/menu.h
index d4855edc..3f380840 100644
--- a/menu.h
+++ b/menu.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.h 4.1 2015/08/31 13:34:12 kls Exp $
+ * $Id: menu.h 4.2 2015/09/08 14:04:27 kls Exp $
*/
#ifndef __MENU_H
@@ -77,12 +77,15 @@ private:
cTimer data;
int channel;
bool addIfConfirmed;
+ cStringList svdrpServerNames;
+ char remote[HOST_NAME_MAX];
cMenuEditStrItem *file;
cMenuEditDateItem *day;
cMenuEditDateItem *firstday;
eOSState SetFolder(void);
void SetFirstDayItem(void);
void SetHelpKeys(void);
+ bool HandleRemoteModifications(cTimer *OldTimer, cTimer *NewTimer);
public:
cMenuEditTimer(cTimer *Timer, bool New = false);
virtual ~cMenuEditTimer();
diff --git a/recording.c b/recording.c
index 3f5cec7c..a847c7d1 100644
--- a/recording.c
+++ b/recording.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 4.3 2015/08/29 14:42:53 kls Exp $
+ * $Id: recording.c 4.4 2015/09/09 10:21:58 kls Exp $
*/
#include "recording.h"
@@ -2018,7 +2018,7 @@ cMark::~cMark()
cString cMark::ToText(void)
{
- return cString::sprintf("%s%s%s\n", *IndexToHMSF(position, true, framesPerSecond), Comment() ? " " : "", Comment() ? Comment() : "");
+ return cString::sprintf("%s%s%s", *IndexToHMSF(position, true, framesPerSecond), Comment() ? " " : "", Comment() ? Comment() : "");
}
bool cMark::Parse(const char *s)
@@ -2037,7 +2037,7 @@ bool cMark::Parse(const char *s)
bool cMark::Save(FILE *f)
{
- return fprintf(f, "%s", *ToText()) > 0;
+ return fprintf(f, "%s\n", *ToText()) > 0;
}
// --- cMarks ----------------------------------------------------------------
diff --git a/svdrp.c b/svdrp.c
index 65be32ad..a57d58ca 100644
--- a/svdrp.c
+++ b/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.6 2015/09/08 11:08:06 kls Exp $
+ * $Id: svdrp.c 4.7 2015/09/10 10:39:45 kls Exp $
*/
#include "svdrp.h"
@@ -512,7 +512,7 @@ public:
cSVDRPClientHandler(int TcpPort, int UdpPort);
virtual ~cSVDRPClientHandler();
void SendDiscover(const char *Address = NULL);
- bool Execute(const char *ServerName, const char *Command, cStringList *Response);
+ bool Execute(const char *ServerName, const char *Command, cStringList *Response = NULL);
bool GetServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlags = sffNone);
bool TriggerFetchingTimers(const char *ServerName);
};
@@ -1305,16 +1305,13 @@ void cSVDRPServer::CmdDELT(const char *Option)
if (isnumber(Option)) {
LOCK_TIMERS_WRITE;
Timers->SetExplicitModify();
- cTimer *Timer = Timers->GetById(strtol(Option, NULL, 10));
- if (Timer && !Timer->Remote()) {
- if (!Timer->Recording()) {
- Timers->Del(Timer);
- Timers->SetModified();
- isyslog("SVDRP < %s deleted timer %s", *connection, *Timer->ToDescr());
- Reply(250, "Timer \"%s\" deleted", Option);
- }
- else
- Reply(550, "Timer \"%s\" is recording", Option);
+ if (cTimer *Timer = Timers->GetById(strtol(Option, NULL, 10))) {
+ if (Timer->Recording())
+ Timer->Skip();
+ Timers->Del(Timer);
+ Timers->SetModified();
+ isyslog("SVDRP < %s deleted timer %s", *connection, *Timer->ToDescr());
+ Reply(250, "Timer \"%s\" deleted", Option);
}
else
Reply(501, "Timer \"%s\" not defined", Option);
@@ -2566,22 +2563,10 @@ bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag)
return false;
}
-// --- cSVDRPCommand ---------------------------------------------------------
-
-cSVDRPCommand::cSVDRPCommand(const char *ServerName, const char *Command)
-{
- serverName = ServerName;
- command = Command;
-}
-
-cSVDRPCommand::~cSVDRPCommand()
-{
-}
-
-bool cSVDRPCommand::Execute(void)
+bool ExecSVDRPCommand(const char *ServerName, const char *Command, cStringList *Response)
{
cMutexLock MutexLock(&SVDRPHandlerMutex);
if (SVDRPClientHandler)
- return SVDRPClientHandler->Execute(serverName, command, &response);
+ return SVDRPClientHandler->Execute(ServerName, Command, Response);
return false;
}
diff --git a/svdrp.h b/svdrp.h
index 10c0c053..ba33fc27 100644
--- a/svdrp.h
+++ b/svdrp.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: svdrp.h 4.4 2015/09/06 12:39:24 kls Exp $
+ * $Id: svdrp.h 4.5 2015/09/09 09:44:12 kls Exp $
*/
#ifndef __SVDRP_H
@@ -12,46 +12,6 @@
#include "tools.h"
-class cSVDRPCommand {
-protected:
- cString serverName;
- cString command;
- cStringList response;
-public:
- cSVDRPCommand(const char *ServerName, const char *Command);
- ///< Sets up an SVDRP Command to be executed on the VDR with the given
- ///< ServerName. A list of all available servers can be retrieved by
- ///< calling GetSVDRPServerNames().
- ///< Command is one SVDRP command, followed by optional parameters,
- ///< just as it can be given in a normal SVDRP connection. It doesn't
- ///< need to be terminated with a newline.
- virtual ~cSVDRPCommand();
- bool Execute(void);
- ///< Sends the Command given in the constructor to the remote VDR
- ///< and collects all of the response strings.
- ///< Returns true if the data exchange was successful. Whether or
- ///< not the actual SVDRP command was successful depends on the
- ///< resulting strings from the remote VDR, which can be accessed
- ///< by calling Response(). Execute() can be called any number of
- ///< times. The list of response strings will be cleared before
- ///< the command is actually executed.
- const cStringList *Response(void) const { return &response; }
- ///< Returns the list of strings the remote VDR has sent in response
- ///< to the command. The response strings are exactly as received,
- ///< with the leading three digit reply code and possible continuation
- ///< line indicator ('-') in place.
- const char *Response(int Index) { return (Index >= 0 && Index < response.Size()) ? response[Index] : NULL; }
- ///< This is a convenience function for accessing the response strings.
- ///< Returns the string at the given Index, or NULL if Index is out
- ///< of range.
- int Code(const char *s) { return s ? atoi(s) : 0; }
- ///< Returns the value of the three digit reply code of the given
- ///< response string.
- const char *Value(const char *s) { return s && s[0] && s[1] && s[2] && s[3] ? s + 4 : NULL; }
- ///< Returns the actual value of the given response string, skipping
- ///< the three digit reply code and possible continuation line indicator.
- };
-
enum eSvdrpFetchFlags {
sffNone = 0b0000,
sffTimers = 0b0001,
@@ -72,5 +32,21 @@ bool GetSVDRPServerNames(cStringList *ServerNames, eSvdrpFetchFlags FetchFlag =
///< client has this flag set will be returned, and the client's flag
///< will be cleared.
///< Returns true if the resulting list is not empty.
+bool ExecSVDRPCommand(const char *ServerName, const char *Command, cStringList *Response = NULL);
+ ///< Sends the given SVDRP Command string to the remote VDR identified
+ ///< by ServerName and collects all of the response strings in Response.
+ ///< If no Response parameter is given, the response from command execution
+ ///< is ignored.
+ ///< Returns true if the data exchange was successful. Whether or
+ ///< not the actual SVDRP command was successful depends on the
+ ///< resulting strings from the remote VDR, which can be accessed
+ ///< through Response. If Response is given, it will be cleared before
+ ///< the command is actually executed.
+inline int SVDRPCode(const char *s) { return s ? atoi(s) : 0; }
+ ///< Returns the value of the three digit reply code of the given
+ ///< SVDRP response string.
+inline const char *SVDRPValue(const char *s) { return s && s[0] && s[1] && s[2] && s[3] ? s + 4 : NULL; }
+ ///< Returns the actual value of the given SVDRP response string, skipping
+ ///< the three digit reply code and possible continuation line indicator.
#endif //__SVDRP_H
diff --git a/timers.c b/timers.c
index 77e9096d..7fd977e2 100644
--- a/timers.c
+++ b/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.3 2015/09/08 10:01:02 kls Exp $
+ * $Id: timers.c 4.4 2015/09/09 10:42:18 kls Exp $
*/
#include "timers.h"
@@ -33,7 +33,7 @@ cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
flags = tfNone;
*file = 0;
aux = NULL;
- remote = NULL;
+ remote = *Setup.SVDRPDefaultHost ? strdup(Setup.SVDRPDefaultHost) : NULL;
event = NULL;
if (Instant)
SetFlags(tfActive | tfInstant);
@@ -91,7 +91,7 @@ cTimer::cTimer(const cEvent *Event)
flags = tfActive;
*file = 0;
aux = NULL;
- remote = NULL;
+ remote = *Setup.SVDRPDefaultHost ? strdup(Setup.SVDRPDefaultHost) : NULL;
event = NULL;
if (Event->Vps() && Setup.UseVps)
SetFlags(tfVps);
@@ -185,7 +185,7 @@ int cTimer::Compare(const cListObject &ListObject) const
cString cTimer::ToText(bool UseChannelID) const
{
strreplace(file, ':', '|');
- cString buffer = cString::sprintf("%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays, true), start, stop, priority, lifetime, file, aux ? aux : "");
+ 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 : "");
strreplace(file, '|', ':');
return buffer;
}
@@ -355,7 +355,7 @@ bool cTimer::Parse(const char *s)
bool cTimer::Save(FILE *f)
{
if (!Remote())
- return fprintf(f, "%s", *ToText(true)) > 0;
+ return fprintf(f, "%s\n", *ToText(true)) > 0;
return true;
}
@@ -726,7 +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->SetId(NewTimerId());
ti->ClrFlags(tfRecording);
Timers->SetModified();
}
@@ -735,6 +735,11 @@ bool cTimers::Load(const char *FileName)
return false;
}
+int cTimers::NewTimerId(void)
+{
+ return ++lastTimerId; // no need for locking, the caller must have a lock on the global Timers list
+}
+
const cTimer *cTimers::GetById(int Id) const
{
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
@@ -824,7 +829,7 @@ cTimers *cTimers::GetTimersWrite(cStateKey &StateKey, int TimeoutMs)
void cTimers::Add(cTimer *Timer, cTimer *After)
{
if (!Timer->Remote())
- Timer->SetId(++lastTimerId);
+ Timer->SetId(NewTimerId());
cConfig<cTimer>::Add(Timer, After);
cStatus::MsgTimerChange(Timer, tcAdd);
}
@@ -882,13 +887,13 @@ bool cTimers::GetRemoteTimers(const char *ServerName)
bool Result = false;
if (ServerName) {
Result = DelRemoteTimers(ServerName);
- cSVDRPCommand Cmd(ServerName, "LSTT ID");
- if (Cmd.Execute()) {
- const char *s;
- for (int i = 0; s = Cmd.Response(i); i++) {
- int Code = Cmd.Code(s);
+ cStringList Response;
+ if (ExecSVDRPCommand(ServerName, "LSTT ID", &Response)) {
+ for (int i = 0; i < Response.Size(); i++) {
+ const char *s = Response[i];
+ int Code = SVDRPCode(s);
if (Code == 250) {
- if (const char *v = Cmd.Value(s)) {
+ if (const char *v = SVDRPValue(s)) {
int Id = atoi(v);
while (*v && *v != ' ')
v++; // skip id
@@ -939,8 +944,7 @@ bool cTimers::DelRemoteTimers(const char *ServerName)
void cTimers::TriggerRemoteTimerPoll(const char *ServerName)
{
if (ServerName) {
- cSVDRPCommand Cmd(ServerName, cString::sprintf("POLL %s TIMERS", Setup.SVDRPHostName));
- if (!Cmd.Execute())
+ if (!ExecSVDRPCommand(ServerName, cString::sprintf("POLL %s TIMERS", Setup.SVDRPHostName)))
esyslog("ERROR: can't send 'POLL %s TIMERS' to '%s'", Setup.SVDRPHostName, ServerName);
}
else {
diff --git a/timers.h b/timers.h
index 38eb9284..4222c104 100644
--- a/timers.h
+++ b/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.2 2015/09/05 13:51:33 kls Exp $
+ * $Id: timers.h 4.3 2015/09/09 10:40:24 kls Exp $
*/
#ifndef __TIMERS_H
@@ -67,6 +67,7 @@ public:
time_t FirstDay(void) const { return weekdays ? day : 0; }
const char *Aux(void) const { return aux; }
const char *Remote(void) const { return remote; }
+ bool Local(void) const { return !remote; } // convenience
time_t Deferred(void) const { return deferred; }
cString ToText(bool UseChannelID = false) const;
cString ToDescr(void) const;
@@ -166,6 +167,7 @@ public:
///< StateKey.Remove();
///< }
static bool Load(const char *FileName);
+ static int NewTimerId(void);
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);