Compare commits

..

13 Commits

Author SHA1 Message Date
Klaus Schmidinger
cd53d57779 Fixed a crash in the LCARS skin's main menu in case there is no current channel 2013-05-19 12:09:55 +02:00
Klaus Schmidinger
0d14872adc Fixed an endless loop in the DrawEllipse() functions for very small ellipses 2013-05-18 12:43:41 +02:00
Klaus Schmidinger
90f4648a7c Fixed unwanted version tag on checkout of older version 2013-05-02 10:21:37 +02:00
Klaus Schmidinger
be88699b00 Fixed an error message when parsing SCR values in diseqc.conf 2013-05-02 09:33:47 +02:00
Klaus Schmidinger
1b1fe2c887 Fixed no longer generating any editing marks if the edited recording results in just one single sequence 2013-05-02 09:23:21 +02:00
Klaus Schmidinger
fa77b5c2b2 Fixed displaying the frame number when setting an editing mark 2013-04-27 10:34:08 +02:00
Klaus Schmidinger
cffde6ee09 Fixed multiple occurrences of the same directory in the recordings list in case there are directories that only differ in non-alphanumeric characters 2013-04-27 10:18:08 +02:00
Klaus Schmidinger
2266b0e633 Adjusted release date 2013-04-13 11:30:25 +02:00
Klaus Schmidinger
06f7c2d414 Changed cThread::SetIOPriority() from "best effort class" to "idle class" in order to improve overall performance when an editing process is running 2013-04-11 08:59:26 +02:00
Klaus Schmidinger
1b1dc6d775 Fixed handling '/' and '~' in recording file names in case DirectoryEncoding is used 2013-04-11 08:24:04 +02:00
Klaus Schmidinger
e5971d2684 Added definitions for older DVB API versions, back until 5.0 2013-04-09 13:44:50 +02:00
Klaus Schmidinger
ae208771e8 Fixed an endless loop in cTextWrapper::Set() in case the given Width is smaller than one character 2013-04-07 14:54:15 +02:00
Klaus Schmidinger
df4ea10419 Fixed initializing cDevice::keepTracks 2013-04-05 10:48:51 +02:00
252 changed files with 10625 additions and 35394 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1658,7 +1658,7 @@ UML_LOOK = NO
# the class node. If there are many fields or methods and many nodes the # the class node. If there are many fields or methods and many nodes the
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
# threshold limits the number of items for each type to make the size more # threshold limits the number of items for each type to make the size more
# manageable. Set this to 0 for no limit. Note that the threshold may be # managable. Set this to 0 for no limit. Note that the threshold may be
# exceeded by 50% before the limit is enforced. # exceeded by 50% before the limit is enforced.
UML_LIMIT_NUM_FIELDS = 10 UML_LIMIT_NUM_FIELDS = 10

2287
HISTORY

File diff suppressed because it is too large Load Diff

146
INSTALL
View File

@ -1,7 +1,7 @@
Installation of the Video Disk Recorder Installation of the Video Disk Recorder
--------------------------------------- ---------------------------------------
Version 2.7 Version 2.0
----------- -----------
Compiling and running the program: Compiling and running the program:
@ -47,9 +47,9 @@ By default the 'vdr' program can be controlled via the PC keyboard.
If you want to disable control via the keyboard, you can add NO_KBD=1 If you want to disable control via the keyboard, you can add NO_KBD=1
to the 'make' call, or use the '--no-kbd' option at runtime. to the 'make' call, or use the '--no-kbd' option at runtime.
If you have a LIRC compatible infrared remote control receiver you can define If you have an infrared remote control unit you can define the REMOTE macro
the REMOTE macro to one of the following values in the 'make' call to make to one of the following values in the 'make' call to make the respective control
the respective control the default: the default:
REMOTE=LIRC control via the "Linux Infrared Remote Control" REMOTE=LIRC control via the "Linux Infrared Remote Control"
(see http://www.lirc.org) (see http://www.lirc.org)
@ -73,15 +73,16 @@ port ("Simple Video Disk Recorder Protocol"). By default, it listens
on port 6419 (use the --port=PORT option to change this). For details on port 6419 (use the --port=PORT option to change this). For details
about the SVDRP syntax see the source file 'svdrp.c'. about the SVDRP syntax see the source file 'svdrp.c'.
WARNING: DUE TO THE OPEN SVDRP PORT THIS PROGRAM MAY CONSTITUTE A
======= POTENTIAL SECURITY HAZARD! IF YOU ARE NOT RUNNING VDR IN
A CONTROLLED ENVIRONMENT, YOU MAY WANT TO DISABLE SVDRP
BY USING '--port=0'!
The file 'svdrphosts.conf' can be used to define which hosts are allowed The file 'svdrphosts.conf' can be used to define which hosts are allowed
to access the SVDRP port. By default only localhost (127.0.0.1) is granted to access the SVDRP port. By default only localhost (127.0.0.1) is granted
access. If you want to give other hosts access to your SVDRP port you need to access. If you want to give other hosts access to your SVDRP port you need to
add their IP numbers to 'svdrphosts.conf'. add their IP numbers to 'svdrphosts.conf'.
You can disable SVDRP access entirely by either running VDR with '--port=0',
or by removing all entries (including 127.0.0.1 for the localhost) from
'svdrphosts.conf'.
If the program shall run as a daemon, use the --daemon option. This If the program shall run as a daemon, use the --daemon option. This
will completely detach it from the terminal and will continue as a will completely detach it from the terminal and will continue as a
background process. background process.
@ -93,24 +94,6 @@ vdr:123:respawn:/usr/local/bin/vdr --terminal=/dev/tty8 -w 60
See the man page vdr(1) for complete information about all command line options. See the man page vdr(1) for complete information about all command line options.
Output devices
--------------
VDR by itself doesn't produce any audio or video output. In order to watch
live tv or recordings, you will need to use a plugin that supports the actual
hardware in your system, for instance:
Plugin: Device:
dvbsddevice Full-Featured SD DVB cards (Fujitsu-Siemens Design)
ftp://ftp.tvdr.de/vdr/Plugins
dvbhddevice Full-featured HD DVB cards (Technotrend TT S2-6400)
https://bitbucket.org/powARman/dvbhddevice
rpihddevice Raspberry Pi
https://projects.vdr-developer.org/git/vdr-plugin-rpihddevice.git
See https://linuxtv.org/vdrwiki/index.php/Output_devices for more.
Standard compliance Standard compliance
------------------- -------------------
@ -151,14 +134,14 @@ displayed correctly. Since BiDi support adds some runtime overhead by requiring
additional memory allocation and copying, this feature is not compiled in additional memory allocation and copying, this feature is not compiled in
by default, so that users that have no need for this don't get any overhead. by default, so that users that have no need for this don't get any overhead.
Workaround for providers not encoding their DVB SI table strings correctly Workaround for providers not encoding their EPG data correctly
-------------------------------------------------------------------------- --------------------------------------------------------------
According to "ETSI EN 300 468" the default character set for SI data is According to "ETSI EN 300 468" the default character set fo SI data is
ISO6937. But unfortunately some broadcasters actually use ISO-8859-9 or ISO6937. But unfortunately some broadcasters actually use ISO-8859-9 or
other encodings, but fail to correctly announce that. other encodings, but fail to correctly announce that.
Users who want to set the default character set to something different can Users who want to set the default character set to something different can
do this by using the command line option --chartab with something do this by setting the environment variable VDR_CHARSET_OVERRIDE to something
like ISO-8859-9. like ISO-8859-9.
Start script with automatic restart in case of hangups: Start script with automatic restart in case of hangups:
@ -264,27 +247,23 @@ Executing commands before and after a recording:
------------------------------------------------ ------------------------------------------------
You can use the '-r' option to define a program or script that gets called You can use the '-r' option to define a program or script that gets called
at various stages of handling recordings. before and after a recording is performed, and after an editing process
has finished or a recording has been deleted.
The program will be called with two or three string parameters. The program will be called with two or three (in case of "edited") string
The first parameter is one of parameters. The first parameter is one of
before if this is *before* a recording starts before if this is *before* a recording starts
started if this is after a recording has *started*
after if this is *after* a recording has finished after if this is *after* a recording has finished
editing if this is before *editing* a recording
edited if this is after a recording has been *edited* edited if this is after a recording has been *edited*
deleted if this is after a recording has been *deleted* deleted if this is after a recording has been *deleted*
copying if this is before *copying* a recording
copied if this is after a recording has been *copied*
renamed if this is after a recording has been *renamed*
moved if this is after a recording has been *moved*
(note that a move across file system borders triggers a sequence
of "copying", "copied" and "deleted")
and the second and third parameter (if present) contain the full name of the recording's and the second parameter contains the full name of the recording's
directory (which may not yet exists at that moment in the "before" case). directory (which may not yet exists at that moment in the "before" case).
See the example below for the exact meaning of these parameters. In the "edited" case it will be the name of the edited version (second
parameter) and the name of the source version (third parameter).
In the "deleted" case the extension of the directory name is ".del"
instead of ".rec".
Within this program you can do anything you would like to do before and/or Within this program you can do anything you would like to do before and/or
after a recording or after an editing process. However, the program must return after a recording or after an editing process. However, the program must return
@ -300,16 +279,9 @@ case "$1" in
before) before)
echo "Before recording $2" echo "Before recording $2"
;; ;;
started)
echo "Started recording $2"
;;
after) after)
echo "After recording $2" echo "After recording $2"
;; ;;
editing)
echo "Editing recording $2"
echo "Source recording $3"
;;
edited) edited)
echo "Edited recording $2" echo "Edited recording $2"
echo "Source recording $3" echo "Source recording $3"
@ -317,22 +289,6 @@ case "$1" in
deleted) deleted)
echo "Deleted recording $2" echo "Deleted recording $2"
;; ;;
copying)
echo "Destination recording $2"
echo "Source recording $3"
;;
copied)
echo "Destination recording $2"
echo "Source recording $3"
;;
renamed)
echo "New name of recording $2"
echo "Old name of recording $3"
;;
moved)
echo "New path of recording $2"
echo "Old path of recording $3"
;;
*) *)
echo "ERROR: unknown state: $1" echo "ERROR: unknown state: $1"
;; ;;
@ -369,9 +325,38 @@ Note that the file system need not be 64-bit proof, since the 'vdr'
program splits video files into chunks of about 2GB. You should use program splits video files into chunks of about 2GB. You should use
a disk with several gigabytes of free space. One GB can store roughly a disk with several gigabytes of free space. One GB can store roughly
half an hour of SD video data, or 10 minutes of HD video. half an hour of SD video data, or 10 minutes of HD video.
Either use one of today's large terabyte disks (preferably with a backup disk
in a RAID-1 array), or use something like "mhddfs" to group several disks If you have more than one disk and don't want to combine them to form
into one large volume. one large logical volume, you can set up several video directories as
mount points for these disks. All of these directories must have the
same basic name and must end with a numeric part, which starts at 0 for
the main directory and has increasing values for the rest of the
directories. For example
/srv/vdr/video0
/srv/vdr/video1
/srv/vdr/video2
would be a setup with three directories. You can use more than one
numeric digit:
/mnt/MyVideos/vdr.00
/mnt/MyVideos/vdr.01
/mnt/MyVideos/vdr.02
...
/mnt/MyVideos/vdr.11
would set up twelve disks (wow, what a machine that would be!).
To use such a multi directory setup, you need to add the '-v' option
with the name of the basic directory when running 'vdr':
vdr -v /srv/vdr/video0
WARNING: Using multiple disks to form one large video directory this way
is deprecated and will be removed from VDR in a future version! Either
use one of today's large terabyte disks (preferably with a backup disk
in a RAID-1 array), or use something like "mhddfs".
Note that you should not copy any non-VDR files into the video directory, Note that you should not copy any non-VDR files into the video directory,
since this might cause a lot of unnecessary disk access when VDR cleans up those since this might cause a lot of unnecessary disk access when VDR cleans up those
@ -431,9 +416,8 @@ access your DiSEqC equipment (see man vdr(5) for details).
A special form of DiSEqC is used to connect several receivers to one signal A special form of DiSEqC is used to connect several receivers to one signal
source using only a single cable. This method, known as "Satellite Channel Routing" source using only a single cable. This method, known as "Satellite Channel Routing"
according to EN50494 (aka "Unicable(TM)", "OLT(TM)", "SatCR", "Single Cable according to EN50494 (aka "Unicable(TM)", "OLT(TM)", "SatCR", "Single Cable
Distribution", "Channel Stacking System" or "Single Cable Interface") or Distribution", "Channel Stacking System" or "Single Cable Interface") uses
EN50607 (aka "JESS") uses the file "scr.conf" to specify which SCR channels the file "scr.conf" to specify which SCR channels use which user band frequency.
use which user band frequency.
If DVB-S devices need to be connected to the same satellite cable, but no If DVB-S devices need to be connected to the same satellite cable, but no
"Satellite Channel Routing" is available, they can be set to be "bonded" in "Satellite Channel Routing" is available, they can be set to be "bonded" in
@ -484,17 +468,19 @@ for a detailed description).
The recommended PC key assignments are: The recommended PC key assignments are:
Up, Down, Left, Right Cursor keys Up, Down, Left, Right Crsr keys in numeric block
Menu 'Home' Menu 'Home' in numeric block
Ok 'Enter' Ok 'Enter'
Back 'Backspace' Back 'End' in numeric block
Red, Green, Yellow, Blue 'F1'..'F4' Red, Green, Yellow, Blue 'F1'..'F4'
0..9 '0'..'9' 0..9 '0'..'9' in top row
Volume+/- 'PgUp', 'PgDn' Power 'P'
Mute 'F10' Volume+/- '+', '-'
Mute 'm'
If you want to change your key assignments later, simply delete the file If you prefer different key assignments, or if the default doesn't work for
'remote.conf' and restart 'vdr' to get into learning mode. your keyboard, simply delete the file 'remote.conf' and restart 'vdr' to get
into learning mode.
Generating source code documentation: Generating source code documentation:
------------------------------------- -------------------------------------

391
MANUAL
View File

