mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The SVDRP port now accepts multiple concurrent connections
This commit is contained in:
parent
b6af7a9cf9
commit
2b9e988dd5
14
HISTORY
14
HISTORY
@ -8596,7 +8596,7 @@ Video Disk Recorder Revision History
|
||||
- Bumped all version numbers to 2.2.0.
|
||||
- Official release.
|
||||
|
||||
2015-04-19: Version 2.3.1
|
||||
2015-04-29: Version 2.3.1
|
||||
|
||||
- The new function cOsd::MaxPixmapSize() can be called to determine the maximum size
|
||||
a cPixmap may have on the current OSD. The 'osddemo' example has been modified
|
||||
@ -8645,3 +8645,15 @@ Video Disk Recorder Revision History
|
||||
//#define DEPRECATED_GETBITMAP
|
||||
in osd.h as a quick workaround. In the long run the plugin will need to be adapted.
|
||||
- The -u option now also accepts a numerical user id (suggested by Derek Kelly).
|
||||
- The SVDRP port now accepts multiple concurrent connections. You can now keep an
|
||||
SVDRP connection open as long as you wish, without preventing others from
|
||||
connecting. Note, though, that SVDRP connections still get closed automatically
|
||||
if there has been no activity for 300 seconds (configurable via
|
||||
"Setup/Miscellaneous/SVDRP timeout (s)").
|
||||
- The SVDRP log messages have been unified and now always contain the IP and port
|
||||
number of the remote host.
|
||||
- SVDRP connections are now handled in a separate thread, which makes them more
|
||||
responsive. Note that there is only one thread that handles all concurrent SVDRP
|
||||
connections. That way each SVDRP command is guaranteed to be processed separately,
|
||||
without interfering with any other SVDRP commands that might be issued at the same
|
||||
time.
|
||||
|
12
interface.c
12
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 3.1 2015/01/11 13:37:47 kls Exp $
|
||||
* $Id: interface.c 4.1 2015/04/28 11:16:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "interface.h"
|
||||
@ -19,27 +19,19 @@
|
||||
|
||||
cInterface *Interface = NULL;
|
||||
|
||||
cInterface::cInterface(int SVDRPport)
|
||||
cInterface::cInterface(void)
|
||||
{
|
||||
interrupted = false;
|
||||
SVDRP = NULL;
|
||||
if (SVDRPport)
|
||||
SVDRP = new cSVDRP(SVDRPport);
|
||||
}
|
||||
|
||||
cInterface::~cInterface()
|
||||
{
|
||||
delete SVDRP;
|
||||
}
|
||||
|
||||
eKeys cInterface::GetKey(bool Wait)
|
||||
{
|
||||
if (!cRemote::HasKeys())
|
||||
Skins.Flush();
|
||||
if (SVDRP) {
|
||||
if (SVDRP->Process())
|
||||
Wait = false;
|
||||
}
|
||||
if (!cRemote::IsLearning())
|
||||
return cRemote::Get(Wait ? 1000 : 10);
|
||||
else
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.31 2004/05/01 11:11:13 kls Exp $
|
||||
* $Id: interface.h 4.1 2015/04/28 11:15:11 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
@ -13,17 +13,14 @@
|
||||
#include "config.h"
|
||||
#include "remote.h"
|
||||
#include "skins.h"
|
||||
#include "svdrp.h"
|
||||
|
||||
class cInterface {
|
||||
private:
|
||||
bool interrupted;
|
||||
cSVDRP *SVDRP;
|
||||
bool QueryKeys(cRemote *Remote, cSkinDisplayMenu *DisplayMenu);
|
||||
public:
|
||||
cInterface(int SVDRPport = 0);
|
||||
cInterface(void);
|
||||
~cInterface();
|
||||
bool HasSVDRPConnection(void) { return SVDRP && SVDRP->HasConnection(); }
|
||||
void Interrupt(void) { interrupted = true; }
|
||||
eKeys GetKey(bool Wait = true);
|
||||
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
||||
|
234
svdrp.c
234
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 3.6 2015/01/12 11:16:27 kls Exp $
|
||||
* $Id: svdrp.c 4.1 2015/04/29 13:10:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -33,14 +33,32 @@
|
||||
#include "keys.h"
|
||||
#include "menu.h"
|
||||
#include "plugin.h"
|
||||
#include "recording.h"
|
||||
#include "remote.h"
|
||||
#include "skins.h"
|
||||
#include "thread.h"
|
||||
#include "timers.h"
|
||||
#include "tools.h"
|
||||
#include "videodir.h"
|
||||
|
||||
// --- cSocket ---------------------------------------------------------------
|
||||
|
||||
class cSocket {
|
||||
private:
|
||||
int port;
|
||||
int sock;
|
||||
int queue;
|
||||
cString lastAcceptedConnection;
|
||||
public:
|
||||
cSocket(int Port, int Queue = 1);
|
||||
~cSocket();
|
||||
bool Open(void);
|
||||
void Close(void);
|
||||
int Socket(void) const { return sock; }
|
||||
int Accept(void);
|
||||
const char *LastAcceptedConnection(void) const { return lastAcceptedConnection; }
|
||||
};
|
||||
|
||||
cSocket::cSocket(int Port, int Queue)
|
||||
{
|
||||
port = Port;
|
||||
@ -100,6 +118,7 @@ bool cSocket::Open(void)
|
||||
LOG_ERROR;
|
||||
return false;
|
||||
}
|
||||
isyslog("SVDRP listening on port %d/tcp", port);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -110,7 +129,7 @@ int cSocket::Accept(void)
|
||||
struct sockaddr_in clientname;
|
||||
uint size = sizeof(clientname);
|
||||
int newsock = accept(sock, (struct sockaddr *)&clientname, &size);
|
||||
if (newsock > 0) {
|
||||
if (newsock >= 0) {
|
||||
bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
|
||||
if (!accepted) {
|
||||
const char *s = "Access denied!\n";
|
||||
@ -119,7 +138,8 @@ int cSocket::Accept(void)
|
||||
close(newsock);
|
||||
newsock = -1;
|
||||
}
|
||||
isyslog("connect from %s, port %hu - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
|
||||
lastAcceptedConnection = cString::sprintf("%s:%hu", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port));
|
||||
isyslog("SVDRP %s connection %s", *lastAcceptedConnection, accepted ? "accepted" : "DENIED");
|
||||
}
|
||||
else if (errno != EINTR && errno != EAGAIN)
|
||||
LOG_ERROR;
|
||||
@ -130,6 +150,19 @@ int cSocket::Accept(void)
|
||||
|
||||
// --- cPUTEhandler ----------------------------------------------------------
|
||||
|
||||
class cPUTEhandler {
|
||||
private:
|
||||
FILE *f;
|
||||
int status;
|
||||
const char *message;
|
||||
public:
|
||||
cPUTEhandler(void);
|
||||
~cPUTEhandler();
|
||||
bool Process(const char *s);
|
||||
int Status(void) { return status; }
|
||||
const char *Message(void) { return message; }
|
||||
};
|
||||
|
||||
cPUTEhandler::cPUTEhandler(void)
|
||||
{
|
||||
if ((f = tmpfile()) != NULL) {
|
||||
@ -385,17 +418,77 @@ const char *GetHelpPage(const char *Cmd, const char **p)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *cSVDRP::grabImageDir = NULL;
|
||||
static cString grabImageDir;
|
||||
|
||||
cSVDRP::cSVDRP(int Port)
|
||||
:socket(Port)
|
||||
class cSVDRP {
|
||||
private:
|
||||
int socket;
|
||||
cString connection;
|
||||
cFile file;
|
||||
cRecordings recordings;
|
||||
cPUTEhandler *PUTEhandler;
|
||||
int numChars;
|
||||
int length;
|
||||
char *cmdLine;
|
||||
time_t lastActivity;
|
||||
void Close(bool SendReply = false, bool Timeout = false);
|
||||
bool Send(const char *s, int length = -1);
|
||||
void Reply(int Code, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
void PrintHelpTopics(const char **hp);
|
||||
void CmdCHAN(const char *Option);
|
||||
void CmdCLRE(const char *Option);
|
||||
void CmdDELC(const char *Option);
|
||||
void CmdDELR(const char *Option);
|
||||
void CmdDELT(const char *Option);
|
||||
void CmdEDIT(const char *Option);
|
||||
void CmdGRAB(const char *Option);
|
||||
void CmdHELP(const char *Option);
|
||||
void CmdHITK(const char *Option);
|
||||
void CmdLSTC(const char *Option);
|
||||
void CmdLSTE(const char *Option);
|
||||
void CmdLSTR(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);
|
||||
void CmdMOVR(const char *Option);
|
||||
void CmdNEWC(const char *Option);
|
||||
void CmdNEWT(const char *Option);
|
||||
void CmdNEXT(const char *Option);
|
||||
void CmdPLAY(const char *Option);
|
||||
void CmdPLUG(const char *Option);
|
||||
void CmdPUTE(const char *Option);
|
||||
void CmdREMO(const char *Option);
|
||||
void CmdSCAN(const char *Option);
|
||||
void CmdSTAT(const char *Option);
|
||||
void CmdUPDT(const char *Option);
|
||||
void CmdUPDR(const char *Option);
|
||||
void CmdVOLU(const char *Option);
|
||||
void Execute(char *Cmd);
|
||||
public:
|
||||
cSVDRP(int Socket, const char *Connection);
|
||||
~cSVDRP();
|
||||
bool HasConnection(void) { return file.IsOpen(); }
|
||||
bool Process(void);
|
||||
};
|
||||
|
||||
cSVDRP::cSVDRP(int Socket, const char *Connection)
|
||||
{
|
||||
socket = Socket;
|
||||
connection = Connection;
|
||||
PUTEhandler = NULL;
|
||||
numChars = 0;
|
||||
length = BUFSIZ;
|
||||
cmdLine = MALLOC(char, length);
|
||||
lastActivity = 0;
|
||||
isyslog("SVDRP listening on port %d", Port);
|
||||
lastActivity = time(NULL);
|
||||
if (file.Open(socket)) {
|
||||
//TODO how can we get the *full* hostname?
|
||||
char buffer[BUFSIZ];
|
||||
gethostname(buffer, sizeof(buffer));
|
||||
time_t now = time(NULL);
|
||||
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s; %s", buffer, VDRVERSION, *TimeToString(now), cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
cSVDRP::~cSVDRP()
|
||||
@ -413,10 +506,11 @@ void cSVDRP::Close(bool SendReply, bool Timeout)
|
||||
gethostname(buffer, sizeof(buffer));
|
||||
Reply(221, "%s closing connection%s", buffer, Timeout ? " (timeout)" : "");
|
||||
}
|
||||
isyslog("closing SVDRP connection"); //TODO store IP#???
|
||||
isyslog("SVDRP %s connection closed", *connection);
|
||||
file.Close();
|
||||
DELETENULL(PUTEhandler);
|
||||
}
|
||||
close(socket);
|
||||
}
|
||||
|
||||
bool cSVDRP::Send(const char *s, int length)
|
||||
@ -454,7 +548,7 @@ void cSVDRP::Reply(int Code, const char *fmt, ...)
|
||||
}
|
||||
else {
|
||||
Reply(451, "Zero return code - looks like a programming error!");
|
||||
esyslog("SVDRP: zero return code!");
|
||||
esyslog("SVDRP %s zero return code!", *connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -641,7 +735,7 @@ void cSVDRP::CmdDELC(const char *Option)
|
||||
Channels.Del(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.SetModified(true);
|
||||
isyslog("channel %s deleted", Option);
|
||||
isyslog("SVDRP %s channel %s deleted", *connection, Option);
|
||||
if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
|
||||
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
|
||||
Channels.SwitchTo(CurrentChannel->Number());
|
||||
@ -714,7 +808,7 @@ void cSVDRP::CmdDELT(const char *Option)
|
||||
cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
||||
if (timer) {
|
||||
if (!timer->Recording()) {
|
||||
isyslog("deleting timer %s", *timer->ToDescr());
|
||||
isyslog("SVDRP %s deleting timer %s", *connection, *timer->ToDescr());
|
||||
Timers.Del(timer);
|
||||
Timers.SetModified();
|
||||
Reply(250, "Timer \"%s\" deleted", Option);
|
||||
@ -831,7 +925,7 @@ void cSVDRP::CmdGRAB(const char *Option)
|
||||
// canonicalize the file name:
|
||||
char RealFileName[PATH_MAX];
|
||||
if (FileName) {
|
||||
if (grabImageDir) {
|
||||
if (*grabImageDir) {
|
||||
cString s(FileName);
|
||||
FileName = s;
|
||||
const char *slash = strrchr(FileName, '/');
|
||||
@ -868,7 +962,7 @@ void cSVDRP::CmdGRAB(const char *Option)
|
||||
int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
|
||||
if (fd >= 0) {
|
||||
if (safe_write(fd, Image, ImageSize) == ImageSize) {
|
||||
dsyslog("grabbed image to %s", FileName);
|
||||
dsyslog("SVDRP %s grabbed image to %s", *connection, FileName);
|
||||
Reply(250, "Grabbed image %s", Option);
|
||||
}
|
||||
else {
|
||||
@ -1195,7 +1289,7 @@ void cSVDRP::CmdLSTT(const char *Option)
|
||||
void cSVDRP::CmdMESG(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
isyslog("SVDRP message: '%s'", Option);
|
||||
isyslog("SVDRP %s message '%s'", *connection, Option);
|
||||
Skins.QueueMessage(mtInfo, Option);
|
||||
Reply(250, "Message queued");
|
||||
}
|
||||
@ -1219,7 +1313,7 @@ void cSVDRP::CmdMODC(const char *Option)
|
||||
*channel = ch;
|
||||
Channels.ReNumber();
|
||||
Channels.SetModified(true);
|
||||
isyslog("modifed channel %d %s", channel->Number(), *channel->ToText());
|
||||
isyslog("SVDRP %s modifed channel %d %s", *connection, channel->Number(), *channel->ToText());
|
||||
Reply(250, "%d %s", channel->Number(), *channel->ToText());
|
||||
}
|
||||
else
|
||||
@ -1262,7 +1356,7 @@ void cSVDRP::CmdMODT(const char *Option)
|
||||
}
|
||||
*timer = t;
|
||||
Timers.SetModified();
|
||||
isyslog("timer %s modified (%s)", *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
isyslog("SVDRP %s timer %s modified (%s)", *connection, *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||
}
|
||||
else
|
||||
@ -1306,7 +1400,7 @@ void cSVDRP::CmdMOVC(const char *Option)
|
||||
else
|
||||
cDevice::SetCurrentChannel(CurrentChannel);
|
||||
}
|
||||
isyslog("channel %d moved to %d", FromNumber, ToNumber);
|
||||
isyslog("SVDRP %s channel %d moved to %d", *connection, FromNumber, ToNumber);
|
||||
Reply(250,"Channel \"%d\" moved to \"%d\"", From, To);
|
||||
}
|
||||
else
|
||||
@ -1382,7 +1476,7 @@ void cSVDRP::CmdNEWC(const char *Option)
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.SetModified(true);
|
||||
isyslog("new channel %d %s", channel->Number(), *channel->ToText());
|
||||
isyslog("SVDRP %s new channel %d %s", *connection, channel->Number(), *channel->ToText());
|
||||
Reply(250, "%d %s", channel->Number(), *channel->ToText());
|
||||
}
|
||||
else
|
||||
@ -1402,7 +1496,7 @@ void cSVDRP::CmdNEWT(const char *Option)
|
||||
if (timer->Parse(Option)) {
|
||||
Timers.Add(timer);
|
||||
Timers.SetModified();
|
||||
isyslog("timer %s added", *timer->ToDescr());
|
||||
isyslog("SVDRP %s timer %s added", *connection, *timer->ToDescr());
|
||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||
return;
|
||||
}
|
||||
@ -1622,11 +1716,11 @@ void cSVDRP::CmdUPDT(const char *Option)
|
||||
t->Parse(Option);
|
||||
delete timer;
|
||||
timer = t;
|
||||
isyslog("timer %s updated", *timer->ToDescr());
|
||||
isyslog("SVDRP %s timer %s updated", *connection, *timer->ToDescr());
|
||||
}
|
||||
else {
|
||||
Timers.Add(timer);
|
||||
isyslog("timer %s added", *timer->ToDescr());
|
||||
isyslog("SVDRP %s timer %s added", *connection, *timer->ToDescr());
|
||||
}
|
||||
Timers.SetModified();
|
||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||
@ -1729,19 +1823,7 @@ void cSVDRP::Execute(char *Cmd)
|
||||
|
||||
bool cSVDRP::Process(void)
|
||||
{
|
||||
bool NewConnection = !file.IsOpen();
|
||||
bool SendGreeting = NewConnection;
|
||||
|
||||
if (file.IsOpen() || file.Open(socket.Accept())) {
|
||||
if (SendGreeting) {
|
||||
//TODO how can we get the *full* hostname?
|
||||
char buffer[BUFSIZ];
|
||||
gethostname(buffer, sizeof(buffer));
|
||||
time_t now = time(NULL);
|
||||
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s; %s", buffer, VDRVERSION, *TimeToString(now), cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8");
|
||||
}
|
||||
if (NewConnection)
|
||||
lastActivity = time(NULL);
|
||||
if (file.IsOpen()) {
|
||||
while (file.Ready(false)) {
|
||||
unsigned char c;
|
||||
int r = safe_read(file, &c, 1);
|
||||
@ -1781,7 +1863,7 @@ bool cSVDRP::Process(void)
|
||||
cmdLine = NewBuffer;
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: out of memory");
|
||||
esyslog("SVDRP %s ERROR: out of memory", *connection);
|
||||
Close();
|
||||
break;
|
||||
}
|
||||
@ -1792,23 +1874,87 @@ bool cSVDRP::Process(void)
|
||||
lastActivity = time(NULL);
|
||||
}
|
||||
else if (r <= 0) {
|
||||
isyslog("lost connection to SVDRP client");
|
||||
isyslog("SVDRP %s lost connection to client", *connection);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
|
||||
isyslog("timeout on SVDRP connection");
|
||||
isyslog("SVDRP %s timeout on connection", *connection);
|
||||
Close(true, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return file.IsOpen();
|
||||
}
|
||||
|
||||
void cSVDRP::SetGrabImageDir(const char *GrabImageDir)
|
||||
void SetSVDRPGrabImageDir(const char *GrabImageDir)
|
||||
{
|
||||
free(grabImageDir);
|
||||
grabImageDir = GrabImageDir ? strdup(GrabImageDir) : NULL;
|
||||
grabImageDir = GrabImageDir;
|
||||
}
|
||||
|
||||
//TODO more than one connection???
|
||||
// --- cSVDRPHandler ---------------------------------------------------------
|
||||
|
||||
class cSVDRPHandler : public cThread {
|
||||
private:
|
||||
cSocket socket;
|
||||
cVector<cSVDRP *> connections;
|
||||
void ProcessConnections(void);
|
||||
protected:
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cSVDRPHandler(int Port);
|
||||
virtual ~cSVDRPHandler();
|
||||
};
|
||||
|
||||
cSVDRPHandler::cSVDRPHandler(int Port)
|
||||
:cThread("SVDRP handler", true)
|
||||
,socket(Port)
|
||||
{
|
||||
}
|
||||
|
||||
cSVDRPHandler::~cSVDRPHandler()
|
||||
{
|
||||
Cancel(3);
|
||||
}
|
||||
|
||||
void cSVDRPHandler::ProcessConnections(void)
|
||||
{
|
||||
for (int i = 0; i < connections.Size(); i++) {
|
||||
if (connections[i]) {
|
||||
if (!connections[i]->Process()) {
|
||||
delete connections[i];
|
||||
connections.Remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSVDRPHandler::Action(void)
|
||||
{
|
||||
if (socket.Open()) {
|
||||
while (Running()) {
|
||||
cFile::AnyFileReady(socket.Socket(), 1000);
|
||||
int NewSocket = socket.Accept();
|
||||
if (NewSocket >= 0)
|
||||
connections.Append(new cSVDRP(NewSocket, socket.LastAcceptedConnection()));
|
||||
ProcessConnections();
|
||||
}
|
||||
socket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
static cSVDRPHandler *SVDRPHandler = NULL;
|
||||
|
||||
void StartSVDRPHandler(int Port)
|
||||
{
|
||||
if (Port && !SVDRPHandler) {
|
||||
SVDRPHandler = new cSVDRPHandler(Port);
|
||||
SVDRPHandler->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void StopSVDRPHandler(void)
|
||||
{
|
||||
delete SVDRPHandler;
|
||||
SVDRPHandler = NULL;
|
||||
}
|
||||
|
87
svdrp.h
87
svdrp.h
@ -4,93 +4,14 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: svdrp.h 3.2 2013/10/21 07:42:03 kls Exp $
|
||||
* $Id: svdrp.h 4.1 2015/04/29 13:10:06 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SVDRP_H
|
||||
#define __SVDRP_H
|
||||
|
||||
#include "recording.h"
|
||||
#include "tools.h"
|
||||
|
||||
class cSocket {
|
||||
private:
|
||||
int port;
|
||||
int sock;
|
||||
int queue;
|
||||
void Close(void);
|
||||
public:
|
||||
cSocket(int Port, int Queue = 1);
|
||||
~cSocket();
|
||||
bool Open(void);
|
||||
int Accept(void);
|
||||
};
|
||||
|
||||
class cPUTEhandler {
|
||||
private:
|
||||
FILE *f;
|
||||
int status;
|
||||
const char *message;
|
||||
public:
|
||||
cPUTEhandler(void);
|
||||
~cPUTEhandler();
|
||||
bool Process(const char *s);
|
||||
int Status(void) { return status; }
|
||||
const char *Message(void) { return message; }
|
||||
};
|
||||
|
||||
class cSVDRP {
|
||||
private:
|
||||
cSocket socket;
|
||||
cFile file;
|
||||
cRecordings recordings;
|
||||
cPUTEhandler *PUTEhandler;
|
||||
int numChars;
|
||||
int length;
|
||||
char *cmdLine;
|
||||
time_t lastActivity;
|
||||
static char *grabImageDir;
|
||||
void Close(bool SendReply = false, bool Timeout = false);
|
||||
bool Send(const char *s, int length = -1);
|
||||
void Reply(int Code, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
void PrintHelpTopics(const char **hp);
|
||||
void CmdCHAN(const char *Option);
|
||||
void CmdCLRE(const char *Option);
|
||||
void CmdDELC(const char *Option);
|
||||
void CmdDELR(const char *Option);
|
||||
void CmdDELT(const char *Option);
|
||||
void CmdEDIT(const char *Option);
|
||||
void CmdGRAB(const char *Option);
|
||||
void CmdHELP(const char *Option);
|
||||
void CmdHITK(const char *Option);
|
||||
void CmdLSTC(const char *Option);
|
||||
void CmdLSTE(const char *Option);
|
||||
void CmdLSTR(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);
|
||||
void CmdMOVR(const char *Option);
|
||||
void CmdNEWC(const char *Option);
|
||||
void CmdNEWT(const char *Option);
|
||||
void CmdNEXT(const char *Option);
|
||||
void CmdPLAY(const char *Option);
|
||||
void CmdPLUG(const char *Option);
|
||||
void CmdPUTE(const char *Option);
|
||||
void CmdREMO(const char *Option);
|
||||
void CmdSCAN(const char *Option);
|
||||
void CmdSTAT(const char *Option);
|
||||
void CmdUPDT(const char *Option);
|
||||
void CmdUPDR(const char *Option);
|
||||
void CmdVOLU(const char *Option);
|
||||
void Execute(char *Cmd);
|
||||
public:
|
||||
cSVDRP(int Port);
|
||||
~cSVDRP();
|
||||
bool HasConnection(void) { return file.IsOpen(); }
|
||||
bool Process(void);
|
||||
static void SetGrabImageDir(const char *GrabImageDir);
|
||||
};
|
||||
void SetSVDRPGrabImageDir(const char *GrabImageDir);
|
||||
void StartSVDRPHandler(int Port);
|
||||
void StopSVDRPHandler(void);
|
||||
|
||||
#endif //__SVDRP_H
|
||||
|
14
vdr.c
14
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.tvdr.de
|
||||
*
|
||||
* $Id: vdr.c 4.2 2015/04/19 12:38:12 kls Exp $
|
||||
* $Id: vdr.c 4.3 2015/04/29 09:18:54 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -65,6 +65,7 @@
|
||||
#include "sourceparams.h"
|
||||
#include "sources.h"
|
||||
#include "status.h"
|
||||
#include "svdrp.h"
|
||||
#include "themes.h"
|
||||
#include "timers.h"
|
||||
#include "tools.h"
|
||||
@ -375,7 +376,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'g' | 0x100:
|
||||
return GenerateIndex(optarg) ? 0 : 2;
|
||||
case 'g': cSVDRP::SetGrabImageDir(*optarg != '-' ? optarg : NULL);
|
||||
case 'g': SetSVDRPGrabImageDir(*optarg != '-' ? optarg : NULL);
|
||||
break;
|
||||
case 'h': DisplayHelp = true;
|
||||
break;
|
||||
@ -831,7 +832,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// User interface:
|
||||
|
||||
Interface = new cInterface(SVDRPport);
|
||||
Interface = new cInterface;
|
||||
|
||||
// Default skins:
|
||||
|
||||
@ -913,6 +914,10 @@ int main(int argc, char *argv[])
|
||||
sd_notify(0, "READY=1\nSTATUS=Ready");
|
||||
#endif
|
||||
|
||||
// SVDRP:
|
||||
|
||||
StartSVDRPHandler(SVDRPport);
|
||||
|
||||
// Main program loop:
|
||||
|
||||
#define DELETE_MENU ((IsInfoMenu &= (Menu == NULL)), delete Menu, Menu = NULL)
|
||||
@ -1418,7 +1423,7 @@ int main(int argc, char *argv[])
|
||||
// Keep the recordings handler alive:
|
||||
RecordingsHandler.Active();
|
||||
|
||||
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && !Interface->HasSVDRPConnection() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
|
||||
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
|
||||
// Handle housekeeping tasks
|
||||
|
||||
// Shutdown:
|
||||
@ -1466,6 +1471,7 @@ Exit:
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
|
||||
StopSVDRPHandler();
|
||||
PluginManager.StopPlugins();
|
||||
cRecordControls::Shutdown();
|
||||
RecordingsHandler.DelAll();
|
||||
|
Loading…
Reference in New Issue
Block a user