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
|
||||
for making the main loop take an active video cutting process into account when
|
||||
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>
|
||||
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"
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
'commands.conf' file containing at least one command definition has been
|
||||
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
|
||||
use a 'fixed' font so that you can generate formatted output. In order to
|
||||
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
|
||||
======= 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
|
||||
# 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:
|
||||
|
||||
@ -22,7 +22,7 @@ INCLUDES = -I$(DVBDIR)/ost/include
|
||||
DTVLIB = $(DTVDIR)/libdtv.a
|
||||
|
||||
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o i18n.o interface.o menu.o\
|
||||
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
|
||||
|
||||
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.
|
||||
It handles everything necessary for a plugin to get hooked into the core
|
||||
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).-->
|
||||
|
||||
<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,
|
||||
but you probably want to see something happening right away <tt>;-)</tt>
|
||||
<p>
|
||||
So, for a quick demonstration of the plugin system, there is a demo plugin called
|
||||
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:
|
||||
<ul>
|
||||
<li>change into the VDR source directory
|
||||
<li><b><tt>make</tt></b> the VDR program with your usual <tt>REMOTE=...</tt> (and maybe other) options
|
||||
<li>do <b><tt>make plugins</tt></b> to build the demo plugin
|
||||
<li>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 -h</tt></b> to see the command line options
|
||||
<li>run VDR with <b><tt>vdr -Phello</tt></b>
|
||||
@ -74,16 +77,14 @@ is used:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
VDR/PLUGINS/SRC
|
||||
VDR/PLUGINS/SRC/demo
|
||||
VDR/PLUGINS/SRC/hello
|
||||
VDR/PLUGINS/lib
|
||||
VDR/PLUGINS/lib/libvdr-demo.so.1.1.0
|
||||
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The <tt>SRC</tt> directory contains one subdirectory for each plugin, which carries
|
||||
the name of that plugin (in the above example that would be <tt>demo</tt> and
|
||||
<tt>hello</tt>, respectively). What's inside the individual source directory of a
|
||||
the name of that plugin (in the above example that would be <tt>hello</tt>).
|
||||
What's inside the individual source directory of a
|
||||
plugin is entirely up to the author of that plugin. The only prerequisites are
|
||||
that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt> and
|
||||
<tt>clean</tt>, and that a call to <tt>make all</tt> actually produces a dynamically
|
||||
@ -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
|
||||
<p>
|
||||
<table border=2>
|
||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>demo</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1.1.0</tt></b></td></tr>
|
||||
<tr><td align=center><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>
|
||||
</table>
|
||||
<p>
|
||||
@ -109,25 +110,25 @@ each of these directories.
|
||||
If you download a plugin <a href="#Building the distribution package">package</a>
|
||||
from the web, it will typically have a name like
|
||||
<p>
|
||||
<tt>vdr-demo-0.0.1.tgz</tt>
|
||||
<tt>vdr-hello-0.0.1.tgz</tt>
|
||||
<p>
|
||||
and will unpack into a directory named
|
||||
<p>
|
||||
<tt>vdr-demo-0.0.1</tt>
|
||||
<tt>vdr-hello-0.0.1</tt>
|
||||
<p>
|
||||
To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>Makefile</tt>
|
||||
you need to unpack such an archive into the <tt>VDR/PLUGINS/SRC</tt> directory and
|
||||
create a symbolic link with the basic plugin name, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
ln -s vdr-demo-0.0.1 demo
|
||||
ln -s vdr-hello-0.0.1 hello
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Since the VDR <tt>Makefile</tt> only searches for directories with names consisting
|
||||
of only lowercase characters and digits, it will only follow the symbolic links, which
|
||||
should lead to the current version of the plugin you want to use. This way you can
|
||||
have several different versions of a plugin source (like <tt>vdr-demo-0.0.1</tt> and
|
||||
<tt>vdr-demo-0.0.2</tt>) and define which one to actually use through the symbolic link.
|
||||
have several different versions of a plugin source (like <tt>vdr-hello-0.0.1</tt> and
|
||||
<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>
|
||||
|
||||
@ -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:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
VDRPLUGINCREATOR(cPluginDemo);
|
||||
VDRPLUGINCREATOR(cPluginHello);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
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>
|
||||
If your plugin requires additional source files, simply add them to your plugin's
|
||||
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>
|
||||
|
||||
@ -230,9 +265,7 @@ Here's an example:
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
static const char *VERSION = "0.0.1";
|
||||
|
||||
...
|
||||
|
||||
const char *cPluginDemo::Version(void)
|
||||
const char *cPluginHello::Version(void)
|
||||
{
|
||||
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;
|
||||
</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>
|
||||
static const char *DESCRIPTION = "A friendly greeting";
|
||||
|
||||
virtual const char *Description(void)
|
||||
{
|
||||
return "A simple demo plugin";
|
||||
return tr(DESCRIPTION);
|
||||
}
|
||||
</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>
|
||||
|
||||
<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:
|
||||
|
||||
<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[] = {
|
||||
{ "aaa", required_argument, NULL, 'a' },
|
||||
{ "bbb", no_argument, NULL, 'b' },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
{ "aaa", required_argument, NULL, 'a' },
|
||||
{ "bbb", no_argument, NULL, 'b' },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "a:b", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': fprintf(stderr, "option -a = %s\n", optarg);
|
||||
case 'a': option_a = optarg;
|
||||
break;
|
||||
case 'b': fprintf(stderr, "option -b\n");
|
||||
case 'b': option_b = true;
|
||||
break;
|
||||
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:
|
||||
|
||||
<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"
|
||||
" -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:
|
||||
|
||||
<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>
|
||||
|
||||
@ -440,7 +482,7 @@ virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The <tt>SetupMenu()</tt> function shall return the plugin's "Setup" menu
|
||||
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.
|
||||
<p>
|
||||
<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
|
||||
an error. If <i>false</i> is returned, an error message will be written to
|
||||
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>
|
||||
The plugin's setup parameters are stored in the same file as VDR's parameters.
|
||||
In order to allow each plugin (and VDR itself) to have its own set of parameters,
|
||||
the <tt>Name</tt> of each parameter will be preceeded with the plugin's
|
||||
name, as in
|
||||
<p>
|
||||
<tt>demo.SomeParameter = 123</tt>
|
||||
<tt>hello.GreetingTime = 3</tt>
|
||||
<p>
|
||||
The prefix will be handled by the core VDR setup code, so the individual
|
||||
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);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
where <tt>Name</tt> is the name of the parameter (<tt>"SomeParameter"</tt> in the above
|
||||
example, without the prefix <tt>"demo."</tt>) and <tt>Value</tt> is a simple data type (like
|
||||
where <tt>Name</tt> is the name of the parameter (<tt>"GreetingTime"</tt> in the above
|
||||
example, without the prefix <tt>"hello."</tt>) and <tt>Value</tt> is a simple data type (like
|
||||
<tt>char *</tt>, <tt>int</tt> etc).
|
||||
Note that this is not a function that the individual plugin class needs to implement!
|
||||
<tt>SetupStore()</tt> is a non-virtual member function of the <tt>cPlugin</tt> class.
|
||||
@ -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
|
||||
name and without any value, as in
|
||||
<p>
|
||||
<tt>SetupStore("SomeParameter");</tt>
|
||||
<tt>SetupStore("GreetingTime");</tt>
|
||||
<p>
|
||||
The VDR menu "Setup/Plugins" will list all loaded plugins with their name,
|
||||
version number and description. Selecting an item in this list will bring up
|
||||
@ -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
|
||||
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>
|
||||
|
||||
<center><i><b>Welcome to Babylon!</b></i></center><p>
|
||||
@ -519,7 +638,7 @@ const tI18nPhrase Phrases[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void cPluginDemo::Start(void)
|
||||
void cPluginHello::Start(void)
|
||||
{
|
||||
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
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -Pdemo
|
||||
vdr -Phello
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If the plugin accepts command line options, they are given as part of the argument
|
||||
to the <b><tt>-P</tt></b> option, which then has to be enclosed in quotes:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -P"demo -a abc -b"
|
||||
vdr -P"hello -a abc -b"
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr -P"demo -a abc -b" -Pdvd -Pmp3
|
||||
vdr -P"hello -a abc -b" -Pdvd -Pmp3
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If you are not starting VDR from the VDR source directory (and thus your plugins
|
||||
@ -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:
|
||||
|
||||
<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>
|
||||
|
||||
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>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
cd VDR/PLUGINS/SRC/demo
|
||||
cd VDR/PLUGINS/SRC/hello
|
||||
make package
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
After this you should find a file named like
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
vdr-demo-0.0.1.tgz
|
||||
vdr-hello-0.0.1.tgz
|
||||
</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.
|
||||
|
||||
</body>
|
||||
|
@ -4,3 +4,7 @@ VDR Plugin 'hello' Revision History
|
||||
2002-05-09: Version 0.0.1
|
||||
|
||||
- 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.
|
||||
*
|
||||
* $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>
|
||||
@ -11,7 +11,7 @@
|
||||
#include <vdr/plugin.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 *MAINMENUENTRY = "Hello";
|
||||
|
||||
@ -34,6 +34,39 @@ public:
|
||||
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)
|
||||
{
|
||||
// Initialize any member varaiables here.
|
||||
@ -86,20 +119,24 @@ void cPluginHello::Start(void)
|
||||
cOsdMenu *cPluginHello::MainMenuAction(void)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
cMenuSetupPage *cPluginHello::SetupMenu(void)
|
||||
{
|
||||
// Return a setup menu in case the plugin supports one.
|
||||
return NULL;
|
||||
return new cMenuSetupHello;
|
||||
}
|
||||
|
||||
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||
{
|
||||
// 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!
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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"
|
||||
@ -35,6 +35,19 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Howdy folks!",
|
||||
"Tach zusammen!",
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "A friendly greeting",
|
||||
"Ein freundlicher Gruß",
|
||||
"",// TODO
|
||||
@ -48,5 +61,31 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// 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 }
|
||||
};
|
||||
|
@ -3,9 +3,14 @@
|
||||
*
|
||||
* 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>
|
||||
|
||||
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
|
||||
* 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"
|
||||
@ -1073,14 +1073,19 @@ bool cSetup::Load(const char *FileName)
|
||||
if (cConfig<cSetupLine>::Load(FileName, true)) {
|
||||
bool result = true;
|
||||
for (cSetupLine *l = First(); l; l = Next(l)) {
|
||||
bool error = false;
|
||||
if (l->Plugin()) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(l->Plugin());
|
||||
if (p && !p->SetupParse(l->Name(), l->Value()))
|
||||
result = false;
|
||||
error = true;
|
||||
}
|
||||
else {
|
||||
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;
|
||||
|
4
config.h
4
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.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
|
||||
@ -19,7 +19,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.1.0"
|
||||
#define VDRVERSION "1.1.1"
|
||||
|
||||
#define MAXPRIORITY 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
|
||||
* 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 <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 ---------------------------------------------------------------
|
||||
|
||||
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)
|
||||
cDvbOsd::cDvbOsd(int VideoDev, int x, int y)
|
||||
:cOsd(x, y)
|
||||
{
|
||||
videoDev = VideoDev;
|
||||
numWindows = 0;
|
||||
x0 = x;
|
||||
y0 = y;
|
||||
if (videoDev >= 0) {
|
||||
if (w > 0 && h > 0)
|
||||
Create(0, 0, w, h, Bpp);
|
||||
}
|
||||
else
|
||||
if (videoDev < 0)
|
||||
esyslog(LOG_ERR, "ERROR: illegal video device handle (%d)!", videoDev);
|
||||
}
|
||||
|
||||
cDvbOsd::~cDvbOsd()
|
||||
{
|
||||
if (videoDev >= 0) {
|
||||
for (int i = 0; i < numWindows; i++) {
|
||||
SetWindow(window[i]);
|
||||
Cmd(OSD_Close);
|
||||
delete window[i];
|
||||
}
|
||||
numWindows = 0;
|
||||
}
|
||||
for (int i = 0; i < NumWindows(); i++)
|
||||
CloseWindow(GetWindowNr(i));
|
||||
}
|
||||
|
||||
bool cDvbOsd::SetWindow(cWindow *Window)
|
||||
{
|
||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||
int Handle = Window->Handle();
|
||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||
Cmd(OSD_SetWindow, 0, Handle + 1);
|
||||
return true;
|
||||
if (Window) {
|
||||
// Window handles are counted 0...(MAXNUMWINDOWS - 1), but the actual window
|
||||
// numbers in the driver are used from 1...MAXNUMWINDOWS.
|
||||
int Handle = Window->Handle();
|
||||
if (0 <= Handle && Handle < MAXNUMWINDOWS) {
|
||||
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 -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (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 (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");
|
||||
if (SetWindow(Window)) {
|
||||
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!
|
||||
return true;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: too many OSD windows");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDvbOsd::AddColor(eDvbColor Color, tWindowHandle Window)
|
||||
void cDvbOsd::CommitWindow(cWindow *Window)
|
||||
{
|
||||
cWindow *w = GetWindow(Window);
|
||||
if (w) {
|
||||
w->Index(Color);
|
||||
w->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
cWindow *cDvbOsd::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 *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);
|
||||
if (SetWindow(Window)) {
|
||||
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||
if (Window->Dirty(x1, y1, x2, y2)) {
|
||||
// commit colors:
|
||||
int FirstColor = 0, LastColor = 0;
|
||||
const eDvbColor *pal;
|
||||
while ((pal = Window->Colors(FirstColor, LastColor)) != NULL)
|
||||
Cmd(OSD_SetPalette, FirstColor, LastColor, 0, 0, 0, pal);
|
||||
// commit modified data:
|
||||
Cmd(OSD_SetBlock, Window->Width(), x1, y1, x2, y2, Window->Data(x1, y1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbOsd::Hide(tWindowHandle Window)
|
||||
void cDvbOsd::ShowWindow(cWindow *Window)
|
||||
{
|
||||
if (SetWindow(GetWindow(Window)))
|
||||
Cmd(OSD_Hide, 0);
|
||||
if (SetWindow(Window))
|
||||
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)))
|
||||
Cmd(OSD_Show, 0);
|
||||
if (SetWindow(Window))
|
||||
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
|
||||
* 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
|
||||
#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 <stdio.h>
|
||||
#include "font.h"
|
||||
#include "osdbase.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);
|
||||
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 {
|
||||
class cDvbOsd : public cOsd {
|
||||
private:
|
||||
int videoDev;
|
||||
int numWindows;
|
||||
int x0, y0;
|
||||
cWindow *window[MAXNUMWINDOWS];
|
||||
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);
|
||||
cWindow *GetWindow(int x, int y);
|
||||
cWindow *GetWindow(tWindowHandle Window);
|
||||
protected:
|
||||
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:
|
||||
cDvbOsd(int VideoDev, int x, int y, int w = -1, int h = -1, int Bpp = -1);
|
||||
// Initializes the OSD on the given VideoDev, starting at screen coordinates
|
||||
// (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.
|
||||
cDvbOsd(int VideoDev, int x, int y);
|
||||
virtual ~cDvbOsd();
|
||||
};
|
||||
|
||||
#endif //__DVBOSD_H
|
||||
|
15
i18n.c
15
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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:
|
||||
*
|
||||
@ -1270,6 +1270,19 @@ const tI18nPhrase Phrases[] = {
|
||||
"Plugins",
|
||||
"Plugins",
|
||||
},
|
||||
{ "Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
"Plugin",
|
||||
},
|
||||
{ "Restart",
|
||||
"Neustart",
|
||||
"Ponoven zagon",
|
||||
|
192
menu.c
192
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.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"
|
||||
@ -1525,19 +1525,41 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||
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 ---------------------------------------------------------
|
||||
|
||||
class cMenuSetupOSD : public cMenuSetupPage {
|
||||
class cMenuSetupOSD : public cMenuSetupBase {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuSetupOSD(void) { Set(); }
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
void cMenuSetupOSD::Set(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("OSD");
|
||||
SetSection(tr("OSD"));
|
||||
Add(new cMenuEditStraItem(tr("Setup.OSD$Language"), &data.OSDLanguage, I18nNumLanguages, I18nLanguages()));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Width"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
|
||||
Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
|
||||
@ -1549,19 +1571,31 @@ void cMenuSetupOSD::Set(void)
|
||||
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 ---------------------------------------------------------
|
||||
|
||||
class cMenuSetupEPG : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupEPG : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupEPG(void) { Set(); }
|
||||
cMenuSetupEPG(void);
|
||||
};
|
||||
|
||||
void cMenuSetupEPG::Set(void)
|
||||
cMenuSetupEPG::cMenuSetupEPG(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("EPG");
|
||||
SetSection(tr("EPG"));
|
||||
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 cMenuEditBoolItem(tr("Setup.EPG$Set system time"), &data.SetSystemTime));
|
||||
@ -1570,34 +1604,43 @@ void cMenuSetupEPG::Set(void)
|
||||
|
||||
// --- cMenuSetupDVB ---------------------------------------------------------
|
||||
|
||||
class cMenuSetupDVB : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupDVB : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupDVB(void) { Set(); }
|
||||
cMenuSetupDVB(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
void cMenuSetupDVB::Set(void)
|
||||
cMenuSetupDVB::cMenuSetupDVB(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("DVB");
|
||||
SetSection(tr("DVB"));
|
||||
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"));
|
||||
}
|
||||
|
||||
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 ---------------------------------------------------------
|
||||
|
||||
class cMenuSetupLNB : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupLNB : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupLNB(void) { Set(); }
|
||||
cMenuSetupLNB(void);
|
||||
};
|
||||
|
||||
void cMenuSetupLNB::Set(void)
|
||||
cMenuSetupLNB::cMenuSetupLNB(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("LNB");
|
||||
SetSection(tr("LNB"));
|
||||
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$High LNB frequency (MHz)"), &data.LnbFrequHi));
|
||||
@ -1606,17 +1649,15 @@ void cMenuSetupLNB::Set(void)
|
||||
|
||||
// --- cMenuSetupCICAM -------------------------------------------------------
|
||||
|
||||
class cMenuSetupCICAM : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupCICAM : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupCICAM(void) { Set(); }
|
||||
cMenuSetupCICAM(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
void cMenuSetupCICAM::Set(void)
|
||||
cMenuSetupCICAM::cMenuSetupCICAM(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("CICAM");
|
||||
SetSection(tr("CICAM"));
|
||||
for (int d = 0; d < cDvbApi::NumDvbApis; d++) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
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 ------------------------------------------------------
|
||||
|
||||
class cMenuSetupRecord : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupRecord : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupRecord(void) { Set(); }
|
||||
cMenuSetupRecord(void);
|
||||
};
|
||||
|
||||
void cMenuSetupRecord::Set(void)
|
||||
cMenuSetupRecord::cMenuSetupRecord(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("Recording");
|
||||
SetSection(tr("Recording"));
|
||||
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$Primary limit"), &data.PrimaryLimit, 0, MAXPRIORITY));
|
||||
@ -1655,34 +1702,28 @@ void cMenuSetupRecord::Set(void)
|
||||
|
||||
// --- cMenuSetupReplay ------------------------------------------------------
|
||||
|
||||
class cMenuSetupReplay : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupReplay : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupReplay(void) { Set(); }
|
||||
cMenuSetupReplay(void);
|
||||
};
|
||||
|
||||
void cMenuSetupReplay::Set(void)
|
||||
cMenuSetupReplay::cMenuSetupReplay(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("Replay");
|
||||
SetSection(tr("Replay"));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Replay$Multi speed mode"), &data.MultiSpeedMode));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Replay$Show replay mode"), &data.ShowReplayMode));
|
||||
}
|
||||
|
||||
// --- cMenuSetupMisc --------------------------------------------------------
|
||||
|
||||
class cMenuSetupMisc : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupMisc : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupMisc(void) { Set(); }
|
||||
cMenuSetupMisc(void);
|
||||
};
|
||||
|
||||
void cMenuSetupMisc::Set(void)
|
||||
cMenuSetupMisc::cMenuSetupMisc(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("Miscellaneous");
|
||||
SetSection(tr("Miscellaneous"));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"), &data.MinEventTimeout));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout));
|
||||
@ -1706,18 +1747,15 @@ cMenuSetupPluginItem::cMenuSetupPluginItem(const char *Name, int Index)
|
||||
|
||||
// --- cMenuSetupPlugins -----------------------------------------------------
|
||||
|
||||
class cMenuSetupPlugins : public cMenuSetupPage {
|
||||
private:
|
||||
virtual void Set(void);
|
||||
class cMenuSetupPlugins : public cMenuSetupBase {
|
||||
public:
|
||||
cMenuSetupPlugins(void) { Set(); }
|
||||
cMenuSetupPlugins(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
void cMenuSetupPlugins::Set(void)
|
||||
cMenuSetupPlugins::cMenuSetupPlugins(void)
|
||||
{
|
||||
Clear();
|
||||
SetupTitle("Plugins");
|
||||
SetSection(tr("Plugins"));
|
||||
SetHasHotkeys();
|
||||
for (int i = 0; ; i++) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(i);
|
||||
@ -1734,25 +1772,25 @@ void cMenuSetupPlugins::Set(void)
|
||||
|
||||
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) {
|
||||
switch (Key) {
|
||||
case kOk: {
|
||||
cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
|
||||
if (item) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
||||
if (p) {
|
||||
cOsdMenu *menu = p->SetupMenu();
|
||||
if (menu)
|
||||
return AddSubMenu(menu);
|
||||
Interface->Info(tr("This plugin has no setup parameters!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (Key == kOk) {
|
||||
if (state == osUnknown) {
|
||||
cMenuSetupPluginItem *item = (cMenuSetupPluginItem *)Get(Current());
|
||||
if (item) {
|
||||
cPlugin *p = cPluginManager::GetPlugin(item->PluginIndex());
|
||||
if (p) {
|
||||
cMenuSetupPage *menu = p->SetupMenu();
|
||||
if (menu) {
|
||||
menu->SetPlugin(p);
|
||||
return AddSubMenu(menu);
|
||||
}
|
||||
Interface->Info(tr("This plugin has no setup parameters!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == osContinue)
|
||||
Store();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
48
menuitems.c
48
menuitems.c
@ -4,12 +4,13 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.c 1.1 2002/05/09 10:10:12 kls Exp $
|
||||
* $Id: menuitems.c 1.2 2002/05/11 10:49:45 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menuitems.h"
|
||||
#include <ctype.h>
|
||||
#include "i18n.h"
|
||||
#include "plugin.h"
|
||||
|
||||
// --- cMenuEditItem ---------------------------------------------------------
|
||||
|
||||
@ -437,15 +438,13 @@ eOSState cMenuTextItem::ProcessKey(eKeys Key)
|
||||
cMenuSetupPage::cMenuSetupPage(void)
|
||||
:cOsdMenu("", 33)
|
||||
{
|
||||
data = Setup;
|
||||
osdLanguage = Setup.OSDLanguage;
|
||||
plugin = NULL;
|
||||
}
|
||||
|
||||
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 *q = buf + snprintf(buf, sizeof(buf), "%s - ", tr("Setup"));
|
||||
snprintf(q, sizeof(buf) - strlen(buf), "%s", tr(s));
|
||||
char buf[40];
|
||||
snprintf(buf, sizeof(buf), "%s - %s", tr("Setup"), Section);
|
||||
SetTitle(buf);
|
||||
}
|
||||
|
||||
@ -455,22 +454,31 @@ eOSState cMenuSetupPage::ProcessKey(eKeys Key)
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: state = (Setup.PrimaryDVB != data.PrimaryDVB) ? osSwitchDvb : osBack;
|
||||
cDvbApi::PrimaryDvbApi->SetVideoFormat(data.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3);
|
||||
Setup = data;
|
||||
Setup.Save();
|
||||
cDvbApi::SetCaCaps();
|
||||
case kOk: Store();
|
||||
state = osBack;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* 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
|
||||
@ -96,15 +96,20 @@ public:
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
class cPlugin;
|
||||
|
||||
class cMenuSetupPage : public cOsdMenu {
|
||||
private:
|
||||
cPlugin *plugin;
|
||||
protected:
|
||||
cSetup data;
|
||||
int osdLanguage;
|
||||
void SetupTitle(const char *s);
|
||||
virtual void Set(void) = 0;
|
||||
void SetSection(const char *Section);
|
||||
virtual void Store(void) = 0;
|
||||
void SetupStore(const char *Name, const char *Value = NULL);
|
||||
void SetupStore(const char *Name, int Value);
|
||||
public:
|
||||
cMenuSetupPage(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
void SetPlugin(cPlugin *Plugin);
|
||||
};
|
||||
|
||||
#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
|
||||
* 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"
|
||||
@ -240,7 +240,7 @@ const char *HelpPages[] = {
|
||||
" of the timer.",
|
||||
"PUTE\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"
|
||||
" entered data is buffered until the terminating '.' is seen).",
|
||||
"UPDT <settings>\n"
|
||||
|
6
tools.h
6
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.h 1.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
|
||||
@ -147,8 +147,8 @@ public:
|
||||
T *Get(int Index) const { return (T *)cListBase::Get(Index); }
|
||||
T *First(void) const { return (T *)objects; }
|
||||
T *Last(void) const { return (T *)lastObject; }
|
||||
T *Prev(const T *object) const { return (T *)object->Prev(); }
|
||||
T *Next(const T *object) const { return (T *)object->Next(); }
|
||||
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->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
|
||||
};
|
||||
|
||||
#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
|
||||
*
|
||||
* $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>
|
||||
@ -578,14 +578,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (Interrupted)
|
||||
isyslog(LOG_INFO, "caught signal %d", Interrupted);
|
||||
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
||||
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
||||
Setup.Save();
|
||||
PluginManager.Shutdown(true);
|
||||
cVideoCutter::Stop();
|
||||
delete Menu;
|
||||
delete ReplayControl;
|
||||
delete Interface;
|
||||
PluginManager.Shutdown(true);
|
||||
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
||||
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
||||
Setup.Save();
|
||||
cDvbApi::Cleanup();
|
||||
if (WatchdogTimeout > 0)
|
||||
dsyslog(LOG_INFO, "max. latency time %d seconds", MaxLatencyTime);
|
||||
|
Loading…
x
Reference in New Issue
Block a user