@ -1,7 +1,7 @@
Video Disk Recorder User's Manual Video Disk Recorder User's Manual
--------------------------------- ---------------------------------
Version 2.7 Version 2.0
----------- -----------
* Remote Control Keys * Remote Control Keys
@ -50,8 +50,8 @@ Version 2.7
Next Next/previous channel group (in live tv mode) Next Next/previous channel group (in live tv mode)
Prev or next/previous editing mark (in replay mode) Prev or next/previous editing mark (in replay mode)
Channel+ channel up (live view), next error (replay) Channel+ channel up
Channel- channel down (live view), previous error (replay) Channel- channel down
PrevChannel previous channel PrevChannel previous channel
Power shutdown Power shutdown
@ -90,7 +90,7 @@ Version 2.7
be treated as part of that number, not as a sort mode toggle. If no numeric be treated as part of that number, not as a sort mode toggle. If no numeric
key has been pressed for more than one second, the number is reset and '0' key has been pressed for more than one second, the number is reset and '0'
functions as sort mode toggle again. functions as sort mode toggle again.
(3) In the "Edit timer" menu, when on the "Day" item, the '0' key toggles between (3) In the "Timers" menu, when on the "Day" item, the '0' key toggles between
a single shot and a repeating timer. If "Day" indicates a repeating timer, a single shot and a repeating timer. If "Day" indicates a repeating timer,
the keys '1'...'7' can be used to toggle the individual days ('1' is Monday). the keys '1'...'7' can be used to toggle the individual days ('1' is Monday).
@ -264,7 +264,7 @@ Version 2.7
* Pausing live video * Pausing live video
If you want to pause the live programme you are just watching, simply press If you want to pause the live programme you are just watching, simple press
"Menu/Yellow" or "Pause" on your remote control. VDR will start an instant "Menu/Yellow" or "Pause" on your remote control. VDR will start an instant
recording of the current channel (just as if you had pressed "Menu/Red" or recording of the current channel (just as if you had pressed "Menu/Red" or
"Record") and immediately begin replaying that recording. Replay will be "Record") and immediately begin replaying that recording. Replay will be
@ -276,9 +276,6 @@ Version 2.7
in the "Setup/Recording" menu. Recording time will be the same as for in the "Setup/Recording" menu. Recording time will be the same as for
any other instant recording, so by default it will record 3 hours (which any other instant recording, so by default it will record 3 hours (which
should be enough for any normal broadcast). should be enough for any normal broadcast).
Note that the timer that is created for recording the paused live video will
always record on the local VDR, even if an "SVDRP default host" has been
set for normal timer recordings.
* Replaying a Recording * Replaying a Recording
@ -366,30 +363,15 @@ Version 2.7
- 0 Toggles an editing mark. If the mark indicator shows a red triangle, - 0 Toggles an editing mark. If the mark indicator shows a red triangle,
the current mark is deleted. Otherwise a new mark is set at the the current mark is deleted. Otherwise a new mark is set at the
current position. current position.
- 1, 3 Move an editing mark back and forward in "adaptive" mode. Pressing - 4, 6 Move an editing mark back and forward. You need to first jump to
either of these keys for the first time moves the mark 120 seconds an editing mark for this to work.
in the given direction (configurable via "Setup/Replay/Initial
duration for adaptive skipping"). Further presses of the same key
keep moving the mark by the same value. Once the other key is
pressed, the value is divided by 2 (hence the name "adaptive") with
every further press of either key. Pressing '1' and '3'
alternatingly divides the distance all the way down to a single
I-frame. That way a particular place in a recording (for instance
the beginning or end of a commercial break) can be found very
quickly. If none of these two keys is pressed for a while
(configurable via "Setup/Replay/Reset timeout for adaptive
skipping") the distance falls back to the initial value.
If replay is not in Pause mode, or if there is no mark at the
current position, the skip is performed without moving any mark.
- 4, 6 Move an editing mark back and forward by one I-frame. You need to
first jump to an editing mark for this to work.
- 7, 9 Jump back and forward between editing marks. Replay goes into still - 7, 9 Jump back and forward between editing marks. Replay goes into still
mode after jumping to a mark. If the current position is at the mode after jumping to a mark. If the current position is at the
first or last mark, or if there are no marks at all, these keys first or last mark, or if there are no marks at all, these keys
jump to the very beginning or end, respectively, of the recording. jump to the very beginning or end, respectively, of the recording.
- 8 Positions replay at a point 3 seconds before the current or next - 8 Positions replay at a point 3 seconds before the current or next
"begin" mark and starts replay. "begin" mark and starts replay.
- 2 Starts the actual cutting process. - 2 Start the actual cutting process.
Editing marks are represented by black, vertical lines in the progress display. Editing marks are represented by black, vertical lines in the progress display.
A small black triangle at the top of the mark means that this is a "begin" A small black triangle at the top of the mark means that this is a "begin"
@ -480,8 +462,6 @@ Version 2.7
"forever", and a value of 0 means that this recording can be "forever", and a value of 0 means that this recording can be
deleted any time if a recording with a higher priority needs disk deleted any time if a recording with a higher priority needs disk
space. space.
Pattern: The pattern to use for recordings matching events (only available
for pattern timers). See section "Pattern timers" below.
File: The name under which a recording created through this timer will 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 be stored on disk (the actual name will also contain the date and
time, so it is possible to have a "repeating timer" store all its time, so it is possible to have a "repeating timer" store all its
@ -503,9 +483,6 @@ Version 2.7
the name of the recording. the name of the recording.
First day: The date of the first day when this timer shall start recording First day: The date of the first day when this timer shall start recording
(only available for repeating timers). (only available for repeating timers).
Record on: The name of the remote VDR this timer shall record on (only available
if there are any remote VDRs connected to this VDR). If this field
is empty, the timer will record on the local VDR.
A timer can also be programmed by pressing the "Red" key on the "Schedule", A timer can also be programmed by pressing the "Red" key on the "Schedule",
"Now", "Next" or "Event" menus. "Now", "Next" or "Event" menus.
@ -513,140 +490,6 @@ Version 2.7
The "Red" key in the "Edit timer" menu opens a list of folders, which can be The "Red" key in the "Edit timer" menu opens a list of folders, which can be
used to define the file name in which the recording will be stored. used to define the file name in which the recording will be stored.
The "Yellow" key in the "Edit timer" menu toggles the timer between "Pattern"
and "Regular".
When editing the "File" field, the "Blue" key in can be used to insert useful
macros.
* Pattern timers
There are cases where it would make sense to have a more flexible kind of
recording timer. For instance, some channels that provide VPS don't always
use the exact same VPS time for a series, which is extremely annoying.
Or you might want to record all films that have a certain pattern in their
title, no matter when they are broadcast. In such cases, "pattern timers"
can help.
In the "Edit timer" menu press the Yellow button to turn a regular timer into
a pattern timer. Pressing this button again switches back to regular.
The following rules apply to pattern timers:
- Pattern timers can only work for channels that provide EPG data.
- When using pattern timers, there should always be at least one free device that
can be used to regularly receive the EPG of the pattern timer's channel.
- A pattern timer records every matching event on the given channel that overlaps
with the given start/stop time. Overlapping events are recorded in full,
even if they extend outside the given start/stop interval.
- In order to actually record an event, a pattern timer "spawns" a separate timer
that does the recording. If there are matching events that would start while
the first spawned timer is still recording (due to the start/stop margins), timers
for those events are also spawned.
- Spawned timers are marked with the flag tfSpawned.
- Spawned timers take the Priority, Lifetime and VPS settings from the pattern timer.
- The special pattern "*" matches every event. So a timer with
a start/stop time of 00:00/23:59 will record every event of that day
into separate recordings. Note that when using this pattern there should
be no other timers for the same channel, because these might interfere.
- Once a timer has been spawned, it is treated like any other regular
timer. Any changes made to the corresponding pattern timer thereafter will have
no effect on spawned timers. Note that after deleting a spawned timer,
the corresponding pattern timer may respawn it.
- Recording is done according to the event's begin/end times, either
by adding the start/stop margins (for non-VPS timers) or by using the
event's running status (for VPS timers).
- If the start/stop margins of a spawned timer are reduced because the event
before and/or after that timer's event is shorter than the respective margin,
the actual recording still uses the full margins.
- If the times of the event change, a non-VPS pattern timer automatically adjusts
itself to the new times. This also happens if the start/stop margins are changed
in the setup.
- The recording of a pattern timer is stored under the given file name, just like
regular timers do. In addition to the "TITLE" and "EPISODE" macros the file
name of a pattern timer can also use "{<}" and "{>}" to reference the part of the
event's title before and after the pattern, respectively. For instance,
if the event's title is "Abc def ghi" and the pattern is "def ", "{<}"
would contain "Abc " and "{>}" would contain "ghi" (note the matching of the
blanks). For completeness, "{=}" can be used to reference the matching
pattern itself.
- In the "Timers" menu pressing the Red button on a pattern timer only toggles the
timer between "on" and "off", even if this is a repeating timer.
- In the "Timers" menu pattern timers are sorted alphabetically to the end of the
list of timers.
- A regular timer that is currently recording can't be changed into a pattern timer.
- In the "Edit timer" menu the file name and pattern are displayed as
separate items. The Yellow button can be used to toggle between a regular
timer and a pattern timer. When going from regular to pattern, the Pattern item will
be initialized with the base part of the file name.
- The characters '^' and '$' can be used at the very beginning and end of
the pattern to anchor the pattern to the begin or end of the title.
Using both of these will match only titles that consist of exactly the given pattern,
with nothing before and nothing after it.
- The Pattern field in the "Edit timer" menu allows blanks at the end of the string,
which may help to separate the text after the matching pattern.
- If the first character of the pattern is '@', an event that matches the
rest of the pattern is only recorded if the resulting recording's file
name (without any folders) is not contained in the donerecs.data file.
This avoids duplicate recordings of the same programme. Timers spawned from
such a pattern timer are marked with the flag tfAvoid.
- When editing the "File" field of a timer, the Blue button can be pressed to
insert one of the macros "TITLE", "EPISODE", "{<}", "{=}" or "{>}",
respectively. Pressing the Blue button repeatedly loops through the available
macros. The "{...}" macros are only available for pattern timers.
- In the "Schedule" and "What's on...?" menus the events that will be recorded
by a pattern timer are marked in the same way as regular timers.
- The TIMERS column in the LCARS skin doesn't show the basic definitions of
pattern timers, it only shows timers actually spawned from pattern timers.
If the pattern is prepended with '@', the name of the resulting recording (everything
after the rightmost '~', or the entire file name, if there is no '~') will be stored
in the file donerecs.data, so that multiple recordings of the same programme can be
avoided. When using this feature, special care must be taken regarding the recording's
file name. For instance, with a combination of
pattern file name
@Columbo Movies~TITLE
if the event's title is just "Columbo", this pattern timer would only record once,
and ignore any future events with that title, even if the episode would be different.
So you may want to use the episode name, as in
pattern file name
@Columbo Movies~TITLE - EPISODE
to make the file name unique. If you have several pattern timers for the same show on
different channels, chances are that the broadcasters handle title and episode
differently, as for example in
TITLE EPISODE pattern file name
Columbo Blueprint for Murder @^Columbo$ TITLE - EPISODE
Columbo - Blueprint for Murder @^Columbo TITLE
Columbo: Blueprint for Murder @^Columbo:_ Columbo - {>}
(note the '_' in the pattern of the third example; this is just used to visualize
the blank at the end of the pattern)
In order to have the same episode result in the same recording file name on all
channels, the file name needs to be generated differently for each channel. First
you need to decide on a proper combination of title and episode name, preferably
one that is already used by one of your channels (let's say the second one).
In the first case, title and episode name are correctly put in their respective
places, and "TITLE - EPISODE" as file name will do. The second case is our common
version, where everything is in the title, so TITLE is just fine. The third case
poses a problem, because everything is in the title, but with a different separator.
Here the special macro "{>}" can be used in the file name, which contains everything
following the matching pattern. There are three macros that can be used here:
{<} everything before the matching pattern
{>} everything after the matching pattern
{=} the matching pattern itself (just for completeness)
As of VDR version 2.5.2, the characters ' ' (blank), ':' and '-' are ignored
when checking whether a particular recording has already been made by a pattern
timer, making "TITLE - EPISODE" and "TITLE: EPISODE" the same.
VDR version 2.6.6 added '/' to this list.
* Managing folders * Managing folders
The "Select folder" menu, which can be accessed by pressing the "Red" key in The "Select folder" menu, which can be accessed by pressing the "Red" key in
@ -657,42 +500,9 @@ VDR version 2.6.6 added '/' to this list.
folder name in the list). The "Yellow" key deletes the current folder (note folder name in the list). The "Yellow" key deletes the current folder (note
that this will merely delete the folder definition stored in 'folders.conf' that this will merely delete the folder definition stored in 'folders.conf'
and has no effect on existing timers or recordings). The "Blue" key can be and has no effect on existing timers or recordings). The "Blue" key can be
used to edit an existing folder definition. The "Red" key opens a folder that used to edit an existing folder definition. The "Red" key selects the current
contains sub folders, while pressing Ok selects the current folder. Once a folder, or enters a sub folder. Once a folder has been selected, the entire
folder has been selected, the entire path of the timer's file name will be path of the timer's file name will be replaced with the selected folder.
replaced with the selected folder.
In the "Recordings" menu the folders of existing recordings can be renamed or
moved by pressing the "Blue" key ("Edit") while the cursor is positioned on
a folder. This will open a menu in which the folder's name and location (the
"parent" folder) can be edited. If such an operation will result in moving
more than one recording, you will be asked for confirmation.
The name, folder, priority and lifetime of an individual recording can be
changed by pressing the "Blue" key ("Info") while the cursor is positioned
on a recording, and in the resulting Info menu pressing the "Blue" key again
to bring up the "Edit recording" menu.
In the "Edit recording" menu the Red button ("Folder") allows you to select one
of your predefined folders. The Green button has multiple functions, depending
on what is currently going on with the recording. It can either stop or cancel
a cut, move or copy operation. If the button reads "Stop..." it means that the
respective operation is already happening, while "Cancel..." means that the
operation is still pending execution. If no operation is currently happening
and the recording has editing marks, the Button will read "Cut" and triggers
cutting the recording (same as pressing '2' while replaying the recording).
The Yellow button ("Delete marks") allows you to delete all editing marks from
the selected recording (if there are any and the recording is not currently
being cut). To directly edit the folder or name of the recording, position the
cursor to the respective line and press the Right key to start editing (press
Ok to confirm the edit, or Back to return to the previous value). If you want
to remove the name of the recording and make the folder name the actual
recording's name, you can position the cursor to the "Name:" field and press
the '0' key. This will take the last element of the recording's folder path
and make it the actual name of the recording. You can do this in turn until
the recording is moved all the way up to the root of the video directory.
Note that, in case you inadvertently pressed the '0' key, you can leave the
"Edit recording" menu with the "Back" key and any changes you have made so far
will not be applied. Once you are finished with editing the recording
properties, press Ok to confirm the changes.
* Parameters in the "Setup" menu * Parameters in the "Setup" menu
@ -796,18 +606,6 @@ VDR version 2.6.6 added '/' to this list.
plain recordings. Set this option to "no" if you want folders plain recordings. Set this option to "no" if you want folders
to be interspersed with recordings when sorted alphabetically. to be interspersed with recordings when sorted alphabetically.
Default sort mode for recordings = by time
Controls whether recordings are sorted by time or by name.
If a particular sort mode has been selected for a folder by
pressing '0', the default no longer applies to that folder.
Sorting direction for recordings = ascending
When recordings are sorted "by time", they appear in ascending
order (i.e. "oldest" to "newest"). If this parameter is set to
"descending", they will be presented "newest" to "oldest.
Note that in the latter case, if "Always sort folders first"
is "yes", folders will appear in reverse alphabetical order.
Number keys for characters = yes Number keys for characters = yes
Controls whether the number keys can be used to enter Controls whether the number keys can be used to enter
characters in a text input field. You may want to set this characters in a text input field. You may want to set this
@ -829,16 +627,6 @@ VDR version 2.6.6 added '/' to this list.
A value of '0' completely turns off scanning on both single A value of '0' completely turns off scanning on both single
and multiple card systems. and multiple card systems.
EPG scan max. channel number = 0
The EPG scan will only tune to transponders of channels with
numbers below this limit. By default all transponders will
be scanned.
EPG pause after scan = no
After a complete scan of all transponders (optionally limited
by "EPG scan max. channel number") the EPG scan pauses for
"EPG scan timeout" hours if this option is set to "yes".
EPG bugfix level = 3 Some tv stations transmit weirdly formatted EPG data. EPG bugfix level = 3 Some tv stations transmit weirdly formatted EPG data.
VDR attempts to fix these bugs up to the given level: VDR attempts to fix these bugs up to the given level:
0 = no EPG fixing 0 = no EPG fixing
@ -916,16 +704,15 @@ VDR version 2.6.6 added '/' to this list.
Defines the standard compliance mode: Defines the standard compliance mode:
0 = DVB 0 = DVB
1 = ANSI/SCTE 1 = ANSI/SCTE
2 = NORDIG
Video format = 4:3 The video format (or aspect ratio) of the tv set in use Video format = 4:3 The video format (or aspect ratio) of the tv set in use
(4:3 or 16:9). Applies only to SD output devices. (4:3 or 16:9).
Video display format = letterbox Video display format = letterbox
The display format to use for playing wide screen video on The display format to use for playing wide screen video on
a 4:3 tv set ("pan & scan", "letterbox" or "center cut out"). a 4:3 tv set ("pan & scan", "letterbox" or "center cut out").
This option is only available if "Video format" is set to This option is only available if "Video format" is set to
4:3. Applies only to SD output devices. 4:3.
Use Dolby Digital = yes Use Dolby Digital = yes
Controls whether Dolby Digital tracks appear in the "Audio" Controls whether Dolby Digital tracks appear in the "Audio"
@ -989,28 +776,6 @@ VDR version 2.6.6 added '/' to this list.
are connected to the same sat cable must be set to the same are connected to the same sat cable must be set to the same
number here. number here.
Use dish positioner = no
By default, the 'P' command code in DiSEqC command sequences
is ignored. Set this parameter to 'yes' if you are using a
satellite dish positioner.
Site latitude (degrees) = 0
Site longitude (degrees) = 0
Set these to the latitude and longitude of your dish's
location if you use a satellite dish positioner. Use the
"Green" key to switch between north/south and east/west,
respectively.
Max. positioner swing (degrees) = 65
Defines the maximum angle by which the positioner can move
the dish away from due south (or north) in either direction.
The valid range is 0...90.
Positioner speed (degrees/s) = 1.5
Defines the speed at which the positioner moves the dish.
The valid range is 0.1...180. This value is used to calculate
how long it takes the positioner to reach the target position.
CAM: CAM:
n CAM Name Shows the CAM slots that are present in this system, where n CAM Name Shows the CAM slots that are present in this system, where
@ -1019,19 +784,7 @@ VDR version 2.6.6 added '/' to this list.
if it is in the process of being reset, its current status if it is in the process of being reset, its current status
is displayed. The "Red" key can be pressed to enter the CAM is displayed. The "Red" key can be pressed to enter the CAM
menu, and the "Green" key triggers a reset of the selected menu, and the "Green" key triggers a reset of the selected
slot. The "Ok" key also opens the CAM menu. The "Yellow" key slot. The "Ok" key also opens the CAM menu.
assigns the selected CAM to a device and switches it to the
current channel. The CAM/device combination remains tuned to
the current channel until the smart card in the CAM has been
activated and thus starts to descramble, or until a recording
needs this device. Pressing the "Yellow" key while a CAM is
in activation mode cancels the activation. The activation mode
remains in effect even if you switch to a different channel
(provided there is more than one device in the system) or
watch a recording. To activate your smart card simply switch
to the channel you want to watch, open the "Setup/CAM" menu,
select the CAM that contains the smart card (in case you
have more than one CAM) and press the "Yellow" key.
Recording: Recording:
@ -1040,22 +793,14 @@ VDR version 2.6.6 added '/' to this list.
after the official end time it shall stop recording. after the official end time it shall stop recording.
These margins are added automatically to timers that These margins are added automatically to timers that
are created from the EPG data. are created from the EPG data.
Note that the actual margins used may be smaller than the
given values, if the event before and/or after the event
to be recorded is shorter than the respective margin.
Default priority = 50 The default Priority and Lifetime values used when Default priority = 50 The default Priority and Lifetime values used when
Default lifetime = 99 creating a new timer event. A Lifetime value of 99 Default lifetime = 99 creating a new timer event. A Lifetime value of 99
means that this recording will never be deleted means that this recording will never be deleted
automatically. automatically.
Record key handling = 2 Pause priority = 10 The Priority and Lifetime values used when pausing live
Defines what happens if the Record key on the remote control Pause lifetime = 1 video.
is pressed during live tv.
0 = no instant recording
1 = confirm instant recording
2 = record instantly
The default is 2.
Pause key handling = 2 Defines what happens if the Pause key on the remote control Pause key handling = 2 Defines what happens if the Pause key on the remote control
is pressed during live tv. is pressed during live tv.
@ -1064,9 +809,6 @@ VDR version 2.6.6 added '/' to this list.
2 = pause live video 2 = pause live video
The default is 2. The default is 2.
Pause priority = 10 The Priority and Lifetime values used when pausing live
Pause lifetime = 1 video.
Use episode name = yes Repeating timers use the EPG's 'Episode name' information Use episode name = yes Repeating timers use the EPG's 'Episode name' information
to create recording file names in a hierarchical structure to create recording file names in a hierarchical structure
(for instance to gather all episodes of a series in a (for instance to gather all episodes of a series in a
@ -1154,70 +896,6 @@ VDR version 2.6.6 added '/' to this list.
Defines whether the player automatically goes into Pause Defines whether the player automatically goes into Pause
mode when setting an editing mark. mode when setting an editing mark.
Pause replay when jumping to a mark = yes
By default replay is automatically paused whenever you jump
to an editing mark with the '7' or '9' key in order to allow
you to easily adjust those marks. If this option is set to
'no', the '9' key will not pause if you are in Play mode and
the mark you jump to is not within 3 seconds of the end of
the recording.
Skip edited parts = no Defines whether the edited parts of a recording are
automatically skipped during replay. This includes jumping
to the first mark if replay starts at the beginning of the
recording, and stopping at the last mark.
Pause replay at last mark = no
If enabled, replay of a recording will go into Pause mode
when it has reached the last "end" mark (if any). Note that
the actual position at which the pause occurs may be a couple
of frames before the last "end" mark, depending on how much
data is buffered by your output device.
Initial duration for adaptive skipping (s) = 120
Defines the number of seconds to jump from the current replay
position in either direction, when pressing the '1' or '3'
key for the first time after the "Reset timeout for adaptive
skipping".
The valid range is 10...600.
Reset timeout for adaptive skipping (s) = 3
Defines the number of seconds after which pressing the
'1' or '3' key falls back to the "Initial duration for adaptive
skipping".
The valid range is 0...10. Setting the timeout to 0 disables
the adaptive mode and makes '1' and '3' always skip the number
of seconds configured as the initial duration.
Alternate behavior for adaptive skipping = no
When skipping in adaptive mode with the '1' and '3' keys, the
distance of the skip is halved with every key press after the
first change of direction. While this allows for locating a
particular position in a recording very fast, once you make
one step too many in the current direction you have no chance
of ever reaching the desired point any more. You will have to
wait for the timeout to occur and start adaptive skipping anew.
If this option is set to 'yes', the skip distance will only be
halved if the direction actually changes. That way, even if
you missed the target point, you can still back up to it.
Use Prev/Next keys for adaptive skipping = no
Normally the Prev/Next keys jump between editing marks (or
the beginning/end of the recording). You can set this option
to 'yes' if you want to use these keys for adaptive skipping
instead.
Skip distance with Green/Yellow keys (s) = 60
Defines the number of seconds to skip in either direction
when pressing the "Green" or "Yellow" key, respectively.
The valid range is 5...600.
Skip distance with Green/Yellow keys in repeat (s) = 60
Defines the number of seconds to skip in either direction
when pressing and holding the "Green" or "Yellow" key,
respectively.
The valid range is 5...600.
Resume ID = 0 Defines an additional ID that can be used in a multi user Resume ID = 0 Defines an additional ID that can be used in a multi user
environment, so that every user has his/her own resume environment, so that every user has his/her own resume
files for each recording. The valid range is 0...99, with files for each recording. The valid range is 0...99, with
@ -1241,23 +919,6 @@ VDR version 2.6.6 added '/' to this list.
connection after which the connection is automatically connection after which the connection is automatically
closed. Default is 300, a value of 0 means no timeout. closed. Default is 300, a value of 0 means no timeout.
SVDRP peering = off Activates automatic connections between VDRs in the same
network. If set to "any hosts" this VDR will establish
connections with any available hosts. If set to "only
default host" this VDR will only connect to the VDR with
the name defined in "SVDRP default host". If no default
host has been defined, the behavior is the same as with
"any hosts". To switch from "off" to "only default host",
you may need to select "any hosts" first and confirm the
dialog by pressing "Ok" in order to be able to select a
default host.
SVDRP host name The name of this VDR, which is used when connecting VDRs
via SVDRP. By default, the machine's host name is used.
SVDRP default host The name of the VDR to be used by default when creating a
new timer.
Zap timeout = 3 The time (in seconds) until a channel counts as "previous" Zap timeout = 3 The time (in seconds) until a channel counts as "previous"
for switching with '0' for switching with '0'
@ -1280,7 +941,7 @@ VDR version 2.6.6 added '/' to this list.
The time (in milliseconds) between two subsequent key The time (in milliseconds) between two subsequent key
presses generated by the remote control's repeat function. presses generated by the remote control's repeat function.
If the remote control in use has a repeat delta that is If the remote control in use has a repeat delta that is
longer than that given in this parameter, that longer delta longer than that given in this parameter, that longer delay
will prevail. will prevail.
Initial channel = The channel ID of the channel that shall be tuned to when Initial channel = The channel ID of the channel that shall be tuned to when
VDR starts. Default is empty, which means that it will VDR starts. Default is empty, which means that it will
@ -1291,27 +952,15 @@ VDR version 2.6.6 added '/' to this list.
VDR was stopped will be used. The valid range is from VDR was stopped will be used. The valid range is from
0 (silent) to 255 (loudest). 0 (silent) to 255 (loudest).
Volume steps = 51 The number of steps the volume will use when moving from
the lowest to the highest value. The valid range is from
5 to 255.
Volume linearize = 0 How to linearize the volume control. The valid range is
from -20 to 20. A value of 0 results in no linearization.
The higher this value is, the more fine grained the control
of the volume is for low sound levels. Lower values do the
same for high sound levels. This allows you to adjust the
more or less linear volume control of your sound card.
Channels wrap = no During zapping with the "Up" and "Down" keys (or the Channels wrap = no During zapping with the "Up" and "Down" keys (or the
"Channel+" and "Channel-" keys) the current channel will "Channel+" and "Channel-" keys) the current channel will
wrap around the beginning or end of the channel list if wrap around the beginning or end of the channel list if
this parameter is set to 'yes'. this parameter is set to 'yes'.
Show channel names with source = off Show channel names with source = no
If this option is turned on, channel names will be displayed If this option is turned on, channel names will be displayed
with the source appended to them, as in "ZDF (S)" (if the with the source appended to them, as in "ZDF (S)", where
option is set to "type), or "ZDF (S19.2E)" (if it is set to 'S' stands for "Satellite".
"full"), where 'S' stands for "Satellite".
Emergency exit = yes If, for some reason, a recording fails because the video Emergency exit = yes If, for some reason, a recording fails because the video
data stream is broken, or the CAM doesn't decrypt etc., data stream is broken, or the CAM doesn't decrypt etc.,

View File

@ -6,7 +6,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Make.config.template 5.2 2024/10/11 14:21:04 kls Exp $ # $Id: Make.config.template 2.19 2013/02/18 10:55:39 kls Exp $
### The C compiler and options: ### The C compiler and options:
@ -16,12 +16,6 @@ CFLAGS = -g -O3 -Wall
CXX = g++ CXX = g++
CXXFLAGS = -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses CXXFLAGS = -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses
# Use 'make DEBUG=1 ...' to build a debug version of VDR and plugins:
ifdef DEBUG
CFLAGS += -O0
CXXFLAGS += -O0
endif
# Use 'make M32=1 ...' to build a 32-bit version of VDR on a 64-bit machine: # Use 'make M32=1 ...' to build a 32-bit version of VDR on a 64-bit machine:
ifdef M32 ifdef M32
CFLAGS += -m32 CFLAGS += -m32
@ -33,19 +27,17 @@ endif
# Default directories (adjust as necessary or desired): # Default directories (adjust as necessary or desired):
#PREFIX = /usr/local #PREFIX = /usr/local
#VDRROOT = $(PREFIX) #BINDIR = $(PREFIX)/bin
#BINDIR = $(VDRROOT)/bin #INCDIR = $(PREFIX)/include
#INCDIR = $(VDRROOT)/include #LIBDIR = $(PREFIX)/lib/vdr
#LIBDIR = $(VDRROOT)/lib #LOCDIR = $(PREFIX)/share/locale
#LOCDIR = $(VDRROOT)/locale #MANDIR = $(PREFIX)/share/man
#MANDIR = $(VDRROOT)/man #PCDIR = $(PREFIX)/lib/pkgconfig
#PCDIR = $(VDRROOT)/pkgconfig #RESDIR = $(PREFIX)/share/vdr
#RESDIR = $(VDRROOT)/share #DVBDIR = /usr/src/v4l-dvb/linux/include/uapi
#DVBDIR = /usr/include
#VIDEODIR = /srv/vdr/video #VIDEODIR = /srv/vdr/video
#CONFDIR = /var/lib/vdr #CONFDIR = /var/lib/vdr
#ARGSDIR = /etc/vdr/conf.d
#CACHEDIR = /var/cache/vdr #CACHEDIR = /var/cache/vdr
# Overrides for preset/legacy configurations: # Overrides for preset/legacy configurations:
@ -65,7 +57,6 @@ ifdef ONEDIR
VIDEODIR = /video VIDEODIR = /video
CACHEDIR = $(VIDEODIR) CACHEDIR = $(VIDEODIR)
CONFDIR = $(VIDEODIR) CONFDIR = $(VIDEODIR)
ARGSDIR = $(VIDEODIR)/conf.d
RESDIR = $(VIDEODIR) RESDIR = $(VIDEODIR)
endif endif
@ -74,25 +65,12 @@ endif
#PLGCFG = $(CONFDIR)/plugins.mk #PLGCFG = $(CONFDIR)/plugins.mk
### The remote control: ### The remote control:
LIRC_DEVICE = /var/run/lirc/lircd LIRC_DEVICE = /var/run/lirc/lircd
### Use this for kernel based driver:
#LIRC_DEVICE = /dev/lirc0
### Define if you always want to use LIRC, independent of the --lirc option:
#REMOTE=LIRC
### Define if you don't want keyboard remote control:
#NO_KBD = 1
### Define if you want vdr to not run as root: ### Define if you want vdr to not run as root:
#VDR_USER = vdr #VDR_USER = vdr
### Define if you want to compile in 'bidi' support:
#BIDI = 1
### Define if you want 'systemd' notification:
#SDNOTIFY = 1
### Fallback for plugins with old makefiles: ### Fallback for plugins with old makefiles:
ifdef PLUGIN ifdef PLUGIN
CFLAGS += -fPIC CFLAGS += -fPIC

110
Makefile
View File

@ -4,26 +4,23 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 5.4 2024/10/21 19:01:16 kls Exp $ # $Id: Makefile 2.54 2013/03/11 15:01:01 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
# Compiler flags: # Compiler flags:
PKG_CONFIG ?= pkg-config
CC ?= gcc CC ?= gcc
CFLAGS ?= -g -O3 -Wall CFLAGS ?= -g -O3 -Wall
CXX ?= g++ CXX ?= g++
CXXFLAGS ?= -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses CXXFLAGS ?= -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses
CXXFLAGS += $(CPPFLAGS)
CDEFINES = -D_GNU_SOURCE CDEFINES = -D_GNU_SOURCE
CDEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE CDEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
LIBS = -ljpeg -lpthread -ldl -lcap -lrt $(shell $(PKG_CONFIG) --libs freetype2 fontconfig) LIBS = -ljpeg -lpthread -ldl -lcap -lrt $(shell pkg-config --libs freetype2 fontconfig)
INCLUDES ?= $(shell $(PKG_CONFIG) --cflags freetype2 fontconfig) INCLUDES ?= $(shell pkg-config --cflags freetype2 fontconfig)
# Directories: # Directories:
@ -31,29 +28,19 @@ CWD ?= $(shell pwd)
LSIDIR ?= $(CWD)/libsi LSIDIR ?= $(CWD)/libsi
PLUGINDIR ?= $(CWD)/PLUGINS PLUGINDIR ?= $(CWD)/PLUGINS
# Failsafe defaults for "make LCLBLD=1":
ifdef LCLBLD
DESTDIR ?= $(CWD)
LOCDIR ?= $(CWD)/locale
HDRDIR ?= $(CWD)/include
LIBDIR ?= $(PLUGINDIR)/lib
endif
DESTDIR ?= DESTDIR ?=
VIDEODIR ?= /srv/vdr/video VIDEODIR ?= /srv/vdr/video
CONFDIR ?= /var/lib/vdr CONFDIR ?= /var/lib/vdr
ARGSDIR ?= /etc/vdr/conf.d
CACHEDIR ?= /var/cache/vdr CACHEDIR ?= /var/cache/vdr
PREFIX ?= /usr/local PREFIX ?= /usr/local
VDRROOT ?= $(PREFIX) BINDIR ?= $(PREFIX)/bin
BINDIR ?= $(VDRROOT)/bin INCDIR ?= $(PREFIX)/include
INCDIR ?= $(VDRROOT)/include LIBDIR ?= $(PREFIX)/lib/vdr
LIBDIR ?= $(VDRROOT)/lib/vdr LOCDIR ?= $(PREFIX)/share/locale
LOCDIR ?= $(VDRROOT)/share/locale MANDIR ?= $(PREFIX)/share/man
MANDIR ?= $(VDRROOT)/share/man PCDIR ?= $(PREFIX)/lib/pkgconfig
PCDIR ?= $(VDRROOT)/lib/pkgconfig RESDIR ?= $(PREFIX)/share/vdr
RESDIR ?= $(VDRROOT)/share/vdr
# Source documentation # Source documentation
@ -64,15 +51,6 @@ DOXYFILE = Doxyfile
-include Make.config -include Make.config
# Output control
ifdef VERBOSE
Q =
else
Q = @
endif
export Q
# Mandatory compiler flags: # Mandatory compiler flags:
CFLAGS += -fPIC CFLAGS += -fPIC
@ -88,9 +66,9 @@ endif
SILIB = $(LSIDIR)/libsi.a SILIB = $(LSIDIR)/libsi.a
OBJS = args.o audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o\ OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o\
dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\ dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
lirc.o menu.o menuitems.o mtd.o nit.o osdbase.o osd.o pat.o player.o plugin.o positioner.o\ lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o\
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\
skinclassic.o skinlcars.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\ skinclassic.o skinlcars.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\
timers.o tools.o transfer.o vdr.o videodir.o timers.o tools.o transfer.o vdr.o videodir.o
@ -111,14 +89,9 @@ ifdef VDR_USER
DEFINES += -DVDR_USER=\"$(VDR_USER)\" DEFINES += -DVDR_USER=\"$(VDR_USER)\"
endif endif
ifdef BIDI ifdef BIDI
INCLUDES += $(shell $(PKG_CONFIG) --cflags fribidi) INCLUDES += $(shell pkg-config --cflags fribidi)
DEFINES += -DBIDI DEFINES += -DBIDI
LIBS += $(shell $(PKG_CONFIG) --libs fribidi) LIBS += $(shell pkg-config --libs fribidi)
endif
ifdef SDNOTIFY
INCLUDES += $(shell $(PKG_CONFIG) --silence-errors --cflags libsystemd-daemon || $(PKG_CONFIG) --cflags libsystemd)
DEFINES += -DSDNOTIFY
LIBS += $(shell $(PKG_CONFIG) --silence-errors --libs libsystemd-daemon || $(PKG_CONFIG) --libs libsystemd)
endif endif
LIRC_DEVICE ?= /var/run/lirc/lircd LIRC_DEVICE ?= /var/run/lirc/lircd
@ -126,7 +99,6 @@ LIRC_DEVICE ?= /var/run/lirc/lircd
DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\" DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\"
DEFINES += -DVIDEODIR=\"$(VIDEODIR)\" DEFINES += -DVIDEODIR=\"$(VIDEODIR)\"
DEFINES += -DCONFDIR=\"$(CONFDIR)\" DEFINES += -DCONFDIR=\"$(CONFDIR)\"
DEFINES += -DARGSDIR=\"$(ARGSDIR)\"
DEFINES += -DCACHEDIR=\"$(CACHEDIR)\" DEFINES += -DCACHEDIR=\"$(CACHEDIR)\"
DEFINES += -DRESDIR=\"$(RESDIR)\" DEFINES += -DRESDIR=\"$(RESDIR)\"
DEFINES += -DPLUGINDIR=\"$(LIBDIR)\" DEFINES += -DPLUGINDIR=\"$(LIBDIR)\"
@ -142,8 +114,7 @@ all: vdr i18n plugins
# Implicit rules: # Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
# Dependencies: # Dependencies:
@ -157,26 +128,21 @@ $(DEPFILE): Makefile
# The main program: # The main program:
vdr: $(OBJS) $(SILIB) vdr: $(OBJS) $(SILIB)
@echo LD $@ $(CXX) $(CXXFLAGS) -rdynamic $(LDFLAGS) $(OBJS) $(LIBS) $(SILIB) -o vdr
$(Q)$(CXX) $(CXXFLAGS) -rdynamic $(LDFLAGS) $(OBJS) $(LIBS) $(SILIB) -o vdr
# The libsi library: # The libsi library:
$(SILIB): make-libsi $(SILIB):
@$(MAKE) --no-print-directory -C $(LSIDIR) CXXFLAGS="$(CXXFLAGS)" DEFINES="$(CDEFINES)" all $(MAKE) --no-print-directory -C $(LSIDIR) CXXFLAGS="$(CXXFLAGS)" DEFINES="$(CDEFINES)" all
make-libsi: # empty rule makes sure the sub-make for libsi is always called
# pkg-config file: # pkg-config file:
.PHONY: vdr.pc .PHONY: vdr.pc
vdr.pc: vdr.pc:
@echo "vdrrootdir=$(VDRROOT)" > $@ @echo "bindir=$(BINDIR)" > $@
@echo "bindir=$(BINDIR)" >> $@
@echo "incdir=$(INCDIR)" >> $@
@echo "mandir=$(MANDIR)" >> $@ @echo "mandir=$(MANDIR)" >> $@
@echo "videodir=$(VIDEODIR)" >> $@
@echo "configdir=$(CONFDIR)" >> $@ @echo "configdir=$(CONFDIR)" >> $@
@echo "argsdir=$(ARGSDIR)" >> $@ @echo "videodir=$(VIDEODIR)" >> $@
@echo "cachedir=$(CACHEDIR)" >> $@ @echo "cachedir=$(CACHEDIR)" >> $@
@echo "resdir=$(RESDIR)" >> $@ @echo "resdir=$(RESDIR)" >> $@
@echo "libdir=$(LIBDIR)" >> $@ @echo "libdir=$(LIBDIR)" >> $@
@ -188,7 +154,7 @@ vdr.pc:
@echo "" >> $@ @echo "" >> $@
@echo "Name: VDR" >> $@ @echo "Name: VDR" >> $@
@echo "Description: Video Disk Recorder" >> $@ @echo "Description: Video Disk Recorder" >> $@
@echo "URL: https://www.tvdr.de/" >> $@ @echo "URL: http://www.tvdr.de/" >> $@
@echo "Version: $(VDRVERSION)" >> $@ @echo "Version: $(VDRVERSION)" >> $@
@echo "Cflags: \$${cflags}" >> $@ @echo "Cflags: \$${cflags}" >> $@
@ -202,21 +168,17 @@ I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr.mo, $(notdir
I18Npot = $(PODIR)/vdr.pot I18Npot = $(PODIR)/vdr.pot
%.mo: %.po %.mo: %.po
@echo MO $@ msgfmt -c -o $@ $<
$(Q)msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.c) $(I18Npot): $(wildcard *.c)
@echo GT $@ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=VDR --package-version=$(VDRVERSION) --msgid-bugs-address='<vdr-bugs@tvdr.de>' -o $@ `ls $^`
$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=VDR --package-version=$(VDRVERSION) --msgid-bugs-address='<vdr-bugs@tvdr.de>' -o $@ `ls $^`
%.po: $(I18Npot) %.po: $(I18Npot)
@echo PO $@ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
$(Q)msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
@touch $@ @touch $@
$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr.mo: $(PODIR)/%.mo $(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr.mo: $(PODIR)/%.mo
@echo IN $@ install -D -m644 $< $@
$(Q)install -D -m644 $< $@
.PHONY: i18n .PHONY: i18n
i18n: $(I18Nmsgs) i18n: $(I18Nmsgs)
@ -258,7 +220,7 @@ plugins: include-dir vdr.pc
INCLUDES="-I$(CWD)/include"\ INCLUDES="-I$(CWD)/include"\
$(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR="$(CWD)" || failed="$$failed $$i";\ $(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR="$(CWD)" || failed="$$failed $$i";\
if [ -n "$(LCLBLD)" ] ; then\ if [ -n "$(LCLBLD)" ] ; then\
(cd $(PLUGINDIR)/src/$$i; for l in `find -name "libvdr-*.so" -o -name "lib$$i-*.so"`; do install -D $$l $(LIBDIR)/`basename $$l`.$(APIVERSION); done);\ (cd $(PLUGINDIR)/src/$$i; for l in `find -name 'libvdr-*.so' -o -name 'lib$$i-*.so'`; do install $$l $(LIBDIR)/`basename $$l`.$(APIVERSION); done);\
if [ -d $(PLUGINDIR)/src/$$i/po ]; then\ if [ -d $(PLUGINDIR)/src/$$i/po ]; then\
for l in `ls $(PLUGINDIR)/src/$$i/po/*.mo`; do\ for l in `ls $(PLUGINDIR)/src/$$i/po/*.mo`; do\
install -D -m644 $$l $(LOCDIR)/`basename $$l | cut -d. -f1`/LC_MESSAGES/vdr-$$i.mo;\ install -D -m644 $$l $(LOCDIR)/`basename $$l | cut -d. -f1`/LC_MESSAGES/vdr-$$i.mo;\
@ -279,13 +241,13 @@ plugins: include-dir vdr.pc
fi;\ fi;\
if [ -n "$$failed" ] ; then echo; echo "*** failed plugins:$$failed"; echo; exit 1; fi if [ -n "$$failed" ] ; then echo; echo "*** failed plugins:$$failed"; echo; exit 1; fi
clean-plugins: vdr.pc clean-plugins:
@for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do $(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR="$(CWD)" clean; done @for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do $(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" clean; done
@-rm -f $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION) @-rm -f $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION)
# Install the files (note that 'install-pc' must be first!): # Install the files (note that 'install-pc' must be first!):
install: install-pc install-bin install-conf install-doc install-plugins install-i18n install-includes install: install-pc install-bin install-dirs install-conf install-doc install-plugins install-i18n install-includes
# VDR binary: # VDR binary:
@ -298,17 +260,11 @@ install-bin: vdr
install-dirs: install-dirs:
@mkdir -p $(DESTDIR)$(VIDEODIR) @mkdir -p $(DESTDIR)$(VIDEODIR)
@mkdir -p $(DESTDIR)$(CONFDIR) @mkdir -p $(DESTDIR)$(CONFDIR)
@mkdir -p $(DESTDIR)$(ARGSDIR)
@mkdir -p $(DESTDIR)$(CACHEDIR) @mkdir -p $(DESTDIR)$(CACHEDIR)
@mkdir -p $(DESTDIR)$(RESDIR) @mkdir -p $(DESTDIR)$(RESDIR)
install-conf: install-dirs install-conf:
# 'cp -n' may be broken, so let's do it the hard way @cp -pn *.conf $(DESTDIR)$(CONFDIR)
@for i in *.conf; do\
if ! [ -e $(DESTDIR)$(CONFDIR)/$$i ] ; then\
cp -p $$i $(DESTDIR)$(CONFDIR);\
fi\
done
# Documentation: # Documentation:
@ -323,7 +279,6 @@ install-doc:
install-plugins: plugins install-plugins: plugins
@-for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do\ @-for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do\
echo; echo "*** Plugin $$i:";\
$(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR=$(CWD) DESTDIR=$(DESTDIR) install;\ $(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR=$(CWD) DESTDIR=$(DESTDIR) install;\
done done
@if [ -d $(PLUGINDIR)/lib ] ; then\ @if [ -d $(PLUGINDIR)/lib ] ; then\
@ -351,7 +306,6 @@ install-pc: vdr.pc
srcdoc: srcdoc:
@cat $(DOXYFILE) > $(DOXYFILE).tmp @cat $(DOXYFILE) > $(DOXYFILE).tmp
@echo PROJECT_NUMBER = $(VDRVERSION) >> $(DOXYFILE).tmp @echo PROJECT_NUMBER = $(VDRVERSION) >> $(DOXYFILE).tmp
@chmod +x $(DOXYFILE).filter
$(DOXYGEN) $(DOXYFILE).tmp $(DOXYGEN) $(DOXYFILE).tmp
@rm $(DOXYFILE).tmp @rm $(DOXYFILE).tmp
@ -360,7 +314,7 @@ srcdoc:
clean: clean:
@$(MAKE) --no-print-directory -C $(LSIDIR) clean @$(MAKE) --no-print-directory -C $(LSIDIR) clean
@-rm -f $(OBJS) $(DEPFILE) vdr vdr.pc core* *~ @-rm -f $(OBJS) $(DEPFILE) vdr vdr.pc core* *~
@-rm -rf $(LOCALEDIR) $(PODIR)/*~ $(PODIR)/*.mo $(PODIR)/*.pot @-rm -rf $(LOCALEDIR) $(PODIR)/*.mo $(PODIR)/*.pot
@-rm -rf include @-rm -rf include
@-rm -rf srcdoc @-rm -rf srcdoc
CLEAN: clean CLEAN: clean

View File

@ -31,11 +31,14 @@ modified {
<div class="center"> <div class="center">
<h1>The VDR Plugin System</h1> <h1>The VDR Plugin System</h1>
<b>Version 2.7</b> <b>Version 2.0</b>
<p> <p>
Copyright &copy; 2021 Klaus Schmidinger<br> Copyright &copy; 2013 Klaus Schmidinger<br>
<a href="mailto:vdr@tvdr.de">vdr@tvdr.de</a><br> <a href="mailto:vdr@tvdr.de">vdr@tvdr.de</a><br>
<a href="https://www.tvdr.de">www.tvdr.de</a> <a href="http://www.tvdr.de">www.tvdr.de</a>
</div>
<div class="center">
<modified>Important modifications introduced since version 1.6 are marked like this.</modified>
</div> </div>
<p> <p>
VDR provides an easy to use plugin interface that allows additional functionality VDR provides an easy to use plugin interface that allows additional functionality
@ -74,15 +77,15 @@ structures and allows it to hook itself into specific areas to perform special a
<li><a href="#Main menu entry">Main menu entry</a> <li><a href="#Main menu entry">Main menu entry</a>
<li><a href="#User interaction">User interaction</a> <li><a href="#User interaction">User interaction</a>
<li><a href="#Housekeeping">Housekeeping</a> <li><a href="#Housekeeping">Housekeeping</a>
<li><a href="#Main thread hook">Main thread hook</a>
<li><a href="#Activity">Activity</a> <li><a href="#Activity">Activity</a>
<li><a href="#Wakeup">Wakeup</a> <li><a href="#Wakeup">Wakeup</a>
<li><a href="#Setup parameters">Setup parameters</a> <li><a href="#Setup parameters">Setup parameters</a>
<li><a href="#The Setup menu">The Setup menu</a> <li><a href="#The Setup menu">The Setup menu</a>
<li><a href="#Additional files">Additional files</a> <li><modified><a href="#Additional files">Additional files</modified></a>
<li><a href="#Internationalization">Internationalization</a> <li><a href="#Internationalization">Internationalization</a>
<li><a href="#Custom services">Custom services</a> <li><a href="#Custom services">Custom services</a>
<li><a href="#SVDRP commands">SVDRP commands</a> <li><a href="#SVDRP commands">SVDRP commands</a>
<li><a href="#Locking">Locking</a>
<li><a href="#Loading plugins into VDR">Loading plugins into VDR</a> <li><a href="#Loading plugins into VDR">Loading plugins into VDR</a>
<li><a href="#Building the distribution package">Building the distribution package</a> <li><a href="#Building the distribution package">Building the distribution package</a>
</ul> </ul>
@ -96,12 +99,10 @@ structures and allows it to hook itself into specific areas to perform special a
<li><a href="#Skins">Skins</a> <li><a href="#Skins">Skins</a>
<li><a href="#Themes">Themes</a> <li><a href="#Themes">Themes</a>
<li><a href="#Devices">Devices</a> <li><a href="#Devices">Devices</a>
<li><a href="#Positioners">Positioners</a>
<li><a href="#Audio">Audio</a> <li><a href="#Audio">Audio</a>
<li><a href="#Remote Control">Remote Control</a> <li><a href="#Remote Control">Remote Control</a>
<li><a href="#Conditional Access">Conditional Access</a> <li><a href="#Conditional Access">Conditional Access</a>
<li><a href="#Electronic Program Guide">Electronic Program Guide</a> <li><modified><a href="#Electronic Program Guide">Electronic Program Guide</modified></a>
<li><a href="#The video directory">The video directory</a>
</ul> </ul>
</ul> </ul>
@ -165,26 +166,28 @@ is used:
VDR/PLUGINS/src VDR/PLUGINS/src
VDR/PLUGINS/src/hello VDR/PLUGINS/src/hello
VDR/PLUGINS/lib VDR/PLUGINS/lib
VDR/PLUGINS/lib/libvdr-hello.so.1 VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
</pre></td></tr></table><p> </pre></td></tr></table><p>
The <tt>src</tt> directory contains one subdirectory for each plugin, which carries The <tt>src</tt> directory contains one subdirectory for each plugin, which carries
the name of that plugin (in the above example that would be <tt>hello</tt>). the name of that plugin (in the above example that would be <tt>hello</tt>).
What's inside the individual source directory of a What's inside the individual source directory of a
plugin is entirely up to the author of that plugin. The only prerequisites are plugin is entirely up to the author of that plugin. The only prerequisites are
that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt>, <tt>install</tt> and that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt><modified>, <tt>install</tt></modified> and
<tt>clean</tt>, and that a call to <tt>make all</tt> actually produces a dynamically <tt>clean</tt>, and that a call to <tt>make all</tt> actually produces a dynamically
loadable library file for that plugin (we'll get to the details later). loadable library file for that plugin (we'll get to the details later).
<modified>
The dynamically loadable library file for the plugin shall be located directly under The dynamically loadable library file for the plugin shall be located directly under
the plugin's source directory. the plugin's source directory.
See the section <a href="#Initializing a new plugin directory">Initializing a new plugin directory</a> See the section <a href="#Initializing a new plugin directory">Initializing a new plugin directory</a>
for how to generate an example Makefile. for how to generate an example Makefile.
</modified>
<p> <p>
The <tt>lib</tt> directory contains the dynamically loadable libraries of all The <tt>lib</tt> directory contains the dynamically loadable libraries of all
available plugins. Note that the names of these files are created by concatenating available plugins. Note that the names of these files are created by concatenating
<p> <p>
<table border=2> <table border=2>
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>hello</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1</tt></b></td></tr> <tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>hello</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1.1.0</tt></b></td></tr>
<tr><td align=center><small>VDR plugin<br>library prefix</small></td><td align=center><small>name of<br>the plugin</small></td><td align=center><small>shared object<br>indicator</small></td><td align=center><small>API version number<br>this plugin was<br>compiled for</small></td></tr> <tr><td align=center><small>VDR plugin<br>library prefix</small></td><td align=center><small>name of<br>the plugin</small></td><td align=center><small>shared object<br>indicator</small></td><td align=center><small>API version number<br>this plugin was<br>compiled for</small></td></tr>
</table> </table>
<p> <p>
@ -195,11 +198,6 @@ the current VDR version. That way minor fixes to VDR, that don't require changes
to the VDR header files, can be made without requiring all plugins to be to the VDR header files, can be made without requiring all plugins to be
recompiled. recompiled.
<p> <p>
While in earlier versions of VDR the API version number was closely related to the
VDR version number, starting with VDR version 2.7.2 the API version number was changed
from a dot separated, three part number to a single integer, completely unrelated to
the VDR version. This was done to avoid confusion.
<p>
The plugin library files can be stored in any directory. If the default organization The plugin library files can be stored in any directory. If the default organization
is not used, the path to the plugin directory has be be given to VDR through the is not used, the path to the plugin directory has be be given to VDR through the
<b><tt>-L</tt></b> option. <b><tt>-L</tt></b> option.
@ -395,7 +393,13 @@ just like shown in the above example. This is a convention that allows the <tt>M
to extract the version number when generating the file name for the distribution archive. to extract the version number when generating the file name for the distribution archive.
<p> <p>
A new plugin project should start with version number <tt>0.0.1</tt> and should reach A new plugin project should start with version number <tt>0.0.1</tt> and should reach
version <tt>1.0.0</tt> once it is completely operative and well tested. version <tt>1.0.0</tt> once it is completely operative and well tested. Following the
Linux kernel version numbering scheme, versions with <i>even</i> release numbers
(like <tt>1.0.x</tt>, <tt>1.2.x</tt>, <tt>1.4.x</tt>...) should be stable releases,
while those with <i>odd</i> release numbers (like <tt>1.1.x</tt>, <tt>1.3.x</tt>,
<tt>1.5.x</tt>...) are usually considered "under development". The three parts of
a version number are not limited to single digits, so a version number of <tt>1.2.15</tt>
would be acceptable.
<hr><h2><a name="Description">Description</a></h2> <hr><h2><a name="Description">Description</a></h2>
@ -579,31 +583,6 @@ esyslog("pluginname: error #%d has occurred", ErrorNumber);
Note that the log messages will be given as provided, the plugin's name will not Note that the log messages will be given as provided, the plugin's name will not
automatically be added, so make sure your log messages are obvious enough. automatically be added, so make sure your log messages are obvious enough.
<p>
Only use the above logging functions for occasional log messages. Do not use
them unconditionally for frequent messages that produce long sequences of lines
in the log file every few seconds. That might make it hard to work on other plugins
or the core VDR code, watching their log entries while they are permanently
interspersed with unrelated stuff.<br>
<br>
The recommended behavior for a plugin that does logging is to implement a command
line option that controls the level of log messages, preferably '-l N, --log=N',
where 'N' is in the range 0...3, with 0 meaning no logging whatsoever, 1 log only
errors, 2 log errors and informational messages, and 3 also log debug information.<br>
<br>
If a plugin can output extensive data for special debugging purposes (either to
the log file or stdout/stderr), this should be enabled by setting proper switches
in one of its source files (see for example how the communication between VDR and
CAMs can be monitored in VDR/ci.c).<br>
<br>
Under no circumstances must a plugin print anything to stdout or stderr during
normal operation! The only exceptions being special debug information as described
above, fatal error messages that will cause VDR to abort, or if it is the sole
purpose of the plugin to display something on stdout, like for instance the
<i>skincurses</i> plugin, which displays the OSD at the console.<br>
<br>
Please make any log messages in <b>ENGLISH</b>! Logs are usually sent to the developers
of a program, and they may not be able to read them if they are in an exotic language.
<hr><h2><a name="Main menu entry">Main menu entry</a></h2> <hr><h2><a name="Main menu entry">Main menu entry</a></h2>
@ -691,6 +670,27 @@ interaction is possible. If a specific action takes longer than a few seconds,
the plugin should launch a separate thread to do this. the plugin should launch a separate thread to do this.
</b> </b>
<hr><h2><a name="Main thread hook">Main thread hook</a></h2>
<div class="blurb">Pushing in...</div><p>
Normally a plugin only reacts on user input if directly called through its
<a href="#Main menu entry">main menu entry</a>, or performs some background
activity in a separate thread. However, sometimes a plugin may need to do
something in the context of the main program thread, without being explicitly
called up by the user. In such a case it can implement the function
<p><table><tr><td class="code"><pre>
virtual void MainThreadHook(void);
</pre></td></tr></table><p>
in which it can do this. This function is called for every plugin once during
every cycle of VDR's main program loop, which typically happens once every
second.
<b>Be very careful when using this function, and make sure you return from it
as soon as possible! If you spend too much time in this function, the user
interface performance will become sluggish!</b>
<hr><h2><a name="Activity">Activity</a></h2> <hr><h2><a name="Activity">Activity</a></h2>
<div class="blurb">Now is not a good time!</div><p> <div class="blurb">Now is not a good time!</div><p>
@ -891,51 +891,70 @@ You can first assign the temporary values to the global variables and then do th
your setup parameters and use that one to copy all parameters with one single statement your setup parameters and use that one to copy all parameters with one single statement
(like VDR does with its cSetup class). (like VDR does with its cSetup class).
<hr><h2><a name="Additional files">Additional files</a></h2> <hr><h2><modified><a name="Additional files">Additional files</a></modified></h2>
<div class="blurb">I want my own stuff!</div><p> <div class="blurb">I want my own stuff!</div><p>
<modified>
There may be situations where a plugin requires files of its own. While the plugin is There may be situations where a plugin requires files of its own. While the plugin is
free to store such files anywhere it sees fit, it might be a good idea to put them in a common free to store such files anywhere it sees fit, it might be a good idea to put them in a common
place, preferably where such data already exists. place, preferably where such data already exists.
</modified>
<p> <p>
<modified>
<i>configuration files</i>, maybe for data that can't be stored in the simple <i>configuration files</i>, maybe for data that can't be stored in the simple
<a href="#Setup parameters">setup parameters</a> of VDR, or maybe because it needs to <a href="#Setup parameters">setup parameters</a> of VDR, or maybe because it needs to
launch other programs that simply need a separate configuration file. launch other programs that simply need a separate configuration file.
</modified>
<p> <p>
<modified>
<i>cache files</i>, to store data so that future requests for that data can be served faster. The data <i>cache files</i>, to store data so that future requests for that data can be served faster. The data
that is stored within a cache might be values that have been computed earlier or duplicates of that is stored within a cache might be values that have been computed earlier or duplicates of
original values that are stored elsewhere. original values that are stored elsewhere.
</modified>
<p> <p>
<modified>
<i>resource files</i>, for providing additional files, like pictures, movie clips or channel logos. <i>resource files</i>, for providing additional files, like pictures, movie clips or channel logos.
</modified>
<p> <p>
<modified>
Therefore VDR provides the functions Therefore VDR provides the functions
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
<modified>
const char *ConfigDirectory(const char *PluginName = NULL); const char *ConfigDirectory(const char *PluginName = NULL);
const char *CacheDirectory(const char *PluginName = NULL); const char *CacheDirectory(const char *PluginName = NULL);
const char *ResourceDirectory(const char *PluginName = NULL); const char *ResourceDirectory(const char *PluginName = NULL);
</modified>
</pre></td></tr></table><p> </pre></td></tr></table><p>
<modified>
each of which returns a string containing the directory that VDR uses for its own each of which returns a string containing the directory that VDR uses for its own
files (defined through the options in the call to VDR), extended by files (defined through the options in the call to VDR), extended by
</modified>
<tt>"/plugins"</tt>. So assuming the VDR configuration directory is <tt>/video</tt> <tt>"/plugins"</tt>. So assuming the VDR configuration directory is <tt>/video</tt>
(the default if no <tt><b>-c</b></tt> or <tt><b>-v</b></tt> option is given), (the default if no <tt><b>-c</b></tt> or <tt><b>-v</b></tt> option is given),
a call to <tt>ConfigDirectory()</tt> will return <tt>/video/plugins</tt>. The first a call to <tt>ConfigDirectory()</tt> will return <tt>/video/plugins</tt>. The first
call to <tt>ConfigDirectory()</tt> will automatically make sure that the <tt>plugins</tt> call to <tt>ConfigDirectory()</tt> will automatically make sure that the <tt>plugins</tt>
subdirectory will exist. If, for some reason, this cannot be achieved, <tt>NULL</tt> subdirectory will exist. If, for some reason, this cannot be achieved, <tt>NULL</tt>
will be returned. will be returned.
<modified>
The behavior of <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt> is similar. The behavior of <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt> is similar.
</modified>
<p> <p>
The additional <tt>plugins</tt> directory is used to keep files from plugins apart The additional <tt>plugins</tt> directory is used to keep files from plugins apart
from those of VDR itself, making sure there will be no name clashes. If a plugin from those of VDR itself, making sure there will be no name clashes. If a plugin
<modified>
needs only one extra file, it is suggested that this file be named <tt>name.*</tt>, needs only one extra file, it is suggested that this file be named <tt>name.*</tt>,
where <i>name</i> shall be the name of the plugin. where <i>name</i> shall be the name of the plugin.
</modified>
<p> <p>
If a plugin needs more than one such file, it is suggested that the plugin stores If a plugin needs more than one such file, it is suggested that the plugin stores
these in a subdirectory of its own, named after the plugin. To easily get such a name these in a subdirectory of its own, named after the plugin. To easily get such a name
<modified>
the functions can be given an additional string that will be appended to the returned the functions can be given an additional string that will be appended to the returned
directory name, as in directory name, as in
</modified>
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
const char *MyConfigDir = ConfigDirectory(Name()); const char *MyConfigDir = ConfigDirectory(Name());
@ -946,12 +965,16 @@ plugin's name. Again, VDR will make sure that the requested directory will exist
(or return <tt>NULL</tt> in case of an error). (or return <tt>NULL</tt> in case of an error).
<p> <p>
<b> <b>
<modified>
The returned strings are statically allocated and will be overwritten by subsequent calls! The returned strings are statically allocated and will be overwritten by subsequent calls!
</modified>
</b> </b>
<p> <p>
<modified>
The <tt>ConfigDirectory()</tt>, <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt> The <tt>ConfigDirectory()</tt>, <tt>CacheDirectory()</tt> and <tt>ResourceDirectory()</tt>
functions are static member functions of the <tt>cPlugin</tt> class. This allows them to be functions are static member functions of the <tt>cPlugin</tt> class. This allows them to be
called even from outside any member function of the derived plugin class, by writing called even from outside any member function of the derived plugin class, by writing
</modified>
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
const char *MyConfigDir = cPlugin::ConfigDirectory(); const char *MyConfigDir = cPlugin::ConfigDirectory();
@ -1161,60 +1184,6 @@ The returned string may consist of several lines, separated by the newline chara
('<tt>\n</tt>'). Each of these lines will be preceded with the <tt>ReplyCode</tt> ('<tt>\n</tt>'). Each of these lines will be preceded with the <tt>ReplyCode</tt>
when presenting them to the caller, and the continuation character ('<tt>-</tt>') when presenting them to the caller, and the continuation character ('<tt>-</tt>')
will be set for all but the last one. will be set for all but the last one.
<p>
<b>The SVDRP functions are called from the separate "SVDRP server handler" thread.
Therefore the plugin needs to take care of proper <a href="#Locking">locking</a> if it accesses any
global data.</b>
<hr><h2><a name="Locking">Locking</a></h2>
<div class="blurb">U can't touch this</div><p>
When accessing global data structures, proper locking is absolutely necessary.
<p>
There are several macros that allow for easy locking and unlocking. They all
follow the naming convention <tt>LOCK_*_READ|WRITE</tt>, where <tt>'*'</tt> is the name
of the global data structure, which can be one of <tt>TIMERS</tt>, <tt>CHANNELS</tt>,
<tt>RECORDINGS</tt> or <tt>SCHEDULES</tt>. To implicitly avoid deadlocks in case you
need to lock more than one structure, always make sure you use these macros in
this sequence!
<p>
Using one of these macros sets a lock on the structure, creates a local pointer to the
respective structure and makes sure the lock is released at the end of the current
block:
<p><table><tr><td class="code"><pre>
if (some condition) {
LOCK_TIMERS_READ; // creates local const cTimers *Timers
for (const cTimer *Timer = Timers-&gt;First(); Timer; Timer = Timers-&gt;Next(Timer)) {
// do something with Timer
}
}
</pre></td></tr></table><p>
Note the naming convention: TIMERS -&gt; Timers etc.
<p>
The <tt>LOCK_*_READ</tt> macros create pointers that are '<tt>const</tt>', while
the <tt>LOCK_*_WRITE</tt> macros allow modifications to the data structures.
Both wait indefinitely to obtain the lock. However, if <tt>LOCK_*_WRITE</tt> is
used twice in the same block, the second call will not obtain a lock and
immediately return <tt>NULL</tt>, which may lead to a crash. In such cases a
warning and backtrace is logged.
<p>
You may keep pointers to objects in such lists, even after releasing
the lock. However, you may only access such objects if you are
holding a proper lock again. If an object has been deleted from the list
while you did not hold a lock (for instance by an other thread), the
object will still be there, but no longer within this list (it is then
stored in the ListGarbageCollector for a few seconds). That way even if you
access the object after it has been deleted, you won't cause a segfault.
You can call the Contains() function to check whether an object you are
holding a pointer to is still in the list. Note that the garbage collector
is purged when the usual housekeeping is done.
<p>
See tools.h, class <tt>cListBase</tt> for more documentation and information on how
to use locking with timeouts, and thread.h, classes <tt>cStateLock</tt> and
<tt>cStateKey</tt> on how to easily react to changes in such lists.
<hr><h2><a name="Loading plugins into VDR">Loading plugins into VDR</a></h2> <hr><h2><a name="Loading plugins into VDR">Loading plugins into VDR</a></h2>
@ -1296,10 +1265,10 @@ If a plugin wants to get informed on various events in VDR, it can derive a clas
class cMyStatusMonitor : public cStatus { class cMyStatusMonitor : public cStatus {
protected: protected:
virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView); virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber<modified>, bool LiveView</modified>);
}; };
void cMyStatusMonitor::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView) void cMyStatusMonitor::ChannelSwitch(const cDevice *Device, int ChannelNumber<modified>, bool LiveView</modified>)
{ {
if (ChannelNumber) if (ChannelNumber)
dsyslog("channel switched to %d on DVB %d", ChannelNumber, Device-&gt;CardIndex()); dsyslog("channel switched to %d on DVB %d", ChannelNumber, Device-&gt;CardIndex());
@ -1556,11 +1525,13 @@ public:
cMyReceiver(int Pid); cMyReceiver(int Pid);
}; };
<modified>
cMyReceiver::cMyReceiver(int Pid) cMyReceiver::cMyReceiver(int Pid)
:cReceiver(NULL, -1) :cReceiver(NULL, -1)
{ {
AddPid(Pid); AddPid(Pid);
} }
</modified>
cMyReceiver::~cMyReceiver() cMyReceiver::~cMyReceiver()
{ {
@ -1586,7 +1557,7 @@ The above example sets up a receiver that wants to receive data from only one
PID (for example the Teletext PID). In order to not interfere with other recording PID (for example the Teletext PID). In order to not interfere with other recording
operations, it sets its priority to <tt>-1</tt> (any negative value will allow operations, it sets its priority to <tt>-1</tt> (any negative value will allow
a <tt>cReceiver</tt> to be detached from its <tt>cDevice</tt> at any time a <tt>cReceiver</tt> to be detached from its <tt>cDevice</tt> at any time
in favor of a timer recording or live viewing). <modified>in favor of a timer recording or live viewing</modified>).
<p> <p>
Once a <tt>cReceiver</tt> has been created, it needs to be <i>attached</i> to Once a <tt>cReceiver</tt> has been created, it needs to be <i>attached</i> to
a <tt>cDevice</tt>: a <tt>cDevice</tt>:
@ -1602,7 +1573,9 @@ the receiver is attached to the device that actually receives the current live
video stream (this may be different from the primary device in case of <i>Transfer video stream (this may be different from the primary device in case of <i>Transfer
Mode</i>). Mode</i>).
<p> <p>
<modified>
The <tt>cReceiver</tt> must be detached from its device before it is deleted. The <tt>cReceiver</tt> must be detached from its device before it is deleted.
</modified>
<hr><h2><a name="Filters">Filters</a></h2> <hr><h2><a name="Filters">Filters</a></h2>
@ -1731,7 +1704,7 @@ restricts this to a <tt>cOsdObject</tt> returned from the plugin's <tt>MainMenuA
function, or any of the skin classes a plugin might implement. function, or any of the skin classes a plugin might implement.
<p> <p>
If a plugin runs a separate thread and wants to issue a message directly from If a plugin runs a separate thread and wants to issue a message directly from
within that thread, it can call within that tread, it can call
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
int cSkins::QueueMessage(eMessageType Type, const char *s, int Seconds = 0, int Timeout = 0); int cSkins::QueueMessage(eMessageType Type, const char *s, int Seconds = 0, int Timeout = 0);
@ -1880,7 +1853,7 @@ If the new device can receive, it most likely needs to provide a way of
selecting which channel it shall tune to: selecting which channel it shall tune to:
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
virtual int NumProvidedSystems(void) const; <modified>virtual int NumProvidedSystems(void) const;</modified>
virtual bool ProvidesSource(int Source) const; virtual bool ProvidesSource(int Source) const;
virtual bool ProvidesTransponder(const cChannel *Channel) const; virtual bool ProvidesTransponder(const cChannel *Channel) const;
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const; virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
@ -1929,9 +1902,9 @@ virtual bool HasDecoder(void) const;
virtual bool CanReplay(void) const; virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode PlayMode); virtual bool SetPlayMode(ePlayMode PlayMode);
virtual int64_t GetSTC(void); virtual int64_t GetSTC(void);
virtual bool IsPlayingVideo(void) const; <modified>virtual bool IsPlayingVideo(void) const;</modified>
virtual bool HasIBPTrickSpeed(void); virtual bool HasIBPTrickSpeed(void);
virtual void TrickSpeed(int Speed, bool Forward); virtual void TrickSpeed(int Speed);
virtual void Clear(void); virtual void Clear(void);
virtual void Play(void); virtual void Play(void);
virtual void Freeze(void); virtual void Freeze(void);
@ -1958,7 +1931,7 @@ the functions
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask); virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
virtual int ReadFilter(int Handle, void *Buffer, size_t Length); <modified>virtual int ReadFilter(int Handle, void *Buffer, size_t Length);</modified>
virtual void CloseFilter(int Handle); virtual void CloseFilter(int Handle);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -2014,6 +1987,7 @@ user - whether this goes through OSD facilities of the physical device (like
a "full featured" DVB card) or through a graphics adapter that overlays its a "full featured" DVB card) or through a graphics adapter that overlays its
output with the video signal, doesn't matter. output with the video signal, doesn't matter.
<p> <p>
<div class="modified">
In order to be able to determine the proper size of the OSD, the device In order to be able to determine the proper size of the OSD, the device
should implement the function should implement the function
@ -2022,6 +1996,7 @@ virtual void GetOsdSize(int &amp;Width, int &amp;Height, double &amp;Aspect);
</pre></td></tr></table><p> </pre></td></tr></table><p>
By default, an OSD size of 720x480 with an aspect ratio of 1.0 is assumed. By default, an OSD size of 720x480 with an aspect ratio of 1.0 is assumed.
</div modified>
<p> <p>
<b>Initializing new devices</b> <b>Initializing new devices</b>
@ -2042,13 +2017,14 @@ Nothing needs to be done to shut down the devices. VDR will automatically
shut down (delete) all devices when the program terminates. It is therefore shut down (delete) all devices when the program terminates. It is therefore
important that the devices are created on the heap, using the <tt>new</tt> important that the devices are created on the heap, using the <tt>new</tt>
operator! operator!
<div class="modified">
<p> <p>
<b>Device hooks</b> <b>Device hooks</b>
<p> <p>
VDR has builtin facilities that select which device is able to provide a given VDR has builtin facilities that select which device is able to provide a given
transponder, or, which device may provide EIT data. However, there may be transponder. However, there may be situations where the setup is so special
situations where the setup is so special that it requires considerations that that it requires considerations that exceed the scope of the core VDR code.
exceed the scope of the core VDR code.
This is where <i>device hooks</i> can be used. This is where <i>device hooks</i> can be used.
<p><table><tr><td class="code"><pre> <p><table><tr><td class="code"><pre>
@ -2056,7 +2032,6 @@ class cMyDeviceHook : public cDeviceHook {
public: public:
cMyDeviceHook(void); cMyDeviceHook(void);
virtual bool DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const; virtual bool DeviceProvidesTransponder(const cDevice *Device, const cChannel *Channel) const;
virtual bool DeviceProvidesEIT(const cDevice *Device) const;
}; };
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -2073,19 +2048,6 @@ bool cMyDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChan
} }
</pre></td></tr></table><p> </pre></td></tr></table><p>
In its <tt>DeviceProvidesEIT()</tt> function the device hook can take
whatever actions are necessary to determine whether the given Device can
provide EIT data, as in
<p><table><tr><td class="code"><pre>
bool cMyDeviceHook::DeviceProvidesEIT(const cDevice *Device) const
{
if (<i>condition where Device can't provide EIT data</i>)
return false;
return true;
}
</pre></td></tr></table><p>
A plugin that creates a derived cDeviceHook shall do so in its <tt>Initialize()</tt> A plugin that creates a derived cDeviceHook shall do so in its <tt>Initialize()</tt>
function, as in function, as in
@ -2094,56 +2056,7 @@ new cMyDeviceHook;
</pre></td></tr></table><p> </pre></td></tr></table><p>
and shall not delete this object. It will be automatically deleted when the program ends. and shall not delete this object. It will be automatically deleted when the program ends.
<p> </div modified>
<b>Power management</b>
<p>
A device that can be put into a power save mode can implement the function
<p><table><tr><td class="code"><pre>
virtual void SetPowerSaveMode(bool On);
</pre></td></tr></table><p>
If On is true, power save mode shall be activated, if it is false,
normal operating mode shall be restored.
<hr><h2><a name="Positioners">Positioners</a></h2>
<div class="blurb">Now you see me - now you don't!</div><p>
If you are using a positioner (also known as "motor" or "rotor") to move your
satellite dish to receive various satellites, you will be using the 'P' command
in the <tt>diseqc.conf</tt> file. This command sends the necessary data to the
positioner to move the dish to the satellite's orbital position. By default VDR
uses its builtin DiSEqC positioner control. If your positioner requires a different
method of controlling (like maybe via a serial link), you can derive a class
from <tt>cPositioner</tt>, as in
<p><table><tr><td class="code"><pre>
#include &lt;vdr/positioner.h&gt;
class cMyPositioner : public cPositioner {
public:
cMyPositioner(void);
virtual void Drive(ePositionerDirection Direction);
virtual void Step(ePositionerDirection Direction, uint Steps = 1);
virtual void Halt(void);
virtual void SetLimit(ePositionerDirection Direction);
virtual void DisableLimits(void);
virtual void EnableLimits(void);
virtual void StorePosition(uint Number);
virtual void RecalcPositions(uint Number);
virtual void GotoPosition(uint Number, int Longitude);
virtual void GotoAngle(int Longitude);
};
</pre></td></tr></table><p>
See the implementation of <tt>cDiseqcPositioner</tt> in <tt>diseqc.c</tt> for details.
<p>
You should create your derived positioner object in the
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
Note that the object has to be created on the heap (using <tt>new</tt>),
and you shall not delete it at any point (it will be deleted automatically
when the program ends).
<hr><h2><a name="Audio">Audio</a></h2> <hr><h2><a name="Audio">Audio</a></h2>
@ -2309,10 +2222,12 @@ Put(uint64 Code, bool Repeat = false, bool Release = false);
The other parameters have the same meaning as in the first version of this function. The other parameters have the same meaning as in the first version of this function.
<p> <p>
<modified>
If your remote control has a repeat function that automatically repeats key events If your remote control has a repeat function that automatically repeats key events
if a key is held pressed down for a while, your derived class should use the global if a key is held pressed down for a while, your derived class should use the global
parameters <tt>Setup.RcRepeatDelay</tt> and <tt>Setup.RcRepeatDelta</tt> to allow parameters <tt>Setup.RcRepeatDelay</tt> and <tt>Setup.RcRepeatDelta</tt> to allow
users to configure the behavior of this function. users to configure the behavior of this function.
</modified>
<hr><h2><a name="Conditional Access">Conditional Access</a></h2> <hr><h2><a name="Conditional Access">Conditional Access</a></h2>
@ -2349,6 +2264,7 @@ virtual bool Assign(cDevice *Device, bool Query = false);
See the description of this function in <tt>ci.h</tt> for details. See the description of this function in <tt>ci.h</tt> for details.
<div class="modified">
<hr><h2><a name="Electronic Program Guide">Electronic Program Guide</a></h2> <hr><h2><a name="Electronic Program Guide">Electronic Program Guide</a></h2>
<div class="blurb">The grass is always greener on the other side...</div><p> <div class="blurb">The grass is always greener on the other side...</div><p>
@ -2378,40 +2294,7 @@ where <tt>DescriptionFromDatabase()</tt> would derive the description of the
to signal VDR that no other EPG handlers shall be queried after this one. to signal VDR that no other EPG handlers shall be queried after this one.
<p> <p>
See <tt>VDR/epg.h</tt> for details. See <tt>VDR/epg.h</tt> for details.
</div modified>
<hr><h2><a name="The video directory">The video directory</a></h2>
<div class="blurb">Bits and pieces...</div><p>
By default VDR assumes that the video directory consists of one large
volume, on which it can store its recordings. If you want to distribute your
recordings over several physical drives, you can derive from <tt>cVideoDirectory</tt>,
as in
<p><table><tr><td class="code"><pre>
#include &lt;vdr/videodir.h&gt;
class cMyVideoDirectory : public cVideoDirectory {
public:
cMyVideoDirectory(void);
virtual ~cMyVideoDirectory();
virtual int FreeMB(int *UsedMB = NULL);
virtual bool Register(const char *FileName);
virtual bool Rename(const char *OldName, const char *NewName);
virtual bool Move(const char *FromName, const char *ToName);
virtual bool Remove(const char *Name);
virtual void Cleanup(const char *IgnoreFiles[] = NULL);
virtual bool Contains(const char *Name);
};
</pre></td></tr></table><p>
See the description in <tt>videodir.h</tt> for details.
<p>
You should create your derived video directory object in the
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
Note that the object has to be created on the heap (using <tt>new</tt>),
and you shall not delete it at any point (it will be deleted automatically
when the program ends).
</body> </body>
</html> </html>

View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
VDR Plugin 'dvbsddevice' Revision History
-----------------------------------------
2009-12-28: Version 0.0.1
- Initial revision.
2010-01-04: Version 0.0.2
- Calling the MakePrimaryDevice() function of the base class to allow
the cDevice to stop displaying subtitles.
- Added support for DVB cards with multiple fontends.
2010-01-30: Version 0.0.3
- The PCR pid is now recorded for channels where this is different from the
video PID.
2011-04-17: Version 0.0.4
- Removed an obsolete local variable in dvbsdffosd.c (thanks to Paul Menzel).
2011-08-27: Version 0.0.5
- Added option --outputonly to use the device only for output (thanks to Udo Richter).
2012-03-07: Version 0.0.6
- Removed the call to EITScanner.UsesDevice(this) from dvbsddevice.c, because
the code following these calls is only executed if LiveView is true, which is
never the case when the EITScanner switches to a channel.
2012-12-27: Version 0.0.7
- Adapted Makefile to changes introduced in recent VDR versions.
2013-01-12: Version 0.0.8
- Adapted Makefile to changes introduced in recent VDR versions.
2013-01-25: Version 0.0.9
- Returning 0 from cDvbSdFfDevice::NumProvidedSystems() if option --outputonly is given.
2013-03-31: Version 2.0.0
- Official release.

View File

@ -0,0 +1,94 @@
#
# Makefile for a Video Disk Recorder plugin
#
# $Id: Makefile 1.20 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
# By default the main source file also carries this name.
PLUGIN = dvbsddevice
### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here):
INCLUDES +=
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
### The object files (add further files here):
OBJS = $(PLUGIN).o dvbsdffdevice.o dvbsdffosd.o
### The main target:
all: $(SOFILE)
### Implicit rules:
%.o: %.c
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies:
MAKEDEP = $(CXX) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
-include $(DEPFILE)
### Targets:
$(SOFILE): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
install: install-lib
dist: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
clean:
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~

View File

@ -0,0 +1,20 @@
This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <Klaus.Schmidinger@tvdr.de>
Project's homepage: http://www.tvdr.de
Latest version available at: ftp://ftp.tvdr.de/vdr
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
See the file COPYING for more information.
Description:
The 'dvbsddevice' plugin implements the output device for the
"Full Featured" DVB cards based on the TechnoTrend/Fujitsu-Siemens
design. This code was originally part of the core VDR source, and
was moved into this plugin in VDR version 1.7.11.

View File

@ -0,0 +1,61 @@
/*
* dvbsddevice.c: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsddevice.c 1.10 2013/03/31 09:30:18 kls Exp $
*/
#include <getopt.h>
#include <vdr/plugin.h>
#include "dvbsdffdevice.h"
static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "SD Full Featured DVB device";
class cPluginDvbsddevice : public cPlugin {
private:
cDvbSdFfDeviceProbe *probe;
public:
cPluginDvbsddevice(void);
virtual ~cPluginDvbsddevice();
virtual const char *Version(void) { return VERSION; }
virtual const char *Description(void) { return DESCRIPTION; }
virtual const char *CommandLineHelp(void);
virtual bool ProcessArgs(int argc, char *argv[]);
};
cPluginDvbsddevice::cPluginDvbsddevice(void)
{
probe = new cDvbSdFfDeviceProbe;
}
cPluginDvbsddevice::~cPluginDvbsddevice()
{
delete probe;
}
const char *cPluginDvbsddevice::CommandLineHelp(void)
{
return " -o --outputonly do not receive, just use as output device\n";
}
bool cPluginDvbsddevice::ProcessArgs(int argc, char *argv[])
{
static struct option long_options[] = {
{ "outputonly", no_argument, NULL, 'o' },
{ NULL, no_argument, NULL, 0 }
};
int c;
while ((c = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
switch (c) {
case 'o': probe->SetOutputOnly(true);
break;
default: return false;
}
}
return true;
}
VDRPLUGINCREATOR(cPluginDvbsddevice); // Don't touch this!

View File

@ -0,0 +1,799 @@
/*
* dvbsdffdevice.h: The DVB SD Full Featured device interface
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsdffdevice.c 2.35 2013/02/17 13:16:18 kls Exp $
*/
#include "dvbsdffdevice.h"
#include <errno.h>
#include <limits.h>
#include <linux/videodev2.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/video.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <vdr/eitscan.h>
#include <vdr/transfer.h>
#include "dvbsdffosd.h"
// --- cDvbSdFfDevice --------------------------------------------------------
int cDvbSdFfDevice::devVideoOffset = -1;
cDvbSdFfDevice::cDvbSdFfDevice(int Adapter, int Frontend, bool OutputOnly)
:cDvbDevice(Adapter, Frontend)
{
spuDecoder = NULL;
digitalAudio = false;
playMode = pmNone;
outputOnly = OutputOnly;
// Devices that are only present on cards with decoders:
fd_osd = DvbOpen(DEV_DVB_OSD, adapter, frontend, O_RDWR);
fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
fd_stc = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR);
// The offset of the /dev/video devices:
if (devVideoOffset < 0) { // the first one checks this
FILE *f = NULL;
char buffer[PATH_MAX];
for (int ofs = 0; ofs < 100; ofs++) {
snprintf(buffer, sizeof(buffer), "/proc/video/dev/video%d", ofs);
if ((f = fopen(buffer, "r")) != NULL) {
if (fgets(buffer, sizeof(buffer), f)) {
if (strstr(buffer, "DVB Board")) { // found the _first_ DVB card
devVideoOffset = ofs;
dsyslog("video device offset is %d", devVideoOffset);
break;
}
}
else
break;
fclose(f);
}
else
break;
}
if (devVideoOffset < 0)
devVideoOffset = 0;
if (f)
fclose(f);
}
devVideoIndex = devVideoOffset >= 0 ? devVideoOffset++ : -1;
}
cDvbSdFfDevice::~cDvbSdFfDevice()
{
delete spuDecoder;
// We're not explicitly closing any device files here, since this sometimes
// caused segfaults. Besides, the program is about to terminate anyway...
}
void cDvbSdFfDevice::MakePrimaryDevice(bool On)
{
if (On)
new cDvbOsdProvider(fd_osd);
cDvbDevice::MakePrimaryDevice(On);
}
bool cDvbSdFfDevice::HasDecoder(void) const
{
return true;
}
bool cDvbSdFfDevice::AvoidRecording(void) const
{
return true;
}
cSpuDecoder *cDvbSdFfDevice::GetSpuDecoder(void)
{
if (!spuDecoder && IsPrimaryDevice())
spuDecoder = new cDvbSpuDecoder();
return spuDecoder;
}
uchar *cDvbSdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
{
if (devVideoIndex < 0)
return NULL;
char buffer[PATH_MAX];
snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, devVideoIndex);
int videoDev = open(buffer, O_RDWR);
if (videoDev >= 0) {
uchar *result = NULL;
// set up the size and RGB
v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = SizeX;
fmt.fmt.pix.height = SizeY;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
if (ioctl(videoDev, VIDIOC_S_FMT, &fmt) == 0) {
v4l2_requestbuffers reqBuf;
memset(&reqBuf, 0, sizeof(reqBuf));
reqBuf.count = 2;
reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqBuf.memory = V4L2_MEMORY_MMAP;
if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) {
v4l2_buffer mbuf;
memset(&mbuf, 0, sizeof(mbuf));
mbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mbuf.memory = V4L2_MEMORY_MMAP;
if (ioctl(videoDev, VIDIOC_QUERYBUF, &mbuf) == 0) {
int msize = mbuf.length;
unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
if (mem && mem != (unsigned char *)-1) {
v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(videoDev, VIDIOC_QBUF, &buf) == 0) {
v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (videoDev, VIDIOC_STREAMON, &type) == 0) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) {
if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) {
// make RGB out of BGR:
int memsize = fmt.fmt.pix.width * fmt.fmt.pix.height;
unsigned char *mem1 = mem;
for (int i = 0; i < memsize; i++) {
unsigned char tmp = mem1[2];
mem1[2] = mem1[0];
mem1[0] = tmp;
mem1 += 3;
}
if (Quality < 0)
Quality = 100;
dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height);
if (Jpeg) {
// convert to JPEG:
result = RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality);
if (!result)
esyslog("ERROR: failed to convert image to JPEG");
}
else {
// convert to PNM:
char buf[32];
snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
int l = strlen(buf);
int bytes = memsize * 3;
Size = l + bytes;
result = MALLOC(uchar, Size);
if (result) {
memcpy(result, buf, l);
memcpy(result + l, mem, bytes);
}
else
esyslog("ERROR: failed to convert image to PNM");
}
}
else
esyslog("ERROR: video device VIDIOC_STREAMOFF failed");
}
else
esyslog("ERROR: video device VIDIOC_DQBUF failed");
}
else
esyslog("ERROR: video device VIDIOC_STREAMON failed");
}
else
esyslog("ERROR: video device VIDIOC_QBUF failed");
munmap(mem, msize);
}
else
esyslog("ERROR: failed to memmap video device");
}
else
esyslog("ERROR: video device VIDIOC_QUERYBUF failed");
}
else
esyslog("ERROR: video device VIDIOC_REQBUFS failed");
}
else
esyslog("ERROR: video device VIDIOC_S_FMT failed");
close(videoDev);
return result;
}
else
LOG_ERROR_STR(buffer);
return NULL;
}
void cDvbSdFfDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
{
cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
if (Setup.VideoFormat) {
CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
}
else {
switch (VideoDisplayFormat) {
case vdfPanAndScan:
CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_PAN_SCAN));
break;
case vdfLetterBox:
CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
break;
case vdfCenterCutOut:
CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT));
break;
default: esyslog("ERROR: unknown video display format %d", VideoDisplayFormat);
}
}
}
void cDvbSdFfDevice::SetVideoFormat(bool VideoFormat16_9)
{
CHECK(ioctl(fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
}
eVideoSystem cDvbSdFfDevice::GetVideoSystem(void)
{
eVideoSystem VideoSystem = vsPAL;
if (fd_video >= 0) {
video_size_t vs;
if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
if (vs.h == 480 || vs.h == 240)
VideoSystem = vsNTSC;
}
else
LOG_ERROR;
}
return VideoSystem;
}
void cDvbSdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
{
if (fd_video >= 0) {
video_size_t vs;
if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
Width = vs.w;
Height = vs.h;
switch (vs.aspect_ratio) {
default:
case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0; break;
case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0; break;
case VIDEO_FORMAT_221_1: VideoAspect = 2.21; break;
}
return;
}
else
LOG_ERROR;
}
cDevice::GetVideoSize(Width, Height, VideoAspect);
}
void cDvbSdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
{
if (fd_video >= 0) {
video_size_t vs;
if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
Width = 720;
if (vs.h != 480 && vs.h != 240)
Height = 576; // PAL
else
Height = 480; // NTSC
switch (Setup.VideoFormat ? vs.aspect_ratio : VIDEO_FORMAT_4_3) {
default:
case VIDEO_FORMAT_4_3: PixelAspect = 4.0 / 3.0; break;
case VIDEO_FORMAT_221_1: // FF DVB cards only distinguish between 4:3 and 16:9
case VIDEO_FORMAT_16_9: PixelAspect = 16.0 / 9.0; break;
}
PixelAspect /= double(Width) / Height;
return;
}
else
LOG_ERROR;
}
cDevice::GetOsdSize(Width, Height, PixelAspect);
}
bool cDvbSdFfDevice::SetAudioBypass(bool On)
{
if (setTransferModeForDolbyDigital != 1)
return false;
return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
}
// ptAudio ptVideo ptPcr ptTeletext ptDolby ptOther
static dmx_pes_type_t PesTypes[] = { DMX_PES_AUDIO, DMX_PES_VIDEO, DMX_PES_PCR, DMX_PES_TELETEXT, DMX_PES_OTHER, DMX_PES_OTHER };
bool cDvbSdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On)
{
if (Handle->pid) {
dmx_pes_filter_params pesFilterParams;
memset(&pesFilterParams, 0, sizeof(pesFilterParams));
if (On) {
if (Handle->handle < 0) {
Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
if (Handle->handle < 0) {
LOG_ERROR;
return false;
}
}
pesFilterParams.pid = Handle->pid;
pesFilterParams.input = DMX_IN_FRONTEND;
pesFilterParams.output = (Type <= ptTeletext && Handle->used <= 1) ? DMX_OUT_DECODER : DMX_OUT_TS_TAP;
pesFilterParams.pes_type= PesTypes[Type < ptOther ? Type : ptOther];
pesFilterParams.flags = DMX_IMMEDIATE_START;
if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
LOG_ERROR;
return false;
}
}
else if (!Handle->used) {
CHECK(ioctl(Handle->handle, DMX_STOP));
if (Type <= ptTeletext) {
pesFilterParams.pid = 0x1FFF;
pesFilterParams.input = DMX_IN_FRONTEND;
pesFilterParams.output = DMX_OUT_DECODER;
pesFilterParams.pes_type= PesTypes[Type];
pesFilterParams.flags = DMX_IMMEDIATE_START;
CHECK(ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams));
if (PesTypes[Type] == DMX_PES_VIDEO) // let's only do this once
SetPlayMode(pmNone); // necessary to switch a PID from DMX_PES_VIDEO/AUDIO to DMX_PES_OTHER
}
close(Handle->handle);
Handle->handle = -1;
}
}
return true;
}
bool cDvbSdFfDevice::ProvidesSource(int Source) const
{
if (outputOnly)
return false;
else
return cDvbDevice::ProvidesSource(Source);
}
int cDvbSdFfDevice::NumProvidedSystems(void) const
{
if (outputOnly)
return 0;
return cDvbDevice::NumProvidedSystems();
}
void cDvbSdFfDevice::TurnOffLiveMode(bool LiveView)
{
if (LiveView) {
// Avoid noise while switching:
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
}
// Turn off live PIDs:
DetachAll(pidHandles[ptAudio].pid);
DetachAll(pidHandles[ptVideo].pid);
DetachAll(pidHandles[ptPcr].pid);
DetachAll(pidHandles[ptTeletext].pid);
DelPid(pidHandles[ptAudio].pid);
DelPid(pidHandles[ptVideo].pid);
DelPid(pidHandles[ptPcr].pid, ptPcr);
DelPid(pidHandles[ptTeletext].pid);
DelPid(pidHandles[ptDolby].pid);
}
bool cDvbSdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
int apid = Channel->Apid(0);
int vpid = Channel->Vpid();
int dpid = Channel->Dpid(0);
bool DoTune = !IsTunedToTransponder(Channel);
bool pidHandlesVideo = pidHandles[ptVideo].pid == vpid;
bool pidHandlesAudio = pidHandles[ptAudio].pid == apid;
bool TurnOffLivePIDs = DoTune
|| !IsPrimaryDevice()
|| LiveView // for a new live view the old PIDs need to be turned off
|| pidHandlesVideo // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
;
bool StartTransferMode = IsPrimaryDevice() && !DoTune
&& (LiveView && HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ? pidHandles[ptAudio].pid != dpid : true)))// the PID is already set as DMX_PES_OTHER
|| !LiveView && (pidHandlesVideo || pidHandlesAudio) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber()))
StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN;
bool TurnOnLivePIDs = !StartTransferMode && LiveView;
// Turn off live PIDs if necessary:
if (TurnOffLivePIDs)
TurnOffLiveMode(LiveView);
// Set the tuner:
if (!cDvbDevice::SetChannelDevice(Channel, LiveView))
return false;
// PID settings:
if (TurnOnLivePIDs) {
SetAudioBypass(false);
if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo) && AddPid(apid, ptAudio))) {
esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
return false;
}
if (IsPrimaryDevice())
AddPid(Channel->Tpid(), ptTeletext);
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true)); // actually one would expect 'false' here, but according to Marco Schluessler <marco@lordzodiac.de> this works
// to avoid missing audio after replaying a DVD; with 'false' there is an audio disturbance when switching
// between two channels on the same transponder on DVB-S
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
}
else if (StartTransferMode)
cControl::Launch(new cTransferControl(this, Channel));
return true;
}
int cDvbSdFfDevice::GetAudioChannelDevice(void)
{
audio_status_t as;
CHECK(ioctl(fd_audio, AUDIO_GET_STATUS, &as));
return as.channel_select;
}
void cDvbSdFfDevice::SetAudioChannelDevice(int AudioChannel)
{
CHECK(ioctl(fd_audio, AUDIO_CHANNEL_SELECT, AudioChannel));
}
void cDvbSdFfDevice::SetVolumeDevice(int Volume)
{
if (digitalAudio)
Volume = 0;
audio_mixer_t am;
// conversion for linear volume response:
am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255;
CHECK(ioctl(fd_audio, AUDIO_SET_MIXER, &am));
}
void cDvbSdFfDevice::SetDigitalAudioDevice(bool On)
{
if (digitalAudio != On) {
if (digitalAudio)
cCondWait::SleepMs(1000); // Wait until any leftover digital data has been flushed
digitalAudio = On;
SetVolumeDevice(On || IsMute() ? 0 : CurrentVolume());
}
}
void cDvbSdFfDevice::SetAudioTrackDevice(eTrackType Type)
{
const tTrackId *TrackId = GetTrack(Type);
if (TrackId && TrackId->id) {
SetAudioBypass(false);
if (IS_AUDIO_TRACK(Type) || (IS_DOLBY_TRACK(Type) && SetAudioBypass(true))) {
if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
DetachAll(pidHandles[ptAudio].pid);
if (CamSlot())
CamSlot()->SetPid(pidHandles[ptAudio].pid, false);
pidHandles[ptAudio].pid = TrackId->id;
SetPid(&pidHandles[ptAudio], ptAudio, true);
if (CamSlot()) {
CamSlot()->SetPid(pidHandles[ptAudio].pid, true);
CamSlot()->StartDecrypting();
}
}
}
else if (IS_DOLBY_TRACK(Type)) {
if (setTransferModeForDolbyDigital == 0)
return;
// Currently this works only in Transfer Mode
ForceTransferMode();
}
}
}
bool cDvbSdFfDevice::CanReplay(void) const
{
return cDevice::CanReplay();
}
bool cDvbSdFfDevice::SetPlayMode(ePlayMode PlayMode)
{
if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
// reopen the devices
fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
SetVideoFormat(Setup.VideoFormat);
}
switch (PlayMode) {
case pmNone:
// special handling to return from PCM replay:
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
CHECK(ioctl(fd_video, VIDEO_PLAY));
CHECK(ioctl(fd_video, VIDEO_STOP, true));
CHECK(ioctl(fd_audio, AUDIO_STOP, true));
CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
break;
case pmAudioVideo:
case pmAudioOnlyBlack:
if (playMode == pmNone)
TurnOffLiveMode(true);
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo));
CHECK(ioctl(fd_audio, AUDIO_PLAY));
CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
CHECK(ioctl(fd_video, VIDEO_PLAY));
break;
case pmAudioOnly:
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_STOP, true));
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
CHECK(ioctl(fd_audio, AUDIO_PLAY));
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
break;
case pmVideoOnly:
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_video, VIDEO_STOP, true));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
CHECK(ioctl(fd_audio, AUDIO_PLAY));
CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
CHECK(ioctl(fd_video, VIDEO_PLAY));
break;
case pmExtern_THIS_SHOULD_BE_AVOIDED:
close(fd_video);
close(fd_audio);
fd_video = fd_audio = -1;
break;
default: esyslog("ERROR: unknown playmode %d", PlayMode);
}
playMode = PlayMode;
return true;
}
int64_t cDvbSdFfDevice::GetSTC(void)
{
if (fd_stc >= 0) {
struct dmx_stc stc;
stc.num = 0;
if (ioctl(fd_stc, DMX_GET_STC, &stc) == -1) {
esyslog("ERROR: stc %d: %m", CardIndex() + 1);
return -1;
}
return stc.stc / stc.base;
}
return -1;
}
void cDvbSdFfDevice::TrickSpeed(int Speed)
{
if (fd_video >= 0)
CHECK(ioctl(fd_video, VIDEO_SLOWMOTION, Speed));
}
void cDvbSdFfDevice::Clear(void)
{
if (fd_video >= 0)
CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
if (fd_audio >= 0)
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
cDevice::Clear();
}
void cDvbSdFfDevice::Play(void)
{
if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
if (fd_audio >= 0)
CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
}
else {
if (fd_audio >= 0) {
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
}
if (fd_video >= 0)
CHECK(ioctl(fd_video, VIDEO_CONTINUE));
}
cDevice::Play();
}
void cDvbSdFfDevice::Freeze(void)
{
if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
if (fd_audio >= 0)
CHECK(ioctl(fd_audio, AUDIO_PAUSE));
}
else {
if (fd_audio >= 0) {
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
CHECK(ioctl(fd_audio, AUDIO_PAUSE));
}
if (fd_video >= 0)
CHECK(ioctl(fd_video, VIDEO_FREEZE));
}
cDevice::Freeze();
}
void cDvbSdFfDevice::Mute(void)
{
if (fd_audio >= 0) {
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
}
cDevice::Mute();
}
void cDvbSdFfDevice::StillPicture(const uchar *Data, int Length)
{
if (!Data || Length < TS_SIZE)
return;
if (Data[0] == 0x47) {
// TS data
cDevice::StillPicture(Data, Length);
}
else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
// PES data
char *buf = MALLOC(char, Length);
if (!buf)
return;
int i = 0;
int blen = 0;
while (i < Length - 6) {
if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
int len = Data[i + 4] * 256 + Data[i + 5];
if ((Data[i + 3] & 0xF0) == 0xE0) { // video packet
// skip PES header
int offs = i + 6;
// skip header extension
if ((Data[i + 6] & 0xC0) == 0x80) {
// MPEG-2 PES header
if (Data[i + 8] >= Length)
break;
offs += 3;
offs += Data[i + 8];
len -= 3;
len -= Data[i + 8];
if (len < 0 || offs + len > Length)
break;
}
else {
// MPEG-1 PES header
while (offs < Length && len > 0 && Data[offs] == 0xFF) {
offs++;
len--;
}
if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
offs += 2;
len -= 2;
}
if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
offs += 5;
len -= 5;
}
else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
offs += 10;
len -= 10;
}
else if (offs < Length && len > 0) {
offs++;
len--;
}
}
if (blen + len > Length) // invalid PES length field
break;
memcpy(&buf[blen], &Data[offs], len);
i = offs + len;
blen += len;
}
else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets
i += len + 6;
else
i++;
}
else
i++;
}
video_still_picture sp = { buf, blen };
CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
free(buf);
}
else {
// non-PES data
video_still_picture sp = { (char *)Data, Length };
CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
}
}
bool cDvbSdFfDevice::Poll(cPoller &Poller, int TimeoutMs)
{
Poller.Add((playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video, true);
return Poller.Poll(TimeoutMs);
}
bool cDvbSdFfDevice::Flush(int TimeoutMs)
{
//TODO actually this function should wait until all buffered data has been processed by the card, but how?
return true;
}
int cDvbSdFfDevice::PlayVideo(const uchar *Data, int Length)
{
return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
}
int cDvbSdFfDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
{
return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
}
int cDvbSdFfDevice::PlayTsVideo(const uchar *Data, int Length)
{
return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
}
int cDvbSdFfDevice::PlayTsAudio(const uchar *Data, int Length)
{
return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
}
// --- cDvbSdFfDeviceProbe ---------------------------------------------------
cDvbSdFfDeviceProbe::cDvbSdFfDeviceProbe(void)
{
outputOnly = false;
}
bool cDvbSdFfDeviceProbe::Probe(int Adapter, int Frontend)
{
static uint32_t SubsystemIds[] = {
0x110A0000, // Fujitsu Siemens DVB-C
0x13C20000, // Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C
0x13C20001, // Technotrend/Hauppauge WinTV DVB-T rev1.X
0x13C20002, // Technotrend/Hauppauge WinTV DVB-C rev2.X
0x13C20003, // Technotrend/Hauppauge WinTV Nexus-S rev2.X
0x13C20004, // Galaxis DVB-S rev1.3
0x13C20006, // Fujitsu Siemens DVB-S rev1.6
0x13C20008, // Technotrend/Hauppauge DVB-T
0x13C2000A, // Technotrend/Hauppauge WinTV Nexus-CA rev1.X
0x13C2000E, // Technotrend/Hauppauge WinTV Nexus-S rev2.3
0x13C21002, // Technotrend/Hauppauge WinTV DVB-S rev1.3 SE
0x00000000
};
uint32_t SubsystemId = GetSubsystemId(Adapter, Frontend);
for (uint32_t *sid = SubsystemIds; *sid; sid++) {
if (*sid == SubsystemId) {
dsyslog("creating cDvbSdFfDevice");
new cDvbSdFfDevice(Adapter, Frontend, outputOnly);
return true;
}
}
return false;
}

View File

@ -0,0 +1,116 @@
/*
* dvbsdffdevice.h: The DVB SD Full Featured device interface
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsdffdevice.h 2.16 2013/02/17 13:16:29 kls Exp $
*/
#ifndef __DVBSDFFDEVICE_H
#define __DVBSDFFDEVICE_H
#include <vdr/dvbdevice.h>
#include <vdr/dvbspu.h>
/// The cDvbSdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API.
class cDvbSdFfDevice : public cDvbDevice {
private:
int fd_osd, fd_audio, fd_video, fd_stc;
bool outputOnly;
protected:
virtual void MakePrimaryDevice(bool On);
public:
cDvbSdFfDevice(int Adapter, int Frontend, bool OutputOnly);
virtual ~cDvbSdFfDevice();
virtual bool HasDecoder(void) const;
virtual bool AvoidRecording(void) const;
// SPU facilities
private:
cDvbSpuDecoder *spuDecoder;
public:
virtual cSpuDecoder *GetSpuDecoder(void);
// Channel facilities
public:
virtual bool ProvidesSource(int Source) const;
virtual int NumProvidedSystems(void) const;
private:
void TurnOffLiveMode(bool LiveView);
protected:
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
// PID handle facilities
private:
bool SetAudioBypass(bool On);
protected:
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
// Image Grab facilities
private:
static int devVideoOffset;
int devVideoIndex;
public:
virtual uchar *GrabImage(int &Size, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
// Video format facilities
public:
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat);
virtual void SetVideoFormat(bool VideoFormat16_9);
virtual eVideoSystem GetVideoSystem(void);
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect);
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect);
// Track facilities
protected:
virtual void SetAudioTrackDevice(eTrackType Type);
// Audio facilities
private:
bool digitalAudio;
protected:
virtual int GetAudioChannelDevice(void);
virtual void SetAudioChannelDevice(int AudioChannel);
virtual void SetVolumeDevice(int Volume);
virtual void SetDigitalAudioDevice(bool On);
// Player facilities
protected:
ePlayMode playMode;
virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode PlayMode);
virtual int PlayVideo(const uchar *Data, int Length);
virtual int PlayAudio(const uchar *Data, int Length, uchar Id);
virtual int PlayTsVideo(const uchar *Data, int Length);
virtual int PlayTsAudio(const uchar *Data, int Length);
public:
virtual int64_t GetSTC(void);
virtual void TrickSpeed(int Speed);
virtual void Clear(void);
virtual void Play(void);
virtual void Freeze(void);
virtual void Mute(void);
virtual void StillPicture(const uchar *Data, int Length);
virtual bool Poll(cPoller &Poller, int TimeoutMs = 0);
virtual bool Flush(int TimeoutMs = 0);
};
class cDvbSdFfDeviceProbe : public cDvbDeviceProbe {
private:
bool outputOnly;
public:
cDvbSdFfDeviceProbe(void);
void SetOutputOnly(bool On) { outputOnly = On; }
virtual bool Probe(int Adapter, int Frontend);
};
#endif //__DVBSDFFDEVICE_H

