Version 0.70

- VDR now requires driver version 0.8.1 or higher.
- Recordings are now saved in PES mode. Note that you now need to install the
  driver *WITHOUT* 'outstream=0'! This is the default when you 'make insmod' in
  the DVB/driver directory.
  Old recordings (in AV_PES mode) can still be replayed (as long as the driver
  still supports replaying AV_PES files). The only limitation with this is that
  in fast forward/back mode the picture may be slightly distorted and there may
  be sound fragments.
- The EPG data is now dumped into the file /video/epg.data every ten minutes.
  Use the Perl script 'epg2html.pl' to convert the raw EPG data into a simple
  HTML programme listing.
- Fixed handling of channel switching with the "Blue" button in the "What's on
  now/next?" menus.
- Fixed saving the MarginStop setup parameter.
- Fixed missing initialization in cConfig.
- Implemented "On Disk Editing".
- There is no more default 'timers.conf' file.
- Added Italian language texts (thanks to Alberto Carraro).
- Fixed starting a replay session when the program is currently in "transfer
  mode".
- Fixed setting/modifying timers via SVDRP with empty summary fields.
- Fixed a problem with recordings that have a single quote character in their
  name (this is now mapped to 0x01).
- Changed the value for Diseqc to '0' in the default 'channels.conf'.
- Fixed displaying channels and recording status in the RCU's LED display when
  a recording is interrupted due to higher priority.
- Implemented safe writing of config files (first writes into a temporary file
  and then renames it).
- In case the video data stream is broken the log message will come only every
  5 seconds.
- The current channel is now saved in the 'setup.conf' file when VDR is cancelled,
  and will be restored next time it is started (thanks to Deti Fliegl).
- The EIT scanning thread is now locked when switching channels to avoid problems.
- Encrypted channels can now be selected even without knowing the PNR (however, it
  is still necessary for the EPG info).
This commit is contained in:
Klaus Schmidinger 2001-01-18 18:00:00 +01:00
parent 9aa2cda494
commit 3fe3c15d5d
37 changed files with 2056 additions and 1173 deletions

View File

@ -43,3 +43,9 @@ Matthias Schniedermeyer <ms@citd.de>
Miha Setina <mihasetina@softhome.net>
for translating the OSD texts to the Slovenian language.
Alberto Carraro <bertocar@tin.it>
for translating the OSD texts to the Italian language.
Deti Fliegl <deti@fliegl.de>
for implementing the 'CurrentChannel' setup parameter.

23
FORMATS
View File

@ -90,3 +90,26 @@ Video Disk Recorder File Formats
CPU status : /usr/loval/bin/cpustatus 2>&1
Disk space : df -h | grep '/video' | awk '{ print 100 - $5 "% free"; }'
* marks.vdr
This file (if present in a recording directory) contains the editing marks
defined for this recording.
Each line contains the definition of one mark in the following format:
hh:mm:ss.ff comment
where 'hh:mm:ss.ff' is a frame position within the recording, given as "hours,
minutes, seconds and (optional) frame number". 'comment' can be any string
and may be used to describe this mark. If present, 'comment' must be separated
from the frame position by at least one blank.
The lines in this file need not necessarily appear in the correct temporal
sequence, they will be automatically sorted by time index.
CURRENT RESTRICTIONS:
- the 'comment' is currently not used by VDR
- marks must have a frame number, and that frame MUST be an I-frame (this
means that only marks generated by VDR itself can be used, since they
will always be guaranteed to mark I-frames).

38
HISTORY
View File

@ -311,3 +311,41 @@ Video Disk Recorder Revision History
can receive a certain channel on the primary interface. This is currently in
an early state and may still cause some problems, but it appears to work nice
already.
2001-01-18: Version 0.70
- VDR now requires driver version 0.8.1 or higher.
- Recordings are now saved in PES mode. Note that you now need to install the
driver *WITHOUT* 'outstream=0'! This is the default when you 'make insmod' in
the DVB/driver directory.
Old recordings (in AV_PES mode) can still be replayed (as long as the driver
still supports replaying AV_PES files). The only limitation with this is that
in fast forward/back mode the picture may be slightly distorted and there may
be sound fragments.
- The EPG data is now dumped into the file /video/epg.data every ten minutes.
Use the Perl script 'epg2html.pl' to convert the raw EPG data into a simple
HTML programme listing.
- Fixed handling of channel switching with the "Blue" button in the "What's on
now/next?" menus.
- Fixed saving the MarginStop setup parameter.
- Fixed missing initialization in cConfig.
- Implemented "On Disk Editing".
- There is no more default 'timers.conf' file.
- Added Italian language texts (thanks to Alberto Carraro).
- Fixed starting a replay session when the program is currently in "transfer
mode".
- Fixed setting/modifying timers via SVDRP with empty summary fields.
- Fixed a problem with recordings that have a single quote character in their
name (this is now mapped to 0x01).
- Changed the value for Diseqc to '0' in the default 'channels.conf'.
- Fixed displaying channels and recording status in the RCU's LED display when
a recording is interrupted due to higher priority.
- Implemented safe writing of config files (first writes into a temporary file
and then renames it).
- In case the video data stream is broken the log message will come only every
5 seconds.
- The current channel is now saved in the 'setup.conf' file when VDR is cancelled,
and will be restored next time it is started (thanks to Deti Fliegl).
- The EIT scanning thread is now locked when switching channels to avoid problems.
- Encrypted channels can now be selected even without knowing the PNR (however, it
is still necessary for the EPG info).

17
INSTALL
View File

