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).
This commit is contained in:
Klaus Schmidinger 2000-09-20 18:00:00 +02:00
parent 76c331181a
commit 7e4b4d2905
22 changed files with 892 additions and 234 deletions

View File

@ -18,6 +18,9 @@ Heino Goldenstein <heino.goldenstein@microplex.de>
Guido Fiala <gfiala@s.netic.de> Guido Fiala <gfiala@s.netic.de>
for implementing slow forward/back 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> Robert Schneider <Robert.Schneider@lotus.com>
for implementing EIT support for displaying the current/next info for implementing EIT support for displaying the current/next info

35
HISTORY
View File

@ -168,3 +168,38 @@ Video Disk Recorder Revision History
entered so far together with the name of that channel are displayed on the entered so far together with the name of that channel are displayed on the
OSD (suggested by Martin Hammerschmid). 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).

32
INSTALL
View File

@ -16,7 +16,11 @@ you will have to change the definition of DVBDIR in the
Makefile. Makefile.
This program requires the card driver version 0.05 or higher 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 After extracting the package, change into the VDR directory
and type 'make'. This should produce an executable file 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 on port 2001 (use the --port=PORT option to change this). For details
about the SVDRP syntax see the source file 'svdrp.c'. 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 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 will completely detach it from the terminal and will continue as a
background process. 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' make sure this directory exists, and that the user who runs the 'vdr'
program has read and write access to that directory. program has read and write access to that directory.
If you prefer a different location for your video files, you can use 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' 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 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 There are three configuration files that hold information about
channels, remote control keys and timers. These files are currrently channels, remote control keys and timers. By default these files are
assumed to be located in the directory from which the 'vdr' program assumed to be located in the video directory, but a different directory
was started (this will become configurable later). The configuration can be used with the '-c' option.
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 configuration files can be edited with any text editor, or will be written
The meaning of the data entries may still vary in future releases, by the 'vdr' program if any changes are made inside the on-screen menus.
so for the moment please look at the source code (config.c) to see The meaning of the data entries may still vary in future releases, so for the
the meaning of the various fields. 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, 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 so please make sure you adapt these to your personal taste. Also make sure

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # 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 DVBDIR = ../DVB
@ -26,21 +26,21 @@ endif
all: vdr all: vdr
config.o : config.c config.h dvbapi.h eit.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 tools.h videodir.h dvbapi.o : dvbapi.c config.h dvbapi.h interface.h svdrp.h tools.h videodir.h
eit.o : eit.c eit.h eit.o : eit.c eit.h tools.h
interface.o: interface.c config.h dvbapi.h eit.h interface.h remote.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 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 tools.h osd.o : osd.c config.h dvbapi.h interface.h osd.h svdrp.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 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 config.h dvbapi.h remote.h tools.h
remote.o : remote.c remote.h tools.h svdrp.o : svdrp.c config.h dvbapi.h interface.h svdrp.h tools.h
svdrp.o : svdrp.c svdrp.h config.h interface.h tools.h
tools.o : tools.c 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 videodir.o : videodir.c tools.h videodir.h
vdr: $(OBJS) vdr: $(OBJS)
g++ -g -O2 $(OBJS) -lncurses -o vdr g++ -g -O2 $(OBJS) -lncurses -ljpeg -o vdr
clean: clean:
-rm $(OBJS) vdr -rm $(OBJS) vdr

1
TODO
View File