View File

@ -0,0 +1,211 @@
/*
* dvbsdffosd.c: Implementation of the DVB SD Full Featured On Screen Display
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsdffosd.c 2.3 2011/04/17 12:55:09 kls Exp $
*/
#include "dvbsdffosd.h"
#include <linux/dvb/osd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/unistd.h>
#include <vdr/tools.h>
// --- cDvbSdFfOsd -----------------------------------------------------------
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
#define MAXOSDMEMORY 92000 // number of bytes available to the OSD (for unmodified DVB cards)
class cDvbSdFfOsd : public cOsd {
private:
int osdDev;
int osdMem;
bool shown;
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
protected:
virtual void SetActive(bool On);
public:
cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level);
virtual ~cDvbSdFfOsd();
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas);
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas);
virtual void Flush(void);
};
cDvbSdFfOsd::cDvbSdFfOsd(int Left, int Top, int OsdDev, uint Level)
:cOsd(Left, Top, Level)
{
osdDev = OsdDev;
shown = false;
if (osdDev < 0)
esyslog("ERROR: invalid OSD device handle (%d)!", osdDev);
else {
osdMem = MAXOSDMEMORY;
#ifdef OSD_CAP_MEMSIZE
// modified DVB cards may have more OSD memory:
osd_cap_t cap;
cap.cmd = OSD_CAP_MEMSIZE;
if (ioctl(osdDev, OSD_GET_CAPABILITY, &cap) == 0)
osdMem = cap.val;
#endif
}
}
cDvbSdFfOsd::~cDvbSdFfOsd()
{
SetActive(false);
}
void cDvbSdFfOsd::SetActive(bool On)
{
if (On != Active()) {
cOsd::SetActive(On);
if (On) {
// must clear all windows here to avoid flashing effects - doesn't work if done
// in Flush() only for the windows that are actually used...
for (int i = 0; i < MAXNUMWINDOWS; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Clear);
}
if (GetBitmap(0)) // only flush here if there are already bitmaps
Flush();
}
else if (shown) {
for (int i = 0; GetBitmap(i); i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Close);
}
shown = false;
}
}
}
eOsdError cDvbSdFfOsd::CanHandleAreas(const tArea *Areas, int NumAreas)
{
eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas);
if (Result == oeOk) {
if (NumAreas > MAXNUMWINDOWS)
return oeTooManyAreas;
int TotalMemory = 0;
for (int i = 0; i < NumAreas; i++) {
if (Areas[i].bpp != 1 && Areas[i].bpp != 2 && Areas[i].bpp != 4 && Areas[i].bpp != 8)
return oeBppNotSupported;
if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0)
return oeWrongAlignment;
if (Areas[i].Width() < 1 || Areas[i].Height() < 1 || Areas[i].Width() > 720 || Areas[i].Height() > 576)
return oeWrongAreaSize;
TotalMemory += Areas[i].Width() * Areas[i].Height() / (8 / Areas[i].bpp);
}
if (TotalMemory > osdMem)
return oeOutOfMemory;
}
return Result;
}
eOsdError cDvbSdFfOsd::SetAreas(const tArea *Areas, int NumAreas)
{
if (shown) {
for (int i = 0; GetBitmap(i); i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_Close);
}
shown = false;
}
return cOsd::SetAreas(Areas, NumAreas);
}
void cDvbSdFfOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
{
if (osdDev >= 0) {
osd_cmd_t dc;
dc.cmd = cmd;
dc.color = color;
dc.x0 = x0;
dc.y0 = y0;
dc.x1 = x1;
dc.y1 = y1;
dc.data = (void *)data;
ioctl(osdDev, OSD_SEND_CMD, &dc);
}
}
void cDvbSdFfOsd::Flush(void)
{
if (!Active())
return;
cBitmap *Bitmap;
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
if (!shown)
Cmd(OSD_Open, Bitmap->Bpp(), Left() + Bitmap->X0(), Top() + Bitmap->Y0(), Left() + Bitmap->X0() + Bitmap->Width() - 1, Top() + Bitmap->Y0() + Bitmap->Height() - 1, (void *)1); // initially hidden!
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
if (!shown || Bitmap->Dirty(x1, y1, x2, y2)) {
if (!shown) {
x1 = y1 = 0;
x2 = Bitmap->Width() - 1;
y2 = Bitmap->Height() - 1;
}
//TODO Workaround: apparently the bitmap sent to the driver always has to be a multiple
//TODO 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 ((x1 > 0 || x2 < Bitmap->Width() - 1) && ((x2 - x1) & 7) != 7) {
if (x2 < Bitmap->Width() - 1)
x2++;
else if (x1 > 0)
x1--;
}
//TODO "... / 2" <==> Bpp???
while ((y1 > 0 || y2 < Bitmap->Height() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
if (y2 < Bitmap->Height() - 1)
y2++;
else if (y1 > 0)
y1--;
}
while ((x1 > 0 || x2 < Bitmap->Width() - 1) && (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) {
if (x2 < Bitmap->Width() - 1)
x2++;
else if (x1 > 0)
x1--;
}
// commit colors:
int NumColors;
const tColor *Colors = Bitmap->Colors(NumColors);
if (Colors) {
//TODO this should be fixed in the driver!
tColor colors[NumColors];
for (int i = 0; i < NumColors; i++) {
// convert AARRGGBB to AABBGGRR (the driver expects the colors the wrong way):
colors[i] = (Colors[i] & 0xFF000000) | ((Colors[i] & 0x0000FF) << 16) | (Colors[i] & 0x00FF00) | ((Colors[i] & 0xFF0000) >> 16);
}
Colors = colors;
//TODO end of stuff that should be fixed in the driver
Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
}
// commit modified data:
Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
}
Bitmap->Clean();
}
if (!shown) {
// Showing the windows in a separate loop to avoid seeing them come up one after another
for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) {
Cmd(OSD_SetWindow, 0, i + 1);
Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0());
}
shown = true;
}
}
// --- cDvbOsdProvider -------------------------------------------------------
cDvbOsdProvider::cDvbOsdProvider(int OsdDev)
{
osdDev = OsdDev;
}
cOsd *cDvbOsdProvider::CreateOsd(int Left, int Top, uint Level)
{
return new cDvbSdFfOsd(Left, Top, osdDev, Level);
}

