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 #include #include -#include #include #include #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 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 #include +#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 #include #include +#if defined(DEBUG_OSD) +#include +#endif #include #include #include -#include #include +#include #include #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 +#include #include #include -#include +#include #include 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;