summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY7
-rw-r--r--eit.c13
-rw-r--r--interface.c8
-rw-r--r--remote.c36
-rw-r--r--remote.h9
-rw-r--r--svdrp.c18
-rw-r--r--svdrp.h6
-rw-r--r--tools.c147
-rw-r--r--tools.h25
9 files changed, 172 insertions, 97 deletions
diff --git a/HISTORY b/HISTORY
index e93ab7cb..bf76f840 100644
--- a/HISTORY
+++ b/HISTORY
@@ -168,7 +168,7 @@ Video Disk Recorder Revision History
entered so far together with the name of that channel are displayed on the
OSD (suggested by Martin Hammerschmid).
-2000-09-15: Version 0.64
+2000-09-16: Version 0.64
- Video files now have the 'group read' bit set.
- Fixed handling errors in 'readstring()'.
@@ -178,4 +178,7 @@ Video Disk Recorder Revision History
current '*.conf' files to your video directory ('/video' by default), or
use "-c ." to get the old behaviour of loading the configuration files
from the current directory.
-
+- Waiting for input is now handled by a common function, which improves
+ response time on user actions. As a consequence the EIT data may sometimes
+ not be displayed, but this will change later when cEIT runs as a separate
+ thread.
diff --git a/eit.c b/eit.c
index c4c12003..c86fecc5 100644
--- a/eit.c
+++ b/eit.c
@@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
- * $Id: eit.c 1.1 2000/09/03 10:22:25 kls Exp $
+ * $Id: eit.c 1.2 2000/09/17 08:02:30 kls Exp $
***************************************************************************/
#include "eit.h"
@@ -22,7 +22,6 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
-#include <sys/poll.h>
#include <sys/ioctl.h>
#include <dvb_comcode.h>
#include "tools.h"
@@ -253,15 +252,12 @@ int cEIT::GetSection(unsigned char *buf, ushort PID, unsigned char sec)
int seclen=0;
unsigned short handle, pid;
unsigned char section, sectionnum=0xff, maxsec=0;
- struct pollfd pfd;
if ((handle = SetBitFilter(PID, (sec<<8)|0x00ff, SECTION_CONTINUOS))==0xffff)
return -1;
seclen=0;
- pfd.fd=fsvbi;
- pfd.events=POLLIN;
- if (poll(&pfd, 1, 20000)==0)
+ if (!cFile::AnyFileReady(fsvbi, 20000))
{
//cerr << "Timeout\n";
return -1;
@@ -318,7 +314,6 @@ int cEIT::GetEIT()
struct eit_short_event_descriptor_struct *eitevt;
int seclen;
unsigned short handle, pid;
- struct pollfd pfd;
eit_event * pevt = (eit_event *)0;
time_t tstart;
@@ -344,9 +339,7 @@ int cEIT::GetEIT()
tstart = time(NULL);
while ((!evtRunning.bIsValid || !evtNext.bIsValid) && nReceivedEITs < 20 && difftime(time(NULL), tstart) < 4)
{
- pfd.fd=fsvbi;
- pfd.events=POLLIN;
- if (poll(&pfd, 1, 5000)==0)
+ if (!cFile::AnyFileReady(fsvbi, 5000))
{
//cerr << "Timeout\n";
CloseFilter(handle);
diff --git a/interface.c b/interface.c
index c8455a05..0993ba8b 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.15 2000/09/10 15:00:00 kls Exp $
+ * $Id: interface.c 1.16 2000/09/17 08:21:45 kls Exp $
*/
#include "interface.h"
@@ -52,10 +52,6 @@ void cInterface::Close(void)
unsigned int cInterface::GetCh(bool Wait)
{
-#ifdef DEBUG_OSD
- timeout(0);
- getch(); // just to make 'ncurses' display the window:
-#endif
if (RcIo.InputAvailable(Wait)) {
unsigned int Command;
return RcIo.GetCommand(&Command, NULL) ? Command : 0;
@@ -77,7 +73,7 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
while (time_ms() < t0) {
Key = GetKey();
- if (Key != kNone)
+ if (Key != kNone || cFile::AnyFileReady())
break;
}
if (KeepChar)
diff --git a/remote.c b/remote.c
index 0476962c..7858a2b2 100644
--- a/remote.c
+++ b/remote.c
@@ -6,7 +6,7 @@
*
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
*
- * $Id: remote.c 1.11 2000/07/29 16:23:47 kls Exp $
+ * $Id: remote.c 1.12 2000/09/16 16:42:30 kls Exp $
*/
#include "remote.h"
@@ -49,6 +49,7 @@ cRcIoBase::~cRcIoBase()
cRcIoKBD::cRcIoKBD(void)
{
+ f.Open(0); // stdin
}
cRcIoKBD::~cRcIoKBD()
@@ -70,12 +71,7 @@ void cRcIoKBD::Flush(int WaitSeconds)
bool cRcIoKBD::InputAvailable(bool Wait)
{
- timeout(Wait ? 1000 : 10);
- int ch = getch();
- if (ch == ERR)
- return false;
- ungetch(ch);
- return true;
+ return f.Ready(Wait);
}
bool cRcIoKBD::GetCommand(unsigned int *Command, unsigned short *)
@@ -98,7 +94,7 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
code = 0;
address = 0xFFFF;
lastNumber = 0;
- if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
+ if (f.Open(DeviceName, O_RDWR | O_NONBLOCK)) {
struct termios t;
if (tcgetattr(f, &t) == 0) {
cfsetspeed(&t, B9600);
@@ -107,17 +103,14 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
return;
}
LOG_ERROR_STR(DeviceName);
- close(f);
+ f.Close();
}
else
LOG_ERROR_STR(DeviceName);
- f = -1;
}
cRcIoRCU::~cRcIoRCU()
{
- if (f >= 0)
- close(f);
}
int cRcIoRCU::ReceiveByte(bool Wait)
@@ -135,7 +128,7 @@ int cRcIoRCU::ReceiveByte(bool Wait)
bool cRcIoRCU::SendByteHandshake(unsigned char c)
{
- if (f >= 0) {
+ if (f.IsOpen()) {
int w = write(f, &c, 1);
if (w == 1) {
for (int reply = ReceiveByte(); reply >= 0;) {
@@ -193,7 +186,7 @@ void cRcIoRCU::Flush(int WaitSeconds)
bool cRcIoRCU::InputAvailable(bool Wait)
{
- return DataAvailable(f, Wait);
+ return f.Ready(Wait);
}
bool cRcIoRCU::GetCommand(unsigned int *Command, unsigned short *Address)
@@ -349,22 +342,21 @@ cRcIoLIRC::cRcIoLIRC(char *DeviceName)
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DeviceName);
- f = socket(AF_UNIX, SOCK_STREAM, 0);
- if (f >= 0) {
- if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock >= 0) {
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
+ f.Open(sock);
return;
+ }
LOG_ERROR_STR(DeviceName);
- close(f);
+ close(sock);
}
else
LOG_ERROR_STR(DeviceName);
- f = -1;
}
cRcIoLIRC::~cRcIoLIRC()
{
- if (f >= 0)
- close(f);
}
const char *cRcIoLIRC::ReceiveString(void)
@@ -406,7 +398,7 @@ void cRcIoLIRC::Flush(int WaitSeconds)
bool cRcIoLIRC::InputAvailable(bool Wait)
{
- return DataAvailable(f, Wait);
+ return f.Ready(Wait);
}
bool cRcIoLIRC::GetCommand(unsigned int *Command, unsigned short *)
diff --git a/remote.h b/remote.h
index 7b94ac78..9346b485 100644
--- a/remote.h
+++ b/remote.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remote.h 1.7 2000/07/15 16:32:43 kls Exp $
+ * $Id: remote.h 1.8 2000/09/16 14:01:14 kls Exp $
*/
#ifndef __REMOTE_H
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <time.h>
+#include "tools.h"
class cRcIoBase {
protected:
@@ -36,6 +37,8 @@ public:
#if defined REMOTE_KBD
class cRcIoKBD : public cRcIoBase {
+private:
+ cFile f;
public:
cRcIoKBD(void);
virtual ~cRcIoKBD();
@@ -48,7 +51,7 @@ public:
class cRcIoRCU : public cRcIoBase {
private:
- int f;
+ cFile f;
unsigned char dp, code, mode;
unsigned short address;
int lastNumber;
@@ -76,7 +79,7 @@ public:
class cRcIoLIRC : public cRcIoBase {
private:
enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 };
- int f;
+ cFile f;
char keyName[LIRC_KEY_BUF];
const char *ReceiveString(void);
public:
diff --git a/svdrp.c b/svdrp.c
index 2af3ee53..438e9331 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 1.6 2000/09/09 10:51:21 kls Exp $
+ * $Id: svdrp.c 1.7 2000/09/16 13:34:28 kls Exp $
*/
#define _GNU_SOURCE
@@ -206,7 +206,6 @@ const char *GetHelpPage(const char *Cmd)
cSVDRP::cSVDRP(int Port)
:socket(Port)
{
- filedes = -1;
isyslog(LOG_INFO, "SVDRP listening on port %d", Port);
}
@@ -217,14 +216,13 @@ cSVDRP::~cSVDRP()
void cSVDRP::Close(void)
{
- if (filedes >= 0) {
+ 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#???
- close(filedes);
- filedes = -1;
+ file.Close();
}
}
@@ -232,7 +230,7 @@ bool cSVDRP::Send(const char *s, int length)
{
if (length < 0)
length = strlen(s);
- int wbytes = write(filedes, s, length);
+ int wbytes = write(file, s, length);
if (wbytes == length)
return true;
if (wbytes < 0)
@@ -244,7 +242,7 @@ bool cSVDRP::Send(const char *s, int length)
void cSVDRP::Reply(int Code, const char *fmt, ...)
{
- if (filedes >= 0) {
+ if (file.IsOpen()) {
if (Code != 0) {
va_list ap;
va_start(ap, fmt);
@@ -632,9 +630,9 @@ void cSVDRP::Execute(char *Cmd)
void cSVDRP::Process(void)
{
- bool SendGreeting = filedes < 0;
+ bool SendGreeting = !file.IsOpen();
- if (filedes >= 0 || (filedes = socket.Accept()) >= 0) {
+ if (file.IsOpen() || file.Open(socket.Accept())) {
char buffer[MAXCMDBUFFER];
if (SendGreeting) {
//TODO how can we get the *full* hostname?
@@ -642,7 +640,7 @@ void cSVDRP::Process(void)
time_t now = time(NULL);
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now));
}
- int rbytes = readstring(filedes, buffer, sizeof(buffer) - 1);
+ int rbytes = file.ReadString(buffer, sizeof(buffer) - 1);
if (rbytes > 0) {
//XXX overflow check???
// strip trailing whitespace:
diff --git a/svdrp.h b/svdrp.h
index 3c1cafa8..674639e1 100644
--- a/svdrp.h
+++ b/svdrp.h
@@ -4,12 +4,14 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: svdrp.h 1.2 2000/08/06 12:45:28 kls Exp $
+ * $Id: svdrp.h 1.3 2000/09/16 11:48:36 kls Exp $
*/
#ifndef __SVDRP_H
#define __SVDRP_H
+#include "tools.h"
+
class cSocket {
private:
int port;
@@ -26,7 +28,7 @@ public:
class cSVDRP {
private:
cSocket socket;
- int filedes;
+ cFile file;
void Close(void);
bool Send(const char *s, int length = -1);
void Reply(int Code, const char *fmt, ...);
diff --git a/tools.c b/tools.c
index d854dfb1..c62a3e13 100644
--- a/tools.c
+++ b/tools.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.c 1.16 2000/09/15 14:45:31 kls Exp $
+ * $Id: tools.c 1.17 2000/09/17 08:23:46 kls Exp $
*/
#define _GNU_SOURCE
@@ -12,31 +12,20 @@
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
+#if defined(DEBUG_OSD)
+#include <ncurses.h>
+#endif
#include <signal.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/wait.h>
#include <unistd.h>
#define MaxBuffer 1000
int SysLogLevel = 3;
-bool DataAvailable(int filedes, bool wait)
-{
- if (filedes >= 0) {
- fd_set set;
- FD_ZERO(&set);
- FD_SET(filedes, &set);
- struct timeval timeout;
- timeout.tv_sec = wait ? 1 : 0;
- timeout.tv_usec = wait ? 0 : 10000;
- return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && FD_ISSET(filedes, &set);
- }
- return false;
-}
-
void writechar(int filedes, char c)
{
write(filedes, &c, sizeof(c));
@@ -56,32 +45,12 @@ char readchar(int filedes)
bool readint(int filedes, int &n)
{
- return DataAvailable(filedes) && read(filedes, &n, sizeof(n)) == sizeof(n);
-}
-
-int readstring(int filedes, char *buffer, int size, bool wait = false)
-{
- int rbytes = 0;
-
- while (DataAvailable(filedes, wait)) {
- int n = read(filedes, buffer + rbytes, size - rbytes);
- if (n == 0)
- break; // EOF
- if (n < 0) {
- LOG_ERROR;
- return -1;
- }
- rbytes += n;
- if (rbytes == size)
- break;
- wait = false;
- }
- return rbytes;
+ return cFile::AnyFileReady(filedes, 0) && read(filedes, &n, sizeof(n)) == sizeof(n);
}
void purge(int filedes)
{
- while (DataAvailable(filedes))
+ while (cFile::AnyFileReady(filedes, 0))
readchar(filedes);
}
@@ -321,6 +290,108 @@ void KillProcess(pid_t pid, int Timeout)
}
}
+// --- cFile -----------------------------------------------------------------
+
+bool cFile::files[FD_SETSIZE] = { false };
+int cFile::maxFiles = 0;
+
+cFile::cFile(void)
+{
+ f = -1;
+}
+
+cFile::~cFile()
+{
+ Close();
+}
+
+bool cFile::Open(const char *FileName, int Flags, mode_t Mode)
+{
+ if (!IsOpen())
+ return Open(open(FileName, Flags, Mode));
+ esyslog(LOG_ERR, "ERROR: attempt to re-open %s", FileName);
+ return false;
+}
+
+bool cFile::Open(int FileDes)
+{
+ if (FileDes >= 0) {
+ if (!IsOpen()) {
+ f = FileDes;
+ if (f >= 0) {
+ if (f < FD_SETSIZE) {
+ if (f >= maxFiles)
+ maxFiles = f + 1;
+ if (!files[f])
+ files[f] = true;
+ else
+ esyslog(LOG_ERR, "ERROR: file descriptor %d already in files[]", f);
+ return true;
+ }
+ else
+ esyslog(LOG_ERR, "ERROR: file descriptor %d is larger than FD_SETSIZE (%d)", f, FD_SETSIZE);
+ }
+ }
+ else
+ esyslog(LOG_ERR, "ERROR: attempt to re-open file descriptor %d", FileDes);
+ }
+ return false;
+}
+
+void cFile::Close(void)
+{
+ if (f >= 0) {
+ close(f);
+ files[f] = false;
+ f = -1;
+ }
+}
+
+int cFile::ReadString(char *Buffer, int Size)
+{
+ int rbytes = 0;
+ bool wait = true;
+
+ while (Ready(wait)) {
+ int n = read(f, Buffer + rbytes, Size - rbytes);
+ if (n == 0)
+ break; // EOF
+ if (n < 0) {
+ LOG_ERROR;
+ return -1;
+ }
+ rbytes += n;
+ if (rbytes == Size)
+ break;
+ wait = false;
+ }
+ return rbytes;
+}
+
+bool cFile::Ready(bool Wait)
+{
+ return f >= 0 && AnyFileReady(f, Wait ? 1000 : 0);
+}
+
+bool cFile::AnyFileReady(int FileDes, int TimeoutMs)
+{
+#ifdef DEBUG_OSD
+ refresh();
+#endif
+ fd_set set;
+ FD_ZERO(&set);
+ for (int i = 0; i < maxFiles; i++) {
+ if (files[i])
+ FD_SET(i, &set);
+ }
+ if (0 <= FileDes && FileDes < FD_SETSIZE && !files[FileDes])
+ FD_SET(FileDes, &set); // in case we come in with an arbitrary descriptor
+ struct timeval timeout;
+ timeout.tv_sec = TimeoutMs / 1000;
+ timeout.tv_usec = (TimeoutMs % 1000) * 1000;
+ return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && (FileDes < 0 || FD_ISSET(FileDes, &set));
+}
+
// --- cListObject -----------------------------------------------------------
cListObject::cListObject(void)
diff --git a/tools.h b/tools.h
index b9f3b6c0..5c749a7c 100644
--- a/tools.h
+++ b/tools.h
@@ -4,16 +4,17 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.h 1.14 2000/09/15 14:23:29 kls Exp $
+ * $Id: tools.h 1.15 2000/09/17 07:58:19 kls Exp $
*/
#ifndef __TOOLS_H
#define __TOOLS_H
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <syslog.h>
-#include <sys/wait.h>
+#include <sys/stat.h>
#include <sys/types.h>
extern int SysLogLevel;
@@ -30,12 +31,10 @@ extern int SysLogLevel;
#define DELETENULL(p) (delete (p), p = NULL)
-bool DataAvailable(int filedes, bool wait = false);
void writechar(int filedes, char c);
void writeint(int filedes, int n);
char readchar(int filedes);
bool readint(int filedes, int &n);
-int readstring(int filedes, char *buffer, int size, bool wait = false);
void purge(int filedes);
char *readline(FILE *f);
char *strn0cpy(char *dest, const char *src, size_t n);
@@ -52,6 +51,24 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
bool CheckProcess(pid_t pid);
void KillProcess(pid_t pid, int Timeout = MAXPROCESSTIMEOUT);
+class cFile {
+private:
+ static bool files[];
+ static int maxFiles;
+ int f;
+public:
+ cFile(void);
+ ~cFile();
+ operator int () { return f; }
+ bool Open(const char *FileName, int Flags, mode_t Mode = S_IRUSR | S_IWUSR | S_IRGRP);
+ bool Open(int FileDes);
+ void Close(void);
+ bool IsOpen(void) { return f >= 0; }
+ int ReadString(char *Buffer, int Size);
+ bool Ready(bool Wait = true);
+ static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000);
+ };
+
class cListObject {
private:
cListObject *prev, *next;