diff options
| -rw-r--r-- | HISTORY | 7 | ||||
| -rw-r--r-- | MANUAL | 4 | ||||
| -rw-r--r-- | config.c | 5 | ||||
| -rw-r--r-- | config.h | 3 | ||||
| -rw-r--r-- | i18n.c | 7 | ||||
| -rw-r--r-- | interface.c | 16 | ||||
| -rw-r--r-- | menu.c | 3 | ||||
| -rw-r--r-- | svdrp.c | 54 | ||||
| -rw-r--r-- | svdrp.h | 8 | ||||
| -rwxr-xr-x | svdrpsend.pl | 57 | 
10 files changed, 147 insertions, 17 deletions
| @@ -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"). @@ -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 @@ -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); @@ -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); @@ -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", diff --git a/interface.c b/interface.c index 2346f6ca..55cdb0b9 100644 --- a/interface.c +++ b/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); @@ -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) @@ -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??? @@ -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 diff --git a/svdrpsend.pl b/svdrpsend.pl new file mode 100755 index 00000000..5efd504b --- /dev/null +++ b/svdrpsend.pl @@ -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; +} + | 
