diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-05-11 18:00:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-05-11 18:00:00 +0200 |
commit | 803c6c6bf6340302f78171892bef599aa272c266 (patch) | |
tree | 01e24d99cf48cd3bed1506ed6727ff385655574e | |
parent | ae8a947367b4be57c9b0ca7bbf0032de0e2018d3 (diff) | |
download | vdr-patch-lnbsharing-vdr-1.1.1.tar.gz vdr-patch-lnbsharing-vdr-1.1.1.tar.bz2 |
Version 1.1.1vdr-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.
-rw-r--r-- | CONTRIBUTORS | 2 | ||||
-rw-r--r-- | HISTORY | 15 | ||||
-rw-r--r-- | MANUAL | 4 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | PLUGINS.html | 207 | ||||
-rw-r--r-- | PLUGINS/SRC/hello/HISTORY | 4 | ||||
-rw-r--r-- | PLUGINS/SRC/hello/hello.c | 47 | ||||
-rw-r--r-- | PLUGINS/SRC/hello/i18n.c | 41 | ||||
-rw-r--r-- | PLUGINS/SRC/hello/i18n.h | 7 | ||||
-rw-r--r-- | config.c | 11 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | dvbosd.c | 545 | ||||
-rw-r--r-- | dvbosd.h | 171 | ||||
-rw-r--r-- | i18n.c | 15 | ||||
-rw-r--r-- | menu.c | 194 | ||||
-rw-r--r-- | menuitems.c | 48 | ||||
-rw-r--r-- | menuitems.h | 15 | ||||
-rw-r--r-- | osdbase.c | 482 | ||||
-rw-r--r-- | osdbase.h | 211 | ||||
-rw-r--r-- | svdrp.c | 4 | ||||
-rw-r--r-- | tools.h | 6 | ||||
-rw-r--r-- | vdr.c | 10 |
22 files changed, 1216 insertions, 831 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index b6bd60a..ce0ffaa 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -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 @@ -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. @@ -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,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 diff --git a/PLUGINS.html b/PLUGINS.html index b903f04..70d6f46 100644 --- a/PLUGINS.html +++ b/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> diff --git a/PLUGINS/SRC/hello/HISTORY b/PLUGINS/SRC/hello/HISTORY index b35760c..dff114d 100644 --- a/PLUGINS/SRC/hello/HISTORY +++ b/PLUGINS/SRC/hello/HISTORY @@ -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. diff --git a/PLUGINS/SRC/hello/hello.c b/PLUGINS/SRC/hello/hello.c index 5db4f2a..65d03c8 100644 --- a/PLUGINS/SRC/hello/hello.c +++ b/PLUGINS/SRC/hello/hello.c @@ -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! diff --git a/PLUGINS/SRC/hello/i18n.c b/PLUGINS/SRC/hello/i18n.c index 7061742..9bb6fbf 100644 --- a/PLUGINS/SRC/hello/i18n.c +++ b/PLUGINS/SRC/hello/i18n.c @@ -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 } }; diff --git a/PLUGINS/SRC/hello/i18n.h b/PLUGINS/SRC/hello/i18n.h index 2976fe8..577628a 100644 --- a/PLUGINS/SRC/hello/i18n.h +++ b/PLUGINS/SRC/hello/i18n.h @@ -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 @@ -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,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 @@ -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"); - } - else - esyslog(LOG_ERR, "ERROR: too many OSD windows"); - return -1; -} - -void cDvbOsd::AddColor(eDvbColor Color, tWindowHandle Window) -{ - cWindow *w = GetWindow(Window); - if (w) { - w->Index(Color); - w->Reset(); + 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; } + return false; } -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) +void cDvbOsd::CommitWindow(cWindow *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(); + 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::Fill(int x1, int y1, int x2, int y2, eDvbColor Color, tWindowHandle Window) +void cDvbOsd::ShowWindow(cWindow *Window) { - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x1, y1) : GetWindow(Window); - if (w) - w->Fill(x1, y1, x2, y2, Color); + if (SetWindow(Window)) + Cmd(OSD_MoveWindow, 0, X0() + Window->X0(), Y0() + Window->Y0()); } -void cDvbOsd::SetBitmap(int x, int y, const cBitmap &Bitmap, tWindowHandle Window) +void cDvbOsd::HideWindow(cWindow *Window, bool Hide) { - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window); - if (w) - w->SetBitmap(x, y, Bitmap); + if (SetWindow(Window)) + Cmd(Hide ? OSD_Hide : OSD_Show, 0); } -int cDvbOsd::Width(unsigned char c) +void cDvbOsd::MoveWindow(cWindow *Window, int x, int y) { - return numWindows ? window[0]->Width(c) : 0; + if (SetWindow(Window)) + Cmd(OSD_MoveWindow, 0, X0() + x, Y0() + y); } -int cDvbOsd::Width(const char *s) +void cDvbOsd::CloseWindow(cWindow *Window) { - return numWindows ? window[0]->Width(s) : 0; + if (SetWindow(Window)) + Cmd(OSD_Close); } - -eDvbFont cDvbOsd::SetFont(eDvbFont Font) -{ - eDvbFont oldFont = Font; - for (int i = 0; i < numWindows; i++) - oldFont = window[i]->SetFont(Font); - return oldFont; -} - -void cDvbOsd::Text(int x, int y, const char *s, eDvbColor ColorFg = clrWhite, eDvbColor ColorBg = clrBackground, tWindowHandle Window) -{ - cWindow *w = (Window == ALL_TILED_WINDOWS) ? GetWindow(x, y) : GetWindow(Window); - if (w) - w->Text(x, y, s, ColorFg, ColorBg); -} - -void cDvbOsd::Relocate(tWindowHandle Window, int x, int y, int NewWidth, int NewHeight) -{ - cWindow *w = GetWindow(Window); - if (w) { - SetWindow(w); - if (NewWidth > 0 && NewHeight > 0) { - if ((NewWidth & 0x03) != 0) { - NewWidth += 4 - (NewWidth & 0x03); - esyslog(LOG_ERR, "ERROR: OSD window width must be a multiple of 4 - increasing to %d", NewWidth); - } - Cmd(OSD_Close); - window[w->Handle()] = new cWindow(w->Handle(), x, y, NewWidth, NewHeight, w->Bpp(), w->ClearWithBackground(), w->Tiled()); - delete w; - Cmd(OSD_Open, 2, x0 + x, y0 + y, x0 + x + NewWidth - 1, y0 + y + NewHeight - 1, (void *)1); // initially hidden! - } - else { - w->Relocate(x, y); - Cmd(OSD_MoveWindow, 0, x0 + x, y0 + y); - } - } -} - -void cDvbOsd::Hide(tWindowHandle Window) -{ - if (SetWindow(GetWindow(Window))) - Cmd(OSD_Hide, 0); -} - -void cDvbOsd::Show(tWindowHandle Window) -{ - if (SetWindow(GetWindow(Window))) - Cmd(OSD_Show, 0); -} - @@ -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 @@ -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", @@ -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()! - - 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; - } + eOSState state = HasSubMenu() ? cMenuSetupBase::ProcessKey(Key) : cOsdMenu::ProcessKey(Key); + + 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; } diff --git a/menuitems.c b/menuitems.c index d09f5b7..3a6f94e 100644 --- a/menuitems.c +++ b/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); +} diff --git a/menuitems.h b/menuitems.h index a08a714..ef25d0d 100644 --- a/menuitems.h +++ b/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 diff --git a/osdbase.c b/osdbase.c new file mode 100644 index 0000000..31e86de --- /dev/null +++ b/osdbase.c @@ -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); +} diff --git a/osdbase.h b/osdbase.h new file mode 100644 index 0000000..859939b --- /dev/null +++ b/osdbase.h @@ -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 @@ -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" @@ -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 @@ -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); |