@ -15,13 +15,11 @@ If you have the DVB driver source in a different location
you will have to change the definition of DVBDIR in the
Makefile.
This program requires the card driver version 0.71 or higher
to work properly. Currently 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 necessary because 'vdr' works
with AV_PES data and will change once it has been modified to work
directly with MPEG2. You also need to apply the patch 'dvb.c.071.diff'
for the On Screen Display to work properly.
This program requires the card driver version 0.8.1 or higher
to work properly. You need to load the dvb.o module *without* option
'outstream=0' (previous versions of VDR required this option to have
the driver supply the data in AV_PES format; as of version 0.70 VDR
works with PES format).
After extracting the package, change into the VDR directory
and type 'make'. This should produce an executable file
@ -39,7 +37,7 @@ following values 'make' call to activate the respective control mode:
REMOTE=RCU control via the "Remote Control Unit" receiver
(see http://www.cadsoft.de/people/kls/vdr/remote.htm)
REMOTE=LIRC control via the "Linux Infrared Remote Control"
(see http://fsinfo.cs.uni-sb.de/~columbus/lirc)
(see http://www.lirc.org)
Adding "DEBUG_OSD=1" will use the PC screen (or current window)
to display texts instead of the DVB card's on-screen display
@ -168,6 +166,5 @@ into learning mode.
If the program has been compiled with 'REMOTE=LIRC', no 'keys.conf' file
will be used. Instead, the key names as listed in the source file 'config.c'
must be used when setting up LIRC. See http://www2.arnes.si/~mthale1 for
more about LIRC.
must be used when setting up LIRC. See http://www.lirc.org for more about LIRC.

46
MANUAL
View File

@ -174,6 +174,52 @@ Video Disk Recorder User's Manual
used to easily delete a recording after watching it, or to switch
to a different recording.
* Editing a Recording
While in Replay mode, the following keys can be used to manipulate editing
marks:
- 0 Toggles an editing mark. If the mark indicator shows a red triangle,
the current mark is deleted. Otherwise a new mark is set at the
current position.
- 4, 6 Move an editing mark back and forward. You need to first jump to
an editing mark for this to work.
- 7, 9 Jump back and forward between editing marks. Replay goes into still
mode after jumping to a mark.
- 8 Positions replay at a point 3 seconds before the current or next
"start" mark and starts replay.
- 2 Start the actual cutting process.
Editing marks are represented by black, vertical lines in the progress display.
A small black triangle at the top of the mark means that this is a "start"
mark, and a triangle at the bottom means that this is an "end" mark.
The cutting process will save all video data between "start" and "end" marks
into a new file (the original recording remains untouched). The new file will
have the same name as the original recording, preceeded with a '%' character
(imagine the '%' somehow looking like a pair of scissors ;-). Red bars in the
progress display indicate which video sequences will be saved by the cutting
process.
The video sequences to be saved by the cutting process are determined by an
"even/odd" algorithm. This means that every odd numbered editing mark (i.e.
1, 3, 5,...) represents a "start" mark, while every even numbered mark (2, 4,
6,...) is an "end" mark. Inserting or toggling a mark on or off automatically
adjusts the sequence to the right side of that mark.
Use the keys described under "Replay Control" to position to, e.g., the
beginning and end of commercial breaks and press the '0' key to set the
necessary editing marks. After that you may want to use the '7' and '9'
keys to jump to each mark and maybe use the '4' and '6' keys to fine tune
them. Once all marks are in place, press '2' to start the actual cutting
process, which will run as a background process. When replaying the edited
version of the recording you can use the '8' key to jump to a point just
before the next cut and have a look at the resulting sequence.
Currently editing marks can only be set at I-frames, which typically is
every 12th frame. So editing can be done with a resolution of roughly half
a second. A "start" mark marks the first frame of a resulting video
sequence, and an "end" mark marks the last frame of that sequence.
* Programming the Timer
Use the "Timer" menu to maintain your list of timer controlled recordings.

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 1.16 2000/11/18 14:58:10 kls Exp $
# $Id: Makefile 1.18 2001/01/13 12:26:43 kls Exp $
DVBDIR = ../DVB
@ -37,9 +37,9 @@ font: genfontfile fontfix.c fontosd.c
# Dependencies:
config.o : config.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h videodir.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
eit.o : eit.c eit.h thread.h tools.h
eit.o : eit.c config.h dvbapi.h dvbosd.h eit.h font.h thread.h tools.h videodir.h
font.o : font.c font.h fontfix.c fontosd.c tools.h
i18n.o : i18n.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h thread.h tools.h
interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h remote.h svdrp.h thread.h tools.h
@ -48,7 +48,7 @@ osd.o : osd.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h os
recording.o: recording.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
remote.o : remote.c config.h dvbapi.h dvbosd.h eit.h font.h remote.h thread.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
thread.o : thread.c thread.h
thread.o : thread.c thread.h tools.h
tools.o : tools.c tools.h
vdr.o : vdr.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h menu.h osd.h recording.h remote.h svdrp.h thread.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h

2
README
View File

@ -27,7 +27,7 @@ driver software (of course, the hardware still has to be bought).
The on screen menu system is simple, but shall provide all the
possibilites necessary to perform timer controlled recording,
file management and, maybe, even "on disk editing". The menus
file management and even "on disk editing". The menus
of commercial set-top-boxes usually are a lot more fancy than
the ones in this system, but here we have the full source code
and can modify the menus in whatever way desired.

3
TODO
View File

@ -3,8 +3,5 @@ TODO list for the Video Disk Recorder project
* Implement simultaneous record/replay with a single DVB card once
the card driver/firmware allows this.
* Implement "on-disk editing" to allow "cutting out" of certain
scenes in order to archive them (or, reversely, cut out
commercial breaks).
* Implement channel scanning.
* Implement remaining commands in SVDRP.

View File

@ -1,147 +1,148 @@
RTL:12188:h:1:27500:163:104:0:12003
Sat.1:12480:v:1:27500:1791:1792:0:46
Pro-7:12480:v:1:27500:255:256:0:898
RTL2:12188:h:1:27500:166:128:0:12020
ARD:11837:h:1:27500:101:102:0:28106
BR3:11837:h:1:27500:201:202:0:28107
Hessen-3:11837:h:1:27500:301:302:0:28108
N3:12110:h:1:27500:2401:2402:0:28224
SR3:11837:h:1:27500:501:502:0:28110
WDR:11837:h:1:27500:601:602:0:28111
BR-alpha:11837:h:1:27500:701:702:0:28112
SWR BW:11837:h:1:27500:801:802:0:28113
Phoenix:11837:h:1:27500:901:902:0:28114
ZDF:11954:h:1:27500:110:120:0:28006
3sat:11954:h:1:27500:210:220:0:28007
KiKa:11954:h:1:27500:310:320:0:28008
arte:11836:h:1:27500:401:402:0:28109
ORF Sat:11954:h:1:27500:506:507:0:28010
ZDF.info:11954:h:1:27500:610:620:0:28011
CNN:12168:v:1:27500:165:100:0:28512
Super RTL:12188:h:1:27500:165:120:0:12040
VOX:12188:h:1:27500:167:136:0:12060
DW TV:12363:v:1:27500:305:306:0:8905
Kabel 1:12480:v:1:27500:511:512:0:899
tm3:12480:v:1:27500:767:768:0:897
DSF:12480:v:1:27500:1023:1024:0:900
HOT:12480:v:1:27500:1279:1280:0:40
Bloomberg TV Germany:12551:v:1:22000:162:99:0:12160
BLOOMBERG TV:11817:v:1:27500:163:92:0:8004
Bloomberg:12168:v:1:27500:167:112:0:12721
Sky News:12552:v:1:22000:305:306:0:3995
KinderNet:12574:h:1:22000:163:92:0:5020
Alice:12610:v:1:22000:162:96:0:12200
n-tv:12669:v:1:22000:162:96:0:12730
Grand Tourisme:12670:v:1:22000:289:290:0:17300
TW1:12692:h:1:22000:166:167:0:13013
Eurosport:11954:h:1:27500:410:420:0:28009
EinsExtra:12110:H:1:27500:101:102:0:28201
EinsFestival:12110:H:1:27500:201:202:0:28202
EinsMuXx:12110:H:1:27500:301:302:0:28203
ZDF Theaterkanal:11954:H:1:27500:1110:1120:0:28016
ZDF.doku:11954:H:1:27500:660:670:0:28014
MDR:12110:h:1:27500:401:402:0:28204
NICK-PARAMOUNT:12246:v:1:27500:167:108:0:29312
ORB:12110:h:1:27500:501:502:0:28205
B1:12110:h:1:27500:601:602:0:28206
ARD Online-Kanal:12722:h:1:22000:8191:701:0:0
RTL:12188:h:0:27500:163:104:0:12003
Sat.1:12480:v:0:27500:1791:1792:0:46
Pro-7:12480:v:0:27500:255:256:0:898
RTL2:12188:h:0:27500:166:128:0:12020
ARD:11837:h:0:27500:101:102:0:28106
BR3:11837:h:0:27500:201:202:0:28107
Hessen-3:11837:h:0:27500:301:302:0:28108
N3:12110:h:0:27500:2401:2402:0:28224
SR3:11837:h:0:27500:501:502:0:28110
WDR:11837:h:0:27500:601:602:0:28111
BR-alpha:11837:h:0:27500:701:702:0:28112
SWR BW:11837:h:0:27500:801:802:0:28113
Phoenix:11837:h:0:27500:901:902:0:28114
ZDF:11954:h:0:27500:110:120:0:28006
3sat:11954:h:0:27500:210:220:0:28007
KiKa:11954:h:0:27500:310:320:0:28008
arte:11836:h:0:27500:401:402:0:28109
ORF Sat:11954:h:0:27500:506:507:0:28010
ZDF.info:11954:h:0:27500:610:620:0:28011
CNN:12168:v:0:27500:165:100:0:28512
Super RTL:12188:h:0:27500:165:120:0:12040
VOX:12188:h:0:27500:167:136:0:12060
DW TV:12363:v:0:27500:305:306:0:8905
Kabel 1:12480:v:0:27500:511:512:0:899
tm3:12480:v:0:27500:767:768:0:897
DSF:12480:v:0:27500:1023:1024:0:900
HOT:12480:v:0:27500:1279:1280:0:40
Bloomberg TV Germany:12551:v:0:22000:162:99:0:12160
BLOOMBERG TV:11817:v:0:27500:163:92:0:8004
Bloomberg:12168:v:0:27500:167:112:0:12721
Sky News:12552:v:0:22000:305:306:0:3995
KinderNet:12574:h:0:22000:163:92:0:5020
Alice:12610:v:0:22000:162:96:0:12200
n-tv:12669:v:0:22000:162:96:0:12730
Grand Tourisme:12670:v:0:22000:289:290:0:17300
TW1:12692:h:0:22000:166:167:0:13013
Eurosport:11954:h:0:27500:410:420:0:28009
EinsExtra:12110:h:0:27500:101:102:0:28201
EinsFestival:12110:h:0:27500:201:202:0:28202
EinsMuXx:12110:h:0:27500:301:302:0:28203
ZDF Theaterkanal:11954:h:0:27500:1110:1120:0:28016
ZDF.doku:11954:h:0:27500:660:670:0:28014
MDR:12110:h:0:27500:401:402:0:28204
NICK-PARAMOUNT:12246:v:0:27500:167:108:0:29312
ORB:12110:h:0:27500:501:502:0:28205
B1:12110:h:0:27500:601:602:0:28206
ARD Online-Kanal:12722:h:0:22000:8191:701:0:0
:Premiere World
Premiere World Promo:11798:h:1:27500:255:256:0:8
Premiere:11798:h:1:27500:511:512:2:10
Star Kino:11798:h:1:27500:767:768:2:9
Cine Action:11798:h:1:27500:1023:1024:2:20
Cine Comedy:11798:h:1:27500:1279:1280:2:29
Sci Fantasy:11798:h:1:27500:1535:1536:2:41
Romantic Movies:11798:h:1:27500:1791:1792:2:11
Studio Universal:11798:h:1:27500:2047:2048:2:21
13th Street:11797:h:1:27500:2303:2304:2:43
Junior:12031:h:1:27500:255:256:2:19
K-Toon:12032:h:1:27500:511:512:2:12
Disney Channel:12031:h:1:27500:767:768:2:15
Fox Kids:11798:h:1:27500:255:256:2:0
Sunset:12031:h:1:27500:1023:1024:2:16
Comedy:12031:h:1:27500:1279:1280:2:28
Planet:12031:h:1:27500:2047:2048:2:13
Discovery Channel:12031:h:1:27500:1791:1792:2:14
Krimi&Co:12031:h:1:27500:1535:1536:2:23
Filmpalast:12090:v:1:27500:255:256:2:36
Heimatkanal:11758:h:1:27500:2815:2816:2:517
Goldstar:11758:h:1:27500:3839:3840:2:518
Classica:12090:v:1:27500:767:768:2:34
Seasons:12090:v:1:27500:511:512:2:33
Blue Channel:11758:h:1:27500:2559:2560:2:516
Feed (F1 Boxengasse):11720:h:1:27500:2559:2560:2:242
Feed (F1 Data):11720:h:1:27500:3071:3072:2:244
Feed (F1 Multi):11720:h:1:27500:2815:2816:2:243
Feed (F1 On Board):11720:h:1:27500:2303:2304:2:241
Feed (F1 Verfolger):11720:h:1:27500:2047:2048:2:240
Premiere World Promo:11798:h:0:27500:255:256:0:8
Premiere:11798:h:0:27500:511:512:2:10
Star Kino:11798:h:0:27500:767:768:2:9
Cine Action:11798:h:0:27500:1023:1024:2:20
Cine Comedy:11798:h:0:27500:1279:1280:2:29
Sci Fantasy:11798:h:0:27500:1535:1536:2:41
Romantic Movies:11798:h:0:27500:1791:1792:2:11
Studio Universal:11798:h:0:27500:2047:2048:2:21
13th Street:11797:h:0:27500:2303:2304:2:43
Junior:12031:h:0:27500:255:256:2:19
K-Toon:12032:h:0:27500:511:512:2:12
Disney Channel:12031:h:0:27500:767:768:2:15
Fox Kids:11798:h:0:27500:255:256:2:0
Sunset:12031:h:0:27500:1023:1024:2:16
Comedy:12031:h:0:27500:1279:1280:2:28
Planet:12031:h:0:27500:2047:2048:2:13
Discovery Channel:12031:h:0:27500:1791:1792:2:14
Krimi&Co:12031:h:0:27500:1535:1536:2:23
Filmpalast:12090:v:0:27500:255:256:2:36
Heimatkanal:11758:h:0:27500:2815:2816:2:517
Goldstar:11758:h:0:27500:3839:3840:2:518
Classica:12090:v:0:27500:767:768:2:34
Seasons:12090:v:0:27500:511:512:2:33
Blue Channel:11758:h:0:27500:2559:2560:2:516
Feed (F1 Boxengasse):11720:h:0:27500:2559:2560:2:242
Feed (F1 Data):11720:h:0:27500:3071:3072:2:244
Feed (F1 Multi):11720:h:0:27500:2815:2816:2:243
Feed (F1 On Board):11720:h:0:27500:2303:2304:2:241
Feed (F1 Verfolger):11720:h:0:27500:2047:2048:2:240
:
TV Niepokalanow:11876:h:1:27500:305:321:0:20601
Mosaico:11934:v:1:27500:165:100:0:29010
Andalucia TV:11934:v:1:27500:166:104:0:29011
TVC Internacional:11934:v:1:27500:167:108:0:0
Nasza TV:11992:h:1:27500:165:98:0:0
WishLine test:12012:v:1:27500:163:90:0:0
Pro 7 Austria:12051:v:1:27500:161:84:0:0
Kabel 1 Schweiz:12051:v:1:27500:162:163:0:0
Kabel 1 Austria:12051:v:1:27500:166:167:0:0
Pro 7 Schweiz:12051:v:1:27500:289:290:0:0
Kiosque:12129:v:1:27500:160:80:0:0
KTO:12129:v:1:27500:170:120:0:0
TCM:12168:v:1:27500:160:80:0:0
Cartoon Network France & Spain:12168:v:1:27500:161:84:0:0
TVBS Europe:12168:v:1:27500:162:88:0:0
TVBS Europe:12168:v:1:27500:162:89:0:0
Travel:12168:v:1:27500:163:92:0:0
TCM Espania:12168:v:1:27500:164:96:0:0
MTV Spain:12168:v:1:27500:167:112:0:0
TCM France:12168:v:1:27500:169:64:0:0
RTL2 CH:12188:h:1:27500:164:112:0:0
La Cinquieme:12207:v:1:27500:160:80:0:0
ARTE:12207:v:1:27500:165:100:0:0
Post Filial TV:12226:h:1:27500:255:256:0:0
Canal Canaris:12246:v:1:27500:160:80:0:0
Canal Canaris:12246:v:1:27500:160:81:0:0
Canal Canaris:12246:v:1:27500:160:82:0:0
Canal Canaris:12246:v:1:27500:160:83:0:0
AB Sat Passion promo:12266:h:1:27500:160:80:0:0
AB Channel 1:12266:h:1:27500:161:84:0:0
Taquilla 0:12285:v:1:27500:165:100:0:0
CSAT:12324:v:1:27500:160:80:0:0
Mosaique:12324:v:1:27500:162:88:0:0
Mosaique 2:12324:v:1:27500:163:92:0:0
Mosaique 3:12324:v:1:27500:164:96:0:0
Le Sesame C+:12324:v:1:27500:165:1965:0:0
FEED:12344:h:1:27500:163:92:0:0
RTM 1:12363:v:1:27500:162:96:0:0
ESC 1:12363:v:1:27500:163:104:0:0
TV5 Europe:12363:v:1:27500:164:112:0:0
TV7 Tunisia:12363:v:1:27500:166:128:0:0
ARTE:12363:v:1:27500:167:137:0:0
RAI Uno:12363:v:1:27500:289:290:0:8904
RTP International:12363:v:1:27500:300:301:0:0
Fashion TV:12402:v:1:27500:163:92:0:0
VideoService:12422:h:1:27500:255:256:0:0
Beta Research promo:12422:h:1:27500:1023:1024:0:0
Canal Canarias:12441:v:1:27500:160:80:0:0
TVC International:12441:v:1:27500:512:660:0:0
Fitur:12441:v:1:27500:514:662:0:0
Astra Info 1:12552:v:1:22000:164:112:0:0
Astra Info 2:12552:v:1:22000:165:120:0:0
Astra Vision 1:12552:v:1:22000:168:144:0:0
Astra Vision 1:12552:v:1:22000:168:145:0:0
Astra Vision 1:12552:v:1:22000:168:146:0:0
Astra Vision 1:12552:v:1:22000:168:147:0:0
Astra Vision 1:12552:v:1:22000:168:148:0:0
Astra Vision 1:12552:v:1:22000:168:149:0:0
Astra Vision 1:12552:v:1:22000:168:150:0:0
RTL Tele Letzebuerg:12552:v:1:22000:168:144:0:0
Astra Mosaic:12552:v:1:22000:175:176:0:0
MHP test:12604:h:1:22000:5632:8191:0:0
VERONICA:12574:h:1:22000:161:84:0:5010
VH1 Classic:12699:v:1:22000:3071:3072:0:28647
VH-1 Germany:12699:v:1:22000:3081:3082:0:28648
Via 1 - Schöner Reisen:12148:h:1:27500:511:512:0:44
Video Italia:12610:v:1:22000:121:122:0:12220
AC 3 promo:12670:v:1:22000:308:256:0:0
ORF/ZDF:12699:h:1:22000:506:507:0:13012
TV Niepokalanow:11876:h:0:27500:305:321:0:20601
Mosaico:11934:v:0:27500:165:100:0:29010
Andalucia TV:11934:v:0:27500:166:104:0:29011
TVC Internacional:11934:v:0:27500:167:108:0:0
Nasza TV:11992:h:0:27500:165:98:0:0
WishLine test:12012:v:0:27500:163:90:0:0
Pro 7 Austria:12051:v:0:27500:161:84:0:0
Kabel 1 Schweiz:12051:v:0:27500:162:163:0:0
Kabel 1 Austria:12051:v:0:27500:166:167:0:0
Pro 7 Schweiz:12051:v:0:27500:289:290:0:0
Kiosque:12129:v:0:27500:160:80:0:0
KTO:12129:v:0:27500:170:120:0:0
TCM:12168:v:0:27500:160:80:0:0
Cartoon Network France & Spain:12168:v:0:27500:161:84:0:0
TVBS Europe:12168:v:0:27500:162:88:0:0
TVBS Europe:12168:v:0:27500:162:89:0:0
Travel:12168:v:0:27500:163:92:0:0
TCM Espania:12168:v:0:27500:164:96:0:0
MTV Spain:12168:v:0:27500:167:112:0:0
TCM France:12168:v:0:27500:169:64:0:0
RTL2 CH:12188:h:0:27500:164:112:0:0
La Cinquieme:12207:v:0:27500:160:80:0:0
ARTE:12207:v:0:27500:165:100:0:0
Post Filial TV:12226:h:0:27500:255:256:0:0
Canal Canaris:12246:v:0:27500:160:80:0:0
Canal Canaris:12246:v:0:27500:160:81:0:0
Canal Canaris:12246:v:0:27500:160:82:0:0
Canal Canaris:12246:v:0:27500:160:83:0:0
AB Sat Passion promo:12266:h:0:27500:160:80:0:0
AB Channel 1:12266:h:0:27500:161:84:0:0
Taquilla 0:12285:v:0:27500:165:100:0:0
CSAT:12324:v:0:27500:160:80:0:0
Mosaique:12324:v:0:27500:162:88:0:0
Mosaique 2:12324:v:0:27500:163:92:0:0
Mosaique 3:12324:v:0:27500:164:96:0:0
Le Sesame C+:12324:v:0:27500:165:1965:0:0
FEED:12344:h:0:27500:163:92:0:0
RTM 1:12363:v:0:27500:162:96:0:0
ESC 1:12363:v:0:27500:163:104:0:0
TV5 Europe:12363:v:0:27500:164:112:0:0
TV7 Tunisia:12363:v:0:27500:166:128:0:0
ARTE:12363:v:0:27500:167:137:0:0
RAI Uno:12363:v:0:27500:289:290:0:8904
RTP International:12363:v:0:27500:300:301:0:0
Fashion TV:12402:v:0:27500:163:92:0:0
VideoService:12422:h:0:27500:255:256:0:0
Beta Research promo:12422:h:0:27500:1023:1024:0:0
Canal Canarias:12441:v:0:27500:160:80:0:0
TVC International:12441:v:0:27500:512:660:0:0
Fitur:12441:v:0:27500:514:662:0:0
Astra Info 1:12552:v:0:22000:164:112:0:0
Astra Info 2:12552:v:0:22000:165:120:0:0
Astra Vision 1:12552:v:0:22000:168:144:0:0
Astra Vision 1:12552:v:0:22000:168:145:0:0
Astra Vision 1:12552:v:0:22000:168:146:0:0
Astra Vision 1:12552:v:0:22000:168:147:0:0
Astra Vision 1:12552:v:0:22000:168:148:0:0
Astra Vision 1:12552:v:0:22000:168:149:0:0
Astra Vision 1:12552:v:0:22000:168:150:0:0
RTL Tele Letzebuerg:12552:v:0:22000:168:144:0:0
Astra Mosaic:12552:v:0:22000:175:176:0:0
MHP test:12604:h:0:22000:5632:8191:0:0
VERONICA:12574:h:0:22000:161:84:0:5010
VH1 Classic:12699:v:0:22000:3071:3072:0:28647
VH-1 Germany:12699:v:0:22000:3081:3082:0:28648
Via 1 - Schöner Reisen:12148:h:0:27500:511:512:0:44
Video Italia:12610:v:0:22000:121:122:0:12220
AC 3 promo:12670:v:0:22000:308:256:0:0
ORF/ZDF:12699:h:0:22000:506:507:0:13012
VIVA:12670:v:0:22000:309:310:0:12732

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.34 2000/11/18 13:26:36 kls Exp $
* $Id: config.c 1.39 2001/01/14 15:29:15 kls Exp $
*/
#include "config.h"
@ -119,10 +119,9 @@ bool cKeys::Load(const char *FileName)
bool cKeys::Save(void)
{
//TODO make backup copies???
bool result = true;
FILE *f = fopen(fileName, "w");
if (f) {
cSafeFile f(fileName);
if (f.Open()) {
if (fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address) > 0) {
for (tKey *k = keys; k->type != kNone; k++) {
if (fprintf(f, "%s\t%08X\n", k->name, k->code) <= 0) {
@ -133,7 +132,7 @@ bool cKeys::Save(void)
}
else
result = false;
fclose(f);
f.Close();
}
else
result = false;
@ -196,7 +195,7 @@ cChannel::cChannel(const cChannel *Channel)
strcpy(name, Channel ? Channel->name : "Pro7");
frequency = Channel ? Channel->frequency : 12480;
polarization = Channel ? Channel->polarization : 'v';
diseqc = Channel ? Channel->diseqc : 1;
diseqc = Channel ? Channel->diseqc : 0;
srate = Channel ? Channel->srate : 27500;
vpid = Channel ? Channel->vpid : 255;
apid = Channel ? Channel->apid : 256;
@ -435,9 +434,11 @@ bool cTimer::Parse(const char *s)
//XXX to hear about that!
char *s2 = NULL;
int l2 = strlen(s);
if (s[l2 - 2] == ':') { // note that 's' has a trailing '\n'
s2 = (char *)malloc(l2 + 2);
strcat(strn0cpy(s2, s, l2), " \n");
while (l2 > 0 && isspace(s[l2 - 1]))
l2--;
if (s[l2 - 1] == ':') {
s2 = (char *)malloc(l2 + 3);
strcat(strn0cpy(s2, s, l2 + 1), " \n");
s = s2;
}
if (8 <= sscanf(s, "%d:%d:%a[^:]:%d:%d:%d:%d:%a[^:\n]:%a[^\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
@ -723,6 +724,7 @@ cSetup::cSetup(void)
MarginStart = 2;
MarginStop = 10;
EPGScanTimeout = 5;
CurrentChannel = -1;
}
bool cSetup::Parse(char *s)
@ -742,6 +744,7 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
else
return false;
return true;
@ -780,8 +783,8 @@ bool cSetup::Save(const char *FileName)
if (!FileName)
FileName = fileName;
if (FileName) {
FILE *f = fopen(FileName, "w");
if (f) {
cSafeFile f(FileName);
if (f.Open()) {
fprintf(f, "# VDR Setup\n");
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
@ -792,8 +795,10 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
fprintf(f, "MarginStart = %d\n", MarginStart);
fprintf(f, "MarginStop = %d\n", MarginStop);
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fclose(f);
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
f.Close();
isyslog(LOG_INFO, "saved setup to %s", FileName);
return true;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.34 2000/11/18 13:25:53 kls Exp $
* $Id: config.h 1.38 2001/01/14 15:29:27 kls Exp $
*/
#ifndef __CONFIG_H
@ -14,11 +14,12 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "dvbapi.h"
#include "eit.h"
#include "tools.h"
#define VDRVERSION "0.68"
#define VDRVERSION "0.70"
#define MaxBuffer 10000
@ -42,6 +43,15 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
k_Flags = k_Repeat | k_Release,
};
// This is in preparation for having more key codes:
#define kMarkToggle k0
#define kMarkMoveBack k4
#define kMarkMoveForward k6
#define kMarkJumpBack k7
#define kMarkJumpForward k9
#define kEditCut k2
#define kEditTest k8
#define RAWKEY(k) ((k) & ~k_Flags)
#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
#define NORMALKEY(k) ((k) & ~k_Repeat)
@ -157,43 +167,45 @@ private:
cList<T>::Clear();
}
public:
cConfig(void) { fileName = NULL; }
virtual ~cConfig() { delete fileName; }
virtual bool Load(const char *FileName)
{
isyslog(LOG_INFO, "loading %s", FileName);
bool result = true;
Clear();
fileName = strdup(FileName);
FILE *f = fopen(fileName, "r");
if (f) {
int line = 0;
char buffer[MaxBuffer];
while (fgets(buffer, sizeof(buffer), f) > 0) {
line++;
T *l = new T;
if (l->Parse(buffer))
Add(l);
else {
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
delete l;
result = false;
break;
bool result = false;
if (access(FileName, F_OK) == 0) {
isyslog(LOG_INFO, "loading %s", FileName);
FILE *f = fopen(fileName, "r");
if (f) {
int line = 0;
char buffer[MaxBuffer];
result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) {
line++;
T *l = new T;
if (l->Parse(buffer))
Add(l);
else {
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
delete l;
result = false;
break;
}
}
}
fclose(f);
}
else {
LOG_ERROR_STR(fileName);
result = false;
fclose(f);
}
else
LOG_ERROR_STR(fileName);
}
return result;
}
bool Save(void)
{
//TODO make backup copies???
bool result = true;
T *l = (T *)First();
FILE *f = fopen(fileName, "w");
if (f) {
cSafeFile f(fileName);
if (f.Open()) {
while (l) {
if (!l->Save(f)) {
result = false;
@ -201,12 +213,10 @@ public:
}
l = (T *)l->Next();
}
fclose(f);
f.Close();
}
else {
LOG_ERROR_STR(fileName);
else
result = false;
}
return result;
}
};
@ -258,6 +268,7 @@ public:
int SetSystemTime;
int MarginStart, MarginStop;
int EPGScanTimeout;
int CurrentChannel;
cSetup(void);
bool Load(const char *FileName);
bool Save(const char *FileName = NULL);

View File

@ -1,100 +0,0 @@
--- dvb.c.001 Sun Sep 17 22:02:37 2000
+++ dvb.c Tue Oct 3 12:11:46 2000
@@ -1143,6 +1143,8 @@
{
int bpp;
int i;
+ int d, delta; //XXX kls: additional variables for data compression
+ u8 c; //XXX kls: additional variables for data compression
DECLARE_WAITQUEUE(wait, current);
if (dvb->bmp_state==BMP_LOADING) {
@@ -1160,27 +1162,38 @@
if (dvb->bmp_state==BMP_LOADING)
return -1;
dvb->bmp_state=BMP_LOADING;
- if (format==BITMAP8) bpp=8;
- else if (format==BITMAP4) bpp=4;
- else if (format==BITMAP2) bpp=2;
- else if (format==BITMAP1) bpp=1;
+ if (format==BITMAP8) { bpp=8; delta = 1; } //XXX kls: initialize 'delta', too
+ else if (format==BITMAP4) { bpp=4; delta = 2; }
+ else if (format==BITMAP2) { bpp=2; delta = 4; }
+ else if (format==BITMAP1) { bpp=1; delta = 8; }
else {
dvb->bmp_state=BMP_NONE;
return -1;
}
- dvb->bmplen= (dx*dy*bpp)/8;
+ dvb->bmplen= ((dx*dy*bpp+7)&~7)/8; //XXX kls: need to round up to include partial bytes
dvb->bmpp=0;
if (dvb->bmplen>32768) {
dvb->bmp_state=BMP_NONE;
return -1;
}
for (i=0; i<dy; i++) {
- if (copy_from_user(dvb->bmpbuf+1024+i*dx, data+i*inc, (dx*bpp)/8)) {
+ if (copy_from_user(dvb->bmpbuf+1024+i*dx, data+i*inc, dx)) { //XXX kls: incoming data is "1 byte per pixel"
dvb->bmp_state=BMP_NONE;
return -1;
}
}
+ // XXX kls: Incoming data is always "one byte per pixel", so we need to compress
+ // the data in case we have a lower resolution than 8 bpp:
+ if (format != BITMAP8) {
+ for (i=0; i<dx*dy/delta; i++) {
+ c = ((u8 *)dvb->bmpbuf)[1024+i*delta+delta-1];
+ for (d=delta-2; d>=0; d--) {
+ c |= (((u8 *)dvb->bmpbuf)[1024+i*delta+d] << ((delta-d-1)*bpp));
+ ((u8 *)dvb->bmpbuf)[1024+i] = c;
+ }
+ }
+ }
dvb->bmplen+=1024;
return outcom(dvb, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
}
@@ -1256,24 +1269,25 @@
int i;
w=x1-x0+1; h=y1-y0+1;
- if (inc>0)
- w=inc;
- if (w>720 || h>576)
+ if (inc<=0)
+ inc=w; //XXX kls: see dvb_4l.h: "inc<=0 uses blockwidth as linewidth"
+ if (w<=0 || w>720 || h<=0 || h>576) //XXX kls: checking lower bounds, too
return -1;
- bpp=8; //dvb->osdbpp[dvb->osdwin];
- bpl=w*bpp/8;
+ bpp=dvb->osdbpp[dvb->osdwin]+1; //XXX kls: 'bpp' needs to be taken from the window
+ bpl=((w*bpp+7)&~7)/8; //XXX kls: need to round up to include partial bytes
size=h*bpl;
- lpb=(64*1024)/bpl;
+ lpb=(32*1024)/bpl; //XXX kls: apparently 32K is the maximum possible value
bnum=size/(lpb*bpl);
brest=size-bnum*lpb*bpl;
for (i=0; i<bnum; i++) {
- LoadBitmap(dvb, BITMAP8, w, lpb, inc, data);
+ LoadBitmap(dvb, bpp2bit[dvb->osdbpp[dvb->osdwin]], w, lpb, inc, data); //XXX kls: need to take the format from the actual window
BlitBitmap(dvb, dvb->osdwin, x0, y0+i*lpb, 1);
- data+=bpl;
+ data+=lpb*inc; //XXX kls: incrementing must be done in "one byte per pixel"
+ ddelay(3); //XXX kls: without this the block is sometimes not fully displayed - firmware bug?
}
if (brest) {
- LoadBitmap(dvb, BITMAP8, w, brest/bpl, inc, data);
+ LoadBitmap(dvb, bpp2bit[dvb->osdbpp[dvb->osdwin]], w, brest/bpl, inc, data); //XXX kls: need to take the format from the actual window
BlitBitmap(dvb, dvb->osdwin, x0, y0+bnum*lpb, 1);
}
ReleaseBitmap(dvb);
@@ -6141,7 +6155,7 @@
init_waitqueue_head(&dvb->bmpq);
spin_lock_init (&(dvb->bmplock));
dvb->bmpp=dvb->bmplen=0;
- dvb->bmpbuf=vmalloc(32768+1024);
+ dvb->bmpbuf=vmalloc(8*32768+1024); //XXX kls: '8*' to be prepared for the maximum possible incoming data at 1 bpp
init_waitqueue_head(&dvb->debiq);
dvb->debilock=SPIN_LOCK_UNLOCKED;

1533
dvbapi.c

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.h 1.26 2000/11/19 14:09:41 kls Exp $
* $Id: dvbapi.h 1.30 2001/01/07 15:56:10 kls Exp $
*/
#ifndef __DVBAPI_H
@ -22,6 +22,7 @@ typedef unsigned char __u8;
#include <dvb.h>
#include "dvbosd.h"
#include "eit.h"
#include "thread.h"
// Overlay facilities
#define MAXCLIPRECTS 100
@ -42,7 +43,24 @@ public:
bool Save(int Index);
};
const char *IndexToHMSF(int Index, bool WithFrame = false);
// Converts the given index to a string, optionally containing the frame number.
int HMSFToIndex(const char *HMSF);
// Converts the given string (format: "hh:mm:ss.ff") to an index.
class cRecordBuffer;
class cReplayBuffer;
class cTransferBuffer;
class cCuttingBuffer;
class cVideoCutter {
private:
static cCuttingBuffer *cuttingBuffer;
public:
static bool Start(const char *FileName);
static void Stop(void);
static bool Active(void);
};
class cDvbApi {
private:
@ -129,22 +147,16 @@ public:
void Close(void);
void Clear(void);
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
void ClrEol(int x, int y, eDvbColor color = clrBackground);
int CellWidth(void);
int LineHeight(void);
int Width(unsigned char c);
int WidthInCells(const char *s);
eDvbFont SetFont(eDvbFont Font);
void Text(int x, int y, const char *s, eDvbColor colorFg = clrWhite, eDvbColor colorBg = clrBackground);
void Flush(void);
// Progress Display facilities
private:
int lastProgress, lastTotal;
char *replayTitle;
public:
bool ShowProgress(bool Initial = false);
// Channel facilities
private:
@ -171,20 +183,10 @@ private:
// Record/Replay facilities
private:
enum { dvbStop = 1, // let's not have 0 as a command
dvbPause,
dvbPlay,
dvbForward,
dvbBackward,
dvbSkip,
dvbGetIndex,
};
pid_t pidRecord, pidReplay;
int fromRecord, toRecord;
int fromReplay, toReplay;
cRecordBuffer *recordBuffer;
cReplayBuffer *replayBuffer;
int ca;
int priority;
void SetReplayMode(int Mode);
protected:
int Ca(void) { return ca; }
// Returns the ca of the current recording session (0..MAXDVBAPI).
@ -192,6 +194,8 @@ protected:
// Returns the priority of the current recording session (0..99),
// or -1 if no recording is currently active.
public:
int SecondsToFrames(int Seconds);
// Returns the number of frames corresponding to the given number of seconds.
bool Recording(void);
// Returns true if we are currently recording.
bool Replaying(void);
@ -209,12 +213,11 @@ public:
// returned.
void StopRecord(void);
// Stops the current recording session (if any).
bool StartReplay(const char *FileName, const char *Title = NULL);
bool StartReplay(const char *FileName);
// Starts replaying the given file.
// If there is already a replay session active, it will be stopped
// and the new file will be played back.
// If provided Title will be used in the progress display.
void Stop(void);
void StopReplay(void);
// Stops the current replay session (if any).
void Pause(void);
// Pauses the current replay session, or resumes a paused session.
@ -224,12 +227,21 @@ public:
// Runs the current replay session forward at a higher speed.
void Backward(void);
// Runs the current replay session backwards at a higher speed.
void Skip(int Seconds);
void SkipSeconds(int Seconds);
// Skips the given number of seconds in the current replay session.
// The sign of 'Seconds' determines the direction in which to skip.
// Use a very large negative value to go all the way back to the
// beginning of the recording.
bool GetIndex(int *Current, int *Total = NULL);
int SkipFrames(int Frames);
// Returns the new index into the current replay session after skipping
// the given number of frames (no actual repositioning is done!).
// The sign of 'Frames' determines the direction in which to skip.
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
// Returns the current and total frame index, optionally snapped to the
// nearest I-frame.
void Goto(int Index, bool Still = false);
// Positions to the given index and displays that frame as a still picture
// if Still is true.
};
class cEITScanner {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbosd.c 1.6 2000/11/18 15:36:51 kls Exp $
* $Id: dvbosd.c 1.7 2000/12/09 11:13:00 kls Exp $
*/
#include "dvbosd.h"
@ -82,6 +82,16 @@ void cBitmap::SetPixel(int x, int y, eDvbColor Color)
}
}
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
{
if (bitmap && Bitmap.bitmap) {
for (int ix = 0; ix < Bitmap.width; ix++) {
for (int iy = 0; iy < Bitmap.height; iy++)
SetPixel(x + ix, y + iy, eDvbColor(Bitmap.bitmap[Bitmap.width * iy + ix]));
}
}
}
int cBitmap::Width(unsigned char c)
{
return font ? font->Width(c) : -1;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbosd.h 1.4 2000/11/18 15:25:25 kls Exp $
* $Id: dvbosd.h 1.5 2000/12/09 10:32:47 kls Exp $
*/
#ifndef __DVBOSD_H
@ -57,6 +57,7 @@ public:
eDvbFont SetFont(eDvbFont Font);
bool Dirty(void);
void SetPixel(int x, int y, eDvbColor Color);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
int Width(unsigned char c);
int Width(const char *s);
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);

58
eit.c
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.9 2000/11/18 13:42:28 kls Exp $
* $Id: eit.c 1.11 2000/12/03 15:33:37 kls Exp $
***************************************************************************/
#include "eit.h"
@ -33,6 +33,8 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "config.h"
#include "videodir.h"
// --- cMJD ------------------------------------------------------------------
@ -129,7 +131,7 @@ bool cMJD::SetSystemTime()
isyslog(LOG_INFO, "System Time = %s (%ld)\n", ctime(&loctim), loctim);
isyslog(LOG_INFO, "Local Time = %s (%ld)\n", ctime(&mjdtime), mjdtime);
if (stime(&mjdtime) < 0)
esyslog(LOG_ERR, "ERROR while setting system time: %s", strerror(errno));
esyslog(LOG_ERR, "ERROR while setting system time: %m");
return true;
}
@ -393,6 +395,21 @@ unsigned short cEventInfo::GetServiceID() const
return uServiceID;
}
/** */
void cEventInfo::Dump(FILE *f) const
{
if (tTime + lDuration >= time(NULL)) {
fprintf(f, "E %u %ld %ld\n", uEventID, tTime, lDuration);
if (!isempty(pTitle))
fprintf(f, "T %s\n", pTitle);
if (!isempty(pSubtitle))
fprintf(f, "S %s\n", pSubtitle);
if (!isempty(pExtendedDescription))
fprintf(f, "D %s\n", pExtendedDescription);
fprintf(f, "e\n");
}
}
// --- cSchedule -------------------------------------------------------------
cSchedule::cSchedule(unsigned short servid)
@ -529,6 +546,19 @@ void cSchedule::Cleanup(time_t tTime)
}
}
/** */
void cSchedule::Dump(FILE *f) const
{
cChannel *channel = Channels.GetByServiceID(uServiceID);
if (channel)
{
fprintf(f, "C %u %s\n", uServiceID, channel->name);
for (cEventInfo *p = Events.First(); p; p = Events.Next(p))
p->Dump(f);
fprintf(f, "c\n");
}
}
// --- cSchedules ------------------------------------------------------------
cSchedules::cSchedules()
@ -590,6 +620,13 @@ void cSchedules::Cleanup()
}
}
/** */
void cSchedules::Dump(FILE *f) const
{
for (cSchedule *p = First(); p; p = Next(p))
p->Dump(f);
}
// --- cEIT ------------------------------------------------------------------
#define DEC(N) dec << setw(N) << setfill(int('0'))
@ -1080,7 +1117,7 @@ cSIProcessor::~cSIProcessor()
{
if (fsvbi >= 0)
{
Stop();
Cancel();
ShutDownFilters();
delete filters;
if (!--numSIProcessors) // the last one deletes it
@ -1105,6 +1142,7 @@ void cSIProcessor::Action()
unsigned int seclen;
unsigned int pid;
time_t lastCleanup = time(NULL);
time_t lastDump = time(NULL);
struct pollfd pfd;
while(true)
@ -1123,6 +1161,19 @@ void cSIProcessor::Action()
schedulesMutex.Unlock();
lastCleanup = now;
}
if (now - lastDump > 600)
{
LOCK_THREAD;
schedulesMutex.Lock();
FILE *f = fopen(AddDirectory(VideoDirectory, "epg.data"), "w");
if (f) {
schedules->Dump(f);
fclose(f);
}
lastDump = now;
schedulesMutex.Unlock();
}
}
/* wait data become ready from the bitfilter */
@ -1283,4 +1334,3 @@ bool cSIProcessor::RefreshFilters()
return ret;
}

5
eit.h
View File

@ -13,7 +13,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.h 1.3 2000/11/17 16:14:27 kls Exp $
* $Id: eit.h 1.4 2000/11/24 14:35:22 kls Exp $
***************************************************************************/
#ifndef __EIT_H
@ -66,6 +66,7 @@ public:
unsigned short GetServiceID(void) const;
int GetChannelNumber(void) const { return nChannelNumber; }
void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
void Dump(FILE *f) const;
};
class cSchedule : public cListObject {
@ -92,6 +93,7 @@ public:
const cEventInfo *GetEvent(time_t tTime) const;
const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
int NumEvents(void) const { return Events.Count(); }
void Dump(FILE *f) const;
};
class cSchedules : public cList<cSchedule> {
@ -107,6 +109,7 @@ public:
~cSchedules();
const cSchedule *GetSchedule(unsigned short servid) const;
const cSchedule *GetSchedule(void) const;
void Dump(FILE *f) const;
};
typedef struct sip_filter {

96
epg2html.pl Normal file
View File

@ -0,0 +1,96 @@
#!/usr/bin/perl
# A simple EPG to HTML converter
#
# Converts the EPG data written by 'vdr' into the file /video/epg.data
# into a simple HTML programme listing, consisting of one file per channel
# plus an 'index.htm' file. All output files are written into the current
# directory.
#
# Usage: epg2html.pl < /video/epg.data
#
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: epg2html.pl 1.2 2000/12/01 18:37:46 kls Exp $
@Index = ();
sub GetDay
{
return substr(localtime(shift), 0, 10);
}
sub GetTime
{
return substr(localtime(shift), 11, 5);
}
sub Tags
{
my $s = shift;
$s =~ s/\&/&amp;/g;
$s =~ s/</&lt;/g;
$s =~ s/>/&gt;/g;
return $s;
}
while (<>) {
chomp;
if (/^C ([^ ]+) *(.*)/) {
my $Channel = $2;
(my $Page = $Channel) =~ y/\/ /-_/;
$Page .= ".htm";
$Channel = Tags($Channel);
push(@Index, qq{<a href="$Page">$Channel</a><br>\n});
my %Events = ();
while (<>) {
if (/^E (.*) (.*) (.*)/) {
(my $Time, $Duration) = ($2, $3);
my $Title = "", $Subtitle = "", $Description = "";
while (<>) {
if (/^T (.*)/) { $Title = Tags($1); }
elsif (/^S (.*)/) { $Subtitle = Tags($1); }
elsif (/^D (.*)/) { $Description = Tags($1); }
elsif (/^e/) {
$Events{$Time} = [($Duration, $Title, $Subtitle, $Description)];
last;
}
}
}
elsif (/^c/) {
my @Schedule = ();
my $Day = "";
for $t (sort keys %Events) {
(my $Duration, $Title, $Subtitle, $Description) = @{$Events{$t}};
my $d = GetDay($t);
if ($d ne $Day) {
push(@Schedule, "</table>\n") if ($Day && @Schedule);
push(@Schedule, "<h2>$d</h2>\n");
push(@Schedule, "<table cellspacing=2>\n");
$Day = $d;
}
my $Entry = $Title;
$Entry .= "<br><i>$Subtitle</i>" if $Subtitle;
$Entry .= "<br>$Description" if $Description;
push(@Schedule, "<tr><td valign=top>" . GetTime($t) . "</td><td>$Entry</td></tr>\n");
}
push(@Schedule, "</table>\n") if (@Schedule);
open(PAGE, ">$Page") or die "$Page: $!\n";
print PAGE "<html>\n<head><title>$Channel</title><head>\n<body>\n";
print PAGE "<h1>$Channel</h1>\n";
print PAGE @Schedule;
print PAGE "</body>\n</html>\n";
close(PAGE);
last;
}
}
}
}
open(INDEX, ">index.htm") or die "index.htm: $!\n";
print INDEX "<html>\n<head><title>EPG Index</title><head>\n<body>\n";
print INDEX sort { lc($a) cmp lc($b) } @Index;
print INDEX "</body>\n</html>\n";
close(INDEX);

140
i18n.c
View File

@ -4,9 +4,10 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: i18n.c 1.6 2000/11/19 12:12:53 kls Exp $
* $Id: i18n.c 1.8 2001/01/06 16:17:39 kls Exp $
*
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
*
*/
@ -31,9 +32,8 @@
* "Italiano",
* },
*
* and so on. Insert your language so that all the entries
* following 'English' will be sorted alphabetically, and write
* the name of your language in your language (not in English,
* and so on. Append your language after the last existing language
* and write the name of your language in your language (not in English,
* which means that it should be 'Italiano', not 'Italian').
* Note that only the characters defined in 'fontosd.c' will
* be available!
@ -48,7 +48,7 @@
#include "config.h"
#include "tools.h"
const int NumLanguages = 3;
const int NumLanguages = 4;
typedef const char *tPhrase[NumLanguages];
@ -57,401 +57,523 @@ const tPhrase Phrases[] = {
{ "English",
"Deutsch",
"Slovenski",
"Italiano",
},
// Menu titles:
{ "Main",
"Hauptmenü",
"Glavni meni",
"Principale",
},
{ "Schedule",
"Programm",
"Urnik",
"Programmi",
},
{ "Channels",
"Kanäle",
"Kanali",
"Canali",
},
{ "Timers",
"Timer",
"Termini",
"Timer",
},
{ "Recordings",
"Aufzeichnungen",
"Posnetki",
"Registrazioni",
},
{ "Setup",
"Einstellungen",
"Nastavitve",
"Opzioni",
},
{ "Commands",
"Befehle",
"Ukazi",
"Comandi",
},
{ "Edit Channel",
"Kanal Editieren",
"Uredi kanal",
"Modifica canale",
},
{ "Edit Timer",
"Timer Editieren",
"Uredi termin",
"Modifica Timer",
},
{ "Event",
"Sendung",
"Oddaja",
"Eventi",
},
{ "Summary",
"Inhalt",
"Vsebina",
"Sommario",
},
{ "Schedule - %s",
"Programm - %s",
"Urnik - %s",
"Programma - %s",
},
{ "What's on now?",
"Was läuft jetzt?",
"Kaj je na sporedu?",
"In programmazione",
},
{ "What's on next?",
"Was läuft als nächstes?",
"Kaj sledi?",
"Prossimi programmi",
},
// Button texts (must not be more than 10 characters!):
{ "Edit",
"Editieren",
"Uredi",
"Modifica",
},
{ "New",
"Neu",
"Novo",
"Nuovo",
},
{ "Delete",
"Löschen",
"Odstrani",
"Cancella",
},
{ "Mark",
"Markieren",
"Oznaci",
"Marca",
},
{ "Record",
"Aufnehmen",
"Posnemi",
"Registra",
},
{ "Play",
"Wiedergabe",
"Predavajaj",
"Riproduci",
},
{ "Resume",
"Weiter",
"Nadaljuj",
"Riprendi",
},
{ "Summary",
"Inhalt",
"Vsebina",
"Sommario",
},
{ "Switch",
"Umschalten",
"Preklopi",
"Cambia",
},
{ "Now",
"Jetzt",
"Sedaj",
"Adesso",
},
{ "Next",
"Nächste",
"Naslednji",
"Prossimo",
},
{ "Schedule",
"Programm",
"Urnik",
"Programma",
},
// Confirmations:
{ "Delete Channel?",
{ "Delete channel?",
"Kanal löschen?",
"Odstrani kanal?",
"Cancello il canale?",
},
{ "Delete Timer?",
{ "Delete timer?",
"Timer löschen?",
"Odstani termin?",
"Cancello il timer?",
},
{ "Delete Recording?",
{ "Delete recording?",
"Aufzeichnung löschen?",
"Odstrani posnetek?",
"Cancello la registrazione?",
},
{ "Stop Recording?",
{ "Stop recording?",
"Aufzeichnung beenden?",
"Koncaj snemanje?",
"Fermo la registrazione?",
},
{ "Cancel editing?",
"Schneiden abbrechen?",
"Zelite prekiniti urejanje?",
"Annullo la modifica?",
},
// Channel parameters:
{ "Name",
"Name",
"Naziv",
"Nome",
},
{ "Frequency",
"Frequenz",
"Frekvenca",
"Frequenza",
},
{ "Polarization",
"Polarisation",
"Polarizacija",
"Polarizzazione",
},
{ "Diseqc",
"Diseqc",
"Diseqc",
"Diseqc",
},
{ "Srate",
"Srate",
"Srate",
"Srate",
},
{ "Vpid",
"Vpid",
"Vpid",
"Vpid",
},
{ "Apid",
"Apid",
"Apid",
"Apid",
},
{ "CA",
"CA",
"CA",
"CA",
},
{ "Pnr",
"Pnr",
"Pnr",
"Pnr",
},
// Timer parameters:
{ "Active",
"Aktiv",
"Aktivno",
"Attivo",
},
{ "Channel",
"Kanal",
"Kanal",
"Canale",
},
{ "Day",
"Tag",
"Dan",
"Giorno",
},
{ "Start",
"Anfang",
"Zacetek",
"Inizio",
},
{ "Stop",
"Ende",
"Konec",
"Fine",
},
{ "Priority",
"Priorität",
"Prioriteta",
"Priorita",
},
{ "Lifetime",
"Lebensdauer",
"Veljavnost",
"Durata",
},
{ "File",
"Datei",
"Datoteka",
"Nome",
},
// Error messages:
{ "Channel is being used by a timer!",
"Kanal wird von einem Timer benutzt!",
"Urnik zaseda kanal!",
"Canale occupato da un timer!",
},
{ "Can't switch channel!",
"Kanal kann nicht umgeschaltet werden!",
"Ne morem preklopiti kanala!",
"Impossibile cambiare canale!",
},
{ "Timer is recording!",
"Timer zeichnet gerade auf!",
"Snemanje po urniku!",
"Registrazione di un timer in corso!",
},
{ "Error while deleting recording!",
"Fehler beim Löschen der Aufzeichnung!",
"Napaka pri odstranjevanju posnetka!",
"Errore durante la canc del filmato!",
},
{ "*** Invalid Channel ***",
"*** Ungültiger Kanal ***",
"*** Neznan kanal ***",
"*** CANALE INVALIDO ***",
},
{ "No free DVB device to record!",
"Keine freie DVB-Karte zum Aufnehmen!",
"Ni proste DVB naprave za snemanje!",
"Nessuna card DVB disp per registrare!",
},
{ "Channel locked (recording)!",
"Kanal blockiert (zeichnet auf)!",
"Zaklenjen kanal (snemanje)!",
"Canale bloccato (in registrazione)!",
},
{ "Can't start editing process!",
"Schnitt kann nicht gestartet werden!",
"Ne morem zaceti urejanja!",
"Imposs iniziare processo di modifica",
},
{ "Editing process already active!",
"Schnitt bereits aktiv!",
"Urejanje je ze aktivno!",
"Processo di modifica gia` attivo",
},
// Setup parameters:
{ "OSD-Language",
"OSD-Sprache",
"OSD-jezik",
"Linguaggio OSD",
},
{ "PrimaryDVB",
"Primäres Interface",
"Primarna naprava",
"Scheda DVB primaria",
},
{ "ShowInfoOnChSwitch",
"Info zeigen",
"Pokazi naziv kanala",
"Vis info nel cambio canale",
},
{ "MenuScrollPage",
"Seitenweise scrollen",
"Drsni meni",
"Scrolla pagina nel menu",
},
{ "MarkInstantRecord",
"Direktaufz. markieren",
"Oznaci direktno snemanje",
"Marca la registrazione",
},
{ "LnbFrequLo",
"Untere LNB-Frequenz",
"Spodnja LNB-frek.",
"Freq LO LNB",
},
{ "LnbFrequHi",
"Obere LNB-Frequenz",
"Zgornja LNB-frek.",
"Freq HI LNB",
},
{ "SetSystemTime",
"Systemzeit stellen",
"Sistemski cas",
"Setta orario auto",
},
{ "MarginStart",
"Zeitpuffer bei Anfang",
"Premor pred zacetkom",
"Min margine inizio",
},
{ "MarginStop",
"Zeitpuffer bei Ende",
"Premor za koncem",
"Min margine fine",
},
{ "EPGScanTimeout",
"Zeit bis EPG Scan",
"Cas do EPG pregleda",
"Timeout EPG",
},
// The days of the week:
{ "MTWTFSS",
"MDMDFSS",
"PTSCPSN",
"DLMMGVS",
},
// Learning keys:
{ "Learning Remote Control Keys",
"Fernbedienungs-Codes lernen",
"Ucim se kod upravljalca",
"Apprendimento tasti unita` remota",
},
{ "Phase 1: Detecting RC code type",
"Phase 1: FB Code feststellen",
"Faza 1: Sprejemanje IR kode",
"Fase 1: tipo ricevitore RC",
},
{ "Press any key on the RC unit",
"Eine Taste auf der FB drücken",
"Pritisnite tipko na upravljalcu",
"Premere un tasto nell'unita` RC",
},
{ "RC code detected!",
"FB Code erkannt!",
"IR koda sprejeta!",
"Codice RC rilevato!",
},
{ "Do not press any key...",
"Keine Taste drücken...",
"Ne pritiskajte tipk...",
"Non premere alcun tasto...",
},
{ "Phase 2: Learning specific key codes",
"Phase 2: Einzelne Tastencodes lernen",
"Faza 2: Ucenje posebnih kod",
"Fase 2: Codici specifici dei tasti",
},
{ "Press key for '%s'",
"Taste für '%s' drücken",
"Pritisnite tipko za '%s'",
"Premere il tasto per '%s'",
},
{ "Press 'Up' to confirm",
"'Auf' drücken zum Bestätigen",
"Pritisnite tipko 'Gor' za potrditev",
"Premere 'Su' per confermare",
},
{ "Press 'Down' to continue",
"'Ab' drücken zum Weitermachen",
"Pritisnite tipko 'Dol' za nadaljevanje",
"Premere 'Giu' per confermare",
},
{ "(press 'Up' to go back)",
"('Auf' drücken um zurückzugehen)",
"(pritisnite 'Gor' za nazaj)",
"(premere 'Su' per tornare indietro)",
},
{ "(press 'Down' to end key definition)",
"('Ab' drücken zum Beenden",
"(pritisnite 'Dol' za konec)",
"('Giu' per finire la definiz tasti)",
},
{ "Phase 3: Saving key codes",
"Phase 3: Codes abspeichern",
"Faza 3: Shranjujem kodo",
"Fase 3: Salvataggio key codes",
},
{ "Press 'Up' to save, 'Down' to cancel",
"'Auf' speichert, 'Ab' bricht ab",
"'Gor' za potrditev, 'Dol' za prekinitev",
"'Su' per salvare, 'Giu' per annullare",
},
// Key names:
{ "Up",
"Auf",
"Gor",
"Su",
},
{ "Down",
"Ab",
"Dol",
"Giu",
},
{ "Menu",
"Menü",
"Meni",
"Menu",
},
{ "Ok",
"Ok",
"Ok",
"Ok",
},
{ "Back",
"Zurück",
"Nazaj",
"Indietro",
},
{ "Left",
"Links",
"Levo",
"Sinistra",
},
{ "Right",
"Rechts",
"Desno",
"Destra",
},
{ "Red",
"Rot",
"Rdeca",
"Rosso",
},
{ "Green",
"Grün",
"Zelena",
"Verde",
},
{ "Yellow",
"Gelb",
"Rumena",
"Giallo",
},
{ "Blue",
"Blau",
"Modra",
"Blu",
},
// Miscellaneous:
{ "yes",
"ja",
"da",
"si",
},
{ "no",
"nein",
"ne",
"no",
},
{ "Stop replaying",
"Wiedergabe beenden",
"Prekini ponavljanje",
"Interrompi riproduzione",
},
{ "Stop recording ", // note the trailing blank!
"Aufzeichnung beenden ",
"Prekini shranjevanje ",
"Interrompi registrazione ",
},
{ "Cancel editing",
"Schneiden abbrechen",
"Prekini urejanje",
"Annulla modifiche",
},
{ "Switching primary DVB...",
"Primäres Interface wird umgeschaltet...",
"Preklapljanje primarne naprave...",
"Cambio su card DVB primaria...",
},
{ "Up/Dn for new location - OK to move",
"Auf/Ab für neue Position - dann OK",
"Gor/Dol za novo poz. - Ok za premik",
"Su/Giu per nuova posizione - OK per muovere",
},
{ "Editing process started",
"Schnitt gestartet",
"Urejanje se je zacelo",
"Processo di modifica iniziato",
},
{ NULL }
};

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 1.32 2000/11/18 15:28:50 kls Exp $
* $Id: interface.c 1.33 2000/12/09 11:04:10 kls Exp $
*/
#include "interface.h"
@ -121,6 +121,12 @@ void cInterface::Fill(int x, int y, int w, int h, eDvbColor Color)
cDvbApi::PrimaryDvbApi->Fill(x, y, w, h, Color);
}
void cInterface::SetBitmap(int x, int y, const cBitmap &Bitmap)
{
if (open)
cDvbApi::PrimaryDvbApi->SetBitmap(x, y, Bitmap);
}
void cInterface::Flush(void)
{
if (open)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.h 1.20 2000/11/18 15:27:59 kls Exp $
* $Id: interface.h 1.21 2000/12/09 10:48:41 kls Exp $
*/
#ifndef __INTERFACE_H
@ -41,6 +41,7 @@ public:
void Clear(void);
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
void Flush(void);
void SetCols(int *c);
eDvbFont SetFont(eDvbFont Font);

265
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 1.52 2000/11/18 16:30:13 kls Exp $
* $Id: menu.c 1.58 2001/01/13 13:07:43 kls Exp $
*/
#include "menu.h"
@ -669,7 +669,7 @@ eOSState cMenuChannels::Del(void)
return osContinue;
}
}
if (Interface->Confirm(tr("Delete Channel?"))) {
if (Interface->Confirm(tr("Delete channel?"))) {
// Move and renumber the channels:
Channels.Del(channel);
Channels.ReNumber();
@ -1039,7 +1039,7 @@ eOSState cMenuTimers::Del(void)
cTimer *ti = Timers.Get(Index);
if (ti) {
if (!ti->recording) {
if (Interface->Confirm(tr("Delete Timer?"))) {
if (Interface->Confirm(tr("Delete timer?"))) {
Timers.Del(Timers.Get(Index));
cOsdMenu::Del(Index);
Timers.Save();
@ -1310,7 +1310,9 @@ private:
cThreadLock threadLock;
const cSchedules *schedules;
bool now, next;
int otherChannel;
eOSState Record(void);
eOSState Switch(void);
void PrepareSchedule(cChannel *Channel);
void PrepareWhatsOnNext(bool On);
public:
@ -1322,6 +1324,7 @@ cMenuSchedule::cMenuSchedule(void)
:cOsdMenu("", 6, 6)
{
now = next = false;
otherChannel = 0;
cChannel *channel = Channels.GetByNumber(cDvbApi::CurrentChannel());
if (channel) {
schedules = cDvbApi::PrimaryDvbApi->Schedules(&threadLock);
@ -1383,6 +1386,16 @@ eOSState cMenuSchedule::Record(void)
return osContinue;
}
eOSState cMenuSchedule::Switch(void)
{
if (otherChannel) {
if (Channels.SwitchTo(otherChannel))
return osEnd;
}
Interface->Error(tr("Can't switch channel!"));
return osContinue;
}
eOSState cMenuSchedule::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
@ -1398,8 +1411,9 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
next = !next;
return AddSubMenu(new cMenuWhatsOn(schedules, now));
case kYellow: return AddSubMenu(new cMenuWhatsOn(schedules, false));
case kBlue: return Switch();
case kOk: if (Count())
return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->eventInfo));
return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->eventInfo, otherChannel));
break;
default: break;
}
@ -1411,6 +1425,10 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
cChannel *channel = Channels.GetByServiceID(ei->GetServiceID());
if (channel) {
PrepareSchedule(channel);
if (channel->number != cDvbApi::CurrentChannel()) {
otherChannel = channel->number;
SetHelp(tr("Record"), tr("Now"), tr("Next"), tr("Switch"));
}
Display();
}
}
@ -1471,7 +1489,7 @@ eOSState cMenuRecordings::Del(void)
if (ri) {
//XXX what if this recording's file is currently in use???
//XXX if (!ti->recording) {
if (Interface->Confirm(tr("Delete Recording?"))) {
if (Interface->Confirm(tr("Delete recording?"))) {
if (ri->recording->Delete()) {
cReplayControl::ClearLastReplayed(ri->recording->FileName());
cOsdMenu::Del(Current());
@ -1645,6 +1663,8 @@ cMenuMain::cMenuMain(bool Replaying)
Add(new cOsdItem(buffer, osStopRecord));
delete buffer;
}
if (cVideoCutter::Active())
Add(new cOsdItem(tr("Cancel editing"), osCancelEdit));
SetHelp(tr("Record"), NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display();
lastActivity = time(NULL);
@ -1661,13 +1681,19 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case osRecordings: return AddSubMenu(new cMenuRecordings);
case osSetup: return AddSubMenu(new cMenuSetup);
case osCommands: return AddSubMenu(new cMenuCommands);
case osStopRecord: if (Interface->Confirm(tr("Stop Recording?"))) {
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
cOsdItem *item = Get(Current());
if (item) {
cRecordControls::Stop(item->Text() + strlen(STOP_RECORDING));
return osEnd;
}
}
break;
case osCancelEdit: if (Interface->Confirm(tr("Cancel editing?"))) {
cVideoCutter::Stop();
return osEnd;
}
break;
default: switch (Key) {
case kMenu: state = osEnd; break;
case kRed: if (!HasSubMenu())
@ -1726,23 +1752,21 @@ cDisplayChannel::~cDisplayChannel()
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
{
if (!Interface->Recording()) {
if (Channel && Channel->number)
Interface->DisplayChannelNumber(Channel->number);
int BufSize = Width() + 1;
char buffer[BufSize];
if (Channel && Channel->number)
snprintf(buffer, BufSize, "%d %s", Channel->number, Channel->name);
else
snprintf(buffer, BufSize, "%s", Channel ? Channel->name : tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, MenuColumns, 1, clrBackground);
Interface->Write(0, 0, buffer);
time_t t = time(NULL);
struct tm *now = localtime(&t);
snprintf(buffer, BufSize, "%02d:%02d", now->tm_hour, now->tm_min);
Interface->Write(-5, 0, buffer);
Interface->Flush();
}
if (Channel && Channel->number)
Interface->DisplayChannelNumber(Channel->number);
int BufSize = Width() + 1;
char buffer[BufSize];
if (Channel && Channel->number)
snprintf(buffer, BufSize, "%d %s", Channel->number, Channel->name);
else
snprintf(buffer, BufSize, "%s", Channel ? Channel->name : tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, MenuColumns, 1, clrBackground);
Interface->Write(0, 0, buffer);
time_t t = time(NULL);
struct tm *now = localtime(&t);
snprintf(buffer, BufSize, "%02d:%02d", now->tm_hour, now->tm_min);
Interface->Write(-5, 0, buffer);
Interface->Flush();
}
void cDisplayChannel::DisplayInfo(void)
@ -1874,7 +1898,6 @@ cRecordControl::~cRecordControl()
{
Stop(true);
delete instantId;
Interface->DisplayRecording(dvbApi->Index(), false);
}
void cRecordControl::Stop(bool KeepInstant)
@ -1890,6 +1913,7 @@ void cRecordControl::Stop(bool KeepInstant)
Timers.Save();
}
timer = NULL;
Interface->DisplayRecording(dvbApi->Index(), false);
}
}
@ -1946,7 +1970,7 @@ void cRecordControls::Stop(cDvbApi *DvbApi)
if (RecordControls[i]) {
if (RecordControls[i]->Uses(DvbApi)) {
isyslog(LOG_INFO, "stopping recording on DVB device %d due to higher priority", DvbApi->Index() + 1);
RecordControls[i]->Stop();
RecordControls[i]->Stop(true);
}
}
}
@ -1975,6 +1999,50 @@ void cRecordControls::Process(void)
}
}
// --- cProgressBar ----------------------------------------------------------
class cProgressBar : public cBitmap {
protected:
int total;
int Pos(int p) { return p * width / total; }
void Mark(int x, bool Start, bool Current);
public:
cProgressBar(int Width, int Height, int Current, int Total, const cMarks &Marks);
};
cProgressBar::cProgressBar(int Width, int Height, int Current, int Total, const cMarks &Marks)
:cBitmap(Width, Height)
{
total = Total;
if (total > 0) {
int p = Pos(Current);
Fill(0, 0, p, Height - 1, clrGreen);
Fill(p + 1, 0, Width - 1, Height - 1, clrWhite);
bool Start = true;
for (const cMark *m = Marks.First(); m; m = Marks.Next(m)) {
int p1 = Pos(m->position);
if (Start) {
const cMark *m2 = Marks.Next(m);
int p2 = Pos(m2 ? m2->position : total);
int h = Height / 3;
Fill(p1, h, p2, Height - h, clrRed);
}
Mark(p1, Start, m->position == Current);
Start = !Start;
}
}
}
void cProgressBar::Mark(int x, bool Start, bool Current)
{
Fill(x, 0, x, height - 1, clrBlack);
const int d = height / (Current ? 3 : 9);
for (int i = 0; i < d; i++) {
int h = Start ? i : height - 1 - i;
Fill(x - d + i, h, x + d - i, h, Current ? clrRed : clrBlack);
}
}
// --- cReplayControl --------------------------------------------------------
char *cReplayControl::fileName = NULL;
@ -1982,16 +2050,18 @@ char *cReplayControl::title = NULL;
cReplayControl::cReplayControl(void)
{
dvbApi = cDvbApi::PrimaryDvbApi;//XXX
visible = shown = false;
if (fileName)
dvbApi->StartReplay(fileName, title);
dvbApi = cDvbApi::PrimaryDvbApi;
visible = shown = displayFrames = false;
if (fileName) {
marks.Load(fileName);
dvbApi->StartReplay(fileName);
}
}
cReplayControl::~cReplayControl()
{
Hide();
dvbApi->Stop();
dvbApi->StopReplay();
}
void cReplayControl::SetRecording(const char *FileName, const char *Title)
@ -2020,7 +2090,7 @@ void cReplayControl::Show(void)
if (!visible) {
Interface->Open(MenuColumns, -3);
needsFastResponse = visible = true;
shown = dvbApi->ShowProgress(true);
shown = ShowProgress(true);
}
}
@ -2032,27 +2102,148 @@ void cReplayControl::Hide(void)
}
}
bool cReplayControl::ShowProgress(bool Initial)
{
int Current, Total;
if (dvbApi->GetIndex(Current, Total) && Total > 0) {
if (Initial) {
Interface->Clear();
if (title)
Interface->Write(0, 0, title);
displayFrames = marks.Count() > 0;
}
Interface->Write(-7, 2, IndexToHMSF(Total));
Interface->Flush();
#ifdef DEBUG_OSD
int p = Width() * Current / Total;
Interface->Fill(0, 1, p, 1, clrGreen);
Interface->Fill(p, 1, Width() - p, 1, clrWhite);
#else
cProgressBar ProgressBar(Width() * dvbApi->CellWidth(), dvbApi->LineHeight(), Current, Total, marks);
Interface->SetBitmap(0, dvbApi->LineHeight(), ProgressBar);
Interface->Flush();
#endif
Interface->Write(0, 2, IndexToHMSF(Current, displayFrames));
Interface->Flush();
return true;
}
return false;
}
void cReplayControl::MarkToggle(void)
{
int Current, Total;
if (dvbApi->GetIndex(Current, Total, true)) {
cMark *m = marks.Get(Current);
if (m)
marks.Del(m);
else
marks.Add(Current);
marks.Save();
}
displayFrames = marks.Count() > 0;
if (!displayFrames)
Interface->Fill(0, 2, Width() / 2, 1, clrBackground);
}
void cReplayControl::MarkJump(bool Forward)
{
int Current, Total;
if (dvbApi->GetIndex(Current, Total)) {
cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current);
if (m)
dvbApi->Goto(m->position, true);
}
}
void cReplayControl::MarkMove(bool Forward)
{
int Current, Total;
if (dvbApi->GetIndex(Current, Total)) {
cMark *m = marks.Get(Current);
if (m) {
int p = dvbApi->SkipFrames(Forward ? 1 : -1);
cMark *m2;
if (Forward) {
if ((m2 = marks.Next(m)) != NULL && m2->position <= p)
return;
}
else {
if ((m2 = marks.Prev(m)) != NULL && m2->position >= p)
return;
}
dvbApi->Goto(m->position = p, true);
marks.Save();
}
}
}
void cReplayControl::EditCut(void)
{
Hide();
if (!cVideoCutter::Active()) {
if (!cVideoCutter::Start(fileName))
Interface->Error(tr("Can't start editing process!"));
else
Interface->Info(tr("Editing process started"));
}
else
Interface->Error(tr("Editing process already active!"));
}
void cReplayControl::EditTest(void)
{
int Current, Total;
if (dvbApi->GetIndex(Current, Total)) {
cMark *m = marks.Get(Current);
if (!m)
m = marks.GetNext(Current);
if (m) {
if ((m->Index() & 0x01) != 0)
m = marks.Next(m);
if (m) {
dvbApi->Goto(m->position - dvbApi->SecondsToFrames(3));
dvbApi->Play();
}
}
}
}
eOSState cReplayControl::ProcessKey(eKeys Key)
{
if (!dvbApi->Replaying())
return osEnd;
if (visible)
shown = dvbApi->ShowProgress(!shown) || shown;
shown = ShowProgress(!shown) || shown;
switch (Key) {
// Positioning:
case kUp: dvbApi->Play(); break;
case kDown: dvbApi->Pause(); break;
case kBlue: Hide();
dvbApi->Stop();
return osEnd;
case kLeft: dvbApi->Backward(); break;
case kRight: dvbApi->Forward(); break;
case kLeft|k_Release:
case kRight|k_Release:
dvbApi->Play(); break;
case kGreen|k_Repeat:
case kGreen: dvbApi->Skip(-60); break;
case kGreen: dvbApi->SkipSeconds(-60); break;
case kYellow|k_Repeat:
case kYellow: dvbApi->Skip(60); break;
case kYellow: dvbApi->SkipSeconds(60); break;
case kBlue: Hide();
dvbApi->StopReplay();
return osEnd;
// Editing:
//XXX should we do this only when the ProgressDisplay is on???
case kMarkToggle: MarkToggle(); break;
case kMarkJumpBack: MarkJump(false); break;
case kMarkJumpForward: MarkJump(true); break;
case kMarkMoveBack|k_Repeat:
case kMarkMoveBack: MarkMove(false); break;
case kMarkMoveForward|k_Repeat:
case kMarkMoveForward: MarkMove(true); break;
case kEditCut: EditCut(); break;
case kEditTest: EditTest(); break;
// Menu control:
case kMenu: Hide(); return osMenu; // allow direct switching to menu
case kOk: visible ? Hide() : Show(); break;
case kBack: return osRecordings;

11
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.h 1.14 2000/11/12 12:33:00 kls Exp $
* $Id: menu.h 1.16 2000/12/25 14:25:29 kls Exp $
*/
#ifndef _MENU_H
@ -79,11 +79,18 @@ public:
class cReplayControl : public cOsdBase {
private:
cDvbApi *dvbApi;
bool visible, shown;
cMarks marks;
bool visible, shown, displayFrames;
void Show(void);
void Hide(void);
static char *fileName;
static char *title;
bool ShowProgress(bool Initial);
void MarkToggle(void);
void MarkJump(bool Forward);
void MarkMove(bool Forward);
void EditCut(void);
void EditTest(void);
public:
cReplayControl(void);
virtual ~cReplayControl();

3
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.h 1.17 2000/11/12 15:27:34 kls Exp $
* $Id: osd.h 1.18 2000/12/24 10:16:52 kls Exp $
*/
#ifndef __OSD_H
@ -29,6 +29,7 @@ enum eOSState { osUnknown,
osReplay,
osStopRecord,
osStopReplay,
osCancelEdit,
osSwitchDvb,
osBack,
osEnd,

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 1.21 2000/11/18 16:22:29 kls Exp $
* $Id: recording.c 1.24 2001/01/13 12:17:15 kls Exp $
*/
#define _GNU_SOURCE
@ -26,6 +26,7 @@
#define NAMEFORMAT "%s/%s/" DATAFORMAT
#define SUMMARYFILESUFFIX "/summary.vdr"
#define MARKSFILESUFFIX "/marks.vdr"
#define FINDCMD "find %s -follow -type d -name '%s' 2> /dev/null | sort -df"
@ -125,6 +126,7 @@ cRecording::cRecording(const char *FileName)
strncpy(name, FileName, p - FileName);
name[p - FileName] = 0;
strreplace(name, '_', ' ');
strreplace(name, '\x01', '\'');
}
// read an optional summary file:
char *SummaryFileName = NULL;
@ -175,8 +177,10 @@ const char *cRecording::FileName(void)
if (!fileName) {
struct tm *t = localtime(&start);
asprintf(&fileName, NAMEFORMAT, VideoDirectory, name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, priority, lifetime);
if (fileName)
if (fileName) {
strreplace(fileName, ' ', '_');
strreplace(fileName, '\'', '\x01');
}
}
return fileName;
}
@ -269,3 +273,107 @@ bool cRecordings::Load(bool Deleted)
return result;
}
// --- cMark -----------------------------------------------------------------
char *cMark::buffer = NULL;
cMark::cMark(int Position, const char *Comment)
{
position = Position;
comment = Comment ? strdup(Comment) : NULL;
}
cMark::~cMark()
{
delete comment;
}
const char *cMark::ToText(void)
{
delete buffer;
asprintf(&buffer, "%s%s%s\n", IndexToHMSF(position, true), comment ? " " : "", comment ? comment : "");
return buffer;
}
bool cMark::Parse(const char *s)
{
delete comment;
comment = NULL;
position = HMSFToIndex(s);
const char *p = strchr(s, ' ');
if (p) {
p = skipspace(p);
if (*p) {
comment = strdup(p);
comment[strlen(comment) - 1] = 0; // strips trailing newline
}
}
return true;
}
bool cMark::Save(FILE *f)
{
return fprintf(f, ToText()) > 0;
}
// --- cMarks ----------------------------------------------------------------
bool cMarks::Load(const char *RecordingFileName)
{
const char *MarksFile = AddDirectory(RecordingFileName, MARKSFILESUFFIX);
if (cConfig<cMark>::Load(MarksFile)) {
Sort();
return true;
}
return false;
}
void cMarks::Sort(void)
{
for (cMark *m1 = First(); m1; m1 = Next(m1)) {
for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) {
if (m2->position < m1->position) {
swap(m1->position, m2->position);
swap(m1->comment, m2->comment);
}
}
}
}
cMark *cMarks::Add(int Position)
{
cMark *m = Get(Position);
if (!m) {
cConfig<cMark>::Add(m = new cMark(Position));
Sort();
}
return m;
}
cMark *cMarks::Get(int Position)
{
for (cMark *mi = First(); mi; mi = Next(mi)) {
if (mi->position == Position)
return mi;
}
return NULL;
}
cMark *cMarks::GetPrev(int Position)
{
for (cMark *mi = Last(); mi; mi = Prev(mi)) {
if (mi->position < Position)
return mi;
}
return NULL;
}
cMark *cMarks::GetNext(int Position)
{
for (cMark *mi = First(); mi; mi = Next(mi)) {
if (mi->position > Position)
return mi;
}
return NULL;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 1.10 2000/10/03 12:27:49 kls Exp $
* $Id: recording.h 1.11 2000/12/16 14:25:20 kls Exp $
*/
#ifndef __RECORDING_H
@ -47,4 +47,27 @@ public:
bool Load(bool Deleted = false);
};
class cMark : public cListObject {
private:
static char *buffer;
public:
int position;
char *comment;
cMark(int Position = 0, const char *Comment = NULL);
~cMark();
const char *ToText(void);
bool Parse(const char *s);
bool Save(FILE *f);
};
class cMarks : public cConfig<cMark> {
public:
bool Load(const char *RecordingFileName);
void Sort(void);
cMark *Add(int Position);
cMark *Get(int Position);
cMark *GetPrev(int Position);
cMark *GetNext(int Position);
};
#endif //__RECORDING_H

View File

@ -6,7 +6,7 @@
*
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
*
* $Id: remote.c 1.19 2000/11/11 11:22:22 kls Exp $
* $Id: remote.c 1.20 2000/12/03 11:55:06 kls Exp $
*/
#include "remote.h"
@ -115,7 +115,7 @@ cRcIoRCU::cRcIoRCU(char *DeviceName)
cRcIoRCU::~cRcIoRCU()
{
Stop();
Cancel();
}
void cRcIoRCU::Action(void)
@ -420,7 +420,7 @@ cRcIoLIRC::cRcIoLIRC(char *DeviceName)
cRcIoLIRC::~cRcIoLIRC()
{
Stop();
Cancel();
}
void cRcIoLIRC::Action(void)

View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection.
*
* $Id: svdrp.c 1.12 2000/11/05 13:44:42 kls Exp $
* $Id: svdrp.c 1.13 2000/12/03 15:34:35 kls Exp $
*/
#define _GNU_SOURCE
@ -18,6 +18,7 @@
#include "svdrp.h"
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdarg.h>

View File

@ -4,12 +4,15 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.c 1.4 2000/11/14 18:38:25 kls Exp $
* $Id: thread.c 1.7 2000/12/24 12:27:21 kls Exp $
*/
#include "thread.h"
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include "tools.h"
// --- cThread ---------------------------------------------------------------
@ -25,7 +28,7 @@ cThread::cThread(void)
signalHandlerInstalled = true;
}
running = false;
parentPid = lockingPid = 0;
parentPid = threadPid = lockingPid = 0;
locked = 0;
}
@ -40,6 +43,7 @@ void cThread::SignalHandler(int signum)
void *cThread::StartThread(cThread *Thread)
{
Thread->threadPid = getpid();
Thread->Action();
return NULL;
}
@ -49,13 +53,37 @@ bool cThread::Start(void)
if (!running) {
running = true;
parentPid = getpid();
pthread_create(&thread, NULL, &StartThread, (void *)this);
pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
}
return true; //XXX return value of pthread_create()???
}
void cThread::Stop(void)
bool cThread::Active(void)
{
if (threadPid) {
if (kill(threadPid, SIGIO) < 0) { // couldn't find another way of checking whether the thread is still running - any ideas?
if (errno == ESRCH)
threadPid = 0;
else
LOG_ERROR;
}
else
return true;
}
return false;
}
void cThread::Cancel(int WaitSeconds)
{
if (WaitSeconds > 0) {
for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
if (!Active())
return;
usleep(10000);
}
esyslog(LOG_ERR, "ERROR: thread %d won't end (waited %d seconds) - cancelling it...", threadPid, WaitSeconds);
}
pthread_cancel(thread);
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.h 1.3 2000/11/14 18:38:11 kls Exp $
* $Id: thread.h 1.4 2000/12/03 11:18:37 kls Exp $
*/
#ifndef __THREAD_H
@ -28,7 +28,7 @@ class cThread {
private:
pthread_t thread;
cMutex Mutex;
pid_t parentPid, lockingPid;
pid_t parentPid, threadPid, lockingPid;
int locked;
bool running;
static bool signalHandlerInstalled;
@ -39,11 +39,12 @@ private:
protected:
void WakeUp(void);
virtual void Action(void) = 0;
void Stop(void);
void Cancel(int WaitSeconds = 0);
public:
cThread(void);
virtual ~cThread();
bool Start(void);
bool Active(void);
};
// cThreadLock can be used to easily set a lock in a thread and make absolutely

