mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Updated The VDR Plugin System (markdown)
parent
64bbb2f651
commit
5f09756fc3
@ -17,9 +17,9 @@ separate from the core VDR source, without the need of patching the original
|
||||
VDR code (and all the problems of correlating various patches).
|
||||
<p>
|
||||
This document is divided into two parts, the first one describing the
|
||||
<a href="#Part I - The External Interface"><i>external</i> interface</a>
|
||||
<a href="#part-i---the-external-interface"><i>external</i> interface</a>
|
||||
of the plugin system, and the second one describing the
|
||||
<a href="#Part II - The Internal Interface"><i>internal</i> interface</a>.
|
||||
<a href="#part-ii---the-internal-interface"><i>internal</i> interface</a>.
|
||||
The <i>external</i> interface handles everything necessary for a plugin to get hooked into the core
|
||||
VDR program and present itself to the user.
|
||||
The <i>internal</i> interface provides the plugin code access to VDR's internal data
|
||||
@ -28,53 +28,53 @@ structures and allows it to hook itself into specific areas to perform special a
|
||||
<hr>
|
||||
<h1>Table Of Contents</h1>
|
||||
<ul>
|
||||
<li><a href="#Part I - The External Interface">Part I - The External Interface</a>
|
||||
<li><a href="#part-i---the-external-interface">Part I - The External Interface</a>
|
||||
<ul>
|
||||
<li><a href="#Quick start">Quick start</a>
|
||||
<li><a href="#The name of the plugin">The name of the plugin</a>
|
||||
<li><a href="#The plugin directory structure">The plugin directory structure</a>
|
||||
<li><a href="#Initializing a new plugin directory">Initializing a new plugin directory</a>
|
||||
<li><a href="#The actual implementation">The actual implementation</a>
|
||||
<li><a href="#Construction and Destruction">Construction and Destruction</a>
|
||||
<li><a href="#Version number">Version number</a>
|
||||
<li><a href="#Description">Description</a>
|
||||
<li><a href="#Command line arguments">Command line arguments</a>
|
||||
<li><a href="#Command line help">Command line help</a>
|
||||
<li><a href="#Getting started">Getting started</a>
|
||||
<li><a href="#Shutting down">Shutting down</a>
|
||||
<li><a href="#Logging">Logging</a>
|
||||
<li><a href="#Main menu entry">Main menu entry</a>
|
||||
<li><a href="#User interaction">User interaction</a>
|
||||
<li><a href="#Housekeeping">Housekeeping</a>
|
||||
<li><a href="#Main thread hook">Main thread hook</a>
|
||||
<li><a href="#Activity">Activity</a>
|
||||
<li><a href="#Wakeup">Wakeup</a>
|
||||
<li><a href="#Setup parameters">Setup parameters</a>
|
||||
<li><a href="#The Setup menu">The Setup menu</a>
|
||||
<li><a href="#Additional files">Additional files</a>
|
||||
<li><a href="#Internationalization">Internationalization</a>
|
||||
<li><a href="#Custom services">Custom services</a>
|
||||
<li><a href="#SVDRP commands">SVDRP commands</a>
|
||||
<li><a href="#Locking">Locking</a>
|
||||
<li><a href="#Loading plugins into VDR">Loading plugins into VDR</a>
|
||||
<li><a href="#Building the distribution package">Building the distribution package</a>
|
||||
<li><a href="#quick-start">Quick start</a>
|
||||
<li><a href="#the-name-of-the-plugin">The name of the plugin</a>
|
||||
<li><a href="#the-plugin-directory-structure">The plugin directory structure</a>
|
||||
<li><a href="#initializing-a-new-plugin-directory">Initializing a new plugin directory</a>
|
||||
<li><a href="#the-actual-implementation">The actual implementation</a>
|
||||
<li><a href="#construction-and-destruction">Construction and Destruction</a>
|
||||
<li><a href="#version-number">Version number</a>
|
||||
<li><a href="#description">Description</a>
|
||||
<li><a href="#command-line-arguments">Command line arguments</a>
|
||||
<li><a href="#command-line-help">Command line help</a>
|
||||
<li><a href="#getting-started">Getting started</a>
|
||||
<li><a href="#shutting-down">Shutting down</a>
|
||||
<li><a href="#logging">Logging</a>
|
||||
<li><a href="#main-menu-entry">Main menu entry</a>
|
||||
<li><a href="#user-interaction">User interaction</a>
|
||||
<li><a href="#housekeeping">Housekeeping</a>
|
||||
<li><a href="#main-thread-hook">Main thread hook</a>
|
||||
<li><a href="#activity">Activity</a>
|
||||
<li><a href="#wakeup">Wakeup</a>
|
||||
<li><a href="#setup-parameters">Setup parameters</a>
|
||||
<li><a href="#the-setup-menu">The Setup menu</a>
|
||||
<li><a href="#additional-files">Additional files</a>
|
||||
<li><a href="#internationalization">Internationalization</a>
|
||||
<li><a href="#custom-services">Custom services</a>
|
||||
<li><a href="#svdrp-commands">SVDRP commands</a>
|
||||
<li><a href="#locking">Locking</a>
|
||||
<li><a href="#loading-plugins-into-vdr">Loading plugins into VDR</a>
|
||||
<li><a href="#building-the-distribution-package">Building the distribution package</a>
|
||||
</ul>
|
||||
<li><a href="#Part II - The Internal Interface">Part II - The Internal Interface</a>
|
||||
<li><a href="#part-ii---the-internal-interface">Part II - The Internal Interface</a>
|
||||
<ul>
|
||||
<li><a href="#Status monitor">Status monitor</a>
|
||||
<li><a href="#Players">Players</a>
|
||||
<li><a href="#Receivers">Receivers</a>
|
||||
<li><a href="#Filters">Filters</a>
|
||||
<li><a href="#The On Screen Display">The On Screen Display</a>
|
||||
<li><a href="#Skins">Skins</a>
|
||||
<li><a href="#Themes">Themes</a>
|
||||
<li><a href="#Devices">Devices</a>
|
||||
<li><a href="#Positioners">Positioners</a>
|
||||
<li><a href="#Audio">Audio</a>
|
||||
<li><a href="#Remote Control">Remote Control</a>
|
||||
<li><a href="#Conditional Access">Conditional Access</a>
|
||||
<li><a href="#Electronic Program Guide">Electronic Program Guide</a>
|
||||
<li><a href="#The video directory">The video directory</a>
|
||||
<li><a href="#status-monitor">Status monitor</a>
|
||||
<li><a href="#players">Players</a>
|
||||
<li><a href="#receivers">Receivers</a>
|
||||
<li><a href="#filters">Filters</a>
|
||||
<li><a href="#the-on-screen-display">The On Screen Display</a>
|
||||
<li><a href="#skins">Skins</a>
|
||||
<li><a href="#themes">Themes</a>
|
||||
<li><a href="#devices">Devices</a>
|
||||
<li><a href="#positioners">Positioners</a>
|
||||
<li><a href="#audio">Audio</a>
|
||||
<li><a href="#remote-control">Remote Control</a>
|
||||
<li><a href="#conditional-access">Conditional Access</a>
|
||||
<li><a href="#electronic-program-guide">Electronic Program Guide</a>
|
||||
<li><a href="#the-video-directory">The video directory</a>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
@ -150,7 +150,7 @@ that there is a <tt>Makefile</tt> that provides the targets <tt>all</tt>, <tt>in
|
||||
loadable library file for that plugin (we'll get to the details later).
|
||||
The dynamically loadable library file for the plugin shall be located directly under
|
||||
the plugin's source directory.
|
||||
See the section <a href="#Initializing a new plugin directory">Initializing a new plugin directory</a>
|
||||
See the section <a href="#initializing-a-new-plugin-directory">Initializing a new plugin directory</a>
|
||||
for how to generate an example Makefile.
|
||||
<p>
|
||||
The <tt>lib</tt> directory contains the dynamically loadable libraries of all
|
||||
@ -177,7 +177,7 @@ The VDR <tt>Makefile</tt> contains the target <tt>plugins</tt>, which calls
|
||||
plus the target <tt>clean-plugins</tt>, which calls <tt>make clean</tt> in
|
||||
each of these directories.
|
||||
<p>
|
||||
If you download a plugin <a href="#Building the distribution package">package</a>
|
||||
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-hello-0.0.1.tgz</tt>
|
||||
@ -234,7 +234,7 @@ necessary. Don't forget to adapt the <tt>Makefile</tt> appropriately.
|
||||
<div>Use the source, Luke!</div><p>
|
||||
|
||||
A newly initialized plugin doesn't really do very much yet.
|
||||
If you <a href="#Loading plugins into VDR">load it into VDR</a> you will find a new
|
||||
If you <a href="#loading-plugins-into-vdr">load it into VDR</a> you will find a new
|
||||
entry in the main menu, with the same name as your plugin (where the first character
|
||||
has been converted to uppercase). There will also be a new entry named "Plugins" in
|
||||
the "Setup" menu, which will bring up a list of all loaded plugins, through which you
|
||||
@ -291,7 +291,7 @@ 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>
|
||||
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).
|
||||
@ -311,8 +311,8 @@ The <b>constructor</b> shall initialize any member variables the plugin defines,
|
||||
<b>must not access any global structures of VDR</b>.
|
||||
It also must not create any threads or other large data structures. These things
|
||||
are done in the
|
||||
<a href="#Getting started"><tt>Initialize()</tt></a> or
|
||||
<a href="#Getting started"><tt>Start()</tt></a>
|
||||
<a href="#getting-started"><tt>Initialize()</tt></a> or
|
||||
<a href="#getting-started"><tt>Start()</tt></a>
|
||||
function later.
|
||||
Constructing a plugin object shall not have any side effects or produce any output,
|
||||
since VDR, for instance, has to create the plugin objects in order to get their
|
||||
@ -320,7 +320,7 @@ command line help - and after that immediately destroys them again.
|
||||
<p>
|
||||
The <b>destructor</b> has to clean up any data created by the plugin.
|
||||
Any threads the plugin may have created shall be stopped in the
|
||||
<a href="#Shutting down"><tt>Stop()</tt></a> function.
|
||||
<a href="#shutting-down"><tt>Stop()</tt></a> function.
|
||||
<p>
|
||||
Of course, if your plugin doesn't define any member variables that need to be
|
||||
initialized (and deleted), you don't need to implement either of these functions.
|
||||
@ -393,7 +393,7 @@ virtual const char *Description(void)
|
||||
</pre>
|
||||
|
||||
Note the <tt>tr()</tt> around the <tt>DESCRIPTION</tt>, which allows the description
|
||||
to be <a href="#Internationalization">internationalized</a>.
|
||||
to be <a href="#internationalization">internationalized</a>.
|
||||
|
||||
<hr><h2>Command line arguments</h2>
|
||||
|
||||
@ -483,7 +483,7 @@ be shorter than 80 characters.
|
||||
<div>Let's get ready to rumble!</div><p>
|
||||
|
||||
If a plugin implements a function that runs in the background (presumably in a
|
||||
thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
|
||||
thread of its own), or wants to make use of <a href="#internationalization">internationalization</a>,
|
||||
it needs to implement one of the functions
|
||||
|
||||
<pre>
|
||||
@ -529,9 +529,9 @@ virtual void Stop(void);
|
||||
in which it shall stop them.
|
||||
<p>
|
||||
The <tt>Stop()</tt> function will only be called if a previous call to the
|
||||
<a href="#Getting started"><tt>Start()</tt></a> function of that plugin has
|
||||
<a href="#getting-started"><tt>Start()</tt></a> function of that plugin has
|
||||
returned <i>true</i>. The <tt>Stop()</tt> functions are called in the reverse order
|
||||
as the <a href="#Getting started"><tt>Start()</tt></a> functions were called.
|
||||
as the <a href="#getting-started"><tt>Start()</tt></a> functions were called.
|
||||
|
||||
<hr><h2>Logging</h2>
|
||||
|
||||
@ -625,7 +625,7 @@ which can do one of three things:
|
||||
eventually start a custom player to replay a file other than a VDR recording.
|
||||
<li>Return a pointer to a <tt>cOsdObject</tt> object which will be displayed
|
||||
instead of the normal menu. The derived <tt>cOsdObject</tt> can open a
|
||||
<a href="#The On Screen Display">raw OSD</a> from within its <tt>Show()</tt>
|
||||
<a href="#the-on-screen-display">raw OSD</a> from within its <tt>Show()</tt>
|
||||
function (it should not attempt to do so from within its constructor, since
|
||||
at that time the OSD is still in use by the main menu).
|
||||
See the 'osddemo' example that comes with VDR for a demonstration of how this
|
||||
@ -670,7 +670,7 @@ the plugin should launch a separate thread to do this.
|
||||
<div>Pushing in...</div><p>
|
||||
|
||||
Normally a plugin only reacts on user input if directly called through its
|
||||
<a href="#Main menu entry">main menu entry</a>, or performs some background
|
||||
<a href="#main-menu-entry">main menu entry</a>, or performs some background
|
||||
activity in a separate thread. However, sometimes a plugin may need to do
|
||||
something in the context of the main program thread, without being explicitly
|
||||
called up by the user. In such a case it can implement the function
|
||||
@ -767,7 +767,7 @@ virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
</pre>
|
||||
|
||||
The <tt>SetupMenu()</tt> function shall return the plugin's <a href="#The Setup menu"><i>Setup</i> menu</a>
|
||||
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
|
||||
@ -789,7 +789,7 @@ bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||
</pre>
|
||||
|
||||
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.
|
||||
used in the <a href="#the-setup-menu"><i>Setup</i> menu</a>'s <tt>Store()</tt> function.
|
||||
<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,
|
||||
@ -895,7 +895,7 @@ free to store such files anywhere it sees fit, it might be a good idea to put th
|
||||
place, preferably where such data already exists.
|
||||
<p>
|
||||
<i>configuration files</i>, maybe for data that can't be stored in the simple
|
||||
<a href="#Setup parameters">setup parameters</a> of VDR, or maybe because it needs to
|
||||
<a href="#setup-parameters">setup parameters</a> of VDR, or maybe because it needs to
|
||||
launch other programs that simply need a separate configuration file.
|
||||
<p>
|
||||
<i>cache files</i>, to store data so that future requests for that data can be served faster. The data
|
||||
@ -1158,7 +1158,7 @@ when presenting them to the caller, and the continuation character ('<tt>-</tt>'
|
||||
will be set for all but the last one.
|
||||
<p>
|
||||
<b>The SVDRP functions are called from the separate "SVDRP server handler" thread.
|
||||
Therefore the plugin needs to take care of proper <a href="#Locking">locking</a> if it accesses any
|
||||
Therefore the plugin needs to take care of proper <a href="#locking">locking</a> if it accesses any
|
||||
global data.</b>
|
||||
|
||||
<hr><h2>Locking</h2>
|
||||
@ -1248,7 +1248,7 @@ There can be any number of <b><tt>-L</tt></b> options, and each of them will app
|
||||
When started with the <b><tt>-h</tt></b> or <b><tt>-V</tt></b> option (for <i>help</i>
|
||||
or <i>version</i> information, respectively), VDR will automatically load all plugins
|
||||
in the default or given directory that match the VDR plugin
|
||||
<a href="#The plugin directory structure">naming convention</a>,
|
||||
<a href="#the-plugin-directory-structure">naming convention</a>,
|
||||
and display their help and/or version information in addition to its own output.
|
||||
|
||||
<hr><h2>Building the distribution package</h2>
|
||||
@ -1258,7 +1258,7 @@ and display their help and/or version information in addition to its own output.
|
||||
If you want to make your plugin available to other VDR users, you'll need to
|
||||
make a package that can be easily distributed.
|
||||
The <tt>Makefile</tt> that has been created by the call to
|
||||
<a href="#Initializing a new plugin directory"><tt>newplugin</tt></a>
|
||||
<a href="#initializing-a-new-plugin-directory"><tt>newplugin</tt></a>
|
||||
provides the target <tt>dist</tt>, which does this for you.
|
||||
<p>
|
||||
Simply change into your source directory and execute <tt>make dist</tt>:
|
||||
@ -1769,7 +1769,7 @@ public:
|
||||
|
||||
See the comments in <tt>VDR/skins.h</tt> for details. <tt>VDR/skinclassic.[hc]</tt>
|
||||
can be used as an example for how to implement all the necessary classes and
|
||||
functions to compose a complete skin. See also the chapter about <a href="#Themes">themes</a>
|
||||
functions to compose a complete skin. See also the chapter about <a href="#themes">themes</a>
|
||||
if you want to make the colors used by your skin configurable.
|
||||
<p>
|
||||
To add your new skin to the list of skins available to the user in Setup/OSD/Skin,
|
||||
@ -1779,7 +1779,7 @@ all you need to do is create a new object of your skin class, as in
|
||||
new cMySkin;
|
||||
</pre>
|
||||
|
||||
in the <a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
in the <a href="#getting-started"><tt>Start()</tt></a> function of your plugin.
|
||||
Do not delete this object, it will be automatically deleted when the program ends.
|
||||
<p>
|
||||
In order to be able to easily identify plugins that implement a skin it is recommended
|
||||
@ -1795,7 +1795,7 @@ where <tt>xyz</tt> is the actual name of the skin.
|
||||
|
||||
<div>Eye of the beholder...</div><p>
|
||||
|
||||
A <i>theme</i> is a collection of colors that can be used by a <a href="#Skins">skin</a>.
|
||||
A <i>theme</i> is a collection of colors that can be used by a <a href="#skins">skin</a>.
|
||||
Since every skin most likely has its own idea about what parts of it can be
|
||||
<i>themed</i>, and different skins may have completely different numbers of
|
||||
"themeable" parts, a particular theme can only be used with the skin it was designed
|
||||
@ -1969,7 +1969,7 @@ StartSectionHandler();
|
||||
|
||||
from its constructor.
|
||||
<p>
|
||||
See <a href="#Filters">Filters</a> on how to set up actual filters that can
|
||||
See <a href="#filters">Filters</a> on how to set up actual filters that can
|
||||
handle section data.
|
||||
|
||||
<p>
|
||||
@ -2029,9 +2029,9 @@ See <tt>VDR/dvbdevice.c</tt> for the implementation of the <tt>cDvbDevice</tt>
|
||||
initialize function.
|
||||
<p>
|
||||
A plugin that adds devices to a VDR instance shall call this
|
||||
function from its <a href="#Getting started"><tt>Initialize()</tt></a> function
|
||||
function from its <a href="#getting-started"><tt>Initialize()</tt></a> function
|
||||
to make sure other plugins that may need to have access to all available devices
|
||||
will see them in their <a href="#Getting started"><tt>Start()</tt></a> function.
|
||||
will see them in their <a href="#getting-started"><tt>Start()</tt></a> function.
|
||||
<p>
|
||||
Nothing needs to be done to shut down the devices. VDR will automatically
|
||||
shut down (delete) all devices when the program terminates. It is therefore
|
||||
@ -2124,7 +2124,7 @@ public:
|
||||
See the implementation of <tt>cDiseqcPositioner</tt> in <tt>diseqc.c</tt> for details.
|
||||
<p>
|
||||
You should create your derived positioner object in the
|
||||
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
<a href="#getting-started"><tt>Start()</tt></a> function of your plugin.
|
||||
Note that the object has to be created on the heap (using <tt>new</tt>),
|
||||
and you shall not delete it at any point (it will be deleted automatically
|
||||
when the program ends).
|
||||
@ -2156,7 +2156,7 @@ public:
|
||||
</pre>
|
||||
|
||||
You should create your derived audio object in the
|
||||
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
<a href="#getting-started"><tt>Start()</tt></a> function of your plugin.
|
||||
Note that the object has to be created on the heap (using <tt>new</tt>),
|
||||
and you shall not delete it at any point (it will be deleted automatically
|
||||
when the program ends).
|
||||
@ -2214,7 +2214,7 @@ class to work, but typically you may want to have a separate thread running that
|
||||
collects the input and delivers it to the <tt>cRemote</tt> base class.
|
||||
<p>
|
||||
You should create your derived remote control object in the
|
||||
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
<a href="#getting-started"><tt>Start()</tt></a> function of your plugin.
|
||||
Note that the object has to be created on the heap (using <tt>new</tt>),
|
||||
and you shall not delete it at any point (it will be deleted automatically
|
||||
when the program ends).
|
||||
@ -2392,7 +2392,7 @@ public:
|
||||
See the description in <tt>videodir.h</tt> for details.
|
||||
<p>
|
||||
You should create your derived video directory object in the
|
||||
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||
<a href="#getting-started"><tt>Start()</tt></a> function of your plugin.
|
||||
Note that the object has to be created on the heap (using <tt>new</tt>),
|
||||
and you shall not delete it at any point (it will be deleted automatically
|
||||
when the program ends).
|
||||
|
Loading…
x
Reference in New Issue
Block a user