mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Made remote controls plugin aware
This commit is contained in:
parent
f3af8e065a
commit
fc66860847
17
HISTORY
17
HISTORY
@ -1479,7 +1479,7 @@ Video Disk Recorder Revision History
|
|||||||
Stefan Huelswitt).
|
Stefan Huelswitt).
|
||||||
- Added an EPG bugfix for the latest VOX EPG data format.
|
- Added an EPG bugfix for the latest VOX EPG data format.
|
||||||
|
|
||||||
2002-09-21: Version 1.1.11
|
2002-09-29: Version 1.1.11
|
||||||
|
|
||||||
- Fixed an incomplete initialization of the filter parameters in eit.c (thanks
|
- Fixed an incomplete initialization of the filter parameters in eit.c (thanks
|
||||||
to Jeremy Hall).
|
to Jeremy Hall).
|
||||||
@ -1517,3 +1517,18 @@ Video Disk Recorder Revision History
|
|||||||
numbers may be different.
|
numbers may be different.
|
||||||
- Added a missing 'public' keyword in device.h (thanks to Martin Hammerschmid).
|
- Added a missing 'public' keyword in device.h (thanks to Martin Hammerschmid).
|
||||||
- Fixed a race condition when starting 'Transfer Mode'.
|
- Fixed a race condition when starting 'Transfer Mode'.
|
||||||
|
- Rearranged the remote control key handling to allow plugins to implement
|
||||||
|
additional types of remote controls (see PLUGINS.html, section "Remote Control").
|
||||||
|
The previously used files 'keys.conf' and 'keys-pc.conf' have been replaced
|
||||||
|
by the file 'remote.conf', which holds the key definitions of all remote controls.
|
||||||
|
- The LIRC remote control keys are now handled just like the keyboard and RCU keys.
|
||||||
|
This means that you can use the lircd.conf file as is for your remote control,
|
||||||
|
without the need of editing it to make the key names the same as used in VDR.
|
||||||
|
When first starting VDR it will go into the "Learning keys" mode and ask you
|
||||||
|
to press the various keys. The resulting key assignment will be stored in
|
||||||
|
the file 'remote.conf'.
|
||||||
|
Since I have no way of testing the LIRC support, I hope I didn't break it in
|
||||||
|
the process...
|
||||||
|
- While learning the remote control keys it is now possible to press the 'Menu'
|
||||||
|
key to skip the definition of keys that are not available on your particular
|
||||||
|
RC unit.
|
||||||
|
14
INSTALL
14
INSTALL
@ -330,8 +330,7 @@ of the card that can receive it.
|
|||||||
Learning the remote control keys:
|
Learning the remote control keys:
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
There is no default 'keys.conf' file, so if you compile the program
|
There is no default 'remote.conf' file, so you will have to go through a "teach-in"
|
||||||
with 'REMOTE=RCU' you will have to go through a "teach-in"
|
|
||||||
session that allows the program to learn your remote control codes.
|
session that allows the program to learn your remote control codes.
|
||||||
It will first attempt to determine the basic data transfer mode and
|
It will first attempt to determine the basic data transfer mode and
|
||||||
timing of your remote control unit, and then will ask you to press one
|
timing of your remote control unit, and then will ask you to press one
|
||||||
@ -342,11 +341,8 @@ you define, the more you will be able to navigate through the menus and
|
|||||||
control recording/replaying. The program uses only a very small number
|
control recording/replaying. The program uses only a very small number
|
||||||
of keys which have multiple meanings in the various modes (see MANUAL
|
of keys which have multiple meanings in the various modes (see MANUAL
|
||||||
for a detailed description).
|
for a detailed description).
|
||||||
If the program has been built with "REMOTE=KBD", it will use the
|
|
||||||
key configuration file 'keys-pc.conf', so that you won't loose data
|
|
||||||
when switching between remote control and keyboard mode.
|
|
||||||
|
|
||||||
The default PC key assignments are:
|
The recommended PC key assignments are:
|
||||||
|
|
||||||
Up, Down, Left, Right Crsr keys in numeric block
|
Up, Down, Left, Right Crsr keys in numeric block
|
||||||
Menu 'Home' in numeric block
|
Menu 'Home' in numeric block
|
||||||
@ -359,10 +355,6 @@ The default PC key assignments are:
|
|||||||
Mute 'm'
|
Mute 'm'
|
||||||
|
|
||||||
If you prefer different key assignments, or if the default doesn't work for
|
If you prefer different key assignments, or if the default doesn't work for
|
||||||
your keyboard, simply delete the file 'keys-pc.conf' and restart 'vdr' to get
|
your keyboard, simply delete the file 'remote.conf' and restart 'vdr' to get
|
||||||
into learning mode.
|
into learning mode.
|
||||||
|
|
||||||
If the program has been compiled with 'REMOTE=LIRC', no 'keys.conf' file
|
|
||||||
will be used. Instead, the key names as listed in the source file 'config.c'
|
|
||||||
must be used when setting up LIRC. See http://www.lirc.org for more about LIRC.
|
|
||||||
|
|
||||||
|
4
Makefile
4
Makefile
@ -4,7 +4,7 @@
|
|||||||
# See the main source file 'vdr.c' for copyright information and
|
# See the main source file 'vdr.c' for copyright information and
|
||||||
# how to reach the author.
|
# how to reach the author.
|
||||||
#
|
#
|
||||||
# $Id: Makefile 1.46 2002/09/08 14:00:48 kls Exp $
|
# $Id: Makefile 1.47 2002/09/28 14:12:43 kls Exp $
|
||||||
|
|
||||||
.DELETE_ON_ERROR:
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ endif
|
|||||||
DTVLIB = $(DTVDIR)/libdtv.a
|
DTVLIB = $(DTVDIR)/libdtv.a
|
||||||
|
|
||||||
OBJS = audio.o config.o cutter.o device.o dvbdevice.o dvbosd.o dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o\
|
OBJS = audio.o config.o cutter.o device.o dvbdevice.o dvbosd.o dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o\
|
||||||
interface.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o receiver.o\
|
interface.o keys.o lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o receiver.o\
|
||||||
recorder.o recording.o remote.o remux.o ringbuffer.o spu.o status.o svdrp.o thread.o\
|
recorder.o recording.o remote.o remux.o ringbuffer.o spu.o status.o svdrp.o thread.o\
|
||||||
tools.o transfer.o vdr.o videodir.o
|
tools.o transfer.o vdr.o videodir.o
|
||||||
|
|
||||||
|
140
PLUGINS.html
140
PLUGINS.html
@ -21,18 +21,18 @@ VDR program and present itself to the user.
|
|||||||
The <i>inside</i> interface provides the plugin code access to VDR's internal data
|
The <i>inside</i> interface provides the plugin code access to VDR's internal data
|
||||||
structures and allows it to hook itself into specific areas to perform special actions.
|
structures and allows it to hook itself into specific areas to perform special actions.
|
||||||
<p>
|
<p>
|
||||||
<!--X1.1.6--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||||
Important modifications introduced in version 1.1.6 are marked like this.
|
|
||||||
<!--X1.1.6--></td></tr></table>
|
|
||||||
<!--X1.1.7--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
|
||||||
Important modifications introduced in version 1.1.7 are marked like this.
|
Important modifications introduced in version 1.1.7 are marked like this.
|
||||||
<!--X1.1.7--></td></tr></table>
|
<!--X1.1.7--></td></tr></table>
|
||||||
<!--X1.1.8--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
<!--X1.1.8--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||||
Important modifications introduced in version 1.1.8 are marked like this.
|
Important modifications introduced in version 1.1.8 are marked like this.
|
||||||
<!--X1.1.8--></td></tr></table>
|
<!--X1.1.8--></td></tr></table>
|
||||||
<!--X1.1.9--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||||
Important modifications introduced in version 1.1.9 are marked like this.
|
Important modifications introduced in version 1.1.9 are marked like this.
|
||||||
<!--X1.1.9--></td></tr></table>
|
<!--X1.1.9--></td></tr></table>
|
||||||
|
<!--X1.1.11--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||||
|
Important modifications introduced in version 1.1.11 are marked like this.
|
||||||
|
<!--X1.1.11--></td></tr></table>
|
||||||
|
|
||||||
<a name="Part I - The Outside Interface"><hr><center><h1>Part I - The Outside Interface</h1></center>
|
<a name="Part I - The Outside Interface"><hr><center><h1>Part I - The Outside Interface</h1></center>
|
||||||
|
|
||||||
@ -957,7 +957,7 @@ stream. There are no prerequisites regarding the length or alignment of an
|
|||||||
individual block of data. The sum of all blocks must simply result in the
|
individual block of data. The sum of all blocks must simply result in the
|
||||||
desired video data stream, and it must be delivered fast enough so that the
|
desired video data stream, and it must be delivered fast enough so that the
|
||||||
DVB device doesn't run out of data.
|
DVB device doesn't run out of data.
|
||||||
<!--X1.1.7--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||||
To avoid busy loops the player should call its member function
|
To avoid busy loops the player should call its member function
|
||||||
|
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
@ -1065,7 +1065,6 @@ enjoy additional players, since they will be able to control them with actions
|
|||||||
that they already know. If you absolutely want to do things differently, just go
|
that they already know. If you absolutely want to do things differently, just go
|
||||||
ahead - it's your show...
|
ahead - it's your show...
|
||||||
|
|
||||||
<!--X1.1.6--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
|
||||||
<hr><h2>Receivers</h2>
|
<hr><h2>Receivers</h2>
|
||||||
|
|
||||||
<center><i><b>Tapping into the stream...</b></i></center><p>
|
<center><i><b>Tapping into the stream...</b></i></center><p>
|
||||||
@ -1119,7 +1118,6 @@ cDevice::PrimaryDevice()->AttachReceiver(Receiver);
|
|||||||
|
|
||||||
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
|
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
|
||||||
and will automatically detach itself from the <tt>cDevice</tt>.
|
and will automatically detach itself from the <tt>cDevice</tt>.
|
||||||
<!--X1.1.6--></td></tr></table>
|
|
||||||
|
|
||||||
<hr><h2>The On Screen Display</h2>
|
<hr><h2>The On Screen Display</h2>
|
||||||
|
|
||||||
@ -1151,7 +1149,6 @@ to define an actual OSD drawing area (see VDR/osdbase.h for the declarations
|
|||||||
of these functions, and VDR/osd.c to see how VDR opens the OSD and sets up
|
of these functions, and VDR/osd.c to see how VDR opens the OSD and sets up
|
||||||
its windows and color depths).
|
its windows and color depths).
|
||||||
|
|
||||||
<!--X1.1.6--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
|
||||||
<hr><h2>Devices</h2>
|
<hr><h2>Devices</h2>
|
||||||
|
|
||||||
<center><i><b>Expanding the possibilities</b></i></center><p>
|
<center><i><b>Expanding the possibilities</b></i></center><p>
|
||||||
@ -1187,7 +1184,7 @@ the <tt>cDvbDevice</tt>, which is used to access the DVB PCI cards.
|
|||||||
If the new device can receive, it most likely needs to provide a way of
|
If the new device can receive, it most likely needs to provide a way of
|
||||||
selecting which channel it shall tune to:
|
selecting which channel it shall tune to:
|
||||||
|
|
||||||
<!--X1.1.9--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
||||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||||
@ -1206,7 +1203,7 @@ A device that can be used for recording must implement the functions
|
|||||||
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
|
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
|
||||||
virtual bool OpenDvr(void);
|
virtual bool OpenDvr(void);
|
||||||
virtual void CloseDvr(void);
|
virtual void CloseDvr(void);
|
||||||
<!--X1.1.9--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||||
virtual bool GetTSPacket(uchar *&Data);
|
virtual bool GetTSPacket(uchar *&Data);
|
||||||
<!--X1.1.9--></td></tr></table>
|
<!--X1.1.9--></td></tr></table>
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
@ -1230,7 +1227,7 @@ to indicate this to VDR.
|
|||||||
<p>
|
<p>
|
||||||
The functions to implement replaying capabilites are
|
The functions to implement replaying capabilites are
|
||||||
|
|
||||||
<!--X1.1.7--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
virtual bool HasDecoder(void) const;
|
virtual bool HasDecoder(void) const;
|
||||||
virtual bool SetPlayMode(ePlayMode PlayMode);
|
virtual bool SetPlayMode(ePlayMode PlayMode);
|
||||||
@ -1254,7 +1251,7 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
|
|||||||
virtual void SetVolumeDevice(int Volume);
|
virtual void SetVolumeDevice(int Volume);
|
||||||
</pre></td></tr></table><p>
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
<!--X1.1.8--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
<!--X1.1.8--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||||
<p>
|
<p>
|
||||||
<b>On Screen Display</b>
|
<b>On Screen Display</b>
|
||||||
<p>
|
<p>
|
||||||
@ -1294,7 +1291,120 @@ 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
|
shut down (delete) all devices when the program terminates. It is therefore
|
||||||
important that the devices are created on the heap, using the <tt>new</tt>
|
important that the devices are created on the heap, using the <tt>new</tt>
|
||||||
operator!
|
operator!
|
||||||
<!--X1.1.6--></td></tr></table>
|
|
||||||
|
<!--X1.1.11--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||||
|
<hr><h2>Remote Control</h2>
|
||||||
|
|
||||||
|
<center><i><b>The joy of zapping!</b></i></center><p>
|
||||||
|
|
||||||
|
There are several ways to control the operation of VDR. The builtin methods
|
||||||
|
are using the PC keyboard, a homebuilt RCU unit or the LIRC interface.
|
||||||
|
Of course there may be many more ways you might think of to implement a
|
||||||
|
remote control, so a plugin can use the <tt>cRemote</tt> class to do that.
|
||||||
|
<p>
|
||||||
|
The simplest method for a plugin to issue commands to VDR is to call the
|
||||||
|
static function <tt>cRemote::Put(eKeys Key)</tt>, as in
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
cRemote::Put(kUp);
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
In this case the plugin must do the mapping of whatever incoming signal or code
|
||||||
|
it processes to the <tt>eKeys</tt> values itself. This makes sense if the incoming
|
||||||
|
codes are well known and won't ever change.
|
||||||
|
<p>
|
||||||
|
In cases where the incoming codes are not known, or not all available keys may
|
||||||
|
be supported by the actual remote control in use, you may want to derive your
|
||||||
|
own remote control class from <tt>cRemote</tt>, as in
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
#include <vdr/remote.h>
|
||||||
|
#include <vdr/thread.h>
|
||||||
|
|
||||||
|
class cMyRemote : public cRemote, private cThread {
|
||||||
|
private:
|
||||||
|
virtual void Action(void);
|
||||||
|
public:
|
||||||
|
cMyRemote(const char *Name);
|
||||||
|
virtual bool Initialize(void);
|
||||||
|
};
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
Note that deriving from <tt>cThread</tt> is not required for a remote control
|
||||||
|
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.
|
||||||
|
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).
|
||||||
|
<p>
|
||||||
|
The constructor of your remote control class should look like this
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
cMyRemote::cMyRemote(const char *Name)
|
||||||
|
:cRemote(Name)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
The <tt>Name</tt> is important in order for the <tt>cRemote</tt> base class
|
||||||
|
to be able to distinguish the codes for the various remote controls.
|
||||||
|
When creating your <tt>cMyRemote</tt> object you should use the value returned
|
||||||
|
by the <tt>Name()</tt> member function of the plugin class, which returns the
|
||||||
|
plugin's name. Calling <tt>Start()</tt> will start the thread that collects
|
||||||
|
the incoming data (by calling your <tt>Action()</tt> function).
|
||||||
|
In case you need to do any other setup steps, like opening a file or initializing
|
||||||
|
member variables, you should do so before calling <tt>Start()</tt>.
|
||||||
|
<p>
|
||||||
|
VDR will handle everything necessary to learn the key mappings of your remote
|
||||||
|
control. In order to do so, it will first call the virtual function <tt>Initialize()</tt>,
|
||||||
|
in which you should take all necessary steps to make sure your remote control
|
||||||
|
can be accessed. This may, for instance, include trying various communications
|
||||||
|
protocols. <tt>Initialize()</tt>, if implemented, shall only return after it has
|
||||||
|
made sure data can be received from the remote control. Before calling this
|
||||||
|
function, VDR will prompt the user on the OSD to press any key on the remote control.
|
||||||
|
As soon as your derived <tt>cRemote</tt> class has detected useful incoming data,
|
||||||
|
<tt>Initialize()</tt> should return <i>true</i>. If any fatal error occurs, <i>false</i>
|
||||||
|
should be returned.
|
||||||
|
<p>
|
||||||
|
If your remote control class needs some setup data that shall be
|
||||||
|
readily available next time VDR starts (without having to go through the initialization
|
||||||
|
procedure again) it can use the <tt>cRemote</tt> member functions
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
void PutSetup(const char *Setup);
|
||||||
|
const char *GetSetup(void);
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
to store and retrieve a character string containing whatever data is needed.
|
||||||
|
Note that the <tt>Initialize()</tt> function will only be called if there are
|
||||||
|
no key mappings known for this remote control. Once the key mappings have been
|
||||||
|
learned, <tt>Initialize()</tt> will never be called again.
|
||||||
|
<p>
|
||||||
|
The <tt>cRemote</tt> class assumes that any incoming remote control code can be
|
||||||
|
expressed as a character string. So whatever data your remote control provides
|
||||||
|
needs to be given to the base class by calling
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
Put(const char *Code, bool Repeat = false, bool Release = false);
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
where <tt>Code</tt> is the string representation of the remote control's
|
||||||
|
incoming data. <tt>Repeat</tt> and <tt>Release</tt> are boolean flags that
|
||||||
|
indicate whether this is a repeated keypress, or the key has been released.
|
||||||
|
Since a common case for remote control data is to be given as a numerical
|
||||||
|
value, there is another <tt>Put()</tt> function available for your convenience,
|
||||||
|
which takes a 64 bit unsigned integer value instead of a character string:
|
||||||
|
|
||||||
|
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||||
|
Put(uint64 Code, bool Repeat = false, bool Release = false);
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
The other parameters have the same meaning as in the first version of this function.
|
||||||
|
<!--X1.1.11--></td></tr></table>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
172
config.c
172
config.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.c 1.105 2002/09/04 13:45:56 kls Exp $
|
* $Id: config.c 1.106 2002/09/28 09:43:41 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -19,169 +19,6 @@
|
|||||||
// format characters in order to allow any number of blanks after a numeric
|
// format characters in order to allow any number of blanks after a numeric
|
||||||
// value!
|
// value!
|
||||||
|
|
||||||
// -- cKeys ------------------------------------------------------------------
|
|
||||||
|
|
||||||
tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
|
|
||||||
{ kUp, "Up", 0 },
|
|
||||||
{ kDown, "Down", 0 },
|
|
||||||
{ kMenu, "Menu", 0 },
|
|
||||||
{ kOk, "Ok", 0 },
|
|
||||||
{ kBack, "Back", 0 },
|
|
||||||
{ kLeft, "Left", 0 },
|
|
||||||
{ kRight, "Right", 0 },
|
|
||||||
{ kRed, "Red", 0 },
|
|
||||||
{ kGreen, "Green", 0 },
|
|
||||||
{ kYellow, "Yellow", 0 },
|
|
||||||
{ kBlue, "Blue", 0 },
|
|
||||||
{ k0, "0", 0 },
|
|
||||||
{ k1, "1", 0 },
|
|
||||||
{ k2, "2", 0 },
|
|
||||||
{ k3, "3", 0 },
|
|
||||||
{ k4, "4", 0 },
|
|
||||||
{ k5, "5", 0 },
|
|
||||||
{ k6, "6", 0 },
|
|
||||||
{ k7, "7", 0 },
|
|
||||||
{ k8, "8", 0 },
|
|
||||||
{ k9, "9", 0 },
|
|
||||||
{ kPower, "Power", 0 },
|
|
||||||
{ kVolUp, "Volume+", 0 },
|
|
||||||
{ kVolDn, "Volume-", 0 },
|
|
||||||
{ kMute, "Mute", 0 },
|
|
||||||
{ kNone, "", 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
cKeys::cKeys(void)
|
|
||||||
{
|
|
||||||
fileName = NULL;
|
|
||||||
code = 0;
|
|
||||||
address = 0;
|
|
||||||
keys = keyTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cKeys::Clear(void)
|
|
||||||
{
|
|
||||||
for (tKey *k = keys; k->type != kNone; k++)
|
|
||||||
k->code = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cKeys::SetDummyValues(void)
|
|
||||||
{
|
|
||||||
for (tKey *k = keys; k->type != kNone; k++)
|
|
||||||
k->code = k->type + 1; // '+1' to avoid 0
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cKeys::Load(const char *FileName)
|
|
||||||
{
|
|
||||||
isyslog("loading %s", FileName);
|
|
||||||
bool result = false;
|
|
||||||
if (FileName)
|
|
||||||
fileName = strdup(FileName);
|
|
||||||
if (fileName) {
|
|
||||||
FILE *f = fopen(fileName, "r");
|
|
||||||
if (f) {
|
|
||||||
int line = 0;
|
|
||||||
char buffer[MAXPARSEBUFFER];
|
|
||||||
result = true;
|
|
||||||
while (fgets(buffer, sizeof(buffer), f) > 0) {
|
|
||||||
line++;
|
|
||||||
if (!isempty(buffer)) {
|
|
||||||
char *Name = buffer;
|
|
||||||
char *p = strpbrk(Name, " \t");
|
|
||||||
if (p) {
|
|
||||||
*p = 0; // terminates 'Name'
|
|
||||||
while (*++p && isspace(*p))
|
|
||||||
;
|
|
||||||
if (*p) {
|
|
||||||
if (strcasecmp(Name, "Code") == 0)
|
|
||||||
code = *p;
|
|
||||||
else if (strcasecmp(Name, "Address") == 0)
|
|
||||||
address = strtol(p, NULL, 16);
|
|
||||||
else {
|
|
||||||
for (tKey *k = keys; k->type != kNone; k++) {
|
|
||||||
if (strcasecmp(Name, k->name) == 0) {
|
|
||||||
k->code = strtol(p, NULL, 16);
|
|
||||||
Name = NULL; // to indicate that we found it
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Name) {
|
|
||||||
esyslog("unknown key in %s, line %d\n", fileName, line);
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
esyslog("error in %s, line %d\n", fileName, line);
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("can't open '%s'\n", fileName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("no key configuration file name supplied!\n");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cKeys::Save(void)
|
|
||||||
{
|
|
||||||
cSafeFile f(fileName);
|
|
||||||
if (f.Open()) {
|
|
||||||
fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address);
|
|
||||||
for (tKey *k = keys; k->type != kNone; k++)
|
|
||||||
fprintf(f, "%s\t%08X\n", k->name, k->code);
|
|
||||||
return f.Close();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
eKeys cKeys::Get(unsigned int Code)
|
|
||||||
{
|
|
||||||
if (Code != 0) {
|
|
||||||
tKey *k;
|
|
||||||
for (k = keys; k->type != kNone; k++) {
|
|
||||||
if (k->code == Code)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return k->type;
|
|
||||||
}
|
|
||||||
return kNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
eKeys cKeys::Translate(const char *Command)
|
|
||||||
{
|
|
||||||
if (Command) {
|
|
||||||
const tKey *k = keys;
|
|
||||||
while ((k->type != kNone) && strcasecmp(k->name, Command) != 0)
|
|
||||||
k++;
|
|
||||||
return k->type;
|
|
||||||
}
|
|
||||||
return kNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int cKeys::Encode(const char *Command)
|
|
||||||
{
|
|
||||||
eKeys k = Translate(Command);
|
|
||||||
if (k != kNone)
|
|
||||||
return keys[k].code;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cKeys::Set(eKeys Key, unsigned int Code)
|
|
||||||
{
|
|
||||||
for (tKey *k = keys; k->type != kNone; k++) {
|
|
||||||
if (k->type == Key) {
|
|
||||||
k->code = Code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- cChannel ---------------------------------------------------------------
|
// -- cChannel ---------------------------------------------------------------
|
||||||
|
|
||||||
char *cChannel::buffer = NULL;
|
char *cChannel::buffer = NULL;
|
||||||
@ -247,7 +84,6 @@ bool cChannel::Parse(const char *s)
|
|||||||
if (*s == ':') {
|
if (*s == ':') {
|
||||||
if (*++s) {
|
if (*++s) {
|
||||||
strn0cpy(name, s, MaxChannelName);
|
strn0cpy(name, s, MaxChannelName);
|
||||||
name[strlen(name) - 1] = 0; // strip the '\n'
|
|
||||||
groupSep = true;
|
groupSep = true;
|
||||||
number = 0;
|
number = 0;
|
||||||
}
|
}
|
||||||
@ -696,7 +532,7 @@ bool cSVDRPhost::Parse(const char *s)
|
|||||||
if (p) {
|
if (p) {
|
||||||
char *error = NULL;
|
char *error = NULL;
|
||||||
int m = strtoul(p + 1, &error, 10);
|
int m = strtoul(p + 1, &error, 10);
|
||||||
if (error && !isspace(*error) || m > 32)
|
if (error && *error && !isspace(*error) || m > 32)
|
||||||
return false;
|
return false;
|
||||||
*(char *)p = 0; // yes, we know it's 'const' - will be restored!
|
*(char *)p = 0; // yes, we know it's 'const' - will be restored!
|
||||||
if (m == 0)
|
if (m == 0)
|
||||||
@ -733,10 +569,6 @@ bool cCaDefinition::Parse(const char *s)
|
|||||||
return 2 == sscanf(s, "%d %a[^\n]", &number, &description) && description && *description;
|
return 2 == sscanf(s, "%d %a[^\n]", &number, &description) && description && *description;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- cKeys ------------------------------------------------------------------
|
|
||||||
|
|
||||||
cKeys Keys;
|
|
||||||
|
|
||||||
// -- cCommands --------------------------------------------------------------
|
// -- cCommands --------------------------------------------------------------
|
||||||
|
|
||||||
cCommands Commands;
|
cCommands Commands;
|
||||||
|
78
config.h
78
config.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.h 1.128 2002/09/21 08:34:25 kls Exp $
|
* $Id: config.h 1.129 2002/09/29 10:42:17 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CONFIG_H
|
#ifndef __CONFIG_H
|
||||||
@ -30,69 +30,8 @@
|
|||||||
#define MINOSDHEIGHT 12
|
#define MINOSDHEIGHT 12
|
||||||
#define MAXOSDHEIGHT 21
|
#define MAXOSDHEIGHT 21
|
||||||
|
|
||||||
enum eKeys { // "Up" and "Down" must be the first two keys!
|
|
||||||
kUp,
|
|
||||||
kDown,
|
|
||||||
kMenu,
|
|
||||||
kOk,
|
|
||||||
kBack,
|
|
||||||
kLeft,
|
|
||||||
kRight,
|
|
||||||
kRed,
|
|
||||||
kGreen,
|
|
||||||
kYellow,
|
|
||||||
kBlue,
|
|
||||||
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
|
|
||||||
kPower,
|
|
||||||
kVolUp,
|
|
||||||
kVolDn,
|
|
||||||
kMute,
|
|
||||||
kNone,
|
|
||||||
// The following flags are OR'd with the above codes:
|
|
||||||
k_Repeat = 0x8000,
|
|
||||||
k_Release = 0x4000,
|
|
||||||
k_Flags = k_Repeat | k_Release,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is in preparation for having more key codes:
|
|
||||||
#define kMarkToggle k0
|
|
||||||
#define kMarkMoveBack k4
|
|
||||||
#define kMarkMoveForward k6
|
|
||||||
#define kMarkJumpBack k7
|
|
||||||
#define kMarkJumpForward k9
|
|
||||||
#define kEditCut k2
|
|
||||||
#define kEditTest k8
|
|
||||||
|
|
||||||
#define RAWKEY(k) (eKeys((k) & ~k_Flags))
|
|
||||||
#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
|
|
||||||
#define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
|
|
||||||
|
|
||||||
#define MaxFileName 256
|
#define MaxFileName 256
|
||||||
|
|
||||||
struct tKey {
|
|
||||||
eKeys type;
|
|
||||||
char *name;
|
|
||||||
unsigned int code;
|
|
||||||
};
|
|
||||||
|
|
||||||
class cKeys {
|
|
||||||
private:
|
|
||||||
char *fileName;
|
|
||||||
public:
|
|
||||||
unsigned char code;
|
|
||||||
unsigned short address;
|
|
||||||
tKey *keys;
|
|
||||||
cKeys(void);
|
|
||||||
void Clear(void);
|
|
||||||
void SetDummyValues(void);
|
|
||||||
bool Load(const char *FileName = NULL);
|
|
||||||
bool Save(void);
|
|
||||||
eKeys Translate(const char *Command);
|
|
||||||
unsigned int Encode(const char *Command);
|
|
||||||
eKeys Get(unsigned int Code);
|
|
||||||
void Set(eKeys Key, unsigned int Code);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4)
|
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4)
|
||||||
|
|
||||||
class cChannel : public cListObject {
|
class cChannel : public cListObject {
|
||||||
@ -214,6 +153,7 @@ public:
|
|||||||
template<class T> class cConfig : public cList<T> {
|
template<class T> class cConfig : public cList<T> {
|
||||||
private:
|
private:
|
||||||
char *fileName;
|
char *fileName;
|
||||||
|
bool allowComments;
|
||||||
void Clear(void)
|
void Clear(void)
|
||||||
{
|
{
|
||||||
free(fileName);
|
free(fileName);
|
||||||
@ -224,13 +164,17 @@ public:
|
|||||||
cConfig(void) { fileName = NULL; }
|
cConfig(void) { fileName = NULL; }
|
||||||
virtual ~cConfig() { free(fileName); }
|
virtual ~cConfig() { free(fileName); }
|
||||||
const char *FileName(void) { return fileName; }
|
const char *FileName(void) { return fileName; }
|
||||||
bool Load(const char *FileName, bool AllowComments = false)
|
bool Load(const char *FileName = NULL, bool AllowComments = false)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
if (FileName) {
|
||||||
|
free(fileName);
|
||||||
fileName = strdup(FileName);
|
fileName = strdup(FileName);
|
||||||
|
allowComments = AllowComments;
|
||||||
|
}
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (access(FileName, F_OK) == 0) {
|
if (fileName && access(fileName, F_OK) == 0) {
|
||||||
isyslog("loading %s", FileName);
|
isyslog("loading %s", fileName);
|
||||||
FILE *f = fopen(fileName, "r");
|
FILE *f = fopen(fileName, "r");
|
||||||
if (f) {
|
if (f) {
|
||||||
int line = 0;
|
int line = 0;
|
||||||
@ -238,11 +182,12 @@ public:
|
|||||||
result = true;
|
result = true;
|
||||||
while (fgets(buffer, sizeof(buffer), f) > 0) {
|
while (fgets(buffer, sizeof(buffer), f) > 0) {
|
||||||
line++;
|
line++;
|
||||||
if (AllowComments) {
|
if (allowComments) {
|
||||||
char *p = strchr(buffer, '#');
|
char *p = strchr(buffer, '#');
|
||||||
if (p)
|
if (p)
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
|
stripspace(buffer);
|
||||||
if (!isempty(buffer)) {
|
if (!isempty(buffer)) {
|
||||||
T *l = new T;
|
T *l = new T;
|
||||||
if (l->Parse(buffer))
|
if (l->Parse(buffer))
|
||||||
@ -322,7 +267,6 @@ public:
|
|||||||
|
|
||||||
extern cChannels Channels;
|
extern cChannels Channels;
|
||||||
extern cTimers Timers;
|
extern cTimers Timers;
|
||||||
extern cKeys Keys;
|
|
||||||
extern cCommands Commands;
|
extern cCommands Commands;
|
||||||
extern cSVDRPhosts SVDRPhosts;
|
extern cSVDRPhosts SVDRPhosts;
|
||||||
extern cCaDefinitions CaDefinitions;
|
extern cCaDefinitions CaDefinitions;
|
||||||
|
16
device.c
16
device.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: device.c 1.21 2002/09/15 11:50:19 kls Exp $
|
* $Id: device.c 1.22 2002/09/28 12:20:22 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
@ -201,7 +201,7 @@ void cDevice::SetVideoFormat(bool VideoFormat16_9)
|
|||||||
//#define PRINTPIDS(s) { char b[500]; char *q = b; q += sprintf(q, "%d %s ", CardIndex(), s); for (int i = 0; i < MAXPIDHANDLES; i++) q += sprintf(q, " %s%4d %d", i == ptOther ? "* " : "", pidHandles[i].pid, pidHandles[i].used); dsyslog(b); }
|
//#define PRINTPIDS(s) { char b[500]; char *q = b; q += sprintf(q, "%d %s ", CardIndex(), s); for (int i = 0; i < MAXPIDHANDLES; i++) q += sprintf(q, " %s%4d %d", i == ptOther ? "* " : "", pidHandles[i].pid, pidHandles[i].used); dsyslog(b); }
|
||||||
#define PRINTPIDS(s)
|
#define PRINTPIDS(s)
|
||||||
|
|
||||||
bool cDevice::HasPid(int Pid)
|
bool cDevice::HasPid(int Pid) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAXPIDHANDLES; i++) {
|
for (int i = 0; i < MAXPIDHANDLES; i++) {
|
||||||
if (pidHandles[i].pid == Pid)
|
if (pidHandles[i].pid == Pid)
|
||||||
@ -275,7 +275,7 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
|
bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -424,7 +424,7 @@ void cDevice::StillPicture(const uchar *Data, int Length)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDevice::Replaying(void)
|
bool cDevice::Replaying(void) const
|
||||||
{
|
{
|
||||||
return player != NULL;
|
return player != NULL;
|
||||||
}
|
}
|
||||||
@ -478,7 +478,7 @@ int cDevice::PlayAudio(const uchar *Data, int Length)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDevice::Priority(void)
|
int cDevice::Priority(void) const
|
||||||
{
|
{
|
||||||
int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
|
int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
|
||||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||||
@ -488,7 +488,7 @@ int cDevice::Priority(void)
|
|||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDevice::CanShift(int Ca, int Priority, int UsedCards)
|
int cDevice::CanShift(int Ca, int Priority, int UsedCards) const
|
||||||
{
|
{
|
||||||
return -1;//XXX+ too complex with multiple recordings per device
|
return -1;//XXX+ too complex with multiple recordings per device
|
||||||
// Test whether a receiver on this device can be shifted to another one
|
// Test whether a receiver on this device can be shifted to another one
|
||||||
@ -523,7 +523,7 @@ int cDevice::CanShift(int Ca, int Priority, int UsedCards)
|
|||||||
return ShiftLevel;
|
return ShiftLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDevice::ProvidesCa(int Ca)
|
int cDevice::ProvidesCa(int Ca) const
|
||||||
{
|
{
|
||||||
if (Ca == CardIndex() + 1)
|
if (Ca == CardIndex() + 1)
|
||||||
return 1; // exactly _this_ card was requested
|
return 1; // exactly _this_ card was requested
|
||||||
@ -542,7 +542,7 @@ int cDevice::ProvidesCa(int Ca)
|
|||||||
return result ? result + others : 0;
|
return result ? result + others : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDevice::Receiving(void)
|
bool cDevice::Receiving(void) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||||
if (receiver[i] && receiver[i]->priority >= 0) // cReceiver with priority < 0 doesn't count
|
if (receiver[i] && receiver[i]->priority >= 0) // cReceiver with priority < 0 doesn't count
|
||||||
|
20
device.h
20
device.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: device.h 1.19 2002/09/21 09:14:08 kls Exp $
|
* $Id: device.h 1.20 2002/09/28 12:20:34 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DEVICE_H
|
#ifndef __DEVICE_H
|
||||||
@ -111,7 +111,7 @@ public:
|
|||||||
bool IsPrimaryDevice(void) const { return this == primaryDevice; }
|
bool IsPrimaryDevice(void) const { return this == primaryDevice; }
|
||||||
int CardIndex(void) const { return cardIndex; }
|
int CardIndex(void) const { return cardIndex; }
|
||||||
// Returns the card index of this device (0 ... MAXDEVICES - 1).
|
// Returns the card index of this device (0 ... MAXDEVICES - 1).
|
||||||
int ProvidesCa(int Ca);
|
int ProvidesCa(int Ca) const;
|
||||||
// Checks whether this device provides the given value in its
|
// Checks whether this device provides the given value in its
|
||||||
// caCaps. Returns 0 if the value is not provided, 1 if only this
|
// caCaps. Returns 0 if the value is not provided, 1 if only this
|
||||||
// value is provided, and > 1 if this and other values are provided.
|
// value is provided, and > 1 if this and other values are provided.
|
||||||
@ -139,7 +139,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
static int currentChannel;
|
static int currentChannel;
|
||||||
public:
|
public:
|
||||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||||
// Returns true if this device can provide the given channel.
|
// Returns true if this device can provide the given channel.
|
||||||
// In case the device has cReceivers attached to it or it is the primary
|
// In case the device has cReceivers attached to it or it is the primary
|
||||||
// device, Priority is used to decide whether the caller's request can
|
// device, Priority is used to decide whether the caller's request can
|
||||||
@ -186,7 +186,7 @@ protected:
|
|||||||
cPidHandle(void) { pid = used = 0; handle = -1; }
|
cPidHandle(void) { pid = used = 0; handle = -1; }
|
||||||
};
|
};
|
||||||
cPidHandle pidHandles[MAXPIDHANDLES];
|
cPidHandle pidHandles[MAXPIDHANDLES];
|
||||||
bool HasPid(int Pid);
|
bool HasPid(int Pid) const;
|
||||||
// Returns true if this device is currently receiving the given PID.
|
// Returns true if this device is currently receiving the given PID.
|
||||||
bool AddPid(int Pid, ePidType PidType = ptOther);
|
bool AddPid(int Pid, ePidType PidType = ptOther);
|
||||||
// Adds a PID to the set of PIDs this device shall receive.
|
// Adds a PID to the set of PIDs this device shall receive.
|
||||||
@ -224,7 +224,7 @@ protected:
|
|||||||
virtual void SetVolumeDevice(int Volume);
|
virtual void SetVolumeDevice(int Volume);
|
||||||
// Sets the audio volume on this device (Volume = 0...255).
|
// Sets the audio volume on this device (Volume = 0...255).
|
||||||
public:
|
public:
|
||||||
bool IsMute(void) { return mute; }
|
bool IsMute(void) const { return mute; }
|
||||||
bool ToggleMute(void);
|
bool ToggleMute(void);
|
||||||
// Turns the volume off or on and returns the new mute state.
|
// Turns the volume off or on and returns the new mute state.
|
||||||
void SetVolume(int Volume, bool Absolute = false);
|
void SetVolume(int Volume, bool Absolute = false);
|
||||||
@ -269,7 +269,7 @@ public:
|
|||||||
// one video and one audio strem.
|
// one video and one audio strem.
|
||||||
virtual int PlayAudio(const uchar *Data, int Length);
|
virtual int PlayAudio(const uchar *Data, int Length);
|
||||||
// Plays additional audio streams, like Dolby Digital.
|
// Plays additional audio streams, like Dolby Digital.
|
||||||
bool Replaying(void);
|
bool Replaying(void) const;
|
||||||
// Returns true if we are currently replaying.
|
// Returns true if we are currently replaying.
|
||||||
void StopReplay(void);
|
void StopReplay(void);
|
||||||
// Stops the current replay session (if any).
|
// Stops the current replay session (if any).
|
||||||
@ -285,9 +285,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
cReceiver *receiver[MAXRECEIVERS];
|
cReceiver *receiver[MAXRECEIVERS];
|
||||||
int ca;
|
int ca;
|
||||||
int CanShift(int Ca, int Priority, int UsedCards = 0);
|
int CanShift(int Ca, int Priority, int UsedCards = 0) const;
|
||||||
protected:
|
protected:
|
||||||
int Priority(void);
|
int Priority(void) const;
|
||||||
// Returns the priority of the current receiving session (0..MAXPRIORITY),
|
// Returns the priority of the current receiving session (0..MAXPRIORITY),
|
||||||
// or -1 if no receiver is currently active. The primary device will
|
// or -1 if no receiver is currently active. The primary device will
|
||||||
// always return at least Setup.PrimaryLimit-1.
|
// always return at least Setup.PrimaryLimit-1.
|
||||||
@ -304,9 +304,9 @@ protected:
|
|||||||
// false in case of a non recoverable error, otherwise it returns true,
|
// false in case of a non recoverable error, otherwise it returns true,
|
||||||
// even if Data is NULL.
|
// even if Data is NULL.
|
||||||
public:
|
public:
|
||||||
int Ca(void) { return ca; }
|
int Ca(void) const { return ca; }
|
||||||
// Returns the ca of the current receiving session.
|
// Returns the ca of the current receiving session.
|
||||||
bool Receiving(void);
|
bool Receiving(void) const;
|
||||||
// Returns true if we are currently receiving.
|
// Returns true if we are currently receiving.
|
||||||
bool AttachReceiver(cReceiver *Receiver);
|
bool AttachReceiver(cReceiver *Receiver);
|
||||||
// Attaches the given receiver to this device.
|
// Attaches the given receiver to this device.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.c 1.19 2002/09/15 13:12:25 kls Exp $
|
* $Id: dvbdevice.c 1.20 2002/09/28 12:21:42 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbdevice.h"
|
#include "dvbdevice.h"
|
||||||
@ -344,7 +344,7 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
|
bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool hasPriority = Priority < 0 || Priority > this->Priority();
|
bool hasPriority = Priority < 0 || Priority > this->Priority();
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.h 1.10 2002/09/08 14:05:29 kls Exp $
|
* $Id: dvbdevice.h 1.11 2002/09/28 12:21:36 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBDEVICE_H
|
#ifndef __DVBDEVICE_H
|
||||||
@ -63,7 +63,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
int frequency;
|
int frequency;
|
||||||
public:
|
public:
|
||||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||||
protected:
|
protected:
|
||||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||||
|
|
||||||
|
18
i18n.c
18
i18n.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: i18n.c 1.92 2002/06/22 09:26:36 kls Exp $
|
* $Id: i18n.c 1.93 2002/09/29 12:32:46 kls Exp $
|
||||||
*
|
*
|
||||||
* Translations provided by:
|
* Translations provided by:
|
||||||
*
|
*
|
||||||
@ -2401,6 +2401,22 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"(Apasati 'Jos' pentru terminare)",
|
"(Apasati 'Jos' pentru terminare)",
|
||||||
"('Le' megnyomása a befejezéshez)",
|
"('Le' megnyomása a befejezéshez)",
|
||||||
},
|
},
|
||||||
|
{ "(press 'Menu' to skip this key)",
|
||||||
|
"('Menü' drücken zum Überspringen)",
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
"",// TODO
|
||||||
|
},
|
||||||
{ "Phase 3: Saving key codes",
|
{ "Phase 3: Saving key codes",
|
||||||
"Phase 3: Codes abspeichern",
|
"Phase 3: Codes abspeichern",
|
||||||
"Faza 3: Shranjujem kodo",
|
"Faza 3: Shranjujem kodo",
|
||||||
|
156
interface.c
156
interface.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: interface.c 1.54 2002/08/11 11:46:47 kls Exp $
|
* $Id: interface.c 1.55 2002/09/29 12:50:22 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
@ -22,27 +22,14 @@ cInterface::cInterface(int SVDRPport)
|
|||||||
open = 0;
|
open = 0;
|
||||||
cols[0] = 0;
|
cols[0] = 0;
|
||||||
width = height = 0;
|
width = height = 0;
|
||||||
keyFromWait = kNone;
|
|
||||||
interrupted = false;
|
interrupted = false;
|
||||||
rcIo = NULL;
|
|
||||||
SVDRP = NULL;
|
SVDRP = NULL;
|
||||||
#if defined(REMOTE_RCU)
|
|
||||||
rcIo = new cRcIoRCU("/dev/ttyS1");
|
|
||||||
#elif defined(REMOTE_LIRC)
|
|
||||||
rcIo = new cRcIoLIRC("/dev/lircd");
|
|
||||||
#elif defined(REMOTE_KBD)
|
|
||||||
rcIo = new cRcIoKBD;
|
|
||||||
#else
|
|
||||||
rcIo = new cRcIoBase; // acts as a dummy device
|
|
||||||
#endif
|
|
||||||
rcIo->SetCode(Keys.code, Keys.address);
|
|
||||||
if (SVDRPport)
|
if (SVDRPport)
|
||||||
SVDRP = new cSVDRP(SVDRPport);
|
SVDRP = new cSVDRP(SVDRPport);
|
||||||
}
|
}
|
||||||
|
|
||||||
cInterface::~cInterface()
|
cInterface::~cInterface()
|
||||||
{
|
{
|
||||||
delete rcIo;
|
|
||||||
delete SVDRP;
|
delete SVDRP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,15 +54,6 @@ void cInterface::Close(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int cInterface::GetCh(bool Wait, bool *Repeat, bool *Release)
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
if (!rcIo->InputAvailable())
|
|
||||||
cFile::AnyFileReady(-1, Wait ? 1000 : 0);
|
|
||||||
unsigned int Command;
|
|
||||||
return rcIo->GetCommand(&Command, Repeat, Release) ? Command : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
eKeys cInterface::GetKey(bool Wait)
|
eKeys cInterface::GetKey(bool Wait)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
@ -89,22 +67,7 @@ eKeys cInterface::GetKey(bool Wait)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eKeys Key = keyFromWait;
|
return cRemote::Get(Wait ? 1000 : 10);
|
||||||
if (Key == kNone) {
|
|
||||||
bool Repeat = false, Release = false;
|
|
||||||
Key = Keys.Get(GetCh(Wait, &Repeat, &Release));
|
|
||||||
if (Repeat)
|
|
||||||
Key = eKeys(Key | k_Repeat);
|
|
||||||
if (Release)
|
|
||||||
Key = eKeys(Key | k_Release);
|
|
||||||
}
|
|
||||||
keyFromWait = kNone;
|
|
||||||
return Key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cInterface::PutKey(eKeys Key)
|
|
||||||
{
|
|
||||||
keyFromWait = Key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||||
@ -120,7 +83,7 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (KeepChar && ISRAWKEY(Key))
|
if (KeepChar && ISRAWKEY(Key))
|
||||||
keyFromWait = Key;
|
cRemote::Put(Key);
|
||||||
interrupted = false;
|
interrupted = false;
|
||||||
return Key;
|
return Key;
|
||||||
}
|
}
|
||||||
@ -362,99 +325,102 @@ void cInterface::Help(const char *Red, const char *Green, const char *Yellow, co
|
|||||||
cStatus::MsgOsdHelpKeys(Red, Green, Yellow, Blue);
|
cStatus::MsgOsdHelpKeys(Red, Green, Yellow, Blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::QueryKeys(void)
|
void cInterface::QueryKeys(cRemote *Remote)
|
||||||
{
|
{
|
||||||
Keys.Clear();
|
cRemote::Clear();
|
||||||
Clear();
|
Clear();
|
||||||
WriteText(1, 1, tr("Learning Remote Control Keys"));
|
WriteText(1, 1, tr("Learning Remote Control Keys"));//XXX Remote->name()!!!
|
||||||
WriteText(1, 3, tr("Phase 1: Detecting RC code type"));
|
WriteText(1, 3, tr("Phase 1: Detecting RC code type"));
|
||||||
WriteText(1, 5, tr("Press any key on the RC unit"));
|
WriteText(1, 5, tr("Press any key on the RC unit"));
|
||||||
Flush();
|
Flush();
|
||||||
#ifndef REMOTE_KBD
|
if (Remote->Initialize()) {
|
||||||
unsigned char Code = '0';
|
|
||||||
unsigned short Address;
|
|
||||||
#endif
|
|
||||||
for (;;) {
|
|
||||||
#ifdef REMOTE_KBD
|
|
||||||
if (GetCh())
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
//TODO on screen display...
|
|
||||||
if (rcIo->DetectCode(&Code, &Address)) {
|
|
||||||
Keys.code = Code;
|
|
||||||
Keys.address = Address;
|
|
||||||
WriteText(1, 5, tr("RC code detected!"));
|
WriteText(1, 5, tr("RC code detected!"));
|
||||||
WriteText(1, 6, tr("Do not press any key..."));
|
WriteText(1, 6, tr("Do not press any key..."));
|
||||||
Flush();
|
Flush();
|
||||||
rcIo->Flush(3000);
|
sleep(3);
|
||||||
ClearEol(0, 5);
|
ClearEol(0, 5);
|
||||||
ClearEol(0, 6);
|
ClearEol(0, 6);
|
||||||
Flush();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
WriteText(1, 3, tr("Phase 2: Learning specific key codes"));
|
WriteText(1, 3, tr("Phase 2: Learning specific key codes"));
|
||||||
tKey *k = Keys.keys;
|
eKeys NewKey = kUp;
|
||||||
while (k->type != kNone) {
|
while (NewKey != kNone) {
|
||||||
char *Prompt;
|
char *Prompt;
|
||||||
asprintf(&Prompt, tr("Press key for '%s'"), tr(k->name));
|
asprintf(&Prompt, tr("Press key for '%s'"), tr(cKey::ToString(NewKey)));
|
||||||
WriteText(1, 5, Prompt);
|
WriteText(1, 5, Prompt);
|
||||||
free(Prompt);
|
free(Prompt);
|
||||||
for (;;) {
|
cRemote::Clear();
|
||||||
unsigned int ch = GetCh();
|
Flush();
|
||||||
if (ch != 0) {
|
for (eKeys k = NewKey; k == NewKey; ) {
|
||||||
switch (Keys.Get(ch)) {
|
char *NewCode = NULL;
|
||||||
case kUp: if (k > Keys.keys) {
|
eKeys Key = cRemote::Get(100, &NewCode);
|
||||||
k--;
|
switch (Key) {
|
||||||
break;
|
case kUp: {
|
||||||
|
NewKey = eKeys(NewKey - 1);
|
||||||
|
cKey *last = Keys.Last();
|
||||||
|
if (last && last->Key() == NewKey)
|
||||||
|
Keys.Del(last);
|
||||||
}
|
}
|
||||||
case kDown: if (k > Keys.keys + 1) {
|
break;
|
||||||
WriteText(1, 5, tr("Press 'Up' to confirm"));
|
case kDown: WriteText(1, 5, tr("Press 'Up' to confirm"));
|
||||||
WriteText(1, 6, tr("Press 'Down' to continue"));
|
WriteText(1, 6, tr("Press 'Down' to continue"));
|
||||||
ClearEol(0, 7);
|
ClearEol(0, 7);
|
||||||
ClearEol(0, 8);
|
ClearEol(0, 8);
|
||||||
|
ClearEol(0, 9);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
eKeys key = GetKey();
|
Key = cRemote::Get(100);
|
||||||
if (key == kUp) {
|
if (Key == kUp) {
|
||||||
Clear();
|
Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (key == kDown) {
|
else if (Key == kDown) {
|
||||||
ClearEol(0, 6);
|
ClearEol(0, 6);
|
||||||
|
k = kNone; // breaks the outer for() loop
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case kMenu: NewKey = eKeys(NewKey + 1);
|
||||||
|
break;
|
||||||
|
case kNone: if (NewCode) {
|
||||||
|
dsyslog("new %s code: %s = %s", Remote->Name(), NewCode, cKey::ToString(NewKey));
|
||||||
|
Keys.Add(new cKey(Remote->Name(), NewCode, NewKey));
|
||||||
|
NewKey = eKeys(NewKey + 1);
|
||||||
|
free(NewCode);
|
||||||
}
|
}
|
||||||
case kNone: k->code = ch;
|
|
||||||
k++;
|
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
if (NewKey > kUp)
|
||||||
if (k > Keys.keys)
|
|
||||||
WriteText(1, 7, tr("(press 'Up' to go back)"));
|
WriteText(1, 7, tr("(press 'Up' to go back)"));
|
||||||
else
|
else
|
||||||
ClearEol(0, 7);
|
ClearEol(0, 7);
|
||||||
if (k > Keys.keys + 1)
|
if (NewKey > kDown)
|
||||||
WriteText(1, 8, tr("(press 'Down' to end key definition)"));
|
WriteText(1, 8, tr("(press 'Down' to end key definition)"));
|
||||||
else
|
else
|
||||||
ClearEol(0, 8);
|
ClearEol(0, 8);
|
||||||
|
if (NewKey > kMenu)
|
||||||
|
WriteText(1, 9, tr("(press 'Menu' to skip this key)"));
|
||||||
|
else
|
||||||
|
ClearEol(0, 9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::LearnKeys(void)
|
void cInterface::LearnKeys(void)
|
||||||
{
|
{
|
||||||
isyslog("learning keys");
|
for (cRemote *Remote = Remotes.First(); Remote; Remote = Remotes.Next(Remote)) {
|
||||||
|
bool known = Keys.KnowsRemote(Remote->Name());
|
||||||
|
dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
|
||||||
|
if (!known) {
|
||||||
Open();
|
Open();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Clear();
|
Clear();
|
||||||
QueryKeys();
|
cRemote::SetLearning(true);
|
||||||
|
QueryKeys(Remote);
|
||||||
|
cRemote::SetLearning(false);
|
||||||
Clear();
|
Clear();
|
||||||
WriteText(1, 1, tr("Learning Remote Control Keys"));
|
WriteText(1, 1, tr("Learning Remote Control Keys"));//XXX Remote->name()!!!
|
||||||
WriteText(1, 3, tr("Phase 3: Saving key codes"));
|
WriteText(1, 3, tr("Phase 3: Saving key codes"));
|
||||||
WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
|
WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -471,20 +437,6 @@ void cInterface::LearnKeys(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void cInterface::DisplayChannelNumber(int Number)
|
|
||||||
{
|
|
||||||
rcIo->Number(Number);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cInterface::DisplayRecording(int Index, bool On)
|
|
||||||
{
|
|
||||||
rcIo->SetPoints(1 << Index, On);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cInterface::Recording(void)
|
|
||||||
{
|
|
||||||
// This is located here because the Interface has to do with the "PrimaryDevice" anyway
|
|
||||||
return cDevice::PrimaryDevice()->Receiving();
|
|
||||||
}
|
}
|
||||||
|
11
interface.h
11
interface.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: interface.h 1.27 2002/06/22 14:39:48 kls Exp $
|
* $Id: interface.h 1.28 2002/09/29 10:46:50 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __INTERFACE_H
|
#ifndef __INTERFACE_H
|
||||||
@ -22,12 +22,9 @@ private:
|
|||||||
int width, height;
|
int width, height;
|
||||||
int open;
|
int open;
|
||||||
int cols[MaxCols];
|
int cols[MaxCols];
|
||||||
eKeys keyFromWait;
|
|
||||||
bool interrupted;
|
bool interrupted;
|
||||||
cSVDRP *SVDRP;
|
cSVDRP *SVDRP;
|
||||||
cRcIoBase *rcIo;
|
void QueryKeys(cRemote *Remote);
|
||||||
unsigned int GetCh(bool Wait = true, bool *Repeat = NULL, bool *Release = NULL);
|
|
||||||
void QueryKeys(void);
|
|
||||||
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
|
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
|
||||||
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
||||||
public:
|
public:
|
||||||
@ -40,7 +37,6 @@ public:
|
|||||||
int Width(void) { return width; }
|
int Width(void) { return width; }
|
||||||
int Height(void) { return height; }
|
int Height(void) { return height; }
|
||||||
eKeys GetKey(bool Wait = true);
|
eKeys GetKey(bool Wait = true);
|
||||||
void PutKey(eKeys Key);
|
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
||||||
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
|
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
|
||||||
@ -59,9 +55,6 @@ public:
|
|||||||
bool Confirm(const char *s, int Seconds = 10, bool WaitForTimeout = false);
|
bool Confirm(const char *s, int Seconds = 10, bool WaitForTimeout = false);
|
||||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||||
void LearnKeys(void);
|
void LearnKeys(void);
|
||||||
void DisplayChannelNumber(int Number);
|
|
||||||
void DisplayRecording(int Index, bool On);
|
|
||||||
bool Recording(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cInterface *Interface;
|
extern cInterface *Interface;
|
||||||
|
27
keys-pc.conf
27
keys-pc.conf
@ -1,27 +0,0 @@
|
|||||||
Code 0
|
|
||||||
Address 0000
|
|
||||||
Up 00000103
|
|
||||||
Down 00000102
|
|
||||||
Menu 00000106
|
|
||||||
Ok 0000000D
|
|
||||||
Back 00000168
|
|
||||||
Left 00000104
|
|
||||||
Right 00000105
|
|
||||||
Red 00000109
|
|
||||||
Green 0000010A
|
|
||||||
Yellow 0000010B
|
|
||||||
Blue 0000010C
|
|
||||||
0 00000030
|
|
||||||
1 00000031
|
|
||||||
2 00000032
|
|
||||||
3 00000033
|
|
||||||
4 00000034
|
|
||||||
5 00000035
|
|
||||||
6 00000036
|
|
||||||
7 00000037
|
|
||||||
8 00000038
|
|
||||||
9 00000039
|
|
||||||
Power 00000050
|
|
||||||
Volume+ 0000002B
|
|
||||||
Volume- 0000002D
|
|
||||||
Mute 0000006D
|
|
154
keys.c
Normal file
154
keys.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* keys.c: Remote control Key handling
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: keys.c 1.1 2002/09/29 09:56:51 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
|
static tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
|
||||||
|
{ kUp, "Up" },
|
||||||
|
{ kDown, "Down" },
|
||||||
|
{ kMenu, "Menu" },
|
||||||
|
{ kOk, "Ok" },
|
||||||
|
{ kBack, "Back" },
|
||||||
|
{ kLeft, "Left" },
|
||||||
|
{ kRight, "Right" },
|
||||||
|
{ kRed, "Red" },
|
||||||
|
{ kGreen, "Green" },
|
||||||
|
{ kYellow, "Yellow" },
|
||||||
|
{ kBlue, "Blue" },
|
||||||
|
{ k0, "0" },
|
||||||
|
{ k1, "1" },
|
||||||
|
{ k2, "2" },
|
||||||
|
{ k3, "3" },
|
||||||
|
{ k4, "4" },
|
||||||
|
{ k5, "5" },
|
||||||
|
{ k6, "6" },
|
||||||
|
{ k7, "7" },
|
||||||
|
{ k8, "8" },
|
||||||
|
{ k9, "9" },
|
||||||
|
{ kPower, "Power" },
|
||||||
|
{ kVolUp, "Volume+" },
|
||||||
|
{ kVolDn, "Volume-" },
|
||||||
|
{ kMute, "Mute" },
|
||||||
|
{ kNone, "" },
|
||||||
|
{ k_Setup, "_Setup" },
|
||||||
|
{ kNone, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
// -- cKey -------------------------------------------------------------------
|
||||||
|
|
||||||
|
cKey::cKey(void)
|
||||||
|
{
|
||||||
|
remote = code = NULL;
|
||||||
|
key = kNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
cKey::cKey(const char *Remote, const char *Code, eKeys Key)
|
||||||
|
{
|
||||||
|
remote = strdup(Remote);
|
||||||
|
code = strdup(Code);
|
||||||
|
key = Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
cKey::~cKey()
|
||||||
|
{
|
||||||
|
free(remote);
|
||||||
|
free(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cKey::Parse(char *s)
|
||||||
|
{
|
||||||
|
char *p = strchr(s, '.');
|
||||||
|
if (p) {
|
||||||
|
*p++ = 0;
|
||||||
|
remote = strdup(s);
|
||||||
|
char *q = strpbrk(p, " \t");
|
||||||
|
if (q) {
|
||||||
|
*q++ = 0;
|
||||||
|
key = FromString(p);
|
||||||
|
if (key != kNone) {
|
||||||
|
q = skipspace(q);
|
||||||
|
if (*q) {
|
||||||
|
code = strdup(q);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cKey::Save(FILE *f)
|
||||||
|
{
|
||||||
|
return fprintf(f, "%s.%-10s %s\n", remote, ToString(key), code) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
eKeys cKey::FromString(const char *Name)
|
||||||
|
{
|
||||||
|
if (Name) {
|
||||||
|
for (tKey *k = keyTable; k->name; k++) {
|
||||||
|
if (strcasecmp(k->name, Name) == 0)
|
||||||
|
return k->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return kNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cKey::ToString(eKeys Key)
|
||||||
|
{
|
||||||
|
for (tKey *k = keyTable; k->name; k++) {
|
||||||
|
if (k->type == Key)
|
||||||
|
return k->name;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- cKeys ------------------------------------------------------------------
|
||||||
|
|
||||||
|
cKeys Keys;
|
||||||
|
|
||||||
|
bool cKeys::KnowsRemote(const char *Remote)
|
||||||
|
{
|
||||||
|
if (Remote) {
|
||||||
|
for (cKey *k = First(); k; k = Next(k)) {
|
||||||
|
if (strcmp(Remote, k->Remote()) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eKeys cKeys::Get(const char *Remote, const char *Code)
|
||||||
|
{
|
||||||
|
if (Remote && Code) {
|
||||||
|
for (cKey *k = First(); k; k = Next(k)) {
|
||||||
|
if (strcmp(Remote, k->Remote()) == 0 && strcmp(Code, k->Code()) == 0)
|
||||||
|
return k->Key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return kNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cKeys::GetSetup(const char *Remote)
|
||||||
|
{
|
||||||
|
if (Remote) {
|
||||||
|
for (cKey *k = First(); k; k = Next(k)) {
|
||||||
|
if (strcmp(Remote, k->Remote()) == 0 && k->Key() == k_Setup)
|
||||||
|
return k->Code();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cKeys::PutSetup(const char *Remote, const char *Setup)
|
||||||
|
{
|
||||||
|
if (!GetSetup(Remote))
|
||||||
|
Add(new cKey(Remote, Setup, k_Setup));
|
||||||
|
else
|
||||||
|
esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote);
|
||||||
|
}
|
87
keys.h
Normal file
87
keys.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* keys.h: Remote control Key handling
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: keys.h 1.1 2002/09/29 09:55:52 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KEYS_H
|
||||||
|
#define __KEYS_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
enum eKeys { // "Up" and "Down" must be the first two keys!
|
||||||
|
kUp,
|
||||||
|
kDown,
|
||||||
|
kMenu,
|
||||||
|
kOk,
|
||||||
|
kBack,
|
||||||
|
kLeft,
|
||||||
|
kRight,
|
||||||
|
kRed,
|
||||||
|
kGreen,
|
||||||
|
kYellow,
|
||||||
|
kBlue,
|
||||||
|
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
|
||||||
|
kPower,
|
||||||
|
kVolUp,
|
||||||
|
kVolDn,
|
||||||
|
kMute,
|
||||||
|
kNone,
|
||||||
|
k_Setup,
|
||||||
|
// The following flags are OR'd with the above codes:
|
||||||
|
k_Repeat = 0x8000,
|
||||||
|
k_Release = 0x4000,
|
||||||
|
k_Flags = k_Repeat | k_Release,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is in preparation for having more key codes:
|
||||||
|
#define kMarkToggle k0
|
||||||
|
#define kMarkMoveBack k4
|
||||||
|
#define kMarkMoveForward k6
|
||||||
|
#define kMarkJumpBack k7
|
||||||
|
#define kMarkJumpForward k9
|
||||||
|
#define kEditCut k2
|
||||||
|
#define kEditTest k8
|
||||||
|
|
||||||
|
#define RAWKEY(k) (eKeys((k) & ~k_Flags))
|
||||||
|
#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
|
||||||
|
#define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
|
||||||
|
|
||||||
|
struct tKey {
|
||||||
|
eKeys type;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class cKey : public cListObject {
|
||||||
|
private:
|
||||||
|
char *remote;
|
||||||
|
char *code;
|
||||||
|
eKeys key;
|
||||||
|
public:
|
||||||
|
cKey(void);
|
||||||
|
cKey(const char *Remote, const char *Code, eKeys Key);
|
||||||
|
~cKey();
|
||||||
|
const char *Remote(void) { return remote; }
|
||||||
|
const char *Code(void) { return code; }
|
||||||
|
eKeys Key(void) { return key; }
|
||||||
|
bool Parse(char *s);
|
||||||
|
bool Save(FILE *f);
|
||||||
|
static eKeys FromString(const char *Name);
|
||||||
|
static const char *ToString(eKeys Key);
|
||||||
|
};
|
||||||
|
|
||||||
|
class cKeys : public cConfig<cKey> {
|
||||||
|
public:
|
||||||
|
bool KnowsRemote(const char *Remote);
|
||||||
|
eKeys Get(const char *Remote, const char *Code);
|
||||||
|
const char *GetSetup(const char *Remote);
|
||||||
|
void PutSetup(const char *Remote, const char *Setup);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern cKeys Keys;
|
||||||
|
|
||||||
|
#endif //__KEYS_H
|
84
lirc.c
Normal file
84
lirc.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* lirc.c: LIRC remote control
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
|
||||||
|
*
|
||||||
|
* $Id: lirc.c 1.1 2002/09/29 13:16:33 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lirc.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#define REPEATLIMIT 20 // ms
|
||||||
|
#define REPEATDELAY 350 // ms
|
||||||
|
|
||||||
|
cLircRemote::cLircRemote(char *DeviceName)
|
||||||
|
:cRemote("LIRC")
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strcpy(addr.sun_path, DeviceName);
|
||||||
|
if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
|
||||||
|
if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
|
||||||
|
Start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_ERROR_STR(DeviceName);
|
||||||
|
close(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LOG_ERROR_STR(DeviceName);
|
||||||
|
f = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cLircRemote::~cLircRemote()
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cLircRemote::Action(void)
|
||||||
|
{
|
||||||
|
dsyslog("LIRC remote control thread started (pid=%d)", getpid());
|
||||||
|
|
||||||
|
int FirstTime = 0;
|
||||||
|
int LastTime = 0;
|
||||||
|
char buf[LIRC_BUFFER_SIZE];
|
||||||
|
char LastKeyName[LIRC_KEY_BUF] = "";
|
||||||
|
bool repeat = false;
|
||||||
|
|
||||||
|
for (; f >= 0;) {
|
||||||
|
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
if (cFile::FileReady(f, REPEATLIMIT) && safe_read(f, buf, sizeof(buf)) > 21) {
|
||||||
|
int count;
|
||||||
|
char KeyName[LIRC_KEY_BUF];
|
||||||
|
sscanf(buf, "%*x %x %29s", &count, KeyName); // '29' in '%29s' is LIRC_KEY_BUF-1!
|
||||||
|
int Now = time_ms();
|
||||||
|
if (count == 0) {
|
||||||
|
strcpy(LastKeyName, KeyName);
|
||||||
|
repeat = false;
|
||||||
|
FirstTime = Now;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Now - FirstTime < REPEATDELAY)
|
||||||
|
continue; // repeat function kicks in after a short delay
|
||||||
|
repeat = true;
|
||||||
|
}
|
||||||
|
LastTime = Now;
|
||||||
|
Put(KeyName, repeat);
|
||||||
|
}
|
||||||
|
else if (repeat) { // the last one was a repeat, so let's generate a release
|
||||||
|
if (time_ms() - LastTime > REPEATDELAY) {
|
||||||
|
Put(LastKeyName, false, true);
|
||||||
|
repeat = false;
|
||||||
|
*LastKeyName = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
lirc.h
Normal file
26
lirc.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* lirc.h: LIRC remote control
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: lirc.h 1.1 2002/09/28 14:11:04 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIRC_H
|
||||||
|
#define __LIRC_H
|
||||||
|
|
||||||
|
#include "remote.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
class cLircRemote : public cRemote, private cThread {
|
||||||
|
private:
|
||||||
|
enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
|
||||||
|
int f;
|
||||||
|
virtual void Action(void);
|
||||||
|
public:
|
||||||
|
cLircRemote(char *DeviceName);
|
||||||
|
virtual ~cLircRemote();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__LIRC_H
|
20
menu.c
20
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.c 1.208 2002/09/06 14:07:58 kls Exp $
|
* $Id: menu.c 1.209 2002/09/29 12:50:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include "menuitems.h"
|
#include "menuitems.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
|
#include "remote.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "videodir.h"
|
#include "videodir.h"
|
||||||
|
|
||||||
@ -2121,7 +2122,7 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
|
|||||||
withInfo = !Switched || Setup.ShowInfoOnChSwitch;
|
withInfo = !Switched || Setup.ShowInfoOnChSwitch;
|
||||||
int EpgLines = withInfo ? 5 : 1;
|
int EpgLines = withInfo ? 5 : 1;
|
||||||
lines = 0;
|
lines = 0;
|
||||||
oldNumber = number = 0;
|
number = 0;
|
||||||
cChannel *channel = Channels.GetByNumber(Number);
|
cChannel *channel = Channels.GetByNumber(Number);
|
||||||
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
@ -2135,7 +2136,6 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
|
|||||||
:cOsdObject(true)
|
:cOsdObject(true)
|
||||||
{
|
{
|
||||||
group = -1;
|
group = -1;
|
||||||
oldNumber = cDevice::CurrentChannel();
|
|
||||||
number = 0;
|
number = 0;
|
||||||
lastTime = time_ms();
|
lastTime = time_ms();
|
||||||
int EpgLines = Setup.ShowInfoOnChSwitch ? 5 : 1;
|
int EpgLines = Setup.ShowInfoOnChSwitch ? 5 : 1;
|
||||||
@ -2145,15 +2145,11 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
|
|||||||
|
|
||||||
cDisplayChannel::~cDisplayChannel()
|
cDisplayChannel::~cDisplayChannel()
|
||||||
{
|
{
|
||||||
if (number < 0)
|
|
||||||
Interface->DisplayChannelNumber(oldNumber);
|
|
||||||
Interface->Close();
|
Interface->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
|
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
|
||||||
{
|
{
|
||||||
if (Channel && Channel->number > 0)
|
|
||||||
Interface->DisplayChannelNumber(Channel->number);
|
|
||||||
int BufSize = Width() + 1;
|
int BufSize = Width() + 1;
|
||||||
char buffer[BufSize];
|
char buffer[BufSize];
|
||||||
if (Channel && Channel->number > 0)
|
if (Channel && Channel->number > 0)
|
||||||
@ -2231,7 +2227,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
|||||||
case k0:
|
case k0:
|
||||||
if (number == 0) {
|
if (number == 0) {
|
||||||
// keep the "Toggle channels" function working
|
// keep the "Toggle channels" function working
|
||||||
Interface->PutKey(Key);
|
cRemote::Put(Key);
|
||||||
return osEnd;
|
return osEnd;
|
||||||
}
|
}
|
||||||
case k1 ... k9:
|
case k1 ... k9:
|
||||||
@ -2290,7 +2286,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
|||||||
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->number);
|
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->number);
|
||||||
return osEnd;
|
return osEnd;
|
||||||
default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
|
default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
|
||||||
Interface->PutKey(Key);
|
cRemote::Put(Key);
|
||||||
return osEnd;
|
return osEnd;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2397,7 +2393,7 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
|
|||||||
break;
|
break;
|
||||||
case kNone: break;
|
case kNone: break;
|
||||||
default: if ((Key & k_Release) == 0) {
|
default: if ((Key & k_Release) == 0) {
|
||||||
Interface->PutKey(Key);
|
cRemote::Put(Key);
|
||||||
return osEnd;
|
return osEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2441,7 +2437,6 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
|
|||||||
if (device->AttachReceiver(recorder)) {
|
if (device->AttachReceiver(recorder)) {
|
||||||
Recording.WriteSummary();
|
Recording.WriteSummary();
|
||||||
cStatus::MsgRecording(device, Recording.Name());
|
cStatus::MsgRecording(device, Recording.Name());
|
||||||
Interface->DisplayRecording(device->CardIndex(), true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DELETENULL(recorder);
|
DELETENULL(recorder);
|
||||||
@ -2487,7 +2482,6 @@ bool cRecordControl::GetEventInfo(void)
|
|||||||
void cRecordControl::Stop(bool KeepInstant)
|
void cRecordControl::Stop(bool KeepInstant)
|
||||||
{
|
{
|
||||||
if (timer) {
|
if (timer) {
|
||||||
cStatus::MsgRecording(device, NULL);
|
|
||||||
DELETENULL(recorder);
|
DELETENULL(recorder);
|
||||||
timer->SetRecording(false);
|
timer->SetRecording(false);
|
||||||
if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && timer->StopTime() <= time(NULL))) {
|
if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && timer->StopTime() <= time(NULL))) {
|
||||||
@ -2496,7 +2490,7 @@ void cRecordControl::Stop(bool KeepInstant)
|
|||||||
Timers.Save();
|
Timers.Save();
|
||||||
}
|
}
|
||||||
timer = NULL;
|
timer = NULL;
|
||||||
Interface->DisplayRecording(device->CardIndex(), false);
|
cStatus::MsgRecording(device, NULL);
|
||||||
cRecordingUserCommand::InvokeCommand(RUC_AFTERRECORDING, fileName);
|
cRecordingUserCommand::InvokeCommand(RUC_AFTERRECORDING, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
menu.h
4
menu.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.h 1.45 2002/06/22 14:49:15 kls Exp $
|
* $Id: menu.h 1.46 2002/09/29 08:16:31 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MENU_H
|
#ifndef __MENU_H
|
||||||
@ -32,7 +32,7 @@ private:
|
|||||||
bool withInfo;
|
bool withInfo;
|
||||||
int lines;
|
int lines;
|
||||||
int lastTime;
|
int lastTime;
|
||||||
int oldNumber, number;
|
int number;
|
||||||
void DisplayChannel(const cChannel *Channel);
|
void DisplayChannel(const cChannel *Channel);
|
||||||
void DisplayInfo(void);
|
void DisplayInfo(void);
|
||||||
public:
|
public:
|
||||||
|
312
rcu.c
Normal file
312
rcu.c
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* rcu.c: RCU remote control
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: rcu.c 1.1 2002/09/29 13:16:44 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rcu.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
#define REPEATLIMIT 20 // ms
|
||||||
|
#define REPEATDELAY 350 // ms
|
||||||
|
|
||||||
|
cRcuRemote::cRcuRemote(char *DeviceName)
|
||||||
|
:cRemote("RCU")
|
||||||
|
{
|
||||||
|
dp = 0;
|
||||||
|
mode = modeB;
|
||||||
|
code = 0;
|
||||||
|
lastNumber = 0;
|
||||||
|
receivedCommand = false;
|
||||||
|
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
|
||||||
|
struct termios t;
|
||||||
|
if (tcgetattr(f, &t) == 0) {
|
||||||
|
cfsetspeed(&t, B9600);
|
||||||
|
cfmakeraw(&t);
|
||||||
|
if (tcsetattr(f, TCSAFLUSH, &t) == 0) {
|
||||||
|
Number(0);//XXX 8888???
|
||||||
|
const char *Setup = GetSetup();
|
||||||
|
if (Setup) {
|
||||||
|
code = *Setup;
|
||||||
|
SetCode(code);
|
||||||
|
isyslog("connecting to %s remote control using code %c", Name(), code);
|
||||||
|
}
|
||||||
|
Start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_ERROR_STR(DeviceName);
|
||||||
|
close(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LOG_ERROR_STR(DeviceName);
|
||||||
|
f = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cRcuRemote::~cRcuRemote()
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::Initialize(void)
|
||||||
|
{
|
||||||
|
if (f >= 0) {
|
||||||
|
unsigned char Code = '0';
|
||||||
|
isyslog("trying codes for %s remote control...", Name());
|
||||||
|
for (;;) {
|
||||||
|
if (DetectCode(&Code)) {
|
||||||
|
code = Code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isyslog("established connection to %s remote control using code %c", Name(), code);
|
||||||
|
char buffer[16];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%c", code);
|
||||||
|
PutSetup(buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRcuRemote::Action(void)
|
||||||
|
{
|
||||||
|
#pragma pack(1)
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned short address;
|
||||||
|
unsigned int command;
|
||||||
|
} data;
|
||||||
|
unsigned char raw[6];
|
||||||
|
} buffer;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
dsyslog("RCU remote control thread started (pid=%d)", getpid());
|
||||||
|
|
||||||
|
time_t LastCodeRefresh = 0;
|
||||||
|
int FirstTime = 0;
|
||||||
|
uint64 LastCommand = 0;
|
||||||
|
bool repeat = false;
|
||||||
|
|
||||||
|
//XXX
|
||||||
|
for (; f >= 0;) {
|
||||||
|
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
if (ReceiveByte(REPEATLIMIT) == 'X') {
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
int b = ReceiveByte();
|
||||||
|
if (b >= 0) {
|
||||||
|
buffer.raw[i] = b;
|
||||||
|
if (i == 5) {
|
||||||
|
unsigned short Address = ntohs(buffer.data.address); // the PIC sends bytes in "network order"
|
||||||
|
uint64 Command = ntohl(buffer.data.command);
|
||||||
|
if (code == 'B' && Address == 0x0000 && Command == 0x00004000)
|
||||||
|
// Well, well, if it isn't the "d-box"...
|
||||||
|
// This remote control sends the above command before and after
|
||||||
|
// each keypress - let's just drop this:
|
||||||
|
break;
|
||||||
|
int Now = time_ms();
|
||||||
|
Command |= uint64(Address) << 32;
|
||||||
|
if (Command != LastCommand) {
|
||||||
|
LastCommand = Command;
|
||||||
|
repeat = false;
|
||||||
|
FirstTime = Now;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Now - FirstTime < REPEATDELAY)
|
||||||
|
break; // repeat function kicks in after a short delay
|
||||||
|
repeat = true;
|
||||||
|
}
|
||||||
|
Put(Command, repeat);
|
||||||
|
receivedCommand = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (repeat) { // the last one was a repeat, so let's generate a release
|
||||||
|
Put(LastCommand, false, true);
|
||||||
|
repeat = false;
|
||||||
|
LastCommand = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LastCommand = 0;
|
||||||
|
if (code && time(NULL) - LastCodeRefresh > 60) {
|
||||||
|
SendCommand(code); // in case the PIC listens to the wrong code
|
||||||
|
LastCodeRefresh = time(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cRcuRemote::ReceiveByte(int TimeoutMs)
|
||||||
|
{
|
||||||
|
// Returns the byte if one was received within a timeout, -1 otherwise
|
||||||
|
if (cFile::FileReady(f, TimeoutMs)) {
|
||||||
|
unsigned char b;
|
||||||
|
if (safe_read(f, &b, 1) == 1)
|
||||||
|
return b;
|
||||||
|
else
|
||||||
|
LOG_ERROR;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::SendByteHandshake(unsigned char c)
|
||||||
|
{
|
||||||
|
if (f >= 0) {
|
||||||
|
int w = write(f, &c, 1);
|
||||||
|
if (w == 1) {
|
||||||
|
for (int reply = ReceiveByte(REPEATLIMIT); reply >= 0;) {
|
||||||
|
if (reply == c)
|
||||||
|
return true;
|
||||||
|
else if (reply == 'X') {
|
||||||
|
// skip any incoming RC code - it will come again
|
||||||
|
for (int i = 6; i--;) {
|
||||||
|
if (ReceiveByte() < 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_ERROR;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::SendByte(unsigned char c)
|
||||||
|
{
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
for (int retry = 5; retry--;) {
|
||||||
|
if (SendByteHandshake(c))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::SetCode(unsigned char Code)
|
||||||
|
{
|
||||||
|
code = Code;
|
||||||
|
return SendCommand(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::SetMode(unsigned char Mode)
|
||||||
|
{
|
||||||
|
mode = Mode;
|
||||||
|
return SendCommand(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::SendCommand(unsigned char Cmd)
|
||||||
|
{
|
||||||
|
return SendByte(Cmd | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::Digit(int n, int v)
|
||||||
|
{
|
||||||
|
return SendByte(((n & 0x03) << 5) | (v & 0x0F) | (((dp >> n) & 0x01) << 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::Number(int n, bool Hex)
|
||||||
|
{
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
if (!Hex) {
|
||||||
|
char buf[8];
|
||||||
|
sprintf(buf, "%4d", n & 0xFFFF);
|
||||||
|
n = 0;
|
||||||
|
for (char *d = buf; *d; d++) {
|
||||||
|
if (*d == ' ')
|
||||||
|
*d = 0xF;
|
||||||
|
n = (n << 4) | ((*d - '0') & 0x0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastNumber = n;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (!Digit(i, n))
|
||||||
|
return false;
|
||||||
|
n >>= 4;
|
||||||
|
}
|
||||||
|
return SendCommand(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::String(char *s)
|
||||||
|
{
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP ";
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for (int i = 0; *s && i < 4; s++, i++) {
|
||||||
|
n <<= 4;
|
||||||
|
for (const char *c = chars; *c; c++) {
|
||||||
|
if (*c == *s) {
|
||||||
|
n |= c - chars;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Number(n, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRcuRemote::SetPoints(unsigned char Dp, bool On)
|
||||||
|
{
|
||||||
|
if (On)
|
||||||
|
dp |= Dp;
|
||||||
|
else
|
||||||
|
dp &= ~Dp;
|
||||||
|
Number(lastNumber, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRcuRemote::DetectCode(unsigned char *Code)
|
||||||
|
{
|
||||||
|
// Caller should initialize 'Code' to 0 and call DetectCode()
|
||||||
|
// until it returns true. Whenever DetectCode() returns false
|
||||||
|
// and 'Code' is not 0, the caller can use 'Code' to display
|
||||||
|
// a message like "Trying code '%c'". If false is returned and
|
||||||
|
// 'Code' is 0, all possible codes have been tried and the caller
|
||||||
|
// can either stop calling DetectCode() (and give some error
|
||||||
|
// message), or start all over again.
|
||||||
|
if (*Code < 'A' || *Code > 'D') {
|
||||||
|
*Code = 'A';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*Code <= 'D') {
|
||||||
|
SetMode(modeH);
|
||||||
|
char buf[5];
|
||||||
|
sprintf(buf, "C0D%c", *Code);
|
||||||
|
String(buf);
|
||||||
|
SetCode(*Code);
|
||||||
|
delay_ms(2 * REPEATDELAY);
|
||||||
|
if (receivedCommand) {
|
||||||
|
SetMode(modeB);
|
||||||
|
String("----");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (*Code < 'D') {
|
||||||
|
(*Code)++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*Code = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber)
|
||||||
|
{
|
||||||
|
if (ChannelNumber && Device->IsPrimaryDevice())
|
||||||
|
Number(ChannelNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRcuRemote::Recording(const cDevice *Device, const char *Name)
|
||||||
|
{
|
||||||
|
SetPoints(1 << Device->CardIndex(), Device->Receiving()); //XXX CardNumber()!!!
|
||||||
|
}
|
44
rcu.h
Normal file
44
rcu.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* rcu.h: RCU remote control
|
||||||
|
*
|
||||||
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: rcu.h 1.1 2002/09/29 08:56:15 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RCU_H
|
||||||
|
#define __RCU_H
|
||||||
|
|
||||||
|
#include "remote.h"
|
||||||
|
#include "status.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
class cRcuRemote : public cRemote, private cThread, private cStatus {
|
||||||
|
private:
|
||||||
|
enum { modeH = 'h', modeB = 'b', modeS = 's' };
|
||||||
|
int f;
|
||||||
|
unsigned char dp, code, mode;
|
||||||
|
int lastNumber;
|
||||||
|
bool receivedCommand;
|
||||||
|
bool SendCommand(unsigned char Cmd);
|
||||||
|
int ReceiveByte(int TimeoutMs = 0);
|
||||||
|
bool SendByteHandshake(unsigned char c);
|
||||||
|
bool SendByte(unsigned char c);
|
||||||
|
bool Digit(int n, int v);
|
||||||
|
bool SetCode(unsigned char Code);
|
||||||
|
bool SetMode(unsigned char Mode);
|
||||||
|
bool Number(int n, bool Hex = false);
|
||||||
|
void SetPoints(unsigned char Dp, bool On);
|
||||||
|
bool String(char *s);
|
||||||
|
bool DetectCode(unsigned char *Code);
|
||||||
|
virtual void Action(void);
|
||||||
|
virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
|
||||||
|
virtual void Recording(const cDevice *Device, const char *Name);
|
||||||
|
public:
|
||||||
|
cRcuRemote(char *DeviceName);
|
||||||
|
virtual ~cRcuRemote();
|
||||||
|
virtual bool Initialize(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__RCU_H
|
579
remote.c
579
remote.c
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* remote.c: Interface to the Remote Control Unit
|
* remote.c: General Remote Control handling
|
||||||
*
|
*
|
||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
|
* $Id: remote.c 1.28 2002/09/29 12:51:26 kls Exp $
|
||||||
*
|
|
||||||
* $Id: remote.c 1.27 2002/05/18 12:55:39 kls Exp $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
@ -18,487 +16,150 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if defined REMOTE_LIRC
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined REMOTE_KBD
|
#if defined REMOTE_KBD
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
// --- cRcIoBase -------------------------------------------------------------
|
// --- cRemote ---------------------------------------------------------------
|
||||||
|
|
||||||
cRcIoBase::cRcIoBase(void)
|
eKeys cRemote::keys[MaxKeys];
|
||||||
|
int cRemote::in = 0;
|
||||||
|
int cRemote::out = 0;
|
||||||
|
bool cRemote::learning = false;
|
||||||
|
char *cRemote::unknownCode = NULL;
|
||||||
|
cMutex cRemote::mutex;
|
||||||
|
cCondVar cRemote::keyPressed;
|
||||||
|
|
||||||
|
cRemote::cRemote(const char *Name)
|
||||||
{
|
{
|
||||||
t = 0;
|
if (Name)
|
||||||
|
name = strdup(Name);
|
||||||
|
Remotes.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
cRcIoBase::~cRcIoBase()
|
cRemote::~cRemote()
|
||||||
{
|
{
|
||||||
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cRcIoKBD --------------------------------------------------------------
|
const char *cRemote::GetSetup(void)
|
||||||
|
{
|
||||||
|
return Keys.GetSetup(Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRemote::PutSetup(const char *Setup)
|
||||||
|
{
|
||||||
|
Keys.PutSetup(Name(), Setup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRemote::Clear(void)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
in = out = 0;
|
||||||
|
if (learning) {
|
||||||
|
free(unknownCode);
|
||||||
|
unknownCode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRemote::Put(eKeys Key)
|
||||||
|
{
|
||||||
|
if (Key != kNone) {
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
if ((Key & k_Release) != 0)
|
||||||
|
Clear();
|
||||||
|
int d = out - in;
|
||||||
|
if (d <= 0)
|
||||||
|
d = MaxKeys + d;
|
||||||
|
if (d - 1 > 0) {
|
||||||
|
keys[in] = Key;
|
||||||
|
if (++in >= MaxKeys)
|
||||||
|
in = 0;
|
||||||
|
keyPressed.Broadcast();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true; // only a real key shall report an overflow!
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRemote::Put(uint64 Code, bool Repeat, bool Release)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%016LX", Code);
|
||||||
|
return Put(buffer, Repeat, Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRemote::Put(const char *Code, bool Repeat, bool Release)
|
||||||
|
{
|
||||||
|
eKeys Key = Keys.Get(Name(), Code);
|
||||||
|
if (Key != kNone) {
|
||||||
|
if (Repeat)
|
||||||
|
Key = eKeys(Key | k_Repeat);
|
||||||
|
if (Release)
|
||||||
|
Key = eKeys(Key | k_Release);
|
||||||
|
return Put(Key);
|
||||||
|
}
|
||||||
|
if (learning) {
|
||||||
|
free(unknownCode);
|
||||||
|
unknownCode = strdup(Code);
|
||||||
|
keyPressed.Broadcast();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
eKeys cRemote::Get(int WaitMs, char **UnknownCode)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
if (in != out) {
|
||||||
|
eKeys k = keys[out];
|
||||||
|
if (++out >= MaxKeys)
|
||||||
|
out = 0;
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
else if (!WaitMs || !keyPressed.TimedWait(mutex, WaitMs)) {
|
||||||
|
if (learning && UnknownCode) {
|
||||||
|
*UnknownCode = unknownCode;
|
||||||
|
unknownCode = NULL;
|
||||||
|
}
|
||||||
|
return kNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cRemotes --------------------------------------------------------------
|
||||||
|
|
||||||
|
cRemotes Remotes;
|
||||||
|
|
||||||
|
// --- cKbdRemote ------------------------------------------------------------
|
||||||
|
|
||||||
#if defined REMOTE_KBD
|
#if defined REMOTE_KBD
|
||||||
|
|
||||||
cRcIoKBD::cRcIoKBD(void)
|
cKbdRemote::cKbdRemote(void)
|
||||||
|
:cRemote("KBD")
|
||||||
{
|
{
|
||||||
f.Open(0); // stdin
|
|
||||||
}
|
|
||||||
|
|
||||||
cRcIoKBD::~cRcIoKBD()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void cRcIoKBD::Flush(int WaitMs)
|
|
||||||
{
|
|
||||||
int t0 = time_ms();
|
|
||||||
|
|
||||||
timeout(10);
|
|
||||||
for (;;) {
|
|
||||||
while (getch() > 0)
|
|
||||||
t0 = time_ms();
|
|
||||||
if (time_ms() - t0 >= WaitMs)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoKBD::InputAvailable(void)
|
|
||||||
{
|
|
||||||
return f.Ready(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoKBD::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
|
|
||||||
{
|
|
||||||
if (Command) {
|
|
||||||
*Command = getch();
|
|
||||||
return int(*Command) > 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cRcIoRCU --------------------------------------------------------------
|
|
||||||
|
|
||||||
#elif defined REMOTE_RCU
|
|
||||||
|
|
||||||
#define REPEATLIMIT 20 // ms
|
|
||||||
#define REPEATDELAY 350 // ms
|
|
||||||
|
|
||||||
cRcIoRCU::cRcIoRCU(char *DeviceName)
|
|
||||||
{
|
|
||||||
dp = 0;
|
|
||||||
mode = modeB;
|
|
||||||
code = 0;
|
|
||||||
address = 0xFFFF;
|
|
||||||
receivedAddress = 0;
|
|
||||||
receivedCommand = 0;
|
|
||||||
receivedData = receivedRepeat = receivedRelease = false;
|
|
||||||
lastNumber = 0;
|
|
||||||
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
|
|
||||||
struct termios t;
|
|
||||||
if (tcgetattr(f, &t) == 0) {
|
|
||||||
cfsetspeed(&t, B9600);
|
|
||||||
cfmakeraw(&t);
|
|
||||||
if (tcsetattr(f, TCSAFLUSH, &t) == 0) {
|
|
||||||
Start();
|
Start();
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_ERROR_STR(DeviceName);
|
|
||||||
close(f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_ERROR_STR(DeviceName);
|
|
||||||
f = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cRcIoRCU::~cRcIoRCU()
|
cKbdRemote::~cKbdRemote()
|
||||||
{
|
{
|
||||||
Cancel();
|
Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cRcIoRCU::Action(void)
|
void cKbdRemote::Action(void)
|
||||||
{
|
{
|
||||||
#pragma pack(1)
|
dsyslog("KBD remote control thread started (pid=%d)", getpid());
|
||||||
union {
|
cPoller Poller(STDIN_FILENO);
|
||||||
struct {
|
for (;;) {//XXX
|
||||||
unsigned short address;
|
int Command = getch();
|
||||||
unsigned int command;
|
if (Command != EOF)
|
||||||
} data;
|
Put(Command);
|
||||||
unsigned char raw[6];
|
Poller.Poll(100);
|
||||||
} buffer;
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
dsyslog("RCU remote control thread started (pid=%d)", getpid());
|
|
||||||
|
|
||||||
int FirstTime = 0;
|
|
||||||
unsigned int LastCommand = 0;
|
|
||||||
|
|
||||||
for (; f >= 0;) {
|
|
||||||
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
if (ReceiveByte(REPEATLIMIT) == 'X') {
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
int b = ReceiveByte();
|
|
||||||
if (b >= 0) {
|
|
||||||
buffer.raw[i] = b;
|
|
||||||
if (i == 5) {
|
|
||||||
unsigned short Address = ntohs(buffer.data.address); // the PIC sends bytes in "network order"
|
|
||||||
unsigned int Command = ntohl(buffer.data.command);
|
|
||||||
if (code == 'B' && address == 0x0000 && Command == 0x00004000)
|
|
||||||
// Well, well, if it isn't the "d-box"...
|
|
||||||
// This remote control sends the above command before and after
|
|
||||||
// each keypress - let's just drop this:
|
|
||||||
break;
|
|
||||||
if (!receivedData) { // only accept new data the previous data has been fetched
|
|
||||||
int Now = time_ms();
|
|
||||||
if (Command != LastCommand) {
|
|
||||||
receivedAddress = Address;
|
|
||||||
receivedCommand = Command;
|
|
||||||
receivedData = true;
|
|
||||||
receivedRepeat = receivedRelease = false;
|
|
||||||
FirstTime = Now;
|
|
||||||
}
|
}
|
||||||
else {
|
dsyslog("KBD remote control thread ended (pid=%d)", getpid());
|
||||||
if (Now - FirstTime < REPEATDELAY)
|
|
||||||
break; // repeat function kicks in after a short delay
|
|
||||||
receivedData = receivedRepeat = true;
|
|
||||||
}
|
|
||||||
LastCommand = Command;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (receivedData) { // the last data before releasing the key hasn't been fetched yet
|
|
||||||
if (receivedRepeat) { // it was a repeat, so let's make it a release
|
|
||||||
receivedRepeat = false;
|
|
||||||
receivedRelease = true;
|
|
||||||
LastCommand = 0;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release
|
|
||||||
receivedData = receivedRelease = true;
|
|
||||||
receivedRepeat = false;
|
|
||||||
LastCommand = 0;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LastCommand = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cRcIoRCU::ReceiveByte(int TimeoutMs)
|
|
||||||
{
|
|
||||||
// Returns the byte if one was received within a timeout, -1 otherwise
|
|
||||||
if (cFile::FileReady(f, TimeoutMs)) {
|
|
||||||
unsigned char b;
|
|
||||||
if (safe_read(f, &b, 1) == 1)
|
|
||||||
return b;
|
|
||||||
else
|
|
||||||
LOG_ERROR;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::SendByteHandshake(unsigned char c)
|
|
||||||
{
|
|
||||||
if (f >= 0) {
|
|
||||||
int w = write(f, &c, 1);
|
|
||||||
if (w == 1) {
|
|
||||||
for (int reply = ReceiveByte(REPEATLIMIT); reply >= 0;) {
|
|
||||||
if (reply == c)
|
|
||||||
return true;
|
|
||||||
else if (reply == 'X') {
|
|
||||||
// skip any incoming RC code - it will come again
|
|
||||||
for (int i = 6; i--;) {
|
|
||||||
if (ReceiveByte() < 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_ERROR;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::SendByte(unsigned char c)
|
|
||||||
{
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
for (int retry = 5; retry--;) {
|
|
||||||
if (SendByteHandshake(c))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::SetCode(unsigned char Code, unsigned short Address)
|
|
||||||
{
|
|
||||||
code = Code;
|
|
||||||
address = Address;
|
|
||||||
return SendCommand(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::SetMode(unsigned char Mode)
|
|
||||||
{
|
|
||||||
mode = Mode;
|
|
||||||
return SendCommand(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cRcIoRCU::Flush(int WaitMs)
|
|
||||||
{
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
int t0 = time_ms();
|
|
||||||
for (;;) {
|
|
||||||
while (ReceiveByte() >= 0)
|
|
||||||
t0 = time_ms();
|
|
||||||
if (time_ms() - t0 >= WaitMs)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
receivedData = receivedRepeat = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
|
|
||||||
{
|
|
||||||
if (receivedData) { // first we check the boolean flag without a lock, to avoid delays
|
|
||||||
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
if (receivedData) { // need to check again, since the status might have changed while waiting for the lock
|
|
||||||
if (Command)
|
|
||||||
*Command = receivedCommand;
|
|
||||||
if (Repeat)
|
|
||||||
*Repeat = receivedRepeat;
|
|
||||||
if (Release)
|
|
||||||
*Release = receivedRelease;
|
|
||||||
receivedData = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (time(NULL) - t > 60) {
|
|
||||||
SendCommand(code); // in case the PIC listens to the wrong code
|
|
||||||
t = time(NULL);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::SendCommand(unsigned char Cmd)
|
|
||||||
{
|
|
||||||
return SendByte(Cmd | 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::Digit(int n, int v)
|
|
||||||
{
|
|
||||||
return SendByte(((n & 0x03) << 5) | (v & 0x0F) | (((dp >> n) & 0x01) << 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::Number(int n, bool Hex)
|
|
||||||
{
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
if (!Hex) {
|
|
||||||
char buf[8];
|
|
||||||
sprintf(buf, "%4d", n & 0xFFFF);
|
|
||||||
n = 0;
|
|
||||||
for (char *d = buf; *d; d++) {
|
|
||||||
if (*d == ' ')
|
|
||||||
*d = 0xF;
|
|
||||||
n = (n << 4) | ((*d - '0') & 0x0F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastNumber = n;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (!Digit(i, n))
|
|
||||||
return false;
|
|
||||||
n >>= 4;
|
|
||||||
}
|
|
||||||
return SendCommand(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::String(char *s)
|
|
||||||
{
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP ";
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
for (int i = 0; *s && i < 4; s++, i++) {
|
|
||||||
n <<= 4;
|
|
||||||
for (const char *c = chars; *c; c++) {
|
|
||||||
if (*c == *s) {
|
|
||||||
n |= c - chars;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Number(n, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cRcIoRCU::SetPoints(unsigned char Dp, bool On)
|
|
||||||
{
|
|
||||||
if (On)
|
|
||||||
dp |= Dp;
|
|
||||||
else
|
|
||||||
dp &= ~Dp;
|
|
||||||
Number(lastNumber, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoRCU::DetectCode(unsigned char *Code, unsigned short *Address)
|
|
||||||
{
|
|
||||||
// Caller should initialize 'Code' to 0 and call DetectCode()
|
|
||||||
// until it returns true. Whenever DetectCode() returns false
|
|
||||||
// and 'Code' is not 0, the caller can use 'Code' to display
|
|
||||||
// a message like "Trying code '%c'". If false is returned and
|
|
||||||
// 'Code' is 0, all possible codes have been tried and the caller
|
|
||||||
// can either stop calling DetectCode() (and give some error
|
|
||||||
// message), or start all over again.
|
|
||||||
if (*Code < 'A' || *Code > 'D') {
|
|
||||||
*Code = 'A';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (*Code <= 'D') {
|
|
||||||
SetMode(modeH);
|
|
||||||
char buf[5];
|
|
||||||
sprintf(buf, "C0D%c", *Code);
|
|
||||||
String(buf);
|
|
||||||
SetCode(*Code, 0);
|
|
||||||
delay_ms(REPEATDELAY);
|
|
||||||
receivedData = receivedRepeat = 0;
|
|
||||||
delay_ms(REPEATDELAY);
|
|
||||||
if (GetCommand()) {
|
|
||||||
*Address = receivedAddress;
|
|
||||||
SetMode(modeB);
|
|
||||||
String("----");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (*Code < 'D') {
|
|
||||||
(*Code)++;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*Code = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cRcIoLIRC -------------------------------------------------------------
|
|
||||||
|
|
||||||
#elif defined REMOTE_LIRC
|
|
||||||
|
|
||||||
#define REPEATLIMIT 20 // ms
|
|
||||||
#define REPEATDELAY 350 // ms
|
|
||||||
|
|
||||||
cRcIoLIRC::cRcIoLIRC(char *DeviceName)
|
|
||||||
{
|
|
||||||
*keyName = 0;
|
|
||||||
receivedData = receivedRepeat = false;
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
strcpy(addr.sun_path, DeviceName);
|
|
||||||
if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
|
|
||||||
if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
|
|
||||||
Start();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG_ERROR_STR(DeviceName);
|
|
||||||
close(f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LOG_ERROR_STR(DeviceName);
|
|
||||||
f = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cRcIoLIRC::~cRcIoLIRC()
|
|
||||||
{
|
|
||||||
Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cRcIoLIRC::Action(void)
|
|
||||||
{
|
|
||||||
dsyslog("LIRC remote control thread started (pid=%d)", getpid());
|
|
||||||
|
|
||||||
int FirstTime = 0;
|
|
||||||
int LastTime = 0;
|
|
||||||
char buf[LIRC_BUFFER_SIZE];
|
|
||||||
char LastKeyName[LIRC_KEY_BUF];
|
|
||||||
|
|
||||||
for (; f >= 0;) {
|
|
||||||
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
if (cFile::FileReady(f, REPEATLIMIT) && safe_read(f, buf, sizeof(buf)) > 21) {
|
|
||||||
if (!receivedData) { // only accept new data the previous data has been fetched
|
|
||||||
int count;
|
|
||||||
sscanf(buf, "%*x %x %29s", &count, LastKeyName); // '29' in '%29s' is LIRC_KEY_BUF-1!
|
|
||||||
int Now = time_ms();
|
|
||||||
if (count == 0) {
|
|
||||||
strcpy(keyName, LastKeyName);
|
|
||||||
receivedData = true;
|
|
||||||
receivedRepeat = receivedRelease = false;
|
|
||||||
FirstTime = Now;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (Now - FirstTime < REPEATDELAY)
|
|
||||||
continue; // repeat function kicks in after a short delay
|
|
||||||
receivedData = receivedRepeat = true;
|
|
||||||
receivedRelease = false;
|
|
||||||
}
|
|
||||||
LastTime = Now;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (receivedData) { // the last data before releasing the key hasn't been fetched yet
|
|
||||||
if (receivedRepeat) { // it was a repeat, so let's make it a release
|
|
||||||
if (time_ms() - LastTime > REPEATDELAY) {
|
|
||||||
receivedRepeat = false;
|
|
||||||
receivedRelease = true;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release
|
|
||||||
if (time_ms() - LastTime > REPEATDELAY) {
|
|
||||||
receivedData = receivedRelease = true;
|
|
||||||
receivedRepeat = false;
|
|
||||||
WakeUp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cRcIoLIRC::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
|
|
||||||
{
|
|
||||||
if (receivedData) { // first we check the boolean flag without a lock, to avoid delays
|
|
||||||
|
|
||||||
LOCK_THREAD;
|
|
||||||
|
|
||||||
if (receivedData) { // need to check again, since the status might have changed while waiting for the lock
|
|
||||||
if (Command)
|
|
||||||
*Command = Keys.Encode(keyName);
|
|
||||||
if (Repeat)
|
|
||||||
*Repeat = receivedRepeat;
|
|
||||||
if (Release)
|
|
||||||
*Release = receivedRelease;
|
|
||||||
receivedData = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
108
remote.h
108
remote.h
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* remote.h: Interface to the Remote Control Unit
|
* remote.h: General Remote Control handling
|
||||||
*
|
*
|
||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: remote.h 1.16 2002/05/09 11:43:04 kls Exp $
|
* $Id: remote.h 1.17 2002/09/29 11:26:45 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __REMOTE_H
|
#ifndef __REMOTE_H
|
||||||
@ -12,91 +12,53 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "keys.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
class cRcIoBase {
|
typedef unsigned long long int uint64;
|
||||||
|
|
||||||
|
class cRemote : public cListObject {
|
||||||
|
private:
|
||||||
|
enum { MaxKeys = 16 };
|
||||||
|
static eKeys keys[MaxKeys];
|
||||||
|
static int in;
|
||||||
|
static int out;
|
||||||
|
static bool learning;
|
||||||
|
static char *unknownCode;
|
||||||
|
static cMutex mutex;
|
||||||
|
static cCondVar keyPressed;
|
||||||
|
char *name;
|
||||||
protected:
|
protected:
|
||||||
time_t t;
|
cRemote(const char *Name);
|
||||||
|
const char *GetSetup(void);
|
||||||
|
void PutSetup(const char *Setup);
|
||||||
|
bool Put(uint64 Code, bool Repeat = false, bool Release = false);
|
||||||
|
bool Put(const char *Code, bool Repeat = false, bool Release = false);
|
||||||
public:
|
public:
|
||||||
enum { modeH = 'h', modeB = 'b', modeS = 's' };
|
virtual ~cRemote();
|
||||||
cRcIoBase(void);
|
virtual bool Initialize(void) { return true; }
|
||||||
virtual ~cRcIoBase();
|
const char *Name(void) { return name; }
|
||||||
virtual bool SetCode(unsigned char Code, unsigned short Address) { return true; }
|
static void SetLearning(bool On) { learning = On; }
|
||||||
virtual bool SetMode(unsigned char Mode) { return true; }
|
static void Clear(void);
|
||||||
virtual bool Number(int n, bool Hex = false) { return true; }
|
static bool Put(eKeys Key);
|
||||||
virtual void SetPoints(unsigned char Dp, bool On) {}
|
static eKeys Get(int WaitMs = 1000, char **UnknownCode = NULL);
|
||||||
virtual bool String(char *s) { return true; }
|
|
||||||
virtual bool DetectCode(unsigned char *Code, unsigned short *Address) { return true; }
|
|
||||||
virtual void Flush(int WaitMs = 0) {}
|
|
||||||
virtual bool InputAvailable(void) { return false; }
|
|
||||||
virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL) { return false; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cRemotes : public cList<cRemote> {};
|
||||||
|
|
||||||
|
extern cRemotes Remotes;
|
||||||
|
|
||||||
#if defined REMOTE_KBD
|
#if defined REMOTE_KBD
|
||||||
|
|
||||||
class cRcIoKBD : public cRcIoBase {
|
class cKbdRemote : public cRemote, private cThread {
|
||||||
private:
|
private:
|
||||||
cFile f;
|
|
||||||
public:
|
|
||||||
cRcIoKBD(void);
|
|
||||||
virtual ~cRcIoKBD();
|
|
||||||
virtual void Flush(int WaitMs = 0);
|
|
||||||
virtual bool InputAvailable(void);
|
|
||||||
virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif defined REMOTE_RCU
|
|
||||||
|
|
||||||
class cRcIoRCU : public cRcIoBase, private cThread {
|
|
||||||
private:
|
|
||||||
int f;
|
|
||||||
unsigned char dp, code, mode;
|
|
||||||
unsigned short address;
|
|
||||||
unsigned short receivedAddress;
|
|
||||||
unsigned int receivedCommand;
|
|
||||||
bool receivedData, receivedRepeat, receivedRelease;
|
|
||||||
int lastNumber;
|
|
||||||
bool SendCommand(unsigned char Cmd);
|
|
||||||
int ReceiveByte(int TimeoutMs = 0);
|
|
||||||
bool SendByteHandshake(unsigned char c);
|
|
||||||
bool SendByte(unsigned char c);
|
|
||||||
bool Digit(int n, int v);
|
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
public:
|
public:
|
||||||
cRcIoRCU(char *DeviceName);
|
cKbdRemote(void);
|
||||||
virtual ~cRcIoRCU();
|
virtual ~cKbdRemote();
|
||||||
virtual bool SetCode(unsigned char Code, unsigned short Address);
|
|
||||||
virtual bool SetMode(unsigned char Mode);
|
|
||||||
virtual bool Number(int n, bool Hex = false);
|
|
||||||
virtual void SetPoints(unsigned char Dp, bool On);
|
|
||||||
virtual bool String(char *s);
|
|
||||||
virtual bool DetectCode(unsigned char *Code, unsigned short *Address);
|
|
||||||
virtual void Flush(int WaitMs = 0);
|
|
||||||
virtual bool InputAvailable(void) { return receivedData; }
|
|
||||||
virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined REMOTE_LIRC
|
|
||||||
|
|
||||||
class cRcIoLIRC : public cRcIoBase, private cThread {
|
|
||||||
private:
|
|
||||||
enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
|
|
||||||
int f;
|
|
||||||
char keyName[LIRC_KEY_BUF];
|
|
||||||
bool receivedData, receivedRepeat, receivedRelease;
|
|
||||||
virtual void Action(void);
|
|
||||||
public:
|
|
||||||
cRcIoLIRC(char *DeviceName);
|
|
||||||
virtual ~cRcIoLIRC();
|
|
||||||
virtual bool InputAvailable(void) { return receivedData; }
|
|
||||||
virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif !defined REMOTE_NONE
|
|
||||||
|
|
||||||
// #error Please define a remote control mode!
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //__REMOTE_H
|
#endif //__REMOTE_H
|
||||||
|
11
svdrp.c
11
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* graphical interface that sits on top of an SVDRP connection.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.c 1.42 2002/09/08 11:22:57 kls Exp $
|
* $Id: svdrp.c 1.43 2002/09/28 15:50:19 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -28,7 +28,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "interface.h"
|
#include "keys.h"
|
||||||
|
#include "remote.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
// --- cSocket ---------------------------------------------------------------
|
// --- cSocket ---------------------------------------------------------------
|
||||||
@ -606,9 +607,9 @@ void cSVDRP::CmdHELP(const char *Option)
|
|||||||
void cSVDRP::CmdHITK(const char *Option)
|
void cSVDRP::CmdHITK(const char *Option)
|
||||||
{
|
{
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
eKeys k = Keys.Translate(Option);
|
eKeys k = cKey::FromString(Option);
|
||||||
if (k != kNone) {
|
if (k != kNone) {
|
||||||
Interface->PutKey(k);
|
cRemote::Put(k);
|
||||||
Reply(250, "Key \"%s\" accepted", Option);
|
Reply(250, "Key \"%s\" accepted", Option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -617,7 +618,7 @@ void cSVDRP::CmdHITK(const char *Option)
|
|||||||
else {
|
else {
|
||||||
Reply(-214, "Valid <key> names for the HITK command:");
|
Reply(-214, "Valid <key> names for the HITK command:");
|
||||||
for (int i = 0; i < kNone; i++) {
|
for (int i = 0; i < kNone; i++) {
|
||||||
Reply(-214, " %s", Keys.keys[i].name);
|
Reply(-214, " %s", cKey::ToString(eKeys(i)));
|
||||||
}
|
}
|
||||||
Reply(214, "End of key list");
|
Reply(214, "End of key list");
|
||||||
}
|
}
|
||||||
|
22
vdr.5
22
vdr.5
@ -8,9 +8,9 @@
|
|||||||
.\" License as specified in the file COPYING that comes with the
|
.\" License as specified in the file COPYING that comes with the
|
||||||
.\" vdr distribution.
|
.\" vdr distribution.
|
||||||
.\"
|
.\"
|
||||||
.\" $Id: vdr.5 1.4 2002/04/07 13:12:04 kls Exp $
|
.\" $Id: vdr.5 1.5 2002/09/29 13:06:40 kls Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH vdr 5 "7 Apr 2002" "1.0.0" "Video Disk Recorder Files"
|
.TH vdr 5 "7 Sep 2002" "1.2.0" "Video Disk Recorder Files"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
vdr file formats - the Video Disk Recorder Files
|
vdr file formats - the Video Disk Recorder Files
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@ -209,12 +209,18 @@ channels that don't require additional decryption hardware.
|
|||||||
|
|
||||||
The values \fB1...4\fR can be used for channels that for some reason explicitly
|
The values \fB1...4\fR can be used for channels that for some reason explicitly
|
||||||
need a given DVB card (for backward compatibility).
|
need a given DVB card (for backward compatibility).
|
||||||
.SS KEYS
|
.SS REMOTE CONTROL KEYS
|
||||||
The file \fIkeys.conf\fR contains the key assignments for the remote control
|
The file \fIremote.conf\fR contains the key assignments for all remote control
|
||||||
unit (RCU). If \fBvdr\fR has been built with REMOTE=KBD, the file \fIkeys-pc.conf\fR
|
units. Each line consists of one key assignment in the following format:
|
||||||
will be used instead. If you are using \fBvdr\fR together with \fBLIRC\fR, no
|
|
||||||
such file will be used. In that case you need to consult the \fBLIRC\fR
|
\fBname.key code\fR
|
||||||
documentation to see how to set up the remote control key assignments there.
|
|
||||||
|
where \fBname\fR is the name of the remote control (for instance KBD for the
|
||||||
|
PC keyboard, RCU for the home-built "Remote Control Unit", or LIRC for the
|
||||||
|
"Linux Infrared Remote Control"), \fBkey\fR is the name of the key that is
|
||||||
|
defined (like Up, Down, Menu etc.), and \fBcode\fR is a character string that
|
||||||
|
this remote control delivers when the given key is pressed.
|
||||||
|
|
||||||
.SS COMMANDS
|
.SS COMMANDS
|
||||||
The file \fIcommands.conf\fR contains the definitions of commands that can
|
The file \fIcommands.conf\fR contains the definitions of commands that can
|
||||||
be executed from the \fBvdr\fR main menu's "Commands" option.
|
be executed from the \fBvdr\fR main menu's "Commands" option.
|
||||||
|
39
vdr.c
39
vdr.c
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||||
*
|
*
|
||||||
* $Id: vdr.c 1.123 2002/09/15 11:08:35 kls Exp $
|
* $Id: vdr.c 1.124 2002/09/29 12:55:03 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -37,19 +37,16 @@
|
|||||||
#include "eitscan.h"
|
#include "eitscan.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "lirc.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "rcu.h"
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "videodir.h"
|
#include "videodir.h"
|
||||||
|
|
||||||
#ifdef REMOTE_KBD
|
|
||||||
#define KEYS_CONF "keys-pc.conf"
|
|
||||||
#else
|
|
||||||
#define KEYS_CONF "keys.conf"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping
|
#define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping
|
||||||
#define SHUTDOWNWAIT 300 // seconds to wait in user prompt before automatic shutdown
|
#define SHUTDOWNWAIT 300 // seconds to wait in user prompt before automatic shutdown
|
||||||
#define MANUALSTART 600 // seconds the next timer must be in the future to assume manual start
|
#define MANUALSTART 600 // seconds the next timer must be in the future to assume manual start
|
||||||
@ -319,11 +316,7 @@ int main(int argc, char *argv[])
|
|||||||
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
|
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
|
||||||
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
|
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
|
||||||
CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true);
|
CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true);
|
||||||
#if defined(REMOTE_LIRC)
|
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
|
||||||
Keys.SetDummyValues();
|
|
||||||
#elif !defined(REMOTE_NONE)
|
|
||||||
bool KeysLoaded = Keys.Load(AddDirectory(ConfigDirectory, KEYS_CONF));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// DVB interfaces:
|
// DVB interfaces:
|
||||||
|
|
||||||
@ -350,6 +343,20 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
cOsd::Initialize();
|
cOsd::Initialize();
|
||||||
|
|
||||||
|
// User interface:
|
||||||
|
|
||||||
|
Interface = new cInterface(SVDRPport);
|
||||||
|
|
||||||
|
// Remote Controls:
|
||||||
|
#if defined(REMOTE_RCU)
|
||||||
|
new cRcuRemote("/dev/ttyS1");
|
||||||
|
#elif defined(REMOTE_LIRC)
|
||||||
|
new cLircRemote("/dev/lircd");
|
||||||
|
#elif defined(REMOTE_KBD)
|
||||||
|
new cKbdRemote;
|
||||||
|
#endif
|
||||||
|
Interface->LearnKeys();
|
||||||
|
|
||||||
// Channel:
|
// Channel:
|
||||||
|
|
||||||
Channels.SwitchTo(Setup.CurrentChannel);
|
Channels.SwitchTo(Setup.CurrentChannel);
|
||||||
@ -360,14 +367,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
cEITScanner EITScanner;
|
cEITScanner EITScanner;
|
||||||
|
|
||||||
// User interface:
|
|
||||||
|
|
||||||
Interface = new cInterface(SVDRPport);
|
|
||||||
#if !defined(REMOTE_LIRC) && !defined(REMOTE_NONE)
|
|
||||||
if (!KeysLoaded)
|
|
||||||
Interface->LearnKeys();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Signal handlers:
|
// Signal handlers:
|
||||||
|
|
||||||
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
||||||
|
Loading…
Reference in New Issue
Block a user