Version 0.85

- Added Norwegian language texts (thanks to Jrgen Tvedt).
- Increased the usleep value in cDvbOsd::Cmd() to 5000 in order to work on
  systems with the KURT/utime-patch (thanks to Guido Fiala).
- Changed the check whether the driver is loaded in runvdr to check for the
  'dvb' module (the last one loaded).
- Fixed repeat function with LIRC (thanks to Stefan Huelswitt).
- Increased the upper limit for the symbol rate to 30000 (thanks to Ulrich
  Rder).
- Made the position of the channel display configurable (thanks to Stefan
  Huelswitt).
- Made the width and height of the OSD configurable (thanks to Stefan Huelswitt).
- DiSEqC support can now be generally enabled/disabled in the Setup menu. This
  may be necessary if your multiswitch gets irritated by the default DiSEqC
  codes '0' (thanks to Markus Lang).
- Fixed replaying in case there is no index file.
- Fixed jumping to an editing mark when replay has been paused.
- Avoiding unnecessary code execution in the replay progress display (thanks
  to Guido Fiala).
- When entering time values the digits that still have to be entered are now
  shown as '-' (as in "1-:--").
- When setting an editing mark while the progress display is not active, the
  display will now be turned on for a short while to indicate the successful
  setting of the mark.
- Updated 'channels.conf' for Premiere World (thanks to Helmut Schchner).
  Check your timers if you use this channels.conf file, since the sequence of
  several PW channels has been changed.
- Changed the color of "Info" messages to "black on green" and that of the
  confirmation messages (like "Delete...") to "black on yellow".