View File

@ -1,14 +0,0 @@
1:15:M------:2128:2205:80:7:Neues:
1:3:-T-----:2013:2125:99:99:SevenDays:
1:10:-T-----:2058:2202:99:10:Quarks:
1:25:-T-----:2305:0020:99:99:UFO:
1:14:--W----:1920:2020:70:99:Rettungsflieger:
0:2:--W----:2110:2325:99:99:BulleVonToelz:
1:3:---T---:2210:2315:50:20:IngoAppelt:
1:2:----F--:2013:2125:99:99:Farscape:
1:1:----F--:2215:2325:50:20:7Tage7Koepfe:
0:11:-----S-:2058:2135:99:99:Computer:
0:2:-----S-:2220:2340:99:30:Wochenshow:
1:11:------S:2013:2035:99:10:Centauri:
1:15:MTWTF--:1828:1901:10:5:nano:
1:1:MTWTF--:1553:1710:99:99:Hammerman:

119
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 1.23 2000/11/11 15:17:12 kls Exp $
* $Id: tools.c 1.27 2001/01/13 15:35:02 kls Exp $
*/
#define _GNU_SOURCE
@ -15,10 +15,7 @@
#if defined(DEBUG_OSD)
#include <ncurses.h>
#endif
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#define MaxBuffer 1000
@ -30,29 +27,6 @@ void writechar(int filedes, char c)
write(filedes, &c, sizeof(c));
}
void writeint(int filedes, int n)
{
write(filedes, &n, sizeof(n));
}
char readchar(int filedes)
{
char c;
read(filedes, &c, 1);
return c;
}
bool readint(int filedes, int &n)
{
return cFile::AnyFileReady(filedes, 0) && read(filedes, &n, sizeof(n)) == sizeof(n);
}
void purge(int filedes)
{
while (cFile::AnyFileReady(filedes, 0))
readchar(filedes);
}
char *readline(FILE *f)
{
static char buffer[MaxBuffer];
@ -146,7 +120,7 @@ const char *AddDirectory(const char *DirName, const char *FileName)
return buf;
}
#define DFCMD "df -m %s"
#define DFCMD "df -m '%s'"
uint FreeDiskSpaceMB(const char *Directory)
{
@ -205,7 +179,7 @@ bool MakeDirs(const char *FileName, bool IsDirectory)
if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
dsyslog(LOG_INFO, "creating directory %s", s);
if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno));
LOG_ERROR_STR(s);
result = false;
break;
}
@ -266,44 +240,32 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
if (remove(FileName) == 0)
return true;
}
else
else if (errno != ENOENT) {
LOG_ERROR_STR(FileName);
return false;
}
bool CheckProcess(pid_t pid)
{
pid_t Pid2Check = pid;
int status;
pid = waitpid(Pid2Check, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return false;
}
return true;
}
void KillProcess(pid_t pid, int Timeout)
char *ReadLink(const char *FileName)
{
pid_t Pid2Wait4 = pid;
for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
int status;
pid_t pid = waitpid(Pid2Wait4, &status, WNOHANG);
if (pid < 0) {
if (errno != ECHILD)
LOG_ERROR;
return;
}
if (pid == Pid2Wait4)
return;
}
esyslog(LOG_ERR, "ERROR: process %d won't end (waited %d seconds) - terminating it...", Pid2Wait4, Timeout);
if (kill(Pid2Wait4, SIGTERM) < 0) {
esyslog(LOG_ERR, "ERROR: process %d won't terminate (%s) - killing it...", Pid2Wait4, strerror(errno));
if (kill(Pid2Wait4, SIGKILL) < 0)
esyslog(LOG_ERR, "ERROR: process %d won't die (%s) - giving up", Pid2Wait4, strerror(errno));
char RealName[_POSIX_PATH_MAX];
const char *TargetName = NULL;
int n = readlink(FileName, RealName, sizeof(RealName) - 1);
if (n < 0) {
if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink
TargetName = FileName;
else { // some other error occurred
LOG_ERROR_STR(FileName);
}
}
else if (n < int(sizeof(RealName))) { // got it!
RealName[n] = 0;
TargetName = RealName;
}
else
esyslog(LOG_ERR, "ERROR: symlink's target name too long: %s", FileName);
return TargetName ? strdup(TargetName) : NULL;
}
// --- cFile -----------------------------------------------------------------
@ -426,6 +388,45 @@ bool cFile::FileReady(int FileDes, int TimeoutMs)
return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set);
}
// --- cSafeFile -------------------------------------------------------------
cSafeFile::cSafeFile(const char *FileName)
{
f = NULL;
fileName = ReadLink(FileName);
tempName = fileName ? new char[strlen(fileName) + 5] : NULL;
if (tempName)
strcat(strcpy(tempName, fileName), ".$$$");
}
cSafeFile::~cSafeFile()
{
if (f)
fclose(f);
unlink(tempName);
delete fileName;
delete tempName;
}
bool cSafeFile::Open(void)
{
if (!f && fileName && tempName) {
f = fopen(tempName, "w");
if (!f)
LOG_ERROR_STR(tempName);
}
return f != NULL;
}
void cSafeFile::Close(void)
{
if (f) {
fclose(f);
f = NULL;
rename(tempName, fileName);
}
}
// --- cListObject -----------------------------------------------------------
cListObject::cListObject(void)

