vdr  2.2.0
keys.c
Go to the documentation of this file.
1 /*
2  * keys.c: Remote control Key handling
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: keys.c 3.0 2012/12/04 12:52:52 kls Exp $
8  */
9 
10 #include "keys.h"
11 #include "plugin.h"
12 
13 static tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
14  { kUp, trNOOP("Key$Up") },
15  { kDown, trNOOP("Key$Down") },
16  { kMenu, trNOOP("Key$Menu") },
17  { kOk, trNOOP("Key$Ok") },
18  { kBack, trNOOP("Key$Back") },
19  { kLeft, trNOOP("Key$Left") },
20  { kRight, trNOOP("Key$Right") },
21  { kRed, trNOOP("Key$Red") },
22  { kGreen, trNOOP("Key$Green") },
23  { kYellow, trNOOP("Key$Yellow") },
24  { kBlue, trNOOP("Key$Blue") },
25  { k0, "0" },
26  { k1, "1" },
27  { k2, "2" },
28  { k3, "3" },
29  { k4, "4" },
30  { k5, "5" },
31  { k6, "6" },
32  { k7, "7" },
33  { k8, "8" },
34  { k9, "9" },
35  { kInfo, trNOOP("Key$Info") },
36  { kPlayPause, trNOOP("Key$Play/Pause") },
37  { kPlay, trNOOP("Key$Play") },
38  { kPause, trNOOP("Key$Pause") },
39  { kStop, trNOOP("Key$Stop") },
40  { kRecord, trNOOP("Key$Record") },
41  { kFastFwd, trNOOP("Key$FastFwd") },
42  { kFastRew, trNOOP("Key$FastRew") },
43  { kNext, trNOOP("Key$Next") },
44  { kPrev, trNOOP("Key$Prev") },
45  { kPower, trNOOP("Key$Power") },
46  { kChanUp, trNOOP("Key$Channel+") },
47  { kChanDn, trNOOP("Key$Channel-") },
48  { kChanPrev, trNOOP("Key$PrevChannel") },
49  { kVolUp, trNOOP("Key$Volume+") },
50  { kVolDn, trNOOP("Key$Volume-") },
51  { kMute, trNOOP("Key$Mute") },
52  { kAudio, trNOOP("Key$Audio") },
53  { kSubtitles, trNOOP("Key$Subtitles") },
54  { kSchedule, trNOOP("Key$Schedule") },
55  { kChannels, trNOOP("Key$Channels") },
56  { kTimers, trNOOP("Key$Timers") },
57  { kRecordings, trNOOP("Key$Recordings") },
58  { kSetup, trNOOP("Key$Setup") },
59  { kCommands, trNOOP("Key$Commands") },
60  { kUser0, trNOOP("Key$User0") },
61  { kUser1, trNOOP("Key$User1") },
62  { kUser2, trNOOP("Key$User2") },
63  { kUser3, trNOOP("Key$User3") },
64  { kUser4, trNOOP("Key$User4") },
65  { kUser5, trNOOP("Key$User5") },
66  { kUser6, trNOOP("Key$User6") },
67  { kUser7, trNOOP("Key$User7") },
68  { kUser8, trNOOP("Key$User8") },
69  { kUser9, trNOOP("Key$User9") },
70  { kNone, "" },
71  { k_Setup, "_Setup" },
72  { kNone, NULL },
73  };
74 
75 // --- cKey ------------------------------------------------------------------
76 
78 {
79  remote = code = NULL;
80  key = kNone;
81 }
82 
83 cKey::cKey(const char *Remote, const char *Code, eKeys Key)
84 {
85  remote = strdup(Remote);
86  code = strdup(Code);
87  key = Key;
88 }
89 
91 {
92  free(remote);
93  free(code);
94 }
95 
96 bool cKey::Parse(char *s)
97 {
98  char *p = strchr(s, '.');
99  if (p) {
100  *p++ = 0;
101  remote = strdup(s);
102  char *q = strpbrk(p, " \t");
103  if (q) {
104  *q++ = 0;
105  key = FromString(p);
106  if (key != kNone) {
107  q = skipspace(q);
108  if (*q) {
109  code = strdup(q);
110  return true;
111  }
112  }
113  }
114  }
115  return false;
116 }
117 
118 bool cKey::Save(FILE *f)
119 {
120  return fprintf(f, "%s.%-10s %s\n", remote, ToString(key), code) > 0;
121 }
122 
123 eKeys cKey::FromString(const char *Name)
124 {
125  if (Name) {
126  for (tKey *k = keyTable; k->name; k++) {
127  const char *n = k->name;
128  const char *p = strchr(n, '$');
129  if (p)
130  n = p + 1;
131  if (strcasecmp(n, Name) == 0)
132  return k->type;
133  }
134  }
135  return kNone;
136 }
137 
138 const char *cKey::ToString(eKeys Key, bool Translate)
139 {
140  for (tKey *k = keyTable; k->name; k++) {
141  if (k->type == Key) {
142  const char *n = k->name;
143  if (Translate)
144  n = tr(n);
145  const char *p = strchr(n, '$');
146  if (p)
147  n = p + 1;
148  return n;
149  }
150  }
151  return NULL;
152 }
153 
154 // --- cKeys -----------------------------------------------------------------
155 
157 
158 bool cKeys::KnowsRemote(const char *Remote)
159 {
160  if (Remote) {
161  for (cKey *k = First(); k; k = Next(k)) {
162  if (strcmp(Remote, k->Remote()) == 0)
163  return true;
164  }
165  }
166  return false;
167 }
168 
169 eKeys cKeys::Get(const char *Remote, const char *Code)
170 {
171  if (Remote && Code) {
172  for (cKey *k = First(); k; k = Next(k)) {
173  if (strcmp(Remote, k->Remote()) == 0 && strcmp(Code, k->Code()) == 0)
174  return k->Key();
175  }
176  }
177  return kNone;
178 }
179 
180 const char *cKeys::GetSetup(const char *Remote)
181 {
182  if (Remote) {
183  for (cKey *k = First(); k; k = Next(k)) {
184  if (strcmp(Remote, k->Remote()) == 0 && k->Key() == k_Setup)
185  return k->Code();
186  }
187  }
188  return NULL;
189 }
190 
191 void cKeys::PutSetup(const char *Remote, const char *Setup)
192 {
193  if (!GetSetup(Remote))
194  Add(new cKey(Remote, Setup, k_Setup));
195  else
196  esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote);
197 }
198 
199 // --- cKeyMacro -------------------------------------------------------------
200 
202 {
203  numKeys = 0;
204  for (int i = 0; i < MAXKEYSINMACRO; i++)
205  macro[i] = kNone; // for compatibility with old code that doesn't know about NumKeys()
206  plugin = NULL;
207 }
208 
210 {
211  free(plugin);
212 }
213 
214 bool cKeyMacro::Parse(char *s)
215 {
216  int n = 0;
217  char *p;
218  char *strtok_next;
219  while ((p = strtok_r(s, " \t", &strtok_next)) != NULL) {
220  if (n < MAXKEYSINMACRO) {
221  if (*p == '@') {
222  if (plugin) {
223  esyslog("ERROR: only one @plugin allowed per macro");
224  return false;
225  }
226  if (!n) {
227  esyslog("ERROR: @plugin can't be first in macro");
228  return false;
229  }
230  macro[n] = k_Plugin;
231  if (n < MAXKEYSINMACRO) {
232  plugin = strdup(p + 1);
233  if (!cPluginManager::GetPlugin(plugin)) {
234  esyslog("ERROR: unknown plugin '%s'", plugin);
235  // this is not a fatal error - plugins may or may not be loaded
236  macro[--n] = kNone; // makes sure the key doesn't cause any side effects
237  }
238  }
239  else {
240  esyslog("ERROR: key macro too long");
241  return false;
242  }
243  }
244  else {
245  macro[n] = cKey::FromString(p);
246  if (macro[n] == kNone) {
247  esyslog("ERROR: unknown key '%s'", p);
248  return false;
249  }
250  }
251  n++;
252  s = NULL;
253  }
254  else {
255  esyslog("ERROR: key macro too long");
256  return false;
257  }
258  }
259  if (n < 2)
260  esyslog("ERROR: empty key macro"); // non fatal
261  numKeys = n;
262  return true;
263 }
264 
265 // --- cKeyMacros ------------------------------------------------------------
266 
268 
270 {
271  if (Key != kNone) {
272  for (cKeyMacro *k = First(); k; k = Next(k)) {
273  if (*k->Macro() == Key)
274  return k;
275  }
276  }
277  return NULL;
278 }
Definition: keys.h:29
bool Parse(char *s)
Definition: keys.c:96
bool Parse(char *s)
Definition: keys.c:214
Definition: keys.h:28
Definition: keys.h:37
bool KnowsRemote(const char *Remote)
Definition: keys.c:158
Definition: keys.h:34
const char * name
Definition: keys.h:89
Definition: keys.h:92
Definition: keys.h:23
Definition: keys.h:19
eKeys Key(void)
Definition: keys.h:103
Definition: keys.h:43
Definition: keys.h:28
Definition: keys.h:39
Definition: keys.h:46
Definition: keys.h:87
Definition: keys.h:28
static eKeys FromString(const char *Name)
Definition: keys.c:123
char * remote
Definition: keys.h:94
Definition: keys.h:17
#define esyslog(a...)
Definition: tools.h:34
Definition: keys.h:28
Definition: keys.h:54
Definition: keys.h:59
Definition: keys.h:33
bool Save(FILE *f)
Definition: keys.c:118
Definition: keys.h:49
Definition: keys.h:27
cKey(void)
Definition: keys.c:77
void PutSetup(const char *Remote, const char *Setup)
Definition: keys.c:191
Definition: keys.h:25
Definition: keys.h:54
Definition: keys.h:38
Definition: keys.h:36
Definition: keys.h:54
Definition: keys.h:55
Definition: keys.h:58
Definition: keys.h:28
char * code
Definition: keys.h:95
Definition: keys.h:54
#define trNOOP(s)
Definition: i18n.h:88
Definition: keys.h:40
eKeys Get(const char *Remote, const char *Code)
Definition: keys.c:169
Definition: keys.h:44
cKeyMacro(void)
Definition: keys.c:201
cListObject * Next(void) const
Definition: tools.h:468
Definition: keys.h:54
Definition: keys.h:48
Definition: keys.h:54
const cKeyMacro * Get(eKeys Key)
Definition: keys.c:269
~cKey()
Definition: keys.c:90
Definition: keys.h:18
cKeys Keys
Definition: keys.c:156
Definition: keys.h:50
Definition: keys.h:52
Definition: keys.h:28
cSetup Setup
Definition: config.c:373
Definition: keys.h:20
Definition: keys.h:26
Definition: keys.h:45
#define MAXKEYSINMACRO
Definition: keys.h:120
static tKey keyTable[]
Definition: keys.c:13
~cKeyMacro()
Definition: keys.c:209
Definition: keys.h:21
Definition: keys.h:110
Definition: keys.h:35
Definition: keys.h:54
cKeyMacros KeyMacros
Definition: keys.c:267
Definition: keys.h:54
const char * Code(void)
Definition: keys.h:102
#define tr(s)
Definition: i18n.h:85
char * skipspace(const char *s)
Definition: tools.h:200
Definition: keys.h:42
static cPlugin * GetPlugin(int Index)
Definition: plugin.c:457
Definition: keys.h:32
Definition: keys.h:31
Definition: keys.h:28
const char * Remote(void)
Definition: keys.h:101
Definition: keys.h:24
Definition: keys.h:54
Definition: keys.h:28
Definition: keys.h:53
Definition: keys.h:54
const char * GetSetup(const char *Remote)
Definition: keys.c:180
eKeys
Definition: keys.h:16
eKeys key
Definition: keys.h:96
static const char * ToString(eKeys Key, bool Translate=false)
Definition: keys.c:138
Definition: keys.h:28
Definition: keys.h:41
Definition: keys.h:28
Definition: keys.h:22