View File

@ -0,0 +1,22 @@
/*
* dvbsdffosd.h: Implementation of the DVB SD Full Featured On Screen Display
*
* See the README file for copyright information and how to reach the author.
*
* $Id: dvbsdffosd.h 2.2 2012/12/03 13:43:55 kls Exp $
*/
#ifndef __DVBSDFFODF_H
#define __DVBSDFFODF_H
#include <vdr/osd.h>
class cDvbOsdProvider : public cOsdProvider {
private:
int osdDev;
public:
cDvbOsdProvider(int OsdDev);
virtual cOsd *CreateOsd(int Left, int Top, uint Level);
};
#endif //__DVBSDFFODF_H

View File

@ -16,19 +16,3 @@ VDR Plugin 'epgtableid0' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2018-04-15: Version 2.4.0
- Official release.
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 1.13 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
# #
@ -62,8 +61,7 @@ all: $(SOFILE)
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -77,8 +75,7 @@ $(DEPFILE): Makefile
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,13 +3,13 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: epgtableid0.c 4.1 2018/04/10 13:00:18 kls Exp $ * $Id: epgtableid0.c 1.4 2013/03/31 09:30:18 kls Exp $
*/ */
#include <vdr/epg.h> #include <vdr/epg.h>
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.0"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "EPG handler for events with table id 0x00"; static const char *DESCRIPTION = "EPG handler for events with table id 0x00";
// --- cTable0Handler -------------------------------------------------------- // --- cTable0Handler --------------------------------------------------------