- Fixed display with DEBUG_OSD (it still crashes sometimes, esp. when replaying,
  but I can't seem to find what causes this... any ideas anybody?).
- Avoiding audio/video distortions in 'Transfer Mode' by no longer actually
  tuning the primary interface (which can't receive this channel, anyway).
  Apparently the driver gets irritated when the channel is switched and a
  replay session is started immediately after that.
- Increased timeout until reporting "video data stream broken" when recording.
- Explicitly switching back to the previously active channel after ending a
  replay session (to have it shown correctly in case it was in 'Transfer Mode').
This commit is contained in:
Klaus Schmidinger 2001-07-29 18:00:00 +02:00
parent 610c5600df
commit 8f9cc68f76
49 changed files with 3437 additions and 1377 deletions

View File

@ -23,6 +23,7 @@ Guido Fiala <gfiala@s.netic.de>
for implementing the SVDRP command 'HITK'
for implementing image grabbing
for implementing overlay capabilities (see his 'kvdr' tool at http://www.s.netic.de/gfiala)
for making the replay progress display avoid unnecessary code execution
Robert Schneider <Robert.Schneider@lotus.com>
for implementing EIT support for displaying the current/next info
@ -42,6 +43,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 +56,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 +73,36 @@ 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
Henning Holtschneider <hh@holtschneider.com>
for patching 'runvdr' to check whether the driver is already loaded
Paulo Manuel Martins Lopes <pmml@netvita.pt>
for translating the OSD texts to the Portugese language
Markus Lang <markus.lang@nissan-db.de> and Ulrich Röder <dynamite@efr-net.de>
for making DiSEqC support configurable
Jean-Claude Repetto <jc@repetto.org>
for translating the OSD texts to the French language
Andre Valentin <av2000@topmail.de>
for increasing the key name buffer size for LIRC
Jørgen Tvedt <pjtvedt@online.no>
for translating the OSD texts to the Norwegian language
Stefan Huelswitt <huels@iname.com>
for fixing the repeat function with LIRC
for making the position of the channel display configurable
for making the width and height of the OSD configurable
Ulrich Röder <dynamite@efr-net.de>
for pointing out that there are channels that have a symbol rate higher than
27500.
Helmut Schächner <schaechner@yahoo.com>
for his support in keeping the Premiere World channels up to date in 'channels.conf'

22
FORMATS
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):
@ -25,7 +25,9 @@ Video Disk Recorder File Formats
- Diseqc number **
- Symbol rate
- Video PID
- Audio PID
- Audio PID (either one number, or two, separated by a comma)
If this channel also carries Dolby Digital sound, the Dolby PIDs follow
the audio PIDs, separated by a semicolon, as in "...:101,102;103,104:..."
- Teletext PID
- Conditional Access (0 = Free To Air, 1 = can be decrypted by the first
DVB card, 2 = can be decrypted by the second DVB card)
@ -60,8 +62,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 '|';
@ -126,3 +130,13 @@ Video Disk Recorder File Formats
- 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).
* 001.vdr ... 255.vdr
These are the actual recorded MPEG data files. In order to keep the size of
an individual file below a given limit, a recording is split into several
files. The contents of these files is "Packetized Elementary Stream" (PES)
and contains ES packets with ids 0xE0 for video, 0xC0 for audio 1 and 0xC1
for audio 2 (if available). Dolby Digital data is stored in packets with
ids 0xBD.

163
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,160 @@ 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).
2001-06-12: Version 0.81
- Fixed handling the case where the driver reports EAGAIN during recording,
but no data comes within 5 seconds.
- Fixed EPG scanning on single DVB card systems.
- There can now be two audio PIDs per channel, which can be toggled via the
"Green" button in the "Main" menu. The "Edit Channel" menu therefore now
has two audio PID fields (Apid1 and Apid2). By default, Apid2 is 0, which
means there is no alternate audio track.
- Fixed replaying in case the driver reports EAGAIN.
- Now 'runvdr' checks if the driver is already loaded (thanks to Henning
Holtschneider).
- Fixed removing recordings with Lifetime = 99.
- Improved channel switching.
2001-06-16: Version 0.82
- Increased timeout until reporting "broken video data stream" when recording.
- Increased amount of non-useful data received by cRemux before assuming the
recording will fail.
- If there are two audio PIDs defined for a channel, both audio tracks will
now be recorded and can be selectively replayed later. See the FORMATS file
for details on how these different audio tracks are stored in the recorded
files. In order for this to work properly you need to use a driver version
dated 2001-06-16 or later, where the default PES filter buffer size has been
reduced. This will create packets for the second audio track that are small
enough to multiplex smoothly with the video data.
- Fixed a bug in the editing mechanism (didn't work with recordings that
consist of more than one data file).
- The compile time switch VFAT has been fixed to recognize the ':' character
in recording names, too.
- Setting all PIDs to 0x1FFF before switching channel.
- New setup parameter "VideoFormat" to define the aspect ratio of the tv set
in use (4:3 or 16:9).
2001-06-26: Version 0.83
- Avoiding "Device or resource busy" error message when setting PIDs.
- Added Portugese language texts (thanks to Paulo Manuel Martins Lopes).
- Recording and replaying Dolby Digital (AC3) sound.
- No longer getting stuck when a channel doesn't sync while switching
with the 'Up' and 'Down' keys.
2001-07-22: Version 0.84
- Fixed video packet scanning to make it recognize the whole range of
allowed video packet ids.
- Added an additional "emergency exit" in case channel switching doesn't
work several times in a row (when will the driver finally become stable
enough to allow rock solid channel switching??).
- No longer sending a Diseqc command if the Diseqc value for a given channel
is '0'. Previously this caused problems with some multi-switches (thanks to
Markus Lang and Ulrich Röder).
- When switching channels by entering the channel number via the numeric keys
on the remote control, the channel number displayed is now followed by the
'-' character to indicate that additional digits can be entered.
- Increased the timeout for numeric channel switching from 500ms to 1s.
- Fixed handling the "Green" button in the "Schedules" menu for channels that
have a second audio PID.
- Fixed high system load when displaying a still picture in replay.
- Fixed a hanging SVDRP connection if the client dies without issuing QUIT.
- Increased the frame buffer size to 192KB.
- Removed a superfluous VIDEO_FREEZE call in the replay buffer.
- Added French language texts (thanks to Jean-Claude Repetto).
- Modified OSD to use 2bpp windows (4 colors) in order to work with less
memory, allow a larger OSD window and be faster. The group separators in the
"Channels" menu had to be given a different color.
- Moved the channel display to the bottom of the screen.
- Displaying the frame counter in the replay progress display only when editing
a mark.
- Fixed handling characters above 0xEF in SVDRP.
- Fixed a possible crash in parsing incorrect lines in 'channels.conf'.
- New channel settings for Premiere World (Dolby Digital PIDs not yet
available).
- Increased the buffer for key names received from LIRC (thanks to Andre
Valentin).
- Fixed handling a channel group separator at the very beginning of the
'channels.conf' file.
2001-07-29: Version 0.85
- Added Norwegian language texts (thanks to Jørgen Tvedt).
- Increased the usleep value in cDvbOsd::Cmd() to 5000 in order to work on
systems with the KURT/utime-patch (thanks to Guido Fiala).
- Changed the check whether the driver is loaded in runvdr to check for the
'dvb' module (the last one loaded).
- Fixed repeat function with LIRC (thanks to Stefan Huelswitt).
- Increased the upper limit for the symbol rate to 30000 (thanks to Ulrich
Röder).
- Made the position of the channel display configurable (thanks to Stefan
Huelswitt).
- Made the width and height of the OSD configurable (thanks to Stefan Huelswitt).
- DiSEqC support can now be generally enabled/disabled in the Setup menu. This
may be necessary if your multiswitch gets irritated by the default DiSEqC
codes '0' (thanks to Markus Lang).
- Fixed replaying in case there is no index file.
- Fixed jumping to an editing mark when replay has been paused.
- Avoiding unnecessary code execution in the replay progress display (thanks
to Guido Fiala).
- When entering time values the digits that still have to be entered are now
shown as '-' (as in "1-:--").
- When setting an editing mark while the progress display is not active, the
display will now be turned on for a short while to indicate the successful
setting of the mark.
- Updated 'channels.conf' for Premiere World (thanks to Helmut Schächner).
Check your timers if you use this channels.conf file, since the sequence of
several PW channels has been changed.
- Changed the color of "Info" messages to "black on green" and that of the
confirmation messages (like "Delete...") to "black on yellow".
- Fixed display with DEBUG_OSD (it still crashes sometimes, esp. when replaying,
but I can't seem to find what causes this... any ideas anybody?).
- Avoiding audio/video distortions in 'Transfer Mode' by no longer actually
tuning the primary interface (which can't receive this channel, anyway).
Apparently the driver gets irritated when the channel is switched and a
replay session is started immediately after that.
- Increased timeout until reporting "video data stream broken" when recording.
- Explicitly switching back to the previously active channel after ending a
replay session (to have it shown correctly in case it was in 'Transfer Mode').

16
INSTALL
View File

@ -15,7 +15,7 @@ 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.8.2 or higher
This program requires the card driver version 0.9.0 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
@ -81,13 +81,25 @@ Automatic restart in case of hangups:
If you run VDR using the 'runvdr' shell script it will use the built-in
watchdog timer to restart the program in case something happens that
causes a program hangup.
causes a program hangup. If you change the command line options for the
call to the VDR program, be sure to NOT use the '-d' option! Otherwise
VDR will go into 'deamon' mode and the initial program call will return
immediately!
Command line options:
---------------------
Use "vdr --help" for a list of available command line options.
Replaying Dolby Digital audio:
------------------------------
To replay Dolby Digital audio you need a program that reads the DD data
from stdin and processes it in a way suitable for your audio hardware.
This program must be given to VDR with the '-a' option, as in
vdr -a ac3play
The video data directory:
-------------------------

48
MANUAL
View File

@ -18,7 +18,7 @@ Video Disk Recorder User's Manual
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
Back - Menu off Main menu Main menu Discard Main menu Recordings menu
Red - Record Edit Edit - Play -
Green - - New New - Rewind Skip -60s
Green - Language New New - Rewind Skip -60s
Yellow - - Delete Delete - Delete Skip +60s
Blue - Resume Mark Mark - Summary Stop
0..9 Ch select - - - Numeric inp. - Editing
@ -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).
@ -100,7 +100,7 @@ Video Disk Recorder User's Manual
and browse through the list with the "Up" and "Down" key; to switch to the
selected channel press "Ok".
3. Directly type in the channel number with the numeric keys ('0'..'9');
if no key is pressed for about half a second, the digits collected so
if no key is pressed for about one second, the digits collected so
far will define the channel number.
4. From the "Now", "Next" and "Event" menus (accessible through the "Schedule"
menu) by pressing the "Blue" button.
@ -115,6 +115,16 @@ Video Disk Recorder User's Manual
To bring up the channel display without switching channels you can press
the "Ok" button.
* Selecting language specific audio track
If the current channel provides different audio tracks (typically for
different languages), the "Green" button in the "Main" menu can be pressed
to toggle between these. There can be two different audio PIDs per channel,
assuming that typically a channel broadcasts a country specific language
plus the movie's original soundtrack.
Recordings made form such channels will contain both audio tracks, and when
replaying the desired audio track can be selected the same way.
* Switching through channel groups
If the 'channels.conf' file contains "group separators" you can switch
@ -257,6 +267,9 @@ Video Disk Recorder User's Manual
to free up space for a new recording. Note that setting this
parameter to very high values for all recordings may soon fill up
the entire disk and cause new recordings to fail due to low disk
space. The special value 99 means that this recording will live
"forever", and a value of 0 means that this recording can be
deleted any time if a recording with a higher priority needs disk
space.
File: The name under which a recording created through this timer will
be stored on disk (the actual name will also contain the date and
@ -309,9 +322,14 @@ 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)
DiSEqC = 1 Generally turns DiSEqC support on or off.
0 = disabled
1 = enabled
SetSystemTime = 0 Defines whether the system time will be set according to
the time received from the DVB data stream.
0 = system time will not be set
@ -341,6 +359,22 @@ Video Disk Recorder User's Manual
never keep the user from viewing stuff on the primary
interface. On systems with only one DVB card, timers
with a priority below PrimaryLimit will never execute.
DefaultPriority = 50 The default Priority and Lifetime values used when
DefaultLifetime = 50 creating a new timer event. A Lifetime value of 99
means that this recording will never be deleted
automatically.
VideoFormat = 0 The video format (or aspect ratio) of the tv set in use.
0 = 4:3
1 = 16:9
ChannelInfoPos = 0 The position of the channel info window in the OSD.
0 = bottom
1 = top
OSDwidth = 52 The width and height of the OSD .
OSDheight = 18 The valid ranges are width=40...56, height=12...21.
* Executing system commands

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/11 11:36:15 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,4 +1,6 @@
Sammlung von "Hilfs"-Scripten
von Matthias Schniedermeyer
ms@citd.de
Diese Sammlung an "Hilfs"-Scripten habe ich mir zum scheiden und anderen
Zwecken zusammengeschrieben.
@ -10,10 +12,10 @@ Ich bin nicht sonderlich gut im "Dokumentieren". Also gilt die Devise
Ein paar Worte zu den "Hart"-Codierten Pfaden.
/yele/video (/video/video0)
/yelg/video (/video/video1)
/dvb/video
/dvb2/video
Sind die 2 Pfade auf meinem DVB-Rechner
Sind die 2 DVB-Rechner.
/x1/video
@ -30,14 +32,23 @@ Enthalten sind folgende Scripte:
cutall -> "Master"-Script zum starten des Scheide vorgangs.
Ist ein "find" nach "cut" -Dateien
cutt -> Das "eigentliche" Schnitt-Script
Scheidet die Stuecke aus, demultipext, remultipext,
splitted die Dateien und macht am Ende ein
ISO-Image daraus
Bei einem einzelnen Block wird diese direkt
gesplitet und dann zu einem ISO-Image verarbeitet
Wenn mehrere Teile (=War mit Werbung) vorhanden
sind, dann werden zuerst die einzelnen Teile,
legt nummerierte Verzeichniss ein und kopiert bzw
splitet die einzelnen Dateien in die Verzeichniss
und macht dann daraus die ISO-Images
(Leider funktioniert das aus irgendwelche Gruenden
(noch) nicht mit Serien die nur eine CD gross sind
aber das wird noch)
index.php -> PHP-Script zum finden der Schnitt-Punkte, mit
Testmoeglichkeit ob erfolgreich an diesem Punkt
geschnitten werden kann
mv2 -> Zum Moven der Aufnahmen von meinem DVB-Rechner
mv2 -> Zum Moven der Aufnahmen von meinen DVB-Rechnern
auf mein "Arbeitsrechner"
play -> Zum Abspielen einer Aufnahme von meinem Recher auf
dem "Frontend" DVB-Rechner
schnitt.pl -> Extraiert ein einzelnes Bild um es anzuzeigen
(Fuer index.php)
schnitt2.pl -> Gibt alles zwischen 2 Schnittpunkten auf STDOUT aus
@ -58,27 +69,43 @@ vdr2 -> Start-Script
vmount -> Mounten aller zusammengehoeriger ISO-Images zum
abspielen
Hilsscripte:
Hilfsscripte:
------------
cut.pl -> Entspricht weitestgehend "split" aber mit
"Nummer" anstatt Buchstaben
cut2 -> Entfernt escapende Backslashes
cut2.pl/cut3.pl -> Fuer Aufnehmen die aus mehreren Bloecken bestehen
(=Mit Werbung)
cutall2 -> Springt ins Schnitt-Verzeichniss und ruft das
"eigentliche" Schnitt-Script auf
lmplex -> Multiplexed Datenstrome unter Zurhilfename
saemtlicher CPUs
cutall3.pl -> Wenn in einem Verzeichniss mehrere Aufnahmen sind
splitet dies Programm diese und ruft fuer jede
Aufnahme das "cutt"-Script auf
schnittcommon.pli -> Das "Common" Script fuer schnitt?.pl
getpreviframe.pl -> Findet das vorherige I-Frame.
unsort -> Macht das Gegenteil von sort.
dump.c -> Muss in der "libmpeg3"-Verzeichniss des
"mpeg2-movie"-Packets kopiert werden und dann mit
"make" compilieren
Dieses C-Programm ist dafuer da um fuer das
PHP-Script das Bild anzuzeigen wo man gerade ist.
Da mir der "urspruengliche" Source-Code dafuer
abhanden gekommen ist und ich den Patch neumachen
musste (Wie immer mit "Verbesserungen") ist index.php
nocht nicht auf die neue Version angepasst. Die
Anpassung besteht aber nur darin eine "1" an die
Kommandozeile anzuhaengen.
Die ganze "Schnittloesung" ist leider etwas "unbrauchbar", weil ich aus
Unachtsamkeit leider die gepatchten Sourcen von 2 wichtigen Programm
geloescht habe.
dumpfrage -> Extraiert das erste Frage in eine Datei zum
anzeigen (gepatchtes dump aus "libmpeg3"
pvademux -> gepatcht um eine Pfad-Angabe
Im Gegensatz zur "alten"-Version ist diese Version "vollstaendig"
einsatzfaehig!
Entweder macht jemand/ich patchen "nochmal" oder ich kann auch die
Binaries zur Verfuegung stellen.
Wenn jemand Fragen zum Einsatz hat dann "loechern Sie mich"
ms@citd.de
Ich kann auch gerne die Einrichtung per "Fernwartung" (=ssh) uebernehmen.
(Wenn noetig compiliere ich auch auch apache mit PHP usw.)

View File

@ -1,30 +1,25 @@
#!/usr/bin/perl -w
#!/usr/bin/perl
use strict;
chdir ($ARGV[0]) if ($ARGV[0]);
my $maxsize = 660 * 1024 * 1024;
$read = $size = 1024*1024;
my $read = 1024*1024;
my $size = 1024*1024;
my $filenum = "1";
my $count = 0;
my ($fi,$data);
$filenum = "1";
$count = 0;
$fi = sprintf ("part%d",$filenum);
open (FI,">$fi");
while ($read == $size)
{
if ($count < $maxsize)
if ($count < 660*1024*1024)
{
$read = read (STDIN,$data,$size);
print FI $data;
$count += $size;
$a = $count /1024/1024;
if ($a % 10 == 0) {
print STDERR "File: $filenum Size: ${a}MB\n";
print stderr "File: $filenum Size: ${a}MB\n";
}
}
else

View File

@ -1,2 +1,2 @@
#!/bin/sh
cat cut | head -n 1 | tr -d [\\\\]
cat cut2 | head -n 1 | tr -d [\\\\]

View File

@ -1,4 +1,2 @@
#!/bin/sh
cutdir=/x1/video/
find $cutdir -name "cut" -exec cutall2 {} \;
find /x1/video/ -name "cut" -exec cutall2 {} \;

View File

@ -1,5 +1,5 @@
#!/bin/sh
a=`echo $1 | cut -d / -f1-5`
cd $a
cutt
cutall3.pl
mv cut cut.bak

View File

@ -3,10 +3,13 @@
DIRA=/x2/temp
DIRB=/x1/temp
if [ -f cut ]; then
if [ ! -f cut2 ]; then
echo Keine Beschreibungsdatei
exit 1
else
name="`cut2`"
echo $name
count=`cat cut | wc -l`
count=`cat cut2 | wc -l`
let count=count-1
let test=count%2
if [ "$test" == "1" ]; then
@ -16,70 +19,88 @@ if [ -f cut ]; then
file=1
while [ "$count" != "0" ]
do
start=`cat cut | tail -n $count | head -n 1`
if [ "$count" == "2" ]; then
start=`cat cut2 | tail -n $count | head -n 1`
let count=count-1
end=`cat cut | tail -n $count | head -n 1`
let count=count-1
echo Cutting\&Demuxing from $start to $end
schnitt2.pl $start $end | pvademux $DIRA teil$file
# schnitt2.pl $start $end | pes2av_pes | pvademux $DIRA teil$file
let file=file+1
done
else
echo Keine Beschreibungsdatei
exit 1
end=`cat cut2 | tail -n $count | head -n 1`
schnitt2.pl $start $end | avpes2mpeg | cut.pl $DIRA
secondway=2
else
while [ "$count" != "0" ]
do
start=`cat cut2 | tail -n $count | head -n 1`
let count=count-1
end=`cat cut2 | tail -n $count | head -n 1`
let count=count-1
echo Cutting \& Converting from $start to $end
schnitt2.pl $start $end | avpes2mpeg > $DIRA/teil$file.mpg
# schnitt2.pl $start $end | pvademux $DIRA teil$file
let file=file+1
done
fi
fi
# Ab hier mkimg
sync
lmplex $DIRA $DIRB `ls -la $DIRA/teil*.m2v | cut -b 30- | sort -n -r | cut -d / -f4`
echo Multiplexing DONE
rm -f $DIRA/teil*.m2v $DIRA/teil*.mp2
rm cut2
sync
if [ -f $DIRB/teil1.mpg ]; then
echo Splitting
if [ "$secondway" != "2" ]; then
cd $DIRA
# cat $DIRB/teil*.mpg | split -b 723517440
cat $DIRB/teil*.mpg | cut.pl
rm $DIRB/teil*
fi
cut2.pl "$name"
if [ -d 2 ]; then
count=1
cond=0
sync
while [ "$cond" != "1" ]
do
echo mkisofs Teil $count
mkisofs -r -o $DIRB/image1.raw $count
rm -rf $count
mv -- $DIRB/image1.raw "$DIRB/${name} CD $count"
sync
let count=count+1
if [ ! -d $count ]; then
cond=1
fi
done
else
echo mkisofs
mkisofs -r -o $DIRB/image1.raw $count
rm -rf $count
mv -- $DIRB/image1.raw "$DIRB/${name}"
fi
else
cd $DIRA
cd $DIRA
if [ -f part2 ]; then
count=1
cond=0
if [ -f part2 ]; then
count=1
cond=0
while [ "$cond" != "1" ]
do
while [ "$cond" != "1" ]
do
mkdir a
mv "part$count" "a/${name} CD $count.mpg"
echo mkisofs Teil $count
mkisofs -r -o $DIRB/image1.raw a
rm -rf a
mv -- $DIRB/image1.raw "$DIRB/${name} CD $count"
sync
let count=count+1
if [ ! -f "part$count" ]; then
cond=1
fi
done
else
mkdir a
mv "part$count" "a/${name} Teil $count"
echo mkisofs Teil $count
mv part1 "a/${name}.mpg"
echo mkisofs
mkisofs -r -o $DIRB/image1.raw a
rm -rf a
mv -- $DIRB/image1.raw "$DIRB/${name} Teil $count"
sync
let count=count+1
if [ ! -f "part$count" ]; then
cond=1
fi
done
else
mkdir a
mv part1 "a/${name}"
echo mkisofs
mkisofs -r -o $DIRB/image1.raw a
rm -rf a
mv -- $DIRB/image1.raw "$DIRB/${name}"
mv -- $DIRB/image1.raw "$DIRB/${name}"
fi
fi

View File

@ -1,18 +1,12 @@
#!/usr/bin/perl
use strict;
my ($index, $oindex);
require "/usr/local/bin/my/schnittcommon.pli";
if (!open (INDEX,"index.vdr"))
{
exit 1;
}
$index = $oindex = $ARGV[0];
if ($index > 0)
{
&prevI;

View File

@ -1,23 +1,30 @@
#!/bin/sh
#
# Move files from DVB-Computer(s) to localmachine into $LOCALDIR
#
DIR = /x1/video
LOCALDIR=/x1/video
if [ ! "$UID" = 0 ]; then
if [ -d "$1" ]; then
cd $DIR
a=`echo "$1" | cut -d / -f4-`
mkdir -p "$a"
cd "$a"
(echo cd "$1"; echo mget \*)| ftp -i dvb
cd $DIR
ls -Ls $1 > /tmp/yele
ls -Ls $a > /tmp/x1
a=`echo "$1" | cut -d \/ -f3-`
diff -u /tmp/yele /tmp/x1 &> /dev/null && rm -rfv /yel?/$a
rm /tmp/yele
rm /tmp/x1
rmdir /yel?/video/*
if [ -f "$1/index.vdr" ]; then
cd $LOCALDIR
recdir=`echo "$1" | cut -d / -f4-`
mkdir -p "$recdir"
cd "$recdir"
dvbcomp=`echo "$1" | cut -d / -f2`
(echo cd "/video/video0/$recdir"; echo mget \*)| ftp -i $dvbcomp
cd $LOCALDIR
ssh $dvbcomp ls -Ls /video/video0/$recdir > /tmp/dvb
ls -Ls $recdir > /tmp/local
diff -u /tmp/dvb /tmp/local &> /dev/null && rm -rfv /$dvbcomp/video?/$recdir
rm /tmp/dvb
rm /tmp/local
rmdir --ignore-fail-on-non-empty `find /$dvbcomp/video?/ -type d -mindepth 1 | cut -d \/ -f-4 | grep -v temp | sort | uniq`
fi
fi
else
echo Not as root
fi
/usr/local/bin/my/process_summary.pl

View File

@ -21,6 +21,7 @@ syswrite (FO,$temp,200000);
close (FI);
close (FO);
`/usr/local/bin/pvademux.old /x2/temp bild`;
`cat bild | /usr/local/bin/avpes2mpeg > avpes`;
`/usr/local/bin/my/dumpframe avpes 1`;
#`/usr/local/bin/pes2av_pes bild | /usr/local/bin/pvademux /x2/temp bild`;
print "$index\n";

View File

@ -10,10 +10,12 @@ if (!open (INDEX,"index.vdr"))
$index = $ARGV[0];
&nextI;
#&readnext;
$file1 = $file;
$offset1 = $offset;
$index = $ARGV[1];
&nextI;
#&readnext;
$file2 = $file;
$offset2 = $offset;

View File

@ -5,7 +5,7 @@ do
if [ -f newpic ]; then
killall xli
rm -f newpic
xli output.ppm &
xli output000.ppm &
fi
sleep 24h
done

View File

@ -4,7 +4,7 @@ cond=0
if [ -f "$1" ]; then
mount "$1" /mnt/1 -o loop
$cond = 1
cond=1
else
while [ "$cond" != "1" ]
do

View File

@ -1,6 +1,6 @@
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
Pro-7:12480:v:0:27500:255:256;257: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
@ -16,7 +16,7 @@ ZDF:11954:h:0:27500:110:120:130:0:28006
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
ORF2:12692:h:0:22000:500:501:505:3:13002
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
@ -46,62 +46,81 @@ 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
ARD Online-Kanal:12722:h:0:22000:0: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
Premiere World:11797:h:0:27500:255:256:32:0:8
Premiere 1:11797:h:0:27500:511:512:0:3:10
Premiere 2:11797:h:0:27500:1791:1792:0:3:11
Premiere 3:11797:h:0:27500:2303:2304:0:3:43
Premiere Star:11797:h:0:27500:767:768:0:3:9
Premiere Sci-Fi:11797:h:0:27500:1535:1536:0:3:41
Premiere Action:11797:h:0:27500:1023:1024:0:3:20
Premiere Comedy:11797:h:0:27500:1279:1280:0:3:29
13th Street:12031:h:0:27500:2303:2304:0:3:42
Studio Universal:12090:V:0:27500:255:256:0:3:36
Filmpalast:12031:h:0:27500:2559:2560:0:3:516
Heimatkanal:12031:h:0:27500:2815:2816:0:3:517
Discovery Channel:12031:h:0:27500:1791:1792:0:3:14
Planet:12090:V:0:27500:1279:1280:0:3:13
Fox Kids:12031:h:0:27500:1279:1280:0:3:28
Junior:12031:h:0:27500:255:256:0:3:19
K-Toon:12031:h:0:27500:511:512:0:3:12
Disney Channel:12090:V:0:27500:767:768:0:3:34
Sunset:12031:h:0:27500:1023:1024:0:3:16
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
Goldstar TV:12031: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
Seasons:12090:V:0:27500:511:512:0:3:33
:Cinedom
Cinedom Deluxe:11758:h:0:27500:255:256,257;259:0:3:189
Cinedom 1A:11758:h:0:27500:511:512,513:0:3:190
Cinedom 1B:12070:h:0:27500:1535:1536,1537:0:3:178
Cinedom 1C:11720:h:0:27500:511:512,513:0:3:180
Cinedom 1D:11720:h:0:27500:1535:1536,1537:0:3:176
Cinedom 2A:11758:h:0:27500:1023:1024:0:3:193
Cinedom 2B:11720:h:0:27500:1279:1280:0:3:183
Cinedom 2C:12070:h:0:27500:1791:1792:0:3:179
Cinedom 2D:12070:h:0:27500:511:512:0:3:184
Cinedom 2E:12070:h:0:27500:1279:1280:0:3:188
Cinedom 3A:11758:h:0:27500:2559:2560:0:3:192
Cinedom 3B:11758:h:0:27500:1535:1536:0:3:195
Cinedom 3C:12070:h:0:27500:767:768:0:3:185
Cinedom 3D:11720:h:0:27500:1023:1024:0:3:182
Cinedom 4A:11758:h:0:27500:767:768:0:3:191
Cinedom 4B:11720:h:0:27500:767:768:0:3:181
Cinedom 4C:12070:h:0:27500:2047:2048:0:3:187
Cinedom 5A:11758:h:0:27500:1279:1280:0:3:194
Cinedom 5B:11720:h:0:27500:1791:1792:0:3:177
Cinedom 5C:12070:h:0:27500:1023:1024:0:3:186
:Beta Digital
CNBC:12148:h:0:27500:255:256:0:3:35
Liberty TV.com:12610:V:0:22000:941:943:0:0:12199
:PW Erotic
Beate-Uhse.TV:11758:h:0:27500:3839:3840:0:3:21
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
:Sportsworld
Premiere Sport 1:11719:h:0:27500:255:256:0:3:17
Premiere Sport 2:11719:h:0:27500:3327:3328:0:3:27
Premiere Sport 3:11758:h:0:27500:2815:2816:0:3:18
:Formel 1
Infokanal:11720:h:0:27500:3071:3072:0:3:244
Multikanal:11720:h:0:27500:2815:2816:0:3:243
Supersignal:11720:h:0:27500:255:256:0:3:17
Verfolgerfeld:11720:h:0:27500:2303:2304:0:3:241
Cockpitkanal:11720:h:0:27500:2559:2560:0:3:242
Boxengasse:11720:h:0:27500:2047:2048:0:3:240
:Premiere World Bundesliga
Superdom:12070:h:0:27500:255:256:0:3:26
Spiel 1:11719:h:0:27500:255:256,257:0:3:17
Spiel 2:11719:h:0:27500:2047:2048,2049:0:3:240
BuLi-Konferenz:12070:h:0:27500:3071:3072,3073:0:3:208
BuLi-Spiel 1:12070:h:0:27500:3327:3328,3329:0:3:209
BuLi-Spiel 2:12070:h:0:27500:2303:2304,2305:0:3:210
BuLi-Spiel 3:12070:h:0:27500:3583:3584,3585:0:3:211
BuLi-Spiel 4:12070:h:0:27500:2559:2560,2561:0:3:212
BuLi-Spiel 5:12070:h:0:27500:2815:2816,2817:0:3:213
:
TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601
Mosaico:11934:v:0:27500:165:100:0:0:29010
@ -164,7 +183,7 @@ 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
MHP test:12604:h:0:22000:5632:0: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
@ -173,3 +192,4 @@ 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
MTV Central Europe:12699:v:0:22000:3031:3032:0:0:28643

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.52 2001/07/27 13:45:28 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;
@ -200,7 +200,10 @@ cChannel::cChannel(const cChannel *Channel)
diseqc = Channel ? Channel->diseqc : 0;
srate = Channel ? Channel->srate : 27500;
vpid = Channel ? Channel->vpid : 255;
apid = Channel ? Channel->apid : 256;
apid1 = Channel ? Channel->apid1 : 256;
apid2 = Channel ? Channel->apid2 : 0;
dpid1 = Channel ? Channel->dpid1 : 257;
dpid2 = Channel ? Channel->dpid2 : 0;
tpid = Channel ? Channel->tpid : 32;
ca = Channel ? Channel->ca : 0;
pnr = Channel ? Channel->pnr : 0;
@ -218,8 +221,19 @@ const char *cChannel::ToText(cChannel *Channel)
delete buffer;
if (Channel->groupSep)
asprintf(&buffer, ":%s\n", s);
else
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%d:%d:%d:%d\n", s, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, Channel->apid, Channel->tpid, Channel->ca, Channel->pnr);
else {
char apidbuf[32];
char *q = apidbuf;
q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
if (Channel->apid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2);
if (Channel->dpid1 || Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1);
if (Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
*q = 0;
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%s:%d:%d:%d\n", s, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, apidbuf, Channel->tpid, Channel->ca, Channel->pnr);
}
return buffer;
}
@ -242,8 +256,21 @@ bool cChannel::Parse(const char *s)
}
else {
groupSep = false;
//XXX
int fields = sscanf(s, "%a[^:]:%d:%c:%d:%d:%d:%d:%d:%d:%d", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apid, &tpid, &ca, &pnr);
char *apidbuf = NULL;
int fields = sscanf(s, "%a[^:]:%d:%c:%d:%d:%d:%a[^:]:%d:%d:%d", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apidbuf, &tpid, &ca, &pnr);
apid1 = apid2 = 0;
dpid1 = dpid2 = 0;
if (apidbuf) {
char *p = strchr(apidbuf, ';');
if (p)
*p++ = 0;
sscanf(apidbuf, "%d,%d", &apid1, &apid2);
if (p)
sscanf(p, "%d,%d", &dpid1, &dpid2);
delete apidbuf;
}
else
return false;
if (fields >= 9) {
if (fields == 9) {
// allow reading of old format
@ -275,7 +302,7 @@ bool cChannel::Switch(cDvbApi *DvbApi, bool Log)
isyslog(LOG_INFO, "switching to channel %d", number);
}
for (int i = 3; i--;) {
if (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid, tpid, ca, pnr))
if (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid1, apid2, dpid1, dpid2, tpid, ca, pnr))
return true;
esyslog(LOG_ERR, "retrying");
}
@ -305,8 +332,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 +357,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 +551,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,14 +761,22 @@ cSetup::cSetup(void)
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
MarkInstantRecord = 1;
LnbSLOF = 11700;
LnbFrequLo = 9750;
LnbFrequHi = 10600;
DiSEqC = 1;
SetSystemTime = 0;
MarginStart = 2;
MarginStop = 10;
EPGScanTimeout = 5;
SVDRPTimeout = 300;
PrimaryLimit = 0;
DefaultPriority = 50;
DefaultLifetime = 50;
VideoFormat = VIDEO_FORMAT_4_3;
ChannelInfoPos = 0;
OSDwidth = 52;
OSDheight = 18;
CurrentChannel = -1;
}
@ -756,14 +791,22 @@ 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, "DiSEqC")) DiSEqC = atoi(Value);
else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
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, "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, "VideoFormat")) VideoFormat = atoi(Value);
else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
else
return false;
@ -813,14 +856,22 @@ 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, "DiSEqC = %d\n", DiSEqC);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
fprintf(f, "MarginStart = %d\n", MarginStart);
fprintf(f, "MarginStop = %d\n", MarginStop);
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, "VideoFormat = %d\n", VideoFormat);
fprintf(f, "ChannelInfoPos = %d\n", ChannelInfoPos);
fprintf(f, "OSDwidth = %d\n", OSDwidth);
fprintf(f, "OSDheight = %d\n", OSDheight);
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.55 2001/07/27 13:32:53 kls Exp $
*/
#ifndef __CONFIG_H
@ -19,10 +19,18 @@
#include "eit.h"
#include "tools.h"
#define VDRVERSION "0.72"
#define VDRVERSION "0.85"
#define MaxBuffer 10000
#define MAXPRIORITY 99
#define MAXLIFETIME 99
#define MINOSDWIDTH 40
#define MAXOSDWIDTH 56
#define MINOSDHEIGHT 12
#define MAXOSDHEIGHT 21
enum eKeys { // "Up" and "Down" must be the first two keys!
kUp,
kDown,
@ -92,7 +100,8 @@ public:
int diseqc;
int srate;
int vpid;
int apid;
int apid1, apid2;
int dpid1, dpid2;
int tpid;
int ca;
int pnr;
@ -106,9 +115,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 +246,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,13 +272,19 @@ public:
int ShowInfoOnChSwitch;
int MenuScrollPage;
int MarkInstantRecord;
int LnbSLOF;
int LnbFrequLo;
int LnbFrequHi;
int DiSEqC;
int SetSystemTime;
int MarginStart, MarginStop;
int EPGScanTimeout;
int SVDRPTimeout;
int PrimaryLimit;
int DefaultPriority, DefaultLifetime;
int VideoFormat;
int ChannelInfoPos;
int OSDwidth, OSDheight;
int CurrentChannel;
cSetup(void);
bool Load(const char *FileName);

1631
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.42 2001/07/27 11:40:38 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,9 +36,6 @@ typedef struct CRect {
signed short x, y, width, height;
};
#define MenuLines 15
#define MenuColumns 40
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);
@ -55,9 +58,22 @@ 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_demuxa1, fd_demuxa2, fd_demuxd1, fd_demuxd2, fd_demuxv, fd_demuxt;
int vPid, aPid1, aPid2, dPid1, dPid2;
bool SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output);
bool SetVpid(int Vpid, dmxOutput_t Output) { return SetPid(fd_demuxv, DMX_PES_VIDEO, Vpid, Output); }
bool SetApid1(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa1, DMX_PES_AUDIO, Apid, Output); }
bool SetApid2(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa2, DMX_PES_OTHER, Apid, Output); }
bool SetDpid1(int Dpid, dmxOutput_t Output) { return SetPid(fd_demuxd1, DMX_PES_OTHER, Dpid, Output); }
bool SetDpid2(int Dpid, dmxOutput_t Output) { return SetPid(fd_demuxd2, DMX_PES_OTHER, Dpid, 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.
@ -138,7 +156,6 @@ private:
cDvbOsd *osd;
#endif
int cols, rows;
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
public:
void Open(int w, int h);
void Close(void);
@ -154,12 +171,16 @@ public:
void Text(int x, int y, const char *s, eDvbColor colorFg = clrWhite, eDvbColor colorBg = clrBackground);
void Flush(void);
// Video format facilities:
void SetVideoFormat(videoFormat_t Format);
// Channel facilities
private:
int currentChannel;
public:
bool SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Tpid, int Ca, int Pnr);
bool SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid, int Ca, int Pnr);
static int CurrentChannel(void) { return PrimaryDvbApi ? PrimaryDvbApi->currentChannel : 0; }
int Channel(void) { return currentChannel; }
@ -184,12 +205,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 +262,24 @@ 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.
// Audio track facilities
public:
bool CanToggleAudioTrack(void);
// Returns true if we are currently replaying and this recording has two
// audio tracks, or if the current channel has two audio PIDs.
bool ToggleAudioTrack(void);
// Toggles the audio track if possible.
// Dolby Digital audio facilities
private:
static char *audioCommand;
public:
static void SetAudioCommand(const char *Command);
static const char *AudioCommand(void) { return audioCommand; }
};
class cEITScanner {

352
dvbosd.c
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.10 2001/07/24 16:25:34 kls Exp $
*/
#include "dvbosd.h"
@ -14,12 +14,83 @@
#include <sys/unistd.h>
#include "tools.h"
// --- cPalette --------------------------------------------------------------
cPalette::cPalette(int Bpp)
{
maxColors = 1 << Bpp;
numColors = 0;
full = false;
}
int cPalette::Index(eDvbColor Color)
{
for (int i = 0; i < numColors; i++) {
if (color[i] == Color) {
used[i] = true;
return i;
}
}
if (!full) {
if (numColors < maxColors) {
color[numColors++] = Color;
used[numColors - 1] = true;
fetched[numColors - 1] = false;
return numColors - 1;
}
for (int i = maxColors; --i >= 0; ) {
if (!used[i]) {
color[i] = Color;
used[i] = true;
fetched[i] = false;
return i;
}
}
esyslog(LOG_ERR, "ERROR: too many different colors used in palette");
full = true;
}
return 0;
}
void cPalette::Reset(void)
{
for (int i = 0; i < numColors; i++)
used[i] = false;
full = false;
}
const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor)
{
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
if (!fetched[FirstColor]) {
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
fetched[LastColor] = true;
LastColor--; // the loop ended one past the last one!
return &color[FirstColor];
}
}
return NULL;
}
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
{
for (int i = 0; i < Palette.numColors; i++) {
if (Palette.used[i]) {
int n = Index(Palette.color[i]);
if (Indexes)
(*Indexes)[i] = n;
}
}
}
// --- cBitmap ---------------------------------------------------------------
cBitmap::cBitmap(int Width, int Height)
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
:cPalette(Bpp)
{
width = Width;
height = Height;
clearWithBackground = ClearWithBackground;
bitmap = NULL;
fontType = fontOsd;
font = NULL;
@ -27,7 +98,7 @@ cBitmap::cBitmap(int Width, int Height)
bitmap = new char[width * height];
if (bitmap) {
Clean();
memset(bitmap, clrTransparent, width * height);
memset(bitmap, 0x00, width * height);
SetFont(fontOsd);
}
else
@ -54,9 +125,38 @@ eDvbFont cBitmap::SetFont(eDvbFont Font)
return oldFont;
}
bool cBitmap::Dirty(void)
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
{
return dirtyX2 >= 0;
if (dirtyX2 >= 0) {
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
//TODO Fix driver (should be able to handle any size bitmaps!)
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
}
//XXX "... / 2" <==> Bpp???
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyY2 < height - 1)
dirtyY2++;
else if (dirtyY1 > 0)
dirtyY1--;
}
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
}
x1 = dirtyX1;
y1 = dirtyY1;
x2 = dirtyX2;
y2 = dirtyY2;
return true;
}
return false;
}
void cBitmap::Clean(void)
@ -67,12 +167,12 @@ void cBitmap::Clean(void)
dirtyY2 = -1;
}
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
void cBitmap::SetIndex(int x, int y, char Index)
{
if (bitmap) {
if (0 <= x && x < width && 0 <= y && y < height) {
if (bitmap[width * y + x] != Color) {
bitmap[width * y + x] = Color;
if (bitmap[width * y + x] != Index) {
bitmap[width * y + x] = Index;
if (dirtyX1 > x) dirtyX1 = x;
if (dirtyY1 > y) dirtyY1 = y;
if (dirtyX2 < x) dirtyX2 = x;
@ -82,12 +182,19 @@ void cBitmap::SetPixel(int x, int y, eDvbColor Color)
}
}
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
{
SetIndex(x, y, Index(Color));
}
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
{
if (bitmap && Bitmap.bitmap) {
tIndexes Indexes;
Take(Bitmap, &Indexes);
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]));
SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
}
}
}
@ -105,6 +212,8 @@ int cBitmap::Width(const char *s)
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
{
if (bitmap) {
char fg = Index(ColorFg);
char bg = Index(ColorBg);
int h = font->Height(s);
while (s && *s) {
const cFont::tCharData *CharData = font->CharData(*s++);
@ -113,7 +222,7 @@ void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor Col
for (int row = 0; row < h; row++) {
cFont::tPixelData PixelData = CharData->lines[row];
for (int col = CharData->width; col-- > 0; ) {
SetPixel(x + col, y + row, (PixelData & 1) ? ColorFg : ColorBg);
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
PixelData >>= 1;
}
}
@ -125,39 +234,109 @@ void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor Col
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
{
if (bitmap) {
char c = Index(Color);
for (int y = y1; y <= y2; y++)
for (int x = x1; x <= x2; x++)
SetPixel(x, y, Color);
SetIndex(x, y, c);
}
}
void cBitmap::Clear(void)
{
Fill(0, 0, width - 1, height - 1, clrBackground);
Reset();
if (clearWithBackground)
Fill(0, 0, width - 1, height - 1, clrBackground);
}
const char *cBitmap::Data(int x, int y)
{
return &bitmap[y * width + x];
}
// --- cWindow ---------------------------------------------------------------
class cWindow : public cBitmap {
private:
int x0, y0;
bool shown;
public:
cWindow(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true);
int X0(void) { return x0; }
int Y0(void) { return y0; }
bool Shown(void) { bool s = shown; shown = true; return s; }
bool Contains(int x, int y);
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
const char *Data(int x, int y);
};
cWindow::cWindow(int x, int y, int w, int h, int Bpp, bool ClearWithBackground)
:cBitmap(w, h, Bpp, ClearWithBackground)
{
x0 = x;
y0 = y;
shown = false;
}
bool cWindow::Contains(int x, int y)
{
x -= x0;
y -= y0;
return x >= 0 && y >= 0 && x < width && y < height;
}
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
{
cBitmap::Fill(x1 - x0, y1 - y0, x2 - x0, y2 - y0, Color);
}
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
{
cBitmap::SetBitmap(x - x0, y - y0, Bitmap);
}
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
{
cBitmap::Text(x - x0, y - y0, s, ColorFg, ColorBg);
}
const char *cWindow::Data(int x, int y)
{
return cBitmap::Data(x, y);
}
// --- cDvbOsd ---------------------------------------------------------------
cDvbOsd::cDvbOsd(int VideoDev, int x1, int y1, int x2, int y2, int Bpp)
:cBitmap(x2 - x1 + 1, y2 - y1 + 1)
cDvbOsd::cDvbOsd(int VideoDev, int x, int y, int w, int h, int Bpp)
{
videoDev = VideoDev;
if (videoDev >= 0)
Cmd(OSD_Open, Bpp, x1, y1, x2, y2);
numWindows = 0;
x0 = x;
y0 = y;
if (videoDev >= 0) {
if (w > 0 && h > 0)
Create(0, 0, w, h, Bpp);
}
else
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
}
cDvbOsd::~cDvbOsd()
{
if (videoDev >= 0)
Cmd(OSD_Close);
if (videoDev >= 0) {
while (numWindows > 0) {
Cmd(OSD_SetWindow, 0, numWindows--);
Cmd(OSD_Close);
delete window[numWindows];
}
}
}
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,41 +348,120 @@ 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);
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.
// TODO Check if this is still necessary with driver versions after 0.7.
ioctl(videoDev, OSD_SEND_CMD, &dc);
usleep(5000); // 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.
// TODO Check if this is still necessary with driver versions after 0.7.
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
}
void cDvbOsd::Flush(void)
bool cDvbOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, eDvbColor Color0, eDvbColor Color1, eDvbColor Color2, eDvbColor Color3)
{
if (Dirty()) {
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
//TODO Fix driver (should be able to handle any size bitmaps!)
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
/* TODO XXX
- check that no two windows overlap
*/
if (numWindows < MAXNUMWINDOWS) {
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
if ((w & 0x03) != 0) {
w += 4 - (w & 0x03);
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
}
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyY2 < height - 1)
dirtyY2++;
else if (dirtyY1 > 0)
dirtyY1--;
cWindow *win = new cWindow(x, y, w, h, Bpp, ClearWithBackground);
if (Color0 != clrTransparent) {
win->Index(Color0);
win->Index(Color1);
win->Index(Color2);
win->Index(Color3);
win->Reset();
}
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
if (dirtyX2 < width - 1)
dirtyX2++;
else if (dirtyX1 > 0)
dirtyX1--;
}
Cmd(OSD_SetBlock, width, dirtyX1, dirtyY1, dirtyX2, dirtyY2, &bitmap[dirtyY1 * width + dirtyX1]);
Clean();
window[numWindows++] = win;
Cmd(OSD_SetWindow, 0, numWindows);
Cmd(OSD_Open, Bpp, x0 + x, y0 + y, x0 + x + w - 1, y0 + y + h - 1, (void *)1); // initially hidden!
}
else
esyslog(LOG_ERR, "ERROR: illegal OSD parameters");
}
else
esyslog(LOG_ERR, "ERROR: too many OSD windows");
return false;
}
cWindow *cDvbOsd::GetWindow(int x, int y)
{
for (int i = 0; i < numWindows; i++) {
if (window[i]->Contains(x, y))
return window[i];
}
return NULL;
}
void cDvbOsd::Flush(void)
{
for (int i = 0; i < numWindows; i++) {
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
if (window[i]->Dirty(x1, y1, x2, y2)) {
Cmd(OSD_SetWindow, 0, i + 1);
int FirstColor = 0, LastColor = 0;
const eDvbColor *pal;
while ((pal = window[i]->Colors(FirstColor, LastColor)) != NULL)
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
Cmd(OSD_SetBlock, window[i]->Width(), x1, y1, x2, y2, window[i]->Data(x1, y1));
window[i]->Clean();
}
}
// Showing the windows in a separate loop to avoid seeing them come up one after another
for (int i = 0; i < numWindows; i++) {
if (!window[i]->Shown()) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_MoveWindow, 0, x0 + window[i]->X0(), y0 + window[i]->Y0());
}
}
}
void cDvbOsd::Clear(void)
{
for (int i = 0; i < numWindows; i++)
window[i]->Clear();
}
void cDvbOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
{
cWindow *w = GetWindow(x1, y1);
if (w)
w->Fill(x1, y1, x2, y2, Color);
}
void cDvbOsd::SetBitmap(int x, int y, const cBitmap &Bitmap)
{
cWindow *w = GetWindow(x, y);
if (w)
w->SetBitmap(x, y, Bitmap);
}
int cDvbOsd::Width(unsigned char c)
{
return numWindows ? window[0]->Width(c) : 0;
}
int cDvbOsd::Width(const char *s)
{
return numWindows ? window[0]->Width(s) : 0;
}
eDvbFont cDvbOsd::SetFont(eDvbFont Font)
{
eDvbFont oldFont = Font;
for (int i = 0; i < numWindows; i++)
oldFont = window[i]->SetFont(Font);
return oldFont;
}
void cDvbOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground)
{
cWindow *w = GetWindow(x, y);
if (w)
w->Text(x, y, s, ColorFg, ColorBg);
}

