summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-09-20 18:00:00 +0200
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-09-20 18:00:00 +0200
commit7e4b4d290570aee1d24241b0e0ac10e7c8148a36 (patch)
tree699b8f551fb4a2deb3c79030d57a56e5f04fc1a4
parent76c331181a23f97d5e3f2b55c4741ef4e521242d (diff)
downloadvdr-patch-lnbsharing-7e4b4d290570aee1d24241b0e0ac10e7c8148a36.tar.gz
vdr-patch-lnbsharing-7e4b4d290570aee1d24241b0e0ac10e7c8148a36.tar.bz2
Version 0.64vdr-0.64
- NOTE: If you are using DVB driver version 0.7 you need to load the dvb.o module with option outstream=0, so your insmod statement should read 'insmod dvb.o outstream=0'. This is currently necessary because 'vdr' still works with AV_PES data. - Video files now have the 'group read' bit set. - Fixed handling errors in 'readstring()'. - Handling SIGPIPE and re-establishing handler after intercepting a signal. - The configuration files are now by default read from the video directory. This can be changed by using the new '-c' option. Make sure you copy your 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. - The new SVDRP command 'HITK' (thanks to Guido Fiala!) can be used to 'hit' a remote control key. Establish an SVDRP connection and enter HITK without a parameter for a list of all valid key names. - The new SVDRP command 'GRAB' (thanks to Guido Fiala!) can be used to grab the current frame and save it to a file. - The new SVDRP commands 'OVL*' can be used to control video overlays (thanks to Guido Fiala!). This is mainly for use in the 'kvdr' tool (see the 'kvdr' page at http://www.s.netic.de/gfiala). - If the name of the video directory used with the '-v' option had trailing slashes, the recording file names have been damaged. Trailing slashes are now silently removed. - Fixed a buffer overflow in EIT parsing. - Added a security warning regarding SVDRP to the INSTALL file. - Fixed 'confirm' dialog. - The daemon mode (option '-d') now no longer works with REMOTE=KBD (there is no stdin in daemon mode, so KBD makes no sense - plus it sometimes crashed).
-rw-r--r--CONTRIBUTORS3
-rw-r--r--HISTORY37
-rw-r--r--INSTALL32
-rw-r--r--Makefile24
-rw-r--r--TODO1
-rw-r--r--config.c18
-rw-r--r--config.h5
-rw-r--r--dvbapi.c268
-rw-r--r--dvbapi.h27
-rw-r--r--eit.c19
-rw-r--r--interface.c35
-rw-r--r--interface.h8
-rw-r--r--menu.c4
-rw-r--r--remote.c60
-rw-r--r--remote.h17
-rw-r--r--svdrp.c280
-rw-r--r--svdrp.h41
-rw-r--r--timers.conf12
-rw-r--r--tools.c157
-rw-r--r--tools.h26
-rw-r--r--vdr.c44
-rw-r--r--videodir.c4
22 files changed, 890 insertions, 232 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 9f6aa1b..03fd4bc 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -18,6 +18,9 @@ Heino Goldenstein <heino.goldenstein@microplex.de>
Guido Fiala <gfiala@s.netic.de>
for implementing slow forward/back
+ for implementing the SVDRP command 'HITK'
+ for implementing image grabbing
+ for implementing overlay capabilities (see his 'kvdr' tool at http://www.s.netic.de/gfiala)
Robert Schneider <Robert.Schneider@lotus.com>
for implementing EIT support for displaying the current/next info
diff --git a/HISTORY b/HISTORY
index dafab3b..f8a1007 100644
--- a/HISTORY
+++ b/HISTORY
@@ -167,4 +167,39 @@ Video Disk Recorder Revision History
- When directly selecting a channel by entering the channel number, the digits
entered so far together with the name of that channel are displayed on the
OSD (suggested by Martin Hammerschmid).
-
+
+2000-09-20: Version 0.64
+
+- NOTE: If you are using DVB driver version 0.7 you need to load the dvb.o
+ module with option outstream=0, so your insmod statement should read
+ 'insmod dvb.o outstream=0'. This is currently necessary because 'vdr'
+ still works with AV_PES data.
+- Video files now have the 'group read' bit set.
+- Fixed handling errors in 'readstring()'.
+- Handling SIGPIPE and re-establishing handler after intercepting a signal.
+- The configuration files are now by default read from the video directory.
+ This can be changed by using the new '-c' option. Make sure you copy your
+ 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.
+- The new SVDRP command 'HITK' (thanks to Guido Fiala!) can be used to 'hit'
+ a remote control key. Establish an SVDRP connection and enter HITK without
+ a parameter for a list of all valid key names.
+- The new SVDRP command 'GRAB' (thanks to Guido Fiala!) can be used to grab
+ the current frame and save it to a file.
+- The new SVDRP commands 'OVL*' can be used to control video overlays (thanks
+ to Guido Fiala!). This is mainly for use in the 'kvdr' tool (see the 'kvdr'
+ page at http://www.s.netic.de/gfiala).
+- If the name of the video directory used with the '-v' option had trailing
+ slashes, the recording file names have been damaged. Trailing slashes are
+ now silently removed.
+- Fixed a buffer overflow in EIT parsing.
+- Added a security warning regarding SVDRP to the INSTALL file.
+- Fixed 'confirm' dialog.
+- The daemon mode (option '-d') now no longer works with REMOTE=KBD (there
+ is no stdin in daemon mode, so KBD makes no sense - plus it sometimes
+ crashed).
diff --git a/INSTALL b/INSTALL
index 1ebffa1..7b953be 100644
--- a/INSTALL
+++ b/INSTALL
@@ -16,7 +16,11 @@ you will have to change the definition of DVBDIR in the
Makefile.
This program requires the card driver version 0.05 or higher
-to work properly.
+to work properly. If you are using driver version 0.7 you need
+to load the dvb.o module with option outstream=0, so your insmod
+statement should read 'insmod dvb.o outstream=0'. This is currently
+necessary because 'vdr' works with AV_PES data and will change
+once it has been modified to work directly with MPEG2.
After extracting the package, change into the VDR directory
and type 'make'. This should produce an executable file
@@ -48,6 +52,11 @@ port ("Simple Video Disk Recorder Protocol"). By default, it listens
on port 2001 (use the --port=PORT option to change this). For details
about the SVDRP syntax see the source file 'svdrp.c'.
+WARNING: DUE TO THE OPEN SVDRP PORT THIS PROGRAM MAY CONSTITUTE A
+======= POTENTIAL SECURITY HAZARD! IF YOU ARE NOT RUNNING VDR IN
+ A CONTROLLED ENVIRONMENT, YOU MAY WANT TO DISABLE SVDRP
+ BY USING '--port=0'!
+
If the program shall run as a daemon, use the --daemon option. This
will completely detach it from the terminal and will continue as a
background process.
@@ -64,7 +73,9 @@ All recordings are written into directories below "/video". Please
make sure this directory exists, and that the user who runs the 'vdr'
program has read and write access to that directory.
If you prefer a different location for your video files, you can use
-the '-v' option to change that.
+the '-v' option to change that. Please make sure that the directory
+name you use with '-v' is a clean and absolute path name (no '..' or
+multiple slashes).
Note that the file system need not be 64-bit proof, since the 'vdr'
program splits video files into chunks of about 1GB. You should use
@@ -102,14 +113,15 @@ Configuration files:
--------------------
There are three configuration files that hold information about
-channels, remote control keys and timers. These files are currrently
-assumed to be located in the directory from which the 'vdr' program
-was started (this will become configurable later). The configuration
-files can be edited with any text editor, or will be written by the
-'vdr' program if any changes are made inside the on-screen menus.
-The meaning of the data entries may still vary in future releases,
-so for the moment please look at the source code (config.c) to see
-the meaning of the various fields.
+channels, remote control keys and timers. By default these files are
+assumed to be located in the video directory, but a different directory
+can be used with the '-c' option.
+
+The configuration files can be edited with any text editor, or will be written
+by the 'vdr' program if any changes are made inside the on-screen menus.
+The meaning of the data entries may still vary in future releases, so for the
+moment please look at the source code (config.c) to see the meaning of the
+various fields.
The files that come with this package contain the author's selections,
so please make sure you adapt these to your personal taste. Also make sure
diff --git a/Makefile b/Makefile
index 2f00459..fef7a6f 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: Makefile 1.9 2000/09/10 08:55:45 kls Exp $
+# $Id: Makefile 1.11 2000/09/20 17:01:57 kls Exp $
DVBDIR = ../DVB
@@ -26,21 +26,21 @@ endif
all: vdr
-config.o : config.c config.h dvbapi.h eit.h interface.h tools.h
-dvbapi.o : dvbapi.c config.h dvbapi.h interface.h tools.h videodir.h
-eit.o : eit.c eit.h
-interface.o: interface.c config.h dvbapi.h eit.h interface.h remote.h tools.h
-menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h recording.h tools.h
-osd.o : osd.c config.h dvbapi.h interface.h osd.h tools.h
-vdr.o : vdr.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h
-recording.o: recording.c config.h dvbapi.h interface.h recording.h tools.h videodir.h
-remote.o : remote.c remote.h tools.h
-svdrp.o : svdrp.c svdrp.h config.h interface.h tools.h
+config.o : config.c config.h dvbapi.h eit.h interface.h svdrp.h tools.h
+dvbapi.o : dvbapi.c config.h dvbapi.h interface.h svdrp.h tools.h videodir.h
+eit.o : eit.c eit.h tools.h
+interface.o: interface.c config.h dvbapi.h eit.h interface.h remote.h svdrp.h tools.h
+menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h
+osd.o : osd.c config.h dvbapi.h interface.h osd.h svdrp.h tools.h
+recording.o: recording.c config.h dvbapi.h interface.h recording.h svdrp.h tools.h videodir.h
+remote.o : remote.c config.h dvbapi.h remote.h tools.h
+svdrp.o : svdrp.c config.h dvbapi.h interface.h svdrp.h tools.h
tools.o : tools.c tools.h
+vdr.o : vdr.c config.h dvbapi.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h
vdr: $(OBJS)
- g++ -g -O2 $(OBJS) -lncurses -o vdr
+ g++ -g -O2 $(OBJS) -lncurses -ljpeg -o vdr
clean:
-rm $(OBJS) vdr
diff --git a/TODO b/TODO
index 09e9a10..f2fb5ea 100644
--- a/TODO
+++ b/TODO
@@ -7,5 +7,4 @@ TODO list for the Video Disk Recorder project
scenes in order to archive them (or, reversely, cut out
commercial breaks).
* Implement channel scanning.
-* Better support for encrypted channels.
* Implement remaining commands in SVDRP.
diff --git a/config.c b/config.c
index 0a965ee..e161efd 100644
--- a/config.c
+++ b/config.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.c 1.22 2000/09/10 15:07:15 kls Exp $
+ * $Id: config.c 1.23 2000/09/17 09:11:59 kls Exp $
*/
#include "config.h"
@@ -155,14 +155,22 @@ eKeys cKeys::Get(unsigned int Code)
return kNone;
}
-unsigned int cKeys::Encode(const char *Command)
+eKeys cKeys::Translate(const char *Command)
{
- if (Command != NULL) {
+ if (Command) {
const tKey *k = keys;
- while ((k->type != kNone) && strcmp(k->name, Command) != 0)
+ while ((k->type != kNone) && strcasecmp(k->name, Command) != 0)
k++;
- return k->code;
+ return k->type;
}
+ return kNone;
+}
+
+unsigned int cKeys::Encode(const char *Command)
+{
+ eKeys k = Translate(Command);
+ if (k != kNone)
+ return keys[k].code;
return 0;
}
diff --git a/config.h b/config.h
index 30dd9ba..418fa63 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 1.19 2000/09/10 15:05:08 kls Exp $
+ * $Id: config.h 1.21 2000/09/17 09:08:13 kls Exp $
*/
#ifndef __CONFIG_H
@@ -17,7 +17,7 @@
#include "dvbapi.h"
#include "tools.h"
-#define VDRVERSION "0.63"
+#define VDRVERSION "0.64"
#define MaxBuffer 10000
@@ -55,6 +55,7 @@ public:
void SetDummyValues(void);
bool Load(const char *FileName = NULL);
bool Save(void);
+ eKeys Translate(const char *Command);
unsigned int Encode(const char *Command);
eKeys Get(unsigned int Code);
void Set(eKeys Key, unsigned int Code);
diff --git a/dvbapi.c b/dvbapi.c
index 9f9cbab..1468de6 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -4,14 +4,18 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.c 1.24 2000/09/10 10:25:09 kls Exp $
+ * $Id: dvbapi.c 1.27 2000/09/17 12:45:55 kls Exp $
*/
#include "dvbapi.h"
#include <errno.h>
#include <fcntl.h>
+extern "C" {
+#include <jpeglib.h>
+}
#include <stdlib.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
@@ -139,7 +143,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record)
LOG_ERROR;
}
if (Record) {
- if ((f = open(fileName, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) >= 0) {
+ if ((f = open(fileName, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP)) >= 0) {
if (delta) {
esyslog(LOG_ERR, "ERROR: padding index file with %d '0' bytes", delta);
while (delta--)
@@ -297,7 +301,7 @@ int cIndexFile::Get(uchar FileNumber, int FileOffset)
bool cIndexFile::StoreResume(int Index)
{
if (fileName) {
- int resumeFile = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ int resumeFile = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (resumeFile >= 0) {
if (write(resumeFile, &Index, sizeof(Index)) != sizeof(Index))
LOG_ERROR_STR(fileName);
@@ -315,8 +319,8 @@ char *cIndexFile::Str(int Index, bool WithFrame)
static char buffer[16];
int f = (Index % FRAMESPERSEC) + 1;
int s = (Index / FRAMESPERSEC);
- int m = s / 60 % 60;
- int h = s / 3600;
+ int m = s / 60 % 60;
+ int h = s / 3600;
s %= 60;
snprintf(buffer, sizeof(buffer), WithFrame ? "%d:%02d:%02d.%02d" : "%d:%02d:%02d", h, m, s, f);
return buffer;
@@ -511,7 +515,7 @@ protected:
char *fileName, *pFileNumber;
bool stop;
int GetAvPesLength(void)
- {
+ {
if (Byte(0) == 'A' && Byte(1) == 'V' && Byte(4) == 'U')
return (Byte(6) << 8) + Byte(7) + AV_PES_HEADER_LEN;
return 0;
@@ -751,7 +755,7 @@ int cRecordBuffer::Write(int Max)
if (n) {
if (stop && pictureType == I_FRAME) {
ok = false;
- return -1; // finish the recording before the next 'I' frame
+ return -1; // finish the recording before the next 'I' frame
}
if (NextFile()) {
if (index && pictureType != NO_PICTURE)
@@ -801,7 +805,7 @@ private:
void Close(void);
public:
cReplayBuffer(int *OutFile, const char *FileName);
- virtual ~cReplayBuffer();
+ virtual ~cReplayBuffer();
virtual int Read(int Max = -1);
virtual int Write(int Max = -1);
void SetMode(eReplayMode Mode);
@@ -1065,9 +1069,14 @@ cDvbApi::cDvbApi(const char *FileName)
if (videoDev < 0)
LOG_ERROR;
cols = rows = 0;
+
+ ovlGeoSet = ovlStat = ovlFbSet = false;
+ ovlBrightness = ovlColour = ovlHue = ovlContrast = 32768;
+ ovlClipCount = 0;
+
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
initscr();
- keypad(stdscr, TRUE);
+ keypad(stdscr, true);
nonl();
cbreak();
noecho();
@@ -1076,7 +1085,7 @@ cDvbApi::cDvbApi(const char *FileName)
#if defined(DEBUG_OSD)
memset(&colorPairs, 0, sizeof(colorPairs));
start_color();
- leaveok(stdscr, TRUE);
+ leaveok(stdscr, true);
window = NULL;
#endif
lastProgress = lastTotal = -1;
@@ -1089,6 +1098,7 @@ cDvbApi::~cDvbApi()
Close();
Stop();
StopRecord();
+ OvlO(false); //Overlay off!
close(videoDev);
}
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
@@ -1187,6 +1197,242 @@ void cDvbApi::Cleanup(void)
PrimaryDvbApi = NULL;
}
+bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
+{
+ int result = 0;
+ // just do this once?
+ struct video_mbuf mbuf;
+ result |= ioctl(videoDev, VIDIOCGMBUF, &mbuf);
+ int msize = mbuf.size;
+ // gf: this needs to be a protected member of cDvbApi! //XXX kls: WHY???
+ unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
+ if (!mem || mem == (unsigned char *)-1)
+ return false;
+ // set up the size and RGB
+ struct video_capability vc;
+ result |= ioctl(videoDev, VIDIOCGCAP, &vc);
+ struct video_mmap vm;
+ vm.frame = 0;
+ if ((SizeX > 0) && (SizeX <= vc.maxwidth) &&
+ (SizeY > 0) && (SizeY <= vc.maxheight)) {
+ vm.width = SizeX;
+ vm.height = SizeY;
+ }
+ else {
+ vm.width = vc.maxwidth;
+ vm.height = vc.maxheight;
+ }
+ vm.format = VIDEO_PALETTE_RGB24;
+ // this needs to be done every time:
+ result |= ioctl(videoDev, VIDIOCMCAPTURE, &vm);
+ result |= ioctl(videoDev, VIDIOCSYNC, &vm.frame);
+ // make RGB out of BGR:
+ int memsize = vm.width * vm.height;
+ unsigned char *mem1 = mem;
+ for (int i = 0; i < memsize; i++) {
+ unsigned char tmp = mem1[2];
+ mem1[2] = mem1[0];
+ mem1[0] = tmp;
+ mem1 += 3;
+ }
+
+ if (Quality < 0)
+ Quality = 255; //XXX is this 'best'???
+
+ isyslog(LOG_INFO, "grabbing to %s (%s %d %d %d)", FileName, Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height);
+ FILE *f = fopen(FileName, "wb");
+ if (f) {
+ if (Jpeg) {
+ // write JPEG file:
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+ cinfo.image_width = vm.width;
+ cinfo.image_height = vm.height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, Quality, true);
+ jpeg_start_compress(&cinfo, true);
+
+ int rs = vm.width * 3;
+ JSAMPROW rp[vm.height];
+ for (int k = 0; k < vm.height; k++)
+ rp[k] = &mem[rs * k];
+ jpeg_write_scanlines(&cinfo, rp, vm.height);
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ }
+ else {
+ // write PNM file:
+ if (fprintf(f, "P6\n%d\n%d\n255\n", vm.width, vm.height) < 0 ||
+ fwrite(mem, vm.width * vm.height * 3, 1, f) < 0) {
+ LOG_ERROR_STR(FileName);
+ result |= 1;
+ }
+ }
+ fclose(f);
+ }
+ else {
+ LOG_ERROR_STR(FileName);
+ result |= 1;
+ }
+
+ if (ovlStat && ovlGeoSet) {
+ // switch the Overlay on again (gf: why have i to do anything again?)
+ OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
+ }
+ if (ovlFbSet)
+ OvlP(ovlBrightness, ovlColour, ovlHue, ovlContrast);
+
+ munmap(mem, msize);
+ return result == 0;
+}
+
+bool cDvbApi::OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette)
+{
+ int result = 0;
+ // get the actual X-Server settings???
+ // plausibility-check problem: can't be verified w/o X-server!!!
+ if (SizeX <= 0 || SizeY <= 0 || FbAddr == 0 || Bpp / 8 > 4 ||
+ Bpp / 8 <= 0 || Palette <= 0 || Palette > 13 || ovlClipCount < 0 ||
+ SizeX > 4096 || SizeY > 4096) {
+ ovlFbSet = ovlGeoSet = false;
+ OvlO(false);
+ return false;
+ }
+ else {
+ dsyslog(LOG_INFO, "OvlF: %d %d %x %d %d", SizeX, SizeY, FbAddr, Bpp, Palette);
+ // this is the problematic part!
+ struct video_buffer vb;
+ result |= ioctl(videoDev, VIDIOCGFBUF, &vb);
+ vb.base = (void*)FbAddr;
+ vb.depth = Bpp;
+ vb.height = SizeY;
+ vb.width = SizeX;
+ vb.bytesperline = ((vb.depth + 1) / 8) * vb.width;
+ //now the real thing: setting the framebuffer
+ result |= ioctl(videoDev, VIDIOCSFBUF, &vb);
+ if (result) {
+ ovlFbSet = ovlGeoSet = false;
+ ovlClipCount = 0;
+ OvlO(false);
+ return false;
+ }
+ else {
+ ovlFbSizeX = SizeX;
+ ovlFbSizeY = SizeY;
+ ovlBpp = Bpp;
+ ovlPalette = Palette;
+ ovlFbSet = true;
+ return true;
+ }
+ }
+}
+
+bool cDvbApi::OvlG(int SizeX, int SizeY, int PosX, int PosY)
+{
+ int result = 0;
+ // get the actual X-Server settings???
+ struct video_capability vc;
+ result |= ioctl(videoDev, VIDIOCGCAP, &vc);
+ if (!ovlFbSet)
+ return false;
+ if (SizeX < vc.minwidth || SizeY < vc.minheight ||
+ SizeX > vc.maxwidth || SizeY>vc.maxheight
+// || PosX > FbSizeX || PosY > FbSizeY
+// PosX < -SizeX || PosY < -SizeY ||
+ ) {
+ ovlGeoSet = false;
+ OvlO(false);
+ return false;
+ }
+ else {
+ struct video_window vw;
+ result |= ioctl(videoDev, VIDIOCGWIN, &vw);
+ vw.x = PosX;
+ vw.y = PosY;
+ vw.width = SizeX;
+ vw.height = SizeY;
+ vw.chromakey = ovlPalette;
+ vw.flags = VIDEO_WINDOW_CHROMAKEY; // VIDEO_WINDOW_INTERLACE; //VIDEO_CLIP_BITMAP;
+ vw.clips = ovlClipRects;
+ vw.clipcount = ovlClipCount;
+ result |= ioctl(videoDev, VIDIOCSWIN, &vw);
+ if (result) {
+ ovlGeoSet = false;
+ ovlClipCount = 0;
+ return false;
+ }
+ else {
+ ovlSizeX = SizeX;
+ ovlSizeY = SizeY;
+ ovlPosX = PosX;
+ ovlPosY = PosY;
+ ovlGeoSet = true;
+ ovlStat = true;
+ return true;
+ }
+ }
+}
+
+bool cDvbApi::OvlC(int ClipCount, CRect *cr)
+{
+ if (ovlGeoSet && ovlFbSet) {
+ for (int i = 0; i < ClipCount; i++) {
+ ovlClipRects[i].x = cr[i].x;
+ ovlClipRects[i].y = cr[i].y;
+ ovlClipRects[i].width = cr[i].width;
+ ovlClipRects[i].height = cr[i].height;
+ ovlClipRects[i].next = &(ovlClipRects[i + 1]);
+ }
+ ovlClipCount = ClipCount;
+ //use it:
+ return OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
+ }
+ return false;
+}
+
+bool cDvbApi::OvlP(__u16 Brightness, __u16 Colour, __u16 Hue, __u16 Contrast)
+{
+ int result = 0;
+ ovlBrightness = Brightness;
+ ovlColour = Colour;
+ ovlHue = Hue;
+ ovlContrast = Contrast;
+ struct video_picture vp;
+ if (!ovlFbSet)
+ return false;
+ result |= ioctl(videoDev, VIDIOCGPICT, &vp);
+ vp.brightness = Brightness;
+ vp.colour = Colour;
+ vp.hue = Hue;
+ vp.contrast = Contrast;
+ vp.depth = ovlBpp;
+ vp.palette = ovlPalette; // gf: is this always ok? VIDEO_PALETTE_RGB565;
+ result |= ioctl(videoDev, VIDIOCSPICT, &vp);
+ return result == 0;
+}
+
+bool cDvbApi::OvlO(bool Value)
+{
+ int result = 0;
+ if (!ovlGeoSet && Value)
+ return false;
+ int one = 1;
+ int zero = 0;
+ result |= ioctl(videoDev, VIDIOCCAPTURE, Value ? &one : &zero);
+ ovlStat = Value;
+ if (result) {
+ ovlStat = false;
+ return false;
+ }
+ return true;
+}
+
#ifdef DEBUG_OSD
void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg)
{
@@ -1233,7 +1479,7 @@ void cDvbApi::Open(int w, int h)
rows = h;
#ifdef DEBUG_OSD
window = subwin(stdscr, h, w, d, 0);
- syncok(window, TRUE);
+ syncok(window, true);
#define B2C(b) (((b) * 1000) / 255)
#define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b))
#else
diff --git a/dvbapi.h b/dvbapi.h
index a43e707..08ba4bf 100644
--- a/dvbapi.h
+++ b/dvbapi.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.h 1.14 2000/09/10 10:03:29 kls Exp $
+ * $Id: dvbapi.h 1.16 2000/09/17 12:15:05 kls Exp $
*/
#ifndef __DVBAPI_H
@@ -21,6 +21,12 @@ typedef unsigned char __u8;
#include <stdio.h>
#include <dvb.h>
+// Overlay facilities
+#define MAXCLIPRECTS 100
+typedef struct CRect {
+ signed short x, y, width, height;
+ };
+
#define MenuLines 15
#define MenuColumns 40
@@ -70,6 +76,25 @@ public:
// Closes down all DVB devices.
// Must be called at the end of the program.
+ // Image Grab facilities
+
+ bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
+
+ // Overlay facilities
+
+private:
+ bool ovlStat, ovlGeoSet, ovlFbSet;
+ int ovlSizeX, ovlSizeY, ovlPosX, ovlPosY, ovlBpp, ovlPalette, ovlClips, ovlClipCount;
+ int ovlFbSizeX, ovlFbSizeY;
+ __u16 ovlBrightness, ovlColour, ovlHue, ovlContrast;
+ struct video_clip ovlClipRects[MAXCLIPRECTS];
+public:
+ bool OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette);
+ bool OvlG(int SizeX, int SizeY, int PosX, int PosY);
+ bool OvlC(int ClipCount, CRect *Cr);
+ bool OvlP(__u16 Brightness, __u16 Color, __u16 Hue, __u16 Contrast);
+ bool OvlO(bool Value);
+
// On Screen Display facilities
private:
diff --git a/eit.c b/eit.c
index c4c1200..d62c902 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.3 2000/09/17 15:23:05 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;
@@ -312,13 +308,12 @@ char * cEIT::mjd2string(unsigned short mjd)
/** */
int cEIT::GetEIT()
{
- unsigned char buf[1024];
+ unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
eit_t *eit;
struct eit_loop_struct1 *eitloop;
struct eit_short_event_descriptor_struct *eitevt;
- int seclen;
+ unsigned 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);
@@ -357,6 +350,8 @@ int cEIT::GetEIT()
seclen=(buf[6]<<8)|buf[7];
pid=(buf[4]<<8)|buf[5];
+ if (seclen >= sizeof(buf))
+ seclen = sizeof(buf) - 1;
read(fsvbi, buf, seclen);
if (seclen < (int)(sizeof(eit_t)
diff --git a/interface.c b/interface.c
index 5633f86..3d01238 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 16:04:14 kls Exp $
+ * $Id: interface.c 1.19 2000/09/19 17:41:23 kls Exp $
*/
#include "interface.h"
@@ -29,11 +29,19 @@ cInterface::cInterface(void)
open = 0;
cols[0] = 0;
keyFromWait = kNone;
+ SVDRP = NULL;
}
-void cInterface::Init(void)
+void cInterface::Init(int SVDRPport)
{
RcIo.SetCode(Keys.code, Keys.address);
+ if (SVDRPport)
+ SVDRP = new cSVDRP(SVDRPport);
+}
+
+void cInterface::Cleanup(void)
+{
+ delete SVDRP;
}
void cInterface::Open(int NumCols, int NumLines)
@@ -52,10 +60,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;
@@ -65,21 +69,24 @@ unsigned int cInterface::GetCh(bool Wait)
eKeys cInterface::GetKey(bool Wait)
{
+ if (SVDRP)
+ SVDRP->Process();
eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait));
keyFromWait = kNone;
return Key;
}
+void cInterface::PutKey(eKeys Key)
+{
+ keyFromWait = Key;
+}
+
eKeys cInterface::Wait(int Seconds, bool KeepChar)
{
- int t0 = time_ms() + Seconds * 1000;
eKeys Key = kNone;
-
- while (time_ms() < t0) {
- Key = GetKey();
- if (Key != kNone)
- break;
- }
+ RcIo.Flush(500);
+ if (cFile::AnyFileReady(-1, Seconds * 1000))
+ Key = GetKey();
if (KeepChar)
keyFromWait = Key;
return Key;
@@ -227,7 +234,7 @@ void cInterface::QueryKeys(void)
Keys.address = Address;
WriteText(1, 5, "RC code detected!");
WriteText(1, 6, "Do not press any key...");
- RcIo.Flush(3);
+ RcIo.Flush(3000);
ClearEol(0, 5);
ClearEol(0, 6);
break;
diff --git a/interface.h b/interface.h
index 4503dc6..8f7f1b8 100644
--- a/interface.h
+++ b/interface.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: interface.h 1.11 2000/09/10 10:35:46 kls Exp $
+ * $Id: interface.h 1.13 2000/09/18 22:29:31 kls Exp $
*/
#ifndef __INTERFACE_H
@@ -12,6 +12,7 @@
#include "config.h"
#include "dvbapi.h"
+#include "svdrp.h"
class cInterface {
public:
@@ -20,16 +21,19 @@ private:
int open;
int cols[MaxCols];
eKeys keyFromWait;
+ cSVDRP *SVDRP;
unsigned int GetCh(bool Wait = true);
void QueryKeys(void);
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
eKeys Wait(int Seconds = 1, bool KeepChar = false);
public:
cInterface(void);
- void Init(void);
+ void Init(int SVDRPport = 0);
+ void Cleanup(void);
void Open(int NumCols = MenuColumns, int NumLines = MenuLines);
void Close(void);
eKeys GetKey(bool Wait = true);
+ void PutKey(eKeys Key);
void Clear(void);
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
void SetCols(int *c);
diff --git a/menu.c b/menu.c
index ad803cf..114ea7e 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 1.26 2000/09/10 15:06:15 kls Exp $
+ * $Id: menu.c 1.27 2000/09/11 21:13:46 kls Exp $
*/
#include "menu.h"
@@ -1190,7 +1190,7 @@ eOSState cDirectChannelSelect::ProcessKey(eKeys Key)
if (number >= 0) {
number = number * 10 + Key - k0;
cChannel *channel = Channels.GetByNumber(number);
- char *Name = channel ? channel->name : "*** Invalid Channel ***";
+ const char *Name = channel ? channel->name : "*** Invalid Channel ***";
int BufSize = MenuColumns + 1;
char buffer[BufSize];
snprintf(buffer, BufSize, "%d %s", number, Name);
diff --git a/remote.c b/remote.c
index 0476962..46565a8 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.13 2000/09/19 17:40:52 kls Exp $
*/
#include "remote.h"
@@ -49,33 +49,29 @@ cRcIoBase::~cRcIoBase()
cRcIoKBD::cRcIoKBD(void)
{
+ f.Open(0); // stdin
}
cRcIoKBD::~cRcIoKBD()
{
}
-void cRcIoKBD::Flush(int WaitSeconds)
+void cRcIoKBD::Flush(int WaitMs)
{
- time_t t0 = time(NULL);
+ int t0 = time_ms();
timeout(10);
for (;;) {
while (getch() > 0)
- t0 = time(NULL);
- if (time(NULL) - t0 >= WaitSeconds)
+ t0 = time_ms();
+ if (time_ms() - t0 >= WaitMs)
break;
}
}
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;) {
@@ -179,21 +172,21 @@ bool cRcIoRCU::SetMode(unsigned char Mode)
return SendCommand(mode);
}
-void cRcIoRCU::Flush(int WaitSeconds)
+void cRcIoRCU::Flush(int WaitMs)
{
- time_t t0 = time(NULL);
+ int t0 = time_ms();
for (;;) {
while (ReceiveByte(false) >= 0)
- t0 = time(NULL);
- if (time(NULL) - t0 >= WaitSeconds)
+ t0 = time_ms();
+ if (time_ms() - t0 >= WaitMs)
break;
}
}
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)
@@ -389,24 +381,24 @@ const char *cRcIoLIRC::ReceiveString(void)
return NULL;
}
-void cRcIoLIRC::Flush(int WaitSeconds)
+void cRcIoLIRC::Flush(int WaitMs)
{
char buf[LIRC_BUFFER_SIZE];
- time_t t0 = time(NULL);
+ int t0 = time_ms();
for (;;) {
while (InputAvailable(false)) {
read(f, buf, sizeof(buf));
- t0 = time(NULL);
+ t0 = time_ms();
}
- if (time(NULL) - t0 >= WaitSeconds)
+ if (time_ms() - t0 >= WaitMs)
break;
}
}
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 7b94ac7..03f9155 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.9 2000/09/19 17:39:36 kls Exp $
*/
#ifndef __REMOTE_H
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <time.h>
+#include "tools.h"
class cRcIoBase {
protected:
@@ -28,7 +29,7 @@ public:
virtual void SetPoints(unsigned char Dp, bool On) {}
virtual bool String(char *s) { return true; }
virtual bool DetectCode(unsigned char *Code, unsigned short *Address) { return true; }
- virtual void Flush(int WaitSeconds = 0) {}
+ virtual void Flush(int WaitMs = 0) {}
virtual bool InputAvailable(bool Wait = false) = 0;
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL) = 0;
};
@@ -36,10 +37,12 @@ public:
#if defined REMOTE_KBD
class cRcIoKBD : public cRcIoBase {
+private:
+ cFile f;
public:
cRcIoKBD(void);
virtual ~cRcIoKBD();
- virtual void Flush(int WaitSeconds = 0);
+ virtual void Flush(int WaitMs = 0);
virtual bool InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
};
@@ -48,7 +51,7 @@ public:
class cRcIoRCU : public cRcIoBase {
private:
- int f;
+ cFile f;
unsigned char dp, code, mode;
unsigned short address;
int lastNumber;
@@ -66,7 +69,7 @@ public:
virtual void SetPoints(unsigned char Dp, bool On);
virtual bool String(char *s);
virtual bool DetectCode(unsigned char *Code, unsigned short *Address);
- virtual void Flush(int WaitSeconds = 0);
+ virtual void Flush(int WaitMs = 0);
virtual bool InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
};
@@ -76,13 +79,13 @@ 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:
cRcIoLIRC(char *DeviceName);
virtual ~cRcIoLIRC();
- virtual void Flush(int WaitSeconds = 0);
+ virtual void Flush(int WaitMs = 0);
virtual bool InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
};
diff --git a/svdrp.c b/svdrp.c
index 2af3ee5..c9ea7c3 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.10 2000/09/17 13:39:37 kls Exp $
*/
#define _GNU_SOURCE
@@ -120,8 +120,15 @@ const char *HelpPages[] = {
" Delete channel.",
"DELT <number>\n"
" Delete timer.",
+ "GRAB <filename> [ jpeg | pnm [ <quality> [ <sizex> <sizey> ] ] ]\n"
+ " Grab the current frame and save it to the given file. Images can\n"
+ " be stored as JPEG (default) or PNM, at the given quality (default\n"
+ " is 'maximum', only applies to JPEG) and size (default is full screen).",
"HELP [ <topic> ]\n"
" The HELP command gives help info.",
+ "HITK [ <key> ]\n"
+ " Hit the given remote control key. Without option a list of all\n"
+ " valid key names is given.",
"LSTC [ <number> | <name> ]\n"
" List channels. Without option, all channels are listed. Otherwise\n"
" only the given channel is listed. If a name is given, all channels\n"
@@ -147,6 +154,16 @@ const char *HelpPages[] = {
" Create a new timer. Settings must be in the same format as returned\n"
" by the LSTT command. It is an error if a timer with the same channel,\n"
" day, start and stop time already exists.",
+ "OVLF <sizex> <sizey> <fbaddr> <bpp> <palette>\n"
+ " Set the size, address depth and palette of the overlay.",
+ "OVLG <sizex> <sizey> <posx> <posy>\n"
+ " Set the size and position of the overlay.",
+ "OVLC <clipcount> <base16-CRect-array>\n"
+ " Set the overlay clipping rectangles.",
+ "OVLP <brightness> <colour> <hue> <contrast>\n"
+ " Set the picture parameters for the overlay.",
+ "OVLO 0 | 1\n"
+ " Switch the overlay on or off.",
"UPDT <settings>\n"
" Updates a timer. Settings must be in the same format as returned\n"
" by the LSTT command. If a timer with the same channel, day, start\n"
@@ -206,7 +223,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 +233,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,11 +247,14 @@ 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)
+ if (wbytes < 0) {
LOG_ERROR;
+ file.Close();
+ cDvbApi::PrimaryDvbApi->OvlO(false);
+ }
else //XXX while...???
esyslog(LOG_ERR, "Wrote %d bytes to client while expecting %d\n", wbytes, length);
return false;
@@ -244,7 +262,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);
@@ -274,7 +292,7 @@ void cSVDRP::Reply(int Code, const char *fmt, ...)
}
}
-void cSVDRP::CmdChan(const char *Option)
+void cSVDRP::CmdCHAN(const char *Option)
{
if (*Option) {
int n = -1;
@@ -331,13 +349,13 @@ void cSVDRP::CmdChan(const char *Option)
Reply(550, "Unable to find channel \"%d\"", CurrentChannel);
}
-void cSVDRP::CmdDelc(const char *Option)
+void cSVDRP::CmdDELC(const char *Option)
{
//TODO combine this with menu action (timers must be updated)
Reply(502, "DELC not yet implemented");
}
-void cSVDRP::CmdDelt(const char *Option)
+void cSVDRP::CmdDELT(const char *Option)
{
if (*Option) {
if (isnumber(Option)) {
@@ -362,7 +380,68 @@ void cSVDRP::CmdDelt(const char *Option)
Reply(501, "Missing timer number");
}
-void cSVDRP::CmdHelp(const char *Option)
+void cSVDRP::CmdGRAB(const char *Option)
+{
+ char *FileName = NULL;
+ bool Jpeg = true;
+ int Quality = -1, SizeX = -1, SizeY = -1;
+ if (*Option) {
+ char buf[strlen(Option) + 1];
+ char *p = strcpy(buf, Option);
+ const char *delim = " \t";
+ FileName = strtok(p, delim);
+ if ((p = strtok(NULL, delim)) != NULL) {
+ if (strcasecmp(p, "JPEG") == 0)
+ Jpeg = true;
+ else if (strcasecmp(p, "PNM") == 0)
+ Jpeg = false;
+ else {
+ Reply(501, "Unknown image type \"%s\"", p);
+ return;
+ }
+ }
+ if ((p = strtok(NULL, delim)) != NULL) {
+ if (isnumber(p))
+ Quality = atoi(p);
+ else {
+ Reply(501, "Illegal quality \"%s\"", p);
+ return;
+ }
+ }
+ if ((p = strtok(NULL, delim)) != NULL) {
+ if (isnumber(p))
+ SizeX = atoi(p);
+ else {
+ Reply(501, "Illegal sizex \"%s\"", p);
+ return;
+ }
+ if ((p = strtok(NULL, delim)) != NULL) {
+ if (isnumber(p))
+ SizeY = atoi(p);
+ else {
+ Reply(501, "Illegal sizey \"%s\"", p);
+ return;
+ }
+ }
+ else {
+ Reply(501, "Missing sizey");
+ return;
+ }
+ }
+ if ((p = strtok(NULL, delim)) != NULL) {
+ Reply(501, "Unexpected parameter \"%s\"", p);
+ return;
+ }
+ if (cDvbApi::PrimaryDvbApi->GrabImage(FileName, Jpeg, Quality, SizeX, SizeY))
+ Reply(250, "Grabbed image %s", Option);
+ else
+ Reply(451, "Grab image failed");
+ }
+ else
+ Reply(501, "Missing filename");
+}
+
+void cSVDRP::CmdHELP(const char *Option)
{
if (*Option) {
const char *hp = GetHelpPage(Option);
@@ -390,7 +469,27 @@ void cSVDRP::CmdHelp(const char *Option)
Reply(214, "End of HELP info");
}
-void cSVDRP::CmdLstc(const char *Option)
+void cSVDRP::CmdHITK(const char *Option)
+{
+ if (*Option) {
+ eKeys k = Keys.Translate(Option);
+ if (k != kNone) {
+ Interface.PutKey(k);
+ Reply(250, "Key \"%s\" accepted", Option);
+ }
+ else
+ Reply(504, "Unknown key: \"%s\"", Option);
+ }
+ else {
+ Reply(-214, "Valid <key> names for the HITK command:");
+ for (int i = 0; i < kNone; i++) {
+ Reply(-214, " %s", Keys.keys[i].name);
+ }
+ Reply(214, "End of key list");
+ }
+}
+
+void cSVDRP::CmdLSTC(const char *Option)
{
if (*Option) {
if (isnumber(Option)) {
@@ -433,7 +532,7 @@ void cSVDRP::CmdLstc(const char *Option)
}
}
-void cSVDRP::CmdLstt(const char *Option)
+void cSVDRP::CmdLSTT(const char *Option)
{
if (*Option) {
if (isnumber(Option)) {
@@ -457,7 +556,7 @@ void cSVDRP::CmdLstt(const char *Option)
}
}
-void cSVDRP::CmdModc(const char *Option)
+void cSVDRP::CmdMODC(const char *Option)
{
if (*Option) {
char *tail;
@@ -486,7 +585,7 @@ void cSVDRP::CmdModc(const char *Option)
Reply(501, "Missing channel settings");
}
-void cSVDRP::CmdModt(const char *Option)
+void cSVDRP::CmdMODT(const char *Option)
{
if (*Option) {
char *tail;
@@ -519,19 +618,19 @@ void cSVDRP::CmdModt(const char *Option)
Reply(501, "Missing timer settings");
}
-void cSVDRP::CmdMovc(const char *Option)
+void cSVDRP::CmdMOVC(const char *Option)
{
//TODO combine this with menu action (timers must be updated)
Reply(502, "MOVC not yet implemented");
}
-void cSVDRP::CmdMovt(const char *Option)
+void cSVDRP::CmdMOVT(const char *Option)
{
//TODO combine this with menu action
Reply(502, "MOVT not yet implemented");
}
-void cSVDRP::CmdNewc(const char *Option)
+void cSVDRP::CmdNEWC(const char *Option)
{
if (*Option) {
cChannel *channel = new cChannel;
@@ -549,7 +648,7 @@ void cSVDRP::CmdNewc(const char *Option)
Reply(501, "Missing channel settings");
}
-void cSVDRP::CmdNewt(const char *Option)
+void cSVDRP::CmdNEWT(const char *Option)
{
if (*Option) {
cTimer *timer = new cTimer;
@@ -573,7 +672,107 @@ void cSVDRP::CmdNewt(const char *Option)
Reply(501, "Missing timer settings");
}
-void cSVDRP::CmdUpdt(const char *Option)
+void cSVDRP::CmdOVLF(const char *Option)
+{
+ if (*Option) {
+ int SizeX = 0, SizeY = 0, Bpp = 0, Palette = 0, FbAddr = 0;
+ if (5 == sscanf(Option, "%d %d %x %d %d", &SizeX, &SizeY, &FbAddr, &Bpp, &Palette)) {
+ //somehow_set_overlay_geometry;
+ if (cDvbApi::PrimaryDvbApi->OvlF(SizeX, SizeY, FbAddr, Bpp, Palette))
+ Reply(250, "Overlay framebuffer set");
+ else
+ Reply(451, "Illegal overlay framebuffer settings");
+ }
+ else
+ Reply(501, "Could not parse overlay framebuffer settings");
+ }
+ else
+ Reply(501, "Missing overlay framebuffer settings");
+}
+
+void cSVDRP::CmdOVLG(const char *Option)
+{
+ if (*Option) {
+ int SizeX = 0, SizeY = 0, PosX = 0, PosY = 0;
+ if (4 == sscanf(Option, "%d %d %d %d", &SizeX, &SizeY, &PosX, &PosY)) {
+ //somehow_set_overlay_geometry;
+ if (cDvbApi::PrimaryDvbApi->OvlG(SizeX, SizeY, PosX, PosY))
+ Reply(250, "Overlay geometry set");
+ else
+ Reply(451, "Illegal overlay geometry settings");
+ }
+ else
+ Reply(501, "Could not parse overlay geometry settings");
+ }
+ else
+ Reply(501, "Missing overlay geometry settings");
+}
+
+void cSVDRP::CmdOVLC(const char *Option)
+{
+ if (*Option) {
+ int ClipCount = 0;
+ unsigned char s[2 * MAXCLIPRECTS * sizeof(CRect) + 2];
+ if (2 == sscanf(Option, "%d %s", &ClipCount, s)) {
+ // Base16-decoding of CRect-array:
+ unsigned char *p = (unsigned char*)ovlClipRects;
+ int i = 0, size = sizeof(CRect)*ClipCount;
+ for (int j = 0; i < size; i++) {
+ p[i] = (s[j++] - 65);
+ p[i] += (s[j++] - 65) << 4;
+ }
+ if (((unsigned)ClipCount == (i / sizeof(CRect))) && (ClipCount >= 0)) {
+ // apply it:
+ if (cDvbApi::PrimaryDvbApi->OvlC(ClipCount, ovlClipRects))
+ Reply(250, "Overlay-Clipping set");
+ else
+ Reply(451, "Illegal overlay clipping settings");
+ return;
+ }
+ }
+ Reply(501, "Error parsing Overlay-Clipping settings");
+ }
+ else
+ Reply(501, "Missing Clipping settings");
+}
+
+void cSVDRP::CmdOVLP(const char *Option)
+{
+ if (*Option) {
+ int Brightness = 0, Colour = 0, Hue = 0, Contrast = 0;
+ if (4 == sscanf(Option, "%d %d %d %d", &Brightness, &Colour, &Hue, &Contrast)) {
+ //somehow_set_overlay_picture_settings;
+ if (cDvbApi::PrimaryDvbApi->OvlP(Brightness, Colour, Hue, Contrast))
+ Reply(250, "Overlay picture settings set");
+ else
+ Reply(451, "Illegal overlay picture settings");
+ }
+ else
+ Reply(501, "Could not parse overlay picture settings");
+ }
+ else
+ Reply(501, "Missing overlay picture settings");
+}
+
+void cSVDRP::CmdOVLO(const char *Option)
+{
+ if (*Option) {
+ int Value;
+ if (1 == sscanf(Option, "%d", &Value)) {
+ //somehow_set_overlay_picture_settings;
+ if (cDvbApi::PrimaryDvbApi->OvlO(Value))
+ Reply(250, "Overlay capture set");
+ else
+ Reply(451, "Error setting overlay capture");
+ }
+ else
+ Reply(501, "Could not parse status");
+ }
+ else
+ Reply(501, "Missing overlay capture status");
+}
+
+void cSVDRP::CmdUPDT(const char *Option)
{
if (*Option) {
cTimer *timer = new cTimer;
@@ -612,19 +811,26 @@ void cSVDRP::Execute(char *Cmd)
while (*s && !isspace(*s))
s++;
*s++ = 0;
- if (CMD("CHAN")) CmdChan(s);
- else if (CMD("DELC")) CmdDelc(s);
- else if (CMD("DELT")) CmdDelt(s);
- else if (CMD("HELP")) CmdHelp(s);
- else if (CMD("LSTC")) CmdLstc(s);
- else if (CMD("LSTT")) CmdLstt(s);
- else if (CMD("MODC")) CmdModc(s);
- else if (CMD("MODT")) CmdModt(s);
- else if (CMD("MOVC")) CmdMovc(s);
- else if (CMD("MOVT")) CmdMovt(s);
- else if (CMD("NEWC")) CmdNewc(s);
- else if (CMD("NEWT")) CmdNewt(s);
- else if (CMD("UPDT")) CmdUpdt(s);
+ if (CMD("CHAN")) CmdCHAN(s);
+ else if (CMD("DELC")) CmdDELC(s);
+ else if (CMD("DELT")) CmdDELT(s);
+ else if (CMD("GRAB")) CmdGRAB(s);
+ else if (CMD("HELP")) CmdHELP(s);
+ else if (CMD("HITK")) CmdHITK(s);
+ else if (CMD("LSTC")) CmdLSTC(s);
+ else if (CMD("LSTT")) CmdLSTT(s);
+ else if (CMD("MODC")) CmdMODC(s);
+ else if (CMD("MODT")) CmdMODT(s);
+ else if (CMD("MOVC")) CmdMOVC(s);
+ else if (CMD("MOVT")) CmdMOVT(s);
+ else if (CMD("NEWC")) CmdNEWC(s);
+ else if (CMD("NEWT")) CmdNEWT(s);
+ else if (CMD("OVLF")) CmdOVLF(s);
+ else if (CMD("OVLG")) CmdOVLG(s);
+ else if (CMD("OVLC")) CmdOVLC(s);
+ else if (CMD("OVLP")) CmdOVLP(s);
+ else if (CMD("OVLO")) CmdOVLO(s);
+ else if (CMD("UPDT")) CmdUPDT(s);
else if (CMD("QUIT")
|| CMD("\x04")) Close();
else Reply(500, "Command unrecognized: \"%s\"", Cmd);
@@ -632,9 +838,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 +848,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 3c1cafa..12eb11e 100644
--- a/svdrp.h
+++ b/svdrp.h
@@ -4,12 +4,15 @@
* 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.6 2000/09/17 13:22:04 kls Exp $
*/
#ifndef __SVDRP_H
#define __SVDRP_H
+#include "dvbapi.h"
+#include "tools.h"
+
class cSocket {
private:
int port;
@@ -26,23 +29,31 @@ public:
class cSVDRP {
private:
cSocket socket;
- int filedes;
+ cFile file;
+ CRect ovlClipRects[MAXCLIPRECTS];
void Close(void);
bool Send(const char *s, int length = -1);
void Reply(int Code, const char *fmt, ...);
- void CmdChan(const char *Option);
- void CmdDelc(const char *Option);
- void CmdDelt(const char *Option);
- void CmdHelp(const char *Option);
- void CmdLstc(const char *Option);
- void CmdLstt(const char *Option);
- void CmdModc(const char *Option);
- void CmdModt(const char *Option);
- void CmdMovc(const char *Option);
- void CmdMovt(const char *Option);
- void CmdNewc(const char *Option);
- void CmdNewt(const char *Option);
- void CmdUpdt(const char *Option);
+ void CmdCHAN(const char *Option);
+ void CmdDELC(const char *Option);
+ void CmdDELT(const char *Option);
+ void CmdGRAB(const char *Option);
+ void CmdHELP(const char *Option);
+ void CmdHITK(const char *Option);
+ void CmdLSTC(const char *Option);
+ void CmdLSTT(const char *Option);
+ void CmdMODC(const char *Option);
+ void CmdMODT(const char *Option);
+ void CmdMOVC(const char *Option);
+ void CmdMOVT(const char *Option);
+ void CmdNEWC(const char *Option);
+ void CmdNEWT(const char *Option);
+ void CmdOVLF(const char *Option);
+ void CmdOVLG(const char *Option);
+ void CmdOVLC(const char *Option);
+ void CmdOVLP(const char *Option);
+ void CmdOVLO(const char *Option);
+ void CmdUPDT(const char *Option);
void Execute(char *Cmd);
public:
cSVDRP(int Port);
diff --git a/timers.conf b/timers.conf
index 9031d35..a625527 100644
--- a/timers.conf
+++ b/timers.conf
@@ -1,12 +1,14 @@
1:15:M------:2128:2205:99:7:Neues:
-1:3:-T-----:2013:2125:99:99:SevenDays
-1:10:-T-----:2058:2202:99:10:Quarks:
-1:26:-T-----:2255:0005:99:99:UFO:
-0:3:---T---:2211:2300:99:10:Switch:
+1:3:-T-----:2013:2125:99:99:SevenDays:
+0:10:-T-----:2058:2202:99:10:Quarks:
+1:26:-T-----:2255:0015:99:99:UFO:
+1:3:---T---:2215:2315:99:10:IngoAppelt:
1:2:----F--:2140:2225:10:10:WWW:
+1:1:----F--:2212:2325:99:99:7Tage7Koepfe:
1:11:-----S-:2158:2235:99:99:Computer:
1:2:-----S-:2213:2320:99:30:Wochenshow:
-1:11:------S:2058:2120:99:10:Centauri:
+1:11:------S:2013:2035:99:10:Centauri:
+1:14:------S:2158:2235:99:14:MaxUndLisa:
1:15:MTWTF--:1828:1901:10:5:nano:
1:1:-TWTF--:0955:1040:99:99:Ellen:
1:1:MTWTF--:1553:1710:99:99:Hammerman:
diff --git a/tools.c b/tools.c
index e081ee7..79d2ee6 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.14 2000/09/09 12:53:34 kls Exp $
+ * $Id: tools.c 1.19 2000/09/19 17:55:09 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;
- break;
- }
- 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);
}
@@ -153,6 +122,14 @@ bool isnumber(const char *s)
return true;
}
+const char *AddDirectory(const char *DirName, const char *FileName)
+{
+ static char *buf = NULL;
+ delete buf;
+ asprintf(&buf, "%s/%s", DirName && *DirName ? DirName : ".", FileName);
+ return buf;
+}
+
#define DFCMD "df -m %s"
uint FreeDiskSpaceMB(const char *Directory)
@@ -313,6 +290,110 @@ 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, 1);
+ if (n == 0)
+ break; // EOF
+ if (n < 0) {
+ LOG_ERROR;
+ return -1;
+ }
+ rbytes += n;
+ if (rbytes == Size || Buffer[rbytes - 1] == '\n')
+ 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
+ if (TimeoutMs == 0)
+ TimeoutMs = 10; // load gets too heavy with 0
+ 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 1ef955c..5c749a7 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.13 2000/09/09 12:53:10 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);
@@ -44,6 +43,7 @@ char *skipspace(char *s);
int time_ms(void);
void delay_ms(int ms);
bool isnumber(const char *s);
+const char *AddDirectory(const char *DirName, const char *FileName);
uint FreeDiskSpaceMB(const char *Directory);
bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false);
@@ -51,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;
diff --git a/vdr.c b/vdr.c
index 4932bf2..91643c2 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
- * $Id: vdr.c 1.30 2000/09/10 14:33:09 kls Exp $
+ * $Id: vdr.c 1.35 2000/09/20 16:45:01 kls Exp $
*/
#include <getopt.h>
@@ -34,7 +34,6 @@
#include "interface.h"
#include "menu.h"
#include "recording.h"
-#include "svdrp.h"
#include "tools.h"
#include "videodir.h"
@@ -46,9 +45,11 @@
static int Interrupted = 0;
-void SignalHandler(int signum)
+static void SignalHandler(int signum)
{
- Interrupted = signum;
+ if (signum != SIGPIPE)
+ Interrupted = signum;
+ signal(signum, SignalHandler);
}
int main(int argc, char *argv[])
@@ -58,9 +59,11 @@ int main(int argc, char *argv[])
#define DEFAULTSVDRPPORT 2001
int SVDRPport = DEFAULTSVDRPPORT;
+ const char *ConfigDirectory = NULL;
bool DaemonMode = false;
static struct option long_options[] = {
+ { "config", required_argument, NULL, 'c' },
{ "daemon", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "log", required_argument, NULL, 'l' },
@@ -71,10 +74,14 @@ int main(int argc, char *argv[])
int c;
int option_index = 0;
- while ((c = getopt_long(argc, argv, "dhl:p:v:", long_options, &option_index)) != -1) {
+ while ((c = getopt_long(argc, argv, "c:dhl:p:v:", long_options, &option_index)) != -1) {
switch (c) {
+ case 'c': ConfigDirectory = optarg;
+ break;
case 'd': DaemonMode = true; break;
- case 'h': printf("Usage: vdr [OPTION]\n\n"
+ case 'h': printf("Usage: vdr [OPTION]\n\n" // for easier orientation, this is column 80|
+ " -c DIR, --config=DIR read config files from DIR (default is to read them\n"
+ " from the video directory)\n"
" -h, --help display this help and exit\n"
" -d, --daemon run in daemon mode\n"
" -l LEVEL, --log=LEVEL set log level (default: 3)\n"
@@ -108,6 +115,8 @@ int main(int argc, char *argv[])
}
break;
case 'v': VideoDirectory = optarg;
+ while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
+ optarg[strlen(optarg) - 1] = 0;
break;
default: abort();
}
@@ -128,7 +137,7 @@ int main(int argc, char *argv[])
// Daemon mode:
if (DaemonMode) {
-#ifndef DEBUG_OSD
+#if !defined(DEBUG_OSD) && !defined(REMOTE_KBD)
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno));
@@ -141,7 +150,7 @@ int main(int argc, char *argv[])
fclose(stdout);
fclose(stderr);
#else
- fprintf(stderr, "vdr: can't run in daemon mode with DEBUG_OSD on!\n");
+ fprintf(stderr, "vdr: can't run in daemon mode with DEBUG_OSD or REMOTE_KBD on!\n");
abort();
#endif
}
@@ -154,16 +163,19 @@ int main(int argc, char *argv[])
// Configuration data:
- Setup.Load("setup.conf");
- Channels.Load("channels.conf");
- Timers.Load("timers.conf");
+ if (!ConfigDirectory)
+ ConfigDirectory = VideoDirectory;
+
+ Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
+ Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"));
+ Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
#ifdef REMOTE_LIRC
Keys.SetDummyValues();
#else
- if (!Keys.Load(KEYS_CONF))
+ if (!Keys.Load(AddDirectory(ConfigDirectory, KEYS_CONF)))
Interface.LearnKeys();
#endif
- Interface.Init();
+ Interface.Init(SVDRPport);
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB);
@@ -174,10 +186,10 @@ int main(int argc, char *argv[])
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
+ if (signal(SIGPIPE, SignalHandler) == SIG_IGN) signal(SIGPIPE, SIG_IGN);
// Main program loop:
- cSVDRP *SVDRP = SVDRPport ? new cSVDRP(SVDRPport) : NULL;
cOsdBase *Menu = NULL;
cReplayControl *ReplayControl = NULL;
int LastChannel = -1;
@@ -267,13 +279,11 @@ int main(int argc, char *argv[])
default: break;
}
}
- if (SVDRP)
- SVDRP->Process();//TODO lock menu vs. SVDRP?
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu;
delete ReplayControl;
- delete SVDRP;
+ Interface.Cleanup();
cDvbApi::Cleanup();
isyslog(LOG_INFO, "exiting");
if (SysLogLevel > 0)
diff --git a/videodir.c b/videodir.c
index 7bd6299..91d362d 100644
--- a/videodir.c
+++ b/videodir.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: videodir.c 1.1 2000/07/29 15:21:42 kls Exp $
+ * $Id: videodir.c 1.2 2000/09/15 13:23:47 kls Exp $
*/
#include "videodir.h"
@@ -137,7 +137,7 @@ int OpenVideoFile(const char *FileName, int Flags)
}
}
}
- int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR);
+ int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR | S_IRGRP);
if (ActualFileName != FileName)
delete ActualFileName;
return Result;