mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
When remote timers are fetched from a peer VDR, we no longer blindly delete and re-add them, but rather compare them and make only the minimum necessary changes
This commit is contained in:
parent
3a3a233994
commit
9c3ce0048a
4
HISTORY
4
HISTORY
@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History
|
|||||||
a subdirectory.
|
a subdirectory.
|
||||||
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
|
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
|
||||||
|
|
||||||
2018-02-27: Version 2.3.9
|
2018-02-28: Version 2.3.9
|
||||||
|
|
||||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||||
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
||||||
@ -9286,3 +9286,5 @@ Video Disk Recorder Revision History
|
|||||||
- Moved handling remote timers into cSVDRPClientHandler::ProcessConnections().
|
- Moved handling remote timers into cSVDRPClientHandler::ProcessConnections().
|
||||||
- Combined Start/StopSVDRPServer/ClientHandler() into Start/StopSVDRPHandler().
|
- Combined Start/StopSVDRPServer/ClientHandler() into Start/StopSVDRPHandler().
|
||||||
- Updated the Polish OSD texts (thanks to Tomasz Maciej Nowak).
|
- Updated the Polish OSD texts (thanks to Tomasz Maciej Nowak).
|
||||||
|
- When remote timers are fetched from a peer VDR, we no longer blindly delete and re-add
|
||||||
|
them, but rather compare them and make only the minimum necessary changes.
|
||||||
|
21
svdrp.c
21
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* graphical interface that sits on top of an SVDRP connection.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.c 4.30 2018/02/26 15:42:15 kls Exp $
|
* $Id: svdrp.c 4.31 2018/02/28 10:04:00 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -483,8 +483,23 @@ bool cSVDRPClient::HasFetchFlag(eSvdrpFetchFlags Flag)
|
|||||||
|
|
||||||
bool cSVDRPClient::GetRemoteTimers(cStringList &Response)
|
bool cSVDRPClient::GetRemoteTimers(cStringList &Response)
|
||||||
{
|
{
|
||||||
if (HasFetchFlag(sffTimers))
|
if (HasFetchFlag(sffTimers)) {
|
||||||
return Execute("LSTT ID", &Response);
|
if (Execute("LSTT ID", &Response)) {
|
||||||
|
for (int i = 0; i < Response.Size(); i++) {
|
||||||
|
char *s = Response[i];
|
||||||
|
int Code = SVDRPCode(s);
|
||||||
|
if (Code == 250)
|
||||||
|
strshift(s, 4);
|
||||||
|
else {
|
||||||
|
if (Code != 550)
|
||||||
|
esyslog("ERROR: %s: %s", ServerName(), s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Response.SortNumerically();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
121
timers.c
121
timers.c
@ -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 4.15 2018/02/25 13:05:03 kls Exp $
|
* $Id: timers.c 4.16 2018/02/28 10:05:52 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
@ -900,45 +900,102 @@ bool cTimers::DeleteExpired(void)
|
|||||||
|
|
||||||
bool cTimers::StoreRemoteTimers(const char *ServerName, const cStringList *RemoteTimers)
|
bool cTimers::StoreRemoteTimers(const char *ServerName, const cStringList *RemoteTimers)
|
||||||
{
|
{
|
||||||
//TODO handle only new/deleted/modified timers?
|
|
||||||
bool Result = false;
|
bool Result = false;
|
||||||
// Delete old remote timers:
|
if (!ServerName || !RemoteTimers || RemoteTimers->Size() == 0) {
|
||||||
cTimer *Timer = First();
|
// Remove remote timers from this list:
|
||||||
while (Timer) {
|
cTimer *Timer = First();
|
||||||
cTimer *t = Next(Timer);
|
while (Timer) {
|
||||||
if (Timer->Remote() && (!ServerName || strcmp(Timer->Remote(), ServerName) == 0)) {
|
cTimer *t = Next(Timer);
|
||||||
Del(Timer);
|
if (Timer->Remote() && (!ServerName || strcmp(Timer->Remote(), ServerName) == 0)) {
|
||||||
Result = true;
|
Del(Timer);
|
||||||
|
Result = true;
|
||||||
|
}
|
||||||
|
Timer = t;
|
||||||
}
|
}
|
||||||
Timer = t;
|
return Result;
|
||||||
}
|
}
|
||||||
// Add new remote timers:
|
// Collect all locally stored remote timers from ServerName:
|
||||||
if (ServerName && RemoteTimers) {
|
cStringList tl;
|
||||||
for (int i = 0; i < RemoteTimers->Size(); i++) {
|
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||||
const char *s = (*RemoteTimers)[i];
|
if (ti->Remote() && strcmp(ti->Remote(), ServerName) == 0)
|
||||||
int Code = SVDRPCode(s);
|
tl.Append(strdup(cString::sprintf("%d %s", ti->Id(), *ti->ToText(true))));
|
||||||
if (Code == 250) {
|
}
|
||||||
if (const char *v = SVDRPValue(s)) {
|
tl.SortNumerically(); // RemoteTimers is also sorted numerically!
|
||||||
int Id = atoi(v);
|
// Compare the two lists and react accordingly:
|
||||||
while (*v && *v != ' ')
|
int il = 0; // index into the local ("left") list of remote timers
|
||||||
v++; // skip id
|
int ir = 0; // index into the remote ("right") list of timers
|
||||||
cTimer *Timer = new cTimer;
|
int sl = tl.Size();
|
||||||
if (Timer->Parse(v)) {
|
int sr = RemoteTimers->Size();
|
||||||
Timer->SetRemote(ServerName);
|
for (;;) {
|
||||||
Timer->SetId(Id);
|
int AddTimer = 0;
|
||||||
Add(Timer);
|
int DelTimer = 0;
|
||||||
|
if (il < sl) { // still have left entries
|
||||||
|
int nl = atoi(tl[il]);
|
||||||
|
if (ir < sr) { // still have right entries
|
||||||
|
// Compare timers:
|
||||||
|
int nr = atoi((*RemoteTimers)[ir]);
|
||||||
|
if (nl == nr) // same timer id
|
||||||
|
AddTimer = DelTimer = nl;
|
||||||
|
else if (nl < nr) // left entry not in right list
|
||||||
|
DelTimer = nl;
|
||||||
|
else // right entry not in left list
|
||||||
|
AddTimer = nr;
|
||||||
|
}
|
||||||
|
else // processed all right entries
|
||||||
|
DelTimer = nl;
|
||||||
|
}
|
||||||
|
else if (ir < sr) // still have right entries
|
||||||
|
AddTimer = atoi((*RemoteTimers)[ir]);
|
||||||
|
else // processed all left and right entries
|
||||||
|
break;
|
||||||
|
if (AddTimer && DelTimer) {
|
||||||
|
if (strcmp(tl[il], (*RemoteTimers)[ir]) != 0) {
|
||||||
|
// Overwrite timer:
|
||||||
|
char *v = (*RemoteTimers)[ir];
|
||||||
|
while (*v && *v != ' ')
|
||||||
|
v++; // skip id
|
||||||
|
if (cTimer *l = GetById(DelTimer, ServerName)) {
|
||||||
|
cTimer r;
|
||||||
|
if (r.Parse(v)) {
|
||||||
|
r.SetRemote(ServerName);
|
||||||
|
r.SetId(AddTimer);
|
||||||
|
*l = r;
|
||||||
Result = true;
|
Result = true;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
esyslog("ERROR: %s: error in timer settings: %s", ServerName, v);
|
esyslog("ERROR: %s: error in timer settings: %s", ServerName, v);
|
||||||
delete Timer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Code != 550)
|
else // identical timer, nothing to do
|
||||||
esyslog("ERROR: %s: %s", ServerName, s);
|
;
|
||||||
|
il++;
|
||||||
|
ir++;
|
||||||
}
|
}
|
||||||
}
|
else if (AddTimer) {
|
||||||
|
char *v = (*RemoteTimers)[ir];
|
||||||
|
while (*v && *v != ' ')
|
||||||
|
v++; // skip id
|
||||||
|
cTimer *Timer = new cTimer;
|
||||||
|
if (Timer->Parse(v)) {
|
||||||
|
Timer->SetRemote(ServerName);
|
||||||
|
Timer->SetId(AddTimer);
|
||||||
|
Add(Timer);
|
||||||
|
Result = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
esyslog("ERROR: %s: error in timer settings: %s", ServerName, v);
|
||||||
|
delete Timer;
|
||||||
|
}
|
||||||
|
ir++;
|
||||||
|
}
|
||||||
|
else if (DelTimer) {
|
||||||
|
if (cTimer *t = GetById(DelTimer, ServerName)) {
|
||||||
|
Del(t);
|
||||||
|
Result = true;
|
||||||
|
}
|
||||||
|
il++;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
timers.h
6
timers.h
@ -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 4.10 2018/02/25 12:54:55 kls Exp $
|
* $Id: timers.h 4.11 2018/02/27 13:57:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TIMERS_H
|
#ifndef __TIMERS_H
|
||||||
@ -190,7 +190,9 @@ public:
|
|||||||
///< this list. If no ServerName is given, all remote timers from all peer machines
|
///< this list. If no ServerName is given, all remote timers from all peer machines
|
||||||
///< will be removed from this list. If no RemoteTimers are given, only the remote
|
///< will be removed from this list. If no RemoteTimers are given, only the remote
|
||||||
///< timers from ServerName will be removed from this list.
|
///< timers from ServerName will be removed from this list.
|
||||||
///< Returns true if any remote timers have been added or deleted
|
///< The given list of RemoteTimers must be sorted numerically (by a call to its
|
||||||
|
///< SortNumerically() function).
|
||||||
|
///< Returns true if any remote timers have been added, deleted or modified.
|
||||||
};
|
};
|
||||||
|
|
||||||
bool HandleRemoteTimerModifications(cTimer *NewTimer, cTimer *OldTimer = NULL, cString *Msg = NULL);
|
bool HandleRemoteTimerModifications(cTimer *NewTimer, cTimer *OldTimer = NULL, cString *Msg = NULL);
|
||||||
|
14
tools.c
14
tools.c
@ -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: tools.c 4.8 2017/06/25 11:45:39 kls Exp $
|
* $Id: tools.c 4.9 2018/02/27 10:09:21 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
@ -296,6 +296,18 @@ cString strgetval(const char *s, const char *name, char d)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strshift(char *s, int n)
|
||||||
|
{
|
||||||
|
if (s && n > 0) {
|
||||||
|
int l = strlen(s);
|
||||||
|
if (n < l)
|
||||||
|
memmove(s, s + n, l - n + 1); // we also copy the terminating 0!
|
||||||
|
else
|
||||||
|
*s = 0;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
bool startswith(const char *s, const char *p)
|
bool startswith(const char *s, const char *p)
|
||||||
{
|
{
|
||||||
while (*p) {
|
while (*p) {
|
||||||
|
18
tools.h
18
tools.h
@ -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: tools.h 4.13 2017/06/25 11:45:38 kls Exp $
|
* $Id: tools.h 4.14 2018/02/28 10:06:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -226,6 +226,12 @@ cString strgetval(const char *s, const char *name, char d = '=');
|
|||||||
///< If an other delimiter shall be used (like, e.g., ':'), it can be given
|
///< If an other delimiter shall be used (like, e.g., ':'), it can be given
|
||||||
///< as the third parameter.
|
///< as the third parameter.
|
||||||
///< If name occurs more than once in s, only the first occurrence is taken.
|
///< If name occurs more than once in s, only the first occurrence is taken.
|
||||||
|
char *strshift(char *s, int n);
|
||||||
|
///< Shifts the given string to the left by the given number of bytes, thus
|
||||||
|
///< removing the first n bytes from s.
|
||||||
|
///< If n is greater than the length of s, the resulting string will be empty.
|
||||||
|
///< If n is <= 0 s will be unchanged.
|
||||||
|
///< Returns s.
|
||||||
bool startswith(const char *s, const char *p);
|
bool startswith(const char *s, const char *p);
|
||||||
bool endswith(const char *s, const char *p);
|
bool endswith(const char *s, const char *p);
|
||||||
bool isempty(const char *s);
|
bool isempty(const char *s);
|
||||||
@ -781,6 +787,12 @@ inline int CompareStringsIgnoreCase(const void *a, const void *b)
|
|||||||
return strcasecmp(*(const char **)a, *(const char **)b);
|
return strcasecmp(*(const char **)a, *(const char **)b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int CompareStringsNumerically(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
int d = atoi(*(const char **)a) - atoi(*(const char **)b);
|
||||||
|
return d ? d : CompareStrings(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
class cStringList : public cVector<char *> {
|
class cStringList : public cVector<char *> {
|
||||||
public:
|
public:
|
||||||
cStringList(int Allocated = 10): cVector<char *>(Allocated) {}
|
cStringList(int Allocated = 10): cVector<char *>(Allocated) {}
|
||||||
@ -793,6 +805,10 @@ public:
|
|||||||
else
|
else
|
||||||
cVector<char *>::Sort(CompareStrings);
|
cVector<char *>::Sort(CompareStrings);
|
||||||
}
|
}
|
||||||
|
void SortNumerically(void)
|
||||||
|
{
|
||||||
|
cVector<char *>::Sort(CompareStringsNumerically);
|
||||||
|
}
|
||||||
virtual void Clear(void);
|
virtual void Clear(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user