mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 1.1.1
- Separated the actual DVB hardware OSD implementation from the abstract OSD interface. 'osdbase.c/.h' now implements the abstract OSD, while 'dvbosd.c/.h' is the actual implementation for the DVB hardware. This is in preparation for allowing additional kinds of OSD hardware implementations. - Fixed leftover references to the file FORMATS in MANUAL and svdrp.c. - Avoiding ambiguities in the cList template class in case one defines a "list of lists" (thanks to Stefan Huelswitt). - Simplified the basic cMenuSetupPage class for easier use in plugins. - Added setup parameters and a Setup menu to the 'hello' plugin example. - Fixed logging error message for unknown config parameters in plugins. - Rearranged cleanup sequence at the end of the main program. - Adapted PLUGINS.html to use the actual code examples from the 'hello' plugin.
This commit is contained in:
parent
ae8a947367
commit
803c6c6bf6
@ -128,6 +128,8 @@ Stefan Huelswitt <huels@iname.com>
|
|||||||
with CAMs and AC3 sound only working the first time
|
with CAMs and AC3 sound only working the first time
|
||||||
for making the main loop take an active video cutting process into account when
|
for making the main loop take an active video cutting process into account when
|
||||||
doing shutdown or housekeeping
|
doing shutdown or housekeeping
|
||||||
|
for making the cList template class avoid ambiguities in case one defines a "list of
|
||||||
|
lists"
|
||||||
|
|
||||||
Ulrich Röder <roeder@efr-net.de>
|
Ulrich Röder <roeder@efr-net.de>
|
||||||
for pointing out that there are channels that have a symbol rate higher than
|
for pointing out that there are channels that have a symbol rate higher than
|
||||||
|
15
HISTORY
15
HISTORY
@ -1254,3 +1254,18 @@ Video Disk Recorder Revision History
|
|||||||
and '-P' used to load plugins. This first step implements the complete "outer"
|
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.
|
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.
|
- The VDR version number is now displayed in the title line of the "Setup" menu.
|
||||||
|
|
||||||
|
2002-05-11: Version 1.1.1
|
||||||
|
|
||||||
|
- Separated the actual DVB hardware OSD implementation from the abstract OSD
|
||||||
|
interface. 'osdbase.c/.h' now implements the abstract OSD, while 'dvbosd.c/.h'
|
||||||
|
is the actual implementation for the DVB hardware. This is in preparation for
|
||||||
|
allowing additional kinds of OSD hardware implementations.
|
||||||
|
- Fixed leftover references to the file FORMATS in MANUAL and svdrp.c.
|
||||||
|
- Avoiding ambiguities in the cList template class in case one defines a "list of
|
||||||
|
lists" (thanks to Stefan Huelswitt).
|
||||||
|
- Simplified the basic cMenuSetupPage class for easier use in plugins.
|
||||||
|
- Added setup parameters and a Setup menu to the 'hello' plugin example.
|
||||||
|
- Fixed logging error message for unknown config parameters in plugins.
|
||||||
|
- Rearranged cleanup sequence at the end of the main program.
|
||||||
|
- Adapted PLUGINS.html to use the actual code examples from the 'hello' plugin.
|
||||||
|
4
MANUAL
4
MANUAL
@ -571,7 +571,7 @@ Video Disk Recorder User's Manual
|
|||||||
* Executing system commands
|
* Executing system commands
|
||||||
|
|
||||||
The "VDR" menu option "Commands" allows you to execute any system commands
|
The "VDR" menu option "Commands" allows you to execute any system commands
|
||||||
defined in the configuration file 'commands.conf' (see FORMATS for details).
|
defined in the configuration file 'commands.conf' (see vdr(5) for details).
|
||||||
The "Commands" option will only be present in the "VDR" menu if a valid
|
The "Commands" option will only be present in the "VDR" menu if a valid
|
||||||
'commands.conf' file containing at least one command definition has been
|
'commands.conf' file containing at least one command definition has been
|
||||||
found at program start.
|
found at program start.
|
||||||
@ -584,7 +584,7 @@ Video Disk Recorder User's Manual
|
|||||||
be displayed on a result screen after executing the command. This screen will
|
be displayed on a result screen after executing the command. This screen will
|
||||||
use a 'fixed' font so that you can generate formatted output. In order to
|
use a 'fixed' font so that you can generate formatted output. In order to
|
||||||
avoid error messages going to stderr, command definitions should redirect
|
avoid error messages going to stderr, command definitions should redirect
|
||||||
stderr to stdout (see FORMATS).
|
stderr to stdout (see vdr(5)).
|
||||||
|
|
||||||
WARNING: THE COMMANDS DEFINED IN 'commands.conf' WILL BE EXECUTED UNDER THE
|
WARNING: THE COMMANDS DEFINED IN 'commands.conf' WILL BE EXECUTED UNDER THE
|
||||||
======= SAME USER ID THAT VDR IS RUNNING WITH. BE VERY CAREFUL WHEN
|
======= SAME USER ID THAT VDR IS RUNNING WITH. BE VERY CAREFUL WHEN
|
||||||
|
4
Makefile
4
Makefile
@ -4,7 +4,7 @@
|
|||||||
# See the main source file 'vdr.c' for copyright information and
|
# See the main source file 'vdr.c' for copyright information and
|
||||||
# how to reach the author.
|
# how to reach the author.
|
||||||
#
|
#
|
||||||
# $Id: Makefile 1.34 2002/05/09 09:35:05 kls Exp $
|
# $Id: Makefile 1.35 2002/05/10 10:24:46 kls Exp $
|
||||||
|
|
||||||
.DELETE_ON_ERROR:
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ INCLUDES = -I$(DVBDIR)/ost/include
|
|||||||
DTVLIB = $(DTVDIR)/libdtv.a
|
DTVLIB = $(DTVDIR)/libdtv.a
|
||||||
|
|
||||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.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\
|
menuitems.o osdbase.o osd.o plugin.o recording.o remote.o remux.o ringbuffer.o\
|
||||||
svdrp.o thread.o tools.o vdr.o videodir.o
|
svdrp.o thread.o tools.o vdr.o videodir.o
|
||||||
|
|
||||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||||
|
207
PLUGINS.html
207
PLUGINS.html
@ -15,7 +15,10 @@ VDR code (and all the problems of correlating various patches).
|
|||||||
This document describes the "outside" interface of the plugin system.
|
This document describes the "outside" interface of the plugin system.
|
||||||
It handles everything necessary for a plugin to get hooked into the core
|
It handles everything necessary for a plugin to get hooked into the core
|
||||||
VDR program and present itself to the user.
|
VDR program and present itself to the user.
|
||||||
|
<p>
|
||||||
|
<!--X1.1.1--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||||
|
Important modifications introduced in version 1.1.1 are marked like this.
|
||||||
|
<!--X1.1.1--></td></tr></table>
|
||||||
<!--<p>TODO: Link to the document about VDR base classes to use when implementing actual functionality (yet to be written).-->
|
<!--<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>
|
<hr><h2>Quick start</h2>
|
||||||
@ -25,12 +28,12 @@ VDR program and present itself to the user.
|
|||||||
Actually you should read this entire document before starting to work with VDR plugins,
|
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>
|
but you probably want to see something happening right away <tt>;-)</tt>
|
||||||
<p>
|
<p>
|
||||||
So, for a quick demonstration of the plugin system, there is a demo plugin called
|
So, for a quick demonstration of the plugin system, there is a sample plugin called
|
||||||
"hello" that comes with the VDR source. To test drive this one, do the following:
|
"hello" that comes with the VDR source. To test drive this one, do the following:
|
||||||
<ul>
|
<ul>
|
||||||
<li>change into the VDR source directory
|
<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><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>do <b><tt>make plugins</tt></b> to build the plugin
|
||||||
<li>run VDR with <b><tt>vdr -V</tt></b> to see the version information
|
<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 -h</tt></b> to see the command line options
|
||||||
<li>run VDR with <b><tt>vdr -Phello</tt></b>
|
<li>run VDR with <b><tt>vdr -Phello</tt></b>
|
||||||
@ -74,16 +77,14 @@ is used:
|
|||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
VDR/PLUGINS/SRC
|
VDR/PLUGINS/SRC
|
||||||
VDR/PLUGINS/SRC/demo
|
|
||||||
VDR/PLUGINS/SRC/hello
|
VDR/PLUGINS/SRC/hello
|
||||||
VDR/PLUGINS/lib
|
VDR/PLUGINS/lib
|
||||||
VDR/PLUGINS/lib/libvdr-demo.so.1.1.0
|
|
||||||
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
|
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
The <tt>SRC</tt> directory contains one subdirectory for each plugin, which carries
|
The <tt>SRC</tt> directory contains one subdirectory for each plugin, which carries
|
||||||
the name of that plugin (in the above example that would be <tt>demo</tt> and
|
the name of that plugin (in the above example that would be <tt>hello</tt>).
|
||||||
<tt>hello</tt>, respectively). What's inside the individual source directory of a
|
What's inside the individual source directory of a
|
||||||
plugin is entirely up to the author of that plugin. The only prerequisites are
|
plugin is entirely up to the author of that plugin. The only prerequisites are
|
||||||
that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt> and
|
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
|
<tt>clean</tt>, and that a call to <tt>make all</tt> actually produces a dynamically
|
||||||
@ -93,7 +94,7 @@ The <tt>lib</tt> directory contains the dynamically loadable libraries of all
|
|||||||
available plugins. Note that the names of these files are created by concatenating
|
available plugins. Note that the names of these files are created by concatenating
|
||||||
<p>
|
<p>
|
||||||
<table border=2>
|
<table border=2>
|
||||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>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><b><tt>libvdr-</tt></b></td><td align=center><b><tt>hello</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1.1.0</tt></b></td></tr>
|
||||||
<tr><td align=center><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>
|
<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>
|
</table>
|
||||||
<p>
|
<p>
|
||||||
@ -109,25 +110,25 @@ each of these directories.
|
|||||||
If you download a plugin <a href="#Building the distribution package">package</a>
|
If you download a plugin <a href="#Building the distribution package">package</a>
|
||||||
from the web, it will typically have a name like
|
from the web, it will typically have a name like
|
||||||
<p>
|
<p>
|
||||||
<tt>vdr-demo-0.0.1.tgz</tt>
|
<tt>vdr-hello-0.0.1.tgz</tt>
|
||||||
<p>
|
<p>
|
||||||
and will unpack into a directory named
|
and will unpack into a directory named
|
||||||
<p>
|
<p>
|
||||||
<tt>vdr-demo-0.0.1</tt>
|
<tt>vdr-hello-0.0.1</tt>
|
||||||
<p>
|
<p>
|
||||||
To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>Makefile</tt>
|
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
|
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
|
create a symbolic link with the basic plugin name, as in
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
ln -s vdr-demo-0.0.1 demo
|
ln -s vdr-hello-0.0.1 hello
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
Since the VDR <tt>Makefile</tt> only searches for directories with names consisting
|
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
|
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
|
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
|
have several different versions of a plugin source (like <tt>vdr-hello-0.0.1</tt> and
|
||||||
<tt>vdr-demo-0.0.2</tt>) and define which one to actually use through the symbolic link.
|
<tt>vdr-hello-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>
|
<a name="Initializing a new plugin directory"><hr><h2>Initializing a new plugin directory</h2>
|
||||||
|
|
||||||
@ -174,7 +175,7 @@ If your plugin shall not be accessible through VDR's main menu, simply remove
|
|||||||
At the end of the plugin's source file you will find a line that looks like this:
|
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>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
VDRPLUGINCREATOR(cPluginDemo);
|
VDRPLUGINCREATOR(cPluginHello);
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
This is the "magic" hook that allows VDR to actually load the plugin into
|
This is the "magic" hook that allows VDR to actually load the plugin into
|
||||||
@ -182,6 +183,40 @@ its memory. You don't need to worry about the details behind all this.
|
|||||||
<p>
|
<p>
|
||||||
If your plugin requires additional source files, simply add them to your plugin's
|
If your plugin requires additional source files, simply add them to your plugin's
|
||||||
source directory and adjust the <tt>Makefile</tt> accordingly.
|
source directory and adjust the <tt>Makefile</tt> accordingly.
|
||||||
|
<p>
|
||||||
|
<!--X1.1.1--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||||
|
Header files usually contain preprocessor statements that prevent the same
|
||||||
|
file (or rather its contents, to be precise) from being included more than once, like
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
#ifndef __I18N_H
|
||||||
|
#define __I18N_H
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
#endif //__I18N_H
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
The example shown here is the way VDR does this in its core source files.
|
||||||
|
It takes the header file's name, converts it to all uppercase, replaces the
|
||||||
|
dot with an underline and preceedes the whole thing with two underlines.
|
||||||
|
The GNU library header files do this pretty much the same way, except that they
|
||||||
|
usually precede the name with only one underline (there are exceptions, though).
|
||||||
|
<p>
|
||||||
|
As long as you make shure that none of your plugin's header files will be named
|
||||||
|
like one of VDR's header files, you can use the same method as VDR. However,
|
||||||
|
if you want to name a header file like one that is already existing in VDR's
|
||||||
|
source (<tt>i18n.h</tt> would be a possible candidate for this), you may want
|
||||||
|
to make sure that the macros used here don't clash. How you do this is completely
|
||||||
|
up to you. You could, for instance, prepend the macro with a <tt>'P'</tt>, as in
|
||||||
|
<tt>P__I18N_H</tt>, or leave out the trailing <tt>_H</tt>, as in <tt>__I18N</tt>,
|
||||||
|
or use a completely different way to make sure a header file is included only once.
|
||||||
|
<p>
|
||||||
|
The 'hello' example that comes with VDR makes use of <a href="#Internationalization">internationalization</a>
|
||||||
|
and implements a file named <tt>i18n.h</tt>. To make sure it won't clash with VDR's
|
||||||
|
<tt>i18n.h</tt> it uses the macro <tt>_I18N__H</tt> (one underline at the beginning
|
||||||
|
and two replacing the dot).
|
||||||
|
<!--X1.1.1--></td></tr></table>
|
||||||
|
|
||||||
<hr><h2>Construction and Destruction</h2>
|
<hr><h2>Construction and Destruction</h2>
|
||||||
|
|
||||||
@ -230,9 +265,7 @@ Here's an example:
|
|||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
static const char *VERSION = "0.0.1";
|
static const char *VERSION = "0.0.1";
|
||||||
|
|
||||||
...
|
const char *cPluginHello::Version(void)
|
||||||
|
|
||||||
const char *cPluginDemo::Version(void)
|
|
||||||
{
|
{
|
||||||
return VERSION;
|
return VERSION;
|
||||||
}
|
}
|
||||||
@ -265,15 +298,20 @@ In order to tell the user what exactly a plugin does, it must implement the func
|
|||||||
virtual const char *Description(void) = 0;
|
virtual const char *Description(void) = 0;
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
which returns a short, one line description of the plugin's purpose.
|
which returns a short, one line description of the plugin's purpose:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
static const char *DESCRIPTION = "A friendly greeting";
|
||||||
|
|
||||||
virtual const char *Description(void)
|
virtual const char *Description(void)
|
||||||
{
|
{
|
||||||
return "A simple demo plugin";
|
return tr(DESCRIPTION);
|
||||||
}
|
}
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
Note the <tt>tr()</tt> around the <tt>DESCRIPTION</tt>, which allows the description
|
||||||
|
to be <a href="#Internationalization">internationalized</a>.
|
||||||
|
|
||||||
<hr><h2>Command line arguments</h2>
|
<hr><h2>Command line arguments</h2>
|
||||||
|
|
||||||
<center><i><b>Taking orders</b></i></center><p>
|
<center><i><b>Taking orders</b></i></center><p>
|
||||||
@ -300,20 +338,21 @@ will survive the entire lifetime of the plugin, so it is safe to store pointers
|
|||||||
these values inside the plugin. Here's an example:
|
these values inside the plugin. Here's an example:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
bool cPluginDemo::ProcessArgs(int argc, char *argv[])
|
bool cPluginHello::ProcessArgs(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
// Implement command line argument processing here if applicable.
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{ "aaa", required_argument, NULL, 'a' },
|
{ "aaa", required_argument, NULL, 'a' },
|
||||||
{ "bbb", no_argument, NULL, 'b' },
|
{ "bbb", no_argument, NULL, 'b' },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'a': fprintf(stderr, "option -a = %s\n", optarg);
|
case 'a': option_a = optarg;
|
||||||
break;
|
break;
|
||||||
case 'b': fprintf(stderr, "option -b\n");
|
case 'b': option_b = true;
|
||||||
break;
|
break;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
@ -342,8 +381,9 @@ The returned string should contain the command line help for this plugin, format
|
|||||||
in the same way as done by VDR itself:
|
in the same way as done by VDR itself:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
const char *cPluginDemo::CommandLineHelp(void)
|
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"
|
return " -a ABC, --aaa=ABC do something nice with ABC\n"
|
||||||
" -b, --bbb activate 'plan B'\n";
|
" -b, --bbb activate 'plan B'\n";
|
||||||
}
|
}
|
||||||
@ -392,9 +432,11 @@ 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:
|
plugin that will have a main menu item:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
const char *cPluginDemo::MainMenuEntry(void)
|
static const char *MAINMENUENTRY = "Hello";
|
||||||
|
|
||||||
|
const char *cPluginHello::MainMenuEntry(void)
|
||||||
{
|
{
|
||||||
return "Demo";
|
return tr(MAINMENUENTRY);
|
||||||
}
|
}
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
@ -440,7 +482,7 @@ virtual cMenuSetupPage *SetupMenu(void);
|
|||||||
virtual bool SetupParse(const char *Name, const char *Value);
|
virtual bool SetupParse(const char *Name, const char *Value);
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
The <tt>SetupMenu()</tt> function shall return the plugin's "Setup" menu
|
The <tt>SetupMenu()</tt> function shall return the plugin's <a href="#The Setup menu"><i>Setup</i> menu</a>
|
||||||
page, where the user can adjust all the parameters known to this plugin.
|
page, where the user can adjust all the parameters known to this plugin.
|
||||||
<p>
|
<p>
|
||||||
<tt>SetupParse()</tt> will be called for each parameter the plugin has
|
<tt>SetupParse()</tt> will be called for each parameter the plugin has
|
||||||
@ -448,13 +490,30 @@ 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
|
<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
|
an error. If <i>false</i> is returned, an error message will be written to
|
||||||
the log file (and program execution will continue).
|
the log file (and program execution will continue).
|
||||||
|
<!--X1.1.1--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||||
|
A possible implementation of <tt>SetupParse()</tt> could look like this:
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||||
|
{
|
||||||
|
// Parse your own setup parameters and store their values.
|
||||||
|
if (!strcasecmp(Name, "GreetingTime")) GreetingTime = atoi(Value);
|
||||||
|
else if (!strcasecmp(Name, "UseAlternateGreeting")) UseAlternateGreeting = atoi(Value);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
It is important to make sure that the parameter names are exactly the same as
|
||||||
|
used in the <a href="#The Setup menu"><i>Setup</i> menu</a>'s <tt>Store()</tt> function.
|
||||||
|
<!--X1.1.1--></td></tr></table>
|
||||||
<p>
|
<p>
|
||||||
The plugin's setup parameters are stored in the same file as VDR's parameters.
|
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,
|
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
|
the <tt>Name</tt> of each parameter will be preceeded with the plugin's
|
||||||
name, as in
|
name, as in
|
||||||
<p>
|
<p>
|
||||||
<tt>demo.SomeParameter = 123</tt>
|
<tt>hello.GreetingTime = 3</tt>
|
||||||
<p>
|
<p>
|
||||||
The prefix will be handled by the core VDR setup code, so the individual
|
The prefix will be handled by the core VDR setup code, so the individual
|
||||||
plugins need not worry about this.
|
plugins need not worry about this.
|
||||||
@ -465,8 +524,8 @@ To store its values in the global setup, a plugin has to call the function
|
|||||||
void SetupStore(const char *Name, <i>type</i> Value);
|
void SetupStore(const char *Name, <i>type</i> Value);
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
where <tt>Name</tt> is the name of the parameter (<tt>"SomeParameter"</tt> in the above
|
where <tt>Name</tt> is the name of the parameter (<tt>"GreetingTime"</tt> in the above
|
||||||
example, without the prefix <tt>"demo."</tt>) and <tt>Value</tt> is a simple data type (like
|
example, without the prefix <tt>"hello."</tt>) and <tt>Value</tt> is a simple data type (like
|
||||||
<tt>char *</tt>, <tt>int</tt> etc).
|
<tt>char *</tt>, <tt>int</tt> etc).
|
||||||
Note that this is not a function that the individual plugin class needs to implement!
|
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.
|
<tt>SetupStore()</tt> is a non-virtual member function of the <tt>cPlugin</tt> class.
|
||||||
@ -474,7 +533,7 @@ Note that this is not a function that the individual plugin class needs to imple
|
|||||||
To remove a parameter from the setup data, call <tt>SetupStore()</tt> with the appropriate
|
To remove a parameter from the setup data, call <tt>SetupStore()</tt> with the appropriate
|
||||||
name and without any value, as in
|
name and without any value, as in
|
||||||
<p>
|
<p>
|
||||||
<tt>SetupStore("SomeParameter");</tt>
|
<tt>SetupStore("GreetingTime");</tt>
|
||||||
<p>
|
<p>
|
||||||
The VDR menu "Setup/Plugins" will list all loaded plugins with their name,
|
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
|
version number and description. Selecting an item in this list will bring up
|
||||||
@ -486,6 +545,66 @@ needs setup parameters that are not directly user adjustable. It can use
|
|||||||
<tt>SetupStore()</tt> and <tt>SetupParse()</tt> without presenting these
|
<tt>SetupStore()</tt> and <tt>SetupParse()</tt> without presenting these
|
||||||
parameters to the user.
|
parameters to the user.
|
||||||
|
|
||||||
|
<!--X1.1.1--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||||
|
<a name="The Setup menu"><hr><h2>The Setup menu</h2>
|
||||||
|
|
||||||
|
<center><i><b>Have it your way!</b></i></center><p>
|
||||||
|
|
||||||
|
To implement a <i>Setup</i> menu, a plugin needs to derive a class from
|
||||||
|
<tt>cMenuSetupPage</tt> and implement its constructor and the pure virtual
|
||||||
|
<tt>Store()</tt> member function:
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
int GreetingTime = 3;
|
||||||
|
int UseAlternateGreeting = false;
|
||||||
|
|
||||||
|
class cMenuSetupHello : public cMenuSetupPage {
|
||||||
|
private:
|
||||||
|
int newGreetingTime;
|
||||||
|
int newUseAlternateGreeting;
|
||||||
|
protected:
|
||||||
|
virtual void Store(void);
|
||||||
|
public:
|
||||||
|
cMenuSetupHello(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuSetupHello::cMenuSetupHello(void)
|
||||||
|
{
|
||||||
|
newGreetingTime = GreetingTime;
|
||||||
|
newUseAlternateGreeting = UseAlternateGreeting;
|
||||||
|
Add(new cMenuEditIntItem( tr("Greeting time (s)"), &newGreetingTime));
|
||||||
|
Add(new cMenuEditBoolItem(tr("Use alternate greeting"), &newUseAlternateGreeting));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuSetupHello::Store(void)
|
||||||
|
{
|
||||||
|
SetupStore("GreetingTime", GreetingTime = newGreetingTime);
|
||||||
|
SetupStore("UseAlternateGreeting", UseAlternateGreeting = newUseAlternateGreeting);
|
||||||
|
}
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
In this example we have two global setup parameters (<tt>GreetingTime</tt> and <tt>UseAlternateGreeting</tt>).
|
||||||
|
The constructor initializes two private members with the values of these parameters, so
|
||||||
|
that the <i>Setup</i> menu can work with temporary copies (in order to discard any changes
|
||||||
|
if the user doesn't confirm them by pressing the "Ok" button).
|
||||||
|
After this the constructor adds the appropriate menu items, using internationalized texts
|
||||||
|
and the addresses of the temporary variables. That's all there is to inizialize a <i>Setup</i>
|
||||||
|
menu - the rest will be done by the core VDR code.
|
||||||
|
<p>
|
||||||
|
Once the user has pressed the "Ok" button to confirm the changes, the <tt>Store()</tt> function will
|
||||||
|
be called, in which all setup parameters must be actually stored in VDR's global setup data.
|
||||||
|
This is done by calling the <tt>SetupStore()</tt> function for each of the parameters.
|
||||||
|
The <i>Name</i> string given here will be used to identify the parameter in VDR's
|
||||||
|
<tt>setup.conf</tt> file, and will be automatically prepended with the plugin's name.
|
||||||
|
<p>
|
||||||
|
Note that in this small example the new values of the parameters are copied into the
|
||||||
|
global variables within each <tt>SetupStore()</tt> call. This is not mandatory, however.
|
||||||
|
You can first assign the temporary values to the global variables and then do the
|
||||||
|
<tt>SetupStore()</tt> calls, or you can define a class or struct that contains all
|
||||||
|
your setup parameters and use that one to copy all parameters with one single statement
|
||||||
|
(like VDR does with its cSetup class).
|
||||||
|
<!--X1.1.1--></td></tr></table>
|
||||||
|
|
||||||
<a name="Internationalization"><hr><h2>Internationalization</h2>
|
<a name="Internationalization"><hr><h2>Internationalization</h2>
|
||||||
|
|
||||||
<center><i><b>Welcome to Babylon!</b></i></center><p>
|
<center><i><b>Welcome to Babylon!</b></i></center><p>
|
||||||
@ -519,7 +638,7 @@ const tI18nPhrase Phrases[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
void cPluginDemo::Start(void)
|
void cPluginHello::Start(void)
|
||||||
{
|
{
|
||||||
RegisterI18n(Phrases);
|
RegisterI18n(Phrases);
|
||||||
}
|
}
|
||||||
@ -557,20 +676,20 @@ core VDR code.
|
|||||||
Plugins are loaded into VDR using the command line option <b><tt>-P</tt></b>, as in
|
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>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
vdr -Pdemo
|
vdr -Phello
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
If the plugin accepts command line options, they are given as part of the argument
|
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:
|
to the <b><tt>-P</tt></b> option, which then has to be enclosed in quotes:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
vdr -P"demo -a abc -b"
|
vdr -P"hello -a abc -b"
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option:
|
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>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
vdr -P"demo -a abc -b" -Pdvd -Pmp3
|
vdr -P"hello -a abc -b" -Pdvd -Pmp3
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
If you are not starting VDR from the VDR source directory (and thus your plugins
|
If you are not starting VDR from the VDR source directory (and thus your plugins
|
||||||
@ -578,7 +697,7 @@ 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:
|
the plugins through the <b><tt>-L</tt></b> option:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
vdr -L/usr/lib/vdr -Pdemo
|
vdr -L/usr/lib/vdr -Phello
|
||||||
</pre></td></tr></table><p>
|
</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
|
There can be any number of <b><tt>-L</tt></b> options, and each of them will apply to the
|
||||||
@ -603,17 +722,17 @@ provides the target <tt>package</tt>, which does this for you.
|
|||||||
Simply change into your source directory and execute <tt>make package</tt>:
|
Simply change into your source directory and execute <tt>make package</tt>:
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
cd VDR/PLUGINS/SRC/demo
|
cd VDR/PLUGINS/SRC/hello
|
||||||
make package
|
make package
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
After this you should find a file named like
|
After this you should find a file named like
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
vdr-demo-0.0.1.tgz
|
vdr-hello-0.0.1.tgz
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
in your source directory, where <tt>demo</tt> will be replaced with your actual
|
in your source directory, where <tt>hello</tt> will be replaced with your actual
|
||||||
plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
|
plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -4,3 +4,7 @@ VDR Plugin 'hello' Revision History
|
|||||||
2002-05-09: Version 0.0.1
|
2002-05-09: Version 0.0.1
|
||||||
|
|
||||||
- Initial revision.
|
- Initial revision.
|
||||||
|
|
||||||
|
2002-05-11: Version 0.0.2
|
||||||
|
|
||||||
|
- Added setup parameters and a Setup menu to adjust them.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: hello.c 1.1 2002/05/09 15:28:51 kls Exp $
|
* $Id: hello.c 1.2 2002/05/11 14:17:20 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
#include <vdr/plugin.h>
|
#include <vdr/plugin.h>
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
static const char *VERSION = "0.0.1";
|
static const char *VERSION = "0.0.2";
|
||||||
static const char *DESCRIPTION = "A friendly greeting";
|
static const char *DESCRIPTION = "A friendly greeting";
|
||||||
static const char *MAINMENUENTRY = "Hello";
|
static const char *MAINMENUENTRY = "Hello";
|
||||||
|
|
||||||
@ -34,6 +34,39 @@ public:
|
|||||||
virtual bool SetupParse(const char *Name, const char *Value);
|
virtual bool SetupParse(const char *Name, const char *Value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Global variables that control the overall behaviour:
|
||||||
|
|
||||||
|
int GreetingTime = 3;
|
||||||
|
int UseAlternateGreeting = false;
|
||||||
|
|
||||||
|
// --- cMenuSetupHello -------------------------------------------------------
|
||||||
|
|
||||||
|
class cMenuSetupHello : public cMenuSetupPage {
|
||||||
|
private:
|
||||||
|
int newGreetingTime;
|
||||||
|
int newUseAlternateGreeting;
|
||||||
|
protected:
|
||||||
|
virtual void Store(void);
|
||||||
|
public:
|
||||||
|
cMenuSetupHello(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuSetupHello::cMenuSetupHello(void)
|
||||||
|
{
|
||||||
|
newGreetingTime = GreetingTime;
|
||||||
|
newUseAlternateGreeting = UseAlternateGreeting;
|
||||||
|
Add(new cMenuEditIntItem( tr("Greeting time (s)"), &newGreetingTime));
|
||||||
|
Add(new cMenuEditBoolItem(tr("Use alternate greeting"), &newUseAlternateGreeting));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuSetupHello::Store(void)
|
||||||
|
{
|
||||||
|
SetupStore("GreetingTime", GreetingTime = newGreetingTime);
|
||||||
|
SetupStore("UseAlternateGreeting", UseAlternateGreeting = newUseAlternateGreeting);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cPluginHello ----------------------------------------------------------
|
||||||
|
|
||||||
cPluginHello::cPluginHello(void)
|
cPluginHello::cPluginHello(void)
|
||||||
{
|
{
|
||||||
// Initialize any member varaiables here.
|
// Initialize any member varaiables here.
|
||||||
@ -86,20 +119,24 @@ void cPluginHello::Start(void)
|
|||||||
cOsdMenu *cPluginHello::MainMenuAction(void)
|
cOsdMenu *cPluginHello::MainMenuAction(void)
|
||||||
{
|
{
|
||||||
// Perform the action when selected from the main VDR menu.
|
// Perform the action when selected from the main VDR menu.
|
||||||
Interface->Info(tr("Hello world!"));
|
Interface->Confirm(UseAlternateGreeting ? tr("Howdy folks!") : tr("Hello world!"), GreetingTime);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cMenuSetupPage *cPluginHello::SetupMenu(void)
|
cMenuSetupPage *cPluginHello::SetupMenu(void)
|
||||||
{
|
{
|
||||||
// Return a setup menu in case the plugin supports one.
|
// Return a setup menu in case the plugin supports one.
|
||||||
return NULL;
|
return new cMenuSetupHello;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||||
{
|
{
|
||||||
// Parse your own setup parameters and store their values.
|
// Parse your own setup parameters and store their values.
|
||||||
return false;
|
if (!strcasecmp(Name, "GreetingTime")) GreetingTime = atoi(Value);
|
||||||
|
else if (!strcasecmp(Name, "UseAlternateGreeting")) UseAlternateGreeting = atoi(Value);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
VDRPLUGINCREATOR(cPluginHello); // Don't touch this!
|
VDRPLUGINCREATOR(cPluginHello); // Don't touch this!
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: i18n.c 1.1 2002/05/09 15:13:31 kls Exp $
|
* $Id: i18n.c 1.2 2002/05/11 12:27:00 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
@ -35,6 +35,19 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"",// TODO
|
"",// TODO
|
||||||
"",// TODO
|
"",// TODO
|
||||||
},
|
},
|
||||||
|
{ "Howdy folks!",
|
||||||
|
"Tach zusammen!",
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
},
|
||||||
{ "A friendly greeting",
|
{ "A friendly greeting",
|
||||||
"Ein freundlicher Gruß",
|
"Ein freundlicher Gruß",
|
||||||
"",// TODO
|
"",// TODO
|
||||||
@ -48,5 +61,31 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"",// TODO
|
"",// TODO
|
||||||
"",// TODO
|
"",// TODO
|
||||||
},
|
},
|
||||||
|
{ "Greeting time (s)",
|
||||||
|
"Dauer des Grußes (s)",
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
},
|
||||||
|
{ "Use alternate greeting",
|
||||||
|
"Alternativen Gruß verwenden",
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
},
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
@ -3,9 +3,14 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: i18n.h 1.1 2002/05/09 15:15:49 kls Exp $
|
* $Id: i18n.h 1.2 2002/05/11 14:48:16 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _I18N__H
|
||||||
|
#define _I18N__H
|
||||||
|
|
||||||
#include <vdr/i18n.h>
|
#include <vdr/i18n.h>
|
||||||
|
|
||||||
extern const tI18nPhrase Phrases[];
|
extern const tI18nPhrase Phrases[];
|
||||||
|
|
||||||
|
#endif //_I18N__H
|
||||||
|
11
config.c
11
config.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.c 1.99 2002/05/05 09:10:00 kls Exp $
|
* $Id: config.c 1.100 2002/05/11 12:05:22 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -1073,14 +1073,19 @@ bool cSetup::Load(const char *FileName)
|
|||||||
if (cConfig<cSetupLine>::Load(FileName, true)) {
|
if (cConfig<cSetupLine>::Load(FileName, true)) {
|
||||||
bool result = true;
|
bool result = true;
|
||||||
for (cSetupLine *l = First(); l; l = Next(l)) {
|
for (cSetupLine *l = First(); l; l = Next(l)) {
|
||||||
|
bool error = false;
|
||||||
if (l->Plugin()) {
|
if (l->Plugin()) {
|
||||||
cPlugin *p = cPluginManager::GetPlugin(l->Plugin());
|
cPlugin *p = cPluginManager::GetPlugin(l->Plugin());
|
||||||
if (p && !p->SetupParse(l->Name(), l->Value()))
|
if (p && !p->SetupParse(l->Name(), l->Value()))
|
||||||
result = false;
|
error = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!Parse(l->Name(), l->Value()))
|
if (!Parse(l->Name(), l->Value()))
|
||||||
result = false;
|
error = true;
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
esyslog(LOG_ERR, "ERROR: unknown config parameter: %s%s%s = %s", l->Plugin() ? l->Plugin() : "", l->Plugin() ? "." : "", l->Name(), l->Value());
|
||||||
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
4
config.h
4
config.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.h 1.113 2002/05/04 14:29:29 kls Exp $
|
* $Id: config.h 1.114 2002/05/10 13:48:00 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CONFIG_H
|
#ifndef __CONFIG_H
|
||||||
@ -19,7 +19,7 @@
|
|||||||
#include "eit.h"
|
#include "eit.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#define VDRVERSION "1.1.0"
|
#define VDRVERSION "1.1.1"
|
||||||
|
|
||||||
#define MAXPRIORITY 99
|
#define MAXPRIORITY 99
|
||||||
#define MAXLIFETIME 99
|
#define MAXLIFETIME 99
|
||||||
|
553
dvbosd.c
553
dvbosd.c
@ -1,383 +1,45 @@
|
|||||||
/*
|
/*
|
||||||
* dvbosd.c: Interface to the DVB On Screen Display
|
* dvbosd.c: Implementation of the DVB On Screen Display
|
||||||
*
|
*
|
||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbosd.c 1.13 2002/04/13 11:34:48 kls Exp $
|
* $Id: dvbosd.c 1.14 2002/05/10 14:22:04 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbosd.h"
|
#include "dvbosd.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/unistd.h>
|
#include <sys/unistd.h>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
// --- cPalette --------------------------------------------------------------
|
cDvbOsd::cDvbOsd(int VideoDev, int x, int y)
|
||||||
|
:cOsd(x, y)
|
||||||
cPalette::cPalette(int Bpp)
|
|
||||||
{
|
|
||||||
maxColors = 1 << Bpp;
|
|
||||||
numColors = 0;
|
|
||||||
full = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!full) {
|
|
||||||
if (numColors < maxColors) {
|
|
||||||
color[numColors++] = Color;
|
|
||||||
used[numColors - 1] = true;
|
|
||||||
fetched[numColors - 1] = false;
|
|
||||||
return numColors - 1;
|
|
||||||
}
|
|
||||||
for (int i = maxColors; --i >= 0; ) {
|
|
||||||
if (!used[i]) {
|
|
||||||
color[i] = Color;
|
|
||||||
used[i] = true;
|
|
||||||
fetched[i] = false;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
esyslog(LOG_ERR, "ERROR: too many different colors used in palette");
|
|
||||||
full = true;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cPalette::Reset(void)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < numColors; i++)
|
|
||||||
used[i] = false;
|
|
||||||
full = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor)
|
|
||||||
{
|
|
||||||
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
|
|
||||||
if (!fetched[FirstColor]) {
|
|
||||||
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
|
|
||||||
fetched[LastColor] = true;
|
|
||||||
LastColor--; // the loop ended one past the last one!
|
|
||||||
return &color[FirstColor];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Palette.numColors; i++) {
|
|
||||||
if (Palette.used[i]) {
|
|
||||||
int n = Index(Palette.color[i]);
|
|
||||||
if (Indexes)
|
|
||||||
(*Indexes)[i] = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cBitmap ---------------------------------------------------------------
|
|
||||||
|
|
||||||
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
|
||||||
:cPalette(Bpp)
|
|
||||||
{
|
|
||||||
width = Width;
|
|
||||||
height = Height;
|
|
||||||
clearWithBackground = ClearWithBackground;
|
|
||||||
bitmap = NULL;
|
|
||||||
fontType = fontOsd;
|
|
||||||
font = NULL;
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
bitmap = new char[width * height];
|
|
||||||
if (bitmap) {
|
|
||||||
Clean();
|
|
||||||
memset(bitmap, 0x00, width * height);
|
|
||||||
SetFont(fontOsd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog(LOG_ERR, "ERROR: can't allocate bitmap!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog(LOG_ERR, "ERROR: illegal bitmap parameters (%d, %d)!", width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
cBitmap::~cBitmap()
|
|
||||||
{
|
|
||||||
delete font;
|
|
||||||
delete bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
eDvbFont cBitmap::SetFont(eDvbFont Font)
|
|
||||||
{
|
|
||||||
eDvbFont oldFont = fontType;
|
|
||||||
if (fontType != Font || !font) {
|
|
||||||
delete font;
|
|
||||||
font = new cFont(Font);
|
|
||||||
fontType = Font;
|
|
||||||
}
|
|
||||||
return oldFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
|
|
||||||
{
|
|
||||||
if (dirtyX2 >= 0) {
|
|
||||||
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
|
||||||
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
|
||||||
//TODO Fix driver (should be able to handle any size bitmaps!)
|
|
||||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
|
|
||||||
if (dirtyX2 < width - 1)
|
|
||||||
dirtyX2++;
|
|
||||||
else if (dirtyX1 > 0)
|
|
||||||
dirtyX1--;
|
|
||||||
}
|
|
||||||
//XXX "... / 2" <==> Bpp???
|
|
||||||
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
|
||||||
if (dirtyY2 < height - 1)
|
|
||||||
dirtyY2++;
|
|
||||||
else if (dirtyY1 > 0)
|
|
||||||
dirtyY1--;
|
|
||||||
}
|
|
||||||
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
|
||||||
if (dirtyX2 < width - 1)
|
|
||||||
dirtyX2++;
|
|
||||||
else if (dirtyX1 > 0)
|
|
||||||
dirtyX1--;
|
|
||||||
}
|
|
||||||
x1 = dirtyX1;
|
|
||||||
y1 = dirtyY1;
|
|
||||||
x2 = dirtyX2;
|
|
||||||
y2 = dirtyY2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::Clean(void)
|
|
||||||
{
|
|
||||||
dirtyX1 = width;
|
|
||||||
dirtyY1 = height;
|
|
||||||
dirtyX2 = -1;
|
|
||||||
dirtyY2 = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::SetIndex(int x, int y, char Index)
|
|
||||||
{
|
|
||||||
if (bitmap) {
|
|
||||||
if (0 <= x && x < width && 0 <= y && y < height) {
|
|
||||||
if (bitmap[width * y + x] != Index) {
|
|
||||||
bitmap[width * y + x] = Index;
|
|
||||||
if (dirtyX1 > x) dirtyX1 = x;
|
|
||||||
if (dirtyY1 > y) dirtyY1 = y;
|
|
||||||
if (dirtyX2 < x) dirtyX2 = x;
|
|
||||||
if (dirtyY2 < y) dirtyY2 = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
|
|
||||||
{
|
|
||||||
SetIndex(x, y, Index(Color));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
|
||||||
{
|
|
||||||
if (bitmap && Bitmap.bitmap) {
|
|
||||||
tIndexes Indexes;
|
|
||||||
Take(Bitmap, &Indexes);
|
|
||||||
for (int ix = 0; ix < Bitmap.width; ix++) {
|
|
||||||
for (int iy = 0; iy < Bitmap.height; iy++)
|
|
||||||
SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cBitmap::Width(unsigned char c)
|
|
||||||
{
|
|
||||||
return font ? font->Width(c) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cBitmap::Width(const char *s)
|
|
||||||
{
|
|
||||||
return font ? font->Width(s) : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
|
||||||
{
|
|
||||||
if (bitmap) {
|
|
||||||
char fg = Index(ColorFg);
|
|
||||||
char bg = Index(ColorBg);
|
|
||||||
int h = font->Height(s);
|
|
||||||
while (s && *s) {
|
|
||||||
const cFont::tCharData *CharData = font->CharData(*s++);
|
|
||||||
if (int(x + CharData->width) > width)
|
|
||||||
break;
|
|
||||||
for (int row = 0; row < h; row++) {
|
|
||||||
cFont::tPixelData PixelData = CharData->lines[row];
|
|
||||||
for (int col = CharData->width; col-- > 0; ) {
|
|
||||||
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
|
|
||||||
PixelData >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x += CharData->width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
|
||||||
{
|
|
||||||
if (bitmap) {
|
|
||||||
char c = Index(Color);
|
|
||||||
for (int y = y1; y <= y2; y++)
|
|
||||||
for (int x = x1; x <= x2; x++)
|
|
||||||
SetIndex(x, y, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cBitmap::Clear(void)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
if (clearWithBackground)
|
|
||||||
Fill(0, 0, width - 1, height - 1, clrBackground);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *cBitmap::Data(int x, int y)
|
|
||||||
{
|
|
||||||
return &bitmap[y * width + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cWindow ---------------------------------------------------------------
|
|
||||||
|
|
||||||
class cWindow : public cBitmap {
|
|
||||||
private:
|
|
||||||
int handle; // the index within the OSD's window array (0...MAXNUMWINDOWS - 1)
|
|
||||||
int x0, y0;
|
|
||||||
int bpp;
|
|
||||||
bool tiled;
|
|
||||||
bool shown;
|
|
||||||
public:
|
|
||||||
cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled);
|
|
||||||
int X0(void) { return x0; }
|
|
||||||
int Y0(void) { return y0; }
|
|
||||||
int Bpp(void) { return bpp; }
|
|
||||||
bool Tiled(void) { return tiled; }
|
|
||||||
bool Shown(void) { bool s = shown; shown = true; return s; }
|
|
||||||
int Handle(void) { return handle; }
|
|
||||||
bool Contains(int x, int y);
|
|
||||||
void Relocate(int x, int y);
|
|
||||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
|
||||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
|
||||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
|
||||||
const char *Data(int x, int y);
|
|
||||||
};
|
|
||||||
|
|
||||||
cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
|
||||||
:cBitmap(w, h, Bpp, ClearWithBackground)
|
|
||||||
{
|
|
||||||
handle = Handle;
|
|
||||||
x0 = x;
|
|
||||||
y0 = y;
|
|
||||||
bpp = Bpp;
|
|
||||||
tiled = Tiled;
|
|
||||||
shown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cWindow::Contains(int x, int y)
|
|
||||||
{
|
|
||||||
x -= x0;
|
|
||||||
y -= y0;
|
|
||||||
return x >= 0 && y >= 0 && x < width && y < height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cWindow::Relocate(int x, int y)
|
|
||||||
{
|
|
||||||
x0 = x;
|
|
||||||
y0 = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
|
||||||
{
|
|
||||||
if (tiled) {
|
|
||||||
x1 -= x0;
|
|
||||||
y1 -= y0;
|
|
||||||
x2 -= x0;
|
|
||||||
y2 -= y0;
|
|
||||||
}
|
|
||||||
cBitmap::Fill(x1, y1, x2, y2, Color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
|
||||||
{
|
|
||||||
if (tiled) {
|
|
||||||
x -= x0;
|
|
||||||
y -= y0;
|
|
||||||
}
|
|
||||||
cBitmap::SetBitmap(x, y, Bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
|
||||||
{
|
|
||||||
if (tiled) {
|
|
||||||
x -= x0;
|
|
||||||
y -= y0;
|
|
||||||
}
|
|
||||||
cBitmap::Text(x, y, s, ColorFg, ColorBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *cWindow::Data(int x, int y)
|
|
||||||
{
|
|
||||||
return cBitmap::Data(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cDvbOsd ---------------------------------------------------------------
|
|
||||||
|
|
||||||
cDvbOsd::cDvbOsd(int VideoDev, int x, int y, int w, int h, int Bpp)
|
|
||||||
{
|
{
|
||||||
videoDev = VideoDev;
|
videoDev = VideoDev;
|
||||||
numWindows = 0;
|
if (videoDev < 0)
|
||||||
x0 = x;
|
|
||||||
y0 = y;
|
|
||||||
if (videoDev >= 0) {
|
|
||||||
if (w > 0 && h > 0)
|
|
||||||
Create(0, 0, w, h, Bpp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
|
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
cDvbOsd::~cDvbOsd()
|
cDvbOsd::~cDvbOsd()
|
||||||
{
|
{
|
||||||
if (videoDev >= 0) {
|
for (int i = 0; i < NumWindows(); i++)
|
||||||
for (int i = 0; i < numWindows; i++) {
|
CloseWindow(GetWindowNr(i));
|
||||||
SetWindow(window[i]);
|
|
||||||
Cmd(OSD_Close);
|
|
||||||
delete window[i];
|
|
||||||
}
|
|
||||||
numWindows = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbOsd::SetWindow(cWindow *Window)
|
bool cDvbOsd::SetWindow(cWindow *Window)
|
||||||
{
|
{
|
||||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
if (Window) {
|
||||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||||
int Handle = Window->Handle();
|
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
int Handle = Window->Handle();
|
||||||
Cmd(OSD_SetWindow, 0, Handle + 1);
|
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||||
return true;
|
Cmd(OSD_SetWindow, 0, Handle + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
esyslog(LOG_ERR, "ERROR: illegal window handle: %d", Handle);
|
||||||
}
|
}
|
||||||
esyslog(LOG_ERR, "ERROR: illegal window handle: %d", Handle);
|
return false;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
||||||
@ -406,166 +68,51 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tWindowHandle cDvbOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
bool cDvbOsd::OpenWindow(cWindow *Window)
|
||||||
{
|
{
|
||||||
if (numWindows < MAXNUMWINDOWS) {
|
if (SetWindow(Window)) {
|
||||||
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
|
Cmd(OSD_Open, Window->Bpp(), X0() + Window->X0(), Y0() + Window->Y0(), X0() + Window->X0() + Window->Width() - 1, Y0() + Window->Y0() + Window->Height() - 1, (void *)1); // initially hidden!
|
||||||
if ((w & 0x03) != 0) {
|
return true;
|
||||||
w += 4 - (w & 0x03);
|
|
||||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
|
|
||||||
}
|
|
||||||
cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
|
|
||||||
if (SetWindow(win)) {
|
|
||||||
window[win->Handle()] = win;
|
|
||||||
Cmd(OSD_Open, Bpp, x0 + x, y0 + y, x0 + x + w - 1, y0 + y + h - 1, (void *)1); // initially hidden!
|
|
||||||
numWindows++;
|
|
||||||
return win->Handle();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
delete win;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog(LOG_ERR, "ERROR: illegal OSD parameters");
|
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
esyslog(LOG_ERR, "ERROR: too many OSD windows");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDvbOsd::AddColor(eDvbColor Color, tWindowHandle Window)
|
void cDvbOsd::CommitWindow(cWindow *Window)
|
||||||
{
|
{
|
||||||
cWindow *w = GetWindow(Window);
|
if (SetWindow(Window)) {
|
||||||
if (w) {
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||||
w->Index(Color);
|
if (Window->Dirty(x1, y1, x2, y2)) {
|
||||||
w->Reset();
|
// commit colors:
|
||||||
}
|
int FirstColor = 0, LastColor = 0;
|
||||||
}
|
const eDvbColor *pal;
|
||||||
|
while ((pal = Window->Colors(FirstColor, LastColor)) != NULL)
|
||||||
cWindow *cDvbOsd::GetWindow(int x, int y)
|
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
||||||
{
|
// commit modified data:
|
||||||
for (int i = 0; i < numWindows; i++) {
|
Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1));
|
||||||
if (window[i]->Tiled() && window[i]->Contains(x, y))
|
|
||||||
return window[i];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cWindow *cDvbOsd::GetWindow(tWindowHandle Window)
|
|
||||||
{
|
|
||||||
if (0 <= Window && Window < numWindows)
|
|
||||||
return window[Window];
|
|
||||||
if (Window == LAST_CREATED_WINDOW && numWindows > 0)
|
|
||||||
return window[numWindows - 1];
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::Flush(void)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < numWindows; i++) {
|
|
||||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
|
||||||
if (window[i]->Dirty(x1, y1, x2, y2)) {
|
|
||||||
SetWindow(window[i]);
|
|
||||||
int FirstColor = 0, LastColor = 0;
|
|
||||||
const eDvbColor *pal;
|
|
||||||
while ((pal = window[i]->Colors(FirstColor, LastColor)) != NULL)
|
|
||||||
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
|
||||||
Cmd(OSD_SetBlock, window[i]->Width(), x1, y1, x2, y2, window[i]->Data(x1, y1));
|
|
||||||
window[i]->Clean();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
|
||||||
for (int i = 0; i < numWindows; i++) {
|
|
||||||
if (!window[i]->Shown()) {
|
|
||||||
SetWindow(window[i]);
|
|
||||||
Cmd(OSD_MoveWindow, 0, x0 + window[i]->X0(), y0 + window[i]->Y0());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::Clear(tWindowHandle Window)
|
|
||||||
{
|
|
||||||
if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
|
|
||||||
for (int i = 0; i < numWindows; i++)
|
|
||||||
if (Window == ALL_WINDOWS || window[i]->Tiled())
|
|
||||||
window[i]->Clear();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cWindow *w = GetWindow(Window);
|
|
||||||
if (w)
|
|
||||||
w->Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
|
|
||||||
{
|
|
||||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
|
|
||||||
if (w)
|
|
||||||
w->Fill(x1, y1, x2, y2, Color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
|
|
||||||
{
|
|
||||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
|
||||||
if (w)
|
|
||||||
w->SetBitmap(x, y, Bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cDvbOsd::Width(unsigned char c)
|
|
||||||
{
|
|
||||||
return numWindows ? window[0]->Width(c) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cDvbOsd::Width(const char *s)
|
|
||||||
{
|
|
||||||
return numWindows ? window[0]->Width(s) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
eDvbFont cDvbOsd::SetFont(eDvbFont Font)
|
|
||||||
{
|
|
||||||
eDvbFont oldFont = Font;
|
|
||||||
for (int i = 0; i < numWindows; i++)
|
|
||||||
oldFont = window[i]->SetFont(Font);
|
|
||||||
return oldFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window)
|
|
||||||
{
|
|
||||||
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
|
||||||
if (w)
|
|
||||||
w->Text(x, y, s, ColorFg, ColorBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cDvbOsd::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
|
|
||||||
{
|
|
||||||
cWindow *w = GetWindow(Window);
|
|
||||||
if (w) {
|
|
||||||
SetWindow(w);
|
|
||||||
if (NewWidth > 0 && NewHeight > 0) {
|
|
||||||
if ((NewWidth & 0x03) != 0) {
|
|
||||||
NewWidth += 4 - (NewWidth & 0x03);
|
|
||||||
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
|
|
||||||
}
|
|
||||||
Cmd(OSD_Close);
|
|
||||||
window[w->Handle()] = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
|
|
||||||
delete w;
|
|
||||||
Cmd(OSD_Open, 2, x0 + x, y0 + y, x0 + x + NewWidth - 1, y0 + y + NewHeight - 1, (void *)1); // initially hidden!
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
w->Relocate(x, y);
|
|
||||||
Cmd(OSD_MoveWindow, 0, x0 + x, y0 + y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDvbOsd::Hide(tWindowHandle Window)
|
void cDvbOsd::ShowWindow(cWindow *Window)
|
||||||
{
|
{
|
||||||
if (SetWindow(GetWindow(Window)))
|
if (SetWindow(Window))
|
||||||
Cmd(OSD_Hide, 0);
|
Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDvbOsd::Show(tWindowHandle Window)
|
void cDvbOsd::HideWindow(cWindow *Window, bool Hide)
|
||||||
{
|
{
|
||||||
if (SetWindow(GetWindow(Window)))
|
if (SetWindow(Window))
|
||||||
Cmd(OSD_Show, 0);
|
Cmd(Hide ? OSD_Hide : OSD_Show, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cDvbOsd::MoveWindow(cWindow *Window, int x, int y)
|
||||||
|
{
|
||||||
|
if (SetWindow(Window))
|
||||||
|
Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDvbOsd::CloseWindow(cWindow *Window)
|
||||||
|
{
|
||||||
|
if (SetWindow(Window))
|
||||||
|
Cmd(OSD_Close);
|
||||||
|
}
|
||||||
|
171
dvbosd.h
171
dvbosd.h
@ -1,178 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* dvbosd.h: Interface to the DVB On Screen Display
|
* dvbosd.h: Implementation of the DVB On Screen Display
|
||||||
*
|
*
|
||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbosd.h 1.10 2002/02/03 16:43:50 kls Exp $
|
* $Id: dvbosd.h 1.11 2002/05/10 14:22:07 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBOSD_H
|
#ifndef __DVBOSD_H
|
||||||
#define __DVBOSD_H
|
#define __DVBOSD_H
|
||||||
|
|
||||||
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
|
||||||
#include <ncurses.h>
|
|
||||||
#undef ERR //XXX ncurses defines this - but this clashes with newer system header files
|
|
||||||
#endif
|
|
||||||
#include <ost/osd.h>
|
#include <ost/osd.h>
|
||||||
#include <stdio.h>
|
#include "osdbase.h"
|
||||||
#include "font.h"
|
|
||||||
|
|
||||||
#define MAXNUMCOLORS 16
|
class cDvbOsd : public cOsd {
|
||||||
|
|
||||||
enum eDvbColor {
|
|
||||||
#ifdef DEBUG_OSD
|
|
||||||
clrBackground,
|
|
||||||
clrTransparent = clrBackground,
|
|
||||||
clrBlack = clrBackground,
|
|
||||||
clrRed,
|
|
||||||
clrGreen,
|
|
||||||
clrYellow,
|
|
||||||
clrBlue,
|
|
||||||
clrMagenta,
|
|
||||||
clrCyan,
|
|
||||||
clrWhite,
|
|
||||||
#else
|
|
||||||
clrTransparent = 0x00000000,
|
|
||||||
clrBackground = 0x7F000000, // 50% gray
|
|
||||||
clrBlack = 0xFF000000,
|
|
||||||
clrRed = 0xFF1414FC,
|
|
||||||
clrGreen = 0xFF24FC24,
|
|
||||||
clrYellow = 0xFF24C0FC,
|
|
||||||
clrMagenta = 0xFFFC00B0,
|
|
||||||
clrBlue = 0xFFFC0000,
|
|
||||||
clrCyan = 0xFFFCFC00,
|
|
||||||
clrWhite = 0xFFFCFCFC,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class cPalette {
|
|
||||||
private:
|
|
||||||
eDvbColor color[MAXNUMCOLORS];
|
|
||||||
int maxColors, numColors;
|
|
||||||
bool used[MAXNUMCOLORS];
|
|
||||||
bool fetched[MAXNUMCOLORS];
|
|
||||||
bool full;
|
|
||||||
protected:
|
|
||||||
typedef unsigned char tIndexes[MAXNUMCOLORS];
|
|
||||||
public:
|
|
||||||
cPalette(int Bpp);
|
|
||||||
int Index(eDvbColor Color);
|
|
||||||
void Reset(void);
|
|
||||||
const eDvbColor *Colors(int &FirstColor, int &LastColor);
|
|
||||||
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
|
|
||||||
};
|
|
||||||
|
|
||||||
class cBitmap : public cPalette {
|
|
||||||
private:
|
|
||||||
cFont *font;
|
|
||||||
eDvbFont fontType;
|
|
||||||
void SetIndex(int x, int y, char Index);
|
|
||||||
char *bitmap;
|
|
||||||
bool clearWithBackground;
|
|
||||||
protected:
|
|
||||||
int width, height;
|
|
||||||
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
|
||||||
public:
|
|
||||||
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
|
|
||||||
virtual ~cBitmap();
|
|
||||||
bool ClearWithBackground(void) { return clearWithBackground; }
|
|
||||||
eDvbFont SetFont(eDvbFont Font);
|
|
||||||
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
|
||||||
void SetPixel(int x, int y, eDvbColor Color);
|
|
||||||
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
|
||||||
int Width(void) { return width; }
|
|
||||||
int Width(unsigned char c);
|
|
||||||
int Width(const char *s);
|
|
||||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
|
||||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
|
||||||
void Clean(void);
|
|
||||||
void Clear(void);
|
|
||||||
const char *Data(int x, int y);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
|
||||||
|
|
||||||
class cWindow;
|
|
||||||
|
|
||||||
typedef int tWindowHandle;
|
|
||||||
|
|
||||||
// '-1' is used as an error return value!
|
|
||||||
#define ALL_WINDOWS (-2)
|
|
||||||
#define ALL_TILED_WINDOWS (-3)
|
|
||||||
#define LAST_CREATED_WINDOW (-4)
|
|
||||||
|
|
||||||
class cDvbOsd {
|
|
||||||
private:
|
private:
|
||||||
int videoDev;
|
int videoDev;
|
||||||
int numWindows;
|
|
||||||
int x0, y0;
|
|
||||||
cWindow *window[MAXNUMWINDOWS];
|
|
||||||
bool SetWindow(cWindow *Window);
|
bool SetWindow(cWindow *Window);
|
||||||
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
|
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
|
||||||
cWindow *GetWindow(int x, int y);
|
protected:
|
||||||
cWindow *GetWindow(tWindowHandle Window);
|
virtual bool OpenWindow(cWindow *Window);
|
||||||
|
virtual void CommitWindow(cWindow *Window);
|
||||||
|
virtual void ShowWindow(cWindow *Window);
|
||||||
|
virtual void HideWindow(cWindow *Window, bool Hide);
|
||||||
|
virtual void MoveWindow(cWindow *Window, int x, int y);
|
||||||
|
virtual void CloseWindow(cWindow *Window);
|
||||||
public:
|
public:
|
||||||
cDvbOsd(int VideoDev, int x, int y, int w = -1, int h = -1, int Bpp = -1);
|
cDvbOsd(int VideoDev, int x, int y);
|
||||||
// Initializes the OSD on the given VideoDev, starting at screen coordinates
|
virtual ~cDvbOsd();
|
||||||
// (x, y). If w, h and Bpp are given, one window with that width, height and
|
|
||||||
// color depth will be created - otherwise the actual windows will have to
|
|
||||||
// be created by separate calls to Create().
|
|
||||||
~cDvbOsd();
|
|
||||||
// Destroys all windows and shuts down the OSD.
|
|
||||||
tWindowHandle Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, bool Tiled = true);
|
|
||||||
// Creates a window at coordinates (x, y), which are relative to the OSD's
|
|
||||||
// origin given in the constructor, with the given width, height and color
|
|
||||||
// depth. ClearWithBackground controls whether the window will be filled with
|
|
||||||
// clrBackground when it is cleared. Setting this to 'false' may be useful
|
|
||||||
// for windows that don't need clrBackground but want to save this color
|
|
||||||
// palette entry for a different color. Tiled controls whether this will
|
|
||||||
// be part of a multi section OSD (with several windows that all have
|
|
||||||
// different color depths and palettes and form one large OSD area), or
|
|
||||||
// whether this is a "standalone" window that will be drawn "in front"
|
|
||||||
// of any windows defined *after* this one (this can be used for highlighting
|
|
||||||
// certain parts of the OSD, as would be done in a 'cursor').
|
|
||||||
// Returns a handle that can be used to identify this window.
|
|
||||||
void AddColor(eDvbColor Color, tWindowHandle Window = LAST_CREATED_WINDOW);
|
|
||||||
// Adds the Color to the color palette of the given window if it is not
|
|
||||||
// already contained in the palette (and if the palette still has free
|
|
||||||
// slots for new colors). The default value LAST_CREATED_WINDOW will
|
|
||||||
// access the most recently created window, without the need of explicitly
|
|
||||||
// using a window handle.
|
|
||||||
void Flush(void);
|
|
||||||
// Actually commits all data of all windows to the OSD.
|
|
||||||
void Clear(tWindowHandle Window = ALL_TILED_WINDOWS);
|
|
||||||
// Clears the given window. If ALL_TILED_WINDOWS is given, only the tiled
|
|
||||||
// windows will be cleared, leaving the standalone windows untouched. If
|
|
||||||
// ALL_WINDOWS is given, the standalone windows will also be cleared.
|
|
||||||
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window = ALL_TILED_WINDOWS);
|
|
||||||
// Fills the rectangle defined by the upper left (x1, y2) and lower right
|
|
||||||
// (x2, y2) corners with the given Color. If a specific window is given,
|
|
||||||
// the coordinates are relative to that window's upper left corner.
|
|
||||||
// Otherwise they are relative to the upper left corner of the entire OSD.
|
|
||||||
// If all tiled windows are selected, only that window which contains the
|
|
||||||
// point (x1, y1) will actually be filled.
|
|
||||||
void SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window = ALL_TILED_WINDOWS);
|
|
||||||
// Sets the pixels within the given window with the data from the given
|
|
||||||
// Bitmap. See Fill() for details about the coordinates.
|
|
||||||
int Width(unsigned char c);
|
|
||||||
// Returns the width (in pixels) of the given character in the current font.
|
|
||||||
int Width(const char *s);
|
|
||||||
// Returns the width (in pixels) of the given string in the current font.
|
|
||||||
eDvbFont SetFont(eDvbFont Font);
|
|
||||||
// Sets the current font for subsequent Width() and Text() operations.
|
|
||||||
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window = ALL_TILED_WINDOWS);
|
|
||||||
// Writes the given string at coordinates (x, y) with the given foreground
|
|
||||||
// and background color into the given window (see Fill() for details
|
|
||||||
// about the coordinates).
|
|
||||||
void Relocate(tWindowHandle Window, int x, int y, int NewWidth = -1, int NewHeight = -1);
|
|
||||||
// Moves the given window to the new location at (x, y). If NewWidth and
|
|
||||||
// NewHeight are also given, the window will also be resized to the new
|
|
||||||
// width and height.
|
|
||||||
void Hide(tWindowHandle Window);
|
|
||||||
// Hides the given window.
|
|
||||||
void Show(tWindowHandle Window);
|
|
||||||
// Shows the given window.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__DVBOSD_H
|
#endif //__DVBOSD_H
|
||||||
|
15
i18n.c
15
i18n.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: i18n.c 1.87 2002/05/09 13:40:51 kls Exp $
|
* $Id: i18n.c 1.88 2002/05/11 11:43:38 kls Exp $
|
||||||
*
|
*
|
||||||
* Translations provided by:
|
* Translations provided by:
|
||||||
*
|
*
|
||||||
@ -1270,6 +1270,19 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"Plugins",
|
"Plugins",
|
||||||
"Plugins",
|
"Plugins",
|
||||||
},
|
},
|
||||||
|
{ "Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
"Plugin",
|
||||||
|
},
|
||||||
{ "Restart",
|
{ "Restart",
|
||||||
"Neustart",
|
"Neustart",
|
||||||
"Ponoven zagon",
|
"Ponoven zagon",
|
||||||
|
192
menu.c
192
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.c 1.190 2002/05/09 10:13:47 kls Exp $
|
* $Id: menu.c 1.191 2002/05/11 11:16:32 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -1525,19 +1525,41 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cMenuSetupBase --------------------------------------------------------
|
||||||
|
|
||||||
|
class cMenuSetupBase : public cMenuSetupPage {
|
||||||
|
protected:
|
||||||
|
cSetup data;
|
||||||
|
virtual void Store(void);
|
||||||
|
public:
|
||||||
|
cMenuSetupBase(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuSetupBase::cMenuSetupBase(void)
|
||||||
|
{
|
||||||
|
data = Setup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuSetupBase::Store(void)
|
||||||
|
{
|
||||||
|
Setup = data;
|
||||||
|
Setup.Save();
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuSetupOSD ---------------------------------------------------------
|
// --- cMenuSetupOSD ---------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupOSD : public cMenuSetupPage {
|
class cMenuSetupOSD : public cMenuSetupBase {
|
||||||
private:
|
private:
|
||||||
virtual void Set(void);
|
virtual void Set(void);
|
||||||
public:
|
public:
|
||||||
cMenuSetupOSD(void) { Set(); }
|
cMenuSetupOSD(void) { Set(); }
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupOSD::Set(void)
|
void cMenuSetupOSD::Set(void)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
SetupTitle("OSD");
|
SetSection(tr("OSD"));
|
||||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Language"), &data.OSDLanguage, I18nNumLanguages, I18nLanguages()));
|
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$Width"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
|
Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
|
||||||
@ -1549,19 +1571,31 @@ void cMenuSetupOSD::Set(void)
|
|||||||
Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"), &data.RecordingDirs));
|
Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"), &data.RecordingDirs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eOSState cMenuSetupOSD::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
int osdLanguage = data.OSDLanguage;
|
||||||
|
eOSState state = cMenuSetupBase::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (data.OSDLanguage != osdLanguage) {
|
||||||
|
int OriginalOSDLanguage = Setup.OSDLanguage;
|
||||||
|
Setup.OSDLanguage = data.OSDLanguage;
|
||||||
|
Set();
|
||||||
|
Display();
|
||||||
|
Setup.OSDLanguage = OriginalOSDLanguage;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuSetupEPG ---------------------------------------------------------
|
// --- cMenuSetupEPG ---------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupEPG : public cMenuSetupPage {
|
class cMenuSetupEPG : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupEPG(void) { Set(); }
|
cMenuSetupEPG(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupEPG::Set(void)
|
cMenuSetupEPG::cMenuSetupEPG(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("EPG"));
|
||||||
SetupTitle("EPG");
|
|
||||||
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG scan timeout (h)"), &data.EPGScanTimeout));
|
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG scan timeout (h)"), &data.EPGScanTimeout));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG bugfix level"), &data.EPGBugfixLevel, 0, MAXEPGBUGFIXLEVEL));
|
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG bugfix level"), &data.EPGBugfixLevel, 0, MAXEPGBUGFIXLEVEL));
|
||||||
Add(new cMenuEditBoolItem(tr("Setup.EPG$Set system time"), &data.SetSystemTime));
|
Add(new cMenuEditBoolItem(tr("Setup.EPG$Set system time"), &data.SetSystemTime));
|
||||||
@ -1570,34 +1604,43 @@ void cMenuSetupEPG::Set(void)
|
|||||||
|
|
||||||
// --- cMenuSetupDVB ---------------------------------------------------------
|
// --- cMenuSetupDVB ---------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupDVB : public cMenuSetupPage {
|
class cMenuSetupDVB : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupDVB(void) { Set(); }
|
cMenuSetupDVB(void);
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupDVB::Set(void)
|
cMenuSetupDVB::cMenuSetupDVB(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("DVB"));
|
||||||
SetupTitle("DVB");
|
|
||||||
Add(new cMenuEditIntItem( tr("Setup.DVB$Primary DVB interface"), &data.PrimaryDVB, 1, cDvbApi::NumDvbApis));
|
Add(new cMenuEditIntItem( tr("Setup.DVB$Primary DVB interface"), &data.PrimaryDVB, 1, cDvbApi::NumDvbApis));
|
||||||
Add(new cMenuEditBoolItem(tr("Setup.DVB$Video format"), &data.VideoFormat, "4:3", "16:9"));
|
Add(new cMenuEditBoolItem(tr("Setup.DVB$Video format"), &data.VideoFormat, "4:3", "16:9"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eOSState cMenuSetupDVB::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
int oldPrimaryDVB = Setup.PrimaryDVB;
|
||||||
|
eOSState state = cMenuSetupBase::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osBack && Key == kOk) {
|
||||||
|
if (Setup.PrimaryDVB != oldPrimaryDVB) {
|
||||||
|
state = osSwitchDvb;
|
||||||
|
cDvbApi::PrimaryDvbApi->SetVideoFormat(Setup.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuSetupLNB ---------------------------------------------------------
|
// --- cMenuSetupLNB ---------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupLNB : public cMenuSetupPage {
|
class cMenuSetupLNB : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupLNB(void) { Set(); }
|
cMenuSetupLNB(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupLNB::Set(void)
|
cMenuSetupLNB::cMenuSetupLNB(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("LNB"));
|
||||||
SetupTitle("LNB");
|
|
||||||
Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"), &data.LnbSLOF));
|
Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"), &data.LnbSLOF));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.LNB$Low LNB frequency (MHz)"), &data.LnbFrequLo));
|
Add(new cMenuEditIntItem( tr("Setup.LNB$Low LNB frequency (MHz)"), &data.LnbFrequLo));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.LNB$High LNB frequency (MHz)"), &data.LnbFrequHi));
|
Add(new cMenuEditIntItem( tr("Setup.LNB$High LNB frequency (MHz)"), &data.LnbFrequHi));
|
||||||
@ -1606,17 +1649,15 @@ void cMenuSetupLNB::Set(void)
|
|||||||
|
|
||||||
// --- cMenuSetupCICAM -------------------------------------------------------
|
// --- cMenuSetupCICAM -------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupCICAM : public cMenuSetupPage {
|
class cMenuSetupCICAM : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupCICAM(void) { Set(); }
|
cMenuSetupCICAM(void);
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupCICAM::Set(void)
|
cMenuSetupCICAM::cMenuSetupCICAM(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("CICAM"));
|
||||||
SetupTitle("CICAM");
|
|
||||||
for (int d = 0; d < cDvbApi::NumDvbApis; d++) {
|
for (int d = 0; d < cDvbApi::NumDvbApis; d++) {
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
@ -1626,19 +1667,25 @@ void cMenuSetupCICAM::Set(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eOSState cMenuSetupCICAM::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
eOSState state = cMenuSetupBase::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osBack && Key == kOk)
|
||||||
|
cDvbApi::SetCaCaps();
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuSetupRecord ------------------------------------------------------
|
// --- cMenuSetupRecord ------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupRecord : public cMenuSetupPage {
|
class cMenuSetupRecord : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupRecord(void) { Set(); }
|
cMenuSetupRecord(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupRecord::Set(void)
|
cMenuSetupRecord::cMenuSetupRecord(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("Recording"));
|
||||||
SetupTitle("Recording");
|
|
||||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Margin at start (min)"), &data.MarginStart));
|
Add(new cMenuEditIntItem( tr("Setup.Recording$Margin at start (min)"), &data.MarginStart));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Margin at stop (min)"), &data.MarginStop));
|
Add(new cMenuEditIntItem( tr("Setup.Recording$Margin at stop (min)"), &data.MarginStop));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Primary limit"), &data.PrimaryLimit, 0, MAXPRIORITY));
|
Add(new cMenuEditIntItem( tr("Setup.Recording$Primary limit"), &data.PrimaryLimit, 0, MAXPRIORITY));
|
||||||
@ -1655,34 +1702,28 @@ void cMenuSetupRecord::Set(void)
|
|||||||
|
|
||||||
// --- cMenuSetupReplay ------------------------------------------------------
|
// --- cMenuSetupReplay ------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupReplay : public cMenuSetupPage {
|
class cMenuSetupReplay : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupReplay(void) { Set(); }
|
cMenuSetupReplay(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupReplay::Set(void)
|
cMenuSetupReplay::cMenuSetupReplay(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("Replay"));
|
||||||
SetupTitle("Replay");
|
|
||||||
Add(new cMenuEditBoolItem(tr("Setup.Replay$Multi speed mode"), &data.MultiSpeedMode));
|
Add(new cMenuEditBoolItem(tr("Setup.Replay$Multi speed mode"), &data.MultiSpeedMode));
|
||||||
Add(new cMenuEditBoolItem(tr("Setup.Replay$Show replay mode"), &data.ShowReplayMode));
|
Add(new cMenuEditBoolItem(tr("Setup.Replay$Show replay mode"), &data.ShowReplayMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuSetupMisc --------------------------------------------------------
|
// --- cMenuSetupMisc --------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupMisc : public cMenuSetupPage {
|
class cMenuSetupMisc : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupMisc(void) { Set(); }
|
cMenuSetupMisc(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupMisc::Set(void)
|
cMenuSetupMisc::cMenuSetupMisc(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("Miscellaneous"));
|
||||||
SetupTitle("Miscellaneous");
|
|
||||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"), &data.MinEventTimeout));
|
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$Min. user inactivity (min)"), &data.MinUserInactivity));
|
||||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout));
|
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout));
|
||||||
@ -1706,18 +1747,15 @@ cMenuSetupPluginItem::cMenuSetupPluginItem(const char *Name, int Index)
|
|||||||
|
|
||||||
// --- cMenuSetupPlugins -----------------------------------------------------
|
// --- cMenuSetupPlugins -----------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupPlugins : public cMenuSetupPage {
|
class cMenuSetupPlugins : public cMenuSetupBase {
|
||||||
private:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
public:
|
||||||
cMenuSetupPlugins(void) { Set(); }
|
cMenuSetupPlugins(void);
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
void cMenuSetupPlugins::Set(void)
|
cMenuSetupPlugins::cMenuSetupPlugins(void)
|
||||||
{
|
{
|
||||||
Clear();
|
SetSection(tr("Plugins"));
|
||||||
SetupTitle("Plugins");
|
|
||||||
SetHasHotkeys();
|
SetHasHotkeys();
|
||||||
for (int i = 0; ; i++) {
|
for (int i = 0; ; i++) {
|
||||||
cPlugin *p = cPluginManager::GetPlugin(i);
|
cPlugin *p = cPluginManager::GetPlugin(i);
|
||||||
@ -1734,25 +1772,25 @@ void cMenuSetupPlugins::Set(void)
|
|||||||
|
|
||||||
eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
|
eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSState state = cOsdMenu::ProcessKey(Key); // not cMenuSetupPage::ProcessKey()!
|
eOSState state = HasSubMenu() ? cMenuSetupBase::ProcessKey(Key) : cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (Key == kOk) {
|
||||||
switch (Key) {
|
if (state == osUnknown) {
|
||||||
case kOk: {
|
cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
|
||||||
cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
|
if (item) {
|
||||||
if (item) {
|
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
||||||
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
if (p) {
|
||||||
if (p) {
|
cMenuSetupPage *menu = p->SetupMenu();
|
||||||
cOsdMenu *menu = p->SetupMenu();
|
if (menu) {
|
||||||
if (menu)
|
menu->SetPlugin(p);
|
||||||
return AddSubMenu(menu);
|
return AddSubMenu(menu);
|
||||||
Interface->Info(tr("This plugin has no setup parameters!"));
|
}
|
||||||
}
|
Interface->Info(tr("This plugin has no setup parameters!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default: break;
|
else if (state == osContinue)
|
||||||
}
|
Store();
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
48
menuitems.c
48
menuitems.c
@ -4,12 +4,13 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menuitems.c 1.1 2002/05/09 10:10:12 kls Exp $
|
* $Id: menuitems.c 1.2 2002/05/11 10:49:45 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menuitems.h"
|
#include "menuitems.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
|
||||||
// --- cMenuEditItem ---------------------------------------------------------
|
// --- cMenuEditItem ---------------------------------------------------------
|
||||||
|
|
||||||
@ -437,15 +438,13 @@ eOSState cMenuTextItem::ProcessKey(eKeys Key)
|
|||||||
cMenuSetupPage::cMenuSetupPage(void)
|
cMenuSetupPage::cMenuSetupPage(void)
|
||||||
:cOsdMenu("", 33)
|
:cOsdMenu("", 33)
|
||||||
{
|
{
|
||||||
data = Setup;
|
plugin = NULL;
|
||||||
osdLanguage = Setup.OSDLanguage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cMenuSetupPage::SetupTitle(const char *s)
|
void cMenuSetupPage::SetSection(const char *Section)
|
||||||
{
|
{
|
||||||
char buf[40]; // can't call tr() for more than one string at a time!
|
char buf[40];
|
||||||
char *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
|
snprintf(buf, sizeof(buf), "%s - %s", tr("Setup"), Section);
|
||||||
snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
|
|
||||||
SetTitle(buf);
|
SetTitle(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,22 +454,31 @@ eOSState cMenuSetupPage::ProcessKey(eKeys Key)
|
|||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
|
case kOk: Store();
|
||||||
cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
|
state = osBack;
|
||||||
Setup = data;
|
|
||||||
Setup.Save();
|
|
||||||
cDvbApi::SetCaCaps();
|
|
||||||
break;
|
break;
|
||||||
default: 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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cMenuSetupPage::SetPlugin(cPlugin *Plugin)
|
||||||
|
{
|
||||||
|
plugin = Plugin;
|
||||||
|
char buf[40];
|
||||||
|
snprintf(buf, sizeof(buf), "%s '%s'", tr("Plugin"), plugin->Name());
|
||||||
|
SetSection(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuSetupPage::SetupStore(const char *Name, const char *Value = NULL)
|
||||||
|
{
|
||||||
|
if (plugin)
|
||||||
|
plugin->SetupStore(Name, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuSetupPage::SetupStore(const char *Name, int Value)
|
||||||
|
{
|
||||||
|
if (plugin)
|
||||||
|
plugin->SetupStore(Name, Value);
|
||||||
|
}
|
||||||
|
15
menuitems.h
15
menuitems.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menuitems.h 1.1 2002/05/09 09:41:06 kls Exp $
|
* $Id: menuitems.h 1.2 2002/05/11 10:48:28 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MENUITEMS_H
|
#ifndef __MENUITEMS_H
|
||||||
@ -96,15 +96,20 @@ public:
|
|||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cPlugin;
|
||||||
|
|
||||||
class cMenuSetupPage : public cOsdMenu {
|
class cMenuSetupPage : public cOsdMenu {
|
||||||
|
private:
|
||||||
|
cPlugin *plugin;
|
||||||
protected:
|
protected:
|
||||||
cSetup data;
|
void SetSection(const char *Section);
|
||||||
int osdLanguage;
|
virtual void Store(void) = 0;
|
||||||
void SetupTitle(const char *s);
|
void SetupStore(const char *Name, const char *Value = NULL);
|
||||||
virtual void Set(void) = 0;
|
void SetupStore(const char *Name, int Value);
|
||||||
public:
|
public:
|
||||||
cMenuSetupPage(void);
|
cMenuSetupPage(void);
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
|
void SetPlugin(cPlugin *Plugin);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__MENUITEMS_H
|
#endif //__MENUITEMS_H
|
||||||
|
482
osdbase.c
Normal file
482
osdbase.c
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
/*
|
||||||
|
* osdbase.c: Basic interface to the On Screen Display
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: osdbase.c 1.1 2002/05/10 14:55:53 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osdbase.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
// --- cPalette --------------------------------------------------------------
|
||||||
|
|
||||||
|
cPalette::cPalette(int Bpp)
|
||||||
|
{
|
||||||
|
maxColors = 1 << Bpp;
|
||||||
|
numColors = 0;
|
||||||
|
full = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!full) {
|
||||||
|
if (numColors < maxColors) {
|
||||||
|
color[numColors++] = Color;
|
||||||
|
used[numColors - 1] = true;
|
||||||
|
fetched[numColors - 1] = false;
|
||||||
|
return numColors - 1;
|
||||||
|
}
|
||||||
|
for (int i = maxColors; --i >= 0; ) {
|
||||||
|
if (!used[i]) {
|
||||||
|
color[i] = Color;
|
||||||
|
used[i] = true;
|
||||||
|
fetched[i] = false;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esyslog(LOG_ERR, "ERROR: too many different colors used in palette");
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cPalette::Reset(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numColors; i++)
|
||||||
|
used[i] = false;
|
||||||
|
full = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eDvbColor *cPalette::Colors(int &FirstColor, int &LastColor)
|
||||||
|
{
|
||||||
|
for (FirstColor = 0; FirstColor < numColors; FirstColor++) {
|
||||||
|
if (!fetched[FirstColor]) {
|
||||||
|
for (LastColor = FirstColor; LastColor < numColors && !fetched[LastColor]; LastColor++)
|
||||||
|
fetched[LastColor] = true;
|
||||||
|
LastColor--; // the loop ended one past the last one!
|
||||||
|
return &color[FirstColor];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cPalette::Take(const cPalette &Palette, tIndexes *Indexes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Palette.numColors; i++) {
|
||||||
|
if (Palette.used[i]) {
|
||||||
|
int n = Index(Palette.color[i]);
|
||||||
|
if (Indexes)
|
||||||
|
(*Indexes)[i] = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cBitmap ---------------------------------------------------------------
|
||||||
|
|
||||||
|
cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
||||||
|
:cPalette(Bpp)
|
||||||
|
{
|
||||||
|
width = Width;
|
||||||
|
height = Height;
|
||||||
|
clearWithBackground = ClearWithBackground;
|
||||||
|
bitmap = NULL;
|
||||||
|
fontType = fontOsd;
|
||||||
|
font = NULL;
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
bitmap = new char[width * height];
|
||||||
|
if (bitmap) {
|
||||||
|
Clean();
|
||||||
|
memset(bitmap, 0x00, width * height);
|
||||||
|
SetFont(fontOsd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog(LOG_ERR, "ERROR: can't allocate bitmap!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog(LOG_ERR, "ERROR: illegal bitmap parameters (%d, %d)!", width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
cBitmap::~cBitmap()
|
||||||
|
{
|
||||||
|
delete font;
|
||||||
|
delete bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
eDvbFont cBitmap::SetFont(eDvbFont Font)
|
||||||
|
{
|
||||||
|
eDvbFont oldFont = fontType;
|
||||||
|
if (fontType != Font || !font) {
|
||||||
|
delete font;
|
||||||
|
font = new cFont(Font);
|
||||||
|
fontType = Font;
|
||||||
|
}
|
||||||
|
return oldFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cBitmap::Dirty(int &x1, int &y1, int &x2, int &y2)
|
||||||
|
{
|
||||||
|
if (dirtyX2 >= 0) {
|
||||||
|
//XXX Workaround: apparently the bitmap sent to the driver always has to be a multiple
|
||||||
|
//XXX of 8 bits wide, and (dx * dy) also has to be a multiple of 8.
|
||||||
|
//TODO Fix driver (should be able to handle any size bitmaps!)
|
||||||
|
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && ((dirtyX2 - dirtyX1) & 7) != 7) {
|
||||||
|
if (dirtyX2 < width - 1)
|
||||||
|
dirtyX2++;
|
||||||
|
else if (dirtyX1 > 0)
|
||||||
|
dirtyX1--;
|
||||||
|
}
|
||||||
|
//XXX "... / 2" <==> Bpp???
|
||||||
|
while ((dirtyY1 > 0 || dirtyY2 < height - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||||
|
if (dirtyY2 < height - 1)
|
||||||
|
dirtyY2++;
|
||||||
|
else if (dirtyY1 > 0)
|
||||||
|
dirtyY1--;
|
||||||
|
}
|
||||||
|
while ((dirtyX1 > 0 || dirtyX2 < width - 1) && (((dirtyX2 - dirtyX1 + 1) * (dirtyY2 - dirtyY1 + 1) / 2) & 7) != 0) {
|
||||||
|
if (dirtyX2 < width - 1)
|
||||||
|
dirtyX2++;
|
||||||
|
else if (dirtyX1 > 0)
|
||||||
|
dirtyX1--;
|
||||||
|
}
|
||||||
|
x1 = dirtyX1;
|
||||||
|
y1 = dirtyY1;
|
||||||
|
x2 = dirtyX2;
|
||||||
|
y2 = dirtyY2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::Clean(void)
|
||||||
|
{
|
||||||
|
dirtyX1 = width;
|
||||||
|
dirtyY1 = height;
|
||||||
|
dirtyX2 = -1;
|
||||||
|
dirtyY2 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::SetIndex(int x, int y, char Index)
|
||||||
|
{
|
||||||
|
if (bitmap) {
|
||||||
|
if (0 <= x && x < width && 0 <= y && y < height) {
|
||||||
|
if (bitmap[width * y + x] != Index) {
|
||||||
|
bitmap[width * y + x] = Index;
|
||||||
|
if (dirtyX1 > x) dirtyX1 = x;
|
||||||
|
if (dirtyY1 > y) dirtyY1 = y;
|
||||||
|
if (dirtyX2 < x) dirtyX2 = x;
|
||||||
|
if (dirtyY2 < y) dirtyY2 = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::SetPixel(int x, int y, eDvbColor Color)
|
||||||
|
{
|
||||||
|
SetIndex(x, y, Index(Color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||||
|
{
|
||||||
|
if (bitmap && Bitmap.bitmap) {
|
||||||
|
tIndexes Indexes;
|
||||||
|
Take(Bitmap, &Indexes);
|
||||||
|
for (int ix = 0; ix < Bitmap.width; ix++) {
|
||||||
|
for (int iy = 0; iy < Bitmap.height; iy++)
|
||||||
|
SetIndex(x + ix, y + iy, Indexes[Bitmap.bitmap[Bitmap.width * iy + ix]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cBitmap::Width(unsigned char c)
|
||||||
|
{
|
||||||
|
return font ? font->Width(c) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cBitmap::Width(const char *s)
|
||||||
|
{
|
||||||
|
return font ? font->Width(s) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||||
|
{
|
||||||
|
if (bitmap) {
|
||||||
|
char fg = Index(ColorFg);
|
||||||
|
char bg = Index(ColorBg);
|
||||||
|
int h = font->Height(s);
|
||||||
|
while (s && *s) {
|
||||||
|
const cFont::tCharData *CharData = font->CharData(*s++);
|
||||||
|
if (int(x + CharData->width) > width)
|
||||||
|
break;
|
||||||
|
for (int row = 0; row < h; row++) {
|
||||||
|
cFont::tPixelData PixelData = CharData->lines[row];
|
||||||
|
for (int col = CharData->width; col-- > 0; ) {
|
||||||
|
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
|
||||||
|
PixelData >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x += CharData->width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||||
|
{
|
||||||
|
if (bitmap) {
|
||||||
|
char c = Index(Color);
|
||||||
|
for (int y = y1; y <= y2; y++)
|
||||||
|
for (int x = x1; x <= x2; x++)
|
||||||
|
SetIndex(x, y, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cBitmap::Clear(void)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
if (clearWithBackground)
|
||||||
|
Fill(0, 0, width - 1, height - 1, clrBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cBitmap::Data(int x, int y)
|
||||||
|
{
|
||||||
|
return &bitmap[y * width + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cWindow ---------------------------------------------------------------
|
||||||
|
|
||||||
|
cWindow::cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||||
|
:cBitmap(w, h, Bpp, ClearWithBackground)
|
||||||
|
{
|
||||||
|
handle = Handle;
|
||||||
|
x0 = x;
|
||||||
|
y0 = y;
|
||||||
|
bpp = Bpp;
|
||||||
|
tiled = Tiled;
|
||||||
|
shown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cWindow::Contains(int x, int y)
|
||||||
|
{
|
||||||
|
x -= x0;
|
||||||
|
y -= y0;
|
||||||
|
return x >= 0 && y >= 0 && x < width && y < height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cWindow::Relocate(int x, int y)
|
||||||
|
{
|
||||||
|
x0 = x;
|
||||||
|
y0 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cWindow::Fill(int x1, int y1, int x2, int y2, eDvbColor Color)
|
||||||
|
{
|
||||||
|
if (tiled) {
|
||||||
|
x1 -= x0;
|
||||||
|
y1 -= y0;
|
||||||
|
x2 -= x0;
|
||||||
|
y2 -= y0;
|
||||||
|
}
|
||||||
|
cBitmap::Fill(x1, y1, x2, y2, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cWindow::SetBitmap(int x, int y, const cBitmap &Bitmap)
|
||||||
|
{
|
||||||
|
if (tiled) {
|
||||||
|
x -= x0;
|
||||||
|
y -= y0;
|
||||||
|
}
|
||||||
|
cBitmap::SetBitmap(x, y, Bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cWindow::Text(int x, int y, const char *s, eDvbColor ColorFg, eDvbColor ColorBg)
|
||||||
|
{
|
||||||
|
if (tiled) {
|
||||||
|
x -= x0;
|
||||||
|
y -= y0;
|
||||||
|
}
|
||||||
|
cBitmap::Text(x, y, s, ColorFg, ColorBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cWindow::Data(int x, int y)
|
||||||
|
{
|
||||||
|
return cBitmap::Data(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cOsd ------------------------------------------------------------------
|
||||||
|
|
||||||
|
cOsd::cOsd(int x, int y)
|
||||||
|
{
|
||||||
|
numWindows = 0;
|
||||||
|
x0 = x;
|
||||||
|
y0 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
cOsd::~cOsd()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numWindows; i++)
|
||||||
|
delete window[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
tWindowHandle cOsd::Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled)
|
||||||
|
{
|
||||||
|
if (numWindows < MAXNUMWINDOWS) {
|
||||||
|
if (x >= 0 && y >= 0 && w > 0 && h > 0 && (Bpp == 1 || Bpp == 2 || Bpp == 4 || Bpp == 8)) {
|
||||||
|
if ((w & 0x03) != 0) {
|
||||||
|
w += 4 - (w & 0x03);
|
||||||
|
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", w);
|
||||||
|
}
|
||||||
|
cWindow *win = new cWindow(numWindows, x, y, w, h, Bpp, ClearWithBackground, Tiled);
|
||||||
|
if (OpenWindow(win)) {
|
||||||
|
window[win->Handle()] = win;
|
||||||
|
numWindows++;
|
||||||
|
return win->Handle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete win;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog(LOG_ERR, "ERROR: illegal OSD parameters");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog(LOG_ERR, "ERROR: too many OSD windows");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::AddColor(eDvbColor Color, tWindowHandle Window)
|
||||||
|
{
|
||||||
|
cWindow *w = GetWindow(Window);
|
||||||
|
if (w) {
|
||||||
|
w->Index(Color);
|
||||||
|
w->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cWindow *cOsd::GetWindow(int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numWindows; i++) {
|
||||||
|
if (window[i]->Tiled() && window[i]->Contains(x, y))
|
||||||
|
return window[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cWindow *cOsd::GetWindow(tWindowHandle Window)
|
||||||
|
{
|
||||||
|
if (0 <= Window && Window < numWindows)
|
||||||
|
return window[Window];
|
||||||
|
if (Window == LAST_CREATED_WINDOW && numWindows > 0)
|
||||||
|
return window[numWindows - 1];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Flush(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numWindows; i++) {
|
||||||
|
CommitWindow(window[i]);
|
||||||
|
window[i]->Clean();
|
||||||
|
}
|
||||||
|
// Showing the windows in a separate loop to avoid seeing them come up one after another
|
||||||
|
for (int i = 0; i < numWindows; i++) {
|
||||||
|
if (!window[i]->Shown())
|
||||||
|
ShowWindow(window[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Clear(tWindowHandle Window)
|
||||||
|
{
|
||||||
|
if (Window == ALL_TILED_WINDOWS || Window == ALL_WINDOWS) {
|
||||||
|
for (int i = 0; i < numWindows; i++)
|
||||||
|
if (Window == ALL_WINDOWS || window[i]->Tiled())
|
||||||
|
window[i]->Clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cWindow *w = GetWindow(Window);
|
||||||
|
if (w)
|
||||||
|
w->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window)
|
||||||
|
{
|
||||||
|
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window);
|
||||||
|
if (w)
|
||||||
|
w->Fill(x1, y1, x2, y2, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window)
|
||||||
|
{
|
||||||
|
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||||
|
if (w)
|
||||||
|
w->SetBitmap(x, y, Bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cOsd::Width(unsigned char c)
|
||||||
|
{
|
||||||
|
return numWindows ? window[0]->Width(c) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cOsd::Width(const char *s)
|
||||||
|
{
|
||||||
|
return numWindows ? window[0]->Width(s) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
eDvbFont cOsd::SetFont(eDvbFont Font)
|
||||||
|
{
|
||||||
|
eDvbFont oldFont = Font;
|
||||||
|
for (int i = 0; i < numWindows; i++)
|
||||||
|
oldFont = window[i]->SetFont(Font);
|
||||||
|
return oldFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window)
|
||||||
|
{
|
||||||
|
cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window);
|
||||||
|
if (w)
|
||||||
|
w->Text(x, y, s, ColorFg, ColorBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight)
|
||||||
|
{
|
||||||
|
cWindow *w = GetWindow(Window);
|
||||||
|
if (w) {
|
||||||
|
if (NewWidth > 0 && NewHeight > 0) {
|
||||||
|
if ((NewWidth & 0x03) != 0) {
|
||||||
|
NewWidth += 4 - (NewWidth & 0x03);
|
||||||
|
esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth);
|
||||||
|
}
|
||||||
|
CloseWindow(w);
|
||||||
|
cWindow *NewWindow = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled());
|
||||||
|
window[w->Handle()] = NewWindow;
|
||||||
|
delete w;
|
||||||
|
OpenWindow(NewWindow);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MoveWindow(w, x, y);
|
||||||
|
w->Relocate(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Hide(tWindowHandle Window)
|
||||||
|
{
|
||||||
|
HideWindow(GetWindow(Window), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsd::Show(tWindowHandle Window)
|
||||||
|
{
|
||||||
|
HideWindow(GetWindow(Window), false);
|
||||||
|
}
|
211
osdbase.h
Normal file
211
osdbase.h
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* osdbase.h: Basic interface to the On Screen Display
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: osdbase.h 1.1 2002/05/10 14:26:09 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __OSDBASE_H
|
||||||
|
#define __OSDBASE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
#define MAXNUMCOLORS 16
|
||||||
|
|
||||||
|
enum eDvbColor {
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
clrBackground,
|
||||||
|
clrTransparent = clrBackground,
|
||||||
|
clrBlack = clrBackground,
|
||||||
|
clrRed,
|
||||||
|
clrGreen,
|
||||||
|
clrYellow,
|
||||||
|
clrBlue,
|
||||||
|
clrMagenta,
|
||||||
|
clrCyan,
|
||||||
|
clrWhite,
|
||||||
|
#else
|
||||||
|
clrTransparent = 0x00000000,
|
||||||
|
clrBackground = 0x7F000000, // 50% gray
|
||||||
|
clrBlack = 0xFF000000,
|
||||||
|
clrRed = 0xFF1414FC,
|
||||||
|
clrGreen = 0xFF24FC24,
|
||||||
|
clrYellow = 0xFF24C0FC,
|
||||||
|
clrMagenta = 0xFFFC00B0,
|
||||||
|
clrBlue = 0xFFFC0000,
|
||||||
|
clrCyan = 0xFFFCFC00,
|
||||||
|
clrWhite = 0xFFFCFCFC,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class cPalette {
|
||||||
|
private:
|
||||||
|
eDvbColor color[MAXNUMCOLORS];
|
||||||
|
int maxColors, numColors;
|
||||||
|
bool used[MAXNUMCOLORS];
|
||||||
|
bool fetched[MAXNUMCOLORS];
|
||||||
|
bool full;
|
||||||
|
protected:
|
||||||
|
typedef unsigned char tIndexes[MAXNUMCOLORS];
|
||||||
|
public:
|
||||||
|
cPalette(int Bpp);
|
||||||
|
int Index(eDvbColor Color);
|
||||||
|
void Reset(void);
|
||||||
|
const eDvbColor *Colors(int &FirstColor, int &LastColor);
|
||||||
|
void Take(const cPalette &Palette, tIndexes *Indexes = NULL);
|
||||||
|
};
|
||||||
|
|
||||||
|
class cBitmap : public cPalette {
|
||||||
|
private:
|
||||||
|
cFont *font;
|
||||||
|
eDvbFont fontType;
|
||||||
|
void SetIndex(int x, int y, char Index);
|
||||||
|
char *bitmap;
|
||||||
|
bool clearWithBackground;
|
||||||
|
protected:
|
||||||
|
int width, height;
|
||||||
|
int dirtyX1, dirtyY1, dirtyX2, dirtyY2;
|
||||||
|
public:
|
||||||
|
cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground = true);
|
||||||
|
virtual ~cBitmap();
|
||||||
|
bool ClearWithBackground(void) { return clearWithBackground; }
|
||||||
|
eDvbFont SetFont(eDvbFont Font);
|
||||||
|
bool Dirty(int &x1, int &y1, int &x2, int &y2);
|
||||||
|
void SetPixel(int x, int y, eDvbColor Color);
|
||||||
|
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||||
|
int Width(void) { return width; }
|
||||||
|
int Width(unsigned char c);
|
||||||
|
int Width(const char *s);
|
||||||
|
int Height(void) { return height; }
|
||||||
|
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||||
|
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||||
|
void Clean(void);
|
||||||
|
void Clear(void);
|
||||||
|
const char *Data(int x, int y);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7
|
||||||
|
|
||||||
|
class cWindow : public cBitmap {
|
||||||
|
private:
|
||||||
|
int handle; // the index within the OSD's window array (0...MAXNUMWINDOWS - 1)
|
||||||
|
int x0, y0;
|
||||||
|
int bpp;
|
||||||
|
bool tiled;
|
||||||
|
bool shown;
|
||||||
|
public:
|
||||||
|
cWindow(int Handle, int x, int y, int w, int h, int Bpp, bool ClearWithBackground, bool Tiled);
|
||||||
|
int X0(void) { return x0; }
|
||||||
|
int Y0(void) { return y0; }
|
||||||
|
int Bpp(void) { return bpp; }
|
||||||
|
bool Tiled(void) { return tiled; }
|
||||||
|
bool Shown(void) { bool s = shown; shown = true; return s; }
|
||||||
|
int Handle(void) { return handle; }
|
||||||
|
bool Contains(int x, int y);
|
||||||
|
void Relocate(int x, int y);
|
||||||
|
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color);
|
||||||
|
void SetBitmap(int x, int y, const cBitmap &Bitmap);
|
||||||
|
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground);
|
||||||
|
const char *Data(int x, int y);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int tWindowHandle;
|
||||||
|
|
||||||
|
// '-1' is used as an error return value!
|
||||||
|
#define ALL_WINDOWS (-2)
|
||||||
|
#define ALL_TILED_WINDOWS (-3)
|
||||||
|
#define LAST_CREATED_WINDOW (-4)
|
||||||
|
|
||||||
|
class cOsd {
|
||||||
|
private:
|
||||||
|
int numWindows;
|
||||||
|
int x0, y0;
|
||||||
|
cWindow *window[MAXNUMWINDOWS];
|
||||||
|
cWindow *GetWindow(int x, int y);
|
||||||
|
cWindow *GetWindow(tWindowHandle Window);
|
||||||
|
protected:
|
||||||
|
cWindow *GetWindowNr(int i) { return i < MAXNUMWINDOWS ? window[i] : NULL; }
|
||||||
|
int NumWindows(void) { return numWindows; }
|
||||||
|
int X0(void) { return x0; }
|
||||||
|
int Y0(void) { return y0; }
|
||||||
|
virtual bool OpenWindow(cWindow *Window) = 0;
|
||||||
|
// Opens the window on the OSD hardware, without actually showing it (the
|
||||||
|
// initial state shall be "hidden").
|
||||||
|
virtual void CommitWindow(cWindow *Window) = 0;
|
||||||
|
// Write any modified data and color definitions to the OSD hardware.
|
||||||
|
// Use the window's Dirty() function to find out which area of data
|
||||||
|
// actually needs to be transferred. If the window has not yet been explicitly
|
||||||
|
// shown through a call to ShowWindow(), no visible activity shall take place.
|
||||||
|
virtual void ShowWindow(cWindow *Window) = 0;
|
||||||
|
// Make the window actually visible on the OSD hardware.
|
||||||
|
virtual void HideWindow(cWindow *Window, bool Hide) = 0;
|
||||||
|
// Temporarily hide the window (if 'Hide' is 'true') or make a previously
|
||||||
|
// hidden window visible again (if 'Hide' is 'false').
|
||||||
|
virtual void MoveWindow(cWindow *Window, int x, int y) = 0;
|
||||||
|
// Move the window to a new location.
|
||||||
|
virtual void CloseWindow(cWindow *Window) = 0;
|
||||||
|
// Close the window and release any OSD hardware resources allocated for it.
|
||||||
|
public:
|
||||||
|
cOsd(int x, int y);
|
||||||
|
// Initializes the OSD, starting at screen coordinates (x, y).
|
||||||
|
virtual ~cOsd();
|
||||||
|
// Destroys all windows and shuts down the OSD.
|
||||||
|
tWindowHandle Create(int x, int y, int w, int h, int Bpp, bool ClearWithBackground = true, bool Tiled = true);
|
||||||
|
// Creates a window at coordinates (x, y), which are relative to the OSD's
|
||||||
|
// origin given in the constructor, with the given width, height and color
|
||||||
|
// depth. ClearWithBackground controls whether the window will be filled with
|
||||||
|
// clrBackground when it is cleared. Setting this to 'false' may be useful
|
||||||
|
// for windows that don't need clrBackground but want to save this color
|
||||||
|
// palette entry for a different color. Tiled controls whether this will
|
||||||
|
// be part of a multi section OSD (with several windows that all have
|
||||||
|
// different color depths and palettes and form one large OSD area), or
|
||||||
|
// whether this is a "standalone" window that will be drawn "in front"
|
||||||
|
// of any windows defined *after* this one (this can be used for highlighting
|
||||||
|
// certain parts of the OSD, as would be done in a 'cursor').
|
||||||
|
// Returns a handle that can be used to identify this window.
|
||||||
|
void AddColor(eDvbColor Color, tWindowHandle Window = LAST_CREATED_WINDOW);
|
||||||
|
// Adds the Color to the color palette of the given window if it is not
|
||||||
|
// already contained in the palette (and if the palette still has free
|
||||||
|
// slots for new colors). The default value LAST_CREATED_WINDOW will
|
||||||
|
// access the most recently created window, without the need of explicitly
|
||||||
|
// using a window handle.
|
||||||
|
void Flush(void);
|
||||||
|
// Actually commits all data of all windows to the OSD.
|
||||||
|
void Clear(tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||||
|
// Clears the given window. If ALL_TILED_WINDOWS is given, only the tiled
|
||||||
|
// windows will be cleared, leaving the standalone windows untouched. If
|
||||||
|
// ALL_WINDOWS is given, the standalone windows will also be cleared.
|
||||||
|
void Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||||
|
// Fills the rectangle defined by the upper left (x1, y2) and lower right
|
||||||
|
// (x2, y2) corners with the given Color. If a specific window is given,
|
||||||
|
// the coordinates are relative to that window's upper left corner.
|
||||||
|
// Otherwise they are relative to the upper left corner of the entire OSD.
|
||||||
|
// If all tiled windows are selected, only that window which contains the
|
||||||
|
// point (x1, y1) will actually be filled.
|
||||||
|
void SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||||
|
// Sets the pixels within the given window with the data from the given
|
||||||
|
// Bitmap. See Fill() for details about the coordinates.
|
||||||
|
int Width(unsigned char c);
|
||||||
|
// Returns the width (in pixels) of the given character in the current font.
|
||||||
|
int Width(const char *s);
|
||||||
|
// Returns the width (in pixels) of the given string in the current font.
|
||||||
|
eDvbFont SetFont(eDvbFont Font);
|
||||||
|
// Sets the current font for subsequent Width() and Text() operations.
|
||||||
|
void Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window = ALL_TILED_WINDOWS);
|
||||||
|
// Writes the given string at coordinates (x, y) with the given foreground
|
||||||
|
// and background color into the given window (see Fill() for details
|
||||||
|
// about the coordinates).
|
||||||
|
void Relocate(tWindowHandle Window, int x, int y, int NewWidth = -1, int NewHeight = -1);
|
||||||
|
// Moves the given window to the new location at (x, y). If NewWidth and
|
||||||
|
// NewHeight are also given, the window will also be resized to the new
|
||||||
|
// width and height.
|
||||||
|
void Hide(tWindowHandle Window);
|
||||||
|
// Hides the given window.
|
||||||
|
void Show(tWindowHandle Window);
|
||||||
|
// Shows the given window.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__OSDBASE_H
|
4
svdrp.c
4
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* graphical interface that sits on top of an SVDRP connection.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.c 1.35 2002/03/23 16:17:39 kls Exp $
|
* $Id: svdrp.c 1.36 2002/05/10 15:05:57 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -240,7 +240,7 @@ const char *HelpPages[] = {
|
|||||||
" of the timer.",
|
" of the timer.",
|
||||||
"PUTE\n"
|
"PUTE\n"
|
||||||
" Put data into the EPG list. The data entered has to strictly follow the\n"
|
" Put data into the EPG list. The data entered has to strictly follow the\n"
|
||||||
" format defined in VDR/FORMATS for the 'epg.data' file. A '.' on a line\n"
|
" format defined in vdr(5) for the 'epg.data' file. A '.' on a line\n"
|
||||||
" by itself terminates the input and starts processing of the data (all\n"
|
" by itself terminates the input and starts processing of the data (all\n"
|
||||||
" entered data is buffered until the terminating '.' is seen).",
|
" entered data is buffered until the terminating '.' is seen).",
|
||||||
"UPDT <settings>\n"
|
"UPDT <settings>\n"
|
||||||
|
6
tools.h
6
tools.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.h 1.42 2002/02/17 12:57:44 kls Exp $
|
* $Id: tools.h 1.43 2002/05/11 08:35:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -147,8 +147,8 @@ public:
|
|||||||
T *Get(int Index) const { return (T *)cListBase::Get(Index); }
|
T *Get(int Index) const { return (T *)cListBase::Get(Index); }
|
||||||
T *First(void) const { return (T *)objects; }
|
T *First(void) const { return (T *)objects; }
|
||||||
T *Last(void) const { return (T *)lastObject; }
|
T *Last(void) const { return (T *)lastObject; }
|
||||||
T *Prev(const T *object) const { return (T *)object->Prev(); }
|
T *Prev(const T *object) const { return (T *)object->cListObject::Prev(); } // need to call cListObject's members to
|
||||||
T *Next(const T *object) const { return (T *)object->Next(); }
|
T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__TOOLS_H
|
#endif //__TOOLS_H
|
||||||
|
10
vdr.c
10
vdr.c
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||||
*
|
*
|
||||||
* $Id: vdr.c 1.104 2002/05/05 10:34:31 kls Exp $
|
* $Id: vdr.c 1.105 2002/05/11 11:46:40 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -578,14 +578,14 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (Interrupted)
|
if (Interrupted)
|
||||||
isyslog(LOG_INFO, "caught signal %d", Interrupted);
|
isyslog(LOG_INFO, "caught signal %d", Interrupted);
|
||||||
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
|
||||||
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
|
||||||
Setup.Save();
|
|
||||||
PluginManager.Shutdown(true);
|
|
||||||
cVideoCutter::Stop();
|
cVideoCutter::Stop();
|
||||||
delete Menu;
|
delete Menu;
|
||||||
delete ReplayControl;
|
delete ReplayControl;
|
||||||
delete Interface;
|
delete Interface;
|
||||||
|
PluginManager.Shutdown(true);
|
||||||
|
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
||||||
|
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
||||||
|
Setup.Save();
|
||||||
cDvbApi::Cleanup();
|
cDvbApi::Cleanup();
|
||||||
if (WatchdogTimeout > 0)
|
if (WatchdogTimeout > 0)
|
||||||
dsyslog(LOG_INFO, "max. latency time %d seconds", MaxLatencyTime);
|
dsyslog(LOG_INFO, "max. latency time %d seconds", MaxLatencyTime);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user