Converted to the new API plus several small enhancements

This commit is contained in:
Klaus Schmidinger 2001-06-02 10:47:40 +02:00
parent 1ef2b1d3a1
commit c40e4eb96e
31 changed files with 1681 additions and 1169 deletions

View File

@ -42,6 +42,7 @@ Bastian Guse <bastian@nocopy.de>
Matthias Schniedermeyer <ms@citd.de>
for implementing the 'MarkInstantRecord' setup option
for his "schnitt" tools
for his "master-timer" tool
Miha Setina <mihasetina@softhome.net>
for translating the OSD texts to the Slovenian language
@ -54,6 +55,7 @@ Deti Fliegl <deti@fliegl.de>
Dave Chapman <dave@dchapman.com>
for implementing support for the teletext PID
for his great support in switching to the NAPI
Hans-Peter Raschke <Hans-Peter.Raschke@Wintermann-DatenService.de>
for his support in adapting VDR to DVB-C
@ -70,3 +72,6 @@ Arnold Niessen <niessen@iae.nl> <arnold.niessen@philips.com>
Jürgen Sauer <jojo@automatix.de>
for implementing the -t option to set the controlling terminal
Benjamin Reichardt <reichard@math.uni-goettingen.de>
for his help in debugging the transition to the new API

View File

@ -13,7 +13,7 @@ Video Disk Recorder File Formats
A "channel definition" is a line with channel data, where the fields
are separated by ':' characters:
Example: "RTL:12188:h:1:27500:163:104:0:0:12003"
Example: "RTL:12188:h:1:27500:163:104:105:0:12003"
The fields in a channel definition have the following meaning (from left
to right):
@ -60,8 +60,10 @@ Video Disk Recorder File Formats
(1..31)
- Start time (first two digits for the hour, second two digits for the minutes)
- End time (first two digits for the hour, second two digits for the minutes)
- Priority (from 00 to 99, 00 = lowest prioity, 99 = highest priority)
- Guaranteed lifetime of recording (in days)
- Priority (from 0 to 99, 0 = lowest prioity, 99 = highest priority)
- Guaranteed lifetime of recording (in days); 0 means that this recording may
be automatically deleted by a new recording with higher priority, 99 means
that this recording will never be automatically deleted
- Name of timer (will be used to name the recording); if the name contains
any ':' characters, these have to be replaced with '|'
- Summary (any newline characters in the summary have to be replaced with '|';

44
HISTORY
View File

@ -290,7 +290,7 @@ Video Disk Recorder Revision History
channel, if the timer currently occupying this DVB card doesn't need the
CAM module (and thus can continue recording on a different DVB card).
- The "Yellow" button in the "What's on now/next?" menus now displays the
schedule of the current channel from that menu.
schedule of the current channel from that menu.
- All DVB cards in a multi-card system now write their EIT information into the
same data structure.
- If there is more than one DVB card in the system, the non-primary cards are
@ -332,8 +332,8 @@ Video Disk Recorder Revision History
- 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 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).
@ -452,3 +452,41 @@ Video Disk Recorder Revision History
- Empty lines in config files no longer cause error messages.
- New SVDRP command LSTE to list the EPG data.
- The SVDRP HELP command now prints the topics in several columns.
2001-06-02: Version 0.80
- VDR now requires driver version 0.9.0 or higher.
- Switched to the "new API" (thanks to Dave Chapman for his great support in
this task).
- New setup parameter "LnbSLOF" that defines the switching frequency of the LNB.
- Fixed a bug in the EPG scanner with more than one DVB card.
- Fixed checking for free disk space, so that it works with NFS mounted drives.
- Files are now created with mode 644.
- Fixed checking the exit status in the 'runvdr' script.
- Activated loading the driver in 'runvdr'. Please read the comments in 'runvdr'
for details.
- The new "emergency exit" feature automatically triggers a restart of VDR (if
used with 'runvdr', otherwise it simply exists) if
* tuning the channel for a recording fails
* no useful data is received within the first 1MB of a recording
* no data is received within a recording for more than 5 seconds
This should make sure that a recording is successfully restarted after any
problems.
- Processing the EIT data is now disabled during replay and 'Transfer Mode' in
order to avoid video and audio glitches (there appears to be a bandwidth
problem somewhere in the driver/firmware/hardware).
- Due to the reduced amount of OSD memory provided by the driver the number of
lines in the OSD had to be reduced by 2. By rearranging some of the display
items the amount of visible information remained the same as before, though.
If your DVB card has even less memory (which would result in only the
channel switching display and the replay progress display being visible, but
no Main menu), try reducing the constant 'MenuLines' in dvbapi.h (currently
'13') even further.
- There are two new setup parameters to define the "Default Priority" and
"Default Lifetime" when creating a new timer event.
- The meaning of the "Lifetime" parameter has been modified: a value of '99'
now means that the recording will live "forever", and a value of '0' means
that the recording has no guaranteed lifetime and will be deleted whenever
a new recording with higher priority needs disk space.
- Updated version of Matthias Schniedermeyer's 'schnitt' tools.
- New 'master-timer' tool (thanks to Matthias Schniedermeyer).

11
MANUAL
View File

@ -32,11 +32,11 @@ Video Disk Recorder User's Manual
confirms any changes (or switches to a channel in the "Channels" menu).
The "Back" key goes back one level in the menu structure, discarding
any changes that might have been made in the current menu.
In the "Timers" menu, the current timer can be enabled or disabled with
the "Right" or "Left" key, respectively (enabled timers are marked with ">").
"Ok" here opens the "Edit timer" menu.
Textual options, like channel names or recording file names, can be edited
by pressing the "Right" button (which puts brackets around the current
character as in "[R]TL"), selecting the desired character position with
@ -46,10 +46,10 @@ Video Disk Recorder User's Manual
brackets (as in abc[^]), the next press to the "Left" or "Ok" button will
actually cut off the string. Using "Up" and/or "Down" brings back the
original rest of the string (unless you have pressed "Left" or "Ok").
The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
in various menus and are listed at the bottom of the on-screen-display.
At any point in the menu system, pressing the "Menu" key again will
immediately leave the menu system (discarding any pending changes).
@ -309,7 +309,8 @@ Video Disk Recorder User's Manual
0 = instant recordings will not be marked
1 = instant recordings will be marked.
LnbFrequLo = 9750 The low and high LNB frequencies (in MHz)
LnbSLOF = 11700 The switching frequency (in MHz) between low and high LOF
LnbFrequLo = 9750 The LNB's low and high local oscillator frequencies (in MHz)
LnbFrequHi = 10600 (these have no meaning for DVB-C receivers)
SetSystemTime = 0 Defines whether the system time will be set according to

View File

@ -4,11 +4,11 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 1.21 2001/03/18 16:47:00 kls Exp $
# $Id: Makefile 1.22 2001/06/02 09:15:39 kls Exp $
DVBDIR = ../DVB
INCLUDES = -I$(DVBDIR)/driver
INCLUDES = -I$(DVBDIR)/ost/include
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o osd.o\
recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
videodir.o
@ -43,7 +43,7 @@ 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 recording.h remote.h remux.h ringbuffer.h svdrp.h thread.h tools.h videodir.h
dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h eit.h font.h recording.h remux.h ringbuffer.h thread.h tools.h videodir.h
dvbosd.o : dvbosd.c dvbosd.h font.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
@ -53,7 +53,7 @@ menu.o : menu.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h
osd.o : osd.c config.h dvbapi.h dvbosd.h eit.h font.h i18n.h interface.h osd.h remote.h svdrp.h thread.h tools.h
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
remux.o : remux.c remux.h tools.h
remux.o : remux.c remux.h thread.h tools.h
ringbuffer.o: ringbuffer.c ringbuffer.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 tools.h

View File

