-
Notifications
You must be signed in to change notification settings - Fork 2
/
remote.cpp
162 lines (146 loc) · 4.47 KB
/
remote.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//////////////////////////////////////////////////////////////////////////////
/// ///
/// This file is part of the VDR mpv plugin and licensed under AGPLv3 ///
/// ///
/// See the README file for copyright information ///
/// ///
//////////////////////////////////////////////////////////////////////////////
#include <vdr/interface.h>
#include <vdr/plugin.h>
#include <vdr/player.h>
extern "C"
{
#include <stdint.h>
}
/**
** remote class.
*/
class cSoftRemote:public cRemote, private cThread
{
private:
cMutex mutex;
cCondVar keyReceived;
cString Command;
virtual void Action(void);
public:
/**
** Soft device remote class constructor.
**
** @param name remote name
*/
cSoftRemote(void) : cRemote("XKeySym")
{
Start();
}
virtual ~cSoftRemote()
{
Cancel(3);
}
/**
** Receive keycode.
**
** @param code key code
*/
void Receive(const char *code) {
cMutexLock MutexLock(&mutex);
Command = code;
keyReceived.Broadcast();
}
void Transfer(eKeys key) {
cRemote::Put(key, true);
}
};
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).
**
** @param keymap<->target keymap "XKeymap" name (obsolete, ignored)
** @param key pressed/released key name
** @param repeat repeated key flag (obsolete, ignored)
** @param release released key flag (obsolete, ignored)
** @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)
{
if (!csoft || !keymap || !key) {
return;
}
if (!letter) {
csoft->Transfer(cKey::FromString(key));
return;
}
csoft->Receive(key);
}
extern "C" void RemoteStart()
{
csoft = new cSoftRemote;
}
extern "C" void RemoteStop()
{
if (csoft) {
delete csoft;
csoft = NULL;
}
}