View File

@ -4,35 +4,26 @@
* 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.8 2001/07/28 16:22:32 kls Exp $
*/
#ifndef __DVBOSD_H
#define __DVBOSD_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 <ost/osd.h>
#include <stdio.h>
#include <dvb.h>
#include "font.h"
enum eDvbColor {
#ifndef DEBUG_OSD
clrTransparent,
#endif
clrBackground,
#define MAXNUMCOLORS 16
enum eDvbColor {
#ifdef DEBUG_OSD
clrBackground,
clrTransparent = clrBackground,
clrBlack = clrBackground,
#else
clrBlack,
#endif
clrRed,
clrGreen,
clrYellow,
@ -40,39 +31,88 @@ enum eDvbColor {
clrMagenta,
clrCyan,
clrWhite,
#else
clrTransparent = 0x00000000,
clrBackground = 0x7F000000, // 50% gray
clrBlack = 0xFF000000,
clrRed = 0xFF1414FC,
clrGreen = 0xFF24FC24,
clrYellow = 0xFF24C0FC,
clrMagenta = 0xFFFC00B0,
clrBlue = 0xFFFC0000,
clrCyan = 0xFFFCFC00,
clrWhite = 0xFFFCFCFC,
#endif
};
class cBitmap {
class cPalette {
private:
eDvbColor color[MAXNUMCOLORS];
int maxColors, numColors;
bool used[MAXNUMCOLORS];
bool fetched[MAXNUMCOLORS];
bool full;
protected:
typedef unsigned char tIndexes[MAXNUMCOLORS];
public:
cPalette(int Bpp);
int Index(eDvbColor Color);
void Reset(void);
const eDvbColor *Colors(int &FirstColor, int &LastColor);
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
};
class cBitmap : public cPalette {
private:
cFont *font;
eDvbFont fontType;
void SetIndex(int x, int y, char Index);
char *bitmap;
bool clearWithBackground;
protected:
int width, height;
char *bitmap;
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
void Clean(void);
public:
cBitmap(int Width, int Height);
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
virtual ~cBitmap();
eDvbFont SetFont(eDvbFont Font);
bool Dirty(void);
bool Dirty(int &x1, int &y1, int &x2, int &y2);
void SetPixel(int x, int y, eDvbColor Color);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
int Width(void) { return width; }
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);
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
void Clean(void);
void Clear(void);
const char *Data(int x, int y);
};
class cDvbOsd : public cBitmap {
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
class cWindow;
class cDvbOsd {
private:
int videoDev;
int numWindows;
int x0, y0;
cWindow *window[MAXNUMWINDOWS];
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
cWindow *GetWindow(int x, int y);
public:
cDvbOsd(int VideoDev, int x1, int y1, int x2, int y2, int Bpp);
cDvbOsd(int VideoDev, int x, int y, int w = -1, int h = -1, int Bpp = -1);
~cDvbOsd();
bool Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, eDvbColor Color0 = clrTransparent, eDvbColor Color1 = clrTransparent, eDvbColor Color2 = clrTransparent, eDvbColor Color3 = clrTransparent);
void Flush(void);
void Clear(void);
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
void SetBitmap(int x, int y, const cBitmap &Bitmap);
int Width(unsigned char c);
int Width(const char *s);
eDvbFont SetFont(eDvbFont Font);
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
};
#endif //__DVBOSD_H

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

456
i18n.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: interface.c 1.35 2001/02/18 10:46:13 kls Exp $
* $Id: interface.c 1.39 2001/07/28 14:57:52 kls Exp $
*/
#include "interface.h"
@ -44,8 +44,13 @@ cInterface::~cInterface()
void cInterface::Open(int NumCols, int NumLines)
{
if (!open++)
if (!open++) {
if (NumCols == 0)
NumCols = Setup.OSDwidth;
if (NumLines == 0)
NumLines = Setup.OSDheight;
cDvbApi::PrimaryDvbApi->Open(width = NumCols, height = NumLines);
}
}
void cInterface::Close(void)
@ -281,16 +286,17 @@ void cInterface::Title(const char *s)
void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
{
ClearEol(0, -3, s ? BgColor : clrBackground);
int Line = (abs(height) == 1) ? 0 : -2;
ClearEol(0, Line, s ? BgColor : clrBackground);
if (s)
Write(0, -3, s, FgColor, BgColor);
Write(0, Line, s, FgColor, BgColor);
}
void cInterface::Info(const char *s)
{
Open();
Open(Setup.OSDwidth, -1);
isyslog(LOG_INFO, "info: %s", s);
Status(s, clrWhite, clrGreen);
Status(s, clrBlack, clrGreen);
Wait();
Status(NULL);
Close();
@ -298,7 +304,7 @@ void cInterface::Info(const char *s)
void cInterface::Error(const char *s)
{
Open();
Open(Setup.OSDwidth, -1);
esyslog(LOG_ERR, "ERROR: %s", s);
Status(s, clrWhite, clrRed);
Wait();
@ -310,7 +316,7 @@ bool cInterface::Confirm(const char *s)
{
Open();
isyslog(LOG_INFO, "confirm: %s", s);
Status(s, clrBlack, clrGreen);
Status(s, clrBlack, clrYellow);
bool result = Wait(10) == kOk;
Status(NULL);
Close();

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.21 2000/12/09 10:48:41 kls Exp $
* $Id: interface.h 1.22 2001/07/27 11:38:01 kls Exp $
*/
#ifndef __INTERFACE_H
@ -32,7 +32,7 @@ private:
public:
cInterface(int SVDRPport = 0);
~cInterface();
void Open(int NumCols = MenuColumns, int NumLines = MenuLines);
void Open(int NumCols = 0, int NumLines = 0);
void Close(void);
int Width(void) { return width; }
int Height(void) { return height; }

250
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.88 2001/07/28 16:17:28 kls Exp $
*/
#include "menu.h"
@ -118,21 +118,24 @@ eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
class cMenuEditBoolItem : public cMenuEditIntItem {
protected:
const char *falseString, *trueString;
virtual void Set(void);
public:
cMenuEditBoolItem(const char *Name, int *Value);
cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL);
};
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value)
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
:cMenuEditIntItem(Name, Value, 0, 1)
{
falseString = FalseString ? FalseString : tr("no");
trueString = TrueString ? TrueString : tr("yes");
Set();
}
void cMenuEditBoolItem::Set(void)
{
char buf[16];
snprintf(buf, sizeof(buf), "%s", *value ? tr("yes") : tr("no"));
snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
SetValue(buf);
}
@ -274,7 +277,12 @@ cMenuEditTimeItem::cMenuEditTimeItem(const char *Name, int *Value)
void cMenuEditTimeItem::Set(void)
{
char buf[10];
snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm);
switch (pos) {
case 1: snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break;
case 2: snprintf(buf, sizeof(buf), "%02d:--", hh); break;
case 3: snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break;
default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm);
}
SetValue(buf);
}
@ -538,10 +546,13 @@ cMenuEditChannel::cMenuEditChannel(int Index)
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency, 10000, 13000)); //TODO exact limits???
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("Srate"), &data.srate, 22000, 30000)); //TODO exact limits - toggle???
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Apid1"), &data.apid1, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Apid2"), &data.apid2, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0xFFFE));
Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 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));
}
@ -579,7 +590,7 @@ cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
index = Index;
channel = Channel;
if (channel->groupSep)
SetColor(clrWhite, clrBlue);
SetColor(clrWhite, clrCyan);
Set();
}
@ -589,7 +600,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);
}
@ -868,7 +879,7 @@ public:
cMenuText::cMenuText(const char *Title, const char *Text, eDvbFont Font)
:cOsdMenu(Title)
{
Add(new cMenuTextItem(Text, 1, 2, MenuColumns - 2, MAXOSDITEMS, clrWhite, clrBackground, Font));
Add(new cMenuTextItem(Text, 1, 2, Setup.OSDwidth - 2, MAXOSDITEMS, clrWhite, clrBackground, Font));
}
eOSState cMenuText::ProcessKey(eKeys Key)
@ -904,13 +915,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 +974,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,
@ -1137,20 +1148,20 @@ cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch)
// like all the others? Well, at least like those who actually send the full range
// of information (like, e.g., 'Sat.1'). Some stations (like 'RTL') don't even
// bother sending anything but the 'Title'...
if (isempty(ExtendedDescription) && !isempty(Subtitle) && strlen(Subtitle) > 2 * MenuColumns) {
if (isempty(ExtendedDescription) && !isempty(Subtitle) && int(strlen(Subtitle)) > 2 * Setup.OSDwidth) {
ExtendedDescription = Subtitle;
Subtitle = NULL;
}
if (!isempty(Title)) {
Add(item = new cMenuTextItem(Title, 1, Line, MenuColumns - 2, -1, clrCyan));
Add(item = new cMenuTextItem(Title, 1, Line, Setup.OSDwidth - 2, -1, clrCyan));
Line += item->Height() + 1;
}
if (!isempty(Subtitle)) {
Add(item = new cMenuTextItem(Subtitle, 1, Line, MenuColumns - 2, -1, clrYellow));
Add(item = new cMenuTextItem(Subtitle, 1, Line, Setup.OSDwidth - 2, -1, clrYellow));
Line += item->Height() + 1;
}
if (!isempty(ExtendedDescription))
Add(new cMenuTextItem(ExtendedDescription, 1, Line, MenuColumns - 2, Height() - Line - 2, clrCyan), true);
Add(new cMenuTextItem(ExtendedDescription, 1, Line, Setup.OSDwidth - 2, Height() - Line - 2, clrCyan), true);
SetHelp(tr("Record"), NULL, NULL, CanSwitch ? tr("Switch") : NULL);
}
}
@ -1265,7 +1276,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 +1402,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,14 +1619,22 @@ 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("DiSEqC"), &data.DiSEqC));
Add(new cMenuEditBoolItem(tr("SetSystemTime"), &data.SetSystemTime));
Add(new cMenuEditIntItem( tr("MarginStart"), &data.MarginStart));
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));
Add(new cMenuEditBoolItem(tr("VideoFormat"), &data.VideoFormat, "4:3", "16:9"));
Add(new cMenuEditBoolItem(tr("ChannelInfoPos"), &data.ChannelInfoPos, tr("bottom"), tr("top")));
Add(new cMenuEditIntItem( tr("OSDwidth"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
Add(new cMenuEditIntItem( tr("OSDheight"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
}
eOSState cMenuSetup::ProcessKey(eKeys Key)
@ -1626,6 +1645,7 @@ eOSState cMenuSetup::ProcessKey(eKeys Key)
switch (Key) {
case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osEnd;
cDvbApi::PrimaryDvbApi->SetUseTSTime(data.SetSystemTime);
cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
Setup = data;
Setup.Save();
break;
@ -1722,7 +1742,7 @@ cMenuMain::cMenuMain(bool Replaying)
}
if (cVideoCutter::Active())
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit));
SetHelp(tr("Record"), NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL);
SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display();
lastActivity = time(NULL);
SetHasHotkeys();
@ -1753,14 +1773,22 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
}
break;
default: switch (Key) {
case kMenu: state = osEnd; break;
case kRed: if (!HasSubMenu())
state = osRecord;
break;
case kBlue: if (!HasSubMenu())
state = osReplay;
break;
default: break;
case kMenu: state = osEnd; break;
case kRed: if (!HasSubMenu())
state = osRecord;
break;
case kGreen: if (!HasSubMenu()) {
if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) {
Interface->Clear();
cDvbApi::PrimaryDvbApi->ToggleAudioTrack();
state = osEnd;
}
}
break;
case kBlue: if (!HasSubMenu())
state = osReplay;
break;
default: break;
}
}
if (Key != kNone)
@ -1772,7 +1800,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
// --- cDisplayChannel -------------------------------------------------------
#define DIRECTCHANNELTIMEOUT 500 //ms
#define DIRECTCHANNELTIMEOUT 1000 //ms
#define INFOTIMEOUT 5000 //ms
cDisplayChannel::cDisplayChannel(int Number, bool Switched, bool Group)
@ -1783,7 +1811,7 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched, bool Group)
lines = 0;
oldNumber = number = 0;
cChannel *channel = Group ? Channels.Get(Number) : Channels.GetByNumber(Number);
Interface->Open(MenuColumns, 5);
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? 5 : -5);
if (channel) {
DisplayChannel(channel);
DisplayInfo();
@ -1797,7 +1825,7 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
oldNumber = cDvbApi::CurrentChannel();
number = 0;
lastTime = time_ms();
Interface->Open(MenuColumns, 5);
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? 5 : -5);
ProcessKey(FirstKey);
}
@ -1810,21 +1838,20 @@ cDisplayChannel::~cDisplayChannel()
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
{
if (Channel && Channel->number)
if (Channel && Channel->number > 0)
Interface->DisplayChannelNumber(Channel->number);
int BufSize = Width() + 1;
char buffer[BufSize];
if (Channel && Channel->number)
snprintf(buffer, BufSize, "%d %s", Channel->number, Channel->name);
if (Channel && Channel->number > 0)
snprintf(buffer, BufSize, "%d%s %s", Channel->number, number ? "-" : "", Channel->name);
else
snprintf(buffer, BufSize, "%s", Channel ? Channel->name : tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, MenuColumns, 1, clrBackground);
Interface->Fill(0, 0, Setup.OSDwidth, 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)
@ -1857,7 +1884,7 @@ void cDisplayChannel::DisplayInfo(void)
if (Lines > lines) {
const int t = 6;
int l = 1;
Interface->Fill(0, 1, MenuColumns, Lines, clrBackground);
Interface->Fill(0, 1, Setup.OSDwidth, Lines, clrBackground);
if (!isempty(PresentTitle)) {
Interface->Write(0, l, Present->GetTimeString(), clrYellow, clrBackground);
Interface->Write(t, l, PresentTitle, clrCyan, clrBackground);
@ -1945,11 +1972,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 +2009,7 @@ bool cRecordControl::Process(void)
{
if (!timer || !timer->Matches())
return false;
AssertFreeDiskSpace();
AssertFreeDiskSpace(timer->priority);
return true;
}
@ -1993,7 +2023,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++) {
@ -2078,7 +2108,7 @@ public:
};
cProgressBar::cProgressBar(int Width, int Height, int Current, int Total, const cMarks &Marks)
:cBitmap(Width, Height)
:cBitmap(Width, Height, 2)
{
total = Total;
if (total > 0) {
@ -2119,6 +2149,8 @@ cReplayControl::cReplayControl(void)
{
dvbApi = cDvbApi::PrimaryDvbApi;
visible = shown = displayFrames = false;
lastCurrent = lastTotal = -1;
timeoutShow = 0;
if (fileName) {
marks.Load(fileName);
dvbApi->StartReplay(fileName);
@ -2152,12 +2184,14 @@ void cReplayControl::ClearLastReplayed(const char *FileName)
}
}
void cReplayControl::Show(void)
void cReplayControl::Show(int Seconds)
{
if (!visible) {
Interface->Open(MenuColumns, -3);
Interface->Open(Setup.OSDwidth, -3);
needsFastResponse = visible = true;
shown = ShowProgress(true);
if (Seconds > 0)
timeoutShow = time(NULL) + Seconds;
}
}
@ -2178,21 +2212,27 @@ bool cReplayControl::ShowProgress(bool Initial)
Interface->Clear();
if (title)
Interface->Write(0, 0, title);
displayFrames = marks.Count() > 0;
lastCurrent = lastTotal = -1;
}
Interface->Write(-7, 2, IndexToHMSF(Total));
Interface->Flush();
if (Total != lastTotal) {
Interface->Write(-7, 2, IndexToHMSF(Total));
Interface->Flush();
lastTotal = Total;
}
if (Current != lastCurrent) {
#ifdef DEBUG_OSD
int p = Width() * Current / Total;
Interface->Fill(0, 1, p, 1, clrGreen);
Interface->Fill(p, 1, Width() - p, 1, clrWhite);
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();
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();
Interface->Write(0, 2, IndexToHMSF(Current, displayFrames));
Interface->Flush();
lastCurrent = Current;
}
return true;
}
return false;
@ -2205,22 +2245,24 @@ void cReplayControl::MarkToggle(void)
cMark *m = marks.Get(Current);
if (m)
marks.Del(m);
else
else {
marks.Add(Current);
Show(2);
}
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);
if (marks.Count()) {
int Current, Total;
if (dvbApi->GetIndex(Current, Total)) {
cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current);
if (m)
dvbApi->Goto(m->position, true);
}
displayFrames = true;
}
}
@ -2230,6 +2272,7 @@ void cReplayControl::MarkMove(bool Forward)
if (dvbApi->GetIndex(Current, Total)) {
cMark *m = marks.Get(Current);
if (m) {
displayFrames = true;
int p = dvbApi->SkipFrames(Forward ? 1 : -1);
cMark *m2;
if (Forward) {
@ -2281,8 +2324,16 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
{
if (!dvbApi->Replaying())
return osEnd;
if (visible)
shown = ShowProgress(!shown) || shown;
if (visible) {
if (timeoutShow && time(NULL) > timeoutShow) {
Hide();
timeoutShow = 0;
}
else
shown = ShowProgress(!shown) || shown;
}
bool DisplayedFrames = displayFrames;
displayFrames = false;
switch (Key) {
// Positioning:
case kUp: dvbApi->Play(); break;
@ -2299,23 +2350,34 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
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;
default: return osUnknown;
default: {
switch (Key) {
// 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;
default: {
displayFrames = DisplayedFrames;
switch (Key) {
// Menu control:
case kMenu: Hide(); return osMenu; // allow direct switching to menu
case kOk: visible ? Hide() : Show(); break;
case kBack: return osRecordings;
default: return osUnknown;
}
}
}
}
}
if (DisplayedFrames && !displayFrames)
Interface->Fill(0, 2, Width() / 2, 1, clrBackground);
return osContinue;
}

6
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.18 2001/02/11 10:30:35 kls Exp $
* $Id: menu.h 1.20 2001/07/28 13:59:29 kls Exp $
*/
#ifndef _MENU_H
@ -83,7 +83,9 @@ private:
cDvbApi *dvbApi;
cMarks marks;
bool visible, shown, displayFrames;
void Show(void);
int lastCurrent, lastTotal;
time_t timeoutShow;
void Show(int Seconds = 0);
void Hide(void);
static char *fileName;
static char *title;

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.22 2001/07/27 11:33:30 kls Exp $
*/
#ifndef __OSD_H
@ -14,7 +14,7 @@
#include "interface.h"
#include "tools.h"
#define MAXOSDITEMS 9
#define MAXOSDITEMS (Setup.OSDheight - 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.32 2001/06/16 10:33:20 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,13 +94,16 @@ void AssertFreeDiskSpace(void)
cRecording *r = Recordings.First();
cRecording *r0 = NULL;
while (r) {
if ((time(NULL) - r->start) / SECSINDAY > r->lifetime) {
if (r0) {
if (r->priority < r0->priority)
if (r->lifetime < MAXLIFETIME) { // 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 || (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;
}
else
r0 = r;
}
r = Recordings.Next(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);
@ -174,18 +177,31 @@ void cResumeFile::Delete(void)
// --- cRecording ------------------------------------------------------------
struct tCharExchange { char a; char b; };
tCharExchange CharExchange[] = {
{ ' ', '_' },
{ '\'', '\x01' },
{ '/', '\x02' },
#ifdef VFAT
{ ':', '\x03' },
#endif
{ 0, 0 }
};
char *ExchangeChars(char *s, bool ToFileSystem)
{
for (struct tCharExchange *ce = CharExchange; ce->a && ce->b; ce++)
strreplace(s, ToFileSystem ? ce->a : ce->b, ToFileSystem ? ce->b : ce->a);
return s;
}
cRecording::cRecording(cTimer *Timer)
{
titleBuffer = NULL;
fileName = NULL;
name = strdup(Timer->file);
// substitute characters that would cause problems in file names:
for (char *p = name; *p; p++) {
switch (*p) {
case '\n': *p = ' '; break;
case '/': *p = '-'; break;
}
}
strreplace(name, '\n', ' ');
summary = Timer->summary ? strdup(Timer->summary) : NULL;
if (summary)
strreplace(summary, '|', '\n');
@ -215,8 +231,7 @@ cRecording::cRecording(const char *FileName)
name = new char[p - FileName + 1];
strncpy(name, FileName, p - FileName);
name[p - FileName] = 0;
strreplace(name, '_', ' ');
strreplace(name, '\x01', '\'');
ExchangeChars(name, false);
}
// read an optional summary file:
char *SummaryFileName = NULL;
@ -239,7 +254,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);
@ -266,11 +281,9 @@ const char *cRecording::FileName(void)
{
if (!fileName) {
struct tm *t = localtime(&start);
ExchangeChars(name, true);
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) {
strreplace(fileName, ' ', '_');
strreplace(fileName, '\'', '\x01');
}
ExchangeChars(name, false);
}
return fileName;
}

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:

View File

@ -6,7 +6,7 @@
*
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
*
* $Id: remote.c 1.21 2001/02/04 19:17:59 kls Exp $
* $Id: remote.c 1.23 2001/07/27 10:17:19 kls Exp $
*/
#include "remote.h"
@ -439,7 +439,7 @@ void cRcIoLIRC::Action(void)
if (cFile::FileReady(f, REPEATLIMIT) && read(f, buf, sizeof(buf)) > 21) {
if (!receivedData) { // only accept new data the previous data has been fetched
int count;
sscanf(buf, "%*x %x %7s", &count, LastKeyName); // '7' in '%7s' is LIRC_KEY_BUF-1!
sscanf(buf, "%*x %x %29s", &count, LastKeyName); // '29' in '%29s' is LIRC_KEY_BUF-1!
int Now = time_ms();
if (count == 0) {
strcpy(keyName, LastKeyName);
@ -466,9 +466,11 @@ void cRcIoLIRC::Action(void)
}
}
else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release
receivedData = receivedRelease = true;
receivedRepeat = false;
WakeUp();
if (time_ms() - LastTime > REPEATDELAY) {
receivedData = receivedRelease = true;
receivedRepeat = false;
WakeUp();
}
}
}
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remote.h 1.14 2001/02/02 14:49:10 kls Exp $
* $Id: remote.h 1.15 2001/07/22 14:42:59 kls Exp $
*/
#ifndef __REMOTE_H
@ -81,7 +81,7 @@ public:
class cRcIoLIRC : public cRcIoBase, private cThread {
private:
enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 };
enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
int f;
char keyName[LIRC_KEY_BUF];
bool receivedData, receivedRepeat, receivedRelease;

539
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.5 2001/06/24 16:37:23 kls Exp $
*/
/* The calling interface of the 'cRemux::Process()' function is defined
@ -62,17 +66,390 @@
*/
#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
// Start codes:
#define SC_PICTURE 0x00 // "picture header"
#define MAXNONUSEFULDATA (10*1024*1024)
class cTS2PES {
private:
int size;
int found;
int count;
uint8_t *buf;
uint8_t cid;
uint8_t audioCid;
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, uint8_t AudioCid = 0x00);
~cTS2PES();
void ts_to_pes(const uint8_t *Buf); // don't need count (=188)
void Clear(void);
};
uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 };
cTS2PES::cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size, uint8_t AudioCid)
{
resultBuffer = ResultBuffer;
resultCount = ResultCount;
size = Size;
audioCid = AudioCid;
if (!(buf = new uint8_t[size]))
esyslog(LOG_ERR, "Not enough memory for ts_transform");
reset_ipack();
}
cTS2PES::~cTS2PES()
{
delete buf;
}
void cTS2PES::Clear(void)
{
reset_ipack();
}
void cTS2PES::store(uint8_t *Data, int Count)
{
if (*resultCount + Count > RESULTBUFFERSIZE) {
esyslog(LOG_ERR, "ERROR: result buffer overflow (%d + %d > %d)", *resultCount, Count, RESULTBUFFERSIZE);
Count = RESULTBUFFERSIZE - *resultCount;
}
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] = (AUDIO_STREAM_S <= cid && cid <= AUDIO_STREAM_E && audioCid) ? audioCid : 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(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure)
{
vPid = VPid;
aPid1 = APid1;
aPid2 = APid2;
dPid1 = DPid1;
dPid2 = DPid2;
exitOnFailure = ExitOnFailure;
synced = false;
skipped = 0;
resultCount = resultDelivered = 0;
vTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS);
aTS2PES1 = new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC0);
aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC1) : NULL;
dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, &resultCount, IPACKS) : NULL;
//XXX don't yet know how to tell apart primary and secondary DD data...
dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, &resultCount, IPACKS) : XXX*/ NULL;
}
cRemux::~cRemux()
{
delete vTS2PES;
delete aTS2PES1;
delete aTS2PES2;
delete dTS2PES1;
delete dTS2PES2;
}
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 +481,140 @@ 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)
void cRemux::SetAudioPid(int APid)
{
int Skip = 0;
aPid1 = APid;
vTS2PES->Clear();
aTS2PES1->Clear();
resultCount = resultDelivered = 0;
}
PictureType = NO_PICTURE;
const uchar *cRemux::Process(const uchar *Data, int &Count, int &Result, uchar *PictureType)
{
uchar dummyPictureType;
if (!PictureType)
PictureType = &dummyPictureType;
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]) {
case SC_VIDEO:
/*XXX
// test recording the raw TS:
Result = Count;
*PictureType = I_FRAME;
return Data;
XXX*/
// 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;
int pid = GetPid(Data + i + 1);
if (Data[i + 3] & 0x10) { // got payload
if (pid == vPid) vTS2PES->ts_to_pes(Data + i);
else if (pid == aPid1) aTS2PES1->ts_to_pes(Data + i);
else if (pid == aPid2 && aTS2PES2) aTS2PES2->ts_to_pes(Data + i);
else if (pid == dPid1 && dTS2PES1) dTS2PES1->ts_to_pes(Data + i);
else if (pid == dPid2 && dTS2PES2) dTS2PES2->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 > MAXNONUSEFULDATA) {
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 VIDEO_STREAM_S ... VIDEO_STREAM_E:
{
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!
case PRIVATE_STREAM1:
case AUDIO_STREAM_S ... AUDIO_STREAM_E:
{
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

37
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.5 2001/06/23 14:06:59 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,31 +19,32 @@
#define P_FRAME 2
#define B_FRAME 3
// Start codes:
#define SC_PICTURE 0x00 // "picture header"
#define SC_SEQU 0xB3 // "sequence header"
#define SC_PHEAD 0xBA // "pack header"
#define SC_SHEAD 0xBB // "system header"
#define SC_AUDIO 0xC0
#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)
#define RESULTBUFFERSIZE (MINVIDEODATA * 4)
typedef unsigned char uchar;
class cTS2PES;
class cRemux {
private:
#if defined(REMUX_NONE)
bool exitOnFailure;
bool synced;
int skipped;
int vPid, aPid1, aPid2, dPid1, dPid2;
cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2;
uchar resultBuffer[RESULTBUFFERSIZE];
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(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure = false);
~cRemux();
const uchar *Process(const uchar *Data, int &Count, int &Result, uchar &PictureType);
void SetAudioPid(int APid);
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/10 17:11:34 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/10 14:00:59 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);

36
runvdr
View File

@ -1,18 +1,44 @@
#!/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.8 2001/07/27 07:35:19 kls Exp $
DVBDIR="../DVB/driver"
VDRPRG="./vdr"
VDRCMD="$VDRPRG -w 60"
VDRCMD="$VDRPRG -w 60 $*"
LSMOD="`/sbin/lsmod | grep -w '^dvb' | wc -l`"
KILLPROC="/sbin/killproc -TERM"
# Load driver if it hasn't been loaded already:
if [ $LSMOD -eq 0 ] ; then
(cd $DVBDIR; make insmod)
fi
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 rmmod; make insmod)
date
done

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.18 2001/04/01 16:06:54 kls Exp $
* $Id: svdrp.c 1.20 2001/07/22 13:58:48 kls Exp $
*/
#define _GNU_SOURCE
@ -941,7 +941,7 @@ void cSVDRP::Process(void)
if (numChars > 0)
numChars--;
}
else if (c <= 0x03 || c == 0x0D || 0xF0 <= c) {
else if (c <= 0x03 || c == 0x0D) {
// ignore control characters
}
else if (numChars < sizeof(cmdLine) - 1) {
@ -955,8 +955,10 @@ void cSVDRP::Process(void)
}
lastActivity = time(NULL);
}
else if (r < 0)
else if (r <= 0) {
isyslog(LOG_INFO, "lost connection to SVDRP client");
Close();
}
}
else if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
isyslog(LOG_INFO, "timeout on SVDRP connection");

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.9 2001/06/27 11:34:41 kls Exp $
*/
#include "thread.h"
@ -14,12 +14,43 @@
#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.
time_t cThread::lastPanic = 0;
int cThread::panicLevel = 0;
bool cThread::signalHandlerInstalled = false;
bool cThread::emergencyExitRequested = false;
cThread::cThread(void)
{
@ -110,6 +141,33 @@ void cThread::WakeUp(void)
kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
}
#define MAXPANICLEVEL 10
void cThread::RaisePanic(void)
{
if (lastPanic > 0) {
if (time(NULL) - lastPanic < 5)
panicLevel++;
else if (panicLevel > 0)
panicLevel--;
}
lastPanic = time(NULL);
if (panicLevel > MAXPANICLEVEL) {
esyslog(LOG_ERR, "ERROR: max. panic level exceeded");
EmergencyExit(true);
}
else
dsyslog(LOG_INFO, "panic level: %d", panicLevel);
}
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.6 2001/06/27 11:22:04 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,9 @@ private:
pid_t parentPid, threadPid, lockingPid;
int locked;
bool running;
static time_t lastPanic;
static int panicLevel;
static bool emergencyExitRequested;
static bool signalHandlerInstalled;
static void SignalHandler(int signum);
static void *StartThread(cThread *Thread);
@ -45,6 +50,8 @@ public:
virtual ~cThread();
bool Start(void);
bool Active(void);
static void RaisePanic(void);
static bool EmergencyExit(bool Request = false);
};
// cThreadLock can be used to easily set a lock in a thread and make absolutely