@ -1,175 +0,0 @@
RTL:12188:h:0:27500:163:104:105:0:12003
Sat.1:12480:v:0:27500:1791:1792:34:0:46
Pro-7:12480:v:0:27500:255:256:32:0:898
RTL2:12188:h:0:27500:166:128:68:0:12020
ARD:11837:h:0:27500:101:102:0:0:28106
BR3:11837:h:0:27500:201:202:0:0:28107
Hessen-3:11837:h:0:27500:301:302:0:0:28108
N3:12110:h:0:27500:2401:2402:0:0:28224
SR3:11837:h:0:27500:501:502:0:0:28110
WDR:11837:h:0:27500:601:602:0:0:28111
BR-alpha:11837:h:0:27500:701:702:0:0:28112
SWR BW:11837:h:0:27500:801:802:0:0:28113
Phoenix:11837:h:0:27500:901:902:0:0:28114
ZDF:11954:h:0:27500:110:120:130:0:28006
3sat:11954:h:0:27500:210:220:230:0:28007
KiKa:11954:h:0:27500:310:320:0:0:28008
arte:11836:h:0:27500:401:402:0:0:28109
ORF1:12692:h:0:22000:160:161:165:3:13001
ORF2:12692:h:0:22000:500:501:505:3:13007
ORF Sat:11954:h:0:27500:506:507:0:0:28010
ZDF.info:11954:h:0:27500:610:620:0:0:28011
CNN:12168:v:0:27500:165:100:0:0:28512
Super RTL:12188:h:0:27500:165:120:65:0:12040
VOX:12188:h:0:27500:167:136:0:0:12060
DW TV:12363:v:0:27500:305:306:0:0:8905
Kabel 1:12480:v:0:27500:511:512:33:0:899
tm3:12480:v:0:27500:767:768:0:0:897
DSF:12480:v:0:27500:1023:1024:0:0:900
HOT:12480:v:0:27500:1279:1280:0:0:40
Bloomberg TV Germany:12551:v:0:22000:162:99:0:0:12160
BLOOMBERG TV:11817:v:0:27500:163:92:0:0:8004
Bloomberg:12168:v:0:27500:167:112:0:0:12721
Sky News:12552:v:0:22000:305:306:0:0:3995
KinderNet:12574:h:0:22000:163:92:0:0:5020
Alice:12610:v:0:22000:162:96:0:0:12200
n-tv:12669:v:0:22000:162:96:55:0:12730
Grand Tourisme:12670:v:0:22000:289:290:0:0:17300
TW1:12692:h:0:22000:166:167:0:0:13013
Eurosport:11954:h:0:27500:410:420:0:0:28009
EinsExtra:12110:h:0:27500:101:102:0:0:28201
EinsFestival:12110:h:0:27500:201:202:0:0:28202
EinsMuXx:12110:h:0:27500:301:302:0:0:28203
ZDF Theaterkanal:11954:h:0:27500:1110:1120:0:0:28016
ZDF.doku:11954:h:0:27500:660:670:0:0:28014
MDR:12110:h:0:27500:401:402:0:0:28204
NICK-PARAMOUNT:12246:v:0:27500:167:108:0:0:29312
ORB:12110:h:0:27500:501:502:0:0:28205
B1:12110:h:0:27500:601:602:0:0:28206
ARD Online-Kanal:12722:h:0:22000:8191:701:0:0:0
:Premiere World
Premiere World Promo:11798:h:0:27500:255:256:0:0:8
Premiere:11798:h:0:27500:511:512:0:3:10
Star Kino:11798:h:0:27500:767:768:0:3:9
Cine Action:11798:h:0:27500:1023:1024:0:3:20
Cine Comedy:11798:h:0:27500:1279:1280:0:3:29
Sci Fantasy:11798:h:0:27500:1535:1536:0:3:41
Romantic Movies:11797:h:0:27500:1791:1792:0:3:11
Studio Universal:12090:v:0:27500:255:256:0:3:36
13th Street:11797:h:0:27500:2303:2304:0:3:43
Junior:12031:h:0:27500:255:256:0:3:19
K-Toon:12032:h:0:27500:511:512:0:3:12
Disney Channel:12090:v:0:27500:767:768:0:3:34
Fox Kids:11797:h:0:27500:2559:2560:0:3:22
Sunset:12031:h:0:27500:1023:1024:0:3:16
Comedy:12031:h:0:27500:1279:1280:0:3:28
Planet:12090:v:0:27500:1279:1280:0:3:13
Discovery Channel:12031:h:0:27500:1791:1792:0:3:14
Krimi&Co:12031:h:0:27500:1535:1536:0:3:23
Filmpalast:11758:h:0:27500:2559:2560:0:3:516
Heimatkanal:11758:h:0:27500:2815:2816:0:3:517
Goldstar:11758:h:0:27500:3839:3840:0:3:518
Classica:12031:h:0:27500:767:768:0:3:15
Seasons:12090:v:0:27500:511:512:0:3:33
Sport 1:11720:h:0:27500:255:256:0:3:17
Sport 2:12070:h:0:27500:2047:2048:0:3:27
Sport 3:12070:h:0:27500:2303:2304:0:3:18
Sport 4:12070:h:0:27500:2559:2560:0:3:24
Feed (F1 Boxengasse):11720:h:0:27500:2559:2560:0:3:242
Feed (F1 Data):11720:h:0:27500:3071:3072:0:3:244
Feed (F1 Multi):11720:h:0:27500:2815:2816:0:3:243
Feed (F1 On Board):11720:h:0:27500:2303:2304:0:3:241
Feed (F1 Verfolger):11720:h:0:27500:2047:2048:0:3:240
Cinedom Deluxe:12070:h:0:27500:1279:1280:0:3:188
Cinedom 1A de:11758:h:0:27500:511:512:0:3:178
Cinedom 1A en:11758:h:0:27500:511:513:0:3:178
Cinedom 1B:12070:h:0:27500:767:768:0:3:185
Cinedom 1C:12070:h:0:27500:1791:1792:0:3:191
Cinedom 1E??:11720:h:0:27500:1535:1537:0:3:176
Cinedom 2A:12070:h:0:27500:1535:1536:0:3:189
Cinedom 2B:11758:h:0:27500:767:768:0:3:179
Cinedom 2C:11758:h:0:27500:1023:1024:0:3:193
Cinedom 2D??:12070:h:0:27500:511:512:0:3:184
Cinedom 3A:11758:h:0:27500:255:256:0:3:177
Cinedom 3B:11758:h:0:27500:1279:1280:0:3:194
Cinedom 3C??:12090:v:0:27500:1279:1280:17689:3:192
Cinedom 4A:11758:h:0:27500:1535:1536:0:3:195
Cinedom 4B:12070:h:0:27500:1023:1025:0:3:186
Cinedom 4C??:11720:h:0:27500:767:768:0:3:181
Cinedom 5A:12032:h:0:27500:2559:2560:0:3:187
Beate Uhse_TV:11797:h:0:27500:2047:2048:0:3:21
Blue Channel:11758:h:0:27500:2559:2560:0:3:516
Blue Movie 1:11758:h:0:27500:1791:1792:0:3:513
Blue Movie 2:11758:h:0:27500:2047:2048:0:3:514
Blue Movie 3:11758:h:0:27500:2303:2304:0:3:515
:
TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601
Mosaico:11934:v:0:27500:165:100:0:0:29010
Andalucia TV:11934:v:0:27500:166:104:0:0:29011
TVC Internacional:11934:v:0:27500:167:108:0:0:0
Nasza TV:11992:h:0:27500:165:98:0:0:0
WishLine test:12012:v:0:27500:163:90:0:0:0
Pro 7 Austria:12051:v:0:27500:161:84:0:0:0
Kabel 1 Schweiz:12051:v:0:27500:162:163:0:0:0
Kabel 1 Austria:12051:v:0:27500:166:167:0:0:0
Pro 7 Schweiz:12051:v:0:27500:289:290:0:0:0
Kiosque:12129:v:0:27500:160:80:0:0:0
KTO:12129:v:0:27500:170:120:0:0:0
TCM:12168:v:0:27500:160:80:0:0:0
Cartoon Network France & Spain:12168:v:0:27500:161:84:0:0:0
TVBS Europe:12168:v:0:27500:162:88:0:0:0
TVBS Europe:12168:v:0:27500:162:89:0:0:0
Travel:12168:v:0:27500:163:92:0:0:0
TCM Espania:12168:v:0:27500:164:96:0:0:0
MTV Spain:12168:v:0:27500:167:112:0:0:0
TCM France:12168:v:0:27500:169:64:0:0:0
RTL2 CH:12188:h:0:27500:164:112:0:0:0
La Cinquieme:12207:v:0:27500:160:80:0:0:0
ARTE:12207:v:0:27500:165:100:0:0:0
Post Filial TV:12226:h:0:27500:255:256:0:0:0
Canal Canaris:12246:v:0:27500:160:80:0:0:0
Canal Canaris:12246:v:0:27500:160:81:0:0:0
Canal Canaris:12246:v:0:27500:160:82:0:0:0
Canal Canaris:12246:v:0:27500:160:83:0:0:0
AB Sat Passion promo:12266:h:0:27500:160:80:0:0:0
AB Channel 1:12266:h:0:27500:161:84:0:0:0
Taquilla 0:12285:v:0:27500:165:100:0:0:0
CSAT:12324:v:0:27500:160:80:0:0:0
Mosaique:12324:v:0:27500:162:88:0:0:0
Mosaique 2:12324:v:0:27500:163:92:0:0:0
Mosaique 3:12324:v:0:27500:164:96:0:0:0
Le Sesame C+:12324:v:0:27500:165:1965:0:0:0
FEED:12344:h:0:27500:163:92:0:0:0
RTM 1:12363:v:0:27500:162:96:0:0:0
ESC 1:12363:v:0:27500:163:104:0:0:0
TV5 Europe:12363:v:0:27500:164:112:0:0:0
TV7 Tunisia:12363:v:0:27500:166:128:0:0:0
ARTE:12363:v:0:27500:167:137:0:0:0
RAI Uno:12363:v:0:27500:289:290:0:0:8904
RTP International:12363:v:0:27500:300:301:0:0:0
Fashion TV:12402:v:0:27500:163:92:0:0:0
VideoService:12422:h:0:27500:255:256:0:0:0
Beta Research promo:12422:h:0:27500:1023:1024:0:0:0
Canal Canarias:12441:v:0:27500:160:80:0:0:0
TVC International:12441:v:0:27500:512:660:0:0:0
Fitur:12441:v:0:27500:514:662:0:0:0
Astra Info 1:12552:v:0:22000:164:112:0:0:0
Astra Info 2:12552:v:0:22000:165:120:0:0:0
Astra Vision 1:12552:v:0:22000:168:144:0:0:0
Astra Vision 1:12552:v:0:22000:168:145:0:0:0
Astra Vision 1:12552:v:0:22000:168:146:0:0:0
Astra Vision 1:12552:v:0:22000:168:147:0:0:0
Astra Vision 1:12552:v:0:22000:168:148:0:0:0
Astra Vision 1:12552:v:0:22000:168:149:0:0:0
Astra Vision 1:12552:v:0:22000:168:150:0:0:0
RTL Tele Letzebuerg:12552:v:0:22000:168:144:0:0:0
Astra Mosaic:12552:v:0:22000:175:176:0:0:0
MHP test:12604:h:0:22000:5632:8191:0:0:0
VERONICA:12574:h:0:22000:161:84:0:0:5010
VH1 Classic:12699:v:0:22000:3071:3072:0:0:28647
VH-1 Germany:12699:v:0:22000:3081:3082:0:0:28648
Via 1 - Schöner Reisen:12148:h:0:27500:511:512:0:0:44
Video Italia:12610:v:0:22000:121:122:0:0:12220
AC 3 promo:12670:v:0:22000:308:256:0:0:0
ORF/ZDF:12699:h:0:22000:506:507:0:0:13012
VIVA:12670:v:0:22000:309:310:0: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.44 2001/04/01 14:32:22 kls Exp $
* $Id: config.c 1.45 2001/06/02 09:42:25 kls Exp $
*/
#include "config.h"
@ -155,7 +155,7 @@ eKeys cKeys::Get(unsigned int Code)
}
eKeys cKeys::Translate(const char *Command)
{
{
if (Command) {
const tKey *k = keys;
while ((k->type != kNone) && strcasecmp(k->name, Command) != 0)
@ -166,7 +166,7 @@ eKeys cKeys::Translate(const char *Command)
}
unsigned int cKeys::Encode(const char *Command)
{
{
eKeys k = Translate(Command);
if (k != kNone)
return keys[k].code;
@ -305,8 +305,8 @@ cTimer::cTimer(bool Instant)
if (stop >= 2400)
stop -= 2400;
//TODO VPS???
priority = DEFAULTPRIORITY;
lifetime = DEFAULTLIFETIME;
priority = Setup.DefaultPriority;
lifetime = Setup.DefaultLifetime;
*file = 0;
summary = NULL;
if (Instant && ch)
@ -330,8 +330,8 @@ cTimer::cTimer(const cEventInfo *EventInfo)
stop = time->tm_hour * 100 + time->tm_min;
if (stop >= 2400)
stop -= 2400;
priority = DEFAULTPRIORITY;
lifetime = DEFAULTLIFETIME;
priority = Setup.DefaultPriority;
lifetime = Setup.DefaultLifetime;
*file = 0;
const char *Title = EventInfo->GetTitle();
if (!isempty(Title))
@ -524,14 +524,14 @@ bool cTimer::Matches(time_t t)
}
time_t cTimer::StartTime(void)
{
{
if (!startTime)
Matches();
return startTime;
}
time_t cTimer::StopTime(void)
{
{
if (!stopTime)
Matches();
return stopTime;
@ -734,6 +734,7 @@ cSetup::cSetup(void)
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
MarkInstantRecord = 1;
LnbSLOF = 11700;
LnbFrequLo = 9750;
LnbFrequHi = 10600;
SetSystemTime = 0;
@ -742,6 +743,8 @@ cSetup::cSetup(void)
EPGScanTimeout = 5;
SVDRPTimeout = 300;
PrimaryLimit = 0;
DefaultPriority = 50;
DefaultLifetime = 50;
CurrentChannel = -1;
}
@ -756,6 +759,7 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value);
else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
@ -764,6 +768,8 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
else
return false;
@ -813,6 +819,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
fprintf(f, "LnbSLOF = %d\n", LnbSLOF);
fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
@ -821,6 +828,8 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fprintf(f, "SVDRPTimeout = %d\n", SVDRPTimeout);
fprintf(f, "PrimaryLimit = %d\n", PrimaryLimit);
fprintf(f, "DefaultPriority = %d\n", DefaultPriority);
fprintf(f, "DefaultLifetime = %d\n", DefaultLifetime);
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
f.Close();
isyslog(LOG_INFO, "saved setup to %s", FileName);

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.44 2001/04/01 14:44:40 kls Exp $
* $Id: config.h 1.45 2001/06/02 09:43:04 kls Exp $
*/
#ifndef __CONFIG_H
@ -19,10 +19,13 @@
#include "eit.h"
#include "tools.h"
#define VDRVERSION "0.72"
#define VDRVERSION "0.80"
#define MaxBuffer 10000
#define MAXPRIORITY 99
#define MAXLIFETIME 99
enum eKeys { // "Up" and "Down" must be the first two keys!
kUp,
kDown,
@ -106,9 +109,6 @@ public:
bool Switch(cDvbApi *DvbApi = NULL, bool Log = true);
};
#define DEFAULTPRIORITY 99
#define DEFAULTLIFETIME 99
class cTimer : public cListObject {
private:
time_t startTime, stopTime;
@ -240,7 +240,7 @@ public:
bool SwitchTo(int Number, cDvbApi *DvbApi = NULL);
int MaxNumber(void) { return maxNumber; }
};
class cTimers : public cConfig<cTimer> {
public:
cTimer *GetTimer(cTimer *Timer);
@ -266,6 +266,7 @@ public:
int ShowInfoOnChSwitch;
int MenuScrollPage;
int MarkInstantRecord;
int LnbSLOF;
int LnbFrequLo;
int LnbFrequHi;
int SetSystemTime;
@ -273,6 +274,7 @@ public:
int EPGScanTimeout;
int SVDRPTimeout;
int PrimaryLimit;
int DefaultPriority, DefaultLifetime;
int CurrentChannel;
cSetup(void);
bool Load(const char *FileName);

1422
dvbapi.c

File diff suppressed because it is too large Load Diff

View File

@ -4,22 +4,28 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.h 1.35 2001/02/11 10:41:10 kls Exp $
* $Id: dvbapi.h 1.36 2001/06/02 09:44:00 kls Exp $
*/
#ifndef __DVBAPI_H
#define __DVBAPI_H
// FIXME: these should be defined in ../DVB/driver/dvb.h!!!
typedef unsigned int __u32;
typedef unsigned short __u16;
typedef unsigned char __u8;
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#include <ncurses.h>
#endif
#include <stdlib.h> // FIXME: this is apparently necessary for the ost/... header files
// FIXME: shouldn't every header file include ALL the other header
// FIXME: files it depends on? The sequence in which header files
// FIXME: are included here should not matter - and it should NOT
// FIXME: be necessary to include <stdlib.h> here!
#include <linux/videodev.h>
#include <ost/dmx.h>
#include <ost/sec.h>
#include <ost/frontend.h>
#include <ost/video.h>
#include <ost/audio.h>
#include <ost/osd.h>
#include <stdio.h>
#include <dvb.h>
#include "dvbosd.h"
#include "eit.h"
#include "thread.h"
@ -30,7 +36,7 @@ typedef struct CRect {
signed short x, y, width, height;
};
#define MenuLines 15
#define MenuLines 13 // XXX originally 15, but since driver version 2001-05-25 there is less OSD memory :-(
#define MenuColumns 40
const char *IndexToHMSF(int Index, bool WithFrame = false);
@ -55,9 +61,19 @@ public:
};
class cDvbApi {
friend class cRecordBuffer;
friend class cReplayBuffer;
friend class cTransferBuffer;
private:
int videoDev;
cDvbApi(const char *VideoFileName, const char *VbiFileName);
int fd_osd, fd_qpskfe, fd_qamfe, fd_sec, fd_dvr, fd_audio, fd_video, fd_demuxa, fd_demuxv, fd_demuxt;
int vPid, aPid;
bool SetPid(int fd, dmxPesType_t PesType, dvb_pid_t Pid, dmxOutput_t Output);
bool SetVpid(int Vpid, dmxOutput_t Output) { return SetPid(fd_demuxv, DMX_PES_VIDEO, Vpid, Output); }
bool SetApid(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa, DMX_PES_AUDIO, Apid, Output); }
bool SetTpid(int Tpid, dmxOutput_t Output) { return SetPid(fd_demuxt, DMX_PES_TELETEXT, Tpid, Output); }
bool SetPids(bool ForRecording);
cDvbApi(int n);
public:
~cDvbApi();
@ -86,8 +102,10 @@ public:
// recording and stop recording if necessary.
int Index(void);
// Returns the index of this DvbApi.
static bool Probe(const char *FileName);
// Probes for existing DVB devices.
static bool Init(void);
// Initializes the DVB API and probes for existing DVB devices.
// Initializes the DVB API.
// Must be called before accessing any DVB functions.
static void Cleanup(void);
// Closes down all DVB devices.
@ -184,12 +202,15 @@ private:
cReplayBuffer *replayBuffer;
int ca;
int priority;
protected:
int Ca(void) { return ca; }
// Returns the ca of the current recording session (0..MAXDVBAPI).
int Priority(void) { return priority; }
// Returns the priority of the current recording session (0..99),
// Returns the priority of the current recording session (0..MAXPRIORITY),
// or -1 if no recording is currently active.
int SetModeRecord(void);
// Initiates recording mode and returns the file handle to read from.
void SetModeReplay(void);
void SetModeNormal(bool FromRecording);
public:
int SecondsToFrames(int Seconds);
// Returns the number of frames corresponding to the given number of seconds.
@ -238,7 +259,7 @@ public:
// 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.
// 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.7 2000/12/09 11:13:00 kls Exp $
* $Id: dvbosd.c 1.8 2001/05/26 11:49:35 kls Exp $
*/
#include "dvbosd.h"
@ -157,7 +157,7 @@ cDvbOsd::~cDvbOsd()
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
{
if (videoDev >= 0) {
struct drawcmd dc;
osd_cmd_t dc;
dc.cmd = cmd;
dc.color = color;
dc.x0 = x0;
@ -169,7 +169,7 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
sigset_t set, oldset;
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &oldset);
ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc);
ioctl(videoDev, OSD_SEND_CMD, &dc);
usleep(10); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places
// XXX and sometimes the OSD was no longer displayed).
// XXX Increase the value if the problem still persists on your particular system.

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.5 2000/12/09 10:32:47 kls Exp $
* $Id: dvbosd.h 1.6 2001/05/01 14:41:42 kls Exp $
*/
#ifndef __DVBOSD_H
@ -18,11 +18,11 @@ typedef unsigned char __u8;
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#include <ncurses.h>
#endif
#include <ost/osd.h>
#include <stdio.h>
#include <dvb.h>
#include "font.h"
enum eDvbColor {
enum eDvbColor {
#ifndef DEBUG_OSD
clrTransparent,
#endif

263
eit.c
View File

@ -13,17 +13,16 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.15 2001/04/01 15:36:09 kls Exp $
* $Id: eit.c 1.16 2001/05/26 10:58:01 kls Exp $
***************************************************************************/
#include "eit.h"
#include <ctype.h>
#include <dvb_comcode.h>
#include <dvb_v4l.h>
#include <fcntl.h>
#include <fstream.h>
#include <iomanip.h>
#include <iostream.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -1108,31 +1107,43 @@ cMutex cSIProcessor::schedulesMutex;
/** */
cSIProcessor::cSIProcessor(const char *FileName)
{
fileName = strdup(FileName);
masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
useTStime = false;
filters = NULL;
if ((fsvbi = open(FileName, O_RDONLY)) >= 0)
{
if (!numSIProcessors++) // the first one creates it
schedules = new cSchedules;
filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
}
else
LOG_ERROR_STR(FileName);
if (!numSIProcessors++) // the first one creates it
schedules = new cSchedules;
filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
SetStatus(true);
Start();
}
cSIProcessor::~cSIProcessor()
{
if (fsvbi >= 0)
active = false;
Cancel(3);
ShutDownFilters();
delete filters;
if (!--numSIProcessors) // the last one deletes it
delete schedules;
delete fileName;
}
void cSIProcessor::SetStatus(bool On)
{
LOCK_THREAD;
schedulesMutex.Lock();
ShutDownFilters();
if (On)
{
active = false;
Cancel(3);
ShutDownFilters();
delete filters;
if (!--numSIProcessors) // the last one deletes it
delete schedules;
close(fsvbi);
AddFilter(0x14, 0x70); // TDT
AddFilter(0x14, 0x73); // TOT
AddFilter(0x12, 0x4e); // event info, actual TS, present/following
AddFilter(0x12, 0x4f); // event info, other TS, present/following
AddFilter(0x12, 0x50); // event info, actual TS, schedule
AddFilter(0x12, 0x60); // event info, other TS, schedule
}
schedulesMutex.Unlock();
}
/** use the vbi device to parse all relevant SI
@ -1140,19 +1151,10 @@ information and let the classes corresponding
to the tables write their information to the disk */
void cSIProcessor::Action()
{
if (fsvbi < 0) {
esyslog(LOG_ERR, "cSIProcessor::Action() called without open file - returning");
return;
}
dsyslog(LOG_INFO, "EIT processing thread started (pid=%d)%s", getpid(), masterSIProcessor ? " - master" : "");
unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
unsigned int seclen;
unsigned int pid;
time_t lastCleanup = time(NULL);
time_t lastDump = time(NULL);
struct pollfd pfd;
active = true;
@ -1187,100 +1189,123 @@ void cSIProcessor::Action()
}
}
/* wait data become ready from the bitfilter */
pfd.fd = fsvbi;
pfd.events = POLLIN;
if(poll(&pfd, 1, 1000) != 0) /* timeout is 5 secs */
// set up pfd structures for all active filter
pollfd pfd[MAX_FILTERS];
int NumUsedFilters = 0;
for (int a = 0; a < MAX_FILTERS ; a++)
{
// fprintf(stderr, "<data>\n");
/* read section */
read(fsvbi, buf, 8);
seclen = (buf[6] << 8) | buf[7];
pid = (buf[4] << 8) | buf[5];
read(fsvbi, buf, seclen);
//dsyslog(LOG_INFO, "Received pid 0x%02x with table ID 0x%02x and length of %04d\n", pid, buf[0], seclen);
switch (pid)
if (filters[a].inuse)
{
case 0x14:
if (buf[0] == 0x70)
{
if (useTStime)
{
cTDT ctdt((tdt_t *)buf);
ctdt.SetSystemTime();
}
}
/*XXX this comes pretty often:
else
dsyslog(LOG_INFO, "Time packet was not 0x70 but 0x%02x\n", (int)buf[0]);
XXX*/
break;
case 0x12:
if (buf[0] != 0x72)
{
LOCK_THREAD;
schedulesMutex.Lock();
cEIT ceit(buf, seclen, schedules);
ceit.ProcessEIT();
schedulesMutex.Unlock();
}
else
dsyslog(LOG_INFO, "Received stuffing section in EIT\n");
break;
default:
break;
pfd[NumUsedFilters].fd = filters[a].handle;
pfd[NumUsedFilters].events = POLLIN;
NumUsedFilters++;
}
}
else
{
LOCK_THREAD;
//XXX this comes pretty often
//isyslog(LOG_INFO, "Received timeout from poll, refreshing filters\n");
RefreshFilters();
// wait until data becomes ready from the bitfilter
if (poll(pfd, NumUsedFilters, 1000) != 0)
{
for (int a = 0; a < NumUsedFilters ; a++)
{
if (pfd[a].revents & POLLIN)
{
/* read section */
unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-)
if (read(filters[a].handle, buf, 3) == 3)
{
int seclen = ((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF);
int pid = filters[a].pid;
int n = read(filters[a].handle, buf + 3, seclen);
if (n == seclen)
{
seclen += 3;
//dsyslog(LOG_INFO, "Received pid 0x%02x with table ID 0x%02x and length of %04d\n", pid, buf[0], seclen);
switch (pid)
{
case 0x14:
if (buf[0] == 0x70)
{
if (useTStime)
{
cTDT ctdt((tdt_t *)buf);
ctdt.SetSystemTime();
}
}
/*XXX this comes pretty often:
else
dsyslog(LOG_INFO, "Time packet was not 0x70 but 0x%02x\n", (int)buf[0]);
XXX*/
break;
case 0x12:
if (buf[0] != 0x72)
{
LOCK_THREAD;
schedulesMutex.Lock();
cEIT ceit(buf, seclen, schedules);
ceit.ProcessEIT();
schedulesMutex.Unlock();
}
else
dsyslog(LOG_INFO, "Received stuffing section in EIT\n");
break;
default:
break;
}
}
else
dsyslog(LOG_INFO, "read incomplete section - seclen = %d, n = %d", seclen, n);
}
}
}
}
// WakeUp();
}
dsyslog(LOG_INFO, "EIT processing thread ended (pid=%d)%s", getpid(), masterSIProcessor ? " - master" : "");
}
/** Add a filter with packet identifier pid and
table identifer tid */
bool cSIProcessor::AddFilter(u_char pid, u_char tid)
{
if (fsvbi < 0)
return false;
int section = ((int)tid << 8) | 0x00ff;
struct bitfilter filt = {
pid,
{ section, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
SECTION_CONTINUOS, 0,
FILTER_MEM,
{},
};
if (ioctl(fsvbi, VIDIOCSBITFILTER, &filt) < 0)
return false;
dmxSctFilterParams sctFilterParams;
sctFilterParams.pid = pid;
memset(&sctFilterParams.filter.filter, 0, DMX_FILTER_SIZE);
memset(&sctFilterParams.filter.mask, 0, DMX_FILTER_SIZE);
sctFilterParams.timeout = 0;
sctFilterParams.flags = DMX_IMMEDIATE_START;
sctFilterParams.filter.filter[0] = tid;
sctFilterParams.filter.mask[0] = 0xFF;
for (int a = 0; a < MAX_FILTERS; a++)
{
if (filters[a].inuse == false)
if (!filters[a].inuse)
{
filters[a].pid = pid;
filters[a].tid = tid;
filters[a].handle = filt.handle;
filters[a].inuse = true;
// dsyslog(LOG_INFO, " Registered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
if ((filters[a].handle = open(fileName, O_RDWR | O_NONBLOCK)) >= 0)
{
if (ioctl(filters[a].handle, DMX_SET_FILTER, &sctFilterParams) >= 0)
filters[a].inuse = true;
else
{
esyslog(LOG_ERR, "ERROR: can't set filter");
close(filters[a].handle);
return false;
}
// dsyslog(LOG_INFO, " Registered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
}
else
{
esyslog(LOG_ERR, "ERROR: can't open filter handle");
return false;
}
return true;
}
}
esyslog(LOG_ERR, "ERROR: too many filters");
return false;
}
@ -1294,27 +1319,19 @@ bool cSIProcessor::SetUseTSTime(bool use)
}
/** */
bool cSIProcessor::ShutDownFilters()
bool cSIProcessor::ShutDownFilters(void)
{
if (fsvbi < 0)
return false;
bool ret = true;
for (int a = 0; a < MAX_FILTERS; a++)
{
if (filters[a].inuse == true)
if (filters[a].inuse)
{
if (ioctl(fsvbi, VIDIOCSSHUTDOWNFILTER, &filters[a].handle) < 0)
ret = false;
close(filters[a].handle);
// dsyslog(LOG_INFO, "Deregistered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
filters[a].inuse = false;
}
}
return ret;
return true; // there's no real 'boolean' to return here...
}
/** */
@ -1323,25 +1340,3 @@ bool cSIProcessor::SetCurrentServiceID(unsigned short servid)
LOCK_THREAD;
return schedules ? schedules->SetCurrentServiceID(servid) : false;
}
/** */
bool cSIProcessor::RefreshFilters()
{
if (fsvbi < 0)
return false;
bool ret = true;
ret = ShutDownFilters();
for (int a = 0; a < MAX_FILTERS; a++)
{
if (filters[a].inuse == false && filters[a].pid != 0 && filters[a].tid != 0)
{
if (!AddFilter(filters[a].pid, filters[a].tid))
ret = false;
}
}
return ret;
}

10
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.6 2001/04/01 15:14:12 kls Exp $
* $Id: eit.h 1.7 2001/05/25 12:56:53 kls Exp $
***************************************************************************/
#ifndef __EIT_H
@ -129,16 +129,16 @@ private:
bool masterSIProcessor;
bool useTStime;
SIP_FILTER *filters;
int fsvbi;
char *fileName;
bool active;
bool RefreshFilters(void);
void Action(void);
bool AddFilter(u_char pid, u_char tid);
bool ShutDownFilters(void);
public:
cSIProcessor(const char *FileName);
~cSIProcessor();
void SetStatus(bool On);
bool SetUseTSTime(bool use);
bool AddFilter(u_char pid, u_char tid);
bool ShutDownFilters(void);
bool SetCurrentServiceID(unsigned short servid);
const cSchedules *Schedules(void) { return schedules; }
};

20
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: i18n.c 1.16 2001/03/31 09:58:14 kls Exp $
* $Id: i18n.c 1.17 2001/06/02 09:39:36 kls Exp $
*
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
@ -452,6 +452,12 @@ const tPhrase Phrases[] = {
"Marca la registrazione",
"Direkte opnamen markeren",
},
{ "LnbSLOF",
"LnbSLOF",
"LnbSLOF",
"LnbSLOF",
"LnbSLOF",
},
{ "LnbFrequLo",
"Untere LNB-Frequenz",
"Spodnja LNB-frek.",
@ -500,6 +506,18 @@ const tPhrase Phrases[] = {
"", // TODO
"", // TODO
},
{ "DefaultPriority",
"Default Priorität",
"", // TODO
"", // TODO
"", // TODO
},
{ "DefaultLifetime",
"Default Lebensdauer",
"", // TODO
"", // TODO
"", // TODO
},
// The days of the week:
{ "MTWTFSS",
"MDMDFSS",

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.35 2001/02/18 10:46:13 kls Exp $
* $Id: interface.c 1.36 2001/06/02 09:05:54 kls Exp $
*/
#include "interface.h"
@ -281,9 +281,9 @@ void cInterface::Title(const char *s)
void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
{
ClearEol(0, -3, s ? BgColor : clrBackground);
ClearEol(0, -2, s ? BgColor : clrBackground);
if (s)
Write(0, -3, s, FgColor, BgColor);
Write(0, -2, s, FgColor, BgColor);
}
void cInterface::Info(const char *s)

54
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.70 2001/03/18 10:16:56 kls Exp $
* $Id: menu.c 1.71 2001/06/02 09:59:54 kls Exp $
*/
#include "menu.h"
@ -539,9 +539,9 @@ cMenuEditChannel::cMenuEditChannel(int Index)
Add(new cMenuEditChrItem( tr("Polarization"), &data.polarization, "hv"));
Add(new cMenuEditIntItem( tr("Diseqc"), &data.diseqc, 0, 10)); //TODO exact limits???
Add(new cMenuEditIntItem( tr("Srate"), &data.srate, 22000, 27500)); //TODO exact limits - toggle???
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 10000)); //TODO exact limits???
Add(new cMenuEditIntItem( tr("Apid"), &data.apid, 0, 10000)); //TODO exact limits???
Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 10000)); //TODO exact limits???
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Apid"), &data.apid, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("CA"), &data.ca, 0, cDvbApi::NumDvbApis));
Add(new cMenuEditIntItem( tr("Pnr"), &data.pnr, 0));
}
@ -589,7 +589,7 @@ void cMenuChannelItem::Set(void)
if (!channel->groupSep)
asprintf(&buffer, "%d\t%s", channel->number, channel->name );
else
asprintf(&buffer, "\t%s", channel->name);
asprintf(&buffer, "\t%s", channel->name);
SetText(buffer, false);
}
@ -904,13 +904,13 @@ cMenuEditTimer::cMenuEditTimer(int Index, bool New)
if (New)
data.active = 1;
Add(new cMenuEditBoolItem(tr("Active"), &data.active));
Add(new cMenuEditChanItem(tr("Channel"), &data.channel));
Add(new cMenuEditDayItem( tr("Day"), &data.day));
Add(new cMenuEditTimeItem(tr("Start"), &data.start));
Add(new cMenuEditTimeItem(tr("Stop"), &data.stop));
Add(new cMenuEditChanItem(tr("Channel"), &data.channel));
Add(new cMenuEditDayItem( tr("Day"), &data.day));
Add(new cMenuEditTimeItem(tr("Start"), &data.start));
Add(new cMenuEditTimeItem(tr("Stop"), &data.stop));
//TODO VPS???
Add(new cMenuEditIntItem( tr("Priority"), &data.priority, 0, 99));
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, 99));
Add(new cMenuEditIntItem( tr("Priority"), &data.priority, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME));
Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), FileNameChars));
}
}
@ -963,9 +963,9 @@ void cMenuTimerItem::Set(void)
{
char *buffer = NULL;
asprintf(&buffer, "%c\t%d\t%s\t%02d:%02d\t%02d:%02d\t%s",
timer->active ? '>' : ' ',
timer->channel,
timer->PrintDay(timer->day),
timer->active ? '>' : ' ',
timer->channel,
timer->PrintDay(timer->day),
timer->start / 100,
timer->start % 100,
timer->stop / 100,
@ -1265,7 +1265,7 @@ eOSState cMenuWhatsOn::Switch(void)
eOSState cMenuWhatsOn::Record(void)
{
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
if (item) {
if (item) {
cTimer *timer = new cTimer(item->eventInfo);
cTimer *t = Timers.GetTimer(timer);
if (!t) {
@ -1391,7 +1391,7 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
eOSState cMenuSchedule::Record(void)
{
cMenuScheduleItem *item = (cMenuScheduleItem *)Get(Current());
if (item) {
if (item) {
cTimer *timer = new cTimer(item->eventInfo);
cTimer *t = Timers.GetTimer(timer);
if (!t) {
@ -1608,6 +1608,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("ShowInfoOnChSwitch"), &data.ShowInfoOnChSwitch));
Add(new cMenuEditBoolItem(tr("MenuScrollPage"), &data.MenuScrollPage));
Add(new cMenuEditBoolItem(tr("MarkInstantRecord"), &data.MarkInstantRecord));
Add(new cMenuEditIntItem( tr("LnbSLOF"), &data.LnbSLOF));
Add(new cMenuEditIntItem( tr("LnbFrequLo"), &data.LnbFrequLo));
Add(new cMenuEditIntItem( tr("LnbFrequHi"), &data.LnbFrequHi));
Add(new cMenuEditBoolItem(tr("SetSystemTime"), &data.SetSystemTime));
@ -1615,7 +1616,9 @@ void cMenuSetup::Set(void)
Add(new cMenuEditIntItem( tr("MarginStop"), &data.MarginStop));
Add(new cMenuEditIntItem( tr("EPGScanTimeout"), &data.EPGScanTimeout));
Add(new cMenuEditIntItem( tr("SVDRPTimeout"), &data.SVDRPTimeout));
Add(new cMenuEditIntItem( tr("PrimaryLimit"), &data.PrimaryLimit));
Add(new cMenuEditIntItem( tr("PrimaryLimit"), &data.PrimaryLimit, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("DefaultPriority"), &data.DefaultPriority, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("DefaultLifetime"), &data.DefaultLifetime, 0, MAXLIFETIME));
}
eOSState cMenuSetup::ProcessKey(eKeys Key)
@ -1945,11 +1948,14 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
asprintf(&instantId, cDvbApi::NumDvbApis > 1 ? "%s - %d" : "%s", Channels.GetChannelNameByNumber(timer->channel), dvbApi->Index() + 1);
}
timer->SetRecording(true);
Channels.SwitchTo(timer->channel, dvbApi);
cRecording Recording(timer);
if (dvbApi->StartRecord(Recording.FileName(), Channels.GetByNumber(timer->channel)->ca, timer->priority))
Recording.WriteSummary();
Interface->DisplayRecording(dvbApi->Index(), true);
if (Channels.SwitchTo(timer->channel, dvbApi)) {
cRecording Recording(timer);
if (dvbApi->StartRecord(Recording.FileName(), Channels.GetByNumber(timer->channel)->ca, timer->priority))
Recording.WriteSummary();
Interface->DisplayRecording(dvbApi->Index(), true);
}
else
cThread::EmergencyExit(true);
}
cRecordControl::~cRecordControl()
@ -1979,7 +1985,7 @@ bool cRecordControl::Process(void)
{
if (!timer || !timer->Matches())
return false;
AssertFreeDiskSpace();
AssertFreeDiskSpace(timer->priority);
return true;
}
@ -1993,7 +1999,7 @@ bool cRecordControls::Start(cTimer *Timer)
cChannel *channel = Channels.GetByNumber(ch);
if (channel) {
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca, Timer ? Timer->priority : DEFAULTPRIORITY);
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca, Timer ? Timer->priority : Setup.DefaultPriority);
if (dvbApi) {
Stop(dvbApi);
for (int i = 0; i < MAXDVBAPI; i++) {

4
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.20 2001/02/03 15:13:59 kls Exp $
* $Id: osd.h 1.21 2001/06/02 09:04:19 kls Exp $
*/
#ifndef __OSD_H
@ -14,7 +14,7 @@
#include "interface.h"
#include "tools.h"
#define MAXOSDITEMS 9
#define MAXOSDITEMS (MenuLines - 4)
enum eOSState { osUnknown,
osMenu,

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.29 2001/03/31 09:38:30 kls Exp $
* $Id: recording.c 1.30 2001/06/02 10:07:01 kls Exp $
*/
#define _GNU_SOURCE
@ -39,7 +39,7 @@
#define DELETEDLIFETIME 1 // hours after which a deleted recording will be actually removed
#define REMOVECHECKDELTA 3600 // seconds between checks for removing deleted files
#define DISKCHECKDELTA 300 // seconds between checks for free disk space
#define REMOVELATENCY 10 // seconds to wait until next check after removing a file
#define REMOVELATENCY 10 // seconds to wait until next check after removing a file
void RemoveDeletedRecordings(void)
{
@ -66,7 +66,7 @@ void RemoveDeletedRecordings(void)
}
}
void AssertFreeDiskSpace(void)
void AssertFreeDiskSpace(int Priority)
{
// With every call to this function we try to actually remove
// a file, or mark a file for removal ("delete" it), so that
@ -94,10 +94,13 @@ void AssertFreeDiskSpace(void)
cRecording *r = Recordings.First();
cRecording *r0 = NULL;
while (r) {
if ((time(NULL) - r->start) / SECSINDAY > r->lifetime) {
if (r->lifetime == MAXLIFETIME)
continue; // recordings with MAXLIFETIME live forever
if ((r->lifetime == 0 && Priority > r->priority) || // the recording has guaranteed lifetime and the new recording has higher priority
(time(NULL) - r->start) / SECSINDAY > r->lifetime) { // the recording's guaranteed lifetime has expired
if (r0) {
if (r->priority < r0->priority)
r0 = r;
if (r->priority < r0->priority || (r->priority == r0->priority && r->start < r0->start))
r0 = r; // in any case we delete the one with the lowest priority (or the older one in case of equal priorities)
}
else
r0 = r;
@ -153,7 +156,7 @@ int cResumeFile::Read(void)
bool cResumeFile::Save(int Index)
{
if (fileName) {
int f = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
int f = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (f >= 0) {
if (write(f, &Index, sizeof(Index)) != sizeof(Index))
LOG_ERROR_STR(fileName);
@ -183,7 +186,7 @@ cRecording::cRecording(cTimer *Timer)
for (char *p = name; *p; p++) {
switch (*p) {
case '\n': *p = ' '; break;
case '/': *p = '-'; break;
case '/': *p = '-'; break;
}
}
summary = Timer->summary ? strdup(Timer->summary) : NULL;
@ -239,7 +242,7 @@ cRecording::cRecording(const char *FileName)
delete summary;
summary = NULL;
}
}
else
esyslog(LOG_ERR, "can't allocate %d byte of memory for summary file '%s'", size + 1, SummaryFileName);

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.13 2001/02/11 10:45:52 kls Exp $
* $Id: recording.h 1.14 2001/06/02 10:00:25 kls Exp $
*/
#ifndef __RECORDING_H
@ -15,7 +15,7 @@
#include "tools.h"
void RemoveDeletedRecordings(void);
void AssertFreeDiskSpace(void);
void AssertFreeDiskSpace(int Priority);
class cResumeFile {
private:

499
remux.c
View File

@ -4,7 +4,11 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.c 1.1 2001/03/31 08:42:17 kls Exp $
* The parts of this code that implement cTS2PES have been taken from
* the Linux DVB driver's 'tuxplayer' example and were rewritten to suit
* VDR's needs.
*
* $Id: remux.c 1.2 2001/05/27 10:27:15 kls Exp $
*/
/* The calling interface of the 'cRemux::Process()' function is defined
@ -62,17 +66,364 @@
*/
#include "remux.h"
#include "thread.h"
#include "tools.h"
#if defined(REMUX_NONE)
// --- cTS2PES ---------------------------------------------------------------
cRemux::cRemux(void)
#include <netinet/in.h>
//XXX TODO: these should really be available in some driver header file!
#define PROG_STREAM_MAP 0xBC
#ifndef PRIVATE_STREAM1
#define PRIVATE_STREAM1 0xBD
#endif
#define PADDING_STREAM 0xBE
#ifndef PRIVATE_STREAM2
#define PRIVATE_STREAM2 0xBF
#endif
#define AUDIO_STREAM_S 0xC0
#define AUDIO_STREAM_E 0xDF
#define VIDEO_STREAM_S 0xE0
#define VIDEO_STREAM_E 0xEF
#define ECM_STREAM 0xF0
#define EMM_STREAM 0xF1
#define DSM_CC_STREAM 0xF2
#define ISO13522_STREAM 0xF3
#define PROG_STREAM_DIR 0xFF
//pts_dts flags
#define PTS_ONLY 0x80
#define TS_SIZE 188
#define PAY_START 0x40
#define PID_MASK_HI 0x1F
//flags
#define ADAPT_FIELD 0x20
//XXX TODO
#define MAX_PLENGTH 0xFFFF
#define MMAX_PLENGTH (4*MAX_PLENGTH)
#define IPACKS 2048
class cTS2PES {
private:
int size;
int found;
int count;
uint8_t *buf;
uint8_t cid;
int plength;
uint8_t plen[2];
uint8_t flag1;
uint8_t flag2;
uint8_t hlength;
int mpeg;
uint8_t check;
int which;
bool done;
uint8_t *resultBuffer;
int *resultCount;
static uint8_t headr[];
void store(uint8_t *Data, int Count);
void reset_ipack(void);
void send_ipack(void);
void write_ipack(const uint8_t *Data, int Count);
void instant_repack(const uint8_t *Buf, int Count);
public:
cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size);
~cTS2PES();
void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
};
uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 };
cTS2PES::cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size)
{
resultBuffer = ResultBuffer;
resultCount = ResultCount;
size = Size;
if (!(buf = new uint8_t[size]))
esyslog(LOG_ERR, "Not enough memory for ts_transform");
reset_ipack();
}
cTS2PES::~cTS2PES()
{
delete buf;
}
void cTS2PES::store(uint8_t *Data, int Count)
{
//XXX overflow check???
memcpy(resultBuffer + *resultCount, Data, Count);
*resultCount += Count;
}
void cTS2PES::reset_ipack(void)
{
found = 0;
cid = 0;
plength = 0;
flag1 = 0;
flag2 = 0;
hlength = 0;
mpeg = 0;
check = 0;
which = 0;
done = false;
count = 0;
}
void cTS2PES::send_ipack(void)
{
if (count < 10)
return;
buf[3] = cid;
buf[4] = (uint8_t)(((count - 6) & 0xFF00) >> 8);
buf[5] = (uint8_t)((count - 6) & 0x00FF);
store(buf, count);
switch (mpeg) {
case 2:
buf[6] = 0x80;
buf[7] = 0x00;
buf[8] = 0x00;
count = 9;
break;
case 1:
buf[6] = 0x0F;
count = 7;
break;
}
}
void cTS2PES::write_ipack(const uint8_t *Data, int Count)
{
if (count < 6) {
memcpy(buf, headr, 3);
count = 6;
}
if (count + Count < size) {
memcpy(buf + count, Data, Count);
count += Count;
}
else {
int rest = size - count;
memcpy(buf + count, Data, rest);
count += rest;
send_ipack();
if (Count - rest > 0)
write_ipack(Data + rest, Count - rest);
}
}
void cTS2PES::instant_repack(const uint8_t *Buf, int Count)
{
int c = 0;
while (c < Count && (mpeg == 0 || (mpeg == 1 && found < 7) || (mpeg == 2 && found < 9)) && (found < 5 || !done)) {
switch (found ) {
case 0:
case 1:
if (Buf[c] == 0x00)
found++;
else
found = 0;
c++;
break;
case 2:
if (Buf[c] == 0x01)
found++;
else if (Buf[c] != 0)
found = 0;
c++;
break;
case 3:
cid = 0;
switch (Buf[c]) {
case PROG_STREAM_MAP:
case PRIVATE_STREAM2:
case PROG_STREAM_DIR:
case ECM_STREAM :
case EMM_STREAM :
case PADDING_STREAM :
case DSM_CC_STREAM :
case ISO13522_STREAM:
done = true;
case PRIVATE_STREAM1:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
found++;
cid = Buf[c++];
break;
default:
found = 0;
break;
}
break;
case 4:
if (Count - c > 1) {
unsigned short *pl = (unsigned short *)(Buf + c);
plength = ntohs(*pl);
c += 2;
found += 2;
}
else {
plen[0] = Buf[c];
found++;
return;
}
break;
case 5: {
plen[1] = Buf[c++];
unsigned short *pl = (unsigned short *)plen;
plength = ntohs(*pl);
found++;
}
break;
case 6:
if (!done) {
flag1 = Buf[c++];
found++;
if ((flag1 & 0xC0) == 0x80 )
mpeg = 2;
else {
esyslog(LOG_INFO, "ERROR: can't record MPEG1!");
hlength = 0;
which = 0;
mpeg = 1;
flag2 = 0;
}
}
break;
case 7:
if (!done && mpeg == 2) {
flag2 = Buf[c++];
found++;
}
break;
case 8:
if (!done && mpeg == 2) {
hlength = Buf[c++];
found++;
}
break;
default:
break;
}
}
if (!plength)
plength = MMAX_PLENGTH - 6;
if (done || ((mpeg == 2 && found >= 9) || (mpeg == 1 && found >= 7))) {
switch (cid) {
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case PRIVATE_STREAM1:
if (mpeg == 2 && found == 9) {
write_ipack(&flag1, 1);
write_ipack(&flag2, 1);
write_ipack(&hlength, 1);
}
if (mpeg == 2 && (flag2 & PTS_ONLY) && found < 14) {
while (c < Count && found < 14) {
write_ipack(Buf + c, 1);
c++;
found++;
}
if (c == Count)
return;
}
while (c < Count && found < plength + 6) {
int l = Count - c;
if (l + found > plength + 6)
l = plength + 6 - found;
write_ipack(Buf + c, l);
found += l;
c += l;
}
break;
}
if (done) {
if (found + Count - c < plength + 6) {
found += Count - c;
c = Count;
}
else {
c += plength + 6 - found;
found = plength + 6;
}
}
if (plength && found == plength + 6) {
send_ipack();
reset_ipack();
if (c < Count)
instant_repack(Buf + c, Count - c);
}
}
return;
}
void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
{
if (!Buf)
return;
if (Buf[1] & PAY_START) {
if (plength == MMAX_PLENGTH - 6 && found > 6) {
plength = found - 6;
found = 0;
send_ipack();
reset_ipack();
}
}
uint8_t off = 0;
if (Buf[3] & ADAPT_FIELD) { // adaptation field?
off = Buf[4] + 1;
if (off + 4 > 187)
return;
}
instant_repack(Buf + 4 + off, TS_SIZE - 4 - off);
}
// --- cRemux ----------------------------------------------------------------
cRemux::cRemux(dvb_pid_t VPid, dvb_pid_t APid, bool ExitOnFailure)
{
vPid = VPid;
aPid = APid;
exitOnFailure = ExitOnFailure;
synced = false;
skipped = 0;
resultCount = resultDelivered = 0;
vTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS);
aTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS);
}
cRemux::~cRemux()
{
delete vTS2PES;
delete aTS2PES;
}
int cRemux::GetPid(const uchar *Data)
{
return (((uint16_t)Data[0] & PID_MASK_HI) << 8) | (Data[1] & 0xFF);
}
int cRemux::GetPacketLength(const uchar *Data, int Count, int Offset)
@ -104,70 +455,130 @@ int cRemux::ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &Pic
return -1;
}
const uchar *cRemux::Process(const uchar *Data, int &Count, int &Result, uchar &PictureType)
const uchar *cRemux::Process(const uchar *Data, int &Count, int &Result, uchar *PictureType)
{
int Skip = 0;
uchar dummyPictureType;
if (!PictureType)
PictureType = &dummyPictureType;
PictureType = NO_PICTURE;
/*XXX
// test recording the raw TS:
Result = Count;
*PictureType = I_FRAME;
return Data;
XXX*/
if (Count >= MINVIDEODATA) {
for (int i = 0; i < Count; i++) {
if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1) {
switch (Data[i + 3]) {
// Remove any previously delivered data from the result buffer:
if (resultDelivered) {
if (resultDelivered < resultCount)
memmove(resultBuffer, resultBuffer + resultDelivered, resultCount - resultDelivered);
resultCount -= resultDelivered;
resultDelivered = 0;
}
// Convert incoming TS data into multiplexed PES:
int used = 0;
for (int i = 0; i < Count; i += TS_SIZE) {
if (Count - i < TS_SIZE)
break;
dvb_pid_t pid = GetPid(Data + i + 1);
if (Data[i + 3] & 0x10) { // got payload
if (pid == vPid)
vTS2PES->ts_to_pes(Data + i);
else if (pid == aPid)
aTS2PES->ts_to_pes(Data + i);
}
used += TS_SIZE;
if (resultCount > (int)sizeof(resultBuffer) / 2)
break;
}
Count = used;
/*XXX
// test recording without determining the real frame borders:
*PictureType = I_FRAME;
Result = resultDelivered = resultCount;
return Result ? resultBuffer : NULL;
XXX*/
// Check if we're getting anywhere here:
if (!synced && skipped >= 0) {
if (skipped > 1024*1024) {
esyslog(LOG_ERR, "ERROR: no useful data seen within %d byte of video stream", skipped);
skipped = -1;
if (exitOnFailure)
cThread::EmergencyExit(true);
}
else
skipped += Count;
}
// Check for frame borders:
*PictureType = NO_PICTURE;
if (resultCount >= MINVIDEODATA) {
for (int i = 0; i < resultCount; i++) {
if (resultBuffer[i] == 0 && resultBuffer[i + 1] == 0 && resultBuffer[i + 2] == 1) {
switch (resultBuffer[i + 3]) {
case SC_VIDEO:
{
uchar pt = NO_PICTURE;
int l = ScanVideoPacket(Data, Count, i, pt);
if (l < 0) {
if (Skip < Count)
Count = Skip;
int l = ScanVideoPacket(resultBuffer, resultCount, i, pt);
if (l < 0)
return NULL; // no useful data found, wait for more
}
if (pt != NO_PICTURE) {
if (pt < I_FRAME || B_FRAME < pt) {
esyslog(LOG_ERR, "ERROR: unknown picture type '%d'", pt);
}
else if (PictureType == NO_PICTURE) {
if (!synced) {
if (pt == I_FRAME) {
Skip = i;
synced = true;
}
else {
i += l;
Skip = i;
break;
}
else if (!synced) {
if (pt == I_FRAME) {
resultDelivered = i; // will drop everything before this position
synced = true;
}
else {
resultDelivered = i + l; // will drop everything before and including this packet
return NULL;
}
if (synced)
PictureType = pt;
}
else {
Count = i;
Result = i - Skip;
return Data + Skip;
}
}
else if (!synced) {
i += l;
Skip = i;
break;
if (synced) {
*PictureType = pt;
Result = l;
const uchar *p = resultBuffer + resultDelivered;
resultDelivered += l;
return p;
}
else {
resultDelivered = i + l; // will drop everything before and including this packet
return NULL;
}
i += l - 1; // -1 to compensate for i++ in the loop!
}
break;
case SC_AUDIO:
i += GetPacketLength(Data, Count, i) - 1; // -1 to compensate for i++ in the loop!
{
int l = GetPacketLength(resultBuffer, resultCount, i);
if (l < 0)
return NULL; // no useful data found, wait for more
if (synced) {
Result = l;
const uchar *p = resultBuffer + resultDelivered;
resultDelivered += l;
return p;
}
else {
resultDelivered = i + l; // will drop everything before and including this packet
return NULL;
}
}
break;
}
}
}
}
if (Skip < Count)
Count = Skip;
return NULL; // no useful data found, wait for more
}
#elif defined(REMUX_TEST)
#endif

27
remux.h
View File

@ -4,16 +4,14 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.h 1.1 2001/03/31 08:42:27 kls Exp $
* $Id: remux.h 1.2 2001/05/26 11:50:52 kls Exp $
*/
#ifndef __REMUX_H
#define __REMUX_H
// There are various experiments with different types of remultiplexers
// going on at the moment. Select the remultiplexer here:
#define REMUX_NONE 1
//#define REMUX_TEST 1
#include <time.h> //XXX FIXME: DVB/ost/include/ost/dmx.h should include <time.h> itself!!!
#include <ost/dmx.h>
// Picture types:
#define NO_PICTURE 0
@ -21,6 +19,7 @@
#define P_FRAME 2
#define B_FRAME 3
//XXX -> remux.c???
// Start codes:
#define SC_PICTURE 0x00 // "picture header"
#define SC_SEQU 0xB3 // "sequence header"
@ -30,22 +29,28 @@
#define SC_VIDEO 0xE0
// The minimum amount of video data necessary to identify frames:
#define MINVIDEODATA (256*1024) // just a safe guess (max. size of any frame block, plus some safety)
#define MINVIDEODATA (16*1024) // just a safe guess (max. size of any frame block, plus some safety)
typedef unsigned char uchar;
class cTS2PES;
class cRemux {
private:
#if defined(REMUX_NONE)
bool exitOnFailure;
bool synced;
int skipped;
dvb_pid_t vPid, aPid;
cTS2PES *vTS2PES, *aTS2PES;
uchar resultBuffer[MINVIDEODATA * 4];//XXX
int resultCount;
int resultDelivered;
int GetPid(const uchar *Data);
int GetPacketLength(const uchar *Data, int Count, int Offset);
int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
#elif defined(REMUX_TEST)
#endif
public:
cRemux(void);
cRemux(dvb_pid_t VPid, dvb_pid_t APid, bool ExitOnFailure = false);
~cRemux();
const uchar *Process(const uchar *Data, int &Count, int &Result, uchar &PictureType);
const uchar *Process(const uchar *Data, int &Count, int &Result, uchar *PictureType = NULL);
};
#endif // __REMUX_H

View File

@ -7,7 +7,7 @@
* Parts of this file were inspired by the 'ringbuffy.c' from the
* LinuxDVB driver (see linuxtv.org).
*
* $Id: ringbuffer.c 1.1 2001/03/18 16:47:00 kls Exp $
* $Id: ringbuffer.c 1.2 2001/05/20 11:58:08 kls Exp $
*/
#include "ringbuffer.h"
@ -37,9 +37,10 @@ public:
// --- cRingBuffer ------------------------------------------------------------
cRingBuffer::cRingBuffer(int Size)
cRingBuffer::cRingBuffer(int Size, bool Statistics)
{
size = Size;
statistics = Statistics;
buffer = NULL;
inputThread = NULL;
outputThread = NULL;
@ -60,7 +61,17 @@ cRingBuffer::~cRingBuffer()
delete inputThread;
delete outputThread;
delete buffer;
dsyslog(LOG_INFO, "buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1));
if (statistics)
dsyslog(LOG_INFO, "buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1));
}
int cRingBuffer::Available(void)
{
mutex.Lock();
int diff = head - tail;
int cont = (diff >= 0) ? diff : size + diff;
mutex.Unlock();
return cont;
}
void cRingBuffer::Clear(void)
@ -78,17 +89,17 @@ int cRingBuffer::Put(const uchar *Data, int Count)
int diff = tail - head;
mutex.Unlock();
int free = (diff > 0) ? diff - 1 : size + diff - 1;
// Statistics:
int fill = size - free - 1 + Count;
if (fill >= size)
fill = size - 1;
if (fill > maxFill) {
maxFill = fill;
int percent = maxFill * 100 / (size - 1);
if (percent > 75)
dsyslog(LOG_INFO, "buffer usage: %d%%", percent);
if (statistics) {
int fill = size - free - 1 + Count;
if (fill >= size)
fill = size - 1;
if (fill > maxFill) {
maxFill = fill;
int percent = maxFill * 100 / (size - 1);
if (percent > 75)
dsyslog(LOG_INFO, "buffer usage: %d%%", percent);
}
}
//
if (free <= 0)
return 0;
if (free < Count)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: ringbuffer.h 1.1 2001/03/18 16:47:00 kls Exp $
* $Id: ringbuffer.h 1.2 2001/05/20 11:56:44 kls Exp $
*/
#ifndef __RINGBUFFER_H
@ -28,7 +28,11 @@ private:
uchar *buffer;
int maxFill;
bool busy;
bool statistics;
protected:
void Lock(void) { mutex.Lock(); }
void Unlock(void) { mutex.Unlock(); }
int Available(void);
bool Busy(void) { return busy; }
void Clear(void);
// Immediately clears the ring buffer.
@ -45,7 +49,7 @@ protected:
// Runs as a separate thread and shall continuously call Get() to
// retrieve data from the ring buffer and write it to a destination.
public:
cRingBuffer(int Size);
cRingBuffer(int Size, bool Statistics = false);
virtual ~cRingBuffer();
bool Start(void);
bool Active(void);

32
runvdr
View File

@ -1,18 +1,40 @@
#!/bin/sh
# runvdr: Loads the DVB driver and runs VDR
#
# If VDR exits abnormally, the driver will be reloaded
# and VDR restarted.
#
# Set the environment variable VDRUSR to the user id you
# want VDR to run with. If VDRUSR is not set, VDR will run
# as 'root', which is not necessarily advisable.
#
# Since this script loads the DVB driver, it must be started
# as user 'root'.
#
# Any command line parameters will be passed on to the
# actual 'vdr' program.
#
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: runvdr 1.5 2001/06/01 16:23:29 kls Exp $
DVBDIR="../DVB/driver"
VDRPRG="./vdr"
VDRCMD="$VDRPRG -w 60"
VDRCMD="$VDRPRG -w 60 $*"
KILLPROC="/sbin/killproc -TERM"
(cd $DVBDIR; make insmod)
while (true) do
# (cd $DVBDIR; make reload)
# sleep 3
$VDRCMD
if test $? -ne 1; then exit; fi
su -c "$VDRCMD" $VDRUSR
if test $? -eq 0; then exit; fi
date
echo "restarting VDR"
$KILLPROC $VDRPRG
sleep 10
(cd $DVBDIR; make reload)
date
done

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.c 1.7 2000/12/24 12:27:21 kls Exp $
* $Id: thread.c 1.8 2001/05/25 09:37:00 kls Exp $
*/
#include "thread.h"
@ -14,12 +14,41 @@
#include <unistd.h>
#include "tools.h"
// --- cMutex ----------------------------------------------------------------
cMutex::cMutex(void)
{
lockingPid = 0;
locked = 0;
pthread_mutex_init(&mutex, NULL);
}
cMutex::~cMutex()
{
pthread_mutex_destroy(&mutex);
}
void cMutex::Lock(void)
{
if (getpid() != lockingPid || !locked)
pthread_mutex_lock(&mutex);
lockingPid = getpid();
locked++;
}
void cMutex::Unlock(void)
{
if (!--locked)
pthread_mutex_unlock(&mutex);
}
// --- cThread ---------------------------------------------------------------
// The signal handler is necessary to be able to use SIGIO to wake up any
// pending 'select()' call.
bool cThread::signalHandlerInstalled = false;
bool cThread::emergencyExitRequested = false;
cThread::cThread(void)
{
@ -110,6 +139,14 @@ void cThread::WakeUp(void)
kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
}
bool cThread::EmergencyExit(bool Request)
{
if (!Request)
return emergencyExitRequested;
esyslog(LOG_ERR, "initiating emergency exit");
return emergencyExitRequested = true; // yes, it's an assignment, not a comparison!
}
// --- cThreadLock -----------------------------------------------------------
cThreadLock::cThreadLock(cThread *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.4 2000/12/03 11:18:37 kls Exp $
* $Id: thread.h 1.5 2001/05/25 09:36:27 kls Exp $
*/
#ifndef __THREAD_H
@ -16,11 +16,13 @@
class cMutex {
private:
pthread_mutex_t mutex;
pid_t lockingPid;
int locked;
public:
cMutex(void) { pthread_mutex_init(&mutex, NULL); }
~cMutex() { pthread_mutex_destroy(&mutex); }
void Lock(void) { pthread_mutex_lock(&mutex); }
void Unlock(void) { pthread_mutex_unlock(&mutex); }
cMutex(void);
~cMutex();
void Lock(void);
void Unlock(void);
};
class cThread {
@ -31,6 +33,7 @@ private:
pid_t parentPid, threadPid, lockingPid;
int locked;
bool running;
static bool emergencyExitRequested;
static bool signalHandlerInstalled;
static void SignalHandler(int signum);
static void *StartThread(cThread *Thread);
@ -45,6 +48,7 @@ public:
virtual ~cThread();
bool Start(void);
bool Active(void);
static bool EmergencyExit(bool Request = false);
};
// cThreadLock can be used to easily set a lock in a thread and make absolutely

18
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.33 2001/04/22 10:31:29 kls Exp $
* $Id: tools.c 1.34 2001/05/20 08:30:54 kls Exp $
*/
#define _GNU_SOURCE
@ -411,6 +411,22 @@ bool cFile::FileReady(int FileDes, int TimeoutMs)
return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set);
}
bool cFile::FileReadyForWriting(int FileDes, int TimeoutMs)
{
#ifdef DEBUG_OSD
refresh();
#endif
fd_set set;
struct timeval timeout;
FD_ZERO(&set);
FD_SET(FileDes, &set);
if (TimeoutMs < 100)
TimeoutMs = 100;
timeout.tv_sec = 0;
timeout.tv_usec = TimeoutMs * 1000;
return select(FD_SETSIZE, NULL, &set, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set);
}
// --- cSafeFile -------------------------------------------------------------
cSafeFile::cSafeFile(const char *FileName)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 1.25 2001/04/01 14:13:42 kls Exp $
* $Id: tools.h 1.26 2001/05/20 08:29:45 kls Exp $
*/
#ifndef __TOOLS_H
@ -67,6 +67,7 @@ public:
bool Ready(bool Wait = true);
static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000);
static bool FileReady(int FileDes, int TimeoutMs = 1000);
static bool FileReadyForWriting(int FileDes, int TimeoutMs = 1000);
};
class cSafeFile {

14
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.56 2001/04/01 11:16:54 kls Exp $
* $Id: vdr.c 1.57 2001/05/25 09:31:09 kls Exp $
*/
#include <getopt.h>
@ -267,6 +267,11 @@ int main(int argc, char *argv[])
}
while (!Interrupted) {
// Handle emergency exits:
if (cThread::EmergencyExit()) {
esyslog(LOG_ERR, "emergency exit requested - shutting down");
break;
}
// Restart the Watchdog timer:
if (WatchdogTimeout > 0) {
int LatencyTime = WatchdogTimeout - alarm(WatchdogTimeout);
@ -388,7 +393,8 @@ int main(int argc, char *argv[])
else
LastActivity = time(NULL);
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
if (Interrupted)
isyslog(LOG_INFO, "caught signal %d", Interrupted);
Setup.CurrentChannel = cDvbApi::CurrentChannel();
Setup.Save();
cVideoCutter::Stop();
@ -401,5 +407,9 @@ int main(int argc, char *argv[])
isyslog(LOG_INFO, "exiting");
if (SysLogLevel > 0)
closelog();
if (cThread::EmergencyExit()) {
esyslog(LOG_ERR, "emergency exit!");
return 1;
}
return 0;
}

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.4 2001/02/11 13:48:30 kls Exp $
* $Id: videodir.c 1.5 2001/05/01 09:48:57 kls Exp $
*/
#include "videodir.h"
@ -137,7 +137,7 @@ int OpenVideoFile(const char *FileName, int Flags)
}
}
}
int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR | S_IRGRP);
int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (ActualFileName != FileName)
delete ActualFileName;
return Result;