mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
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:
parent
610c5600df
commit
8f9cc68f76
36
CONTRIBUTORS
36
CONTRIBUTORS
@ -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
22
FORMATS
@ -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
163
HISTORY
@ -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
16
INSTALL
@ -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
48
MANUAL
@ -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
|
||||
|
||||
|
8
Makefile
8
Makefile
@ -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
|
||||
|
@ -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.)
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
#!/bin/sh
|
||||
cat cut | head -n 1 | tr -d [\\\\]
|
||||
cat cut2 | head -n 1 | tr -d [\\\\]
|
||||
|
@ -1,4 +1,2 @@
|
||||
#!/bin/sh
|
||||
cutdir=/x1/video/
|
||||
|
||||
find $cutdir -name "cut" -exec cutall2 {} \;
|
||||
find /x1/video/ -name "cut" -exec cutall2 {} \;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
a=`echo $1 | cut -d / -f1-5`
|
||||
cd $a
|
||||
cutt
|
||||
cutall3.pl
|
||||
mv cut cut.bak
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
||||
|
@ -5,7 +5,7 @@ do
|
||||
if [ -f newpic ]; then
|
||||
killall xli
|
||||
rm -f newpic
|
||||
xli output.ppm &
|
||||
xli output000.ppm &
|
||||
fi
|
||||
sleep 24h
|
||||
done
|
||||
|
@ -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
|
||||
|
124
channels.conf
124
channels.conf
@ -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
|
||||
|
81
config.c
81
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.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);
|
||||
|
26
config.h
26
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.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);
|
||||
|
75
dvbapi.h
75
dvbapi.h
@ -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
352
dvbosd.c
@ -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);
|
||||
}
|
||||
|
||||
|
84
dvbosd.h
84
dvbosd.h
@ -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
263
eit.c
@ -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
10
eit.h
@ -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; }
|
||||
};
|
||||
|
22
interface.c
22
interface.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.c 1.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();
|
||||
|
@ -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
250
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.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
6
menu.h
@ -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
4
osd.h
@ -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,
|
||||
|
57
recording.c
57
recording.c
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
12
remote.c
12
remote.c
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
remote.h
4
remote.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: remote.h 1.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
539
remux.c
@ -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
37
remux.h
@ -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
|
||||
|
37
ringbuffer.c
37
ringbuffer.c
@ -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)
|
||||
|
@ -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
36
runvdr
@ -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
|
||||
|
8
svdrp.c
8
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 1.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");
|
||||
|
60
thread.c
60
thread.c
@ -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)
|
||||
|
17
thread.h
17
thread.h
@ -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
22
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 1.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)
|
||||
|
3
tools.h
3
tools.h
@ -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
20
vdr.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user