@ -7,5 +7,4 @@ TODO list for the Video Disk Recorder project
scenes in order to archive them (or, reversely, cut out scenes in order to archive them (or, reversely, cut out
commercial breaks). commercial breaks).
* Implement channel scanning. * Implement channel scanning.
* Better support for encrypted channels.
* Implement remaining commands in SVDRP. * Implement remaining commands in SVDRP.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "config.h"
@ -155,14 +155,22 @@ eKeys cKeys::Get(unsigned int Code)
return kNone; return kNone;
} }
eKeys cKeys::Translate(const char *Command)
{
if (Command) {
const tKey *k = keys;
while ((k->type != kNone) && strcasecmp(k->name, Command) != 0)
k++;
return k->type;
}
return kNone;
}
unsigned int cKeys::Encode(const char *Command) unsigned int cKeys::Encode(const char *Command)
{ {
if (Command != NULL) { eKeys k = Translate(Command);
const tKey *k = keys; if (k != kNone)
while ((k->type != kNone) && strcmp(k->name, Command) != 0) return keys[k].code;
k++;
return k->code;
}
return 0; return 0;
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __CONFIG_H
@ -17,7 +17,7 @@
#include "dvbapi.h" #include "dvbapi.h"
#include "tools.h" #include "tools.h"
#define VDRVERSION "0.63" #define VDRVERSION "0.64"
#define MaxBuffer 10000 #define MaxBuffer 10000
@ -55,6 +55,7 @@ public:
void SetDummyValues(void); void SetDummyValues(void);
bool Load(const char *FileName = NULL); bool Load(const char *FileName = NULL);
bool Save(void); bool Save(void);
eKeys Translate(const char *Command);
unsigned int Encode(const char *Command); unsigned int Encode(const char *Command);
eKeys Get(unsigned int Code); eKeys Get(unsigned int Code);
void Set(eKeys Key, unsigned int Code); void Set(eKeys Key, unsigned int Code);

258
dvbapi.c
View File

@ -4,14 +4,18 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 "dvbapi.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
extern "C" {
#include <jpeglib.h>
}
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
@ -139,7 +143,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record)
LOG_ERROR; LOG_ERROR;
} }
if (Record) { 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) { if (delta) {
esyslog(LOG_ERR, "ERROR: padding index file with %d '0' bytes", delta); esyslog(LOG_ERR, "ERROR: padding index file with %d '0' bytes", delta);
while (delta--) while (delta--)
@ -297,7 +301,7 @@ int cIndexFile::Get(uchar FileNumber, int FileOffset)
bool cIndexFile::StoreResume(int Index) bool cIndexFile::StoreResume(int Index)
{ {
if (fileName) { 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 (resumeFile >= 0) {
if (write(resumeFile, &Index, sizeof(Index)) != sizeof(Index)) if (write(resumeFile, &Index, sizeof(Index)) != sizeof(Index))
LOG_ERROR_STR(fileName); LOG_ERROR_STR(fileName);
@ -1065,9 +1069,14 @@ cDvbApi::cDvbApi(const char *FileName)
if (videoDev < 0) if (videoDev < 0)
LOG_ERROR; LOG_ERROR;
cols = rows = 0; cols = rows = 0;
ovlGeoSet = ovlStat = ovlFbSet = false;
ovlBrightness = ovlColour = ovlHue = ovlContrast = 32768;
ovlClipCount = 0;
#if defined(DEBUG_OSD) || defined(REMOTE_KBD) #if defined(DEBUG_OSD) || defined(REMOTE_KBD)
initscr(); initscr();
keypad(stdscr, TRUE); keypad(stdscr, true);
nonl(); nonl();
cbreak(); cbreak();
noecho(); noecho();
@ -1076,7 +1085,7 @@ cDvbApi::cDvbApi(const char *FileName)
#if defined(DEBUG_OSD) #if defined(DEBUG_OSD)
memset(&colorPairs, 0, sizeof(colorPairs)); memset(&colorPairs, 0, sizeof(colorPairs));
start_color(); start_color();
leaveok(stdscr, TRUE); leaveok(stdscr, true);
window = NULL; window = NULL;
#endif #endif
lastProgress = lastTotal = -1; lastProgress = lastTotal = -1;
@ -1089,6 +1098,7 @@ cDvbApi::~cDvbApi()
Close(); Close();
Stop(); Stop();
StopRecord(); StopRecord();
OvlO(false); //Overlay off!
close(videoDev); close(videoDev);
} }
#if defined(DEBUG_OSD) || defined(REMOTE_KBD) #if defined(DEBUG_OSD) || defined(REMOTE_KBD)
@ -1187,6 +1197,242 @@ void cDvbApi::Cleanup(void)
PrimaryDvbApi = NULL; 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 #ifdef DEBUG_OSD
void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg) void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg)
{ {
@ -1233,7 +1479,7 @@ void cDvbApi::Open(int w, int h)
rows = h; rows = h;
#ifdef DEBUG_OSD #ifdef DEBUG_OSD
window = subwin(stdscr, h, w, d, 0); window = subwin(stdscr, h, w, d, 0);
syncok(window, TRUE); syncok(window, true);
#define B2C(b) (((b) * 1000) / 255) #define B2C(b) (((b) * 1000) / 255)
#define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b)) #define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b))
#else #else

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __DVBAPI_H
@ -21,6 +21,12 @@ typedef unsigned char __u8;
#include <stdio.h> #include <stdio.h>
#include <dvb.h> #include <dvb.h>
// Overlay facilities
#define MAXCLIPRECTS 100
typedef struct CRect {
signed short x, y, width, height;
};
#define MenuLines 15 #define MenuLines 15
#define MenuColumns 40 #define MenuColumns 40
@ -70,6 +76,25 @@ public:
// Closes down all DVB devices. // Closes down all DVB devices.
// Must be called at the end of the program. // 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 // On Screen Display facilities
private: private:

19
eit.c
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (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" #include "eit.h"
@ -22,7 +22,6 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
#include <sys/poll.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <dvb_comcode.h> #include <dvb_comcode.h>
#include "tools.h" #include "tools.h"
@ -253,15 +252,12 @@ int cEIT::GetSection(unsigned char *buf, ushort PID, unsigned char sec)
int seclen=0; int seclen=0;
unsigned short handle, pid; unsigned short handle, pid;
unsigned char section, sectionnum=0xff, maxsec=0; unsigned char section, sectionnum=0xff, maxsec=0;
struct pollfd pfd;
if ((handle = SetBitFilter(PID, (sec<<8)|0x00ff, SECTION_CONTINUOS))==0xffff) if ((handle = SetBitFilter(PID, (sec<<8)|0x00ff, SECTION_CONTINUOS))==0xffff)
return -1; return -1;
seclen=0; seclen=0;
pfd.fd=fsvbi; if (!cFile::AnyFileReady(fsvbi, 20000))
pfd.events=POLLIN;
if (poll(&pfd, 1, 20000)==0)
{ {
//cerr << "Timeout\n"; //cerr << "Timeout\n";
return -1; return -1;
@ -312,13 +308,12 @@ char * cEIT::mjd2string(unsigned short mjd)
/** */ /** */
int cEIT::GetEIT() 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; eit_t *eit;
struct eit_loop_struct1 *eitloop; struct eit_loop_struct1 *eitloop;
struct eit_short_event_descriptor_struct *eitevt; struct eit_short_event_descriptor_struct *eitevt;
int seclen; unsigned int seclen;
unsigned short handle, pid; unsigned short handle, pid;
struct pollfd pfd;
eit_event * pevt = (eit_event *)0; eit_event * pevt = (eit_event *)0;
time_t tstart; time_t tstart;
@ -344,9 +339,7 @@ int cEIT::GetEIT()
tstart = time(NULL); tstart = time(NULL);
while ((!evtRunning.bIsValid || !evtNext.bIsValid) && nReceivedEITs < 20 && difftime(time(NULL), tstart) < 4) while ((!evtRunning.bIsValid || !evtNext.bIsValid) && nReceivedEITs < 20 && difftime(time(NULL), tstart) < 4)
{ {
pfd.fd=fsvbi; if (!cFile::AnyFileReady(fsvbi, 5000))
pfd.events=POLLIN;
if (poll(&pfd, 1, 5000)==0)
{ {
//cerr << "Timeout\n"; //cerr << "Timeout\n";
CloseFilter(handle); CloseFilter(handle);
@ -357,6 +350,8 @@ int cEIT::GetEIT()
seclen=(buf[6]<<8)|buf[7]; seclen=(buf[6]<<8)|buf[7];
pid=(buf[4]<<8)|buf[5]; pid=(buf[4]<<8)|buf[5];
if (seclen >= sizeof(buf))
seclen = sizeof(buf) - 1;
read(fsvbi, buf, seclen); read(fsvbi, buf, seclen);
if (seclen < (int)(sizeof(eit_t) if (seclen < (int)(sizeof(eit_t)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "interface.h"
@ -29,11 +29,19 @@ cInterface::cInterface(void)
open = 0; open = 0;
cols[0] = 0; cols[0] = 0;
keyFromWait = kNone; keyFromWait = kNone;
SVDRP = NULL;
} }
void cInterface::Init(void) void cInterface::Init(int SVDRPport)
{ {
RcIo.SetCode(Keys.code, Keys.address); 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) void cInterface::Open(int NumCols, int NumLines)
@ -52,10 +60,6 @@ void cInterface::Close(void)
unsigned int cInterface::GetCh(bool Wait) unsigned int cInterface::GetCh(bool Wait)
{ {
#ifdef DEBUG_OSD
timeout(0);
getch(); // just to make 'ncurses' display the window:
#endif
if (RcIo.InputAvailable(Wait)) { if (RcIo.InputAvailable(Wait)) {
unsigned int Command; unsigned int Command;
return RcIo.GetCommand(&Command, NULL) ? Command : 0; return RcIo.GetCommand(&Command, NULL) ? Command : 0;
@ -65,21 +69,24 @@ unsigned int cInterface::GetCh(bool Wait)
eKeys cInterface::GetKey(bool Wait) eKeys cInterface::GetKey(bool Wait)
{ {
if (SVDRP)
SVDRP->Process();
eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait)); eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait));
keyFromWait = kNone; keyFromWait = kNone;
return Key; return Key;
} }
void cInterface::PutKey(eKeys Key)
{
keyFromWait = Key;
}
eKeys cInterface::Wait(int Seconds, bool KeepChar) eKeys cInterface::Wait(int Seconds, bool KeepChar)
{ {
int t0 = time_ms() + Seconds * 1000;
eKeys Key = kNone; eKeys Key = kNone;
RcIo.Flush(500);
while (time_ms() < t0) { if (cFile::AnyFileReady(-1, Seconds * 1000))
Key = GetKey(); Key = GetKey();
if (Key != kNone)
break;
}
if (KeepChar) if (KeepChar)
keyFromWait = Key; keyFromWait = Key;
return Key; return Key;
@ -227,7 +234,7 @@ void cInterface::QueryKeys(void)
Keys.address = Address; Keys.address = Address;
WriteText(1, 5, "RC code detected!"); WriteText(1, 5, "RC code detected!");
WriteText(1, 6, "Do not press any key..."); WriteText(1, 6, "Do not press any key...");
RcIo.Flush(3); RcIo.Flush(3000);
ClearEol(0, 5); ClearEol(0, 5);
ClearEol(0, 6); ClearEol(0, 6);
break; break;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __INTERFACE_H
@ -12,6 +12,7 @@
#include "config.h" #include "config.h"
#include "dvbapi.h" #include "dvbapi.h"
#include "svdrp.h"
class cInterface { class cInterface {
public: public:
@ -20,16 +21,19 @@ private:
int open; int open;
int cols[MaxCols]; int cols[MaxCols];
eKeys keyFromWait; eKeys keyFromWait;
cSVDRP *SVDRP;
unsigned int GetCh(bool Wait = true); unsigned int GetCh(bool Wait = true);
void QueryKeys(void); void QueryKeys(void);
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor); void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
eKeys Wait(int Seconds = 1, bool KeepChar = false); eKeys Wait(int Seconds = 1, bool KeepChar = false);
public: public:
cInterface(void); cInterface(void);
void Init(void); void Init(int SVDRPport = 0);
void Cleanup(void);
void Open(int NumCols = MenuColumns, int NumLines = MenuLines); void Open(int NumCols = MenuColumns, int NumLines = MenuLines);
void Close(void); void Close(void);
eKeys GetKey(bool Wait = true); eKeys GetKey(bool Wait = true);
void PutKey(eKeys Key);
void Clear(void); void Clear(void);
void ClearEol(int x, int y, eDvbColor Color = clrBackground); void ClearEol(int x, int y, eDvbColor Color = clrBackground);
void SetCols(int *c); void SetCols(int *c);

4
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "menu.h"
@ -1190,7 +1190,7 @@ eOSState cDirectChannelSelect::ProcessKey(eKeys Key)
if (number >= 0) { if (number >= 0) {
number = number * 10 + Key - k0; number = number * 10 + Key - k0;
cChannel *channel = Channels.GetByNumber(number); cChannel *channel = Channels.GetByNumber(number);
char *Name = channel ? channel->name : "*** Invalid Channel ***"; const char *Name = channel ? channel->name : "*** Invalid Channel ***";
int BufSize = MenuColumns + 1; int BufSize = MenuColumns + 1;
char buffer[BufSize]; char buffer[BufSize];
snprintf(buffer, BufSize, "%d %s", number, Name); snprintf(buffer, BufSize, "%d %s", number, Name);

View File

@ -6,7 +6,7 @@
* *
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16. * 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" #include "remote.h"
@ -49,33 +49,29 @@ cRcIoBase::~cRcIoBase()
cRcIoKBD::cRcIoKBD(void) cRcIoKBD::cRcIoKBD(void)
{ {
f.Open(0); // stdin
} }
cRcIoKBD::~cRcIoKBD() cRcIoKBD::~cRcIoKBD()
{ {
} }
void cRcIoKBD::Flush(int WaitSeconds) void cRcIoKBD::Flush(int WaitMs)
{ {
time_t t0 = time(NULL); int t0 = time_ms();
timeout(10); timeout(10);
for (;;) { for (;;) {
while (getch() > 0) while (getch() > 0)
t0 = time(NULL); t0 = time_ms();
if (time(NULL) - t0 >= WaitSeconds) if (time_ms() - t0 >= WaitMs)
break; break;
} }
} }
bool cRcIoKBD::InputAvailable(bool Wait) bool cRcIoKBD::InputAvailable(bool Wait)
{ {
timeout(Wait ? 1000 : 10); return f.Ready(Wait);
int ch = getch();
if (ch == ERR)
return false;
ungetch(ch);
return true;
} }
bool cRcIoKBD::GetCommand(unsigned int *Command, unsigned short *) bool cRcIoKBD::GetCommand(unsigned int *Command, unsigned short *)
@ -98,7 +94,7 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
code = 0; code = 0;
address = 0xFFFF; address = 0xFFFF;
lastNumber = 0; lastNumber = 0;
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) { if (f.Open(DeviceName, O_RDWR | O_NONBLOCK)) {
struct termios t; struct termios t;
if (tcgetattr(f, &t) == 0) { if (tcgetattr(f, &t) == 0) {
cfsetspeed(&t, B9600); cfsetspeed(&t, B9600);
@ -107,17 +103,14 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
return; return;
} }
LOG_ERROR_STR(DeviceName); LOG_ERROR_STR(DeviceName);
close(f); f.Close();
} }
else else
LOG_ERROR_STR(DeviceName); LOG_ERROR_STR(DeviceName);
f = -1;
} }
cRcIoRCU::~cRcIoRCU() cRcIoRCU::~cRcIoRCU()
{ {
if (f >= 0)
close(f);
} }
int cRcIoRCU::ReceiveByte(bool Wait) int cRcIoRCU::ReceiveByte(bool Wait)
@ -135,7 +128,7 @@ int cRcIoRCU::ReceiveByte(bool Wait)
bool cRcIoRCU::SendByteHandshake(unsigned char c) bool cRcIoRCU::SendByteHandshake(unsigned char c)
{ {
if (f >= 0) { if (f.IsOpen()) {
int w = write(f, &c, 1); int w = write(f, &c, 1);
if (w == 1) { if (w == 1) {
for (int reply = ReceiveByte(); reply >= 0;) { for (int reply = ReceiveByte(); reply >= 0;) {
@ -179,21 +172,21 @@ bool cRcIoRCU::SetMode(unsigned char Mode)
return SendCommand(mode); return SendCommand(mode);
} }
void cRcIoRCU::Flush(int WaitSeconds) void cRcIoRCU::Flush(int WaitMs)
{ {
time_t t0 = time(NULL); int t0 = time_ms();
for (;;) { for (;;) {
while (ReceiveByte(false) >= 0) while (ReceiveByte(false) >= 0)
t0 = time(NULL); t0 = time_ms();
if (time(NULL) - t0 >= WaitSeconds) if (time_ms() - t0 >= WaitMs)
break; break;
} }
} }
bool cRcIoRCU::InputAvailable(bool Wait) bool cRcIoRCU::InputAvailable(bool Wait)
{ {
return DataAvailable(f, Wait); return f.Ready(Wait);
} }
bool cRcIoRCU::GetCommand(unsigned int *Command, unsigned short *Address) bool cRcIoRCU::GetCommand(unsigned int *Command, unsigned short *Address)
@ -349,22 +342,21 @@ cRcIoLIRC::cRcIoLIRC(char *DeviceName)
struct sockaddr_un addr; struct sockaddr_un addr;
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DeviceName); strcpy(addr.sun_path, DeviceName);
f = socket(AF_UNIX, SOCK_STREAM, 0); int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (f >= 0) { if (sock >= 0) {
if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0) if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
f.Open(sock);
return; return;
}
LOG_ERROR_STR(DeviceName); LOG_ERROR_STR(DeviceName);
close(f); close(sock);
} }
else else
LOG_ERROR_STR(DeviceName); LOG_ERROR_STR(DeviceName);
f = -1;
} }
cRcIoLIRC::~cRcIoLIRC() cRcIoLIRC::~cRcIoLIRC()
{ {
if (f >= 0)
close(f);
} }
const char *cRcIoLIRC::ReceiveString(void) const char *cRcIoLIRC::ReceiveString(void)
@ -389,24 +381,24 @@ const char *cRcIoLIRC::ReceiveString(void)
return NULL; return NULL;
} }
void cRcIoLIRC::Flush(int WaitSeconds) void cRcIoLIRC::Flush(int WaitMs)
{ {
char buf[LIRC_BUFFER_SIZE]; char buf[LIRC_BUFFER_SIZE];
time_t t0 = time(NULL); int t0 = time_ms();
for (;;) { for (;;) {
while (InputAvailable(false)) { while (InputAvailable(false)) {
read(f, buf, sizeof(buf)); read(f, buf, sizeof(buf));
t0 = time(NULL); t0 = time_ms();
} }
if (time(NULL) - t0 >= WaitSeconds) if (time_ms() - t0 >= WaitMs)
break; break;
} }
} }
bool cRcIoLIRC::InputAvailable(bool Wait) bool cRcIoLIRC::InputAvailable(bool Wait)
{ {
return DataAvailable(f, Wait); return f.Ready(Wait);
} }
bool cRcIoLIRC::GetCommand(unsigned int *Command, unsigned short *) 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __REMOTE_H
@ -12,6 +12,7 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "tools.h"
class cRcIoBase { class cRcIoBase {
protected: protected:
@ -28,7 +29,7 @@ public:
virtual void SetPoints(unsigned char Dp, bool On) {} virtual void SetPoints(unsigned char Dp, bool On) {}
virtual bool String(char *s) { return true; } virtual bool String(char *s) { return true; }
virtual bool DetectCode(unsigned char *Code, unsigned short *Address) { 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 InputAvailable(bool Wait = false) = 0;
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL) = 0; virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL) = 0;
}; };
@ -36,10 +37,12 @@ public:
#if defined REMOTE_KBD #if defined REMOTE_KBD
class cRcIoKBD : public cRcIoBase { class cRcIoKBD : public cRcIoBase {
private:
cFile f;
public: public:
cRcIoKBD(void); cRcIoKBD(void);
virtual ~cRcIoKBD(); virtual ~cRcIoKBD();
virtual void Flush(int WaitSeconds = 0); virtual void Flush(int WaitMs = 0);
virtual bool InputAvailable(bool Wait = false); virtual bool InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL); virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
}; };
@ -48,7 +51,7 @@ public:
class cRcIoRCU : public cRcIoBase { class cRcIoRCU : public cRcIoBase {
private: private:
int f; cFile f;
unsigned char dp, code, mode; unsigned char dp, code, mode;
unsigned short address; unsigned short address;
int lastNumber; int lastNumber;
@ -66,7 +69,7 @@ public:
virtual void SetPoints(unsigned char Dp, bool On); virtual void SetPoints(unsigned char Dp, bool On);
virtual bool String(char *s); virtual bool String(char *s);
virtual bool DetectCode(unsigned char *Code, unsigned short *Address); 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 InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL); virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
}; };
@ -76,13 +79,13 @@ public:
class cRcIoLIRC : public cRcIoBase { class cRcIoLIRC : public cRcIoBase {
private: private:
enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 }; enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 };
int f; cFile f;
char keyName[LIRC_KEY_BUF]; char keyName[LIRC_KEY_BUF];
const char *ReceiveString(void); const char *ReceiveString(void);
public: public:
cRcIoLIRC(char *DeviceName); cRcIoLIRC(char *DeviceName);
virtual ~cRcIoLIRC(); virtual ~cRcIoLIRC();
virtual void Flush(int WaitSeconds = 0); virtual void Flush(int WaitMs = 0);
virtual bool InputAvailable(bool Wait = false); virtual bool InputAvailable(bool Wait = false);
virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL); virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
}; };

280
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * 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 #define _GNU_SOURCE
@ -120,8 +120,15 @@ const char *HelpPages[] = {
" Delete channel.", " Delete channel.",
"DELT <number>\n" "DELT <number>\n"
" Delete timer.", " 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" "HELP [ <topic> ]\n"
" The HELP command gives help info.", " 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" "LSTC [ <number> | <name> ]\n"
" List channels. Without option, all channels are listed. Otherwise\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" " 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" " 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" " by the LSTT command. It is an error if a timer with the same channel,\n"
" day, start and stop time already exists.", " 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" "UPDT <settings>\n"
" Updates a timer. Settings must be in the same format as returned\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" " 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) cSVDRP::cSVDRP(int Port)
:socket(Port) :socket(Port)
{ {
filedes = -1;
isyslog(LOG_INFO, "SVDRP listening on port %d", Port); isyslog(LOG_INFO, "SVDRP listening on port %d", Port);
} }
@ -217,14 +233,13 @@ cSVDRP::~cSVDRP()
void cSVDRP::Close(void) void cSVDRP::Close(void)
{ {
if (filedes >= 0) { if (file.IsOpen()) {
//TODO how can we get the *full* hostname? //TODO how can we get the *full* hostname?
char buffer[MAXCMDBUFFER]; char buffer[MAXCMDBUFFER];
gethostname(buffer, sizeof(buffer)); gethostname(buffer, sizeof(buffer));
Reply(221, "%s closing connection", buffer); Reply(221, "%s closing connection", buffer);
isyslog(LOG_INFO, "closing connection"); //TODO store IP#??? isyslog(LOG_INFO, "closing connection"); //TODO store IP#???
close(filedes); file.Close();
filedes = -1;
} }
} }
@ -232,11 +247,14 @@ bool cSVDRP::Send(const char *s, int length)
{ {
if (length < 0) if (length < 0)
length = strlen(s); length = strlen(s);
int wbytes = write(filedes, s, length); int wbytes = write(file, s, length);
if (wbytes == length) if (wbytes == length)
return true; return true;
if (wbytes < 0) if (wbytes < 0) {
LOG_ERROR; LOG_ERROR;
file.Close();
cDvbApi::PrimaryDvbApi->OvlO(false);
}
else //XXX while...??? else //XXX while...???
esyslog(LOG_ERR, "Wrote %d bytes to client while expecting %d\n", wbytes, length); esyslog(LOG_ERR, "Wrote %d bytes to client while expecting %d\n", wbytes, length);
return false; return false;
@ -244,7 +262,7 @@ bool cSVDRP::Send(const char *s, int length)
void cSVDRP::Reply(int Code, const char *fmt, ...) void cSVDRP::Reply(int Code, const char *fmt, ...)
{ {
if (filedes >= 0) { if (file.IsOpen()) {
if (Code != 0) { if (Code != 0) {
va_list ap; va_list ap;
va_start(ap, fmt); 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) { if (*Option) {
int n = -1; int n = -1;
@ -331,13 +349,13 @@ void cSVDRP::CmdChan(const char *Option)
Reply(550, "Unable to find channel \"%d\"", CurrentChannel); 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) //TODO combine this with menu action (timers must be updated)
Reply(502, "DELC not yet implemented"); Reply(502, "DELC not yet implemented");
} }
void cSVDRP::CmdDelt(const char *Option) void cSVDRP::CmdDELT(const char *Option)
{ {
if (*Option) { if (*Option) {
if (isnumber(Option)) { if (isnumber(Option)) {
@ -362,7 +380,68 @@ void cSVDRP::CmdDelt(const char *Option)
Reply(501, "Missing timer number"); 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) { if (*Option) {
const char *hp = GetHelpPage(Option); const char *hp = GetHelpPage(Option);
@ -390,7 +469,27 @@ void cSVDRP::CmdHelp(const char *Option)
Reply(214, "End of HELP info"); 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 (*Option) {
if (isnumber(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 (*Option) {
if (isnumber(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) { if (*Option) {
char *tail; char *tail;
@ -486,7 +585,7 @@ void cSVDRP::CmdModc(const char *Option)
Reply(501, "Missing channel settings"); Reply(501, "Missing channel settings");
} }
void cSVDRP::CmdModt(const char *Option) void cSVDRP::CmdMODT(const char *Option)
{ {
if (*Option) { if (*Option) {
char *tail; char *tail;
@ -519,19 +618,19 @@ void cSVDRP::CmdModt(const char *Option)
Reply(501, "Missing timer settings"); 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) //TODO combine this with menu action (timers must be updated)
Reply(502, "MOVC not yet implemented"); Reply(502, "MOVC not yet implemented");
} }
void cSVDRP::CmdMovt(const char *Option) void cSVDRP::CmdMOVT(const char *Option)
{ {
//TODO combine this with menu action //TODO combine this with menu action
Reply(502, "MOVT not yet implemented"); Reply(502, "MOVT not yet implemented");
} }
void cSVDRP::CmdNewc(const char *Option) void cSVDRP::CmdNEWC(const char *Option)
{ {
if (*Option) { if (*Option) {
cChannel *channel = new cChannel; cChannel *channel = new cChannel;
@ -549,7 +648,7 @@ void cSVDRP::CmdNewc(const char *Option)
Reply(501, "Missing channel settings"); Reply(501, "Missing channel settings");
} }
void cSVDRP::CmdNewt(const char *Option) void cSVDRP::CmdNEWT(const char *Option)
{ {
if (*Option) { if (*Option) {
cTimer *timer = new cTimer; cTimer *timer = new cTimer;
@ -573,7 +672,107 @@ void cSVDRP::CmdNewt(const char *Option)
Reply(501, "Missing timer settings"); 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) { if (*Option) {
cTimer *timer = new cTimer; cTimer *timer = new cTimer;
@ -612,19 +811,26 @@ void cSVDRP::Execute(char *Cmd)
while (*s && !isspace(*s)) while (*s && !isspace(*s))
s++; s++;
*s++ = 0; *s++ = 0;
if (CMD("CHAN")) CmdChan(s); if (CMD("CHAN")) CmdCHAN(s);
else if (CMD("DELC")) CmdDelc(s); else if (CMD("DELC")) CmdDELC(s);
else if (CMD("DELT")) CmdDelt(s); else if (CMD("DELT")) CmdDELT(s);
else if (CMD("HELP")) CmdHelp(s); else if (CMD("GRAB")) CmdGRAB(s);
else if (CMD("LSTC")) CmdLstc(s); else if (CMD("HELP")) CmdHELP(s);
else if (CMD("LSTT")) CmdLstt(s); else if (CMD("HITK")) CmdHITK(s);
else if (CMD("MODC")) CmdModc(s); else if (CMD("LSTC")) CmdLSTC(s);
else if (CMD("MODT")) CmdModt(s); else if (CMD("LSTT")) CmdLSTT(s);
else if (CMD("MOVC")) CmdMovc(s); else if (CMD("MODC")) CmdMODC(s);
else if (CMD("MOVT")) CmdMovt(s); else if (CMD("MODT")) CmdMODT(s);
else if (CMD("NEWC")) CmdNewc(s); else if (CMD("MOVC")) CmdMOVC(s);
else if (CMD("NEWT")) CmdNewt(s); else if (CMD("MOVT")) CmdMOVT(s);
else if (CMD("UPDT")) CmdUpdt(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") else if (CMD("QUIT")
|| CMD("\x04")) Close(); || CMD("\x04")) Close();
else Reply(500, "Command unrecognized: \"%s\"", Cmd); else Reply(500, "Command unrecognized: \"%s\"", Cmd);
@ -632,9 +838,9 @@ void cSVDRP::Execute(char *Cmd)
void cSVDRP::Process(void) 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]; char buffer[MAXCMDBUFFER];
if (SendGreeting) { if (SendGreeting) {
//TODO how can we get the *full* hostname? //TODO how can we get the *full* hostname?
@ -642,7 +848,7 @@ void cSVDRP::Process(void)
time_t now = time(NULL); time_t now = time(NULL);
Reply(220, "%s SVDRP VideoDiskRecorder %s; %s", buffer, VDRVERSION, ctime(&now)); 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) { if (rbytes > 0) {
//XXX overflow check??? //XXX overflow check???
// strip trailing whitespace: // strip trailing whitespace:

41
svdrp.h
View File

@ -4,12 +4,15 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __SVDRP_H
#define __SVDRP_H #define __SVDRP_H
#include "dvbapi.h"
#include "tools.h"
class cSocket { class cSocket {
private: private:
int port; int port;
@ -26,23 +29,31 @@ public:
class cSVDRP { class cSVDRP {
private: private:
cSocket socket; cSocket socket;
int filedes; cFile file;
CRect ovlClipRects[MAXCLIPRECTS];
void Close(void); void Close(void);
bool Send(const char *s, int length = -1); bool Send(const char *s, int length = -1);
void Reply(int Code, const char *fmt, ...); void Reply(int Code, const char *fmt, ...);
void CmdChan(const char *Option); void CmdCHAN(const char *Option);
void CmdDelc(const char *Option); void CmdDELC(const char *Option);
void CmdDelt(const char *Option); void CmdDELT(const char *Option);
void CmdHelp(const char *Option); void CmdGRAB(const char *Option);
void CmdLstc(const char *Option); void CmdHELP(const char *Option);
void CmdLstt(const char *Option); void CmdHITK(const char *Option);
void CmdModc(const char *Option); void CmdLSTC(const char *Option);
void CmdModt(const char *Option); void CmdLSTT(const char *Option);
void CmdMovc(const char *Option); void CmdMODC(const char *Option);
void CmdMovt(const char *Option); void CmdMODT(const char *Option);
void CmdNewc(const char *Option); void CmdMOVC(const char *Option);
void CmdNewt(const char *Option); void CmdMOVT(const char *Option);
void CmdUpdt(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); void Execute(char *Cmd);
public: public:
cSVDRP(int Port); cSVDRP(int Port);

View File

@ -1,12 +1,14 @@
1:15:M------:2128:2205:99:7:Neues: 1:15:M------:2128:2205:99:7:Neues:
1:3:-T-----:2013:2125:99:99:SevenDays 1:3:-T-----:2013:2125:99:99:SevenDays:
1:10:-T-----:2058:2202:99:10:Quarks: 0:10:-T-----:2058:2202:99:10:Quarks:
1:26:-T-----:2255:0005:99:99:UFO: 1:26:-T-----:2255:0015:99:99:UFO:
0:3:---T---:2211:2300:99:10:Switch: 1:3:---T---:2215:2315:99:10:IngoAppelt:
1:2:----F--:2140:2225:10:10:WWW: 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:11:-----S-:2158:2235:99:99:Computer:
1:2:-----S-:2213:2320:99:30:Wochenshow: 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:15:MTWTF--:1828:1901:10:5:nano:
1:1:-TWTF--:0955:1040:99:99:Ellen: 1:1:-TWTF--:0955:1040:99:99:Ellen:
1:1:MTWTF--:1553:1710:99:99:Hammerman: 1:1:MTWTF--:1553:1710:99:99:Hammerman:

157
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #define _GNU_SOURCE
@ -12,31 +12,20 @@
#include <ctype.h> #include <ctype.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#if defined(DEBUG_OSD)
#include <ncurses.h>
#endif
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#define MaxBuffer 1000 #define MaxBuffer 1000
int SysLogLevel = 3; 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) void writechar(int filedes, char c)
{ {
write(filedes, &c, sizeof(c)); write(filedes, &c, sizeof(c));
@ -56,32 +45,12 @@ char readchar(int filedes)
bool readint(int filedes, int &n) bool readint(int filedes, int &n)
{ {
return DataAvailable(filedes) && read(filedes, &n, sizeof(n)) == sizeof(n); return cFile::AnyFileReady(filedes, 0) && 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;
} }
void purge(int filedes) void purge(int filedes)
{ {
while (DataAvailable(filedes)) while (cFile::AnyFileReady(filedes, 0))
readchar(filedes); readchar(filedes);
} }
@ -153,6 +122,14 @@ bool isnumber(const char *s)
return true; 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" #define DFCMD "df -m %s"
uint FreeDiskSpaceMB(const char *Directory) 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::cListObject(void) cListObject::cListObject(void)

26
tools.h
View File

@ -4,16 +4,17 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TOOLS_H
#define __TOOLS_H #define __TOOLS_H
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <syslog.h> #include <syslog.h>
#include <sys/wait.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
extern int SysLogLevel; extern int SysLogLevel;
@ -30,12 +31,10 @@ extern int SysLogLevel;
#define DELETENULL(p) (delete (p), p = NULL) #define DELETENULL(p) (delete (p), p = NULL)
bool DataAvailable(int filedes, bool wait = false);
void writechar(int filedes, char c); void writechar(int filedes, char c);
void writeint(int filedes, int n); void writeint(int filedes, int n);
char readchar(int filedes); char readchar(int filedes);
bool readint(int filedes, int &n); bool readint(int filedes, int &n);
int readstring(int filedes, char *buffer, int size, bool wait = false);
void purge(int filedes); void purge(int filedes);
char *readline(FILE *f); char *readline(FILE *f);
char *strn0cpy(char *dest, const char *src, size_t n); char *strn0cpy(char *dest, const char *src, size_t n);
@ -44,6 +43,7 @@ char *skipspace(char *s);
int time_ms(void); int time_ms(void);
void delay_ms(int ms); void delay_ms(int ms);
bool isnumber(const char *s); bool isnumber(const char *s);
const char *AddDirectory(const char *DirName, const char *FileName);
uint FreeDiskSpaceMB(const char *Directory); uint FreeDiskSpaceMB(const char *Directory);
bool DirectoryOk(const char *DirName, bool LogErrors = false); bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = 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); bool CheckProcess(pid_t pid);
void KillProcess(pid_t pid, int Timeout = MAXPROCESSTIMEOUT); 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 { class cListObject {
private: private:
cListObject *prev, *next; cListObject *prev, *next;

44
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * 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> #include <getopt.h>
@ -34,7 +34,6 @@
#include "interface.h" #include "interface.h"
#include "menu.h" #include "menu.h"
#include "recording.h" #include "recording.h"
#include "svdrp.h"
#include "tools.h" #include "tools.h"
#include "videodir.h" #include "videodir.h"
@ -46,9 +45,11 @@
static int Interrupted = 0; 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[]) int main(int argc, char *argv[])
@ -58,9 +59,11 @@ int main(int argc, char *argv[])
#define DEFAULTSVDRPPORT 2001 #define DEFAULTSVDRPPORT 2001
int SVDRPport = DEFAULTSVDRPPORT; int SVDRPport = DEFAULTSVDRPPORT;
const char *ConfigDirectory = NULL;
bool DaemonMode = false; bool DaemonMode = false;
static struct option long_options[] = { static struct option long_options[] = {
{ "config", required_argument, NULL, 'c' },
{ "daemon", no_argument, NULL, 'd' }, { "daemon", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "log", required_argument, NULL, 'l' }, { "log", required_argument, NULL, 'l' },
@ -71,10 +74,14 @@ int main(int argc, char *argv[])
int c; int c;
int option_index = 0; 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) { switch (c) {
case 'c': ConfigDirectory = optarg;
break;
case 'd': DaemonMode = true; 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" " -h, --help display this help and exit\n"
" -d, --daemon run in daemon mode\n" " -d, --daemon run in daemon mode\n"
" -l LEVEL, --log=LEVEL set log level (default: 3)\n" " -l LEVEL, --log=LEVEL set log level (default: 3)\n"
@ -108,6 +115,8 @@ int main(int argc, char *argv[])
} }
break; break;
case 'v': VideoDirectory = optarg; case 'v': VideoDirectory = optarg;
while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
optarg[strlen(optarg) - 1] = 0;
break; break;
default: abort(); default: abort();
} }
@ -128,7 +137,7 @@ int main(int argc, char *argv[])
// Daemon mode: // Daemon mode:
if (DaemonMode) { if (DaemonMode) {
#ifndef DEBUG_OSD #if !defined(DEBUG_OSD) && !defined(REMOTE_KBD)
pid_t pid = fork(); pid_t pid = fork();
if (pid < 0) { if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno)); fprintf(stderr, "%s\n", strerror(errno));
@ -141,7 +150,7 @@ int main(int argc, char *argv[])
fclose(stdout); fclose(stdout);
fclose(stderr); fclose(stderr);
#else #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(); abort();
#endif #endif
} }
@ -154,16 +163,19 @@ int main(int argc, char *argv[])
// Configuration data: // Configuration data:
Setup.Load("setup.conf"); if (!ConfigDirectory)
Channels.Load("channels.conf"); ConfigDirectory = VideoDirectory;
Timers.Load("timers.conf");
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"));
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
#ifdef REMOTE_LIRC #ifdef REMOTE_LIRC
Keys.SetDummyValues(); Keys.SetDummyValues();
#else #else
if (!Keys.Load(KEYS_CONF)) if (!Keys.Load(AddDirectory(ConfigDirectory, KEYS_CONF)))
Interface.LearnKeys(); Interface.LearnKeys();
#endif #endif
Interface.Init(); Interface.Init(SVDRPport);
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB); 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(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN); if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, 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: // Main program loop:
cSVDRP *SVDRP = SVDRPport ? new cSVDRP(SVDRPport) : NULL;
cOsdBase *Menu = NULL; cOsdBase *Menu = NULL;
cReplayControl *ReplayControl = NULL; cReplayControl *ReplayControl = NULL;
int LastChannel = -1; int LastChannel = -1;
@ -267,13 +279,11 @@ int main(int argc, char *argv[])
default: break; default: break;
} }
} }
if (SVDRP)
SVDRP->Process();//TODO lock menu vs. SVDRP?
} }
isyslog(LOG_INFO, "caught signal %d", Interrupted); isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu; delete Menu;
delete ReplayControl; delete ReplayControl;
delete SVDRP; Interface.Cleanup();
cDvbApi::Cleanup(); cDvbApi::Cleanup();
isyslog(LOG_INFO, "exiting"); isyslog(LOG_INFO, "exiting");
if (SysLogLevel > 0) if (SysLogLevel > 0)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #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) if (ActualFileName != FileName)
delete ActualFileName; delete ActualFileName;
return Result; return Result;