View File

@ -86,20 +86,3 @@ VDR Plugin 'hello' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2018-04-15: Version 2.4.0
- Updated the French OSD texts (thanks to Bernard Jaulin).
- Official release.
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.18 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir) LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
@ -63,8 +62,7 @@ all: $(SOFILE) i18n
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -84,16 +82,13 @@ I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLU
I18Npot = $(PODIR)/$(PLUGIN).pot I18Npot = $(PODIR)/$(PLUGIN).pot
%.mo: %.po %.mo: %.po
@echo MO $@ msgfmt -c -o $@ $<
$(Q)msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.c) $(I18Npot): $(wildcard *.c)
@echo GT $@ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
%.po: $(I18Npot) %.po: $(I18Npot)
@echo PO $@ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
$(Q)msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
@touch $@ @touch $@
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo $(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@ -107,8 +102,7 @@ install-i18n: $(I18Nmsgs)
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: hello.c 4.1 2018/04/10 13:00:22 kls Exp $ * $Id: hello.c 2.6 2013/03/31 09:30:18 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -12,7 +12,7 @@
#include <vdr/interface.h> #include <vdr/interface.h>
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.0"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = trNOOP("A friendly greeting"); static const char *DESCRIPTION = trNOOP("A friendly greeting");
static const char *MAINMENUENTRY = trNOOP("Hello"); static const char *MAINMENUENTRY = trNOOP("Hello");

View File

@ -1,5 +1,5 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Marc Rovira Vall <tm05462@salleURL.edu>, 2003 # Marc Rovira Vall <tm05462@salleURL.edu>, 2003
# Ramon Roca <ramon.roca@xcombo.com>, 2003 # Ramon Roca <ramon.roca@xcombo.com>, 2003
@ -7,7 +7,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006 # Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Mogens Elneff <mogens@elneff.dk>, 2004 # Mogens Elneff <mogens@elneff.dk>, 2004
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Klaus Schmidinger <vdr@tvdr.de>, 2000 # Klaus Schmidinger <vdr@tvdr.de>, 2000
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Dimitrios Dimitrakos <mail@dimitrios.de>, 2002 # Dimitrios Dimitrakos <mail@dimitrios.de>, 2002
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Ruben Nunez Francisco <ruben.nunez@tang-it.com>, 2002 # Ruben Nunez Francisco <ruben.nunez@tang-it.com>, 2002
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,35 +1,35 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Arthur Konovalov <artlov@gmail.com>, 2004, 2015 # Arthur Konovalov <kasjas@hot.ee>, 2004
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n" "Last-Translator: Arthur Konovalov <kasjas@hot.ee>\n"
"Language-Team: Estonian <vdr@linuxtv.org>\n" "Language-Team: Estonian <vdr@linuxtv.org>\n"
"Language: et\n" "Language: et\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=ISO-8859-13\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "A friendly greeting" msgid "A friendly greeting"
msgstr "Sõbralik tervitus" msgstr ""
msgid "Hello" msgid "Hello"
msgstr "Tere" msgstr ""
msgid "Greeting time (s)" msgid "Greeting time (s)"
msgstr "Tervituse kestus (s)" msgstr ""
msgid "Use alternate greeting" msgid "Use alternate greeting"
msgstr "Vahelduv tervitus" msgstr ""
msgid "Howdy folks!" msgid "Howdy folks!"
msgstr "Kuidas käsi käib?" msgstr ""
msgid "Hello world!" msgid "Hello world!"
msgstr "Tere, maailm!" msgstr ""

View File

@ -1,5 +1,5 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Hannu Savolainen <hannu@opensound.com>, 2002 # Hannu Savolainen <hannu@opensound.com>, 2002
# Jaakko Hyvätti <jaakko@hyvatti.iki.fi>, 2002 # Jaakko Hyvätti <jaakko@hyvatti.iki.fi>, 2002
@ -8,7 +8,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,19 +1,18 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Jean-Claude Repetto <jc@repetto.org>, 2001 # Jean-Claude Repetto <jc@repetto.org>, 2001
# Olivier Jacques <jacquesolivier@hotmail.com>, 2003 # Olivier Jacques <jacquesolivier@hotmail.com>, 2003
# Gregoire Favre <greg@magma.unil.ch>, 2003 # Gregoire Favre <greg@magma.unil.ch>, 2003
# Nicolas Huillard <nhuillard@e-dition.fr>, 2005 # Nicolas Huillard <nhuillard@e-dition.fr>, 2005
# Bernard Jaulin <bernard.jaulin@gmail.com>, 2018
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2018-04-14 8:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"
"Last-Translator: Bernard Jaulin <bernard.jaulin@gmail.com>\n" "Last-Translator: Nicolas Huillard <nhuillard@e-dition.fr>\n"
"Language-Team: French <vdr@linuxtv.org>\n" "Language-Team: French <vdr@linuxtv.org>\n"
"Language: fr\n" "Language: fr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -21,19 +20,19 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "A friendly greeting" msgid "A friendly greeting"
msgstr "Bien le bonjour" msgstr ""
msgid "Hello" msgid "Hello"
msgstr "Hello" msgstr ""
msgid "Greeting time (s)" msgid "Greeting time (s)"
msgstr "Durée pour le salut (s)" msgstr ""
msgid "Use alternate greeting" msgid "Use alternate greeting"
msgstr "Changer de salutation" msgstr ""
msgid "Howdy folks!" msgid "Howdy folks!"
msgstr "Bonjour à tous !" msgstr ""
msgid "Hello world!" msgid "Hello world!"
msgstr "Bonjour le monde !" msgstr ""

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Adrian Caval <anrxc@sysphere.org>, 2008 # Adrian Caval <anrxc@sysphere.org>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2008-03-17 19:52+0100\n" "PO-Revision-Date: 2008-03-17 19:52+0100\n"

View File

@ -1,12 +1,12 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Istvan Koenigsberger <istvnko@hotmail.com>, 2002 # Istvan Koenigsberger <istvnko@hotmail.com>, 2002
# Guido Josten <guido.josten@t-online.de>, 2002 # Guido Josten <guido.josten@t-online.de>, 2002
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Diego Pierotto <vdr-italian@tiscali.it>, 2008 # Diego Pierotto <vdr-italian@tiscali.it>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2008-01-27 20:11+0100\n" "PO-Revision-Date: 2008-01-27 20:11+0100\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Valdemaras Pipiras <varas@ambernet.lt>, 2009 # Valdemaras Pipiras <varas@ambernet.lt>, 2009
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2009-12-08 12:18+0200\n" "PO-Revision-Date: 2009-12-08 12:18+0200\n"

View File

@ -1,5 +1,5 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Arnold Niessen <niessen@iae.nl> <arnold.niessen@philips.com>, 2001 # Arnold Niessen <niessen@iae.nl> <arnold.niessen@philips.com>, 2001
# Hans Dingemans <hans.dingemans@tacticalops.nl>, 2003 # Hans Dingemans <hans.dingemans@tacticalops.nl>, 2003
@ -7,7 +7,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,12 +1,12 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Jørgen Tvedt <pjtvedt@online.no>, 2001 # Jørgen Tvedt <pjtvedt@online.no>, 2001
# Truls Slevigen <truls@slevigen.no>, 2002 # Truls Slevigen <truls@slevigen.no>, 2002
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,38 +1,35 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Michael Rakowski <mrak@gmx.de>, 2002 # Michael Rakowski <mrak@gmx.de>, 2002
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2018-02-19 00:41+0100\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"
"Last-Translator: Tomasz Maciej Nowak <tmn505@gmail.com>\n" "Last-Translator: Michael Rakowski <mrak@gmx.de>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n" "Language-Team: Polish <vdr@linuxtv.org>\n"
"Language: pl_PL\n" "Language: pl\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=ISO-8859-2\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.0.6\n"
msgid "A friendly greeting" msgid "A friendly greeting"
msgstr "Przyjazne pozdrowienie" msgstr ""
msgid "Hello" msgid "Hello"
msgstr "Witaj" msgstr ""
msgid "Greeting time (s)" msgid "Greeting time (s)"
msgstr "Czas pozdrowienia (s)" msgstr ""
msgid "Use alternate greeting" msgid "Use alternate greeting"
msgstr "Użyj alternatywnego pozdrowienia" msgstr ""
msgid "Howdy folks!" msgid "Howdy folks!"
msgstr "Siema ziomy!" msgstr ""
msgid "Hello world!" msgid "Hello world!"
msgstr "Witaj świecie!" msgstr ""

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Paulo Lopes <pmml@netvita.pt>, 2001 # Paulo Lopes <pmml@netvita.pt>, 2001
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,12 +1,12 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Paul Lacatus <paul@campina.iiruc.ro>, 2002 # Paul Lacatus <paul@campina.iiruc.ro>, 2002
# Lucian Muresan <lucianm@users.sourceforge.net>, 2004 # Lucian Muresan <lucianm@users.sourceforge.net>, 2004
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Vyacheslav Dikonov <sdiconov@mail.ru>, 2004 # Vyacheslav Dikonov <sdiconov@mail.ru>, 2004
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006 # Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2009-09-30 09:48+0100\n" "PO-Revision-Date: 2009-09-30 09:48+0100\n"

View File

@ -1,12 +1,12 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Miha Setina <mihasetina@softhome.net>, 2000 # Miha Setina <mihasetina@softhome.net>, 2000
# Matjaz Thaler <matjaz.thaler@guest.arnes.si>, 2003 # Matjaz Thaler <matjaz.thaler@guest.arnes.si>, 2003
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,12 +1,12 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Tomas Prybil <tomas@prybil.se>, 2002 # Tomas Prybil <tomas@prybil.se>, 2002
# Jan Ekholm <chakie@infa.abo.fi>, 2003 # Jan Ekholm <chakie@infa.abo.fi>, 2003
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-11 12:34+0200\n" "PO-Revision-Date: 2007-08-11 12:34+0200\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Oktay Yolgeçen <oktay_73@yahoo.de>, 2007 # Oktay Yolgeçen <oktay_73@yahoo.de>, 2007
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2008-05-12 22:34:4800\n" "PO-Revision-Date: 2008-05-12 22:34:4800\n"

View File

@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Marc Rovira Vall <tm05462@salleURL.edu>, 2003 # Marc Rovira Vall <tm05462@salleURL.edu>, 2003
# Ramon Roca <ramon.roca@xcombo.com>, 2003 # Ramon Roca <ramon.roca@xcombo.com>, 2003
# Jordi Vilà <jvila@tinet.org>, 2003 # Jordi Vilà <jvila@tinet.org>, 2003
# Nan Feng VDR <nfgx@21cn.com>, 2009 # Nan Feng VDR <nfgx@21cn.com>, 2009.2
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-hello 2.6.0\n" "Project-Id-Version: vdr-hello 0.2.5\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 14:04+0100\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2009-01-23 09:48+0800\n" "PO-Revision-Date: 2009-01-23 09:48+0800\n"

View File

@ -59,35 +59,3 @@ VDR Plugin 'osddemo' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2014-02-06: Version 2.1.2
- Fixed flickering if subtitles are active while the OSD demo is running.
- Fixed a possible crash in the OSD demo (reported by Christopher Reimer).
2015-02-19: Version 2.2.0
- Official release.
2015-03-08: Version 2.3.1
- Now using cOsd::MaxPixmapSize().
- Fixed a vertical black line in the "TiledPixmaps" area on the rpihddevice OSD with
1280x800 pixel (thanks to Thomas Reufer).
- Added a demo case for storing images (thanks to Thomas Reufer).
2018-04-15: Version 2.4.0
- Official release.
2020-10-12: Version 2.4.1
- Added test cases for alignment of semi-circles (press key '4').
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.16 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
# #
@ -62,8 +61,7 @@ all: $(SOFILE)
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -77,8 +75,7 @@ $(DEPFILE): Makefile
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,13 +3,13 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: osddemo.c 4.5 2020/10/14 20:32:41 kls Exp $ * $Id: osddemo.c 2.12 2013/03/31 09:30:18 kls Exp $
*/ */
#include <vdr/osd.h> #include <vdr/osd.h>
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.1"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "Demo of arbitrary OSD setup"; static const char *DESCRIPTION = "Demo of arbitrary OSD setup";
static const char *MAINMENUENTRY = "Osd Demo"; static const char *MAINMENUENTRY = "Osd Demo";
@ -90,137 +90,6 @@ void DrawSlopes(cOsd *Osd)
Osd->Flush(); Osd->Flush();
} }
// --- DrawImages ------------------------------------------------------------
struct tOsdImageRef {
int image;
cSize size;
};
#define NUMOSDIMAGES 16
#define NUMOSDIMAGEVARIANTS 8
void DrawImages(cOsd *Osd)
{
// Create images:
cImage *images[NUMOSDIMAGEVARIANTS];
for (int i = 0; i < NUMOSDIMAGEVARIANTS; i++) {
images[i] = new cImage(cSize(
i == 0 || i == 1 ? Osd->MaxPixmapSize().Width() + 1 : rand() % Osd->Width(),
i == 0 || i == 2 ? Osd->MaxPixmapSize().Height() + 1 : rand() % Osd->Height()));
for (int x = 0; x < images[i]->Width(); x++) {
for (int y = 0; y < images[i]->Height(); y++) {
images[i]->SetPixel(cPoint(x, y),
(!x || !y || x == images[i]->Width() - 1 || y == images[i]->Height() - 1) ? clrWhite :
(x > images[i]->Width() / 2 ?
(y > images[i]->Height() / 2 ? clrBlue : clrGreen) :
(y > images[i]->Height() / 2 ? clrRed : clrYellow)));
}
}
}
// Store images:
tOsdImageRef osdImages[NUMOSDIMAGES];
for (int i = 0; i < NUMOSDIMAGES; i++) {
osdImages[i].image = cOsdProvider::StoreImage(*images[i % NUMOSDIMAGEVARIANTS]);
osdImages[i].size.Set(images[i % NUMOSDIMAGEVARIANTS]->Size());
}
// Delete images:
for (int i = 0; i < NUMOSDIMAGEVARIANTS; i++)
delete images[i];
// Draw images:
for (int i = 0; i < NUMOSDIMAGES; i++)
Osd->DrawImage(cPoint(rand() % (Osd->Width() + osdImages[i].size.Width()), rand() % (Osd->Height() + osdImages[i].size.Height())).Shifted(-osdImages[i].size.Width(), -osdImages[i].size.Height()), osdImages[i].image);
// Drop image references:
for (int i = 0; i < NUMOSDIMAGES; i++)
cOsdProvider::DropImage(osdImages[i].image);
Osd->Flush();
}
// --- DrawEllipseAlignments -------------------------------------------------
void DrawEllipseAlignments(cOsd *Osd)
{
cFont *Font = cFont::CreateFont(Setup.FontOsd, 20);
int xa = 0;
int ya = 0;
int xb = Osd->Width() - 1;
int yb = Osd->Height() - 1;
Osd->DrawRectangle(xa, ya, xb, yb, clrBlack);
int d = 50;
int a = d / 2 + 1;
int t = a * 2;
int n = 30;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(a, t, a + d - 1, t + d - 1, clrGreen);
Osd->DrawEllipse(a, t - d / 2, a + d - 1, t, clrGreen, 6);
Osd->DrawEllipse(a, t + d, a + d - 1, t + d + d / 2, clrGreen, 8);
Osd->DrawText(a + d / 3, t + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
d = 50;
a = d * 3;
n = 20;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(t, a, t + d - 1, a + d - 1, clrGreen);
Osd->DrawEllipse(t - d / 2, a, t, a + d - 1, clrGreen, 7);
Osd->DrawEllipse(t + d, a, t + d + d / 2, a + d - 1, clrGreen, 5);
Osd->DrawText(t + d / 3, a + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
d = 50;
a = d * 3;
t = d * 5;
n = 30;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(a, t, a + d - 1, t + d - 1, clrGreen);
Osd->DrawEllipse(a, t - d, a + d - 1, t, clrGreen, 2);
Osd->DrawEllipse(a, t + d, a + d - 1, t + d + d, clrGreen, 3);
Osd->DrawText(a + d / 3, t + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
d = 50;
a = d * 3;
t = d * 9;
n = 30;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(a, t, a + d - 1, t + d - 1, clrGreen);
Osd->DrawEllipse(a, t - d, a + d - 1, t, clrGreen, 1);
Osd->DrawEllipse(a, t + d, a + d - 1, t + d + d, clrGreen, 4);
Osd->DrawText(a + d / 3, t + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
d = 50;
a = d * 12;
t = d * 5;
n = 20;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(t, a, t + d - 1, a + d - 1, clrGreen);
Osd->DrawEllipse(t - d, a, t, a + d - 1, clrGreen, 2);
Osd->DrawEllipse(t + d, a, t + d + d, a + d - 1, clrGreen, 1);
Osd->DrawText(t + d / 3, a + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
d = 50;
a = d * 12;
t = d * 9;
n = 20;
for (int i = 0; i < n; i++) {
Osd->DrawRectangle(t, a, t + d - 1, a + d - 1, clrGreen);
Osd->DrawEllipse(t - d, a, t, a + d - 1, clrGreen, 3);
Osd->DrawEllipse(t + d, a, t + d + d, a + d - 1, clrGreen, 4);
Osd->DrawText(t + d / 3, a + d / 3, itoa(d), clrRed, clrGreen, Font);
a += d + 5;
d++;
}
Osd->Flush();
delete Font;
}
// --- cLineGame ------------------------------------------------------------- // --- cLineGame -------------------------------------------------------------
class cLineGame : public cOsdObject { class cLineGame : public cOsdObject {
@ -250,7 +119,7 @@ cLineGame::~cLineGame()
void cLineGame::Show(void) void cLineGame::Show(void)
{ {
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop()); osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50);
if (osd) { if (osd) {
int x1 = cOsd::OsdWidth() - 1; int x1 = cOsd::OsdWidth() - 1;
int y1 = cOsd::OsdHeight() - 1; int y1 = cOsd::OsdHeight() - 1;
@ -341,7 +210,7 @@ cPixmap *cTrueColorDemo::CreateTextPixmap(const char *s, int Line, int Layer, tC
if (Pixmap) { if (Pixmap) {
Pixmap->Clear(); Pixmap->Clear();
Pixmap->SetAlpha(0); Pixmap->SetAlpha(0);
Pixmap->DrawText(cPoint(0, 0), s, ColorFg, ColorBg, Font, w); Pixmap->DrawText(cPoint(0, 0), s, ColorFg, ColorBg, Font);
} }
return Pixmap; return Pixmap;
} }
@ -558,20 +427,16 @@ void cTrueColorDemo::Action(void)
const int Size = SmlFont->Width(Text) + 10; const int Size = SmlFont->Width(Text) + 10;
const int NumDots = 12; const int NumDots = 12;
const int AnimFrames = NumDots; const int AnimFrames = NumDots;
int Rows = min(osd->MaxPixmapSize().Height() / Size, AnimFrames);
int Cols = (AnimFrames + Rows - 1) / Rows;
// Temporarily using pixmap layer 0 to have the text alpha blended: // Temporarily using pixmap layer 0 to have the text alpha blended:
AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size * Cols, Size * Rows)); AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames));
if (AnimPixmap) { if (AnimPixmap) {
AnimPixmap->SetAlpha(0); AnimPixmap->SetAlpha(0);
AnimPixmap->Clear(); AnimPixmap->Clear();
const int Diameter = Size / 5; const int Diameter = Size / 5;
int xc = Size / 2 - Diameter / 2;
for (int Frame = 0; Frame < AnimFrames; Frame++) { for (int Frame = 0; Frame < AnimFrames; Frame++) {
int x0 = Frame / Rows * Size; AnimPixmap->DrawEllipse(cRect(0, Frame * Size, Size, Size), 0xDDFFFFFF);
int y0 = Frame % Rows * Size; int yc = Frame * Size + Size / 2 - Diameter / 2;
AnimPixmap->DrawEllipse(cRect(x0, y0, Size, Size), 0xDDFFFFFF);
int xc = x0 + Size / 2 - Diameter / 2;
int yc = y0 + Size / 2 - Diameter / 2;
int Color = 0xFF; int Color = 0xFF;
int Delta = Color / NumDots / 3; int Delta = Color / NumDots / 3;
for (int a = 0; a < NumDots; a++) { for (int a = 0; a < NumDots; a++) {
@ -581,7 +446,7 @@ void cTrueColorDemo::Action(void)
AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color)); AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color));
Color -= Delta; Color -= Delta;
} }
AnimPixmap->DrawText(cPoint(x0, y0), Text, clrBlack, clrTransparent, SmlFont, Size, Size, taCenter); AnimPixmap->DrawText(cPoint(0, Frame * Size), Text, clrBlack, clrTransparent, SmlFont, Size, Size, taCenter);
} }
AnimPixmap->SetLayer(3); // now setting the actual pixmap layer AnimPixmap->SetLayer(3); // now setting the actual pixmap layer
FadeInPixmap = AnimPixmap; FadeInPixmap = AnimPixmap;
@ -615,8 +480,6 @@ void cTrueColorDemo::Action(void)
if (Delta < FrameTime) if (Delta < FrameTime)
cCondWait::SleepMs(FrameTime - Delta); cCondWait::SleepMs(FrameTime - Delta);
} }
destroyablePixmap = NULL;
toggleablePixmap = NULL;
delete OsdFont; delete OsdFont;
delete SmlFont; delete SmlFont;
delete LrgFont; delete LrgFont;
@ -633,7 +496,7 @@ bool cTrueColorDemo::SetArea(void)
void cTrueColorDemo::Show(void) void cTrueColorDemo::Show(void)
{ {
osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop()); osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50);
if (osd) { if (osd) {
if (SetArea()) { if (SetArea()) {
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrGray50); osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrGray50);
@ -671,14 +534,6 @@ eOSState cTrueColorDemo::ProcessKey(eKeys Key)
SetArea(); SetArea();
DrawSlopes(osd); DrawSlopes(osd);
break; break;
case k3: Cancel(3);
SetArea();
DrawImages(osd);
break;
case k4: Cancel(3);
SetArea();
DrawEllipseAlignments(osd);
return osContinue;
case kBack: case kBack:
case kOk: return osEnd; case kOk: return osEnd;
default: return state; default: return state;

View File

@ -87,36 +87,3 @@ VDR Plugin 'pictures' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2013-07-01:
- Added option -x to pic2mpg.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2015-07-23: Version 2.3.1
- Added a missing 'const'.
2017-10-06: Version 2.3.2
- Adapted the pic2mpg script to new ffmpeg options.
- No longer using 'convert' to scale/rotate the pictures.
2018-04-15: Version 2.4.0
- Official release.
2021-12-27: Version 2.6.0
- Official release.
2022-12-05: Version 2.6.1
Fixed initializing cPictureControl.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.18 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir) LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
@ -63,8 +62,7 @@ all: $(SOFILE) i18n
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -84,16 +82,13 @@ I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLU
I18Npot = $(PODIR)/$(PLUGIN).pot I18Npot = $(PODIR)/$(PLUGIN).pot
%.mo: %.po %.mo: %.po
@echo MO $@ msgfmt -c -o $@ $<
$(Q)msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.c) $(I18Npot): $(wildcard *.c)
@echo GT $@ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
%.po: $(I18Npot) %.po: $(I18Npot)
@echo PO $@ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
$(Q)msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
@touch $@ @touch $@
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo $(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@ -107,8 +102,7 @@ install-i18n: $(I18Nmsgs)
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: menu.c 4.1 2015/07/17 10:13:56 kls Exp $ * $Id: menu.c 1.1 2008/01/13 11:35:18 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -85,7 +85,7 @@ eOSState cPictureMenu::SelectItem(const char *Path, bool SlideShow)
if (Item) { if (Item) {
const cList<cPictureEntry> *l = pictureEntry->Entries(); const cList<cPictureEntry> *l = pictureEntry->Entries();
if (l) { if (l) {
const cPictureEntry *pe = l->Get(Current()); cPictureEntry *pe = l->Get(Current());
if (pe) { if (pe) {
if (SlideShow) { if (SlideShow) {
cControl::Launch(new cPictureControl(pictures, pe, true)); cControl::Launch(new cPictureControl(pictures, pe, true));

View File

@ -7,7 +7,7 @@
# #
# See the README file for copyright information and how to reach the author. # See the README file for copyright information and how to reach the author.
# #
# $Id: pic2mpg 4.1 2017/10/06 14:42:18 kls Exp $ # $Id: pic2mpg 2.5 2013/02/17 13:17:13 kls Exp $
use File::Path; use File::Path;
use File::Spec; use File::Spec;
@ -23,10 +23,9 @@ Options: -f Force conversion
-o percent overscan in percent -o percent overscan in percent
-s size Screen size (WIDTHxHEIGHT, default is 1920x1080) -s size Screen size (WIDTHxHEIGHT, default is 1920x1080)
-v num Verbose (0=none, 1=list files, 2=detailed) -v num Verbose (0=none, 1=list files, 2=detailed)
-x dir[,...] eXclude the given directories
}; };
getopts("fho:s:v:x:") || die $Usage; getopts("fho:s:v:") || die $Usage;
die $Usage if $opt_h; die $Usage if $opt_h;
@ -34,7 +33,6 @@ $Force = $opt_f;
$Overscan = $opt_o || 0; $Overscan = $opt_o || 0;
$Size = $opt_s || "1920x1080"; $Size = $opt_s || "1920x1080";
$Verbose = $opt_v; $Verbose = $opt_v;
@Exclude = split(',', $opt_x || "");
$ListFiles = $Verbose >= 1; $ListFiles = $Verbose >= 1;
$Detailed = $Verbose >= 2; $Detailed = $Verbose >= 2;
@ -87,11 +85,7 @@ chdir($PICDIR) || die "$PICDIR: $!\n";
@Pictures = `find -type f | sort`; @Pictures = `find -type f | sort`;
chomp(@Pictures); chomp(@Pictures);
PIC:
for $pic (@Pictures) { for $pic (@Pictures) {
for (@Exclude) {
next PIC if ($pic =~ /\/$_\//);
}
my $mpg = "$MPGDIR/$pic.mpg"; my $mpg = "$MPGDIR/$pic.mpg";
if ($Force || !-e $mpg || -M $mpg > -M $pic) { if ($Force || !-e $mpg || -M $mpg > -M $pic) {
(my $dir = $mpg) =~ s/\/[^\/]*$//; (my $dir = $mpg) =~ s/\/[^\/]*$//;
@ -128,7 +122,7 @@ for ($i = 0; $i < 10; $i++) { # dirs might become empty when removing empty subd
for $dir (@Dirs) { for $dir (@Dirs) {
$dir = EscapeMeta($dir); $dir = EscapeMeta($dir);
print "removing $dir\n"; print "removing $dir\n";
Exec("rm -rf $dir"); !system("rm -rf $dir") || die "$dir: $!\n";
} }
} }
@ -142,18 +136,17 @@ sub ConvertFile
my $Exif = ImageInfo($Pict); my $Exif = ImageInfo($Pict);
my $Orientation = $$Exif{"Orientation"}; my $Orientation = $$Exif{"Orientation"};
my ($Degrees) = $Orientation =~ /Rotate ([0-9]+)/; my ($Degrees) = $Orientation =~ /Rotate ([0-9]+)/;
my $Rotate = ($Degrees == 90) ? "transpose=clock" : ($Degrees == 180) ? "hflip,vflip" : ($Degrees == 270) ? "transpose=cclock" : ""; my $Rotate = $Degrees ? "-rotate $Degrees" : "";
$Rotate .= ',' if ($Rotate);
my $Background = '#000000@1';
print "orientation = '$Orientation' -> rotation = $Rotate\n" if ($Detailed); print "orientation = '$Orientation' -> rotation = $Rotate\n" if ($Detailed);
$Pict = EscapeMeta($Pict); $Pict = EscapeMeta($Pict);
$Mpeg = EscapeMeta($Mpeg); $Mpeg = EscapeMeta($Mpeg);
print "$Pict -> $Mpeg $Rotate\n" if $ListFiles; print "$Pict -> $Mpeg $Rotate\n" if $ListFiles;
my $Cmd = "ffmpeg -i $Pict -vf '${Rotate}scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:$Background' -c:v libx264 -pix_fmt yuv420p -f mpegts -y $Mpeg " my $Cmd = "convert $Pict -background '#000000' $Rotate -resize $Size -gravity center -extent $Extent ppm:- | "
. "ffmpeg -f image2pipe -vcodec ppm -i pipe:0 -an -vcodec libx264 -vpre baseline -s $Size -qscale 2 -f mpegts -y $Mpeg "
. ($Detailed ? "" : "2>/dev/null"); . ($Detailed ? "" : "2>/dev/null");
Exec($Cmd); !system($Cmd) || die "$Cmd: $!\n";
$Cmd = "touch -r $Pict $Mpeg"; $Cmd = "touch -r $Pict $Mpeg";
Exec($Cmd); !system($Cmd) || die "$Cmd: $!\n";
} }
sub EscapeMeta sub EscapeMeta
@ -163,10 +156,3 @@ sub EscapeMeta
$s =~ s/([$META])/\\$1/g; $s =~ s/([$META])/\\$1/g;
return $s; return $s;
} }
sub Exec
{
my $Cmd = shift;
print "==> '$Cmd'\n" if ($Verbose);
!system($Cmd) || die "$Cmd: $!\n";
}

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: pictures.c 5.1 2022/12/05 15:26:23 kls Exp $ * $Id: pictures.c 2.9 2013/03/31 09:30:18 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -11,7 +11,7 @@
#include "menu.h" #include "menu.h"
#include "player.h" #include "player.h"
static const char *VERSION = "2.6.1"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = trNOOP("A simple picture viewer"); static const char *DESCRIPTION = trNOOP("A simple picture viewer");
static const char *MAINMENUENTRY = trNOOP("Pictures"); static const char *MAINMENUENTRY = trNOOP("Pictures");

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: player.c 5.1 2022/12/05 15:26:23 kls Exp $ * $Id: player.c 2.2 2012/04/28 11:58:15 kls Exp $
*/ */
#include "player.h" #include "player.h"
@ -96,10 +96,8 @@ int cPictureControl::active = 0;
cString cPictureControl::lastDisplayed; cString cPictureControl::lastDisplayed;
cPictureControl::cPictureControl(cPictureEntry *Pictures, const cPictureEntry *PictureEntry, bool SlideShow) cPictureControl::cPictureControl(cPictureEntry *Pictures, const cPictureEntry *PictureEntry, bool SlideShow)
:cControl(NULL) :cControl(player = new cPicturePlayer)
{ {
player = new cPicturePlayer;
SetPlayer(player);
pictures = Pictures; pictures = Pictures;
pictureEntry = PictureEntry; pictureEntry = PictureEntry;
osd = NULL; osd = NULL;
@ -213,7 +211,7 @@ cString cPictureControl::GetHeader(void)
eOSState cPictureControl::ProcessKey(eKeys Key) eOSState cPictureControl::ProcessKey(eKeys Key)
{ {
switch (int(Key)) { switch (Key) {
case kUp: case kUp:
case kPlay: slideShowDelay.Set(); case kPlay: slideShowDelay.Set();
slideShow = true; slideShow = true;

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Klaus Schmidinger <vdr@tvdr.de>, 2008 # Klaus Schmidinger <vdr@tvdr.de>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-01-12 17:41+0100\n" "PO-Revision-Date: 2008-01-12 17:41+0100\n"

View File

@ -1,33 +0,0 @@
# VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package.
# Arthur Konovalov <artlov@gmail.com>, 2015
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-01-12 17:41+0100\n"
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
"Language-Team: Estonian <vdr@linuxtv.org>\n"
"Language: et\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Pictures"
msgstr "Pildid"
msgid "A simple picture viewer"
msgstr "Lihtne pildivaatur"
msgid "Picture directory"
msgstr "Pildikaust"
msgid "Slide show delay (s)"
msgstr "Slaidiseanssi viide (s)"
msgid "No picture directory has been defined!"
msgstr "Pildikaust on määramata!"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2008 # Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-01-12 17:41+0100\n" "PO-Revision-Date: 2008-01-12 17:41+0100\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Patrice Staudt <patrice.staudt@laposte.net>, 2008 # Patrice Staudt <patrice.staudt@laposte.net>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-01-12 17:41+0100\n" "PO-Revision-Date: 2008-01-12 17:41+0100\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Diego Pierotto <vdr-italian@tiscali.it>, 2008 # Diego Pierotto <vdr-italian@tiscali.it>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-01-27 20:22+0100\n" "PO-Revision-Date: 2008-01-27 20:22+0100\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Valdemaras Pipiras <varas@ambernet.lt>, 2009 # Valdemaras Pipiras <varas@ambernet.lt>, 2009
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2009-12-08 12:41+0100\n" "PO-Revision-Date: 2009-12-08 12:41+0100\n"

View File

@ -1,34 +0,0 @@
# VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package.
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2018-02-19 00:48+0100\n"
"PO-Revision-Date: 2018-02-19 00:53+0100\n"
"Last-Translator: Tomasz Maciej Nowak <tmn505@gmail.com>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.0.6\n"
msgid "Pictures"
msgstr "Zdjęcia"
msgid "A simple picture viewer"
msgstr "Prosta przeglądarka zdjęć"
msgid "Picture directory"
msgstr "Katalog ze zdjęciami"
msgid "Slide show delay (s)"
msgstr "Pokaz slajdów opóźnienie (s)"
msgid "No picture directory has been defined!"
msgstr "Nie zdefiniowano katalogu ze zdjęciami!"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Alexander Gross <Bikalexander@gmail.com>, 2008 # Alexander Gross <Bikalexander@gmail.com>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2008-03-14 00:45+0100\n" "PO-Revision-Date: 2008-03-14 00:45+0100\n"

View File

@ -1,11 +1,11 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Klaus Schmidinger <vdr@tvdr.de>, 2008 # Klaus Schmidinger <vdr@tvdr.de>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-pictures 2.6.0\n" "Project-Id-Version: vdr-pictures 0.1.3\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2012-12-18 12:57+0100\n" "POT-Creation-Date: 2012-12-18 12:57+0100\n"
"PO-Revision-Date: 2009-09-30 12:54+0100\n" "PO-Revision-Date: 2009-09-30 12:54+0100\n"

340
PLUGINS/src/rcu/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

22
PLUGINS/src/rcu/HISTORY Normal file
View File

@ -0,0 +1,22 @@
VDR Plugin 'rcu' Revision History
---------------------------------
2012-02-27: Version 0.0.1
- Initial revision.
2012-03-07: Version 0.0.2
- Added new parameter LiveView to ChannelSwitch().
2012-12-27: Version 0.0.3
- Adapted Makefile to changes introduced in recent VDR versions.
2013-01-12: Version 0.0.4
- Adapted Makefile to changes introduced in recent VDR versions.
2013-03-31: Version 2.0.0
- Official release.

94
PLUGINS/src/rcu/Makefile Normal file
View File

@ -0,0 +1,94 @@
#
# Makefile for a Video Disk Recorder plugin
#
# $Id: Makefile 1.13 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
# By default the main source file also carries this name.
PLUGIN = rcu
### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory:
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
### The compiler options:
export CFLAGS = $(call PKGCFG,cflags)
export CXXFLAGS = $(call PKGCFG,cxxflags)
### The version number of VDR's plugin API:
APIVERSION = $(call PKGCFG,apiversion)
### Allow user defined options to overwrite defaults:
-include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here):
INCLUDES +=
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
### The object files (add further files here):
OBJS = $(PLUGIN).o
### The main target:
all: $(SOFILE)
### Implicit rules:
%.o: %.c
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies:
MAKEDEP = $(CXX) -MM -MG
DEPFILE = .dependencies
$(DEPFILE): Makefile
@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
-include $(DEPFILE)
### Targets:
$(SOFILE): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
install: install-lib
dist: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
clean:
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~

19
PLUGINS/src/rcu/README Normal file
View File

@ -0,0 +1,19 @@
This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <Klaus.Schmidinger@tvdr.de>
Project's homepage: http://www.tvdr.de/remote.htm
Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
See the file COPYING for more information.
Description:
============
The "Remote Control Unit" used to be part of the core VDR source
code, and has been moved into a separate plugin in version 1.7.25.

420
PLUGINS/src/rcu/rcu.c Normal file
View File

@ -0,0 +1,420 @@
/*
* rcu.c: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id: rcu.c 1.5 2013/03/31 09:30:18 kls Exp $
*/
#include <getopt.h>
#include <netinet/in.h>
#include <termios.h>
#include <unistd.h>
#include <vdr/plugin.h>
#include <vdr/remote.h>
#include <vdr/status.h>
#include <vdr/thread.h>
#include <vdr/tools.h>
static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "Remote Control Unit";
#define REPEATLIMIT 150 // ms
#define REPEATDELAY 350 // ms
#define HANDSHAKETIMEOUT 20 // ms
#define DEFAULTDEVICE "/dev/ttyS1"
class cRcuRemote : public cRemote, private cThread, private cStatus {
private:
enum { modeH = 'h', modeB = 'b', modeS = 's' };
int f;
unsigned char dp, code, mode;
int number;
unsigned int data;
bool receivedCommand;
bool SendCommand(unsigned char Cmd);
int ReceiveByte(int TimeoutMs = 0);
bool SendByteHandshake(unsigned char c);
bool SendByte(unsigned char c);
bool SendData(unsigned int n);
void SetCode(unsigned char Code);
void SetMode(unsigned char Mode);
void SetNumber(int n, bool Hex = false);
void SetPoints(unsigned char Dp, bool On);
void SetString(const char *s);
bool DetectCode(unsigned char *Code);
virtual void Action(void);
virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView);
virtual void Recording(const cDevice *Device, const char *Name, const char *FileName, bool On);
public:
cRcuRemote(const char *DeviceName);
virtual ~cRcuRemote();
virtual bool Ready(void);
virtual bool Initialize(void);
};
cRcuRemote::cRcuRemote(const char *DeviceName)
:cRemote("RCU")
,cThread("RCU remote control")
{
dp = 0;
mode = modeB;
code = 0;
number = 0;
data = 0;
receivedCommand = false;
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
struct termios t;
if (tcgetattr(f, &t) == 0) {
cfsetspeed(&t, B9600);
cfmakeraw(&t);
if (tcsetattr(f, TCSAFLUSH, &t) == 0) {
SetNumber(8888);
const char *Setup = GetSetup();
if (Setup) {
code = *Setup;
SetCode(code);
isyslog("connecting to %s remote control using code %c", Name(), code);
}
Start();
return;
}
}
LOG_ERROR_STR(DeviceName);
close(f);
}
else
LOG_ERROR_STR(DeviceName);
f = -1;
}
cRcuRemote::~cRcuRemote()
{
Cancel();
}
bool cRcuRemote::Ready(void)
{
return f >= 0;
}
bool cRcuRemote::Initialize(void)
{
if (f >= 0) {
unsigned char Code = '0';
isyslog("trying codes for %s remote control...", Name());
for (;;) {
if (DetectCode(&Code)) {
code = Code;
break;
}
}
isyslog("established connection to %s remote control using code %c", Name(), code);
char buffer[16];
snprintf(buffer, sizeof(buffer), "%c", code);
PutSetup(buffer);
return true;
}
return false;
}
void cRcuRemote::Action(void)
{
#pragma pack(1)
union {
struct {
unsigned short address;
unsigned int command;
} data;
unsigned char raw[6];
} buffer;
#pragma pack()
time_t LastCodeRefresh = 0;
cTimeMs FirstTime;
unsigned char LastCode = 0, LastMode = 0;
uint64_t LastCommand = ~0; // 0x00 might be a valid command
unsigned int LastData = 0;
bool repeat = false;
while (Running() && f >= 0) {
if (ReceiveByte(REPEATLIMIT) == 'X') {
for (int i = 0; i < 6; i++) {
int b = ReceiveByte();
if (b >= 0) {
buffer.raw[i] = b;
if (i == 5) {
unsigned short Address = ntohs(buffer.data.address); // the PIC sends bytes in "network order"
uint64_t Command = ntohl(buffer.data.command);
if (code == 'B' && Address == 0x0000 && Command == 0x00004000)
// Well, well, if it isn't the "d-box"...
// This remote control sends the above command before and after
// each keypress - let's just drop this:
break;
Command |= uint64_t(Address) << 32;
if (Command != LastCommand) {
LastCommand = Command;
repeat = false;
FirstTime.Set();
}
else {
if (FirstTime.Elapsed() < REPEATDELAY)
break; // repeat function kicks in after a short delay
repeat = true;
}
Put(Command, repeat);
receivedCommand = true;
}
}
else
break;
}
}
else if (repeat) { // the last one was a repeat, so let's generate a release
Put(LastCommand, false, true);
repeat = false;
LastCommand = ~0;
}
else {
unsigned int d = data;
if (d != LastData) {
SendData(d);
LastData = d;
}
unsigned char c = code;
if (c != LastCode) {
SendCommand(c);
LastCode = c;
}
unsigned char m = mode;
if (m != LastMode) {
SendCommand(m);
LastMode = m;
}
LastCommand = ~0;
}
if (!repeat && code && time(NULL) - LastCodeRefresh > 60) {
SendCommand(code); // in case the PIC listens to the wrong code
LastCodeRefresh = time(NULL);
}
}
}
int cRcuRemote::ReceiveByte(int TimeoutMs)
{
// Returns the byte if one was received within a timeout, -1 otherwise
if (cFile::FileReady(f, TimeoutMs)) {
unsigned char b;
if (safe_read(f, &b, 1) == 1)
return b;
else
LOG_ERROR;
}
return -1;
}
bool cRcuRemote::SendByteHandshake(unsigned char c)
{
if (f >= 0) {
int w = write(f, &c, 1);
if (w == 1) {
for (int reply = ReceiveByte(HANDSHAKETIMEOUT); reply >= 0;) {
if (reply == c)
return true;
else if (reply == 'X') {
// skip any incoming RC code - it will come again
for (int i = 6; i--;) {
if (ReceiveByte() < 0)
return false;
}
}
else
return false;
}
}
LOG_ERROR;
}
return false;
}
bool cRcuRemote::SendByte(unsigned char c)
{
for (int retry = 5; retry--;) {
if (SendByteHandshake(c))
return true;
}
return false;
}
bool cRcuRemote::SendData(unsigned int n)
{
for (int i = 0; i < 4; i++) {
if (!SendByte(n & 0x7F))
return false;
n >>= 8;
}
return SendCommand(mode);
}
void cRcuRemote::SetCode(unsigned char Code)
{
code = Code;
}
void cRcuRemote::SetMode(unsigned char Mode)
{
mode = Mode;
}
bool cRcuRemote::SendCommand(unsigned char Cmd)
{
return SendByte(Cmd | 0x80);
}
void cRcuRemote::SetNumber(int n, bool Hex)
{
number = n;
if (!Hex) {
char buf[8];
sprintf(buf, "%4d", n & 0xFFFF);
n = 0;
for (char *d = buf; *d; d++) {
if (*d == ' ')
*d = 0xF;
n = (n << 4) | ((*d - '0') & 0x0F);
}
}
unsigned int m = 0;
for (int i = 0; i < 4; i++) {
m <<= 8;
m |= ((i & 0x03) << 5) | (n & 0x0F) | (((dp >> i) & 0x01) << 4);
n >>= 4;
}
data = m;
}
void cRcuRemote::SetString(const char *s)
{
const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP ";
int n = 0;
for (int i = 0; *s && i < 4; s++, i++) {
n <<= 4;
for (const char *c = chars; *c; c++) {
if (*c == *s) {
n |= c - chars;
break;
}
}
}
SetNumber(n, true);
}
void cRcuRemote::SetPoints(unsigned char Dp, bool On)
{
if (On)
dp |= Dp;
else
dp &= ~Dp;
SetNumber(number);
}
bool cRcuRemote::DetectCode(unsigned char *Code)
{
// Caller should initialize 'Code' to 0 and call DetectCode()
// until it returns true. Whenever DetectCode() returns false
// and 'Code' is not 0, the caller can use 'Code' to display
// a message like "Trying code '%c'". If false is returned and
// 'Code' is 0, all possible codes have been tried and the caller
// can either stop calling DetectCode() (and give some error
// message), or start all over again.
if (*Code < 'A' || *Code > 'D') {
*Code = 'A';
return false;
}
if (*Code <= 'D') {
SetMode(modeH);
char buf[5];
sprintf(buf, "C0D%c", *Code);
SetString(buf);
SetCode(*Code);
cCondWait::SleepMs(2 * REPEATDELAY);
if (receivedCommand) {
SetMode(modeB);
SetString("----");
return true;
}
if (*Code < 'D') {
(*Code)++;
return false;
}
}
*Code = 0;
return false;
}
void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView)
{
if (ChannelNumber && LiveView)
SetNumber(cDevice::CurrentChannel());
}
void cRcuRemote::Recording(const cDevice *Device, const char *Name, const char *FileName, bool On)
{
SetPoints(1 << Device->DeviceNumber(), Device->Receiving());
}
class cPluginRcu : public cPlugin {
private:
// Add any member variables or functions you may need here.
const char *device;
public:
cPluginRcu(void);
virtual const char *Version(void) { return VERSION; }
virtual const char *Description(void) { return DESCRIPTION; }
virtual const char *CommandLineHelp(void);
virtual bool ProcessArgs(int argc, char *argv[]);
virtual bool Start(void);
};
cPluginRcu::cPluginRcu(void)
{
// Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
device = DEFAULTDEVICE;
}
const char *cPluginRcu::CommandLineHelp(void)
{
// Return a string that describes all known command line options.
return " -d DEV, --device=DEV set the device to use (default is " DEFAULTDEVICE ")\n";
}
bool cPluginRcu::ProcessArgs(int argc, char *argv[])
{
// Implement command line argument processing here if applicable.
static struct option long_options[] = {
{ "dev", required_argument, NULL, 'd' },
{ NULL, no_argument, NULL, 0 }
};
int c;
while ((c = getopt_long(argc, argv, "d:", long_options, NULL)) != -1) {
switch (c) {
case 'd': device = optarg;
break;
default: return false;
}
}
return true;
}
bool cPluginRcu::Start(void)
{
// Start any background activities the plugin shall perform.
new cRcuRemote(device);
return true;
}
VDRPLUGINCREATOR(cPluginRcu); // Don't touch this!

View File

@ -21,19 +21,3 @@ VDR Plugin 'servicedemo' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2018-04-15: Version 2.4.0
- Official release.
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.14 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -17,8 +17,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN1).c | awk '{ pr
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
# #
@ -59,8 +58,7 @@ all: libvdr-$(PLUGIN1).so libvdr-$(PLUGIN2).so
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -74,12 +72,10 @@ $(DEPFILE): Makefile
### Targets: ### Targets:
libvdr-$(PLUGIN1).so: $(PLUGIN1).o libvdr-$(PLUGIN1).so: $(PLUGIN1).o
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGIN1).o -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGIN1).o -o $@
libvdr-$(PLUGIN2).so: $(PLUGIN2).o libvdr-$(PLUGIN2).so: $(PLUGIN2).o
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGIN2).o -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGIN2).o -o $@
install-lib: libvdr-$(PLUGIN1).so libvdr-$(PLUGIN2).so install-lib: libvdr-$(PLUGIN1).so libvdr-$(PLUGIN2).so
install -D libvdr-$(PLUGIN1).so $(DESTDIR)$(LIBDIR)/libvdr-$(PLUGIN1).so.$(APIVERSION) install -D libvdr-$(PLUGIN1).so $(DESTDIR)$(LIBDIR)/libvdr-$(PLUGIN1).so.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Udo Richter <udo_richter@gmx.de> Written by: Udo Richter <udo_richter@gmx.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,14 +3,14 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: svccli.c 4.1 2018/04/10 13:00:53 kls Exp $ * $Id: svccli.c 2.4 2013/03/31 09:30:18 kls Exp $
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <vdr/interface.h> #include <vdr/interface.h>
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.0"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "Service demo client"; static const char *DESCRIPTION = "Service demo client";
static const char *MAINMENUENTRY = "Service demo"; static const char *MAINMENUENTRY = "Service demo";

View File

@ -3,14 +3,14 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: svcsvr.c 4.1 2018/04/10 13:00:57 kls Exp $ * $Id: svcsvr.c 2.4 2013/03/31 09:30:18 kls Exp $
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <vdr/interface.h> #include <vdr/interface.h>
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.0"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "Service demo server"; static const char *DESCRIPTION = "Service demo server";
class cPluginSvcSvr : public cPlugin { class cPluginSvcSvr : public cPlugin {

View File

@ -118,46 +118,3 @@ VDR Plugin 'skincurses' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-08: Version 2.1.2
- Added a missing trailing blank in some translations.
2015-02-19: Version 2.2.0
- Official release.
2016-12-22: Version 2.3.2
- Added cFont::Width(void) to get the default character width and allow stretched
font drawing in high level OSDs (dummy for skincurses).
- Fixed truncated date/time strings in the skins on multi-byte UTF-8 systems
(reported by Sergey Chernyavskiy).
2018-04-15: Version 2.4.0
- Official release.
2019-03-12: Version 2.4.1
- Changes for ncurses version 6 (thanks to Ulrick Eckhardt).
2020-05-11: Version 2.4.2
- Fixed 'Changes for ncurses version 6'.
- Reacting to changes in screen size.
- Simplified color handling.
- Using 'stdscr' directly instead of an additional window.
2021-07-01: Version 2.4.3
- The number of errors (if any) of a recording is now displayed in the recording's
Info menu.
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.18 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
LOCDIR = $(call PKGCFG,locdir) LOCDIR = $(call PKGCFG,locdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
@ -63,8 +62,7 @@ all: $(SOFILE) i18n
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -84,16 +82,13 @@ I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLU
I18Npot = $(PODIR)/$(PLUGIN).pot I18Npot = $(PODIR)/$(PLUGIN).pot
%.mo: %.po %.mo: %.po
@echo MO $@ msgfmt -c -o $@ $<
$(Q)msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.c) $(I18Npot): $(wildcard *.c)
@echo GT $@ xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
%.po: $(I18Npot) %.po: $(I18Npot)
@echo PO $@ msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
$(Q)msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
@touch $@ @touch $@
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo $(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
@ -107,8 +102,7 @@ install-i18n: $(I18Nmsgs)
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -lncursesw -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -lncursesw -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Klaus Schmidinger <vdr@tvdr.de>, 2007 # Klaus Schmidinger <vdr@tvdr.de>, 2007
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-15 16:07+0200\n" "PO-Revision-Date: 2007-08-15 16:07+0200\n"
"Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n" "Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
"Language-Team: German <vdr@linuxtv.org>\n" "Language-Team: German <vdr@linuxtv.org>\n"
@ -19,15 +19,11 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "Eine reine Text-Oberfläche" msgstr "Eine reine Text-Oberfläche"
msgid "errors"
msgstr "Fehler"
msgid "Key$Mute" msgid "Key$Mute"
msgstr "Stumm" msgstr "Stumm"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "Lautstärke " msgstr "Lautstärke"
msgid "Text mode" msgid "Text mode"
msgstr "Text-Modus" msgstr "Text-Modus"

View File

@ -1,33 +0,0 @@
# VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package.
# Arthur Konovalov <artlov@gmail.com>, 2015
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
"PO-Revision-Date: 2007-08-14 20:48+0300\n"
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
"Language-Team: Estonian <vdr@linuxtv.org>\n"
"Language: et\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "A text only skin"
msgstr "Tekstipõhine kest"
msgid "errors"
msgstr ""
msgid "Key$Mute"
msgstr "Hääletu"
#. TRANSLATORS: note the trailing blank!
msgid "Volume "
msgstr "Helitugevus "
msgid "Text mode"
msgstr "Tekst"

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2007 # Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2007
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2007-08-14 20:48+0300\n" "PO-Revision-Date: 2007-08-14 20:48+0300\n"
"Last-Translator: Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>\n" "Last-Translator: Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -19,13 +19,9 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "Tekstipohjainen ulkoasu" msgstr "Tekstipohjainen ulkoasu"
msgid "errors"
msgstr ""
msgid "Key$Mute" msgid "Key$Mute"
msgstr "Mykistys" msgstr "Mykistys"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "Äänenvoimakkuus " msgstr "Äänenvoimakkuus "

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Diego Pierotto <vdr-italian@tiscali.it>, 2008 # Diego Pierotto <vdr-italian@tiscali.it>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2008-01-27 20:35+0100\n" "PO-Revision-Date: 2008-01-27 20:35+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian <vdr@linuxtv.org>\n" "Language-Team: Italian <vdr@linuxtv.org>\n"
@ -19,13 +19,9 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "Una interfaccia solo testo" msgstr "Una interfaccia solo testo"
msgid "errors"
msgstr ""
msgid "Key$Mute" msgid "Key$Mute"
msgstr "Muto" msgstr "Muto"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "Volume " msgstr "Volume "

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Valdemaras Pipiras <varas@ambernet.lt>, 2010 # Valdemaras Pipiras <varas@ambernet.lt>, 2010
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2010-02-22 18:18+0200\n" "PO-Revision-Date: 2010-02-22 18:18+0200\n"
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n" "Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
"Language-Team: Lithuanian <vdr@linuxtv.org>\n" "Language-Team: Lithuanian <vdr@linuxtv.org>\n"
@ -19,13 +19,9 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "Tekstinis apvalkalas" msgstr "Tekstinis apvalkalas"
msgid "errors"
msgstr ""
msgid "Key$Mute" msgid "Key$Mute"
msgstr "Išjungti garsą" msgstr "Išjungti garsą"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "Garsas " msgstr "Garsas "

View File

@ -1,35 +0,0 @@
# VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package.
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
"PO-Revision-Date: 2018-02-19 01:02+0100\n"
"Last-Translator: Tomasz Maciej Nowak <tmn505@gmail.com>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 2.0.6\n"
msgid "A text only skin"
msgstr "Skóra tekstowa"
msgid "errors"
msgstr ""
msgid "Key$Mute"
msgstr "Wycisz"
#. TRANSLATORS: note the trailing blank!
msgid "Volume "
msgstr "Głośność "
msgid "Text mode"
msgstr "Tryb tekstowy"

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Alexander Gross <Bikalexander@gmail.com>, 2008 # Alexander Gross <Bikalexander@gmail.com>, 2008
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2008-03-14 00:21+0100\n" "PO-Revision-Date: 2008-03-14 00:21+0100\n"
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n" "Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
"Language-Team: Russian <vdr@linuxtv.org>\n" "Language-Team: Russian <vdr@linuxtv.org>\n"
@ -20,15 +20,11 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "¿àÞáâÞ âÕÚáâÞÒëÙ ØÝâÕàäÕÙá" msgstr "¿àÞáâÞ âÕÚáâÞÒëÙ ØÝâÕàäÕÙá"
msgid "errors"
msgstr ""
msgid "Key$Mute" msgid "Key$Mute"
msgstr "²ëÚÛ. ÓàÞÜÚÞáâì" msgstr "²ëÚÛ. ÓàÞÜÚÞáâì"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "³àÞÜÚÞáâì " msgstr "³àÞÜÚÞáâì"
msgid "Text mode" msgid "Text mode"
msgstr "ÀÕÖØÜ âÕÚáâÐ" msgstr "ÀÕÖØÜ âÕÚáâÐ"

View File

@ -1,13 +1,13 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de> # Copyright (C) 2013 Klaus Schmidinger <vdr@tvdr.de>
# This file is distributed under the same license as the VDR package. # This file is distributed under the same license as the VDR package.
# Klaus Schmidinger <vdr@tvdr.de>, 2007 # Klaus Schmidinger <vdr@tvdr.de>, 2007
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-skincurses 2.6.0\n" "Project-Id-Version: vdr-skincurses 0.1.12\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2021-07-01 17:28+0200\n" "POT-Creation-Date: 2012-12-18 14:04+0100\n"
"PO-Revision-Date: 2009-09-30 12:52+0100\n" "PO-Revision-Date: 2009-09-30 12:52+0100\n"
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n" "Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
"Language-Team: Slovak <vdr@linuxtv.org>\n" "Language-Team: Slovak <vdr@linuxtv.org>\n"
@ -19,15 +19,11 @@ msgstr ""
msgid "A text only skin" msgid "A text only skin"
msgstr "Iba text vzhµadu" msgstr "Iba text vzhµadu"
msgid "errors"
msgstr ""
msgid "Key$Mute" msgid "Key$Mute"
msgstr "Stlmi» zvuk" msgstr "Stlmi» zvuk"
#. TRANSLATORS: note the trailing blank!
msgid "Volume " msgid "Volume "
msgstr "Hlasitos» " msgstr "Hlasitos»"
msgid "Text mode" msgid "Text mode"
msgstr "Textový re¾im" msgstr "Textový re¾im"

View File

@ -3,7 +3,7 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: skincurses.c 5.1 2021/07/01 15:40:46 kls Exp $ * $Id: skincurses.c 2.13 2013/03/31 09:30:18 kls Exp $
*/ */
#include <ncurses.h> #include <ncurses.h>
@ -12,7 +12,7 @@
#include <vdr/skins.h> #include <vdr/skins.h>
#include <vdr/videodir.h> #include <vdr/videodir.h>
static const char *VERSION = "2.4.3"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = trNOOP("A text only skin"); static const char *DESCRIPTION = trNOOP("A text only skin");
static const char *MAINMENUENTRY = NULL; static const char *MAINMENUENTRY = NULL;
@ -20,7 +20,6 @@ static const char *MAINMENUENTRY = NULL;
class cCursesFont : public cFont { class cCursesFont : public cFont {
public: public:
virtual int Width(void) const { return 1; }
virtual int Width(uint c) const { return 1; } virtual int Width(uint c) const { return 1; }
virtual int Width(const char *s) const { return s ? Utf8StrLen(s) : 0; } virtual int Width(const char *s) const { return s ? Utf8StrLen(s) : 0; }
virtual int Height(void) const { return 1; } virtual int Height(void) const { return 1; }
@ -60,7 +59,9 @@ static int ScOsdHeight = 20;
class cCursesOsd : public cOsd { class cCursesOsd : public cOsd {
private: private:
WINDOW *savedRegion; WINDOW *savedRegion;
cVector<int> colorPairs; WINDOW *window;
enum { MaxColorPairs = 16 };
int colorPairs[MaxColorPairs];
void SetColor(int colorFg, int colorBg = clrBackground); void SetColor(int colorFg, int colorBg = clrBackground);
public: public:
cCursesOsd(int Left, int Top); cCursesOsd(int Left, int Top);
@ -77,34 +78,40 @@ cCursesOsd::cCursesOsd(int Left, int Top)
{ {
savedRegion = NULL; savedRegion = NULL;
memset(colorPairs, 0x00, sizeof(colorPairs));
start_color(); start_color();
leaveok(stdscr, true); leaveok(stdscr, true);
refresh(); // to react on changes to screen size
int begy, begx; window = subwin(stdscr, ScOsdHeight, ScOsdWidth, 0, 0);
int maxy, maxx; syncok(window, true);
getmaxyx(stdscr, maxy, maxx);
getbegyx(stdscr, begy, begx);
ScOsdWidth = maxx - begx;
ScOsdHeight = maxy - begy;
} }
cCursesOsd::~cCursesOsd() cCursesOsd::~cCursesOsd()
{ {
erase(); if (window) {
werase(window);
Flush(); Flush();
delwin(window);
window = NULL;
}
} }
void cCursesOsd::SetColor(int colorFg, int colorBg) void cCursesOsd::SetColor(int colorFg, int colorBg)
{ {
int color = (colorBg << 16) | colorFg | 0x80000000; int color = (colorBg << 16) | colorFg | 0x80000000;
int i = colorPairs.IndexOf(color); for (int i = 0; i < MaxColorPairs; i++) {
if (i < 0) { if (!colorPairs[i]) {
colorPairs.Append(color); colorPairs[i] = color;
i = colorPairs.Size() - 1;
init_pair(i + 1, colorFg, colorBg); init_pair(i + 1, colorFg, colorBg);
//XXX??? attron(COLOR_PAIR(WHITE_ON_BLUE));
wattrset(window, COLOR_PAIR(i + 1));
break;
}
else if (color == colorPairs[i]) {
wattrset(window, COLOR_PAIR(i + 1));
break;
}
} }
attrset(COLOR_PAIR(i + 1));
} }
void cCursesOsd::SaveRegion(int x1, int y1, int x2, int y2) void cCursesOsd::SaveRegion(int x1, int y1, int x2, int y2)
@ -114,14 +121,13 @@ void cCursesOsd::SaveRegion(int x1, int y1, int x2, int y2)
savedRegion = NULL; savedRegion = NULL;
} }
savedRegion = newwin(y2 - y1 + 1, x2 - x1 + 1, y1, x1); savedRegion = newwin(y2 - y1 + 1, x2 - x1 + 1, y1, x1);
if (savedRegion) copywin(window, savedRegion, y1, x1, 0, 0, y2 - y1, x2 - x1, false);
copywin(stdscr, savedRegion, y1, x1, 0, 0, y2 - y1, x2 - x1, false);
} }
void cCursesOsd::RestoreRegion(void) void cCursesOsd::RestoreRegion(void)
{ {
if (savedRegion) { if (savedRegion) {
overwrite(savedRegion, stdscr); copywin(savedRegion, window, 0, 0, savedRegion->_begy, savedRegion->_begx, savedRegion->_maxy - savedRegion->_begy, savedRegion->_maxx - savedRegion->_begx, false);
delwin(savedRegion); delwin(savedRegion);
savedRegion = NULL; savedRegion = NULL;
} }
@ -161,22 +167,18 @@ void cCursesOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor Co
} }
} }
SetColor(ColorFg, ColorBg); SetColor(ColorFg, ColorBg);
mvaddnstr(y, x, s, Width ? Width : ScOsdWidth - x); wmove(window, y, x); // ncurses wants 'y' before 'x'!
waddnstr(window, s, Width ? Width : ScOsdWidth - x);
} }
void cCursesOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color) void cCursesOsd::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
{ {
SetColor(Color, Color); SetColor(Color, Color);
int dx = x2 - x1; for (int y = y1; y <= y2; y++) {
int dy = y2 - y1; wmove(window, y, x1); // ncurses wants 'y' before 'x'!
if (dx >= dy) { whline(window, ' ', x2 - x1 + 1);
for (int y = y1; y <= y2; y++)
mvhline(y, x1, ' ', dx + 1);
}
else {
for (int x = x1; x <= x2; x++)
mvvline(y1, x, ' ', dy + 1);
} }
wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work
} }
void cCursesOsd::Flush(void) void cCursesOsd::Flush(void)
@ -405,7 +407,8 @@ void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event)
return; return;
int y = 2; int y = 2;
cTextScroller ts; cTextScroller ts;
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString()); char t[32];
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground); ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s", *Event->GetVpsString()); cString buffer = cString::sprintf(" VPS: %s", *Event->GetVpsString());
@ -447,18 +450,9 @@ void cSkinCursesDisplayMenu::SetRecording(const cRecording *Recording)
cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : ""); cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground); ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
y += ts.Height(); y += ts.Height();
int xt = ScOsdWidth;
if (Info->GetEvent()->ParentalRating()) { if (Info->GetEvent()->ParentalRating()) {
cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString()); cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
int w = Utf8StrLen(buffer); osd->DrawText(ScOsdWidth - Utf8StrLen(buffer), y, buffer, clrBlack, clrYellow, &Font);
osd->DrawText(xt - w, y, buffer, clrBlack, clrYellow, &Font);
xt -= w + 1;
}
if (Info->Errors() > 0) {
cString buffer = cString::sprintf(" %d %s ", Info->Errors(), tr("errors"));
int w = Utf8StrLen(buffer);
osd->DrawText(xt - w, y, buffer, clrBlack, clrYellow, &Font);
xt -= w + 1;
} }
y += 1; y += 1;
const char *Title = Info->Title(); const char *Title = Info->Title();
@ -620,7 +614,6 @@ void cSkinCursesDisplayVolume::SetVolume(int Current, int Total, bool Mute)
osd->DrawText(0, 0, tr("Key$Mute"), clrGreen, clrBackground, &Font); osd->DrawText(0, 0, tr("Key$Mute"), clrGreen, clrBackground, &Font);
} }
else { else {
// TRANSLATORS: note the trailing blank!
const char *Prompt = tr("Volume "); const char *Prompt = tr("Volume ");
int l = Utf8StrLen(Prompt); int l = Utf8StrLen(Prompt);
int p = (ScOsdWidth - l) * Current / Total; int p = (ScOsdWidth - l) * Current / Total;
@ -833,8 +826,12 @@ bool cPluginSkinCurses::ProcessArgs(int argc, char *argv[])
bool cPluginSkinCurses::Initialize(void) bool cPluginSkinCurses::Initialize(void)
{ {
// Initialize any background activities the plugin shall perform. // Initialize any background activities the plugin shall perform.
if (initscr()) WINDOW *w = initscr();
if (w) {
ScOsdWidth = w->_maxx - w->_begx + 1;
ScOsdHeight = w->_maxy - w->_begy + 1;
return true; return true;
}
return false; return false;
} }

View File

@ -60,26 +60,3 @@ VDR Plugin 'status' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2018-04-15: Version 2.4.0
- Official release.
2021-12-27: Version 2.6.0
- Official release.
2025-02-10: Version 2.6.1
- Added cStatus::OsdItem2().
- Activated logging of OsdItem2().
- Added cStatus::OsdCurrentItem2().
- Added cStatus::OsdStatusMessage2().

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.15 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
# #
@ -62,8 +61,7 @@ all: $(SOFILE)
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -77,8 +75,7 @@ $(DEPFILE): Makefile
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <vdr@tvdr.de> Written by: Klaus Schmidinger <vdr@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,13 +3,13 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: status.c 5.4 2025/02/12 21:18:53 kls Exp $ * $Id: status.c 2.4 2013/03/31 09:30:18 kls Exp $
*/ */
#include <vdr/plugin.h> #include <vdr/plugin.h>
#include <vdr/status.h> #include <vdr/status.h>
static const char *VERSION = "2.6.1"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "Status monitor test"; static const char *DESCRIPTION = "Status monitor test";
static const char *MAINMENUENTRY = NULL; static const char *MAINMENUENTRY = NULL;
@ -27,10 +27,10 @@ protected:
virtual void SetSubtitleTrack(int Index, const char * const *Tracks); virtual void SetSubtitleTrack(int Index, const char * const *Tracks);
virtual void OsdClear(void); virtual void OsdClear(void);
virtual void OsdTitle(const char *Title); virtual void OsdTitle(const char *Title);
virtual void OsdStatusMessage2(eMessageType Type, const char *Message); virtual void OsdStatusMessage(const char *Message);
virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue); virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue);
virtual void OsdItem2(const char *Text, int Index, bool Selectable); virtual void OsdItem(const char *Text, int Index);
virtual void OsdCurrentItem2(const char *Text, int Index); virtual void OsdCurrentItem(const char *Text);
virtual void OsdTextItem(const char *Text, bool Scroll); virtual void OsdTextItem(const char *Text, bool Scroll);
virtual void OsdChannel(const char *Text); virtual void OsdChannel(const char *Text);
virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle); virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle);
@ -86,9 +86,9 @@ void cStatusTest::OsdTitle(const char *Title)
dsyslog("status: cStatusTest::OsdTitle '%s'", Title); dsyslog("status: cStatusTest::OsdTitle '%s'", Title);
} }
void cStatusTest::OsdStatusMessage2(eMessageType Type, const char *Message) void cStatusTest::OsdStatusMessage(const char *Message)
{ {
dsyslog("status: cStatusTest::OsdStatusMessage2 %d '%s'", Type, Message); dsyslog("status: cStatusTest::OsdStatusMessage '%s'", Message);
} }
void cStatusTest::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue) void cStatusTest::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue)
@ -96,14 +96,14 @@ void cStatusTest::OsdHelpKeys(const char *Red, const char *Green, const char *Ye
dsyslog("status: cStatusTest::OsdHelpKeys %s - %s - %s - %s", Red, Green, Yellow, Blue); dsyslog("status: cStatusTest::OsdHelpKeys %s - %s - %s - %s", Red, Green, Yellow, Blue);
} }
void cStatusTest::OsdItem2(const char *Text, int Index, bool Selected) void cStatusTest::OsdItem(const char *Text, int Index)
{ {
dsyslog("status: cStatusTest::OsdItem2 %s %d %d", Text, Index, Selected); //dsyslog("status: cStatusTest::OsdItem %s %d", Text, Index);
} }
void cStatusTest::OsdCurrentItem2(const char *Text, int Index) void cStatusTest::OsdCurrentItem(const char *Text)
{ {
dsyslog("status: cStatusTest::OsdCurrentItem %s %d", Text, Index); dsyslog("status: cStatusTest::OsdCurrentItem %s", Text);
} }
void cStatusTest::OsdTextItem(const char *Text, bool Scroll) void cStatusTest::OsdTextItem(const char *Text, bool Scroll)

