mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
New SVDRP command MESG; SVDRP can reuse port; SVDRP timeout
This commit is contained in:
parent
c464c4f9b9
commit
3586013b8f
7
HISTORY
7
HISTORY
@ -350,7 +350,7 @@ Video Disk Recorder Revision History
|
||||
- Encrypted channels can now be selected even without knowing the PNR (however, it
|
||||
is still necessary for the EPG info).
|
||||
|
||||
2001-02-11: Version 0.71
|
||||
2001-02-18: Version 0.71
|
||||
|
||||
- Fixed 'Transfer Mode' in cases where a non-primary interface was switched to
|
||||
a channel that only the primary interface can receive (which could happen in
|
||||
@ -392,3 +392,8 @@ Video Disk Recorder Revision History
|
||||
- When removing recordings empty directories are now removed from the video
|
||||
directory.
|
||||
- Added the "schnitt" tools from Matthias Schniedermeyer.
|
||||
- New SVDRP command MESG to display a short message on the OSD.
|
||||
- The Perl script 'svdrpsend.pl' can be used to send SVDRP commands to VDR.
|
||||
- SVDRP can now immediately reuse the same port if VDR is restarted.
|
||||
- SVDRP now has a timeout after which the connection is automatically closed
|
||||
(default is 300 seconds, can be changed in "Setup").
|
||||
|
4
MANUAL
4
MANUAL
@ -328,6 +328,10 @@ Video Disk Recorder User's Manual
|
||||
to keep the EPG up-to-date.
|
||||
A value of '0' turns off scanning on a single card system.
|
||||
|
||||
SVDRPTimeout = 300 The time (in seconds) of inactivity on an open SVDRP
|
||||
connection after which the connection is automatically
|
||||
closed. Default is 300, a value of 0 means no timeout.
|
||||
|
||||
* Executing system commands
|
||||
|
||||
The "Main" menu option "Commands" allows you to execute any system commands
|
||||
|
5
config.c
5
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.41 2001/02/11 11:22:48 kls Exp $
|
||||
* $Id: config.c 1.42 2001/02/18 13:11:59 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -738,6 +738,7 @@ cSetup::cSetup(void)
|
||||
MarginStart = 2;
|
||||
MarginStop = 10;
|
||||
EPGScanTimeout = 5;
|
||||
SVDRPTimeout = 300;
|
||||
CurrentChannel = -1;
|
||||
}
|
||||
|
||||
@ -758,6 +759,7 @@ bool cSetup::Parse(char *s)
|
||||
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
|
||||
else
|
||||
return false;
|
||||
@ -811,6 +813,7 @@ bool cSetup::Save(const char *FileName)
|
||||
fprintf(f, "MarginStart = %d\n", MarginStart);
|
||||
fprintf(f, "MarginStop = %d\n", MarginStop);
|
||||
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
|
||||
fprintf(f, "SVDRPTimeout = %d\n", SVDRPTimeout);
|
||||
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
|
||||
f.Close();
|
||||
isyslog(LOG_INFO, "saved setup to %s", FileName);
|
||||
|
3
config.h
3
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.40 2001/02/03 15:55:45 kls Exp $
|
||||
* $Id: config.h 1.41 2001/02/18 13:12:06 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -269,6 +269,7 @@ public:
|
||||
int SetSystemTime;
|
||||
int MarginStart, MarginStop;
|
||||
int EPGScanTimeout;
|
||||
int SVDRPTimeout;
|
||||
int CurrentChannel;
|
||||
cSetup(void);
|
||||
bool Load(const char *FileName);
|
||||
|
7
i18n.c
7
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.12 2001/02/13 22:17:27 kls Exp $
|
||||
* $Id: i18n.c 1.13 2001/02/18 13:14:00 kls Exp $
|
||||
*
|
||||
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
|
||||
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
|
||||
@ -416,6 +416,11 @@ const tPhrase Phrases[] = {
|
||||
"Cas do EPG pregleda",
|
||||
"Timeout EPG",
|
||||
},
|
||||
{ "SVDRPTimeout",
|
||||
"SVDRP Timeout",
|
||||
"", // TODO
|
||||
"Timeout SVDRP",
|
||||
},
|
||||
// The days of the week:
|
||||
{ "MTWTFSS",
|
||||
"MDMDFSS",
|
||||
|
16
interface.c
16
interface.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.c 1.34 2001/02/02 14:49:39 kls Exp $
|
||||
* $Id: interface.c 1.35 2001/02/18 10:46:13 kls Exp $
|
||||
*/
|
||||
|
||||
#include "interface.h"
|
||||
@ -70,8 +70,16 @@ unsigned int cInterface::GetCh(bool Wait, bool *Repeat, bool *Release)
|
||||
eKeys cInterface::GetKey(bool Wait)
|
||||
{
|
||||
Flush();
|
||||
if (SVDRP)
|
||||
if (SVDRP) {
|
||||
SVDRP->Process();
|
||||
if (!open) {
|
||||
char *message = SVDRP->GetMessage();
|
||||
if (message) {
|
||||
Info(message);
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
eKeys Key = keyFromWait;
|
||||
if (Key == kNone) {
|
||||
bool Repeat = false, Release = false;
|
||||
@ -281,7 +289,7 @@ void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||
void cInterface::Info(const char *s)
|
||||
{
|
||||
Open();
|
||||
isyslog(LOG_INFO, s);
|
||||
isyslog(LOG_INFO, "info: %s", s);
|
||||
Status(s, clrWhite, clrGreen);
|
||||
Wait();
|
||||
Status(NULL);
|
||||
@ -291,7 +299,7 @@ void cInterface::Info(const char *s)
|
||||
void cInterface::Error(const char *s)
|
||||
{
|
||||
Open();
|
||||
esyslog(LOG_ERR, s);
|
||||
esyslog(LOG_ERR, "ERROR: %s", s);
|
||||
Status(s, clrWhite, clrRed);
|
||||
Wait();
|
||||
Status(NULL);
|
||||
|
3
menu.c
3
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 1.65 2001/02/11 11:01:47 kls Exp $
|
||||
* $Id: menu.c 1.66 2001/02/18 13:12:32 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -1608,6 +1608,7 @@ void cMenuSetup::Set(void)
|
||||
Add(new cMenuEditIntItem( tr("MarginStart"), &data.MarginStart));
|
||||
Add(new cMenuEditIntItem( tr("MarginStop"), &data.MarginStop));
|
||||
Add(new cMenuEditIntItem( tr("EPGScanTimeout"), &data.EPGScanTimeout));
|
||||
Add(new cMenuEditIntItem( tr("SVDRPTimeout"), &data.SVDRPTimeout));
|
||||
}
|
||||
|
||||
eOSState cMenuSetup::ProcessKey(eKeys Key)
|
||||
|
54
svdrp.c
54
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 1.13 2000/12/03 15:34:35 kls Exp $
|
||||
* $Id: svdrp.c 1.14 2001/02/18 14:18:13 kls Exp $
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@ -63,6 +63,10 @@ bool cSocket::Open(void)
|
||||
port = 0;
|
||||
return false;
|
||||
}
|
||||
// allow it to always reuse the same port:
|
||||
int ReUseAddr = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ReUseAddr, sizeof(ReUseAddr));
|
||||
//
|
||||
struct sockaddr_in name;
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_port = htons(port);
|
||||
@ -137,6 +141,12 @@ const char *HelpPages[] = {
|
||||
"LSTT [ <number> ]\n"
|
||||
" List timers. Without option, all timers are listed. Otherwise\n"
|
||||
" only the given timer is listed.",
|
||||
"MESG [ <message> ]\n"
|
||||
" Displays the given message on the OSD. If message is omitted, the\n"
|
||||
" currently pending message (if any) will be returned. The message\n"
|
||||
" will be displayed for a few seconds as soon as the OSD has become\n"
|
||||
" idle. If a new MESG command is entered while the previous message\n"
|
||||
" has not yet been displayed, the old message will be overwritten.",
|
||||
"MODC <number> <settings>\n"
|
||||
" Modify a channel. Settings must be in the same format as returned\n"
|
||||
" by the LSTC command.",
|
||||
@ -224,22 +234,25 @@ const char *GetHelpPage(const char *Cmd)
|
||||
cSVDRP::cSVDRP(int Port)
|
||||
:socket(Port)
|
||||
{
|
||||
message = NULL;
|
||||
lastActivity = 0;
|
||||
isyslog(LOG_INFO, "SVDRP listening on port %d", Port);
|
||||
}
|
||||
|
||||
cSVDRP::~cSVDRP()
|
||||
{
|
||||
Close();
|
||||
delete message;
|
||||
}
|
||||
|
||||
void cSVDRP::Close(void)
|
||||
void cSVDRP::Close(bool Timeout)
|
||||
{
|
||||
if (file.IsOpen()) {
|
||||
//TODO how can we get the *full* hostname?
|
||||
char buffer[MAXCMDBUFFER];
|
||||
gethostname(buffer, sizeof(buffer));
|
||||
Reply(221, "%s closing connection", buffer);
|
||||
isyslog(LOG_INFO, "closing connection"); //TODO store IP#???
|
||||
Reply(221, "%s closing connection%s", buffer, Timeout ? " (timeout)" : "");
|
||||
isyslog(LOG_INFO, "closing SVDRP connection"); //TODO store IP#???
|
||||
file.Close();
|
||||
}
|
||||
}
|
||||
@ -557,6 +570,20 @@ void cSVDRP::CmdLSTT(const char *Option)
|
||||
}
|
||||
}
|
||||
|
||||
void cSVDRP::CmdMESG(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
delete message;
|
||||
message = strdup(Option);
|
||||
isyslog(LOG_INFO, "SVDRP message: '%s'", message);
|
||||
Reply(250, "Message stored");
|
||||
}
|
||||
else if (message)
|
||||
Reply(250, "%s", message);
|
||||
else
|
||||
Reply(550, "No pending message");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdMODC(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
@ -820,6 +847,7 @@ void cSVDRP::Execute(char *Cmd)
|
||||
else if (CMD("HITK")) CmdHITK(s);
|
||||
else if (CMD("LSTC")) CmdLSTC(s);
|
||||
else if (CMD("LSTT")) CmdLSTT(s);
|
||||
else if (CMD("MESG")) CmdMESG(s);
|
||||
else if (CMD("MODC")) CmdMODC(s);
|
||||
else if (CMD("MODT")) CmdMODT(s);
|
||||
else if (CMD("MOVC")) CmdMOVC(s);
|
||||
@ -839,7 +867,8 @@ void cSVDRP::Execute(char *Cmd)
|
||||
|
||||
void cSVDRP::Process(void)
|
||||
{
|
||||
bool SendGreeting = !file.IsOpen();
|
||||
bool NewConnection = !file.IsOpen();
|
||||
bool SendGreeting = NewConnection;
|
||||
|
||||
if (file.IsOpen() || file.Open(socket.Accept())) {
|
||||
char buffer[MAXCMDBUFFER];
|
||||
@ -849,6 +878,8 @@ void cSVDRP::Process(void)
|
||||
time_t now = time(NULL);
|
||||
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now));
|
||||
}
|
||||
if (NewConnection)
|
||||
lastActivity = time(NULL);
|
||||
int rbytes = file.ReadString(buffer, sizeof(buffer) - 1);
|
||||
if (rbytes > 0) {
|
||||
//XXX overflow check???
|
||||
@ -859,11 +890,22 @@ void cSVDRP::Process(void)
|
||||
buffer[rbytes] = 0;
|
||||
// showtime!
|
||||
Execute(buffer);
|
||||
lastActivity = time(NULL);
|
||||
}
|
||||
else if (rbytes < 0)
|
||||
Close();
|
||||
else if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
|
||||
isyslog(LOG_INFO, "timeout on SVDRP connection");
|
||||
Close(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO timeout???
|
||||
char *cSVDRP::GetMessage(void)
|
||||
{
|
||||
char *s = message;
|
||||
message = NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
//TODO more than one connection???
|
||||
|
8
svdrp.h
8
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 1.6 2000/09/17 13:22:04 kls Exp $
|
||||
* $Id: svdrp.h 1.7 2001/02/18 13:36:47 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SVDRP_H
|
||||
@ -31,7 +31,9 @@ private:
|
||||
cSocket socket;
|
||||
cFile file;
|
||||
CRect ovlClipRects[MAXCLIPRECTS];
|
||||
void Close(void);
|
||||
char *message;
|
||||
time_t lastActivity;
|
||||
void Close(bool Timeout = false);
|
||||
bool Send(const char *s, int length = -1);
|
||||
void Reply(int Code, const char *fmt, ...);
|
||||
void CmdCHAN(const char *Option);
|
||||
@ -42,6 +44,7 @@ private:
|
||||
void CmdHITK(const char *Option);
|
||||
void CmdLSTC(const char *Option);
|
||||
void CmdLSTT(const char *Option);
|
||||
void CmdMESG(const char *Option);
|
||||
void CmdMODC(const char *Option);
|
||||
void CmdMODT(const char *Option);
|
||||
void CmdMOVC(const char *Option);
|
||||
@ -59,6 +62,7 @@ public:
|
||||
cSVDRP(int Port);
|
||||
~cSVDRP();
|
||||
void Process(void);
|
||||
char *GetMessage(void);
|
||||
};
|
||||
|
||||
#endif //__SVDRP_H
|
||||
|
57
svdrpsend.pl
Executable file
57
svdrpsend.pl
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use Socket;
|
||||
use Getopt::Std;
|
||||
|
||||
$Usage = qq{
|
||||
Usage: $0 options command...
|
||||
|
||||
Options: -d hostname destination hostname (default: localhost)
|
||||
-p port SVDRP port number (default: 2001)
|
||||
};
|
||||
|
||||
die $Usage if (!$ARGV[0] || !getopts("d:p:"));
|
||||
|
||||
$Dest = $opt_d || "localhost";
|
||||
$Port = $opt_p || 2001;
|
||||
$Cmd = "@ARGV" || Error("missing command");
|
||||
|
||||
$Timeout = 10; # max. seconds to wait for response
|
||||
|
||||
$SIG{ALRM} = sub { Error("timeout"); };
|
||||
alarm($Timeout);
|
||||
|
||||
$iaddr = inet_aton($Dest) || Error("no host: $Dest");
|
||||
$paddr = sockaddr_in($Port, $iaddr);
|
||||
|
||||
$proto = getprotobyname('tcp');
|
||||
socket(SOCK, PF_INET, SOCK_STREAM, $proto) || Error("socket: $!");
|
||||
connect(SOCK, $paddr) || Error("connect: $!");
|
||||
select(SOCK); $| = 1;
|
||||
Receive();
|
||||
Send($Cmd);
|
||||
Send("quit");
|
||||
close(SOCK) || Error("close: $!");
|
||||
|
||||
sub Send
|
||||
{
|
||||
my $cmd = shift || Error("no command to send");
|
||||
print SOCK "$cmd\r\n";
|
||||
Receive();
|
||||
}
|
||||
|
||||
sub Receive
|
||||
{
|
||||
while (<SOCK>) {
|
||||
print STDOUT $_;
|
||||
last if substr($_, 3, 1) ne "-";
|
||||
}
|
||||
}
|
||||
|
||||
sub Error
|
||||
{
|
||||
print STDERR "@_\n";
|
||||
close(SOCK);
|
||||
exit 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user