Implemented centralized 'wait for input'

This commit is contained in:
Klaus Schmidinger 2000-09-17 08:23:46 +02:00
parent 7fbf9e6c49
commit 4716cfb5a1
9 changed files with 172 additions and 97 deletions

View File

@ -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.

13
eit.c
View File

@ -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);

View File

@ -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)

View File

@ -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 *)

View File

@ -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:

18
svdrp.c
View File

@ -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:

View File

@ -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, ...);

147
tools.c
View File

@ -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)

25
tools.h
View File

@ -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;