View File

@ -25,19 +25,3 @@ VDR Plugin 'svdrpdemo' Revision History
2013-03-31: Version 2.0.0 2013-03-31: Version 2.0.0
- Official release. - Official release.
2014-01-01: Version 2.1.1
- Avoiding unnecessary pkg-config warnings in plugin Makefiles.
2015-02-19: Version 2.2.0
- Official release.
2018-04-15: Version 2.4.0
- Official release.
2021-12-27: Version 2.6.0
- Official release.

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: Makefile 4.3 2020/06/22 15:08:46 kls Exp $ # $Id: Makefile 2.15 2013/01/12 13:45:01 kls Exp $
# The official name of this plugin. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin. # This name will be used in the '-P...' option of VDR to load the plugin.
@ -16,8 +16,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
### The directory environment: ### The directory environment:
# Use package data if installed...otherwise assume we're under the VDR source directory: # Use package data if installed...otherwise assume we're under the VDR source directory:
PKG_CONFIG ?= pkg-config PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
PKGCFG = $(if $(VDRDIR),$(shell $(PKG_CONFIG) --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." $(PKG_CONFIG) --variable=$(1) vdr))
LIBDIR = $(call PKGCFG,libdir) LIBDIR = $(call PKGCFG,libdir)
PLGCFG = $(call PKGCFG,plgcfg) PLGCFG = $(call PKGCFG,plgcfg)
# #
@ -62,8 +61,7 @@ all: $(SOFILE)
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
@echo CC $@ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
### Dependencies: ### Dependencies:
@ -77,8 +75,7 @@ $(DEPFILE): Makefile
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
@echo LD $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -o $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)

View File

@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Klaus Schmidinger <Klaus.Schmidinger@tvdr.de> Written by: Klaus Schmidinger <Klaus.Schmidinger@tvdr.de>
Project's homepage: https://www.tvdr.de Project's homepage: http://www.tvdr.de
Latest version available at: https://www.tvdr.de Latest version available at: http://www.tvdr.de
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by

View File

@ -3,12 +3,12 @@
* *
* See the README file for copyright information and how to reach the author. * See the README file for copyright information and how to reach the author.
* *
* $Id: svdrpdemo.c 4.1 2018/04/10 13:01:07 kls Exp $ * $Id: svdrpdemo.c 2.3 2013/03/31 09:30:18 kls Exp $
*/ */
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "2.4.0"; static const char *VERSION = "2.0.0";
static const char *DESCRIPTION = "How to add SVDRP support to a plugin"; static const char *DESCRIPTION = "How to add SVDRP support to a plugin";
class cPluginSvdrpdemo : public cPlugin { class cPluginSvdrpdemo : public cPlugin {

6
README
View File

@ -4,7 +4,7 @@ Video Disk Recorder ('VDR')
These files contain the source code of the "Video Disk Recorder", These files contain the source code of the "Video Disk Recorder",
which is based on the DVB driver of the LinuxTV project (http://linuxtv.org). which is based on the DVB driver of the LinuxTV project (http://linuxtv.org).
For details about the "Video Disk Recorder" project please For details about the "Video Disk Recorder" project please
refer to https://www.tvdr.de. refer to http://www.tvdr.de.
Please see the INSTALL file for details on how to install Please see the INSTALL file for details on how to install
this program on your computer. this program on your computer.
@ -32,10 +32,6 @@ of commercial set-top boxes usually are a lot more fancy than
the ones in this system, but here we have the full source code the ones in this system, but here we have the full source code
and can modify the menus in whatever way desired. and can modify the menus in whatever way desired.
If you actually use VDR, please add yourself to the "VDR User Counter"
at https://www.tvdr.de/counter.htm. You can also like VDR on facebook
at https://www.facebook.com/VideoDiskRecorder.
"VDR Video Disk Recorder" is a registered trademark of Klaus Schmidinger. "VDR Video Disk Recorder" is a registered trademark of Klaus Schmidinger.
"TVDR TV Done Right" is a registered trademark of Klaus Schmidinger. "TVDR TV Done Right" is a registered trademark of Klaus Schmidinger.

Some files were not shown because too many files have changed in this diff Show More