22
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.32 2001/04/01 14:13:36 kls Exp $
* $Id: tools.c 1.34 2001/05/20 08:30:54 kls Exp $
*/
#define _GNU_SOURCE
@ -120,7 +120,7 @@ const char *AddDirectory(const char *DirName, const char *FileName)
return buf;
}
#define DFCMD "df -m '%s'"
#define DFCMD "df -m -P '%s'"
uint FreeDiskSpaceMB(const char *Directory)
{
@ -132,7 +132,7 @@ uint FreeDiskSpaceMB(const char *Directory)
if (p) {
char *s;
while ((s = readline(p)) != NULL) {
if (*s == '/') {
if (strchr(s, '/')) {
uint available;
sscanf(s, "%*s %*d %*d %u", &available);
Free = available;
@ -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 {

20
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.58 2001/06/23 12:29:41 kls Exp $
*/
#include <getopt.h>
@ -77,6 +77,7 @@ int main(int argc, char *argv[])
char *Terminal = NULL;
static struct option long_options[] = {
{ "audio", required_argument, NULL, 'a' },
{ "config", required_argument, NULL, 'c' },
{ "daemon", no_argument, NULL, 'd' },
{ "device", required_argument, NULL, 'D' },
@ -91,8 +92,10 @@ int main(int argc, char *argv[])
int c;
int option_index = 0;
while ((c = getopt_long(argc, argv, "c:dD:hl:p:v:w:t:", long_options, &option_index)) != -1) {
while ((c = getopt_long(argc, argv, "a:c:dD:hl:p:v:w:t:", long_options, &option_index)) != -1) {
switch (c) {
case 'a': cDvbApi::SetAudioCommand(optarg);
break;
case 'c': ConfigDirectory = optarg;
break;
case 'd': DaemonMode = true; break;
@ -107,6 +110,7 @@ int main(int argc, char *argv[])
return 2;
break;
case 'h': printf("Usage: vdr [OPTION]\n\n" // for easier orientation, this is column 80|
" -a CMD, --audio=CMD send Dolby Digital audio to stdin of command CMD\n"
" -c DIR, --config=DIR read config files from DIR (default is to read them\n"
" from the video directory)\n"
" -h, --help display this help and exit\n"
@ -267,6 +271,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 +397,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 +411,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;