33
tools.h
View File

@ -4,13 +4,13 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 1.20 2000/11/12 15:27:06 kls Exp $
* $Id: tools.h 1.23 2001/01/13 15:36:00 kls Exp $
*/
#ifndef __TOOLS_H
#define __TOOLS_H
#include <errno.h>
//#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
@ -24,19 +24,16 @@ extern int SysLogLevel;
#define isyslog if (SysLogLevel > 1) syslog
#define dsyslog if (SysLogLevel > 2) syslog
#define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %s", __FILE__, __LINE__, strerror(errno))
#define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %s", s, strerror(errno));
#define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %m", __FILE__, __LINE__)
#define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %m", s)
#define SECSINDAY 86400
#define MAXPROCESSTIMEOUT 3 // seconds
#define DELETENULL(p) (delete (p), p = NULL)
template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; };
void writechar(int filedes, char c);
void writeint(int filedes, int n);
char readchar(int filedes);
bool readint(int filedes, int &n);
void purge(int filedes);
char *readline(FILE *f);
char *strn0cpy(char *dest, const char *src, size_t n);
char *strreplace(char *s, char c1, char c2);
@ -51,8 +48,7 @@ uint FreeDiskSpaceMB(const char *Directory);
bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false);
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
bool CheckProcess(pid_t pid);
void KillProcess(pid_t pid, int Timeout = MAXPROCESSTIMEOUT);
char *ReadLink(const char *FileName);
class cFile {
private:
@ -73,6 +69,19 @@ public:
static bool FileReady(int FileDes, int TimeoutMs = 1000);
};
class cSafeFile {
private:
FILE *f;
char *fileName;
char *tempName;
public:
cSafeFile(const char *FileName);
~cSafeFile();
operator FILE* () { return f; }
bool Open(void);
void Close(void);
};
class cListObject {
private:
cListObject *prev, *next;
@ -105,6 +114,8 @@ template<class T> class cList : public cListBase {
public:
T *Get(int Index) const { return (T *)cListBase::Get(Index); }
T *First(void) const { return (T *)objects; }
T *Last(void) const { return (T *)lastObject; }
T *Prev(const T *object) const { return (T *)object->Prev(); }
T *Next(const T *object) const { return (T *)object->Next(); }
};

15
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.46 2000/11/18 13:46:56 kls Exp $
* $Id: vdr.c 1.49 2001/01/14 15:29:51 kls Exp $
*/
#include <getopt.h>
@ -141,8 +141,8 @@ int main(int argc, char *argv[])
#if !defined(DEBUG_OSD) && !defined(REMOTE_KBD)
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno));
esyslog(LOG_ERR, "ERROR: %s", strerror(errno));
fprintf(stderr, "%m\n");
esyslog(LOG_ERR, "ERROR: %m");
abort();
}
if (pid != 0)
@ -179,7 +179,7 @@ int main(int argc, char *argv[])
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB);
Channels.SwitchTo(1);
Channels.SwitchTo(Setup.CurrentChannel);
cEITScanner EITScanner;
@ -306,10 +306,15 @@ int main(int argc, char *argv[])
default: break;
}
}
if (!Menu)
if (!Menu) {
EITScanner.Process();
cVideoCutter::Active();
}
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
Setup.CurrentChannel = cDvbApi::CurrentChannel();
Setup.Save();
cVideoCutter::Stop();
delete Menu;
delete ReplayControl;
delete Interface;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: videodir.c 1.2 2000/09/15 13:23:47 kls Exp $
* $Id: videodir.c 1.3 2000/12/24 12:51:41 kls Exp $
*/
#include "videodir.h"
@ -180,3 +180,20 @@ bool VideoFileSpaceAvailable(unsigned int SizeMB)
}
return Dir.FreeMB() >= SizeMB;
}
const char *PrefixVideoFileName(const char *FileName, char Prefix)
{
static char *PrefixedName = NULL;
if (!PrefixedName || strlen(PrefixedName) <= strlen(FileName))
PrefixedName = (char *)realloc(PrefixedName, strlen(FileName) + 2);
if (PrefixedName) {
strcpy(PrefixedName, VideoDirectory);
char *p = PrefixedName + strlen(PrefixedName);
*p++ = '/';
*p++ = Prefix;
strcpy(p, FileName + strlen(VideoDirectory) + 1);
}
return PrefixedName;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: videodir.h 1.1 2000/07/29 14:08:27 kls Exp $
* $Id: videodir.h 1.2 2000/12/24 12:41:10 kls Exp $
*/
#ifndef __VIDEODIR_H
@ -17,5 +17,6 @@ int CloseVideoFile(int FileHandle);
bool RenameVideoFile(const char *OldName, const char *NewName);
bool RemoveVideoFile(const char *FileName);
bool VideoFileSpaceAvailable(unsigned int SizeMB);
const char *PrefixVideoFileName(const char *FileName, char Prefix);
#endif //__VIDEODIR_H