mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
Add repeat handling for X11 keyboard remote control
This commit is contained in:
parent
6acd2feb3f
commit
b883fa606b
147
softhdcuvid.cpp
147
softhdcuvid.cpp
@ -28,6 +28,7 @@
|
|||||||
#include <vdr/osd.h>
|
#include <vdr/osd.h>
|
||||||
#include <vdr/dvbspu.h>
|
#include <vdr/dvbspu.h>
|
||||||
#include <vdr/shutdown.h>
|
#include <vdr/shutdown.h>
|
||||||
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG
|
#ifdef HAVE_CONFIG
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -202,76 +203,122 @@ static signed char SuspendMode; ///< suspend mode
|
|||||||
/**
|
/**
|
||||||
** Soft device plugin remote class.
|
** Soft device plugin remote class.
|
||||||
*/
|
*/
|
||||||
class cSoftRemote:public cRemote
|
class cSoftRemote:public cRemote, private cThread
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
cMutex mutex;
|
||||||
|
cCondVar keyReceived;
|
||||||
|
cString Command;
|
||||||
|
virtual void Action(void);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Soft device remote class constructor.
|
** Soft device remote class constructor.
|
||||||
**
|
**
|
||||||
** @param name remote name
|
** @param name remote name
|
||||||
*/
|
*/
|
||||||
cSoftRemote(const char *name):cRemote(name)
|
cSoftRemote(void) : cRemote("XKeySym")
|
||||||
{
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~cSoftRemote()
|
||||||
|
{
|
||||||
|
Cancel(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Put keycode into vdr event queue.
|
** Receive keycode.
|
||||||
**
|
**
|
||||||
** @param code key code
|
** @param code key code
|
||||||
** @param repeat flag key repeated
|
|
||||||
** @param release flag key released
|
|
||||||
*/
|
*/
|
||||||
bool Put(const char *code, bool repeat = false, bool release = false) {
|
void Receive(const char *code) {
|
||||||
return cRemote::Put(code, repeat, release);
|
cMutexLock MutexLock(&mutex);
|
||||||
|
Command = code;
|
||||||
|
keyReceived.Broadcast();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void cSoftRemote::Action(void)
|
||||||
|
{
|
||||||
|
// see also VDR's cKbdRemote::Action()
|
||||||
|
cTimeMs FirstTime;
|
||||||
|
cTimeMs LastTime;
|
||||||
|
cString FirstCommand = "";
|
||||||
|
cString LastCommand = "";
|
||||||
|
bool Delayed = false;
|
||||||
|
bool Repeat = false;
|
||||||
|
|
||||||
|
while (Running()) {
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
if (keyReceived.TimedWait(mutex, Setup.RcRepeatDelta * 3 / 2) && **Command) {
|
||||||
|
if (strcmp(Command, LastCommand) == 0) {
|
||||||
|
// If two keyboard events with the same command come in without an intermediate
|
||||||
|
// timeout, this is a long key press that caused the repeat function to kick in:
|
||||||
|
Delayed = false;
|
||||||
|
FirstCommand = "";
|
||||||
|
if (FirstTime.Elapsed() < (uint)Setup.RcRepeatDelay)
|
||||||
|
continue; // repeat function kicks in after a short delay
|
||||||
|
if (LastTime.Elapsed() < (uint)Setup.RcRepeatDelta)
|
||||||
|
continue; // skip same keys coming in too fast
|
||||||
|
cRemote::Put(Command, true);
|
||||||
|
Repeat = true;
|
||||||
|
LastTime.Set();
|
||||||
|
}
|
||||||
|
else if (strcmp(Command, FirstCommand) == 0) {
|
||||||
|
// If the same command comes in twice with an intermediate timeout, we
|
||||||
|
// need to delay the second command to see whether it is going to be
|
||||||
|
// a repeat function or a separate key press:
|
||||||
|
Delayed = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This is a totally new key press, so we accept it immediately:
|
||||||
|
cRemote::Put(Command);
|
||||||
|
Delayed = false;
|
||||||
|
FirstCommand = Command;
|
||||||
|
FirstTime.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Repeat) {
|
||||||
|
// Timeout after a repeat function, so we generate a 'release':
|
||||||
|
cRemote::Put(LastCommand, false, true);
|
||||||
|
Repeat = false;
|
||||||
|
}
|
||||||
|
else if (Delayed && *FirstCommand) {
|
||||||
|
// Timeout after two normal key presses of the same key, so accept the
|
||||||
|
// delayed key:
|
||||||
|
cRemote::Put(FirstCommand);
|
||||||
|
Delayed = false;
|
||||||
|
FirstCommand = "";
|
||||||
|
FirstTime.Set();
|
||||||
|
}
|
||||||
|
else if (**FirstCommand && FirstTime.Elapsed() > (uint)Setup.RcRepeatDelay) {
|
||||||
|
Delayed = false;
|
||||||
|
FirstCommand = "";
|
||||||
|
FirstTime.Set();
|
||||||
|
}
|
||||||
|
LastCommand = Command;
|
||||||
|
Command = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static cSoftRemote *csoft = NULL;
|
||||||
/**
|
/**
|
||||||
** Feed key press as remote input (called from C part).
|
** Feed key press as remote input (called from C part).
|
||||||
**
|
**
|
||||||
** @param keymap target keymap "XKeymap" name
|
** @param keymap target keymap "XKeymap" name (obsolete, ignored)
|
||||||
** @param key pressed/released key name
|
** @param key pressed/released key name
|
||||||
** @param repeat repeated key flag
|
** @param repeat repeated key flag (obsolete, ignored)
|
||||||
** @param release released key flag
|
** @param release released key flag (obsolete, ignored)
|
||||||
** @param letter x11 character string (system setting locale)
|
** @param letter x11 character string (system setting locale)
|
||||||
*/
|
*/
|
||||||
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat, int release, const char *letter)
|
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat, int release, const char *letter)
|
||||||
{
|
{
|
||||||
cRemote *remote;
|
if (!csoft || !keymap || !key) {
|
||||||
cSoftRemote *csoft;
|
return;
|
||||||
|
|
||||||
if (!keymap || !key) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// find remote
|
|
||||||
for (remote = Remotes.First(); remote; remote = Remotes.Next(remote)) {
|
|
||||||
if (!strcmp(remote->Name(), keymap)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if remote not already exists, create it
|
|
||||||
if (remote) {
|
|
||||||
csoft = (cSoftRemote *) remote;
|
|
||||||
} else {
|
|
||||||
dsyslog("[softhddev]%s: remote '%s' not found\n", __FUNCTION__, keymap);
|
|
||||||
csoft = new cSoftRemote(keymap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter);
|
csoft->Receive(key);
|
||||||
if (key[1]) { // no single character
|
|
||||||
if (!csoft->Put(key, repeat, release) && letter && !cRemote::IsLearning()) {
|
|
||||||
cCharSetConv conv;
|
|
||||||
unsigned code;
|
|
||||||
|
|
||||||
code = Utf8CharGet(conv.Convert(letter));
|
|
||||||
if (code <= 0xFF) {
|
|
||||||
cRemote::Put(KBDKEY(code)); // feed it for edit mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!csoft->Put(key, repeat, release)) {
|
|
||||||
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -3068,6 +3115,8 @@ bool cPluginSoftHdDevice::Start(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
csoft = new cSoftRemote;
|
||||||
|
|
||||||
switch (::Start()) {
|
switch (::Start()) {
|
||||||
case 1:
|
case 1:
|
||||||
//cControl::Launch(new cSoftHdControl);
|
//cControl::Launch(new cSoftHdControl);
|
||||||
@ -3095,6 +3144,8 @@ void cPluginSoftHdDevice::Stop(void)
|
|||||||
// dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
// dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||||
|
|
||||||
::Stop();
|
::Stop();
|
||||||
|
delete csoft;
|
||||||
|
csoft = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user