mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 1.1.0
- Begin of the 1.1 development branch. THIS IS NOT A STABLE VERSION! The current stable version for every day use is still the 1.0 branch. - First step towards a universal plugin interface. See the file PLUGINS.html for a detailed description. The man page vdr(1) describes the new options '-L' and '-P' used to load plugins. This first step implements the complete "outer" shell for plugins. The "inner" access to VDR data structures will follow. - The VDR version number is now displayed in the title line of the "Setup" menu.
This commit is contained in:
parent
c9a5d8ea53
commit
ae8a947367
55
CONTRIBUTORS
55
CONTRIBUTORS
@ -1,4 +1,7 @@
|
||||
Thanks go to the following people for patches and contributions:
|
||||
Tons of suggestions, bugreports, patches and other contributions have been
|
||||
provided by the people on the 'linux-dvb' and 'vdr' mailing lists.
|
||||
Special thanks go to the following individuals (if your name is missing here,
|
||||
please send an email to kls@cadsoft.de):
|
||||
|
||||
Carsten Koch <Carsten.Koch@icem.de>
|
||||
for adding LIRC support
|
||||
@ -9,6 +12,7 @@ Carsten Koch <Carsten.Koch@icem.de>
|
||||
for implementing the 'new recording' indicator
|
||||
for suggesting that the "Back" button in replay mode should bring up the "Recordings" menu
|
||||
for fixing the watchdog timer if the program hangs in OSD activities
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||
|
||||
Plamen Ganev <pganev@com-it.net>
|
||||
for fixing the frequency offset for Hotbird channels
|
||||
@ -28,7 +32,7 @@ Guido Fiala <gfiala@s.netic.de>
|
||||
now does these things itself)
|
||||
for making the replay progress display avoid unnecessary code execution
|
||||
|
||||
Robert Schneider <Robert.Schneider@lotus.com>
|
||||
Robert Schneider <Robert.Schneider@de.ibm.com>
|
||||
for implementing EIT support for displaying the current/next info
|
||||
for extending EIT support to implement a complete EPG
|
||||
|
||||
@ -117,6 +121,13 @@ Stefan Huelswitt <huels@iname.com>
|
||||
for implementing backtracing for fast forward/rewind
|
||||
for implementing the replay mode display
|
||||
for fixing a crash when replaying with DEBUG_OSD=1
|
||||
for fixing a crash when selecting the "Jump" function directly after setting
|
||||
an editing mark
|
||||
for reporting a possible endless loop in shifting recordings between DVB cards
|
||||
for making it no longer setting PIDs 0x1FFF, which apparently fixes problems
|
||||
with CAMs and AC3 sound only working the first time
|
||||
for making the main loop take an active video cutting process into account when
|
||||
doing shutdown or housekeeping
|
||||
|
||||
Ulrich Röder <roeder@efr-net.de>
|
||||
for pointing out that there are channels that have a symbol rate higher than
|
||||
@ -157,6 +168,8 @@ Werner Fink <werner@suse.de>
|
||||
for helping to debug leftover 'zombie' processes when closing a pipe
|
||||
for making the Dolby Digital thread start only if the recording actually
|
||||
contains Dolby Digital data
|
||||
for improving thread locking in the ring buffer to avoid possible race conditions
|
||||
under heavy load
|
||||
|
||||
Rolf Hakenes <hakenes@hippomi.de>
|
||||
for providing 'libdtv' and adapting the EIT mechanisms to it
|
||||
@ -185,7 +198,7 @@ Thomas Heiligenmann <thomas@heiligenmann.de>
|
||||
Norbert Schmidt <nschmidt-nrw@t-online.de>
|
||||
for filling in some missing teletext PIDs
|
||||
|
||||
Thilo Wunderlich <tw@ubcom.net>
|
||||
Thilo Wunderlich <wunderlich@speedway.org>
|
||||
for his help in keeping 'channels.conf' up to date
|
||||
for reporting a problem with accessing the epg.data file before it is fully written
|
||||
|
||||
@ -202,6 +215,8 @@ Sergei Haller <Sergei.Haller@math.uni-giessen.de>
|
||||
for adding the TPID to Hessen-3 in 'channels.conf'
|
||||
for suggesting that the EPG scan should skip channels with their 'Ca' parameter
|
||||
explicitly set to an other DVB card
|
||||
for implementing enhanced string editing with upper-/lowercase, insert/overwrite
|
||||
and delete
|
||||
|
||||
Andreas Gebel <andreas@xcapenet.de>
|
||||
for his help in keeping 'channels.conf' up to date
|
||||
@ -280,3 +295,37 @@ Dirk Wiebel <dirk@wiebel.de>
|
||||
Gerald Raaf <graaf@attglobal.net>
|
||||
for helping to fix the still picture workaround in case the progress display
|
||||
is active
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||
|
||||
Andreas Roedl <flood@flood-net.de>
|
||||
for adding some DVB-T channels for Berlin (Germany) to channels.conf.terr
|
||||
|
||||
Jean Martin <mac_j_fr@hotmail.com>
|
||||
for pointing out a problem with OSD color palette handling on "big endian" systems
|
||||
|
||||
Steffen Koch <Steffen.Koch@koch-enterprises.de>
|
||||
for reporting a crash when selecting the "Jump" function directly after setting
|
||||
an editing mark
|
||||
|
||||
Matthias Hilbig <hilbig@upb.de>
|
||||
for fixing some missing ',' in i18n.c
|
||||
|
||||
Simon Dean <linux-dvb@sickhack.com>
|
||||
for reporting a problem with '.' at the end of a directory name in case of VFAT=1
|
||||
(Windows can't handle these)
|
||||
|
||||
Dimitrios Dimitrakos <mail@dimitrios.de>
|
||||
for translating OSD texts to the Greek language
|
||||
|
||||
Marcus Kuba <marcus@kuba4u.de>
|
||||
for reporting a bug in the unit of the "SVDRP timeout" setup parameter
|
||||
|
||||
Ulrich Petri <ulope@gmx.de>
|
||||
for his help in debugging a crash on systems with disks that have a block size
|
||||
larger than 1MB
|
||||
|
||||
Oliver Lorei <oliverlorei@cityweb.de>
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf.cable'
|
||||
|
||||
Andreas Böttger <fboettger@t-online.de>
|
||||
for reporting a bug in skipping forward in time shift mode near the end of the recording
|
||||
|
66
HISTORY
66
HISTORY
@ -1,7 +1,9 @@
|
||||
Video Disk Recorder Revision History
|
||||
------------------------------------
|
||||
|
||||
2000-02-19: Version 0.01 (Initial revision).
|
||||
2000-02-19: Version 0.01
|
||||
|
||||
- Initial revision.
|
||||
|
||||
2000-03-11: Version 0.02
|
||||
|
||||
@ -1190,3 +1192,65 @@ Video Disk Recorder Revision History
|
||||
- Fixed a bug in the editing process in case a previously edited file with the
|
||||
same name was manually deleted on a system with more than one video directory
|
||||
(thanks to Dirk Wiebel for reporting this one).
|
||||
|
||||
2002-04-21: Version 1.0.1
|
||||
|
||||
- Added some DVB-T channels for Berlin (Germany) to channels.conf.terr (thanks to
|
||||
Andreas Roedl).
|
||||
- Implemented enhanced string editing with upper-/lowercase, insert/overwrite
|
||||
and delete (thanks to Sergei Haller).
|
||||
- Fixed color palette handling on "big endian" systems (thanks to Jean Martin
|
||||
for pointing out this one).
|
||||
- Updated the "Blue Movie" channels to the new "Premiere Erotik" (thanks to
|
||||
Thilo Wunderlich). NOTE: this adds a new channel to 'channels.conf', so that
|
||||
any timers referencing a channel with a number higher than 102 should be
|
||||
checked and adapted if necessary (this only applies if you are using the default
|
||||
'channels.conf').
|
||||
- Improved thread locking in the ring buffer to avoid possible race conditions
|
||||
under heavy load (thanks to Werner Fink).
|
||||
- Fixed a crash when selecting the "Jump" function directly after setting an
|
||||
editing mark (thanks to Steffen Koch for reporting and Stefan Huelswitt for
|
||||
fixing this one).
|
||||
- Fixed some missing ',' in i18n.c (thanks to Matthias Hilbig).
|
||||
- Fixed a possible endless loop in shifting recordings between DVB cards (thanks
|
||||
to Stefan Huelswitt for reporting this one).
|
||||
- Updated the Premiere World Formula 1 channels in 'channels.conf' (thanks to Mel
|
||||
Schächner).
|
||||
- No longer setting PIDs 0x1FFF, which apparently fixes problems with CAMs and
|
||||
AC3 sound only working the first time (thanks to Stefan Huelswitt).
|
||||
- Now encoding '.' at the end of a directory name in case of VFAT=1, since Windows
|
||||
can't handle these (thanks to Simon Dean for reporting this one).
|
||||
|
||||
2002-05-05: Version 1.0.2
|
||||
|
||||
- Now taking an active video cutting process into account when doing shutdown or
|
||||
housekeeping (thanks to Stefan Huelswitt).
|
||||
- The default duration of an instant recording has been increased to 3 hours and
|
||||
is now configurable in the "Setup/Recording" menu.
|
||||
- Added Greek language texts (thanks to Dimitrios Dimitrakos).
|
||||
- Fixed the unit of the "SVDRP timeout" setup parameter (thanks to Marcus Kuba
|
||||
for reporting this one).
|
||||
- Fixed a crash on systems with disks that have a block size larger than 1MB
|
||||
(thanks to Ulrich Petri for helping to debug this one).
|
||||
- Updated 'channels.conf' for the new PW settings (thanks to Andreas Share,
|
||||
Carsten Koch, Gerald Raaf and Mel Schächner). Note that all channels with numbers
|
||||
over 50 may have moved, so you should carefully check any timers you have set!
|
||||
- Updated 'channels.conf.cable' for the new PW settings (thanks to Oliver Lorei
|
||||
Stephan Schreiber and Uwe Scheffler). Note that all channels may have moved, so
|
||||
you should carefully check any timers you have set!
|
||||
For future updates of this file somebody with digital cable should take the role
|
||||
of the "maintainer" and send me updated versions based on the file that comes
|
||||
with the most recent version of VDR. I will then simply replace the entire file
|
||||
'channels.conf.cable' whenever a new version is sent to me.
|
||||
- Fixed skipping forward in time shift mode near the end of the recording (thanks
|
||||
to Andreas Böttger for reporting this one).
|
||||
|
||||
2002-05-09: Version 1.1.0
|
||||
|
||||
- Begin of the 1.1 development branch. THIS IS NOT A STABLE VERSION!
|
||||
The current stable version for every day use is still the 1.0 branch.
|
||||
- First step towards a universal plugin interface. See the file PLUGINS.html
|
||||
for a detailed description. The man page vdr(1) describes the new options '-L'
|
||||
and '-P' used to load plugins. This first step implements the complete "outer"
|
||||
shell for plugins. The "inner" access to VDR data structures will follow.
|
||||
- The VDR version number is now displayed in the title line of the "Setup" menu.
|
||||
|
21
MANUAL
21
MANUAL
@ -17,9 +17,9 @@ Video Disk Recorder User's Manual
|
||||
Ok Ch display Select Switch Edit Accept Play Progress disp.
|
||||
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
|
||||
Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu
|
||||
Red - Record Edit Edit - Play Jump
|
||||
Green - Language New New - Rewind Skip -60s
|
||||
Yellow - - Delete Delete - Delete Skip +60s
|
||||
Red - Record Edit Edit ABC/abc Play Jump
|
||||
Green - Language New New Ins/Ovr Rewind Skip -60s
|
||||
Yellow - - Delete Delete Delete Delete Skip +60s
|
||||
Blue - Stop/Resume Mark On/Off(1) - Summary Stop
|
||||
0..9 Ch select - - - Numeric inp. - Editing
|
||||
|
||||
@ -58,11 +58,10 @@ Video Disk Recorder User's Manual
|
||||
by pressing the "Right" button (which puts brackets around the current
|
||||
character as in "[R]TL"), selecting the desired character position with
|
||||
"Left" and "Right", and changing the character with the "Up" and "Down"
|
||||
keys. "Ok" then confirms the changes. The special character '^' can be used
|
||||
to "cut off" a string at this position. When this character is visible in the
|
||||
brackets (as in abc[^]), the next press to the "Left" or "Ok" button will
|
||||
actually cut off the string. Using "Up" and/or "Down" brings back the
|
||||
original rest of the string (unless you have pressed "Left" or "Ok").
|
||||
keys. "Ok" then confirms the changes. The "Red" key toggles between
|
||||
upper- and lowercase characters, while the "Green" key switches between
|
||||
insert and overwrite mode. The "Yellow" key deletes the current character
|
||||
(or the one to the right of the cursor in insert mode).
|
||||
|
||||
The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
|
||||
in various menus and are listed at the bottom of the on-screen-display.
|
||||
@ -519,6 +518,12 @@ Video Disk Recorder User's Manual
|
||||
If this parameter is empty, the channel name will be used
|
||||
by default.
|
||||
|
||||
Instant rec. time = 180
|
||||
Defines the duration of an instant recording in minutes.
|
||||
Default is 180 minutes (3 hours). The stop time of an
|
||||
instant recording can be modified at any time by editing
|
||||
the respective timer in the "Timers" menu.
|
||||
|
||||
Record Dolby Digital = yes
|
||||
Turns recording of the Dolby Digital audio channels on
|
||||
or off. This may be useful if you don't have the equipment
|
||||
|
28
Makefile
28
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.33 2002/04/01 12:50:48 kls Exp $
|
||||
# $Id: Makefile 1.34 2002/05/09 09:35:05 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -13,15 +13,17 @@ DTVDIR = ./libdtv
|
||||
MANDIR = /usr/local/man
|
||||
BINDIR = /usr/local/bin
|
||||
|
||||
PLUGINDIR= ./PLUGINS
|
||||
|
||||
VIDEODIR = /video
|
||||
|
||||
INCLUDES = -I$(DVBDIR)/ost/include
|
||||
|
||||
DTVLIB = $(DTVDIR)/libdtv.a
|
||||
|
||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o osd.o\
|
||||
recording.o remote.o remux.o ringbuffer.o svdrp.o thread.o tools.o vdr.o\
|
||||
videodir.o
|
||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o\
|
||||
menuitems.o osd.o plugin.o recording.o remote.o remux.o ringbuffer.o\
|
||||
svdrp.o thread.o tools.o vdr.o videodir.o
|
||||
|
||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
||||
@ -69,7 +71,7 @@ include $(DEPFILE)
|
||||
# The main program:
|
||||
|
||||
vdr: $(OBJS) $(DTVLIB)
|
||||
g++ -g -O2 $(OBJS) $(NCURSESLIB) -ljpeg -lpthread $(LIBDIRS) $(DTVLIB) -o vdr
|
||||
g++ -g -O2 -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr
|
||||
|
||||
# The font files:
|
||||
|
||||
@ -88,6 +90,21 @@ genfontfile: genfontfile.c
|
||||
$(DTVLIB) $(DTVDIR)/libdtv.h:
|
||||
make -C $(DTVDIR) all
|
||||
|
||||
# The 'include' directory (for plugins):
|
||||
|
||||
include-dir:
|
||||
@mkdir -p include/vdr
|
||||
@(cd include/vdr; for i in ../../*.h; do ln -fs $$i .; done)
|
||||
|
||||
# Plugins:
|
||||
|
||||
plugins: include-dir
|
||||
@for i in `ls $(PLUGINDIR)/SRC | grep -v '[^a-z0-9]'`; do make -C "$(PLUGINDIR)/SRC/$$i" all; done
|
||||
|
||||
plugins-clean:
|
||||
@for i in `ls $(PLUGINDIR)/SRC | grep -v '[^a-z0-9]'`; do make -C "$(PLUGINDIR)/SRC/$$i" clean; done
|
||||
@-rm -f $(PLUGINDIR)/lib/*
|
||||
|
||||
# Install the files:
|
||||
|
||||
install:
|
||||
@ -104,6 +121,7 @@ install:
|
||||
clean:
|
||||
make -C $(DTVDIR) clean
|
||||
-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~
|
||||
-rm -rf include
|
||||
fontclean:
|
||||
-rm -f fontfix.c fontosd.c
|
||||
CLEAN: clean fontclean
|
||||
|
620
PLUGINS.html
Normal file
620
PLUGINS.html
Normal file
@ -0,0 +1,620 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>The VDR Plugin System</title>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
<h1>The VDR Plugin System</h1>
|
||||
|
||||
VDR provides an easy to use plugin interface that allows additional functionality
|
||||
to be added to the program by implementing a dynamically loadable library file.
|
||||
This interface allows programmers to develop additional functionality for VDR completely
|
||||
separate from the core VDR source, without the need of patching the original
|
||||
VDR code (and all the problems of correlating various patches).
|
||||
<p>
|
||||
This document describes the "outside" interface of the plugin system.
|
||||
It handles everything necessary for a plugin to get hooked into the core
|
||||
VDR program and present itself to the user.
|
||||
|
||||
<!--<p>TODO: Link to the document about VDR base classes to use when implementing actual functionality (yet to be written).-->
|
||||
|
||||
<hr><h2>Quick start</h2>
|
||||
|
||||
<center><i><b>Can't wait, can't wait!</b></i></center><p>
|
||||
|
||||
Actually you should read this entire document before starting to work with VDR plugins,
|
||||
but you probably want to see something happening right away <tt>;-)</tt>
|
||||
<p>
|
||||
So, for a quick demonstration of the plugin system, there is a demo plugin called
|
||||
"hello" that comes with the VDR source. To test drive this one, do the following:
|
||||
<ul>
|
||||
<li>change into the VDR source directory
|
||||
<li><b><tt>make</tt></b> the VDR program with your usual <tt>REMOTE=...</tt> (and maybe other) options
|
||||
<li>do <b><tt>make plugins</tt></b> to build the demo plugin
|
||||
<li>run VDR with <b><tt>vdr -V</tt></b> to see the version information
|
||||
<li>run VDR with <b><tt>vdr -h</tt></b> to see the command line options
|
||||
<li>run VDR with <b><tt>vdr -Phello</tt></b>
|
||||
<li>open VDR's main menu and select the <i>Hello</i> item
|
||||
<li>open the <i>Setup</i> menu from VDR's main menu and select <i>Plugins</i>
|
||||
</ul>
|
||||
If you enjoyed this brief glimpse into VDR plugin handling, read through the rest of
|
||||
this document and eventually write your own VDR plugin.
|
||||
|
||||
<hr><h2>The name of the plugin</h2>
|
||||
|
||||
<center><i><b>Give me some I.D.!</b></i></center><p>
|
||||
|
||||
One of the first things to consider when writing a VDR plugin is giving the thing
|
||||
a proper name. This name will be used in the VDR command line in order to load
|
||||
the plugin, and will also be the name of the plugin's source directory, as well
|
||||
as part of the final library name.
|
||||
<p>
|
||||
The plugin's name should typically be as short as possible. Three letter
|
||||
abbreviations like <b><tt>dvd</tt></b> (for a DVD player) or <b><tt>mp3</tt></b>
|
||||
(for an MP3 player) would be good choices. It is also recommended that the name
|
||||
consists of only lowercase letters and digits.
|
||||
No other characters should be used here.
|
||||
<p>
|
||||
A plugin can access its name through the (non virtual) member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
const char *Name(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The actual name is derived from the plugin's library file name, as defined in the
|
||||
next chapter.
|
||||
|
||||
<a name="The plugin directory structure"><hr><h2>The plugin directory structure</h2>
|
||||
|
||||
<center><i><b>Where is everybody?</b></i></center><p>
|
||||
|
||||
By default plugins are located in a directory named <tt>PLUGINS</tt> below the
|
||||
VDR source directory. Inside this directory the following subdirectory structure
|
||||
is used:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
VDR/PLUGINS/SRC
|
||||
VDR/PLUGINS/SRC/demo
|
||||
VDR/PLUGINS/SRC/hello
|
||||
VDR/PLUGINS/lib
|
||||
VDR/PLUGINS/lib/libvdr-demo.so.1.1.0
|
||||
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
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>demo</tt> and
|
||||
<tt>hello</tt>, respectively). What's inside the individual source directory of a
|
||||
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> and
|
||||
<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).
|
||||
<p>
|
||||
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
|
||||
<p>
|
||||
<table border=2>
|
||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>demo</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><font size=-1>VDR plugin<br>library prefix</font></td><td align=center><font size=-1>name of<br>the plugin</font></td><td align=center><font size=-1>shared object<br>indicator</font></td><td align=center><font size=-1>VDR version number<br>this plugin was<br>compiled for</font></td></tr>
|
||||
</table>
|
||||
<p>
|
||||
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
|
||||
<b><tt>-L</tt></b> option.
|
||||
<p>
|
||||
The VDR <tt>Makefile</tt> contains the target <tt>plugins</tt>, which calls
|
||||
<tt>make all</tt> in every directory found under <tt>VDR/PLUGINS/SRC</tt>,
|
||||
plus the target <tt>plugins-clean</tt>, which calls <tt>make clean</tt> in
|
||||
each of these directories.
|
||||
<p>
|
||||
If you download a plugin <a href="#Building the distribution package">package</a>
|
||||
from the web, it will typically have a name like
|
||||
<p>
|
||||
<tt>vdr-demo-0.0.1.tgz</tt>
|
||||
<p>
|
||||
and will unpack into a directory named
|
||||
<p>
|
||||
<tt>vdr-demo-0.0.1</tt>
|
||||
<p>
|
||||
To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>Makefile</tt>
|
||||
you need to unpack such an archive into the <tt>VDR/PLUGINS/SRC</tt> directory and
|
||||
create a symbolic link with the basic plugin name, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
ln -s vdr-demo-0.0.1 demo
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Since the VDR <tt>Makefile</tt> only searches for directories with names consisting
|
||||
of only lowercase characters and digits, it will only follow the symbolic links, which
|
||||
should lead to the current version of the plugin you want to use. This way you can
|
||||
have several different versions of a plugin source (like <tt>vdr-demo-0.0.1</tt> and
|
||||
<tt>vdr-demo-0.0.2</tt>) and define which one to actually use through the symbolic link.
|
||||
|
||||
<a name="Initializing a new plugin directory"><hr><h2>Initializing a new plugin directory</h2>
|
||||
|
||||
<center><i><b>A room with a view</b></i></center><p>
|
||||
|
||||
Call the Perl script <tt>newplugin</tt> from the VDR source directory to create
|
||||
a new plugin directory with a <tt>Makefile</tt> and a main source file implementing
|
||||
the basic derived plugin class.
|
||||
You will also find a <tt>README</tt> file there with some inital text, where you
|
||||
should fill in actual information about your project.
|
||||
A <tt>HISTORY</tt> file is set up with an "Initial revision" entry. As your project
|
||||
evolves, you should add the changes here with date and version number.
|
||||
<p>
|
||||
<tt>newplugin</tt> also creates a copy of the GPL license file <tt>COPYING</tt>,
|
||||
assuming that you will release your work under that license. Change this if you
|
||||
have other plans.
|
||||
<p>
|
||||
Add further files and maybe subdirectories to your plugin source directory as
|
||||
necessary. Don't forget to adapt the <tt>Makefile</tt> appropriately.
|
||||
|
||||
<hr><h2>The actual implementation</h2>
|
||||
|
||||
<center><i><b>Use the source, Luke!</b></i></center><p>
|
||||
|
||||
A newly initialized plugin doesn't really do very much yet.
|
||||
If you <a href="#Loading plugins into VDR">load it into VDR</a> you will find a new
|
||||
entry in the main menu, with the same name as your plugin (where the first character
|
||||
has been converted to uppercase). There will also be a new entry named "Plugins" in
|
||||
the "Setup" menu, which will bring up a list of all loaded plugins, through which you
|
||||
can access each plugin's own setup parameters (if it provides any).
|
||||
<p>
|
||||
To implement actual functionality into your plugin you need to edit the source file
|
||||
that was generated as <tt>PLUGINS/SRC/name.c</tt>. Read the comments in that file
|
||||
to see where you can bring in your own code. The following sections of this document
|
||||
will walk you through the individual member functions of the plugin class.
|
||||
<p>
|
||||
Depending on what your plugin shall do, you may or may not need all of the given
|
||||
member functions. Except for the <tt>MainMenuEntry()</tt> function they all by default
|
||||
return values that will result in no actual functionality. You can either completely
|
||||
delete unused functions from your source file, or just leave them as they are.
|
||||
If your plugin shall not be accessible through VDR's main menu, simply remove
|
||||
(or comment out) the line implementing the <tt>MainMenuEntry()</tt> function.
|
||||
<p>
|
||||
At the end of the plugin's source file you will find a line that looks like this:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
VDRPLUGINCREATOR(cPluginDemo);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
This is the "magic" hook that allows VDR to actually load the plugin into
|
||||
its memory. You don't need to worry about the details behind all this.
|
||||
<p>
|
||||
If your plugin requires additional source files, simply add them to your plugin's
|
||||
source directory and adjust the <tt>Makefile</tt> accordingly.
|
||||
|
||||
<hr><h2>Construction and Destruction</h2>
|
||||
|
||||
<center><i><b>What goes up, must come down...</b></i></center><p>
|
||||
|
||||
The constructor and destructor of a plugin are defined as
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
cPlugin(void);
|
||||
virtual ~cPlugin();
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The <b>constructor</b> shall initialize any member variables the plugin defines, but
|
||||
<b>must not access any global structures of VDR</b>.
|
||||
It also must not create any threads or other large data structures. These things
|
||||
are done in the <a href="#Getting started"><tt>Start()</tt></a> function later.
|
||||
Constructing a plugin object shall not have any side effects or produce any output,
|
||||
since VDR, for instance, has to create the plugin objects in order to get their
|
||||
command line help - and after that immediately destroys them again.
|
||||
<p>
|
||||
The <b>destructor</b> has to clean up any data created by the plugin, and has to
|
||||
take care that any threads the plugin may have created will be stopped.
|
||||
<p>
|
||||
Of course, if your plugin doesn't define any member variables that need to be
|
||||
initialized (and deleted), you don't need to implement either of these functions.
|
||||
|
||||
<hr><h2>Version number</h2>
|
||||
|
||||
<center><i><b>Which incarnation is this?</b></i></center><p>
|
||||
|
||||
Every plugin must have a version number of its own, which does not necessarily
|
||||
have to be in any way related to the VDR version number.
|
||||
VDR requests a plugin's version number through a call to the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual const char *Version(void) = 0;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Since this is a "pure" virtual function, any derived plugin class <b>must</b>
|
||||
implement it. The returned string should identify this version of the plugin.
|
||||
Typically this would be something like "0.0.1", but it may also contain other
|
||||
information, like for instance "0.0.1pre2" or the like. The string should only
|
||||
be as long as really necessary, and shall not contain the plugin's name itself.
|
||||
Here's an example:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
static const char *VERSION = "0.0.1";
|
||||
|
||||
...
|
||||
|
||||
const char *cPluginDemo::Version(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Note that the definition of the version number is expected to be located in the
|
||||
main source file, and must be written as
|
||||
<pre>
|
||||
static const char *VERSION = ...
|
||||
</pre>
|
||||
just like shown in the above example. This is a convention that allows the <tt>Makefile</tt>
|
||||
to extract the version number when generating the file name for the distribution archive.
|
||||
<p>
|
||||
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. 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>Description</h2>
|
||||
|
||||
<center><i><b>What is it that you do?</b></i></center><p>
|
||||
|
||||
In order to tell the user what exactly a plugin does, it must implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual const char *Description(void) = 0;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which returns a short, one line description of the plugin's purpose.
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual const char *Description(void)
|
||||
{
|
||||
return "A simple demo plugin";
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<hr><h2>Command line arguments</h2>
|
||||
|
||||
<center><i><b>Taking orders</b></i></center><p>
|
||||
|
||||
A VDR plugin can have command line arguments just like any normal program.
|
||||
If a plugin wants to react on command line arguments, it needs to implement
|
||||
the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual bool ProcessArgs(int argc, char *argv[]);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The parameters <tt>argc</tt> and <tt>argv</tt> have exactly the same meaning
|
||||
as in a normal C program's <tt>main()</tt> function.
|
||||
<tt>argv[0]</tt> contains the name of the plugin (as given in the <b><tt>-P</tt></b>
|
||||
option of the <tt>vdr</tt> call).
|
||||
<p>
|
||||
Each plugin has its own set of command line options, which are totally independent
|
||||
from those of any other plugin or VDR itself.
|
||||
<p>
|
||||
You can use the <tt>getopt()</tt> or <tt>getopt_long()</tt> function to process
|
||||
these arguments. As with any normal C program, the strings pointed to by <tt>argv</tt>
|
||||
will survive the entire lifetime of the plugin, so it is safe to store pointers to
|
||||
these values inside the plugin. Here's an example:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
bool cPluginDemo::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
{ "aaa", required_argument, NULL, 'a' },
|
||||
{ "bbb", no_argument, NULL, 'b' },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': fprintf(stderr, "option -a = %s\n", optarg);
|
||||
break;
|
||||
case 'b': fprintf(stderr, "option -b\n");
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The return value must be <i>true</i> if all options have been processed
|
||||
correctly, or <i>false</i> in case of an error. The first plugin that returns
|
||||
<i>false</i> from a call to its <tt>ProcessArgs()</tt> function will cause VDR
|
||||
to exit.
|
||||
|
||||
<hr><h2>Command line help</h2>
|
||||
|
||||
<center><i><b>Tell me about it...</b></i></center><p>
|
||||
|
||||
If a plugin accepts command line options, it should implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual const char *CommandLineHelp(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which will be called if the user enters the <b><tt>-h</tt></b> option when starting VDR.
|
||||
The returned string should contain the command line help for this plugin, formatted
|
||||
in the same way as done by VDR itself:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
const char *cPluginDemo::CommandLineHelp(void)
|
||||
{
|
||||
return " -a ABC, --aaa=ABC do something nice with ABC\n"
|
||||
" -b, --bbb activate 'plan B'\n";
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
This command line help will be printed directly below VDR's help texts (separated
|
||||
by a line indicating the plugin's name, version and description), so if you use the
|
||||
same formatting as shown here it will line up nicely.
|
||||
Note that all lines should be terminated with a newline character, and should
|
||||
be shorter than 80 characters.
|
||||
|
||||
<a name="Getting started"><hr><h2>Getting started</h2>
|
||||
|
||||
<center><i><b>Let's get ready to rumble!</b></i></center><p>
|
||||
|
||||
If a plugin implements a function that runs in the background (presumably in a
|
||||
thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
|
||||
it needs to implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual void Start(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which is called once for each plugin at program startup.
|
||||
Inside this function the plugin must set up everything necessary to perform
|
||||
its task. This may, for instance, be a thread that collects data from the DVB
|
||||
stream, which is later presented to the user via a function that is available
|
||||
from the main menu.
|
||||
<p>
|
||||
If the plugin doesn't implement any background functionality or internationalized
|
||||
texts, it doesn't need to implement this function.
|
||||
|
||||
<hr><h2>Main menu entry</h2>
|
||||
|
||||
<center><i><b>Today's special is...</b></i></center><p>
|
||||
|
||||
If the plugin implements a feature that the user shall be able to access
|
||||
from VDR's main menu, it needs to implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual const char *MainMenuEntry(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The default implementation returns a <tt>NULL</tt> pointer, which means that
|
||||
this plugin will not have an item in the main menu. Here's an example of a
|
||||
plugin that will have a main menu item:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
const char *cPluginDemo::MainMenuEntry(void)
|
||||
{
|
||||
return "Demo";
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The menu entries of all plugins will be inserted into VDR's main menu right
|
||||
after the <i>Recordings</i> item, in the same sequence as they were given
|
||||
in the call to VDR.
|
||||
|
||||
<hr><h2>User interaction</h2>
|
||||
|
||||
<center><i><b>It's showtime!</b></i></center><p>
|
||||
|
||||
If the user selects the main menu entry of a plugin, VDR calls the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual cOsdMenu *MainMenuAction(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which can do one of two things:
|
||||
<ul>
|
||||
<li>Return a pointer to a <tt>cOsdMenu</tt> object which will be displayed
|
||||
as a submenu of the main menu (just like the <i>Recordings</i> menu, for instance).
|
||||
That menu can then implement further functionality and, for instance, could
|
||||
eventually start a custom player to replay a file other than a VDR recording.
|
||||
<li>Perform a specific action and return <tt>NULL</tt>. In that case the main menu
|
||||
will be closed after calling <tt>MainMenuAction()</tt>.
|
||||
</ul>
|
||||
<b>
|
||||
It is very important that a call to <tt>MainMenuAction()</tt> returns as soon
|
||||
as possible! As long as the program stays inside this function, no other user
|
||||
interaction is possible. If a specific action takes longer than a few seconds,
|
||||
the plugin should launch a separate thread to do this.
|
||||
</b>
|
||||
|
||||
<hr><h2>Setup parameters</h2>
|
||||
|
||||
<center><i><b>Remember me...</b></i></center><p>
|
||||
|
||||
If a plugin requires its own setup parameters, it needs to implement the following
|
||||
functions to handle these parameters:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The <tt>SetupMenu()</tt> function shall return the plugin's "Setup" menu
|
||||
page, where the user can adjust all the parameters known to this plugin.
|
||||
<p>
|
||||
<tt>SetupParse()</tt> will be called for each parameter the plugin has
|
||||
previously stored in the global setup data (see below). It shall return
|
||||
<i>true</i> if the parameter was parsed correctly, <i>false</i> in case of
|
||||
an error. If <i>false</i> is returned, an error message will be written to
|
||||
the log file (and program execution will continue).
|
||||
<p>
|
||||
The plugin's setup parameters are stored in the same file as VDR's parameters.
|
||||
In order to allow each plugin (and VDR itself) to have its own set of parameters,
|
||||
the <tt>Name</tt> of each parameter will be preceeded with the plugin's
|
||||
name, as in
|
||||
<p>
|
||||
<tt>demo.SomeParameter = 123</tt>
|
||||
<p>
|
||||
The prefix will be handled by the core VDR setup code, so the individual
|
||||
plugins need not worry about this.
|
||||
<p>
|
||||
To store its values in the global setup, a plugin has to call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
void SetupStore(const char *Name, <i>type</i> Value);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
where <tt>Name</tt> is the name of the parameter (<tt>"SomeParameter"</tt> in the above
|
||||
example, without the prefix <tt>"demo."</tt>) and <tt>Value</tt> is a simple data type (like
|
||||
<tt>char *</tt>, <tt>int</tt> etc).
|
||||
Note that this is not a function that the individual plugin class needs to implement!
|
||||
<tt>SetupStore()</tt> is a non-virtual member function of the <tt>cPlugin</tt> class.
|
||||
<p>
|
||||
To remove a parameter from the setup data, call <tt>SetupStore()</tt> with the appropriate
|
||||
name and without any value, as in
|
||||
<p>
|
||||
<tt>SetupStore("SomeParameter");</tt>
|
||||
<p>
|
||||
The VDR menu "Setup/Plugins" will list all loaded plugins with their name,
|
||||
version number and description. Selecting an item in this list will bring up
|
||||
the plugin's "Setup" menu if that plugin has implemented the <tt>SetupMenu()</tt>
|
||||
function.
|
||||
<p>
|
||||
Finally, a plugin doesn't have to implement the <tt>SetupMenu()</tt> if it only
|
||||
needs setup parameters that are not directly user adjustable. It can use
|
||||
<tt>SetupStore()</tt> and <tt>SetupParse()</tt> without presenting these
|
||||
parameters to the user.
|
||||
|
||||
<a name="Internationalization"><hr><h2>Internationalization</h2>
|
||||
|
||||
<center><i><b>Welcome to Babylon!</b></i></center><p>
|
||||
|
||||
If a plugin displays texts to the user, it should implement internationalized
|
||||
versions of these texts and call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
void RegisterI18n(const tI18nPhrase * const Phrases);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
to register them with VDR's internationalization mechanism.
|
||||
<p>
|
||||
The call to this function must be done in the <a href="#Getting started"><tt>Start()</tt></a> function of the plugin:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
const tI18nPhrase Phrases[] = {
|
||||
{ "Hello world!",
|
||||
"Hallo Welt!",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void cPluginDemo::Start(void)
|
||||
{
|
||||
RegisterI18n(Phrases);
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Each entry of type <tt>tI18nPhrase</tt> must have exactly as many members as defined
|
||||
by the constant <tt>I18nNumLanguages</tt> in the file <tt>VDR/i18n.h</tt>, and the
|
||||
sequence of the various languages must be the same as defined in <tt>VDR/i18n.c</tt>.<br>
|
||||
<b>It is very important that the array is terminated with a <tt>{ NULL }</tt>
|
||||
entry!</b>.
|
||||
<p>
|
||||
Usually you won't be able to fill in all the different translations by yourself, so
|
||||
you may want to contact the maintainers of these languages (listed in the file
|
||||
<tt>VDR/i18n.c</tt>) and ask them to provide the additional translations.
|
||||
<p>
|
||||
The actual runtime selection of the texts corresponding to the selected language
|
||||
is done by wrapping each internationalized text with the <tt>tr()</tt> macro:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
const char *s = tr("Hello world!");
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The text given here must be the first one defined in the related <i>Phrases</i>
|
||||
entry (which is the English version), and the returned pointer is either a translated
|
||||
version (if available) or the original string. In the latter case a message will be
|
||||
written to the log file, indicating that a translation is missing.
|
||||
Texts are first searched for in the <i>Phrases</i> registered for this plugin (if any)
|
||||
and then in the global VDR texts. So a plugin can make use of texts defined by the
|
||||
core VDR code.
|
||||
|
||||
<a name="Loading plugins into VDR"><hr><h2>Loading plugins into VDR</h2>
|
||||
|
||||
<center><i><b>Saddling up!</b></i></center><p>
|
||||
|
||||
Plugins are loaded into VDR using the command line option <b><tt>-P</tt></b>, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -Pdemo
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If the plugin accepts command line options, they are given as part of the argument
|
||||
to the <b><tt>-P</tt></b> option, which then has to be enclosed in quotes:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -P"demo -a abc -b"
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -P"demo -a abc -b" -Pdvd -Pmp3
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If you are not starting VDR from the VDR source directory (and thus your plugins
|
||||
cannot be found at their default location) you need to tell VDR the location of
|
||||
the plugins through the <b><tt>-L</tt></b> option:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -L/usr/lib/vdr -Pdemo
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
There can be any number of <b><tt>-L</tt></b> options, and each of them will apply to the
|
||||
<b><tt>-P</tt></b> options following it.
|
||||
<p>
|
||||
When started with the <b><tt>-h</tt></b> or <b><tt>-V</tt></b> option (for <i>help</i>
|
||||
or <i>version</i> information, respectively), VDR will automatically load all plugins
|
||||
in the default or given directory that match the VDR plugin
|
||||
<a href="#The plugin directory structure">naming convention</a>,
|
||||
and display their help and/or version information in addition to its own output.
|
||||
|
||||
<a name="Building the distribution package"><hr><h2>Building the distribution package</h2>
|
||||
|
||||
<center><i><b>Let's get this show on the road!</b></i></center><p>
|
||||
|
||||
If you want to make your plugin available to other VDR users, you'll need to
|
||||
make a package that can be easily distributed.
|
||||
The <tt>Makefile</tt> that has been created by the call to
|
||||
<a href="#Initializing a new plugin directory"><tt>newplugin</tt></a>
|
||||
provides the target <tt>package</tt>, which does this for you.
|
||||
<p>
|
||||
Simply change into your source directory and execute <tt>make package</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
cd VDR/PLUGINS/SRC/demo
|
||||
make package
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
After this you should find a file named like
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr-demo-0.0.1.tgz
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
in your source directory, where <tt>demo</tt> will be replaced with your actual
|
||||
plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
|
||||
|
||||
</body>
|
||||
</html>
|
340
PLUGINS/SRC/hello/COPYING
Normal file
340
PLUGINS/SRC/hello/COPYING
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General
|
||||
Public License instead of this License.
|
6
PLUGINS/SRC/hello/HISTORY
Normal file
6
PLUGINS/SRC/hello/HISTORY
Normal file
@ -0,0 +1,6 @@
|
||||
VDR Plugin 'hello' Revision History
|
||||
-----------------------------------
|
||||
|
||||
2002-05-09: Version 0.0.1
|
||||
|
||||
- Initial revision.
|
78
PLUGINS/SRC/hello/Makefile
Normal file
78
PLUGINS/SRC/hello/Makefile
Normal file
@ -0,0 +1,78 @@
|
||||
#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# $Id: Makefile 1.1 2002/05/09 15:17:44 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 = hello
|
||||
|
||||
### The version number of this plugin (taken from the main source file):
|
||||
|
||||
VERSION = `grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g'`
|
||||
|
||||
### The directory environment:
|
||||
|
||||
DVBDIR = ../../../../DVB/ost/include
|
||||
VDRDIR = ../../..
|
||||
VDRINC = $(VDRDIR)/include
|
||||
LIBDIR = ../../lib
|
||||
TMPDIR = /tmp
|
||||
|
||||
### The version number of VDR (taken from VDR's "config.h"):
|
||||
|
||||
VDRVERSION = `grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g'`
|
||||
|
||||
### The name of the distribution archive:
|
||||
|
||||
ARCHIVE = vdr-$(PLUGIN)-$(VERSION)
|
||||
|
||||
### Includes and Defines (add further entries here):
|
||||
|
||||
INCLUDES = -I$(VDRINC) -I$(DVBDIR)
|
||||
|
||||
DEFINES = -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
OBJS = $(PLUGIN).o i18n.o
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -O2 -Wall -Woverloaded-virtual -m486
|
||||
|
||||
### Implicit rules:
|
||||
|
||||
%.o: %.c
|
||||
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
|
||||
|
||||
# Dependencies:
|
||||
|
||||
MAKEDEP = g++ -MM -MG
|
||||
DEPFILE = .dependencies
|
||||
$(DEPFILE): Makefile
|
||||
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||
|
||||
include $(DEPFILE)
|
||||
|
||||
### Targets:
|
||||
|
||||
all: libvdr-$(PLUGIN).so
|
||||
|
||||
libvdr-$(PLUGIN).so: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
|
||||
@cp $@ $(LIBDIR)/$@.$(VDRVERSION)
|
||||
|
||||
package: clean
|
||||
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||
@mkdir $(TMPDIR)/$(ARCHIVE)
|
||||
@cp -a * $(TMPDIR)/$(ARCHIVE)
|
||||
@tar czf $(ARCHIVE).tgz -C $(TMPDIR) $(ARCHIVE)
|
||||
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||
@echo Distribution archive created as $(ARCHIVE).tgz
|
||||
|
||||
clean:
|
||||
@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
|
11
PLUGINS/SRC/hello/README
Normal file
11
PLUGINS/SRC/hello/README
Normal file
@ -0,0 +1,11 @@
|
||||
This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <kls@cadsoft.de>
|
||||
|
||||
Project's homepage: www.cadsoft.de/people/kls/vdr
|
||||
|
||||
Latest version available at: www.cadsoft.de/people/kls/vdr/software.htm
|
||||
|
||||
See the file COPYING for license information.
|
||||
|
||||
Description: This is a small demo of the VDR plugin interface.
|
105
PLUGINS/SRC/hello/hello.c
Normal file
105
PLUGINS/SRC/hello/hello.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* hello.c: A plugin for the Video Disk Recorder
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: hello.c 1.1 2002/05/09 15:28:51 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <vdr/interface.h>
|
||||
#include <vdr/plugin.h>
|
||||
#include "i18n.h"
|
||||
|
||||
static const char *VERSION = "0.0.1";
|
||||
static const char *DESCRIPTION = "A friendly greeting";
|
||||
static const char *MAINMENUENTRY = "Hello";
|
||||
|
||||
class cPluginHello : public cPlugin {
|
||||
private:
|
||||
// Add any member variables or functions you may need here.
|
||||
const char *option_a;
|
||||
bool option_b;
|
||||
public:
|
||||
cPluginHello(void);
|
||||
virtual ~cPluginHello();
|
||||
virtual const char *Version(void) { return VERSION; }
|
||||
virtual const char *Description(void) { return tr(DESCRIPTION); }
|
||||
virtual const char *CommandLineHelp(void);
|
||||
virtual bool ProcessArgs(int argc, char *argv[]);
|
||||
virtual void Start(void);
|
||||
virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); }
|
||||
virtual cOsdMenu *MainMenuAction(void);
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
};
|
||||
|
||||
cPluginHello::cPluginHello(void)
|
||||
{
|
||||
// Initialize any member varaiables here.
|
||||
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
||||
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
||||
option_a = NULL;
|
||||
option_b = false;
|
||||
}
|
||||
|
||||
cPluginHello::~cPluginHello()
|
||||
{
|
||||
// Clean up after yourself!
|
||||
}
|
||||
|
||||
const char *cPluginHello::CommandLineHelp(void)
|
||||
{
|
||||
// Return a string that describes all known command line options.
|
||||
return " -a ABC, --aaa=ABC do something nice with ABC\n"
|
||||
" -b, --bbb activate 'plan B'\n";
|
||||
}
|
||||
|
||||
bool cPluginHello::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
// Implement command line argument processing here if applicable.
|
||||
static struct option long_options[] = {
|
||||
{ "aaa", required_argument, NULL, 'a' },
|
||||
{ "bbb", no_argument, NULL, 'b' },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': option_a = optarg;
|
||||
break;
|
||||
case 'b': option_b = true;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPluginHello::Start(void)
|
||||
{
|
||||
// Start any background activities the plugin shall perform.
|
||||
RegisterI18n(Phrases);
|
||||
}
|
||||
|
||||
cOsdMenu *cPluginHello::MainMenuAction(void)
|
||||
{
|
||||
// Perform the action when selected from the main VDR menu.
|
||||
Interface->Info(tr("Hello world!"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cMenuSetupPage *cPluginHello::SetupMenu(void)
|
||||
{
|
||||
// Return a setup menu in case the plugin supports one.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||
{
|
||||
// Parse your own setup parameters and store their values.
|
||||
return false;
|
||||
}
|
||||
|
||||
VDRPLUGINCREATOR(cPluginHello); // Don't touch this!
|
52
PLUGINS/SRC/hello/i18n.c
Normal file
52
PLUGINS/SRC/hello/i18n.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* i18n.c: Internationalization
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.1 2002/05/09 15:13:31 kls Exp $
|
||||
*/
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
const tI18nPhrase Phrases[] = {
|
||||
{ "Hello",
|
||||
"Hallo",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Hello world!",
|
||||
"Hallo Welt!",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "A friendly greeting",
|
||||
"Ein freundlicher Gruß",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ NULL }
|
||||
};
|
11
PLUGINS/SRC/hello/i18n.h
Normal file
11
PLUGINS/SRC/hello/i18n.h
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* i18n.h: Internationalization
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: i18n.h 1.1 2002/05/09 15:15:49 kls Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/i18n.h>
|
||||
|
||||
extern const tI18nPhrase Phrases[];
|
125
channels.conf
125
channels.conf
@ -48,83 +48,68 @@ ORB:12110:h:0:27500:501:502:504:0:28205
|
||||
B1:12110:h:0:27500:601:602:604:0:28206
|
||||
ARD Online-Kanal:12722:h:0:22000:0:701:0:0:0
|
||||
:Premiere World
|
||||
Premiere World:11797:h:0:27500:255:256:32:0:8
|
||||
Premiere 1:11797:h:0:27500:511:512:0:101:10
|
||||
Premiere 2:11797:h:0:27500:1791:1792:0:101:11
|
||||
Premiere Start:11797:h:0:27500:255:256:0:101:8
|
||||
Premiere 1:11797:h:0:27500:511:512,513;515:0:101:10
|
||||
Premiere 2:11797:h:0:27500:1791:1792,1793;1795:0:101:11
|
||||
Premiere 3:11797:h:0:27500:2303:2304:0:101:43
|
||||
Premiere One:12032:h:0:27500:3071:3072:0:101:51
|
||||
Premiere Star:11797:h:0:27500:767:768:0:101:9
|
||||
Premiere Sci-Fi:11797:h:0:27500:1535:1536:0:101:41
|
||||
Premiere Action:11797:h:0:27500:1023:1024:0:101:20
|
||||
Premiere X-Action:11798:h:0:27500:2047:2048:0:101:50
|
||||
Premiere Comedy:11797:h:0:27500:1279:1280:0:101:29
|
||||
13th Street:12031:h:0:27500:2303:2304:0:101:42
|
||||
Premiere 4:11797:h:0:27500:767:768:0:101:9
|
||||
Premiere 5:11797:h:0:27500:1279:1280:0:101:29
|
||||
Premiere 6:11797:h:0:27500:1535:1536:0:101:41
|
||||
Premiere 7:11797:h:0:27500:1023:1024:0:101:20
|
||||
13th Street:11758:h:0:27500:2303:2304:0:101:42
|
||||
Studio Universal:12090:V:0:27500:255:256:0:101:36
|
||||
Filmpalast:12031:h:0:27500:2559:2560:0:101:516
|
||||
Heimatkanal:12031:h:0:27500:2815:2816:0:101:517
|
||||
Discovery Channel:12031:h:0:27500:1791:1792:0:101:14
|
||||
Planet:12090:V:0:27500:1279:1280:0:101:13
|
||||
Fox Kids:12031:h:0:27500:1279:1280:0:101:28
|
||||
Fox Kids Türkce:11914:H:0:27500:767:768:8191:101:54
|
||||
Junior:12031:h:0:27500:255:256:0:101:19
|
||||
K-Toon:12031:h:0:27500:511:512:0:101:12
|
||||
Premiere Serie:12031:h:0:27500:1023:1024:0:101:16
|
||||
Disney Channel:12090:V:0:27500:767:768:0:101:34
|
||||
Sunset:12031:h:0:27500:1023:1024:0:101:16
|
||||
Premiere Nostalgie:12031:h:0:27500:2559:2560:0:101:516
|
||||
Discovery Channel:12031:h:0:27500:1791:1792:0:101:14
|
||||
Planet:12090:v:0:27500:1279:1280:0:101:13
|
||||
Fox Kids:11758:h:0:27500:1279:1280:0:101:28
|
||||
Junior:11758:h:0:27500:255:256:0:101:19
|
||||
K-Toon:11758:h:0:27500:511:512:0:101:12
|
||||
Krimi&Co:12031:h:0:27500:1535:1536:0:101:23
|
||||
Goldstar TV:12031:h:0:27500:3839:3840:0:101:518
|
||||
Classica:12031:h:0:27500:767:768:0:101:15
|
||||
Seasons:12090:V:0:27500:511:512:0:101:33
|
||||
:Cinedom
|
||||
Cinedom Deluxe:11758:h:0:27500:255:256,257;259:0:101:189
|
||||
Cinedom 1A:11758:h:0:27500:511:512,513:0:101:190
|
||||
Cinedom 1B:12070:h:0:27500:1535:1536,1537:0:101:178
|
||||
Cinedom 1C:11720:h:0:27500:511:512,513:0:101:180
|
||||
Cinedom 1D:11720:h:0:27500:1535:1536,1537:0:101:176
|
||||
Cinedom 2A:11758:h:0:27500:1023:1024,1025:0:101:193
|
||||
Cinedom 2B:11720:h:0:27500:1279:1280:0:101:183
|
||||
Cinedom 2C:12070:h:0:27500:1791:1792:0:101:179
|
||||
Cinedom 2D:12070:h:0:27500:511:512:0:101:184
|
||||
Cinedom 2E:12070:h:0:27500:1279:1280:0:101:188
|
||||
Cinedom 3A:11758:h:0:27500:2559:2560:0:101:192
|
||||
Cinedom 3B:11758:h:0:27500:1535:1536:0:101:195
|
||||
Cinedom 3C:12070:h:0:27500:767:768:0:101:185
|
||||
Cinedom 3D:11720:h:0:27500:1023:1024:0:101:182
|
||||
Cinedom 4A:11758:h:0:27500:767:768:0:101:191
|
||||
Cinedom 4B:11720:h:0:27500:767:768:0:101:181
|
||||
Cinedom 4C:12070:h:0:27500:2047:2048:0:101:187
|
||||
Cinedom 5A:11758:h:0:27500:1279:1280:0:101:194
|
||||
Cinedom 5B:11720:h:0:27500:1791:1792:0:101:177
|
||||
Cinedom 5C:12070:h:0:27500:1023:1024:0:101:186
|
||||
Goldstar TV:11758:h:0:27500:3839:3840:0:101:518
|
||||
Classica:11758:h:0:27500:767:768:0:101:15
|
||||
Sonnenklar TV:12090:V:0:27500:1023:1024:0:0:32
|
||||
:Premiere Direkt
|
||||
Premiere Direkt 1A:12031:h:0:27500:511:512,513;515:0:101:177
|
||||
Premiere Direkt 1B:11719:h:0:27500:1023:1024,1025;1027:0:101:182
|
||||
Premiere Direkt 2A:12031:h:0:27500:255:256;259:0:101:176
|
||||
Premiere Direkt 2B:11719:h:0:27500:767:768;769:0:101:181
|
||||
Premiere Direkt 3A:11719:h:0:27500:511:512;515:0:101:180
|
||||
Premiere Direkt 3B:11719:h:0:27500:1279:1280;1283:0:101:183
|
||||
Premiere Direkt 4A:12031:h:0:27500:2815:2816:0:101:18
|
||||
Premiere Direkt 4B:12070:h:0:27500:1535:1536:0:101:216
|
||||
:PW Erotic
|
||||
Beate-Uhse.TV:11758:h:0:27500:1023:1024:0:101:21
|
||||
Premiere Erotik 1:12031:h:0:27500:1279:1280:0:101:513
|
||||
Premiere Erotik 2:11719:h:0:27500:1535:1536:0:101:778
|
||||
Premiere Erotik 3:11719:h:0:27500:1791:1792:0:101:779
|
||||
Premiere Erotik 4:11719:h:0:27500:3583:3584:0:101:780
|
||||
:Sportsworld
|
||||
Premiere Sport 1:11720:h:0:27500:255:256,257:0:101:17
|
||||
Premiere Sport 2:12031:h:0:27500:3839:3840:0:101:27
|
||||
:Formel 1
|
||||
Supersignal:12070:h:0:27500:255:256:0:101:211
|
||||
Cockpitkanal:12070:h:0:27500:511:512:0:101:212
|
||||
Boxengasse:12070:h:0:27500:767:768:0:101:213
|
||||
Verfolgerfeld:12070:h:0:27500:1023:1024:0:101:214
|
||||
Infokanal:12070:h:0:27500:1279:1280:0:101:215
|
||||
Multikanal:11720:h:0:27500:255:256:0:101:17
|
||||
:Beta Digital
|
||||
N24:12480:v:0:27500:2047:2048:0:0:47
|
||||
CNBC:11954:h:0:27500:510:520:0:0:28010
|
||||
Liberty TV.com:12610:V:0:22000:941:943,942:0:0:12199
|
||||
:PW Erotic
|
||||
Beate-Uhse.TV:11758:h:0:27500:3839:3840:0:101:21
|
||||
Blue Movie 1:11758:h:0:27500:1791:1792:0:101:513
|
||||
Blue Movie 2:11758:h:0:27500:2047:2048:0:101:514
|
||||
Blue Movie 3:11758:h:0:27500:2303:2304:0:101:515
|
||||
:Sportsworld
|
||||
Premiere Sport 1:11720:h:0:27500:255:256,257:0:101:17
|
||||
Premiere Sport 2:12070:h:0:27500:3839:3840:0:101:27
|
||||
Premiere Sport 3:12070:h:0:27500:255:256:0:101:26
|
||||
:Formel 1
|
||||
Infokanal:11720:h:0:27500:3071:3072:0:101:244
|
||||
Multikanal:11720:h:0:27500:2815:2816:0:101:243
|
||||
Supersignal:11720:h:0:27500:255:256:0:101:17
|
||||
Verfolgerfeld:11720:h:0:27500:2303:2304:0:101:241
|
||||
Cockpitkanal:11720:h:0:27500:2559:2560:0:101:242
|
||||
Boxengasse:11720:h:0:27500:2047:2048:0:101:240
|
||||
:Premiere World Bundesliga
|
||||
Superdom:11758:h:0:27500:2815:8192:0:101:18
|
||||
BuLi-Konferenz:11758:h:0:27500:3327:3328,3329:0:101:215
|
||||
BuLi-Spiel 1:11720:h:0:27500:255:256,257:0:101:17
|
||||
BuLi-Spiel 2:11720:h:0:27500:2047:2048,2049:0:101:240
|
||||
BuLi-Spiel 3:11720:h:0:27500:2303:2304,2305:0:101:241
|
||||
BuLi-Spiel 4:11720:h:0:27500:2559:2560,2561:0:101:242
|
||||
BuLi-Spiel 5:11720:h:0:27500:2815:2816,2817:0:101:243
|
||||
BuLi-Spiel 6:11720:h:0:27500:3071:3072,3073:0:101:244
|
||||
BuLi-Spiel 7:11758:h:0:27500:3071:3072,3073:0:101:214
|
||||
:Premiere Bundesliga
|
||||
BL-Konferenz:12031:h:0:27500:2303:2304,2305:0:101:210
|
||||
BuLi 1:11719:h:0:27500:255:256,257:0:101:17
|
||||
BuLi 2:11719:h:0:27500:2047:2048,2049:0:101:240
|
||||
BuLi 3:11719:h:0:27500:2303:2304,2305:0:101:241
|
||||
BuLi 4:11719:h:0:27500:2559:2560,2561:0:101:242
|
||||
BuLi 5:11719:h:0:27500:2815:2816,2817:0:101:243
|
||||
BuLi 6:11719:h:0:27500:3071:3072,3073:0:101:244
|
||||
BuLi 7:11719:h:0:27500:3327:3328,3329:0:101:245
|
||||
BuLi 8:12031:h:0:27500:3071:3072,3073:0:101:208
|
||||
BuLi 9:12031:h:0:27500:3327:3328,3329:0:101:209
|
||||
:
|
||||
TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601
|
||||
Mosaico:11934:v:0:27500:165:100:0:0:29010
|
||||
@ -168,7 +153,7 @@ ESC 1:12363:v:0:27500:163:104:0:0:0
|
||||
TV5 Europe:12363:v:0:27500:164:112:0:0:0
|
||||
TV7 Tunisia:12363:v:0:27500:166:128:0:0:0
|
||||
ARTE:12363:v:0:27500:167:137:0:0:0
|
||||
RAI Uno:12363:v:0:27500:289:290:0:0:8904
|
||||
RAI Uno:10788:v:0:22000:289:290:0:0:9004
|
||||
RTP International:12363:v:0:27500:300:301:0:0:0
|
||||
Fashion TV:12402:v:0:27500:163:92:0:0:0
|
||||
VideoService:12422:h:0:27500:255:256:0:0:0
|
||||
|
@ -1,184 +1,165 @@
|
||||
:verschlüsselte Fernsehprogramm
|
||||
PREMIERE ONE:378:h:0:6900:3071:3072:0:1:51
|
||||
PREMIERE MOVIE 1:370:h:0:6900:511:512;515:0:1:10
|
||||
PREMIERE MOVIE 2:370:h:0:6900:1791:1792:0:1:11
|
||||
PREMIERE MOVIE 3:370:h:0:6900:2303:2304:0:1:43
|
||||
PREMIERE ACTION:370:h:0:6900:1023:1024,1025:0:1:20
|
||||
PREMIERE X-ACTION:370:h:0:6900:2047:2048,2049:0:1:50
|
||||
PREMIERE SCI-FI:370:h:0:6900:1535:1536:0:1:41
|
||||
PREMIERE STAR:370:h:0:6900:767:768:0:1:9
|
||||
PREMIERE COMEDY:370:h:0:6900:1279:1280:0:1:29
|
||||
13 TH STREET:378:h:0:6900:2303:2304,2305:0:1:42
|
||||
KRIMI &CO:378:h:0:6900:1535:1536:0:1:23
|
||||
STUDIO UNIVERSAL:402:h:0:6900:1050:1054:0:1:36
|
||||
DISCOVERY CHANNEL:378:h:0:6900:1791:1792:0:1:14
|
||||
FILMPALAST:378:h:0:6900:2559:2560:0:1:516
|
||||
DISNEY CHANNEL:402:h:0:6900:1030:1034:0:1:34
|
||||
SUNSET:378:h:0:6900:1023:1024:0:1:16
|
||||
PLANET:402:h:0:6900:1100:1104:0:1:13
|
||||
CLASSICA:378:h:0:6900:767:768:0:1:15
|
||||
GOLDSTAR TV:378:h:0:6900:3839:3840:0:1:518
|
||||
HEIMATKANAL:378:h:0:6900:2815:2816:0:1:517
|
||||
K-TOON:378:h:0:6900:511:512:0:1:12
|
||||
FOX KIDS:378:h:0:6900:1279:1280:0:1:28
|
||||
KiKa:394:h:0:6900:310:320:330:0:28008
|
||||
JUNIOR:378:h:0:6900:255:256:0:1:19
|
||||
:Fernsehprogramme
|
||||
Das Erste:410:h:0:6900:101:102,88:104:0:28106
|
||||
ZDF:394:h:0:6900:110:120,121:130:0:28006
|
||||
Das Erste:410:h:0:6900:101:102:111:0:28106
|
||||
ZDF:394:h:0:6900:110:120:130:0:28006
|
||||
3sat:394:h:0:6900:210:220:230:0:28007
|
||||
arte:410:h:0:6900:401:402:404:0:28109
|
||||
EuroNews:394:h:0:6900:2221:2233:768:0:28015
|
||||
ZDF.info:394:h:0:6900:610:620:0:0:28011
|
||||
ZDF.doku:394:h:0:6900:660:670:0:0:28014
|
||||
ZDF Theaterkanal:394:h:0:6900:1110:1120:130:0:28016
|
||||
EinsExtra:426:h:0:6900:101:102:0:0:28201
|
||||
EinsFestival:426:h:0:6900:201:202:0:0:28202
|
||||
EinsMuXx:426:h:0:6900:301:302:0:0:28203
|
||||
3sat:394:h:0:6900:210:220:230:0:28007
|
||||
arte:410:h:0:6900:401:402:404:0:28109
|
||||
EuroNews:394:h:0:6900:2221:2233:768:0:28015
|
||||
Phoenix:410:h:0:6900:901:902:0:0:28114
|
||||
Eurosport:394:h:0:6900:410:420:430:0:28009
|
||||
DW-tv:610:h:0:6900:634:632:0:0:6101
|
||||
CNBC:394:h:0:6900:510:520:530:0:28010
|
||||
:Regionalprogramme
|
||||
WDR FERNSEHEN:410:h:0:6900:601:602:604:0:28111
|
||||
B1 Berlin:426:h:0:6900:601:602,603:604:0:28206
|
||||
ORB-Fernsehen:426:h:0:6900:501:502:504:0:28205
|
||||
MDR FERNSEHEN:426:h:0:6900:401:402:404:0:28204
|
||||
SR Fernsehen Suedwest:410:h:0:6900:501:502:504:0:28110
|
||||
SuedWest BW:410:h:0:6900:801:802:804:0:28113
|
||||
SuedWest RP:426:h:0:6900:3101:3102:3104:0:28231
|
||||
BR-alpha:410:h:0:6900:701:702:704:0:28112
|
||||
B1 Berlin:426:h:0:6900:601:602:604:0:28206
|
||||
N3:426:h:0:6900:2401:2402:2404:0:28224
|
||||
ORB-Fernsehen:426:h:0:6900:501:502:504:0:28205
|
||||
hessen fernsehen:410:h:0:6900:301:302:304:0:28108
|
||||
Bayerisches FS:410:h:0:6900:201:202:204:0:28107
|
||||
Test-R:410:h:0:6900:901:902:104:0:28130
|
||||
:Premiere Hauptprogramme
|
||||
Premiere START:370:C:0:6900:255:256:32:101:8
|
||||
Premiere 1:370:C:0:6900:511:512:0:101:10
|
||||
Premiere 2:370:C:0:6900:1791:1792:0:101:11
|
||||
Premiere 3:370:C:0:6900:2303:2304:0:101:43
|
||||
Premiere 4:370:C:0:6900:767:768:0:101:9
|
||||
Premiere 5:370:C:0:6900:1279:1280:0:101:29
|
||||
Premiere 6:370:C:0:6900:1535:1536:0:101:41
|
||||
Premiere 7:370:C:0:6900:1023:1024:0:101:20
|
||||
Premiere SERIE:378:C:0:6900:1023:1024:0:101:16
|
||||
Premiere Nostalgie:378:C:0:6900:2559:2560:0:101:516
|
||||
13 TH STREET:354:C:0:6900:2303:2304:0:101:42
|
||||
Stundio Universal:402:C:0:6900:1050:1054:0:101:36
|
||||
Krimi &Co:378:C:0:6900:1535:1536:0:101:23
|
||||
Disney Channel:402:C:0:6900:1030:1034:0:101:34
|
||||
Discovery Channel:378:C:0:6900:1791:1792:0:101:14
|
||||
Fox Kids:354:C:0:6900:1279:1280:0:101:28
|
||||
Junior:354:C:0:6900:255:256:0:101:19
|
||||
K-TOON:354:C:0:6900:0:0:0:101:12
|
||||
GOLDSTAR TV:354:C:0:6900:3839:3840:0:101:518
|
||||
CLASSICA:354:C:0:6900:767:768:0:101:15
|
||||
:Mediavision
|
||||
Extreme Sport:346:h:0:6900:801:802:0:1:50700
|
||||
Bloomberg:346:h:0:6900:811:812:0:1:50701
|
||||
Single TV:346:h:0:6900:621:622:0:1:50706
|
||||
Fashion TV:346:h:0:6900:821:822:0:1:50702
|
||||
BET ON JAZZ:346:h:0:6900:841:842:0:1:50704
|
||||
LANDSCAPE:346:h:0:6900:831:832:0:1:50703
|
||||
Einstein:346:h:0:6900:623:624:0:1:50719
|
||||
Bloomberg:346:h:0:6900:811:812:0:101:50701
|
||||
Fashion TV:346:h:0:6900:821:822:0:101:50702
|
||||
Einstein:346:h:0:6900:623:624:0:101:50719
|
||||
Extreme Sport:346:h:0:6900:801:802:0:101:50700
|
||||
LANDSCAPE:346:h:0:6900:831:832:0:101:50703
|
||||
Single TV:346:h:0:6900:621:622:0:101:50706
|
||||
Leitseite:346:h:0:6900:2254:0:0:0:5004
|
||||
Via 1 - Schöner Reisen:346:h:0:6900:611:612:0:0:50705
|
||||
Parlamentsfernsehen:610:h:0:6900:33:36:47:0:6100
|
||||
Vh1 - Classic:610:h:0:6900:604:603:0:0:6106
|
||||
BET ON JAZZ:346:h:0:6900:841:842:0:101:50704
|
||||
:Digit. Bouquet"Kabel Berlin"
|
||||
Parlamentsfernsehen:610:C:0:6900:33:36:47:0:6100
|
||||
DW-tv:610:C:0:6900:634:632:0:0:6101
|
||||
Kanal 7:610:C:0:6900:49:52:0:101:6103
|
||||
Euronews:610:C:0:6900:597:592,591:0:101:6104
|
||||
Vh1 - Classic:610:h:0:6900:604:603:0:101:6106
|
||||
Travel:610:C:0:6900:595:594:0:101:6105
|
||||
Nuvolari:618:C:0:6900:1011:1012:0:101:50101
|
||||
Marco Polo:618:C:0:6900:1021:1022:0:101:50102
|
||||
Alice:618:C:0:6900:1031:1032:0:101:50103
|
||||
Leonardo:618:C:0:6900:1041:1042:0:101:50104
|
||||
Club:618:C:0:6900:1051:1052:0:101:50105
|
||||
Avante:618:C:0:6900:1061:1062:0:101:50106
|
||||
Expo 24*7:618:C:0:6900:1071:1072:0:101:50107
|
||||
Innergy:618:C:0:6900:0:0:0:101:50108
|
||||
BBC Prime:618:C:0:6900:1091:1092:0:101:50109
|
||||
Eurosport News:618:C:0:6900:1101:1102:0:101:50110
|
||||
:Diverse TV-Sender
|
||||
TV Polonia:434:h:0:6900:641:642:0:1:53204
|
||||
Kanal D:434:h:0:6900:651:652:0:1:53205
|
||||
RTP international:434:h:0:6900:661:662:0:1:53206
|
||||
ERT-Sat:434:h:0:6900:691:692:0:1:53209
|
||||
CNE:434:h:0:6900:4056:4057:0:1:53208
|
||||
ZEE TV:442:h:0:6900:517:773:0:1:53301
|
||||
NTV i:442:h:0:6900:514:515:0:1:53302
|
||||
TV Polonia:434:h:0:6900:641:642:0:101:53204
|
||||
Kanal D:434:h:0:6900:651:652:0:101:53205
|
||||
RTP international:434:h:0:6900:661:662:0:101:53206
|
||||
ERT-Sat:434:h:0:6900:691:692:0:101:53209
|
||||
CNE:434:h:0:6900:4056:4057:0:101:53208
|
||||
ZEE TV:442:h:0:6900:517:773:0:101:53301
|
||||
NTV i:442:h:0:6900:514:515:0:101:53302
|
||||
ATV:434:h:0:6900:631:632:0:0:53203
|
||||
TW1:610:h:0:6900:6106:6107:0:0:6106
|
||||
PREMIERE WORLD:370:h:0:6900:255:256:32:0:8
|
||||
:Premiere World Bundesliga
|
||||
Superdom:362:h:0:6900:255:256:0:1:26
|
||||
Spiel 1:362:h:0:6900:255:256,257:0:1:17
|
||||
Spiel 2:362:h:0:6900:2047:2048,2049:0:1:240
|
||||
BuLi-Konferenz:362:h:0:6900:3071:3072,3073:0:1:208
|
||||
BuLi-Spiel 1:362:h:0:6900:3327:3328,3329:0:1:209
|
||||
BuLi-Spiel 2:362:h:0:6900:2303:2304,2305:0:1:210
|
||||
BuLi-Spiel 3:362:h:0:6900:3583:3584,3585:0:1:211
|
||||
BuLi-Spiel 4:362:h:0:6900:2559:2560,2561:0:1:212
|
||||
BuLi-Spiel 5:362:h:0:6900:2815:2816,2817:0:1:213
|
||||
:Premiere Sport
|
||||
PREMIERE SPORT 1:362:h:0:6900:255:256:0:1:17
|
||||
PREMIERE SPORT 2:362:h:0:6900:3327:3328:0:1:27
|
||||
PREMIERE SPORT 3:354:h:0:6900:2815:2816:0:1:18
|
||||
:Premiere Formel 1
|
||||
F1 Studio:362:h:0:6900:255:256:0:1:17
|
||||
F1 Box:362:h:0:6900:2047:2048:0:1:240
|
||||
F1 Verfolger:362:h:0:6900:2303:2304:0:1:241
|
||||
F1 Cockpit:362:h:0:6900:2559:2560:0:1:242
|
||||
F1 Multi:362:h:0:6900:2815:2816:0:1:243
|
||||
F1 Info:362:h:0:6900:3071:3072:0:1:244
|
||||
:Premiere Cinedom 1
|
||||
Cinedom 1A:362:h:0:6900:1535:1536,1537:0:1:176
|
||||
Cinedom 1B:386:h:0:6900:1535:1536,1537:0:1:178
|
||||
Cinedom 1C:362:h:0:6900:511:512,513:0:1:180
|
||||
Cinedom 1D:354:h:0:6900:511:512,513:0:1:190
|
||||
:Premiere Cinedom 2
|
||||
Cinedom 2A:386:h:0:6900:1791:1792,1793:0:1:179
|
||||
Cinedom 2B:362:h:0:6900:1279:1280,1281:0:1:183
|
||||
Cinedom 2C:386:h:0:6900:511:512:0:1:184
|
||||
Cinedom 2D:386:h:0:6900:1279:1280:0:1:188
|
||||
Cinedom 2E:354:h:0:6900:1023:1024:0:1:193
|
||||
: Premiere Cinedom 3
|
||||
Cinedom 3A:362:h:0:6900:1023:1024,1025:0:1:182
|
||||
Cinedom 3B:386:h:0:6900:767:768:0:1:185
|
||||
Cinedom 3C:354:h:0:6900:2559:2560:0:1:192
|
||||
Cinedom 3D:354:h:0:6900:1535:1536:0:1:195
|
||||
: Premiere Cinedom 4
|
||||
Cinedom 4A:362:h:0:6900:767:768,769:0:1:181
|
||||
Cinedom 4B:386:h:0:6900:2047:2048:0:1:187
|
||||
Cinedom 4C:354:h:0:6900:767:768:0:1:191
|
||||
: Premiere Cinedom 5
|
||||
Cinedom 5A:386:h:0:6900:1023:1024,1025:0:1:186
|
||||
Cinedom 5B:354:h:0:6900:1279:1280,1281:0:1:194
|
||||
: Premiere Cinedom Deluxe
|
||||
CINEDOM DELUXE:354:h:0:6900:255:256,257:0:1:189
|
||||
:Premiere Erotic
|
||||
BEATE-UHSE.TV:354:h:0:6900:3839:3840:0:1:21
|
||||
BLUE MOVIE 1:354:h:0:6900:1791:1792:0:1:513
|
||||
BLUE MOVIE 2:354:h:0:6900:2047:2048:0:1:514
|
||||
BLUE MOVIE 3:354:h:0:6900:2303:2304:0:1:515
|
||||
PREMIERE SPORT 1:362:C:0:6900:255:256,257:0:101:17
|
||||
PREMIERE SPORT 2:378:C:0:6900:3839:3840,3841:0:101:27
|
||||
:Premiere Direkt 1
|
||||
PREMIERE DIREKT 1A:362:C:0:6900:1023:1024,1025:0:101:182
|
||||
PREMIERE DIREKT 1B:378:C:0:6900:511:512,513:0:101:177
|
||||
:Premiere Direkt 2
|
||||
PREMIERE DIREKT 2A:378:C:0:6900:255:256,257:0:101:176
|
||||
PREMIERE DIREKT 2B:362:C:0:6900:767:768,769:0:101:181
|
||||
:Premiere Direkt 3
|
||||
PREMIERE DIREKT 3A:362:C:0:6900:511:512,513:0:101:180
|
||||
PREMIERE DIREKT 3B:362:C:0:6900:1279:1280,1281:0:101:183
|
||||
:Premiere Direkt 4
|
||||
PREMIERE DIREKT 4A:378:C:0:6900:2815:2816,2817:0:101:18
|
||||
PREMIERE DIREKT 4B:386:C:0:6900:1535:1536,1537:0:101:216
|
||||
:Premiere Erotik
|
||||
BEATE-UHSE.TV:354:C:0:6900:1023:1024:0:101:21
|
||||
PREMIERE EROTIK 1:378:C:0:6900:1279:1280:0:101:513
|
||||
PREMIERE EROTIK 2:362:C:0:6900:1535:1536:0:101:778
|
||||
PREMIERE EROTIK 3:362:C:0:6900:1791:1792:0:101:779
|
||||
PREMIERE EROTIK 4:362:C:0:6900:3583:3584:0:101:780
|
||||
:Radioprogramme
|
||||
Fritz:426:h:0:6900:0:901:0:0:28209
|
||||
HR XXL:410:h:0:6900:0:3501:0:0:28125
|
||||
JUMP:426:h:0:6900:0:1001:0:0:28210
|
||||
SPUTNIK:426:h:0:6900:0:1201:0:0:28212
|
||||
RADIOmultikulti:426:h:0:6900:0:1301:0:0:28213
|
||||
DLR-Berlin:394:h:0:6900:0:710:0:0:28012
|
||||
DLF-Köln:394:h:0:6900:0:810:0:0:28013
|
||||
Österreich 1:394:h:0:6900:0:169:0:0:28017
|
||||
100,6:354:h:0:6900:0:1312:0:0:161
|
||||
Bayern 4 Klassik:410:h:0:6900:0:3001:0:0:28120
|
||||
B5 aktuell:410:h:0:6900:0:3101:0:0:28121
|
||||
Bremen 2:410:h:0:6900:0:3801:0:0:28128
|
||||
Bayern 1:410:h:0:6900:0:3601:0:0:28126
|
||||
NDR 4 Info:410:h:0:6900:0:3701:0:0:28127
|
||||
SR 1:410:h:0:6900:0:3901:0:0:28129
|
||||
hr-klassik:410:h:0:6900:0:3401:0:0:28124
|
||||
hr2:410:h:0:6900:0:3301:0:0:28123
|
||||
hr-chronos:410:h:0:6900:0:3201:0:0:28122
|
||||
Radio 3:426:h:0:6900:0:701:0:0:28207
|
||||
MDR KULTUR:426:h:0:6900:0:801:0:0:28208
|
||||
MDR info:426:h:0:6900:0:1101:0:0:28211
|
||||
SWR-2:426:h:0:6900:0:1401:0:0:28214
|
||||
WDR3:426:h:0:6900:0:1501:0:0:28215
|
||||
WDR Radio 5:426:h:0:6900:0:1601:0:0:28216
|
||||
Fritz:426:h:0:6900:1:901:0:0:28209
|
||||
HR XXL:410:h:0:6900:1:3501:0:0:28125
|
||||
JUMP:426:h:0:6900:1:1001:0:0:28210
|
||||
SPUTNIK:426:h:0:6900:1:1201:0:0:28212
|
||||
RADIOmultikulti:426:h:0:6900:1:1301:0:0:28213
|
||||
DLR-Berlin:394:h:0:6900:1:710:0:0:28012
|
||||
DLF-Köln:394:h:0:6900:1:810:0:0:28013
|
||||
Österreich 1:394:h:0:6900:1:169:0:0:28017
|
||||
100,6:354:h:0:6900:1:1312:0:0:161
|
||||
Bayern 4 Klassik:410:h:0:6900:1:3001:0:0:28120
|
||||
B5 aktuell:410:h:0:6900:1:3101:0:0:28121
|
||||
Bremen 2:410:h:0:6900:1:3801:0:0:28128
|
||||
Bayern 1:410:h:0:6900:1:3601:0:0:28126
|
||||
NDR 4 Info:410:h:0:6900:1:3701:0:0:28127
|
||||
SR 1:410:h:0:6900:1:3901:0:0:28129
|
||||
hr-klassik:410:h:0:6900:1:3401:0:0:28124
|
||||
hr2:410:h:0:6900:1:3301:0:0:28123
|
||||
hr-chronos:410:h:0:6900:1:3201:0:0:28122
|
||||
Radio 3:426:h:0:6900:1:701:0:0:28207
|
||||
MDR KULTUR:426:h:0:6900:1:801:0:0:28208
|
||||
MDR info:426:h:0:6900:1:1101:0:0:28211
|
||||
SWR-2:426:h:0:6900:1:1401:0:0:28214
|
||||
WDR3:426:h:0:6900:1:1501:0:0:28215
|
||||
WDR Radio 5:426:h:0:6900:1:1601:0:0:28216
|
||||
:verschlüsselte Radioprogramme
|
||||
ALTERNATIVE ROCK:378:h:0:6900:1:800:0:1:151
|
||||
HITLISTE:378:h:0:6900:1:784:0:1:150
|
||||
DANCE:378:h:0:6900:1:816:0:1:152
|
||||
EASY LISTENING:402:h:0:6900:1:1201:0:1:162
|
||||
CLASSIC ROCK:378:h:0:6900:1:544:0:1:154
|
||||
Cristal New Age:442:h:0:6900:1:536:0:0:53351
|
||||
Movie Sounds:442:h:0:6900:1:537:0:1:53352
|
||||
LOVE SONGS:402:h:0:6900:1:1191:0:1:163
|
||||
KLASSIK POPULÄR:378:h:0:6900:1:592:0:1:145
|
||||
KLASS. SYMPHONIEN:378:h:0:6900:1:608:0:1:146
|
||||
OPER & VOKALMUSIK:378:h:0:6900:1:624:0:1:147
|
||||
BAROCKMUSIK:378:h:0:6900:1:640:0:1:148
|
||||
JAZZ:378:h:0:6900:1:656:0:1:149
|
||||
COUNTRY:378:h:0:6900:1:352:0:1:153
|
||||
FILMMUSIK:378:h:0:6900:1:368:0:1:155
|
||||
DEUTSCHE HITS:402:h:0:6900:1:1156:0:1:156
|
||||
SOUL CLASSICS:402:h:0:6900:1:1161:0:1:157
|
||||
TÜRK MÜZIGI:402:h:0:6900:1:1166:0:1:158
|
||||
GOLD:402:h:0:6900:1:1171:0:1:159
|
||||
MUSICALS:402:h:0:6900:1:1196:0:1:164
|
||||
OLD GOLD:402:h:0:6900:1:1186:0:1:165
|
||||
SCHLAGER:402:h:0:6900:1:1176:0:1:166
|
||||
VOLKSMUSIK:402:h:0:6900:1:1181:0:1:167
|
||||
All Jazz:442:h:0:6900:1:535:0:1:53350
|
||||
Sinfonica:442:h:0:6900:1:538:0:1:53353
|
||||
Opernfestival:442:h:0:6900:1:539:0:1:53354
|
||||
Barock Fantasie:442:h:0:6900:1:540:0:1:53355
|
||||
Musica Camerata:442:h:0:6900:1:541:0:1:53356
|
||||
Musica Antica:442:h:0:6900:1:542:0:1:53357
|
||||
Adagio:442:h:0:6900:1:543:0:1:53358
|
||||
Jazz Legends:442:h:0:6900:1:544:0:1:53359
|
||||
ALTERNATIVE ROCK:370:C:0:6900:1:800:0:101:151
|
||||
CLASSIC ROCK:370:C:0:6900:1:544:0:101:154
|
||||
DANCE:370:C:0:6900:1:816:0:101:152
|
||||
LOVE SONGS:370:C:0:6900:1:352:0:101:163
|
||||
GOLD:370:C:0:6900:1:576:0:101:159
|
||||
OLD GOLD:370:C:0:6900:1:304:0:101:165
|
||||
SOUL CLASSICS:370:C:0:6900:1:400:0:101:157
|
||||
EASY LISTENING:370:C:0:6900:1:384:0:101:162
|
||||
DEUTSCHE HITS:370:C:0:6900:1:592:0:101:156
|
||||
SCHLAGER:370:C:0:6900:1:320:0:101:166
|
||||
VOLKSMUSIK:362:C:0:6900:1:336:0:101:167
|
||||
COUNTRY:362:C:0:6900:1:352:0:101:153
|
||||
FILMMUSIK:362:C:0:6900:1:368:0:101:155
|
||||
MUSICALS:362:C:0:6900:1:384:0:101:164
|
||||
JAZZ:362:C:0:6900:1:656:0:101:149
|
||||
KLASSIK POPUL04R:378:C:0:6900:1:592:0:101:145
|
||||
ORCHESTRALE WERKE:378:C:0:6900:1:608:0:101:146
|
||||
BAROCK:378:C:0:6900:1:640:0:101:148
|
||||
OPER:378:C:0:6900:1:624:0:101:147
|
||||
TÜRK MÜZIGI:378:C:0:6900:1:560:0:101:158
|
||||
HITLISTE:370:C:0:6900:1:784:0:101:150
|
||||
Radio GoldStar:354:C:0:6900:1:368:0:101:171
|
||||
All Jazz:442:C:0:6900:1:535:0:101:53350
|
||||
Cristal New Age:442:C:0:6900:1:536:0:101:53351
|
||||
Movie Sounds:442:C:0:6900:1:537:0:101:53352
|
||||
Sinfonica:442:C:0:6900:1:538:0:101:53353
|
||||
Opernfestival:442:C:0:6900:1:539:0:101:53354
|
||||
Barock Fantasie:442:C:0:6900:1:540:0:101:53355
|
||||
Musica Camerata:442:C:0:6900:1:541:0:101:53356
|
||||
Musica Antica:442:C:0:6900:1:542:0:101:53357
|
||||
Adagio:442:C:0:6900:1:543:0:101:53358
|
||||
Jazz legends:442:C:0:6900:1:544:0:101:53359
|
||||
|
@ -9,3 +9,12 @@ BBC CHOICE:505833:0:0:0:620:621:0:0:4351
|
||||
BBC NEWS 24:505833:0:0:0:640:641:0:0:4415
|
||||
BBC Knowledge:505833:0:0:0:630:631:0:0:4607
|
||||
Shop!:561833:0:0:0:6049:6050:0:0:13120
|
||||
: DVB-T Berlin Germany
|
||||
RTL 1:778000:V:0:27500:160:80:0:1:1
|
||||
RTL 2:778000:V:0:27500:161:82:0:1:2
|
||||
Super RTL:778000:V:0:27500:162:84:0:1:3
|
||||
VOX:778000:V:0:27500:165:81:0:1:4
|
||||
SAT 1:714000:V:0:27500:160:80:0:1:18
|
||||
PRO 7:714000:V:0:27500:161:82:0:1:19
|
||||
KABEL 1:714000:V:0:27500:162:84:0:1:20
|
||||
N24:714000:V:0:27500:163:86:0:1:21
|
||||
|
373
config.c
373
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.97 2002/04/02 21:56:51 kls Exp $
|
||||
* $Id: config.c 1.99 2002/05/05 09:10:00 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -13,6 +13,7 @@
|
||||
#include "dvbapi.h"
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "plugin.h"
|
||||
|
||||
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
|
||||
// format characters in order to allow any number of blanks after a numeric
|
||||
@ -332,7 +333,8 @@ cTimer::cTimer(bool Instant)
|
||||
struct tm *now = localtime_r(&t, &tm_r);
|
||||
day = now->tm_mday;
|
||||
start = now->tm_hour * 100 + now->tm_min;
|
||||
stop = start + 200; // "instant recording" records 2 hours by default
|
||||
stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
|
||||
stop = (stop / 60) * 100 + (stop % 60);
|
||||
if (stop >= 2400)
|
||||
stop -= 2400;
|
||||
//TODO VPS???
|
||||
@ -386,11 +388,12 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool cTimer::operator< (const cTimer &Timer)
|
||||
bool cTimer::operator< (const cListObject &ListObject)
|
||||
{
|
||||
cTimer *ti = (cTimer *)&ListObject;
|
||||
time_t t1 = StartTime();
|
||||
time_t t2 = (*(cTimer *)&Timer).StartTime();
|
||||
return t1 < t2 || (t1 == t2 && priority > Timer.priority);
|
||||
time_t t2 = ti->StartTime();
|
||||
return t1 < t2 || (t1 == t2 && priority > ti->priority);
|
||||
}
|
||||
|
||||
const char *cTimer::ToText(cTimer *Timer)
|
||||
@ -916,12 +919,76 @@ const cCaDefinition *cCaDefinitions::Get(int Number)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// -- cSetupLine -------------------------------------------------------------
|
||||
|
||||
cSetupLine::cSetupLine(void)
|
||||
{
|
||||
plugin = name = value = NULL;
|
||||
}
|
||||
|
||||
cSetupLine::cSetupLine(const char *Name, const char *Value, const char *Plugin)
|
||||
{
|
||||
name = strdup(Name);
|
||||
value = strdup(Value);
|
||||
plugin = Plugin ? strdup(Plugin) : NULL;
|
||||
}
|
||||
|
||||
cSetupLine::~cSetupLine()
|
||||
{
|
||||
delete plugin;
|
||||
delete name;
|
||||
delete value;
|
||||
}
|
||||
|
||||
bool cSetupLine::operator< (const cListObject &ListObject)
|
||||
{
|
||||
const cSetupLine *sl = (cSetupLine *)&ListObject;
|
||||
if (!plugin && !sl->plugin)
|
||||
return strcasecmp(name, sl->name) < 0;
|
||||
if (!plugin)
|
||||
return true;
|
||||
if (!sl->plugin)
|
||||
return false;
|
||||
int result = strcasecmp(plugin, sl->plugin);
|
||||
if (result == 0)
|
||||
result = strcasecmp(name, sl->name);
|
||||
return result < 0;
|
||||
}
|
||||
|
||||
bool cSetupLine::Parse(char *s)
|
||||
{
|
||||
char *p = strchr(s, '=');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
char *Name = compactspace(s);
|
||||
char *Value = compactspace(p + 1);
|
||||
if (*Name && *Value) {
|
||||
p = strchr(Name, '.');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
char *Plugin = compactspace(Name);
|
||||
Name = compactspace(p + 1);
|
||||
if (!(*Plugin && *Name))
|
||||
return false;
|
||||
plugin = strdup(Plugin);
|
||||
}
|
||||
name = strdup(Name);
|
||||
value = strdup(Value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSetupLine::Save(FILE *f)
|
||||
{
|
||||
return fprintf(f, "%s%s%s = %s\n", plugin ? plugin : "", plugin ? "." : "", name, value) > 0;
|
||||
}
|
||||
|
||||
// -- cSetup -----------------------------------------------------------------
|
||||
|
||||
cSetup Setup;
|
||||
|
||||
char *cSetup::fileName = NULL;
|
||||
|
||||
cSetup::cSetup(void)
|
||||
{
|
||||
OSDLanguage = 0;
|
||||
@ -930,6 +997,7 @@ cSetup::cSetup(void)
|
||||
MenuScrollPage = 1;
|
||||
MarkInstantRecord = 1;
|
||||
strcpy(NameInstantRecord, "TITLE EPISODE");
|
||||
InstantRecordTime = 180;
|
||||
LnbSLOF = 11700;
|
||||
LnbFrequLo = 9750;
|
||||
LnbFrequHi = 10600;
|
||||
@ -964,19 +1032,77 @@ cSetup::cSetup(void)
|
||||
CurrentVolume = MAXVOLUME;
|
||||
}
|
||||
|
||||
void cSetup::PrintCaCaps(FILE *f, const char *Name)
|
||||
cSetup& cSetup::operator= (const cSetup &s)
|
||||
{
|
||||
memcpy(&__BeginData__, &s.__BeginData__, (char *)&s.__EndData__ - (char *)&s.__BeginData__);
|
||||
return *this;
|
||||
}
|
||||
|
||||
cSetupLine *cSetup::Get(const char *Name, const char *Plugin)
|
||||
{
|
||||
for (cSetupLine *l = First(); l; l = Next(l)) {
|
||||
if ((l->Plugin() == NULL) == (Plugin == NULL)) {
|
||||
if ((!Plugin || strcasecmp(l->Plugin(), Plugin) == 0) && strcasecmp(l->Name(), Name) == 0)
|
||||
return l;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cSetup::Store(const char *Name, const char *Value, const char *Plugin)
|
||||
{
|
||||
if (Name && *Name) {
|
||||
cSetupLine *l = Get(Name, Plugin);
|
||||
if (l)
|
||||
Del(l);
|
||||
if (Value)
|
||||
Add(new cSetupLine(Name, Value, Plugin));
|
||||
}
|
||||
}
|
||||
|
||||
void cSetup::Store(const char *Name, int Value, const char *Plugin)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%d", Value);
|
||||
Store(Name, buffer, Plugin);
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
bool cSetup::Load(const char *FileName)
|
||||
{
|
||||
if (cConfig<cSetupLine>::Load(FileName, true)) {
|
||||
bool result = true;
|
||||
for (cSetupLine *l = First(); l; l = Next(l)) {
|
||||
if (l->Plugin()) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(l->Plugin());
|
||||
if (p && !p->SetupParse(l->Name(), l->Value()))
|
||||
result = false;
|
||||
}
|
||||
else {
|
||||
if (!Parse(l->Name(), l->Value()))
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cSetup::StoreCaCaps(const char *Name)
|
||||
{
|
||||
for (int d = 0; d < MAXDVBAPI; d++) {
|
||||
int written = 0;
|
||||
char buffer[MAXPARSEBUFFER];
|
||||
char *q = buffer;
|
||||
*buffer = 0;
|
||||
for (int i = 0; i < MAXCACAPS; i++) {
|
||||
if (CaCaps[d][i]) {
|
||||
if (!written++)
|
||||
fprintf(f, "CaCaps = %d", d + 1);
|
||||
fprintf(f, " %d", CaCaps[d][i]);
|
||||
if (!*buffer)
|
||||
q += snprintf(buffer, sizeof(buffer), "%d", d + 1);
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), " %d", CaCaps[d][i]);
|
||||
}
|
||||
}
|
||||
if (written)
|
||||
fprintf(f, "\n");
|
||||
if (*buffer)
|
||||
Store(Name, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1003,142 +1129,99 @@ bool cSetup::ParseCaCaps(const char *Value)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSetup::Parse(char *s)
|
||||
bool cSetup::Parse(const char *Name, const char *Value)
|
||||
{
|
||||
char *p = strchr(s, '=');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
char *Name = compactspace(s);
|
||||
char *Value = compactspace(p + 1);
|
||||
if (*Name && *Value) {
|
||||
if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
|
||||
else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
|
||||
else if (!strcasecmp(Name, "NameInstantRecord")) strn0cpy(NameInstantRecord, Value, MaxFileName);
|
||||
else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value);
|
||||
else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
|
||||
else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DiSEqC")) DiSEqC = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value);
|
||||
else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "UseSubtitle")) UseSubtitle = atoi(Value);
|
||||
else if (!strcasecmp(Name, "RecordingDirs")) RecordingDirs = atoi(Value);
|
||||
else if (!strcasecmp(Name, "VideoFormat")) VideoFormat = atoi(Value);
|
||||
else if (!strcasecmp(Name, "RecordDolbyDigital")) RecordDolbyDigital = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MultiSpeedMode")) MultiSpeedMode = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ShowReplayMode")) ShowReplayMode = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CaCaps")) return ParseCaCaps(Value);
|
||||
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSetup::Load(const char *FileName)
|
||||
{
|
||||
isyslog(LOG_INFO, "loading %s", FileName);
|
||||
delete fileName;
|
||||
fileName = strdup(FileName);
|
||||
FILE *f = fopen(fileName, "r");
|
||||
if (f) {
|
||||
int line = 0;
|
||||
char buffer[MAXPARSEBUFFER];
|
||||
bool result = true;
|
||||
while (fgets(buffer, sizeof(buffer), f) > 0) {
|
||||
line++;
|
||||
stripspace(buffer);
|
||||
if (!isempty(buffer)) {
|
||||
if (*buffer != '#' && !Parse(buffer)) {
|
||||
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
|
||||
else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
|
||||
else if (!strcasecmp(Name, "NameInstantRecord")) strn0cpy(NameInstantRecord, Value, MaxFileName);
|
||||
else if (!strcasecmp(Name, "InstantRecordTime")) InstantRecordTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value);
|
||||
else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
|
||||
else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DiSEqC")) DiSEqC = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value);
|
||||
else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "UseSubtitle")) UseSubtitle = atoi(Value);
|
||||
else if (!strcasecmp(Name, "RecordingDirs")) RecordingDirs = atoi(Value);
|
||||
else if (!strcasecmp(Name, "VideoFormat")) VideoFormat = atoi(Value);
|
||||
else if (!strcasecmp(Name, "RecordDolbyDigital")) RecordDolbyDigital = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MultiSpeedMode")) MultiSpeedMode = atoi(Value);
|
||||
else if (!strcasecmp(Name, "ShowReplayMode")) ShowReplayMode = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CaCaps")) return ParseCaCaps(Value);
|
||||
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value);
|
||||
else
|
||||
LOG_ERROR_STR(FileName);
|
||||
return false;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSetup::Save(const char *FileName)
|
||||
bool cSetup::Save(void)
|
||||
{
|
||||
if (!FileName)
|
||||
FileName = fileName;
|
||||
if (FileName) {
|
||||
cSafeFile f(FileName);
|
||||
if (f.Open()) {
|
||||
fprintf(f, "# VDR Setup\n");
|
||||
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
|
||||
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
|
||||
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
|
||||
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
|
||||
fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
|
||||
fprintf(f, "NameInstantRecord = %s\n", NameInstantRecord);
|
||||
fprintf(f, "LnbSLOF = %d\n", LnbSLOF);
|
||||
fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
|
||||
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
|
||||
fprintf(f, "DiSEqC = %d\n", DiSEqC);
|
||||
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
|
||||
fprintf(f, "TimeTransponder = %d\n", TimeTransponder);
|
||||
fprintf(f, "MarginStart = %d\n", MarginStart);
|
||||
fprintf(f, "MarginStop = %d\n", MarginStop);
|
||||
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
|
||||
fprintf(f, "EPGBugfixLevel = %d\n", EPGBugfixLevel);
|
||||
fprintf(f, "SVDRPTimeout = %d\n", SVDRPTimeout);
|
||||
fprintf(f, "SortTimers = %d\n", SortTimers);
|
||||
fprintf(f, "PrimaryLimit = %d\n", PrimaryLimit);
|
||||
fprintf(f, "DefaultPriority = %d\n", DefaultPriority);
|
||||
fprintf(f, "DefaultLifetime = %d\n", DefaultLifetime);
|
||||
fprintf(f, "UseSubtitle = %d\n", UseSubtitle);
|
||||
fprintf(f, "RecordingDirs = %d\n", RecordingDirs);
|
||||
fprintf(f, "VideoFormat = %d\n", VideoFormat);
|
||||
fprintf(f, "RecordDolbyDigital = %d\n", RecordDolbyDigital);
|
||||
fprintf(f, "ChannelInfoPos = %d\n", ChannelInfoPos);
|
||||
fprintf(f, "OSDwidth = %d\n", OSDwidth);
|
||||
fprintf(f, "OSDheight = %d\n", OSDheight);
|
||||
fprintf(f, "OSDMessageTime = %d\n", OSDMessageTime);
|
||||
fprintf(f, "MaxVideoFileSize = %d\n", MaxVideoFileSize);
|
||||
fprintf(f, "SplitEditedFiles = %d\n", SplitEditedFiles);
|
||||
fprintf(f, "MinEventTimeout = %d\n", MinEventTimeout);
|
||||
fprintf(f, "MinUserInactivity = %d\n", MinUserInactivity);
|
||||
fprintf(f, "MultiSpeedMode = %d\n", MultiSpeedMode);
|
||||
fprintf(f, "ShowReplayMode = %d\n", ShowReplayMode);
|
||||
PrintCaCaps(f, "CaCaps");
|
||||
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
|
||||
fprintf(f, "CurrentVolume = %d\n", CurrentVolume);
|
||||
if (f.Close()) {
|
||||
isyslog(LOG_INFO, "saved setup to %s", FileName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Store("OSDLanguage", OSDLanguage);
|
||||
Store("PrimaryDVB", PrimaryDVB);
|
||||
Store("ShowInfoOnChSwitch", ShowInfoOnChSwitch);
|
||||
Store("MenuScrollPage", MenuScrollPage);
|
||||
Store("MarkInstantRecord", MarkInstantRecord);
|
||||
Store("NameInstantRecord", NameInstantRecord);
|
||||
Store("InstantRecordTime", InstantRecordTime);
|
||||
Store("LnbSLOF", LnbSLOF);
|
||||
Store("LnbFrequLo", LnbFrequLo);
|
||||
Store("LnbFrequHi", LnbFrequHi);
|
||||
Store("DiSEqC", DiSEqC);
|
||||
Store("SetSystemTime", SetSystemTime);
|
||||
Store("TimeTransponder", TimeTransponder);
|
||||
Store("MarginStart", MarginStart);
|
||||
Store("MarginStop", MarginStop);
|
||||
Store("EPGScanTimeout", EPGScanTimeout);
|
||||
Store("EPGBugfixLevel", EPGBugfixLevel);
|
||||
Store("SVDRPTimeout", SVDRPTimeout);
|
||||
Store("SortTimers", SortTimers);
|
||||
Store("PrimaryLimit", PrimaryLimit);
|
||||
Store("DefaultPriority", DefaultPriority);
|
||||
Store("DefaultLifetime", DefaultLifetime);
|
||||
Store("UseSubtitle", UseSubtitle);
|
||||
Store("RecordingDirs", RecordingDirs);
|
||||
Store("VideoFormat", VideoFormat);
|
||||
Store("RecordDolbyDigital", RecordDolbyDigital);
|
||||
Store("ChannelInfoPos", ChannelInfoPos);
|
||||
Store("OSDwidth", OSDwidth);
|
||||
Store("OSDheight", OSDheight);
|
||||
Store("OSDMessageTime", OSDMessageTime);
|
||||
Store("MaxVideoFileSize", MaxVideoFileSize);
|
||||
Store("SplitEditedFiles", SplitEditedFiles);
|
||||
Store("MinEventTimeout", MinEventTimeout);
|
||||
Store("MinUserInactivity", MinUserInactivity);
|
||||
Store("MultiSpeedMode", MultiSpeedMode);
|
||||
Store("ShowReplayMode", ShowReplayMode);
|
||||
StoreCaCaps("CaCaps");
|
||||
Store("CurrentChannel", CurrentChannel);
|
||||
Store("CurrentVolume", CurrentVolume);
|
||||
|
||||
Sort();
|
||||
|
||||
if (cConfig<cSetupLine>::Save()) {
|
||||
isyslog(LOG_INFO, "saved setup to %s", FileName());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "attempt to save setup without file name");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
43
config.h
43
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.109 2002/04/07 13:08:12 kls Exp $
|
||||
* $Id: config.h 1.113 2002/05/04 14:29:29 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,7 +19,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.0.0"
|
||||
#define VDRVERSION "1.1.0"
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
@ -149,7 +149,7 @@ public:
|
||||
cTimer(const cEventInfo *EventInfo);
|
||||
virtual ~cTimer();
|
||||
cTimer& operator= (const cTimer &Timer);
|
||||
bool operator< (const cTimer &Timer);
|
||||
virtual bool operator< (const cListObject &ListObject);
|
||||
const char *ToText(void);
|
||||
bool Parse(const char *s);
|
||||
bool Save(FILE *f);
|
||||
@ -220,7 +220,8 @@ private:
|
||||
public:
|
||||
cConfig(void) { fileName = NULL; }
|
||||
virtual ~cConfig() { delete fileName; }
|
||||
virtual bool Load(const char *FileName, bool AllowComments = false)
|
||||
const char *FileName(void) { return fileName; }
|
||||
bool Load(const char *FileName, bool AllowComments = false)
|
||||
{
|
||||
Clear();
|
||||
fileName = strdup(FileName);
|
||||
@ -323,20 +324,42 @@ extern cCommands Commands;
|
||||
extern cSVDRPhosts SVDRPhosts;
|
||||
extern cCaDefinitions CaDefinitions;
|
||||
|
||||
class cSetup {
|
||||
class cSetupLine : public cListObject {
|
||||
private:
|
||||
static char *fileName;
|
||||
void PrintCaCaps(FILE *f, const char *Name);
|
||||
bool ParseCaCaps(const char *Value);
|
||||
char *plugin;
|
||||
char *name;
|
||||
char *value;
|
||||
public:
|
||||
cSetupLine(void);
|
||||
cSetupLine(const char *Name, const char *Value, const char *Plugin = NULL);
|
||||
virtual ~cSetupLine();
|
||||
virtual bool operator< (const cListObject &ListObject);
|
||||
const char *Plugin(void) { return plugin; }
|
||||
const char *Name(void) { return name; }
|
||||
const char *Value(void) { return value; }
|
||||
bool Parse(char *s);
|
||||
bool Save(FILE *f);
|
||||
};
|
||||
|
||||
class cSetup : public cConfig<cSetupLine> {
|
||||
friend class cPlugin; // needs to be able to call Store()
|
||||
private:
|
||||
void StoreCaCaps(const char *Name);
|
||||
bool ParseCaCaps(const char *Value);
|
||||
bool Parse(const char *Name, const char *Value);
|
||||
cSetupLine *Get(const char *Name, const char *Plugin = NULL);
|
||||
void Store(const char *Name, const char *Value, const char *Plugin = NULL);
|
||||
void Store(const char *Name, int Value, const char *Plugin = NULL);
|
||||
public:
|
||||
// Also adjust cMenuSetup (menu.c) when adding parameters here!
|
||||
int __BeginData__;
|
||||
int OSDLanguage;
|
||||
int PrimaryDVB;
|
||||
int ShowInfoOnChSwitch;
|
||||
int MenuScrollPage;
|
||||
int MarkInstantRecord;
|
||||
char NameInstantRecord[MaxFileName];
|
||||
int InstantRecordTime;
|
||||
int LnbSLOF;
|
||||
int LnbFrequLo;
|
||||
int LnbFrequHi;
|
||||
@ -365,9 +388,11 @@ public:
|
||||
int CaCaps[MAXDVBAPI][MAXCACAPS];
|
||||
int CurrentChannel;
|
||||
int CurrentVolume;
|
||||
int __EndData__;
|
||||
cSetup(void);
|
||||
cSetup& operator= (const cSetup &s);
|
||||
bool Load(const char *FileName);
|
||||
bool Save(const char *FileName = NULL);
|
||||
bool Save(void);
|
||||
};
|
||||
|
||||
extern cSetup Setup;
|
||||
|
33
dvbapi.c
33
dvbapi.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbapi.c 1.170 2002/04/07 09:35:51 kls Exp $
|
||||
* $Id: dvbapi.c 1.174 2002/05/03 15:59:32 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbapi.h"
|
||||
@ -279,8 +279,7 @@ bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *Pictu
|
||||
int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *FileOffset, int *Length, bool StayOffEnd)
|
||||
{
|
||||
if (index) {
|
||||
if (Forward)
|
||||
CatchUp();
|
||||
CatchUp();
|
||||
int d = Forward ? 1 : -1;
|
||||
for (;;) {
|
||||
Index += d;
|
||||
@ -533,6 +532,8 @@ void cRecordBuffer::Input(void)
|
||||
int w = Put(p, r);
|
||||
p += w;
|
||||
r -= w;
|
||||
if (r > 0)
|
||||
usleep(1); // this keeps the CPU load low
|
||||
}
|
||||
t = time(NULL);
|
||||
}
|
||||
@ -1810,21 +1811,24 @@ bool cDvbApi::SetPrimaryDvbApi(int n)
|
||||
return false;
|
||||
}
|
||||
|
||||
int cDvbApi::CanShift(int Ca, int Priority)
|
||||
int cDvbApi::CanShift(int Ca, int Priority, int UsedCards)
|
||||
{
|
||||
// Test whether a recording on this DVB device can be shifted to another one
|
||||
// in order to perform a new recording with the given Ca and Priority on this device:
|
||||
int ShiftLevel = -1; // default means this device can't be shifted
|
||||
if (UsedCards & (1 << CardIndex()) != 0)
|
||||
return ShiftLevel; // otherwise we would get into a loop
|
||||
if (Recording()) {
|
||||
if (ProvidesCa(Ca) // this device provides the requested Ca
|
||||
&& (Ca != this->Ca() // the requested Ca is different from the one currently used...
|
||||
|| Priority > this->Priority())) { // ...or the request comes from a higher priority
|
||||
cDvbApi *d = NULL;
|
||||
int Provides[MAXDVBAPI];
|
||||
UsedCards |= (1 << CardIndex());
|
||||
for (int i = 0; i < NumDvbApis; i++) {
|
||||
if ((Provides[i] = dvbApi[i]->ProvidesCa(this->Ca())) != 0) { // this device is basicly able to do the job
|
||||
if (dvbApi[i] != this) { // it is not _this_ device
|
||||
int sl = dvbApi[i]->CanShift(this->Ca(), Priority); // this is the original Priority!
|
||||
int sl = dvbApi[i]->CanShift(this->Ca(), Priority, UsedCards); // this is the original Priority!
|
||||
if (sl >= 0 && (ShiftLevel < 0 || sl < ShiftLevel)) {
|
||||
d = dvbApi[i];
|
||||
ShiftLevel = sl;
|
||||
@ -2301,16 +2305,17 @@ bool cDvbApi::SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output)
|
||||
{
|
||||
if (Pid) {
|
||||
CHECK(ioctl(fd, DMX_STOP));
|
||||
dmxPesFilterParams pesFilterParams;
|
||||
pesFilterParams.pid = Pid;
|
||||
pesFilterParams.input = DMX_IN_FRONTEND;
|
||||
pesFilterParams.output = Output;
|
||||
pesFilterParams.pesType = PesType;
|
||||
pesFilterParams.flags = DMX_IMMEDIATE_START;
|
||||
if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
|
||||
if (Pid != 0x1FFF)
|
||||
if (Pid != 0x1FFF) {
|
||||
dmxPesFilterParams pesFilterParams;
|
||||
pesFilterParams.pid = Pid;
|
||||
pesFilterParams.input = DMX_IN_FRONTEND;
|
||||
pesFilterParams.output = Output;
|
||||
pesFilterParams.pesType = PesType;
|
||||
pesFilterParams.flags = DMX_IMMEDIATE_START;
|
||||
if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
|
||||
LOG_ERROR;
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
4
dvbapi.h
4
dvbapi.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbapi.h 1.68 2002/03/10 10:50:00 kls Exp $
|
||||
* $Id: dvbapi.h 1.69 2002/04/21 09:49:22 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBAPI_H
|
||||
@ -104,7 +104,7 @@ private:
|
||||
static int useDvbApi;
|
||||
int cardIndex;
|
||||
int caCaps[MAXCACAPS];
|
||||
int CanShift(int Ca, int Priority);
|
||||
int CanShift(int Ca, int Priority, int UsedCards = 0);
|
||||
public:
|
||||
static cDvbApi *PrimaryDvbApi;
|
||||
static void SetUseDvbApi(int n);
|
||||
|
5
dvbosd.c
5
dvbosd.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbosd.c 1.12 2002/01/13 16:25:18 kls Exp $
|
||||
* $Id: dvbosd.c 1.13 2002/04/13 11:34:48 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbosd.h"
|
||||
@ -25,6 +25,9 @@ cPalette::cPalette(int Bpp)
|
||||
|
||||
int cPalette::Index(eDvbColor Color)
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
Color = eDvbColor(((Color & 0xFF) << 24) | ((Color & 0xFF00) << 8) | ((Color & 0xFF0000) >> 8) | ((Color & 0xFF000000) >> 24));
|
||||
#endif
|
||||
for (int i = 0; i < numColors; i++) {
|
||||
if (color[i] == Color) {
|
||||
used[i] = true;
|
||||
|
20
i18n.h
20
i18n.h
@ -4,16 +4,28 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.h 1.1 2000/11/11 09:27:25 kls Exp $
|
||||
* $Id: i18n.h 1.2 2002/05/05 13:42:31 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __I18N_H
|
||||
#define __I18N_H
|
||||
|
||||
extern const int NumLanguages;
|
||||
#include <stdio.h>
|
||||
|
||||
const char *tr(const char *s);
|
||||
const int I18nNumLanguages = 12;
|
||||
|
||||
const char * const * Languages(void);
|
||||
typedef const char *tI18nPhrase[I18nNumLanguages];
|
||||
|
||||
void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin);
|
||||
|
||||
const char *I18nTranslate(const char *s, const char *Plugin = NULL);
|
||||
|
||||
const char * const * I18nLanguages(void);
|
||||
|
||||
#ifdef PLUGIN_NAME_I18N
|
||||
#define tr(s) I18nTranslate(s, PLUGIN_NAME_I18N)
|
||||
#else
|
||||
#define tr(s) I18nTranslate(s)
|
||||
#endif
|
||||
|
||||
#endif //__I18N_H
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.24 2001/09/01 15:14:50 kls Exp $
|
||||
* $Id: interface.h 1.25 2002/04/19 13:17:15 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
@ -46,6 +46,7 @@ public:
|
||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||
void Flush(void);
|
||||
void SetCols(int *c);
|
||||
const int *GetCols(void) { return cols; }
|
||||
eDvbFont SetFont(eDvbFont Font);
|
||||
char *WrapText(const char *Text, int Width, int *Height);
|
||||
void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
|
611
menu.c
611
menu.c
@ -4,10 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.182 2002/04/06 09:41:59 kls Exp $
|
||||
* $Id: menu.c 1.190 2002/05/09 10:13:47 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -15,134 +16,19 @@
|
||||
#include "config.h"
|
||||
#include "eit.h"
|
||||
#include "i18n.h"
|
||||
#include "menuitems.h"
|
||||
#include "plugin.h"
|
||||
#include "videodir.h"
|
||||
|
||||
#define MENUTIMEOUT 120 // seconds
|
||||
#define MAXWAIT4EPGINFO 10 // seconds
|
||||
#define MODETIMEOUT 3 // seconds
|
||||
|
||||
#define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
|
||||
|
||||
#define CHNUMWIDTH (Channels.Count() > 999 ? 5 : 4) // there are people with more than 999 channels...
|
||||
|
||||
const char *FileNameChars = " aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-.#~^";
|
||||
|
||||
// --- cMenuEditItem ---------------------------------------------------------
|
||||
|
||||
class cMenuEditItem : public cOsdItem {
|
||||
private:
|
||||
const char *name;
|
||||
const char *value;
|
||||
public:
|
||||
cMenuEditItem(const char *Name);
|
||||
~cMenuEditItem();
|
||||
void SetValue(const char *Value);
|
||||
};
|
||||
|
||||
cMenuEditItem::cMenuEditItem(const char *Name)
|
||||
{
|
||||
name = strdup(Name);
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
cMenuEditItem::~cMenuEditItem()
|
||||
{
|
||||
delete name;
|
||||
delete value;
|
||||
}
|
||||
|
||||
void cMenuEditItem::SetValue(const char *Value)
|
||||
{
|
||||
delete value;
|
||||
value = strdup(Value);
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s:\t%s", name, value);
|
||||
SetText(buffer, false);
|
||||
Display();
|
||||
}
|
||||
|
||||
// --- cMenuEditIntItem ------------------------------------------------------
|
||||
|
||||
class cMenuEditIntItem : public cMenuEditItem {
|
||||
protected:
|
||||
int *value;
|
||||
int min, max;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
min = Min;
|
||||
max = Max;
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditIntItem::Set(void)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", *value);
|
||||
SetValue(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
int newValue;
|
||||
if (k0 <= Key && Key <= k9) {
|
||||
if (fresh) {
|
||||
*value = 0;
|
||||
fresh = false;
|
||||
}
|
||||
newValue = *value * 10 + (Key - k0);
|
||||
}
|
||||
else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
|
||||
newValue = *value - 1;
|
||||
fresh = true;
|
||||
}
|
||||
else if (NORMALKEY(Key) == kRight) {
|
||||
newValue = *value + 1;
|
||||
fresh = true;
|
||||
}
|
||||
else
|
||||
return state;
|
||||
if ((!fresh || min <= newValue) && newValue <= max) {
|
||||
*value = newValue;
|
||||
Set();
|
||||
}
|
||||
state = osContinue;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuEditBoolItem -----------------------------------------------------
|
||||
|
||||
class cMenuEditBoolItem : public cMenuEditIntItem {
|
||||
protected:
|
||||
const char *falseString, *trueString;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL);
|
||||
};
|
||||
|
||||
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
|
||||
:cMenuEditIntItem(Name, Value, 0, 1)
|
||||
{
|
||||
falseString = FalseString ? FalseString : tr("no");
|
||||
trueString = TrueString ? TrueString : tr("yes");
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditBoolItem::Set(void)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
|
||||
SetValue(buf);
|
||||
}
|
||||
const char *FileNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-.#~";
|
||||
|
||||
// --- cMenuEditChanItem -----------------------------------------------------
|
||||
|
||||
@ -448,186 +334,6 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key)
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuEditChrItem ------------------------------------------------------
|
||||
|
||||
class cMenuEditChrItem : public cMenuEditItem {
|
||||
private:
|
||||
char *value;
|
||||
const char *allowed;
|
||||
const char *current;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
|
||||
~cMenuEditChrItem();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
allowed = strdup(Allowed);
|
||||
current = strchr(allowed, *Value);
|
||||
if (!current)
|
||||
current = allowed;
|
||||
Set();
|
||||
}
|
||||
|
||||
cMenuEditChrItem::~cMenuEditChrItem()
|
||||
{
|
||||
delete allowed;
|
||||
}
|
||||
|
||||
void cMenuEditChrItem::Set(void)
|
||||
{
|
||||
char buf[2];
|
||||
snprintf(buf, sizeof(buf), "%c", *value);
|
||||
SetValue(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
if (NORMALKEY(Key) == kLeft) {
|
||||
if (current > allowed)
|
||||
current--;
|
||||
}
|
||||
else if (NORMALKEY(Key) == kRight) {
|
||||
if (*(current + 1))
|
||||
current++;
|
||||
}
|
||||
else
|
||||
return state;
|
||||
*value = *current;
|
||||
Set();
|
||||
state = osContinue;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuEditStrItem ------------------------------------------------------
|
||||
|
||||
class cMenuEditStrItem : public cMenuEditItem {
|
||||
private:
|
||||
char *value;
|
||||
int length;
|
||||
const char *allowed;
|
||||
int pos;
|
||||
virtual void Set(void);
|
||||
char Inc(char c, bool Up);
|
||||
public:
|
||||
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
|
||||
~cMenuEditStrItem();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
length = Length;
|
||||
allowed = strdup(Allowed);
|
||||
pos = -1;
|
||||
Set();
|
||||
}
|
||||
|
||||
cMenuEditStrItem::~cMenuEditStrItem()
|
||||
{
|
||||
delete allowed;
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::Set(void)
|
||||
{
|
||||
char buf[1000];
|
||||
if (pos >= 0) {
|
||||
strncpy(buf, value, pos);
|
||||
const char *s = value[pos] != '^' ? value + pos + 1 : "";
|
||||
snprintf(buf + pos, sizeof(buf) - pos - 2, "[%c]%s", *(value + pos), s);
|
||||
SetValue(buf);
|
||||
}
|
||||
else
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
char cMenuEditStrItem::Inc(char c, bool Up)
|
||||
{
|
||||
const char *p = strchr(allowed, c);
|
||||
if (!p)
|
||||
p = allowed;
|
||||
if (Up) {
|
||||
if (!*++p)
|
||||
p = allowed;
|
||||
}
|
||||
else if (--p < allowed)
|
||||
p = allowed + strlen(allowed) - 1;
|
||||
return *p;
|
||||
}
|
||||
|
||||
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft: if (pos > 0) {
|
||||
if (value[pos] == '^')
|
||||
value[pos] = 0;
|
||||
pos--;
|
||||
}
|
||||
break;
|
||||
case kRight|k_Repeat:
|
||||
case kRight: if (pos < length && value[pos] != '^' && (pos < int(strlen(value) - 1) || value[pos] != ' ')) {
|
||||
if (++pos >= int(strlen(value))) {
|
||||
value[pos] = ' ';
|
||||
value[pos + 1] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kUp|k_Repeat:
|
||||
case kUp:
|
||||
case kDown|k_Repeat:
|
||||
case kDown: if (pos >= 0)
|
||||
value[pos] = Inc(value[pos], NORMALKEY(Key) == kUp);
|
||||
else
|
||||
return cMenuEditItem::ProcessKey(Key);
|
||||
break;
|
||||
case kOk: if (pos >= 0) {
|
||||
if (value[pos] == '^')
|
||||
value[pos] = 0;
|
||||
pos = -1;
|
||||
stripspace(value);
|
||||
break;
|
||||
}
|
||||
// run into default
|
||||
default: return cMenuEditItem::ProcessKey(Key);
|
||||
}
|
||||
Set();
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
// --- cMenuEditStraItem -----------------------------------------------------
|
||||
|
||||
class cMenuEditStraItem : public cMenuEditIntItem {
|
||||
private:
|
||||
const char * const *strings;
|
||||
protected:
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings);
|
||||
};
|
||||
|
||||
cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
|
||||
:cMenuEditIntItem(Name, Value, 0, NumStrings - 1)
|
||||
{
|
||||
strings = Strings;
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditStraItem::Set(void)
|
||||
{
|
||||
SetValue(strings[*value]);
|
||||
}
|
||||
|
||||
// --- cMenuEditCaItem -------------------------------------------------------
|
||||
|
||||
class cMenuEditCaItem : public cMenuEditIntItem {
|
||||
@ -699,7 +405,7 @@ cMenuEditChannel::cMenuEditChannel(int Index)
|
||||
channel = Channels.Get(Index);
|
||||
if (channel) {
|
||||
data = *channel;
|
||||
Add(new cMenuEditStrItem( tr("Name"), data.name, sizeof(data.name), FileNameChars));
|
||||
Add(new cMenuEditStrItem( tr("Name"), data.name, sizeof(data.name), tr(FileNameChars)));
|
||||
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency));
|
||||
Add(new cMenuEditChrItem( tr("Polarization"), &data.polarization, "hv"));
|
||||
Add(new cMenuEditIntItem( tr("DiSEqC"), &data.diseqc, 0, 10)); //TODO exact limits???
|
||||
@ -919,116 +625,6 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuTextItem ---------------------------------------------------------
|
||||
|
||||
class cMenuTextItem : public cOsdItem {
|
||||
private:
|
||||
char *text;
|
||||
int x, y, w, h, lines, offset;
|
||||
eDvbColor fgColor, bgColor;
|
||||
eDvbFont font;
|
||||
public:
|
||||
cMenuTextItem(const char *Text, int X, int Y, int W, int H = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground, eDvbFont Font = fontOsd);
|
||||
~cMenuTextItem();
|
||||
int Height(void) { return h; }
|
||||
void Clear(void);
|
||||
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
bool CanScrollUp(void) { return offset > 0; }
|
||||
bool CanScrollDown(void) { return h + offset < lines; }
|
||||
void ScrollUp(bool Page);
|
||||
void ScrollDown(bool Page);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuTextItem::cMenuTextItem(const char *Text, int X, int Y, int W, int H, eDvbColor FgColor, eDvbColor BgColor, eDvbFont Font)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
fgColor = FgColor;
|
||||
bgColor = BgColor;
|
||||
font = Font;
|
||||
offset = 0;
|
||||
eDvbFont oldFont = Interface->SetFont(font);
|
||||
text = Interface->WrapText(Text, w - 1, &lines);
|
||||
Interface->SetFont(oldFont);
|
||||
if (h < 0)
|
||||
h = lines;
|
||||
}
|
||||
|
||||
cMenuTextItem::~cMenuTextItem()
|
||||
{
|
||||
delete text;
|
||||
}
|
||||
|
||||
void cMenuTextItem::Clear(void)
|
||||
{
|
||||
Interface->Fill(x, y, w, h, bgColor);
|
||||
}
|
||||
|
||||
void cMenuTextItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
int l = 0;
|
||||
char *t = text;
|
||||
eDvbFont oldFont = Interface->SetFont(font);
|
||||
while (*t) {
|
||||
char *n = strchr(t, '\n');
|
||||
if (l >= offset) {
|
||||
if (n)
|
||||
*n = 0;
|
||||
Interface->Write(x, y + l - offset, t, fgColor, bgColor);
|
||||
if (n)
|
||||
*n = '\n';
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!n)
|
||||
break;
|
||||
t = n + 1;
|
||||
if (++l >= h + offset)
|
||||
break;
|
||||
}
|
||||
Interface->SetFont(oldFont);
|
||||
// scroll indicators use inverted color scheme!
|
||||
if (CanScrollUp()) Interface->Write(x + w - 1, y, "^", bgColor, fgColor);
|
||||
if (CanScrollDown()) Interface->Write(x + w - 1, y + h - 1, "v", bgColor, fgColor);
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollUp(bool Page)
|
||||
{
|
||||
if (CanScrollUp()) {
|
||||
Clear();
|
||||
offset = max(offset - (Page ? h : 1), 0);
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollDown(bool Page)
|
||||
{
|
||||
if (CanScrollDown()) {
|
||||
Clear();
|
||||
offset = min(offset + (Page ? h : 1), lines - h);
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
eOSState cMenuTextItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kUp|k_Repeat:
|
||||
case kUp: ScrollUp(NORMALKEY(Key) == kLeft); break;
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
case kDown|k_Repeat:
|
||||
case kDown: ScrollDown(NORMALKEY(Key) == kRight); break;
|
||||
default: return osUnknown;
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
// --- cMenuText -------------------------------------------------------------
|
||||
|
||||
class cMenuText : public cOsdMenu {
|
||||
@ -1086,7 +682,7 @@ cMenuEditTimer::cMenuEditTimer(int Index, bool New)
|
||||
//TODO VPS???
|
||||
Add(new cMenuEditIntItem( tr("Priority"), &data.priority, 0, MAXPRIORITY));
|
||||
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME));
|
||||
Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), FileNameChars));
|
||||
Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), tr(FileNameChars)));
|
||||
SetFirstDayItem();
|
||||
}
|
||||
}
|
||||
@ -1929,60 +1525,6 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuSetupPage --------------------------------------------------------
|
||||
|
||||
class cMenuSetupPage : public cOsdMenu {
|
||||
protected:
|
||||
cSetup data;
|
||||
int osdLanguage;
|
||||
void SetupTitle(const char *s);
|
||||
virtual void Set(void) = 0;
|
||||
public:
|
||||
cMenuSetupPage(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuSetupPage::cMenuSetupPage(void)
|
||||
:cOsdMenu("", 33)
|
||||
{
|
||||
data = Setup;
|
||||
osdLanguage = Setup.OSDLanguage;
|
||||
}
|
||||
|
||||
void cMenuSetupPage::SetupTitle(const char *s)
|
||||
{
|
||||
char buf[40]; // can't call tr() for more than one string at a time!
|
||||
char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
|
||||
snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
|
||||
SetTitle(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuSetupPage::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
|
||||
cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
|
||||
Setup = data;
|
||||
Setup.Save();
|
||||
cDvbApi::SetCaCaps();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (data.OSDLanguage != osdLanguage) {
|
||||
int OriginalOSDLanguage = Setup.OSDLanguage;
|
||||
Setup.OSDLanguage = data.OSDLanguage;
|
||||
Set();
|
||||
Display();
|
||||
osdLanguage = data.OSDLanguage;
|
||||
Setup.OSDLanguage = OriginalOSDLanguage;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuSetupOSD ---------------------------------------------------------
|
||||
|
||||
class cMenuSetupOSD : public cMenuSetupPage {
|
||||
@ -1996,7 +1538,7 @@ void cMenuSetupOSD::Set(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("OSD");
|
||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Language"), &data.OSDLanguage, NumLanguages, Languages()));
|
||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Language"), &data.OSDLanguage, I18nNumLanguages, I18nLanguages()));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Width"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"), &data.OSDMessageTime, 1, 60));
|
||||
@ -2104,7 +1646,8 @@ void cMenuSetupRecord::Set(void)
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Default lifetime (d)"), &data.DefaultLifetime, 0, MAXLIFETIME));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Use episode name"), &data.UseSubtitle));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Mark instant recording"), &data.MarkInstantRecord));
|
||||
Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"), data.NameInstantRecord, sizeof(data.NameInstantRecord), FileNameChars));
|
||||
Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"), data.NameInstantRecord, sizeof(data.NameInstantRecord), tr(FileNameChars)));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"), &data.InstantRecordTime, 1, MAXINSTANTRECTIME));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Record Dolby Digital"), &data.RecordDolbyDigital));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZE));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"), &data.SplitEditedFiles));
|
||||
@ -2142,7 +1685,76 @@ void cMenuSetupMisc::Set(void)
|
||||
SetupTitle("Miscellaneous");
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"), &data.MinEventTimeout));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (min)"), &data.SVDRPTimeout));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout));
|
||||
}
|
||||
|
||||
// --- cMenuSetupPluginItem --------------------------------------------------
|
||||
|
||||
class cMenuSetupPluginItem : public cOsdItem {
|
||||
private:
|
||||
int pluginIndex;
|
||||
public:
|
||||
cMenuSetupPluginItem(const char *Name, int Index);
|
||||
int PluginIndex(void) { return pluginIndex; }
|
||||
};
|
||||
|
||||
cMenuSetupPluginItem::cMenuSetupPluginItem(const char *Name, int Index)
|
||||
:cOsdItem(Name)
|
||||
{
|
||||
pluginIndex = Index;
|
||||
}
|
||||
|
||||
// --- cMenuSetupPlugins -----------------------------------------------------
|
||||
|
||||
class cMenuSetupPlugins : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuSetupPlugins(void) { Set(); }
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
void cMenuSetupPlugins::Set(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("Plugins");
|
||||
SetHasHotkeys();
|
||||
for (int i = 0; ; i++) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(i);
|
||||
if (p) {
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s (%s) - %s", p->Name(), p->Version(), p->Description());
|
||||
Add(new cMenuSetupPluginItem(hk(buffer), i));
|
||||
delete buffer;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cOsdMenu::ProcessKey(Key); // not cMenuSetupPage::ProcessKey()!
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: {
|
||||
cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
|
||||
if (item) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
||||
if (p) {
|
||||
cOsdMenu *menu = p->SetupMenu();
|
||||
if (menu)
|
||||
return AddSubMenu(menu);
|
||||
Interface->Info(tr("This plugin has no setup parameters!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuSetup ------------------------------------------------------------
|
||||
@ -2165,7 +1777,9 @@ cMenuSetup::cMenuSetup(void)
|
||||
void cMenuSetup::Set(void)
|
||||
{
|
||||
Clear();
|
||||
SetTitle(tr("Setup"));
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "%s - VDR %s", tr("Setup"), VDRVERSION);
|
||||
SetTitle(buffer);
|
||||
SetHasHotkeys();
|
||||
Add(new cOsdItem(hk(tr("OSD")), osUser1));
|
||||
Add(new cOsdItem(hk(tr("EPG")), osUser2));
|
||||
@ -2175,7 +1789,9 @@ void cMenuSetup::Set(void)
|
||||
Add(new cOsdItem(hk(tr("Recording")), osUser6));
|
||||
Add(new cOsdItem(hk(tr("Replay")), osUser7));
|
||||
Add(new cOsdItem(hk(tr("Miscellaneous")), osUser8));
|
||||
Add(new cOsdItem(hk(tr("Restart")), osUser9));
|
||||
if (cPluginManager::HasPlugins())
|
||||
Add(new cOsdItem(hk(tr("Plugins")), osUser9));
|
||||
Add(new cOsdItem(hk(tr("Restart")), osUser10));
|
||||
}
|
||||
|
||||
eOSState cMenuSetup::Restart(void)
|
||||
@ -2201,7 +1817,8 @@ eOSState cMenuSetup::ProcessKey(eKeys Key)
|
||||
case osUser6: return AddSubMenu(new cMenuSetupRecord);
|
||||
case osUser7: return AddSubMenu(new cMenuSetupReplay);
|
||||
case osUser8: return AddSubMenu(new cMenuSetupMisc);
|
||||
case osUser9: return Restart();
|
||||
case osUser9: return AddSubMenu(new cMenuSetupPlugins);
|
||||
case osUser10: return Restart();
|
||||
default: ;
|
||||
}
|
||||
if (Setup.OSDLanguage != osdLanguage) {
|
||||
@ -2264,6 +1881,22 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuPluginItem -------------------------------------------------------
|
||||
|
||||
class cMenuPluginItem : public cOsdItem {
|
||||
private:
|
||||
int pluginIndex;
|
||||
public:
|
||||
cMenuPluginItem(const char *Name, int Index);
|
||||
int PluginIndex(void) { return pluginIndex; }
|
||||
};
|
||||
|
||||
cMenuPluginItem::cMenuPluginItem(const char *Name, int Index)
|
||||
:cOsdItem(Name, osPlugin)
|
||||
{
|
||||
pluginIndex = Index;
|
||||
}
|
||||
|
||||
// --- cMenuMain -------------------------------------------------------------
|
||||
|
||||
#define STOP_RECORDING tr(" Stop recording ")
|
||||
@ -2308,6 +1941,22 @@ void cMenuMain::Set(void)
|
||||
Add(new cOsdItem(hk(tr("Channels")), osChannels));
|
||||
Add(new cOsdItem(hk(tr("Timers")), osTimers));
|
||||
Add(new cOsdItem(hk(tr("Recordings")), osRecordings));
|
||||
|
||||
// Plugins:
|
||||
|
||||
for (int i = 0; ; i++) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(i);
|
||||
if (p) {
|
||||
const char *item = p->MainMenuEntry();
|
||||
if (item)
|
||||
Add(new cMenuPluginItem(hk(item), i));
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// More basic menu items:
|
||||
|
||||
Add(new cOsdItem(hk(tr("Setup")), osSetup));
|
||||
if (Commands.Count())
|
||||
Add(new cOsdItem(hk(tr("Commands")), osCommands));
|
||||
@ -2375,6 +2024,19 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
return osEnd;
|
||||
}
|
||||
break;
|
||||
case osPlugin: {
|
||||
cMenuPluginItem *item = (cMenuPluginItem *)Get(Current());
|
||||
if (item) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
||||
if (p) {
|
||||
cOsdMenu *menu = p->MainMenuAction();
|
||||
if (menu)
|
||||
return AddSubMenu(menu);
|
||||
}
|
||||
}
|
||||
state = osEnd;
|
||||
}
|
||||
break;
|
||||
default: switch (Key) {
|
||||
case kMenu: state = osEnd; break;
|
||||
case kRed: if (!HasSubMenu())
|
||||
@ -3185,6 +2847,7 @@ void cReplayControl::TimeSearch(void)
|
||||
else
|
||||
return;
|
||||
}
|
||||
timeoutShow = 0;
|
||||
TimeSearchDisplay();
|
||||
timeSearchActive = true;
|
||||
}
|
||||
@ -3287,7 +2950,7 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
|
||||
}
|
||||
else if (modeOnly)
|
||||
ShowMode();
|
||||
else
|
||||
else
|
||||
shown = ShowProgress(!shown) || shown;
|
||||
}
|
||||
bool DisplayedFrames = displayFrames;
|
||||
|
8
menu.h
8
menu.h
@ -4,11 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.h 1.41 2002/03/31 13:53:23 kls Exp $
|
||||
* $Id: menu.h 1.42 2002/04/13 15:31:41 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef _MENU_H
|
||||
#define _MENU_H
|
||||
#ifndef __MENU_H
|
||||
#define __MENU_H
|
||||
|
||||
#include "dvbapi.h"
|
||||
#include "osd.h"
|
||||
@ -142,4 +142,4 @@ public:
|
||||
static void ClearLastReplayed(const char *FileName);
|
||||
};
|
||||
|
||||
#endif //_MENU_H
|
||||
#endif //__MENU_H
|
||||
|
476
menuitems.c
Normal file
476
menuitems.c
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* menuitems.c: General purpose menu items
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.c 1.1 2002/05/09 10:10:12 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menuitems.h"
|
||||
#include <ctype.h>
|
||||
#include "i18n.h"
|
||||
|
||||
// --- cMenuEditItem ---------------------------------------------------------
|
||||
|
||||
cMenuEditItem::cMenuEditItem(const char *Name)
|
||||
{
|
||||
name = strdup(Name);
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
cMenuEditItem::~cMenuEditItem()
|
||||
{
|
||||
delete name;
|
||||
delete value;
|
||||
}
|
||||
|
||||
void cMenuEditItem::SetValue(const char *Value)
|
||||
{
|
||||
delete value;
|
||||
value = strdup(Value);
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s:\t%s", name, value);
|
||||
SetText(buffer, false);
|
||||
Display();
|
||||
}
|
||||
|
||||
// --- cMenuEditIntItem ------------------------------------------------------
|
||||
|
||||
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
min = Min;
|
||||
max = Max;
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditIntItem::Set(void)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", *value);
|
||||
SetValue(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
int newValue;
|
||||
if (k0 <= Key && Key <= k9) {
|
||||
if (fresh) {
|
||||
*value = 0;
|
||||
fresh = false;
|
||||
}
|
||||
newValue = *value * 10 + (Key - k0);
|
||||
}
|
||||
else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
|
||||
newValue = *value - 1;
|
||||
fresh = true;
|
||||
}
|
||||
else if (NORMALKEY(Key) == kRight) {
|
||||
newValue = *value + 1;
|
||||
fresh = true;
|
||||
}
|
||||
else
|
||||
return state;
|
||||
if ((!fresh || min <= newValue) && newValue <= max) {
|
||||
*value = newValue;
|
||||
Set();
|
||||
}
|
||||
state = osContinue;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuEditBoolItem -----------------------------------------------------
|
||||
|
||||
cMenuEditBoolItem::cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString, const char *TrueString)
|
||||
:cMenuEditIntItem(Name, Value, 0, 1)
|
||||
{
|
||||
falseString = FalseString ? FalseString : tr("no");
|
||||
trueString = TrueString ? TrueString : tr("yes");
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditBoolItem::Set(void)
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%s", *value ? trueString : falseString);
|
||||
SetValue(buf);
|
||||
}
|
||||
|
||||
// --- cMenuEditChrItem ------------------------------------------------------
|
||||
|
||||
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
allowed = strdup(Allowed);
|
||||
current = strchr(allowed, *Value);
|
||||
if (!current)
|
||||
current = allowed;
|
||||
Set();
|
||||
}
|
||||
|
||||
cMenuEditChrItem::~cMenuEditChrItem()
|
||||
{
|
||||
delete allowed;
|
||||
}
|
||||
|
||||
void cMenuEditChrItem::Set(void)
|
||||
{
|
||||
char buf[2];
|
||||
snprintf(buf, sizeof(buf), "%c", *value);
|
||||
SetValue(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
if (NORMALKEY(Key) == kLeft) {
|
||||
if (current > allowed)
|
||||
current--;
|
||||
}
|
||||
else if (NORMALKEY(Key) == kRight) {
|
||||
if (*(current + 1))
|
||||
current++;
|
||||
}
|
||||
else
|
||||
return state;
|
||||
*value = *current;
|
||||
Set();
|
||||
state = osContinue;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuEditStrItem ------------------------------------------------------
|
||||
|
||||
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
|
||||
:cMenuEditItem(Name)
|
||||
{
|
||||
value = Value;
|
||||
length = Length;
|
||||
allowed = strdup(Allowed);
|
||||
pos = -1;
|
||||
insert = uppercase = false;
|
||||
newchar = true;
|
||||
Set();
|
||||
}
|
||||
|
||||
cMenuEditStrItem::~cMenuEditStrItem()
|
||||
{
|
||||
delete allowed;
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::SetHelpKeys(void)
|
||||
{
|
||||
if (pos >= 0)
|
||||
Interface->Help(tr("ABC/abc"), tr(insert ? "Overwrite" : "Insert"), tr("Delete"));
|
||||
else
|
||||
Interface->Help(NULL);
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::Set(void)
|
||||
{
|
||||
char buf[1000];
|
||||
const char *fmt = insert && newchar ? "[]%c%s" : "[%c]%s";
|
||||
|
||||
if (pos >= 0) {
|
||||
strncpy(buf, value, pos);
|
||||
snprintf(buf + pos, sizeof(buf) - pos - 2, fmt, *(value + pos), value + pos + 1);
|
||||
int width = Interface->Width() - Interface->GetCols()[0];
|
||||
if (cDvbApi::PrimaryDvbApi->WidthInCells(buf) <= width) {
|
||||
// the whole buffer fits on the screen
|
||||
SetValue(buf);
|
||||
return;
|
||||
}
|
||||
width *= cDvbApi::PrimaryDvbApi->CellWidth();
|
||||
width -= cDvbApi::PrimaryDvbApi->Width('>'); // assuming '<' and '>' have the same with
|
||||
int w = 0;
|
||||
int i = 0;
|
||||
int l = strlen(buf);
|
||||
while (i < l && w <= width)
|
||||
w += cDvbApi::PrimaryDvbApi->Width(buf[i++]);
|
||||
if (i >= pos + 4) {
|
||||
// the cursor fits on the screen
|
||||
buf[i - 1] = '>';
|
||||
buf[i] = 0;
|
||||
SetValue(buf);
|
||||
return;
|
||||
}
|
||||
// the cursor doesn't fit on the screen
|
||||
w = 0;
|
||||
if (buf[i = pos + 3]) {
|
||||
buf[i] = '>';
|
||||
buf[i + 1] = 0;
|
||||
}
|
||||
else
|
||||
i--;
|
||||
while (i >= 0 && w <= width)
|
||||
w += cDvbApi::PrimaryDvbApi->Width(buf[i--]);
|
||||
buf[++i] = '<';
|
||||
SetValue(buf + i);
|
||||
}
|
||||
else
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
char cMenuEditStrItem::Inc(char c, bool Up)
|
||||
{
|
||||
const char *p = strchr(allowed, c);
|
||||
if (!p)
|
||||
p = allowed;
|
||||
if (Up) {
|
||||
if (!*++p)
|
||||
p = allowed;
|
||||
}
|
||||
else if (--p < allowed)
|
||||
p = allowed + strlen(allowed) - 1;
|
||||
return *p;
|
||||
}
|
||||
|
||||
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kRed: // Switch between upper- and lowercase characters
|
||||
if (pos >= 0 && (!insert || !newchar)) {
|
||||
uppercase = !uppercase;
|
||||
value[pos] = uppercase ? toupper(value[pos]) : tolower(value[pos]);
|
||||
}
|
||||
break;
|
||||
case kGreen: // Toggle insert/overwrite modes
|
||||
if (pos >= 0) {
|
||||
insert = !insert;
|
||||
newchar = true;
|
||||
}
|
||||
SetHelpKeys();
|
||||
break;
|
||||
case kYellow|k_Repeat:
|
||||
case kYellow: // Remove the character at current position; in insert mode it is the character to the right of cursor
|
||||
if (pos >= 0) {
|
||||
if (strlen(value) > 1) {
|
||||
memmove(value + pos, value + pos + 1, strlen(value) - pos);
|
||||
// reduce position, if we removed the last character
|
||||
if (pos == int(strlen(value)))
|
||||
pos--;
|
||||
}
|
||||
else if (strlen(value) == 1)
|
||||
value[0] = ' '; // This is the last character in the string, replace it with a blank
|
||||
if (isalpha(value[pos]))
|
||||
uppercase = isupper(value[pos]);
|
||||
newchar = true;
|
||||
}
|
||||
break;
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft: if (pos > 0) {
|
||||
if (!insert || newchar)
|
||||
pos--;
|
||||
newchar = true;
|
||||
}
|
||||
if (!insert && isalpha(value[pos]))
|
||||
uppercase = isupper(value[pos]);
|
||||
break;
|
||||
case kRight|k_Repeat:
|
||||
case kRight: if (pos < length && pos < int(strlen(value)) ) {
|
||||
if (++pos >= int(strlen(value))) {
|
||||
if (pos >= 2 && value[pos - 1] == ' ' && value[pos - 2] == ' ')
|
||||
pos--; // allow only two blanks at the end
|
||||
else {
|
||||
value[pos] = ' ';
|
||||
value[pos + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
newchar = true;
|
||||
if (!insert && isalpha(value[pos]))
|
||||
uppercase = isupper(value[pos]);
|
||||
if (pos == 0)
|
||||
SetHelpKeys();
|
||||
break;
|
||||
case kUp|k_Repeat:
|
||||
case kUp:
|
||||
case kDown|k_Repeat:
|
||||
case kDown: if (pos >= 0) {
|
||||
if (insert && newchar) {
|
||||
// create a new character in insert mode
|
||||
if (int(strlen(value)) < length) {
|
||||
memmove(value + pos + 1, value + pos, strlen(value) - pos + 1);
|
||||
value[pos] = ' ';
|
||||
}
|
||||
}
|
||||
if (uppercase)
|
||||
value[pos] = toupper(Inc(tolower(value[pos]), NORMALKEY(Key) == kUp));
|
||||
else
|
||||
value[pos] = Inc( value[pos], NORMALKEY(Key) == kUp);
|
||||
newchar = false;
|
||||
}
|
||||
else
|
||||
return cMenuEditItem::ProcessKey(Key);
|
||||
break;
|
||||
case kOk: if (pos >= 0) {
|
||||
pos = -1;
|
||||
newchar = true;
|
||||
stripspace(value);
|
||||
SetHelpKeys();
|
||||
break;
|
||||
}
|
||||
// run into default
|
||||
default: return cMenuEditItem::ProcessKey(Key);
|
||||
}
|
||||
Set();
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
// --- cMenuEditStraItem -----------------------------------------------------
|
||||
|
||||
cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
|
||||
:cMenuEditIntItem(Name, Value, 0, NumStrings - 1)
|
||||
{
|
||||
strings = Strings;
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuEditStraItem::Set(void)
|
||||
{
|
||||
SetValue(strings[*value]);
|
||||
}
|
||||
|
||||
// --- cMenuTextItem ---------------------------------------------------------
|
||||
|
||||
cMenuTextItem::cMenuTextItem(const char *Text, int X, int Y, int W, int H, eDvbColor FgColor, eDvbColor BgColor, eDvbFont Font)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
w = W;
|
||||
h = H;
|
||||
fgColor = FgColor;
|
||||
bgColor = BgColor;
|
||||
font = Font;
|
||||
offset = 0;
|
||||
eDvbFont oldFont = Interface->SetFont(font);
|
||||
text = Interface->WrapText(Text, w - 1, &lines);
|
||||
Interface->SetFont(oldFont);
|
||||
if (h < 0)
|
||||
h = lines;
|
||||
}
|
||||
|
||||
cMenuTextItem::~cMenuTextItem()
|
||||
{
|
||||
delete text;
|
||||
}
|
||||
|
||||
void cMenuTextItem::Clear(void)
|
||||
{
|
||||
Interface->Fill(x, y, w, h, bgColor);
|
||||
}
|
||||
|
||||
void cMenuTextItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
int l = 0;
|
||||
char *t = text;
|
||||
eDvbFont oldFont = Interface->SetFont(font);
|
||||
while (*t) {
|
||||
char *n = strchr(t, '\n');
|
||||
if (l >= offset) {
|
||||
if (n)
|
||||
*n = 0;
|
||||
Interface->Write(x, y + l - offset, t, fgColor, bgColor);
|
||||
if (n)
|
||||
*n = '\n';
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!n)
|
||||
break;
|
||||
t = n + 1;
|
||||
if (++l >= h + offset)
|
||||
break;
|
||||
}
|
||||
Interface->SetFont(oldFont);
|
||||
// scroll indicators use inverted color scheme!
|
||||
if (CanScrollUp()) Interface->Write(x + w - 1, y, "^", bgColor, fgColor);
|
||||
if (CanScrollDown()) Interface->Write(x + w - 1, y + h - 1, "v", bgColor, fgColor);
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollUp(bool Page)
|
||||
{
|
||||
if (CanScrollUp()) {
|
||||
Clear();
|
||||
offset = max(offset - (Page ? h : 1), 0);
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
void cMenuTextItem::ScrollDown(bool Page)
|
||||
{
|
||||
if (CanScrollDown()) {
|
||||
Clear();
|
||||
offset = min(offset + (Page ? h : 1), lines - h);
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
eOSState cMenuTextItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kUp|k_Repeat:
|
||||
case kUp: ScrollUp(NORMALKEY(Key) == kLeft); break;
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
case kDown|k_Repeat:
|
||||
case kDown: ScrollDown(NORMALKEY(Key) == kRight); break;
|
||||
default: return osUnknown;
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
// --- cMenuSetupPage --------------------------------------------------------
|
||||
|
||||
cMenuSetupPage::cMenuSetupPage(void)
|
||||
:cOsdMenu("", 33)
|
||||
{
|
||||
data = Setup;
|
||||
osdLanguage = Setup.OSDLanguage;
|
||||
}
|
||||
|
||||
void cMenuSetupPage::SetupTitle(const char *s)
|
||||
{
|
||||
char buf[40]; // can't call tr() for more than one string at a time!
|
||||
char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
|
||||
snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
|
||||
SetTitle(buf);
|
||||
}
|
||||
|
||||
eOSState cMenuSetupPage::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
|
||||
cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
|
||||
Setup = data;
|
||||
Setup.Save();
|
||||
cDvbApi::SetCaCaps();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (data.OSDLanguage != osdLanguage) {
|
||||
int OriginalOSDLanguage = Setup.OSDLanguage;
|
||||
Setup.OSDLanguage = data.OSDLanguage;
|
||||
Set();
|
||||
Display();
|
||||
osdLanguage = data.OSDLanguage;
|
||||
Setup.OSDLanguage = OriginalOSDLanguage;
|
||||
}
|
||||
return state;
|
||||
}
|
110
menuitems.h
Normal file
110
menuitems.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* menuitems.h: General purpose menu items
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.h 1.1 2002/05/09 09:41:06 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENUITEMS_H
|
||||
#define __MENUITEMS_H
|
||||
|
||||
#include "osd.h"
|
||||
|
||||
class cMenuEditItem : public cOsdItem {
|
||||
private:
|
||||
const char *name;
|
||||
const char *value;
|
||||
public:
|
||||
cMenuEditItem(const char *Name);
|
||||
~cMenuEditItem();
|
||||
void SetValue(const char *Value);
|
||||
};
|
||||
|
||||
class cMenuEditIntItem : public cMenuEditItem {
|
||||
protected:
|
||||
int *value;
|
||||
int min, max;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cMenuEditBoolItem : public cMenuEditIntItem {
|
||||
protected:
|
||||
const char *falseString, *trueString;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditBoolItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL);
|
||||
};
|
||||
|
||||
class cMenuEditChrItem : public cMenuEditItem {
|
||||
private:
|
||||
char *value;
|
||||
const char *allowed;
|
||||
const char *current;
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
|
||||
~cMenuEditChrItem();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cMenuEditStrItem : public cMenuEditItem {
|
||||
private:
|
||||
char *value;
|
||||
int length;
|
||||
const char *allowed;
|
||||
int pos;
|
||||
bool insert, newchar, uppercase;
|
||||
void SetHelpKeys(void);
|
||||
virtual void Set(void);
|
||||
char Inc(char c, bool Up);
|
||||
public:
|
||||
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
|
||||
~cMenuEditStrItem();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cMenuEditStraItem : public cMenuEditIntItem {
|
||||
private:
|
||||
const char * const *strings;
|
||||
protected:
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings);
|
||||
};
|
||||
|
||||
class cMenuTextItem : public cOsdItem {
|
||||
private:
|
||||
char *text;
|
||||
int x, y, w, h, lines, offset;
|
||||
eDvbColor fgColor, bgColor;
|
||||
eDvbFont font;
|
||||
public:
|
||||
cMenuTextItem(const char *Text, int X, int Y, int W, int H = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground, eDvbFont Font = fontOsd);
|
||||
~cMenuTextItem();
|
||||
int Height(void) { return h; }
|
||||
void Clear(void);
|
||||
virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
bool CanScrollUp(void) { return offset > 0; }
|
||||
bool CanScrollDown(void) { return h + offset < lines; }
|
||||
void ScrollUp(bool Page);
|
||||
void ScrollDown(bool Page);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cMenuSetupPage : public cOsdMenu {
|
||||
protected:
|
||||
cSetup data;
|
||||
int osdLanguage;
|
||||
void SetupTitle(const char *s);
|
||||
virtual void Set(void) = 0;
|
||||
public:
|
||||
cMenuSetupPage(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
#endif //__MENUITEMS_H
|
250
newplugin
Executable file
250
newplugin
Executable file
@ -0,0 +1,250 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# newplugin: Initializing a new plugin source directory
|
||||
#
|
||||
# Creates a new plugin source directory from which to start implementing
|
||||
# a plugin for VDR.
|
||||
# See the file PLUGINS.html for detailed instructions on how to
|
||||
# write a plugin.
|
||||
#
|
||||
# Usage: newplugin <name>
|
||||
#
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: newplugin 1.1 2002/05/09 15:12:26 kls Exp $
|
||||
|
||||
$PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
|
||||
|
||||
die "Please use only lowercase letters and digits in the plugin name\n" if ($PLUGIN_NAME =~ tr/a-z0-9//c);
|
||||
|
||||
$PLUGIN_CLASS = ucfirst($PLUGIN_NAME);
|
||||
|
||||
$PLUGIN_VERSION = "0.0.1";
|
||||
$PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin";
|
||||
$PLUGIN_MAINENTRY = $PLUGIN_CLASS;
|
||||
|
||||
$PLUGINS_SRC = "PLUGINS/SRC";
|
||||
|
||||
$README = qq
|
||||
{This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Your Name <email\@host.dom>
|
||||
|
||||
Project's homepage: URL
|
||||
|
||||
Latest version available at: URL
|
||||
|
||||
See the file COPYING for license information.
|
||||
|
||||
Description:
|
||||
};
|
||||
|
||||
$HISTORY_TITLE = "VDR Plugin '$PLUGIN_NAME' Revision History";
|
||||
$HISTORY_LINE = '-' x length($HISTORY_TITLE);
|
||||
$HISTORY_DATE = sprintf("%4d-%02d-%02d", (localtime)[5] + 1900, (localtime)[4] + 1, (localtime)[3]);
|
||||
$HISTORY = qq
|
||||
{$HISTORY_TITLE
|
||||
$HISTORY_LINE
|
||||
|
||||
$HISTORY_DATE: Version $PLUGIN_VERSION
|
||||
|
||||
- Initial revision.
|
||||
};
|
||||
|
||||
$MAKEFILE = qq
|
||||
{#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# \$Id\$
|
||||
|
||||
# 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 = $PLUGIN_NAME
|
||||
|
||||
### The version number of this plugin (taken from the main source file):
|
||||
|
||||
VERSION = `grep 'static const char \\*VERSION *=' \$(PLUGIN).c | awk '{ print \$\$6 }' | sed -e 's/[";]//g'`
|
||||
|
||||
### The directory environment:
|
||||
|
||||
DVBDIR = ../../../../DVB/ost/include
|
||||
VDRDIR = ../../..
|
||||
VDRINC = \$(VDRDIR)/include
|
||||
LIBDIR = ../../lib
|
||||
TMPDIR = /tmp
|
||||
|
||||
### The version number of VDR (taken from VDR's "config.h"):
|
||||
|
||||
VDRVERSION = `grep 'define VDRVERSION ' \$(VDRDIR)/config.h | awk '{ print \$\$3 }' | sed -e 's/"//g'`
|
||||
|
||||
### The name of the distribution archive:
|
||||
|
||||
ARCHIVE = vdr-\$(PLUGIN)-\$(VERSION)
|
||||
|
||||
### Includes and Defines (add further entries here):
|
||||
|
||||
INCLUDES = -I\$(VDRINC) -I\$(DVBDIR)
|
||||
|
||||
DEFINES = -DPLUGIN_NAME_I18N='"\$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
OBJS = \$(PLUGIN).o
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -O2 -Wall -Woverloaded-virtual -m486
|
||||
|
||||
### Implicit rules:
|
||||
|
||||
%.o: %.c
|
||||
\$(CXX) \$(CXXFLAGS) -c \$(DEFINES) \$(INCLUDES) \$<
|
||||
|
||||
# Dependencies:
|
||||
|
||||
MAKEDEP = g++ -MM -MG
|
||||
DEPFILE = .dependencies
|
||||
\$(DEPFILE): Makefile
|
||||
\@\$(MAKEDEP) \$(DEFINES) \$(INCLUDES) \$(OBJS:%.o=%.c) > \$\@
|
||||
|
||||
include \$(DEPFILE)
|
||||
|
||||
### Targets:
|
||||
|
||||
all: libvdr-\$(PLUGIN).so
|
||||
|
||||
libvdr-\$(PLUGIN).so: \$(OBJS)
|
||||
\$(CXX) \$(CXXFLAGS) -shared \$(OBJS) -o \$\@
|
||||
\@cp \$\@ \$(LIBDIR)/\$\@.\$(VDRVERSION)
|
||||
|
||||
package: clean
|
||||
\@-rm -rf \$(TMPDIR)/\$(ARCHIVE)
|
||||
\@mkdir \$(TMPDIR)/\$(ARCHIVE)
|
||||
\@cp -a * \$(TMPDIR)/\$(ARCHIVE)
|
||||
\@tar czf \$(ARCHIVE).tgz -C \$(TMPDIR) \$(ARCHIVE)
|
||||
\@-rm -rf \$(TMPDIR)/\$(ARCHIVE)
|
||||
\@echo Distribution archive created as \$(ARCHIVE).tgz
|
||||
|
||||
clean:
|
||||
\@-rm -f \$(OBJS) \$(DEPFILE) *.so *.tgz core* *~
|
||||
};
|
||||
|
||||
$MAIN = qq
|
||||
{/*
|
||||
* $PLUGIN_NAME.c: A plugin for the Video Disk Recorder
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* \$Id\$
|
||||
*/
|
||||
|
||||
#include <vdr/plugin.h>
|
||||
|
||||
static const char *VERSION = "$PLUGIN_VERSION";
|
||||
static const char *DESCRIPTION = "$PLUGIN_DESCRIPTION";
|
||||
static const char *MAINMENUENTRY = "$PLUGIN_MAINENTRY";
|
||||
|
||||
class cPlugin$PLUGIN_CLASS : public cPlugin {
|
||||
private:
|
||||
// Add any member variables or functions you may need here.
|
||||
public:
|
||||
cPlugin$PLUGIN_CLASS(void);
|
||||
virtual ~cPlugin$PLUGIN_CLASS();
|
||||
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 void Start(void);
|
||||
virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
|
||||
virtual cOsdMenu *MainMenuAction(void);
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
};
|
||||
|
||||
cPlugin${PLUGIN_CLASS}::cPlugin$PLUGIN_CLASS(void)
|
||||
{
|
||||
// Initialize any member varaiables here.
|
||||
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
||||
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
||||
}
|
||||
|
||||
cPlugin${PLUGIN_CLASS}::~cPlugin$PLUGIN_CLASS()
|
||||
{
|
||||
// Clean up after yourself!
|
||||
}
|
||||
|
||||
const char *cPlugin${PLUGIN_CLASS}::CommandLineHelp(void)
|
||||
{
|
||||
// Return a string that describes all known command line options.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cPlugin${PLUGIN_CLASS}::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
// Implement command line argument processing here if applicable.
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlugin${PLUGIN_CLASS}::Start(void)
|
||||
{
|
||||
// Start any background activities the plugin shall perform.
|
||||
}
|
||||
|
||||
cOsdMenu *cPlugin${PLUGIN_CLASS}::MainMenuAction(void)
|
||||
{
|
||||
// Perform the action when selected from the main VDR menu.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cMenuSetupPage *cPlugin${PLUGIN_CLASS}::SetupMenu(void)
|
||||
{
|
||||
// Return a setup menu in case the plugin supports one.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cPlugin${PLUGIN_CLASS}::SetupParse(const char *Name, const char *Value)
|
||||
{
|
||||
// Parse your own setup parameters and store their values.
|
||||
return false;
|
||||
}
|
||||
|
||||
VDRPLUGINCREATOR(cPlugin$PLUGIN_CLASS); // Don't touch this!
|
||||
};
|
||||
|
||||
$PLUGINDIR = "$PLUGINS_SRC/$PLUGIN_NAME";
|
||||
|
||||
die "The directory $PLUGINS_SRC doesn't exist!\n" unless (-d "$PLUGINS_SRC");
|
||||
die "A plugin named '$PLUGIN_NAME' already exists in $PLUGINS_SRC!\n" if (-e "$PLUGINDIR");
|
||||
mkdir("$PLUGINDIR") || die "$!";
|
||||
|
||||
CreateFile("README", $README);
|
||||
CreateFile("HISTORY", $HISTORY);
|
||||
CreateFile("Makefile", $MAKEFILE);
|
||||
CreateFile("$PLUGIN_NAME.c", $MAIN);
|
||||
`cp COPYING "$PLUGINDIR"` if (-e "COPYING");
|
||||
|
||||
print qq{
|
||||
The new plugin source directory has been created in "$PLUGINDIR".
|
||||
|
||||
The next steps you should perform now are:
|
||||
|
||||
* edit the file "README" to adjust it to your specific implementation
|
||||
* fill in the code skeleton in "$PLUGIN_NAME.c" to implement your plugin function
|
||||
* add further source files if necessary
|
||||
* adapt the "Makefile" if necessary
|
||||
* do "make plugins" from the VDR source directory to build your plugin
|
||||
|
||||
};
|
||||
|
||||
sub CreateFile
|
||||
{
|
||||
my ($Name, $Content) = @_;
|
||||
open(FILE, ">$PLUGINDIR/$Name") || die "$Name: $!\n";
|
||||
print FILE $Content;
|
||||
close(FILE);
|
||||
}
|
||||
|
11
osd.c
11
osd.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.c 1.23 2002/03/29 16:34:03 kls Exp $
|
||||
* $Id: osd.c 1.24 2002/05/01 11:53:24 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osd.h"
|
||||
@ -105,12 +105,13 @@ cOsdMenu::~cOsdMenu()
|
||||
|
||||
const char *cOsdMenu::hk(const char *s)
|
||||
{
|
||||
static char buffer[32];
|
||||
static char buffer[64];
|
||||
if (s && hasHotkeys) {
|
||||
if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
|
||||
digit = 10; // prevents automatic hotkeys - input already has them
|
||||
if (digit < 9) {
|
||||
snprintf(buffer, sizeof(buffer), " %d %s", ++digit, s);
|
||||
digit = -1; // prevents automatic hotkeys - input already has them
|
||||
if (digit >= 0) {
|
||||
digit++;
|
||||
snprintf(buffer, sizeof(buffer), " %c %s", (digit < 10) ? '0' + digit : ' ' , s);
|
||||
s = buffer;
|
||||
}
|
||||
}
|
||||
|
4
osd.h
4
osd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.h 1.27 2002/03/10 16:18:11 kls Exp $
|
||||
* $Id: osd.h 1.28 2002/05/01 11:17:42 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSD_H
|
||||
@ -23,6 +23,7 @@ enum eOSState { osUnknown,
|
||||
osChannels,
|
||||
osTimers,
|
||||
osRecordings,
|
||||
osPlugin,
|
||||
osSetup,
|
||||
osCommands,
|
||||
osRecord,
|
||||
@ -43,6 +44,7 @@ enum eOSState { osUnknown,
|
||||
osUser7,
|
||||
osUser8,
|
||||
osUser9,
|
||||
osUser10,
|
||||
};
|
||||
|
||||
class cOsdItem : public cListObject {
|
||||
|
319
plugin.c
Normal file
319
plugin.c
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* plugin.c: The VDR plugin interface
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: plugin.c 1.1 2002/05/09 16:26:56 kls Exp $
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include "config.h"
|
||||
|
||||
#define LIBVDR_PREFIX "libvdr-"
|
||||
#define SO_INDICATOR ".so."
|
||||
|
||||
#define MAXPLUGINARGS 1024
|
||||
|
||||
// --- cPlugin ---------------------------------------------------------------
|
||||
|
||||
cPlugin::cPlugin(void)
|
||||
{
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
cPlugin::~cPlugin()
|
||||
{
|
||||
I18nRegister(NULL, Name());
|
||||
}
|
||||
|
||||
void cPlugin::SetName(const char *s)
|
||||
{
|
||||
name = s;
|
||||
}
|
||||
|
||||
const char *cPlugin::CommandLineHelp(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cPlugin::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlugin::Start(void)
|
||||
{
|
||||
}
|
||||
|
||||
const char *cPlugin::MainMenuEntry(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cOsdMenu *cPlugin::MainMenuAction(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cMenuSetupPage *cPlugin::SetupMenu(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cPlugin::SetupParse(const char *Name, const char *Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void cPlugin::SetupStore(const char *Name, const char *Value)
|
||||
{
|
||||
Setup.Store(Name, Value, this->Name());
|
||||
}
|
||||
|
||||
void cPlugin::SetupStore(const char *Name, int Value)
|
||||
{
|
||||
Setup.Store(Name, Value, this->Name());
|
||||
}
|
||||
|
||||
void cPlugin::RegisterI18n(const tI18nPhrase * const Phrases)
|
||||
{
|
||||
I18nRegister(Phrases, Name());
|
||||
}
|
||||
|
||||
// --- cDll ------------------------------------------------------------------
|
||||
|
||||
cDll::cDll(const char *FileName, const char *Args)
|
||||
{
|
||||
fileName = strdup(FileName);
|
||||
args = Args ? strdup(Args) : NULL;
|
||||
handle = NULL;
|
||||
plugin = NULL;
|
||||
}
|
||||
|
||||
cDll::~cDll()
|
||||
{
|
||||
delete plugin;
|
||||
if (handle)
|
||||
dlclose(handle);
|
||||
delete args;
|
||||
delete fileName;
|
||||
}
|
||||
|
||||
static char *SkipQuote(char *s)
|
||||
{
|
||||
char c = *s;
|
||||
strcpy(s, s + 1);
|
||||
while (*s && *s != c) {
|
||||
if (*s == '\\')
|
||||
strcpy(s, s + 1);
|
||||
if (*s)
|
||||
s++;
|
||||
}
|
||||
if (*s) {
|
||||
strcpy(s, s + 1);
|
||||
return s;
|
||||
}
|
||||
esyslog(LOG_ERR, "ERROR: missing closing %c", c);
|
||||
fprintf(stderr, "vdr: missing closing %c\n", c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cDll::Load(bool Log)
|
||||
{
|
||||
if (Log)
|
||||
isyslog(LOG_INFO, "loading plugin: %s", fileName);
|
||||
if (handle) {
|
||||
esyslog(LOG_ERR, "attempt to load plugin '%s' twice!", fileName);
|
||||
return false;
|
||||
}
|
||||
handle = dlopen(fileName, RTLD_NOW);
|
||||
const char *error = dlerror();
|
||||
if (!error) {
|
||||
void *(*creator)(void);
|
||||
(void *)creator = dlsym(handle, "VDRPluginCreator");
|
||||
if (!(error = dlerror()))
|
||||
plugin = (cPlugin *)creator();
|
||||
}
|
||||
if (!error) {
|
||||
if (plugin && args) {
|
||||
int argc = 0;
|
||||
char *argv[MAXPLUGINARGS];
|
||||
char *p = args;
|
||||
char *q = NULL;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
if (!q)
|
||||
q = p;
|
||||
switch (*p) {
|
||||
case '\\': strcpy(p, p + 1);
|
||||
if (*p)
|
||||
p++;
|
||||
else {
|
||||
esyslog(LOG_ERR, "ERROR: missing character after \\");
|
||||
fprintf(stderr, "vdr: missing character after \\\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
case '\'': if ((p = SkipQuote(p)) == NULL)
|
||||
return false;
|
||||
break;
|
||||
default: if (!*p || isspace(*p)) {
|
||||
done = !*p;
|
||||
*p = 0;
|
||||
if (q) {
|
||||
if (argc < MAXPLUGINARGS - 1)
|
||||
argv[argc++] = q;
|
||||
else {
|
||||
esyslog(LOG_ERR, "ERROR: plugin argument list too long");
|
||||
fprintf(stderr, "vdr: plugin argument list too long\n");
|
||||
return false;
|
||||
}
|
||||
q = NULL;
|
||||
}
|
||||
}
|
||||
if (!done)
|
||||
p++;
|
||||
}
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
if (argc)
|
||||
plugin->SetName(argv[0]);
|
||||
optind = 0; // to reset the getopt() data
|
||||
return !argc || plugin->ProcessArgs(argc, argv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog(LOG_ERR, "ERROR: %s", error);
|
||||
fprintf(stderr, "vdr: %s\n", error);
|
||||
}
|
||||
return !error && plugin;
|
||||
}
|
||||
|
||||
// --- cPluginManager --------------------------------------------------------
|
||||
|
||||
cPluginManager *cPluginManager::pluginManager = NULL;
|
||||
|
||||
cPluginManager::cPluginManager(const char *Directory)
|
||||
{
|
||||
directory = NULL;
|
||||
if (pluginManager) {
|
||||
fprintf(stderr, "vdr: attempt to create more than one plugin manager - exiting!\n");
|
||||
exit(2);
|
||||
}
|
||||
SetDirectory(Directory);
|
||||
pluginManager = this;
|
||||
}
|
||||
|
||||
cPluginManager::~cPluginManager()
|
||||
{
|
||||
Shutdown();
|
||||
delete directory;
|
||||
if (pluginManager == this)
|
||||
pluginManager = NULL;
|
||||
}
|
||||
|
||||
void cPluginManager::SetDirectory(const char *Directory)
|
||||
{
|
||||
delete directory;
|
||||
directory = Directory ? strdup(Directory) : NULL;
|
||||
}
|
||||
|
||||
void cPluginManager::AddPlugin(const char *Args)
|
||||
{
|
||||
if (strcmp(Args, "*") == 0) {
|
||||
DIR *d = opendir(directory);
|
||||
if (d) {
|
||||
struct dirent *e;
|
||||
while ((e = readdir(d)) != NULL) {
|
||||
if (strstr(e->d_name, LIBVDR_PREFIX) == e->d_name) {
|
||||
char *p = strstr(e->d_name, SO_INDICATOR);
|
||||
if (p) {
|
||||
*p = 0;
|
||||
p += strlen(SO_INDICATOR);
|
||||
if (strcmp(p, VDRVERSION) == 0) {
|
||||
char *name = e->d_name + strlen(LIBVDR_PREFIX);
|
||||
if (strcmp(name, "*") != 0) { // let's not get into a loop!
|
||||
AddPlugin(e->d_name + strlen(LIBVDR_PREFIX));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
return;
|
||||
}
|
||||
char *s = strdup(Args);
|
||||
char *p = strchr(s, ' ');
|
||||
if (p)
|
||||
*p = 0;
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s/%s%s%s%s", directory, LIBVDR_PREFIX, s, SO_INDICATOR, VDRVERSION);
|
||||
dlls.Add(new cDll(buffer, Args));
|
||||
delete buffer;
|
||||
delete s;
|
||||
}
|
||||
|
||||
bool cPluginManager::LoadPlugins(bool Log)
|
||||
{
|
||||
for (cDll *dll = dlls.First(); dll; dll = dlls.Next(dll)) {
|
||||
if (!dll->Load(Log))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPluginManager::StartPlugins(void)
|
||||
{
|
||||
for (cDll *dll = dlls.First(); dll; dll = dlls.Next(dll)) {
|
||||
cPlugin *p = dll->Plugin();
|
||||
if (p) {
|
||||
int Language = Setup.OSDLanguage;
|
||||
Setup.OSDLanguage = 0; // the i18n texts are only available _after_ Start()
|
||||
isyslog(LOG_INFO, "starting plugin: %s (%s): %s", p->Name(), p->Version(), p->Description());
|
||||
Setup.OSDLanguage = Language;
|
||||
dll->Plugin()->Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cPluginManager::HasPlugins(void)
|
||||
{
|
||||
return pluginManager && pluginManager->dlls.Count();
|
||||
}
|
||||
|
||||
cPlugin *cPluginManager::GetPlugin(int Index)
|
||||
{
|
||||
cDll *dll = pluginManager ? pluginManager->dlls.Get(Index) : NULL;
|
||||
return dll ? dll->Plugin() : NULL;
|
||||
}
|
||||
|
||||
cPlugin *cPluginManager::GetPlugin(const char *Name)
|
||||
{
|
||||
if (pluginManager) {
|
||||
for (cDll *dll = pluginManager->dlls.First(); dll; dll = pluginManager->dlls.Next(dll)) {
|
||||
cPlugin *p = dll->Plugin();
|
||||
if (p && strcmp(p->Name(), Name) == 0)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cPluginManager::Shutdown(bool Log)
|
||||
{
|
||||
cDll *dll;
|
||||
while ((dll = dlls.Last()) != NULL) {
|
||||
if (Log) {
|
||||
cPlugin *p = dll->Plugin();
|
||||
if (p)
|
||||
isyslog(LOG_INFO, "stopping plugin: %s", p->Name());
|
||||
}
|
||||
dlls.Del(dll);
|
||||
}
|
||||
}
|
81
plugin.h
Normal file
81
plugin.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* plugin.h: The VDR plugin interface
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: plugin.h 1.1 2002/05/09 10:16:09 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PLUGIN_H
|
||||
#define __PLUGIN_H
|
||||
|
||||
#include "i18n.h"
|
||||
#include "menuitems.h"
|
||||
#include "osd.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRPLUGINCREATOR(PluginClass) extern "C" void *VDRPluginCreator(void) { return new PluginClass; }
|
||||
|
||||
class cPlugin {
|
||||
friend class cDll;
|
||||
private:
|
||||
const char *name;
|
||||
void SetName(const char *s);
|
||||
public:
|
||||
cPlugin(void);
|
||||
virtual ~cPlugin();
|
||||
|
||||
const char *Name(void) { return name; }
|
||||
virtual const char *Version(void) = 0;
|
||||
virtual const char *Description(void) = 0;
|
||||
virtual const char *CommandLineHelp(void);
|
||||
|
||||
virtual bool ProcessArgs(int argc, char *argv[]);
|
||||
virtual void Start(void);
|
||||
|
||||
virtual const char *MainMenuEntry(void);
|
||||
virtual cOsdMenu *MainMenuAction(void);
|
||||
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
void SetupStore(const char *Name, const char *Value = NULL);
|
||||
void SetupStore(const char *Name, int Value);
|
||||
|
||||
void RegisterI18n(const tI18nPhrase * const Phrases);
|
||||
};
|
||||
|
||||
class cDll : public cListObject {
|
||||
private:
|
||||
char *fileName;
|
||||
char *args;
|
||||
void *handle;
|
||||
cPlugin *plugin;
|
||||
public:
|
||||
cDll(const char *FileName, const char *Args);
|
||||
virtual ~cDll();
|
||||
bool Load(bool Log = false);
|
||||
cPlugin *Plugin(void) { return plugin; }
|
||||
};
|
||||
|
||||
class cDlls : public cList<cDll> {};
|
||||
|
||||
class cPluginManager {
|
||||
private:
|
||||
static cPluginManager *pluginManager;
|
||||
char *directory;
|
||||
cDlls dlls;
|
||||
public:
|
||||
cPluginManager(const char *Directory);
|
||||
virtual ~cPluginManager();
|
||||
void SetDirectory(const char *Directory);
|
||||
void AddPlugin(const char *Args);
|
||||
bool LoadPlugins(bool Log = false);
|
||||
void StartPlugins(void);
|
||||
static bool HasPlugins(void);
|
||||
static cPlugin *GetPlugin(int Index);
|
||||
static cPlugin *GetPlugin(const char *Name);
|
||||
void Shutdown(bool Log = false);
|
||||
};
|
||||
|
||||
#endif //__PLUGIN_H
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.c 1.60 2002/04/01 10:51:23 kls Exp $
|
||||
* $Id: recording.c 1.61 2002/04/21 14:02:55 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -222,7 +222,6 @@ static char *ExchangeChars(char *s, bool ToFileSystem)
|
||||
case '+':
|
||||
case ',':
|
||||
case '-':
|
||||
case '.':
|
||||
case ';':
|
||||
case '=':
|
||||
case '0' ... '9':
|
||||
@ -237,7 +236,8 @@ static char *ExchangeChars(char *s, bool ToFileSystem)
|
||||
case ' ': *p = '_'; break;
|
||||
case '~': *p = '/'; break;
|
||||
// characters that have to be encoded:
|
||||
default: {
|
||||
default:
|
||||
if (*p != '.' || !*(p + 1) || *(p + 1) == '~') { // Windows can't handle '.' at the end of directory names
|
||||
int l = p - s;
|
||||
s = (char *)realloc(s, strlen(s) + 10);
|
||||
p = s + l;
|
||||
|
4
remote.h
4
remote.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: remote.h 1.15 2001/07/22 14:42:59 kls Exp $
|
||||
* $Id: remote.h 1.16 2002/05/09 11:43:04 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __REMOTE_H
|
||||
@ -95,7 +95,7 @@ public:
|
||||
|
||||
#elif !defined REMOTE_NONE
|
||||
|
||||
#error Please define a remote control mode!
|
||||
// #error Please define a remote control mode!
|
||||
|
||||
#endif
|
||||
|
||||
|
66
ringbuffer.c
66
ringbuffer.c
@ -7,7 +7,7 @@
|
||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||
* LinuxDVB driver (see linuxtv.org).
|
||||
*
|
||||
* $Id: ringbuffer.c 1.5 2001/11/03 09:50:46 kls Exp $
|
||||
* $Id: ringbuffer.c 1.6 2002/04/18 15:46:36 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
@ -154,7 +154,6 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
|
||||
Lock();
|
||||
int rest = Size() - head;
|
||||
int diff = tail - head;
|
||||
Unlock();
|
||||
int free = (diff > 0) ? diff - 1 : Size() + diff - 1;
|
||||
if (statistics) {
|
||||
int fill = Size() - free - 1 + Count;
|
||||
@ -167,22 +166,25 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
|
||||
dsyslog(LOG_INFO, "buffer usage: %d%%", percent);
|
||||
}
|
||||
}
|
||||
if (free <= 0)
|
||||
return 0;
|
||||
if (free < Count)
|
||||
Count = free;
|
||||
if (Count > maxFill)
|
||||
maxFill = Count;
|
||||
if (Count >= rest) {
|
||||
memcpy(buffer + head, Data, rest);
|
||||
if (Count - rest)
|
||||
memcpy(buffer, Data + rest, Count - rest);
|
||||
head = Count - rest;
|
||||
}
|
||||
else {
|
||||
memcpy(buffer + head, Data, Count);
|
||||
head += Count;
|
||||
if (free > 0) {
|
||||
if (free < Count)
|
||||
Count = free;
|
||||
if (Count > maxFill)
|
||||
maxFill = Count;
|
||||
if (Count >= rest) {
|
||||
memcpy(buffer + head, Data, rest);
|
||||
if (Count - rest)
|
||||
memcpy(buffer, Data + rest, Count - rest);
|
||||
head = Count - rest;
|
||||
}
|
||||
else {
|
||||
memcpy(buffer + head, Data, Count);
|
||||
head += Count;
|
||||
}
|
||||
}
|
||||
else
|
||||
Count = 0;
|
||||
Unlock();
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
@ -193,22 +195,24 @@ int cRingBufferLinear::Get(uchar *Data, int Count)
|
||||
Lock();
|
||||
int rest = Size() - tail;
|
||||
int diff = head - tail;
|
||||
Unlock();
|
||||
int cont = (diff >= 0) ? diff : Size() + diff;
|
||||
if (rest <= 0)
|
||||
return 0;
|
||||
if (cont < Count)
|
||||
Count = cont;
|
||||
if (Count >= rest) {
|
||||
memcpy(Data, buffer + tail, rest);
|
||||
if (Count - rest)
|
||||
memcpy(Data + rest, buffer, Count - rest);
|
||||
tail = Count - rest;
|
||||
}
|
||||
else {
|
||||
memcpy(Data, buffer + tail, Count);
|
||||
tail += Count;
|
||||
if (rest > 0) {
|
||||
if (cont < Count)
|
||||
Count = cont;
|
||||
if (Count >= rest) {
|
||||
memcpy(Data, buffer + tail, rest);
|
||||
if (Count - rest)
|
||||
memcpy(Data + rest, buffer, Count - rest);
|
||||
tail = Count - rest;
|
||||
}
|
||||
else {
|
||||
memcpy(Data, buffer + tail, Count);
|
||||
tail += Count;
|
||||
}
|
||||
}
|
||||
else
|
||||
Count = 0;
|
||||
Unlock();
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
8
tools.c
8
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 1.62 2002/03/31 20:51:06 kls Exp $
|
||||
* $Id: tools.c 1.63 2002/05/01 16:20:30 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -251,10 +251,10 @@ int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
|
||||
int Free = 0;
|
||||
struct statfs statFs;
|
||||
if (statfs(Directory, &statFs) == 0) {
|
||||
int blocksPerMeg = 1024 * 1024 / statFs.f_bsize;
|
||||
double blocksPerMeg = 1024.0 * 1024.0 / statFs.f_bsize;
|
||||
if (UsedMB)
|
||||
*UsedMB = (statFs.f_blocks - statFs.f_bfree) / blocksPerMeg;
|
||||
Free = statFs.f_bavail / blocksPerMeg;
|
||||
*UsedMB = int((statFs.f_blocks - statFs.f_bfree) / blocksPerMeg);
|
||||
Free = int(statFs.f_bavail / blocksPerMeg);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(Directory);
|
||||
|
24
vdr.1
24
vdr.1
@ -8,9 +8,9 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.1 1.3 2002/04/07 13:11:43 kls Exp $
|
||||
.\" $Id: vdr.1 1.4 2002/05/09 16:04:17 kls Exp $
|
||||
.\"
|
||||
.TH vdr 1 "7 Apr 2002" "1.0.0" "Video Disk Recorder"
|
||||
.TH vdr 1 "9 May 2002" "1.1.0" "Video Disk Recorder"
|
||||
.SH NAME
|
||||
vdr - the Video Disk Recorder
|
||||
.SH SYNOPSIS
|
||||
@ -68,6 +68,11 @@ Set logging to \fIlevel\fR.
|
||||
\fB2\fR\ =\ errors and info, \fB3\fR\ =\ errors, info and debug.
|
||||
The default logging level is \fB3\fR.
|
||||
.TP
|
||||
.BI -L\ dir ,\ --lib= dir
|
||||
Search for plugins in directory \fIdir\fR (default is ./PLUGINS/lib).
|
||||
There can be several \fB-L\fR options with different \fIdir\fR values.
|
||||
Each of them will apply to the \fB-P\fR options following it.
|
||||
.TP
|
||||
.B -m, --mute
|
||||
Mute audio of the primary DVB device at startup.
|
||||
.TP
|
||||
@ -77,6 +82,18 @@ The default SVDRP port is \fB2001\fR.
|
||||
You need to edit the file \fIsvdrphosts.conf\fR in order to enable
|
||||
access to the SVDRP port.
|
||||
.TP
|
||||
.BI -P\ options ,\ --plugin= options
|
||||
Load a plugin, defined by the given \fIoptions\fR.
|
||||
The first word in \fIoptions\fR must be the name of an existing \fBvdr\fR
|
||||
plugin, optionally followed by a blank separated list of command line options
|
||||
for that plugin. If \fIoptions\fR contains any blanks, you need to enclose it
|
||||
in quotes, like for example
|
||||
|
||||
\fBvdr -P "abc -a -b xyz"\fR
|
||||
|
||||
which would load a plugin named \fBabc\fR, giving it the command line options
|
||||
\fB-a\ -b\ xyz\fR.
|
||||
.TP
|
||||
.BI -r\ cmd ,\ --record= cmd
|
||||
Call \fIcmd\fR before and after a recording.
|
||||
.TP
|
||||
@ -104,6 +121,9 @@ Successful program execution.
|
||||
.B 1
|
||||
An error has been detected which requires the DVB driver and \fBvdr\fR
|
||||
to be re-loaded.
|
||||
.TP
|
||||
.B 2
|
||||
An non-recoverable error has been detected, \fBvdr\fR has given up.
|
||||
.SH FILES
|
||||
.TP
|
||||
.I channels.conf
|
||||
|
133
vdr.c
133
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.102 2002/03/29 10:09:20 kls Exp $
|
||||
* $Id: vdr.c 1.104 2002/05/05 10:34:31 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -36,6 +36,7 @@
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "menu.h"
|
||||
#include "plugin.h"
|
||||
#include "recording.h"
|
||||
#include "tools.h"
|
||||
#include "videodir.h"
|
||||
@ -79,14 +80,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
#define DEFAULTSVDRPPORT 2001
|
||||
#define DEFAULTWATCHDOG 0 // seconds
|
||||
#define DEFAULTPLUGINDIR "./PLUGINS/lib"
|
||||
|
||||
int SVDRPport = DEFAULTSVDRPPORT;
|
||||
const char *ConfigDirectory = NULL;
|
||||
bool DisplayHelp = false;
|
||||
bool DisplayVersion = false;
|
||||
bool DaemonMode = false;
|
||||
bool MuteAudio = false;
|
||||
int WatchdogTimeout = DEFAULTWATCHDOG;
|
||||
const char *Terminal = NULL;
|
||||
const char *Shutdown = NULL;
|
||||
cPluginManager PluginManager(DEFAULTPLUGINDIR);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "audio", required_argument, NULL, 'a' },
|
||||
@ -95,8 +100,10 @@ int main(int argc, char *argv[])
|
||||
{ "device", required_argument, NULL, 'D' },
|
||||
{ "epgfile", required_argument, NULL, 'E' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "lib", required_argument, NULL, 'L' },
|
||||
{ "log", required_argument, NULL, 'l' },
|
||||
{ "mute", no_argument, NULL, 'm' },
|
||||
{ "plugin", required_argument, NULL, 'P' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "record", required_argument, NULL, 'r' },
|
||||
{ "shutdown", required_argument, NULL, 's' },
|
||||
@ -108,8 +115,7 @@ int main(int argc, char *argv[])
|
||||
};
|
||||
|
||||
int c;
|
||||
int option_index = 0;
|
||||
while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:mp:r:s:t:v:Vw:", long_options, &option_index)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:L:mp:P:r:s:t:v:Vw:", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': cDvbApi::SetAudioCommand(optarg);
|
||||
break;
|
||||
@ -128,40 +134,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'E': cSIProcessor::SetEpgDataFileName(*optarg != '-' ? optarg : NULL);
|
||||
break;
|
||||
case 'h': printf("Usage: vdr [OPTION]\n\n" // for easier orientation, this is column 80|
|
||||
" -a CMD, --audio=CMD send Dolby Digital audio to stdin of command CMD\n"
|
||||
" -c DIR, --config=DIR read config files from DIR (default is to read them\n"
|
||||
" from the video directory)\n"
|
||||
" -d, --daemon run in daemon mode\n"
|
||||
" -D NUM, --device=NUM use only the given DVB device (NUM = 0, 1, 2...)\n"
|
||||
" there may be several -D options (default: all DVB\n"
|
||||
" devices will be used)\n"
|
||||
" -E FILE --epgfile=FILE write the EPG data into the given FILE (default is\n"
|
||||
" %s); use '-E-' to disable this\n"
|
||||
" if FILE is a directory, the default EPG file will be\n"
|
||||
" created in that directory\n"
|
||||
" -h, --help print this help and exit\n"
|
||||
" -l LEVEL, --log=LEVEL set log level (default: 3)\n"
|
||||
" 0 = no logging, 1 = errors only,\n"
|
||||
" 2 = errors and info, 3 = errors, info and debug\n"
|
||||
" -m, --mute mute audio of the primary DVB device at startup\n"
|
||||
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
|
||||
" 0 turns off SVDRP\n"
|
||||
" -r CMD, --record=CMD call CMD before and after a recording\n"
|
||||
" -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
|
||||
" -t TTY, --terminal=TTY controlling tty\n"
|
||||
" -V, --version print version information and exit\n"
|
||||
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
|
||||
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
|
||||
" seconds (default: %d); '0' disables the watchdog\n"
|
||||
"\n"
|
||||
"Report bugs to <vdr-bugs@cadsoft.de>\n",
|
||||
cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
|
||||
DEFAULTSVDRPPORT,
|
||||
VideoDirectory,
|
||||
DEFAULTWATCHDOG
|
||||
);
|
||||
return 0;
|
||||
case 'h': DisplayHelp = true;
|
||||
break;
|
||||
case 'l': if (isnumber(optarg)) {
|
||||
int l = atoi(optarg);
|
||||
@ -173,6 +146,8 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "vdr: invalid log level: %s\n", optarg);
|
||||
return 2;
|
||||
break;
|
||||
case 'L': PluginManager.SetDirectory(optarg);
|
||||
break;
|
||||
case 'm': MuteAudio = true;
|
||||
break;
|
||||
case 'p': if (isnumber(optarg))
|
||||
@ -182,14 +157,15 @@ int main(int argc, char *argv[])
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 'P': PluginManager.AddPlugin(optarg);
|
||||
break;
|
||||
case 'r': cRecordingUserCommand::SetCommand(optarg);
|
||||
break;
|
||||
case 's': Shutdown = optarg;
|
||||
break;
|
||||
case 't': Terminal = optarg;
|
||||
break;
|
||||
case 'V': printf("vdr, version %s\n", VDRVERSION);
|
||||
return 0;
|
||||
case 'V': DisplayVersion = true;
|
||||
break;
|
||||
case 'v': VideoDirectory = optarg;
|
||||
while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
|
||||
@ -209,6 +185,71 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// Help and version info:
|
||||
|
||||
if (DisplayHelp || DisplayVersion) {
|
||||
if (!PluginManager.HasPlugins())
|
||||
PluginManager.AddPlugin("*"); // adds all available plugins
|
||||
PluginManager.LoadPlugins();
|
||||
if (DisplayHelp) {
|
||||
printf("Usage: vdr [OPTIONS]\n\n" // for easier orientation, this is column 80|
|
||||
" -a CMD, --audio=CMD send Dolby Digital audio to stdin of command CMD\n"
|
||||
" -c DIR, --config=DIR read config files from DIR (default is to read them\n"
|
||||
" from the video directory)\n"
|
||||
" -d, --daemon run in daemon mode\n"
|
||||
" -D NUM, --device=NUM use only the given DVB device (NUM = 0, 1, 2...)\n"
|
||||
" there may be several -D options (default: all DVB\n"
|
||||
" devices will be used)\n"
|
||||
" -E FILE --epgfile=FILE write the EPG data into the given FILE (default is\n"
|
||||
" %s); use '-E-' to disable this\n"
|
||||
" if FILE is a directory, the default EPG file will be\n"
|
||||
" created in that directory\n"
|
||||
" -h, --help print this help and exit\n"
|
||||
" -l LEVEL, --log=LEVEL set log level (default: 3)\n"
|
||||
" 0 = no logging, 1 = errors only,\n"
|
||||
" 2 = errors and info, 3 = errors, info and debug\n"
|
||||
" -L DIR, --lib=DIR search for plugins in DIR (default is %s)\n"
|
||||
" -m, --mute mute audio of the primary DVB device at startup\n"
|
||||
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
|
||||
" 0 turns off SVDRP\n"
|
||||
" -P OPT, --plugin=OPT load a plugin defined by the given options\n"
|
||||
" -r CMD, --record=CMD call CMD before and after a recording\n"
|
||||
" -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
|
||||
" -t TTY, --terminal=TTY controlling tty\n"
|
||||
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
|
||||
" -V, --version print version information and exit\n"
|
||||
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
|
||||
" seconds (default: %d); '0' disables the watchdog\n"
|
||||
"\n",
|
||||
cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
|
||||
DEFAULTPLUGINDIR,
|
||||
DEFAULTSVDRPPORT,
|
||||
VideoDirectory,
|
||||
DEFAULTWATCHDOG
|
||||
);
|
||||
}
|
||||
if (DisplayVersion)
|
||||
printf("vdr (%s) - The Video Disk Recorder\n", VDRVERSION);
|
||||
if (PluginManager.HasPlugins()) {
|
||||
if (DisplayHelp)
|
||||
printf("Plugins: vdr -P\"name [OPTIONS]\"\n\n");
|
||||
for (int i = 0; ; i++) {
|
||||
cPlugin *p = PluginManager.GetPlugin(i);
|
||||
if (p) {
|
||||
const char *help = p->CommandLineHelp();
|
||||
printf("%s (%s) - %s\n", p->Name(), p->Version(), p->Description());
|
||||
if (DisplayHelp && help) {
|
||||
printf("\n");
|
||||
puts(help);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Log file:
|
||||
|
||||
if (SysLogLevel > 0)
|
||||
@ -250,6 +291,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
isyslog(LOG_INFO, "VDR version %s started", VDRVERSION);
|
||||
|
||||
// Load plugins:
|
||||
|
||||
if (!PluginManager.LoadPlugins(true))
|
||||
return 2;
|
||||
|
||||
// Configuration data:
|
||||
|
||||
if (!ConfigDirectory)
|
||||
@ -276,6 +322,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
cSIProcessor::Read();
|
||||
|
||||
// Start plugins:
|
||||
|
||||
PluginManager.StartPlugins();
|
||||
|
||||
// Channel:
|
||||
|
||||
Channels.SwitchTo(Setup.CurrentChannel);
|
||||
if (MuteAudio)
|
||||
cDvbApi::PrimaryDvbApi->ToggleMute();
|
||||
@ -469,7 +521,7 @@ int main(int argc, char *argv[])
|
||||
Interface->Info(tr("Editing process finished"));
|
||||
}
|
||||
}
|
||||
if (!*Interact && (!cRecordControls::Active() || ForceShutdown)) {
|
||||
if (!*Interact && ((!cRecordControls::Active() && !cVideoCutter::Active()) || ForceShutdown)) {
|
||||
time_t Now = time(NULL);
|
||||
if (Now - LastActivity > ACTIVITYTIMEOUT) {
|
||||
// Shutdown:
|
||||
@ -529,6 +581,7 @@ int main(int argc, char *argv[])
|
||||
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
||||
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
||||
Setup.Save();
|
||||
PluginManager.Shutdown(true);
|
||||
cVideoCutter::Stop();
|
||||
delete Menu;
|
||||
delete ReplayControl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user