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).
|
||||
- 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
|
||||
to Jeremy Hall).
|
||||
@ -1517,3 +1517,18 @@ Video Disk Recorder Revision History
|
||||
numbers may be different.
|
||||
- Added a missing 'public' keyword in device.h (thanks to Martin Hammerschmid).
|
||||
- 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:
|
||||
---------------------------------
|
||||
|
||||
There is no default 'keys.conf' file, so if you compile the program
|
||||
with 'REMOTE=RCU' you will have to go through a "teach-in"
|
||||
There is no default 'remote.conf' file, so you will have to go through a "teach-in"
|
||||
session that allows the program to learn your remote control codes.
|
||||
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
|
||||
@ -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
|
||||
of keys which have multiple meanings in the various modes (see MANUAL
|
||||
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
|
||||
Menu 'Home' in numeric block
|
||||
@ -359,10 +355,6 @@ The default PC key assignments are:
|
||||
Mute 'm'
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
# 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:
|
||||
|
||||
@ -33,7 +33,7 @@ endif
|
||||
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\
|
||||
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\
|
||||
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
|
||||
structures and allows it to hook itself into specific areas to perform special actions.
|
||||
<p>
|
||||
<!--X1.1.6--><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%>
|
||||
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
Important modifications introduced in version 1.1.7 are marked like this.
|
||||
<!--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.
|
||||
<!--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.
|
||||
<!--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>
|
||||
|
||||
@ -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
|
||||
desired video data stream, and it must be delivered fast enough so that the
|
||||
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
|
||||
|
||||
<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
|
||||
ahead - it's your show...
|
||||
|
||||
<!--X1.1.6--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
<hr><h2>Receivers</h2>
|
||||
|
||||
<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>
|
||||
and will automatically detach itself from the <tt>cDevice</tt>.
|
||||
<!--X1.1.6--></td></tr></table>
|
||||
|
||||
<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
|
||||
its windows and color depths).
|
||||
|
||||
<!--X1.1.6--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
<hr><h2>Devices</h2>
|
||||
|
||||
<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
|
||||
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>
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
||||
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 OpenDvr(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);
|
||||
<!--X1.1.9--></td></tr></table>
|
||||
</pre></td></tr></table><p>
|
||||
@ -1230,7 +1227,7 @@ to indicate this to VDR.
|
||||
<p>
|
||||
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>
|
||||
virtual bool HasDecoder(void) const;
|
||||
virtual bool SetPlayMode(ePlayMode PlayMode);
|
||||
@ -1254,7 +1251,7 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
|
||||
virtual void SetVolumeDevice(int Volume);
|
||||
</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>
|
||||
<b>On Screen Display</b>
|
||||
<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
|
||||
important that the devices are created on the heap, using the <tt>new</tt>
|
||||
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>
|
||||
</html>
|
||||
|
172
config.c
172
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.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"
|
||||
@ -19,169 +19,6 @@
|
||||
// format characters in order to allow any number of blanks after a numeric
|
||||
// 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 ---------------------------------------------------------------
|
||||
|
||||
char *cChannel::buffer = NULL;
|
||||
@ -247,7 +84,6 @@ bool cChannel::Parse(const char *s)
|
||||
if (*s == ':') {
|
||||
if (*++s) {
|
||||
strn0cpy(name, s, MaxChannelName);
|
||||
name[strlen(name) - 1] = 0; // strip the '\n'
|
||||
groupSep = true;
|
||||
number = 0;
|
||||
}
|
||||
@ -696,7 +532,7 @@ bool cSVDRPhost::Parse(const char *s)
|
||||
if (p) {
|
||||
char *error = NULL;
|
||||
int m = strtoul(p + 1, &error, 10);
|
||||
if (error && !isspace(*error) || m > 32)
|
||||
if (error && *error && !isspace(*error) || m > 32)
|
||||
return false;
|
||||
*(char *)p = 0; // yes, we know it's 'const' - will be restored!
|
||||
if (m == 0)
|
||||
@ -733,10 +569,6 @@ bool cCaDefinition::Parse(const char *s)
|
||||
return 2 == sscanf(s, "%d %a[^\n]", &number, &description) && description && *description;
|
||||
}
|
||||
|
||||
// -- cKeys ------------------------------------------------------------------
|
||||
|
||||
cKeys Keys;
|
||||
|
||||
// -- cCommands --------------------------------------------------------------
|
||||
|
||||
cCommands Commands;
|
||||
|
78
config.h
78
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.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
|
||||
@ -30,69 +30,8 @@
|
||||
#define MINOSDHEIGHT 12
|
||||
#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
|
||||
|
||||
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)
|
||||
|
||||
class cChannel : public cListObject {
|
||||
@ -214,6 +153,7 @@ public:
|
||||
template<class T> class cConfig : public cList<T> {
|
||||
private:
|
||||
char *fileName;
|
||||
bool allowComments;
|
||||
void Clear(void)
|
||||
{
|
||||
free(fileName);
|
||||
@ -224,13 +164,17 @@ public:
|
||||
cConfig(void) { fileName = NULL; }
|
||||
virtual ~cConfig() { free(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();
|
||||
if (FileName) {
|
||||
free(fileName);
|
||||
fileName = strdup(FileName);
|
||||
allowComments = AllowComments;
|
||||
}
|
||||
bool result = false;
|
||||
if (access(FileName, F_OK) == 0) {
|
||||
isyslog("loading %s", FileName);
|
||||
if (fileName && access(fileName, F_OK) == 0) {
|
||||
isyslog("loading %s", fileName);
|
||||
FILE *f = fopen(fileName, "r");
|
||||
if (f) {
|
||||
int line = 0;
|
||||
@ -238,11 +182,12 @@ public:
|
||||
result = true;
|
||||
while (fgets(buffer, sizeof(buffer), f) > 0) {
|
||||
line++;
|
||||
if (AllowComments) {
|
||||
if (allowComments) {
|
||||
char *p = strchr(buffer, '#');
|
||||
if (p)
|
||||
*p = 0;
|
||||
}
|
||||
stripspace(buffer);
|
||||
if (!isempty(buffer)) {
|
||||
T *l = new T;
|
||||
if (l->Parse(buffer))
|
||||
@ -322,7 +267,6 @@ public:
|
||||
|
||||
extern cChannels Channels;
|
||||
extern cTimers Timers;
|
||||
extern cKeys Keys;
|
||||
extern cCommands Commands;
|
||||
extern cSVDRPhosts SVDRPhosts;
|
||||
extern cCaDefinitions CaDefinitions;
|
||||
|
16
device.c
16
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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"
|
||||
@ -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)
|
||||
|
||||
bool cDevice::HasPid(int Pid)
|
||||
bool cDevice::HasPid(int Pid) const
|
||||
{
|
||||
for (int i = 0; i < MAXPIDHANDLES; i++) {
|
||||
if (pidHandles[i].pid == Pid)
|
||||
@ -275,7 +275,7 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
||||
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;
|
||||
}
|
||||
@ -424,7 +424,7 @@ void cDevice::StillPicture(const uchar *Data, int Length)
|
||||
{
|
||||
}
|
||||
|
||||
bool cDevice::Replaying(void)
|
||||
bool cDevice::Replaying(void) const
|
||||
{
|
||||
return player != NULL;
|
||||
}
|
||||
@ -478,7 +478,7 @@ int cDevice::PlayAudio(const uchar *Data, int Length)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cDevice::Priority(void)
|
||||
int cDevice::Priority(void) const
|
||||
{
|
||||
int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
@ -488,7 +488,7 @@ int cDevice::Priority(void)
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
|
||||
int cDevice::ProvidesCa(int Ca)
|
||||
int cDevice::ProvidesCa(int Ca) const
|
||||
{
|
||||
if (Ca == CardIndex() + 1)
|
||||
return 1; // exactly _this_ card was requested
|
||||
@ -542,7 +542,7 @@ int cDevice::ProvidesCa(int Ca)
|
||||
return result ? result + others : 0;
|
||||
}
|
||||
|
||||
bool cDevice::Receiving(void)
|
||||
bool cDevice::Receiving(void) const
|
||||
{
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
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
|
||||
* 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
|
||||
@ -111,7 +111,7 @@ public:
|
||||
bool IsPrimaryDevice(void) const { return this == primaryDevice; }
|
||||
int CardIndex(void) const { return cardIndex; }
|
||||
// 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
|
||||
// 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.
|
||||
@ -139,7 +139,7 @@ public:
|
||||
protected:
|
||||
static int currentChannel;
|
||||
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.
|
||||
// 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
|
||||
@ -186,7 +186,7 @@ protected:
|
||||
cPidHandle(void) { pid = used = 0; handle = -1; }
|
||||
};
|
||||
cPidHandle pidHandles[MAXPIDHANDLES];
|
||||
bool HasPid(int Pid);
|
||||
bool HasPid(int Pid) const;
|
||||
// Returns true if this device is currently receiving the given PID.
|
||||
bool AddPid(int Pid, ePidType PidType = ptOther);
|
||||
// Adds a PID to the set of PIDs this device shall receive.
|
||||
@ -224,7 +224,7 @@ protected:
|
||||
virtual void SetVolumeDevice(int Volume);
|
||||
// Sets the audio volume on this device (Volume = 0...255).
|
||||
public:
|
||||
bool IsMute(void) { return mute; }
|
||||
bool IsMute(void) const { return mute; }
|
||||
bool ToggleMute(void);
|
||||
// Turns the volume off or on and returns the new mute state.
|
||||
void SetVolume(int Volume, bool Absolute = false);
|
||||
@ -269,7 +269,7 @@ public:
|
||||
// one video and one audio strem.
|
||||
virtual int PlayAudio(const uchar *Data, int Length);
|
||||
// Plays additional audio streams, like Dolby Digital.
|
||||
bool Replaying(void);
|
||||
bool Replaying(void) const;
|
||||
// Returns true if we are currently replaying.
|
||||
void StopReplay(void);
|
||||
// Stops the current replay session (if any).
|
||||
@ -285,9 +285,9 @@ public:
|
||||
private:
|
||||
cReceiver *receiver[MAXRECEIVERS];
|
||||
int ca;
|
||||
int CanShift(int Ca, int Priority, int UsedCards = 0);
|
||||
int CanShift(int Ca, int Priority, int UsedCards = 0) const;
|
||||
protected:
|
||||
int Priority(void);
|
||||
int Priority(void) const;
|
||||
// Returns the priority of the current receiving session (0..MAXPRIORITY),
|
||||
// or -1 if no receiver is currently active. The primary device will
|
||||
// always return at least Setup.PrimaryLimit-1.
|
||||
@ -304,9 +304,9 @@ protected:
|
||||
// false in case of a non recoverable error, otherwise it returns true,
|
||||
// even if Data is NULL.
|
||||
public:
|
||||
int Ca(void) { return ca; }
|
||||
int Ca(void) const { return ca; }
|
||||
// Returns the ca of the current receiving session.
|
||||
bool Receiving(void);
|
||||
bool Receiving(void) const;
|
||||
// Returns true if we are currently receiving.
|
||||
bool AttachReceiver(cReceiver *Receiver);
|
||||
// Attaches the given receiver to this device.
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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"
|
||||
@ -344,7 +344,7 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
||||
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 hasPriority = Priority < 0 || Priority > this->Priority();
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* 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
|
||||
@ -63,7 +63,7 @@ public:
|
||||
private:
|
||||
int frequency;
|
||||
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:
|
||||
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
|
||||
* 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:
|
||||
*
|
||||
@ -2401,6 +2401,22 @@ const tI18nPhrase Phrases[] = {
|
||||
"(Apasati 'Jos' pentru terminare)",
|
||||
"('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: Codes abspeichern",
|
||||
"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
|
||||
* 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"
|
||||
@ -22,27 +22,14 @@ cInterface::cInterface(int SVDRPport)
|
||||
open = 0;
|
||||
cols[0] = 0;
|
||||
width = height = 0;
|
||||
keyFromWait = kNone;
|
||||
interrupted = false;
|
||||
rcIo = 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)
|
||||
SVDRP = new cSVDRP(SVDRPport);
|
||||
}
|
||||
|
||||
cInterface::~cInterface()
|
||||
{
|
||||
delete rcIo;
|
||||
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)
|
||||
{
|
||||
Flush();
|
||||
@ -89,22 +67,7 @@ eKeys cInterface::GetKey(bool Wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
eKeys Key = keyFromWait;
|
||||
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;
|
||||
return cRemote::Get(Wait ? 1000 : 10);
|
||||
}
|
||||
|
||||
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
@ -120,7 +83,7 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
break;
|
||||
}
|
||||
if (KeepChar && ISRAWKEY(Key))
|
||||
keyFromWait = Key;
|
||||
cRemote::Put(Key);
|
||||
interrupted = false;
|
||||
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);
|
||||
}
|
||||
|
||||
void cInterface::QueryKeys(void)
|
||||
void cInterface::QueryKeys(cRemote *Remote)
|
||||
{
|
||||
Keys.Clear();
|
||||
cRemote::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, 5, tr("Press any key on the RC unit"));
|
||||
Flush();
|
||||
#ifndef REMOTE_KBD
|
||||
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;
|
||||
if (Remote->Initialize()) {
|
||||
WriteText(1, 5, tr("RC code detected!"));
|
||||
WriteText(1, 6, tr("Do not press any key..."));
|
||||
Flush();
|
||||
rcIo->Flush(3000);
|
||||
sleep(3);
|
||||
ClearEol(0, 5);
|
||||
ClearEol(0, 6);
|
||||
Flush();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WriteText(1, 3, tr("Phase 2: Learning specific key codes"));
|
||||
tKey *k = Keys.keys;
|
||||
while (k->type != kNone) {
|
||||
eKeys NewKey = kUp;
|
||||
while (NewKey != kNone) {
|
||||
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);
|
||||
free(Prompt);
|
||||
for (;;) {
|
||||
unsigned int ch = GetCh();
|
||||
if (ch != 0) {
|
||||
switch (Keys.Get(ch)) {
|
||||
case kUp: if (k > Keys.keys) {
|
||||
k--;
|
||||
break;
|
||||
cRemote::Clear();
|
||||
Flush();
|
||||
for (eKeys k = NewKey; k == NewKey; ) {
|
||||
char *NewCode = NULL;
|
||||
eKeys Key = cRemote::Get(100, &NewCode);
|
||||
switch (Key) {
|
||||
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) {
|
||||
WriteText(1, 5, tr("Press 'Up' to confirm"));
|
||||
break;
|
||||
case kDown: WriteText(1, 5, tr("Press 'Up' to confirm"));
|
||||
WriteText(1, 6, tr("Press 'Down' to continue"));
|
||||
ClearEol(0, 7);
|
||||
ClearEol(0, 8);
|
||||
ClearEol(0, 9);
|
||||
for (;;) {
|
||||
eKeys key = GetKey();
|
||||
if (key == kUp) {
|
||||
Key = cRemote::Get(100);
|
||||
if (Key == kUp) {
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
else if (key == kDown) {
|
||||
else if (Key == kDown) {
|
||||
ClearEol(0, 6);
|
||||
k = kNone; // breaks the outer for() loop
|
||||
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;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k > Keys.keys)
|
||||
if (NewKey > kUp)
|
||||
WriteText(1, 7, tr("(press 'Up' to go back)"));
|
||||
else
|
||||
ClearEol(0, 7);
|
||||
if (k > Keys.keys + 1)
|
||||
if (NewKey > kDown)
|
||||
WriteText(1, 8, tr("(press 'Down' to end key definition)"));
|
||||
else
|
||||
ClearEol(0, 8);
|
||||
if (NewKey > kMenu)
|
||||
WriteText(1, 9, tr("(press 'Menu' to skip this key)"));
|
||||
else
|
||||
ClearEol(0, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
for (;;) {
|
||||
Clear();
|
||||
QueryKeys();
|
||||
cRemote::SetLearning(true);
|
||||
QueryKeys(Remote);
|
||||
cRemote::SetLearning(false);
|
||||
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, 5, tr("Press 'Up' to save, 'Down' to cancel"));
|
||||
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
|
||||
* 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
|
||||
@ -22,12 +22,9 @@ private:
|
||||
int width, height;
|
||||
int open;
|
||||
int cols[MaxCols];
|
||||
eKeys keyFromWait;
|
||||
bool interrupted;
|
||||
cSVDRP *SVDRP;
|
||||
cRcIoBase *rcIo;
|
||||
unsigned int GetCh(bool Wait = true, bool *Repeat = NULL, bool *Release = NULL);
|
||||
void QueryKeys(void);
|
||||
void QueryKeys(cRemote *Remote);
|
||||
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
|
||||
eKeys Wait(int Seconds = 0, bool KeepChar = false);
|
||||
public:
|
||||
@ -40,7 +37,6 @@ public:
|
||||
int Width(void) { return width; }
|
||||
int Height(void) { return height; }
|
||||
eKeys GetKey(bool Wait = true);
|
||||
void PutKey(eKeys Key);
|
||||
void Clear(void);
|
||||
void ClearEol(int x, int y, 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);
|
||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
void LearnKeys(void);
|
||||
void DisplayChannelNumber(int Number);
|
||||
void DisplayRecording(int Index, bool On);
|
||||
bool Recording(void);
|
||||
};
|
||||
|
||||
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
|
||||
* 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"
|
||||
@ -20,6 +20,7 @@
|
||||
#include "menuitems.h"
|
||||
#include "plugin.h"
|
||||
#include "recording.h"
|
||||
#include "remote.h"
|
||||
#include "status.h"
|
||||
#include "videodir.h"
|
||||
|
||||
@ -2121,7 +2122,7 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
|
||||
withInfo = !Switched || Setup.ShowInfoOnChSwitch;
|
||||
int EpgLines = withInfo ? 5 : 1;
|
||||
lines = 0;
|
||||
oldNumber = number = 0;
|
||||
number = 0;
|
||||
cChannel *channel = Channels.GetByNumber(Number);
|
||||
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
||||
if (channel) {
|
||||
@ -2135,7 +2136,6 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
|
||||
:cOsdObject(true)
|
||||
{
|
||||
group = -1;
|
||||
oldNumber = cDevice::CurrentChannel();
|
||||
number = 0;
|
||||
lastTime = time_ms();
|
||||
int EpgLines = Setup.ShowInfoOnChSwitch ? 5 : 1;
|
||||
@ -2145,15 +2145,11 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
|
||||
|
||||
cDisplayChannel::~cDisplayChannel()
|
||||
{
|
||||
if (number < 0)
|
||||
Interface->DisplayChannelNumber(oldNumber);
|
||||
Interface->Close();
|
||||
}
|
||||
|
||||
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
|
||||
{
|
||||
if (Channel && Channel->number > 0)
|
||||
Interface->DisplayChannelNumber(Channel->number);
|
||||
int BufSize = Width() + 1;
|
||||
char buffer[BufSize];
|
||||
if (Channel && Channel->number > 0)
|
||||
@ -2231,7 +2227,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
case k0:
|
||||
if (number == 0) {
|
||||
// keep the "Toggle channels" function working
|
||||
Interface->PutKey(Key);
|
||||
cRemote::Put(Key);
|
||||
return osEnd;
|
||||
}
|
||||
case k1 ... k9:
|
||||
@ -2290,7 +2286,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->number);
|
||||
return osEnd;
|
||||
default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
|
||||
Interface->PutKey(Key);
|
||||
cRemote::Put(Key);
|
||||
return osEnd;
|
||||
}
|
||||
};
|
||||
@ -2397,7 +2393,7 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
|
||||
break;
|
||||
case kNone: break;
|
||||
default: if ((Key & k_Release) == 0) {
|
||||
Interface->PutKey(Key);
|
||||
cRemote::Put(Key);
|
||||
return osEnd;
|
||||
}
|
||||
}
|
||||
@ -2441,7 +2437,6 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
|
||||
if (device->AttachReceiver(recorder)) {
|
||||
Recording.WriteSummary();
|
||||
cStatus::MsgRecording(device, Recording.Name());
|
||||
Interface->DisplayRecording(device->CardIndex(), true);
|
||||
}
|
||||
else
|
||||
DELETENULL(recorder);
|
||||
@ -2487,7 +2482,6 @@ bool cRecordControl::GetEventInfo(void)
|
||||
void cRecordControl::Stop(bool KeepInstant)
|
||||
{
|
||||
if (timer) {
|
||||
cStatus::MsgRecording(device, NULL);
|
||||
DELETENULL(recorder);
|
||||
timer->SetRecording(false);
|
||||
if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && timer->StopTime() <= time(NULL))) {
|
||||
@ -2496,7 +2490,7 @@ void cRecordControl::Stop(bool KeepInstant)
|
||||
Timers.Save();
|
||||
}
|
||||
timer = NULL;
|
||||
Interface->DisplayRecording(device->CardIndex(), false);
|
||||
cStatus::MsgRecording(device, NULL);
|
||||
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
|
||||
* 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
|
||||
@ -32,7 +32,7 @@ private:
|
||||
bool withInfo;
|
||||
int lines;
|
||||
int lastTime;
|
||||
int oldNumber, number;
|
||||
int number;
|
||||
void DisplayChannel(const cChannel *Channel);
|
||||
void DisplayInfo(void);
|
||||
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
|
||||
* how to reach the author.
|
||||
*
|
||||
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
|
||||
*
|
||||
* $Id: remote.c 1.27 2002/05/18 12:55:39 kls Exp $
|
||||
* $Id: remote.c 1.28 2002/09/29 12:51:26 kls Exp $
|
||||
*/
|
||||
|
||||
#include "remote.h"
|
||||
@ -18,487 +16,150 @@
|
||||
#include <termios.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
|
||||
#include <ncurses.h>
|
||||
#endif
|
||||
|
||||
#include "config.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
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_ERROR_STR(DeviceName);
|
||||
close(f);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(DeviceName);
|
||||
f = -1;
|
||||
}
|
||||
|
||||
cRcIoRCU::~cRcIoRCU()
|
||||
cKbdRemote::~cKbdRemote()
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void cRcIoRCU::Action(void)
|
||||
void cKbdRemote::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());
|
||||
|
||||
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;
|
||||
dsyslog("KBD remote control thread started (pid=%d)", getpid());
|
||||
cPoller Poller(STDIN_FILENO);
|
||||
for (;;) {//XXX
|
||||
int Command = getch();
|
||||
if (Command != EOF)
|
||||
Put(Command);
|
||||
Poller.Poll(100);
|
||||
}
|
||||
else {
|
||||
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;
|
||||
dsyslog("KBD remote control thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
#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
|
||||
* 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
|
||||
@ -12,91 +12,53 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "keys.h"
|
||||
#include "thread.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:
|
||||
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:
|
||||
enum { modeH = 'h', modeB = 'b', modeS = 's' };
|
||||
cRcIoBase(void);
|
||||
virtual ~cRcIoBase();
|
||||
virtual bool SetCode(unsigned char Code, unsigned short Address) { return true; }
|
||||
virtual bool SetMode(unsigned char Mode) { return true; }
|
||||
virtual bool Number(int n, bool Hex = false) { return true; }
|
||||
virtual void SetPoints(unsigned char Dp, bool On) {}
|
||||
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; }
|
||||
virtual ~cRemote();
|
||||
virtual bool Initialize(void) { return true; }
|
||||
const char *Name(void) { return name; }
|
||||
static void SetLearning(bool On) { learning = On; }
|
||||
static void Clear(void);
|
||||
static bool Put(eKeys Key);
|
||||
static eKeys Get(int WaitMs = 1000, char **UnknownCode = NULL);
|
||||
};
|
||||
|
||||
class cRemotes : public cList<cRemote> {};
|
||||
|
||||
extern cRemotes Remotes;
|
||||
|
||||
#if defined REMOTE_KBD
|
||||
|
||||
class cRcIoKBD : public cRcIoBase {
|
||||
class cKbdRemote : public cRemote, private cThread {
|
||||
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);
|
||||
public:
|
||||
cRcIoRCU(char *DeviceName);
|
||||
virtual ~cRcIoRCU();
|
||||
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);
|
||||
cKbdRemote(void);
|
||||
virtual ~cKbdRemote();
|
||||
};
|
||||
|
||||
#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 //__REMOTE_H
|
||||
|
11
svdrp.c
11
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 1.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"
|
||||
@ -28,7 +28,8 @@
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
#include "device.h"
|
||||
#include "interface.h"
|
||||
#include "keys.h"
|
||||
#include "remote.h"
|
||||
#include "tools.h"
|
||||
|
||||
// --- cSocket ---------------------------------------------------------------
|
||||
@ -606,9 +607,9 @@ void cSVDRP::CmdHELP(const char *Option)
|
||||
void cSVDRP::CmdHITK(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
eKeys k = Keys.Translate(Option);
|
||||
eKeys k = cKey::FromString(Option);
|
||||
if (k != kNone) {
|
||||
Interface->PutKey(k);
|
||||
cRemote::Put(k);
|
||||
Reply(250, "Key \"%s\" accepted", Option);
|
||||
}
|
||||
else
|
||||
@ -617,7 +618,7 @@ void cSVDRP::CmdHITK(const char *Option)
|
||||
else {
|
||||
Reply(-214, "Valid <key> names for the HITK command:");
|
||||
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");
|
||||
}
|
||||
|
22
vdr.5
22
vdr.5
@ -8,9 +8,9 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" 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
|
||||
vdr file formats - the Video Disk Recorder Files
|
||||
.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
|
||||
need a given DVB card (for backward compatibility).
|
||||
.SS KEYS
|
||||
The file \fIkeys.conf\fR contains the key assignments for the remote control
|
||||
unit (RCU). If \fBvdr\fR has been built with REMOTE=KBD, the file \fIkeys-pc.conf\fR
|
||||
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
|
||||
documentation to see how to set up the remote control key assignments there.
|
||||
.SS REMOTE CONTROL KEYS
|
||||
The file \fIremote.conf\fR contains the key assignments for all remote control
|
||||
units. Each line consists of one key assignment in the following format:
|
||||
|
||||
\fBname.key code\fR
|
||||
|
||||
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
|
||||
The file \fIcommands.conf\fR contains the definitions of commands that can
|
||||
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
|
||||
*
|
||||
* $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>
|
||||
@ -37,19 +37,16 @@
|
||||
#include "eitscan.h"
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "keys.h"
|
||||
#include "lirc.h"
|
||||
#include "menu.h"
|
||||
#include "osd.h"
|
||||
#include "plugin.h"
|
||||
#include "rcu.h"
|
||||
#include "recording.h"
|
||||
#include "tools.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 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
|
||||
@ -319,11 +316,7 @@ int main(int argc, char *argv[])
|
||||
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
|
||||
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
|
||||
CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true);
|
||||
#if defined(REMOTE_LIRC)
|
||||
Keys.SetDummyValues();
|
||||
#elif !defined(REMOTE_NONE)
|
||||
bool KeysLoaded = Keys.Load(AddDirectory(ConfigDirectory, KEYS_CONF));
|
||||
#endif
|
||||
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
|
||||
|
||||
// DVB interfaces:
|
||||
|
||||
@ -350,6 +343,20 @@ int main(int argc, char *argv[])
|
||||
|
||||
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:
|
||||
|
||||
Channels.SwitchTo(Setup.CurrentChannel);
|
||||
@ -360,14 +367,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
cEITScanner EITScanner;
|
||||
|
||||
// User interface:
|
||||
|
||||
Interface = new cInterface(SVDRPport);
|
||||
#if !defined(REMOTE_LIRC) && !defined(REMOTE_NONE)
|
||||
if (!KeysLoaded)
|
||||
Interface->LearnKeys();
|
||||
#endif
|
||||
|
||||
// Signal handlers:
|
||||
|
||||
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
||||
|
Loading…
Reference in New Issue
Block a user