vdr  1.7.31
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 2.1 2010/04/05 10:05:58 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  { kPlay, trNOOP("Key$Play") },
37  { kPause, trNOOP("Key$Pause") },
38  { kStop, trNOOP("Key$Stop") },
39  { kRecord, trNOOP("Key$Record") },
40  { kFastFwd, trNOOP("Key$FastFwd") },
41  { kFastRew, trNOOP("Key$FastRew") },
42  { kNext, trNOOP("Key$Next") },
43  { kPrev, trNOOP("Key$Prev") },
44  { kPower, trNOOP("Key$Power") },
45  { kChanUp, trNOOP("Key$Channel+") },
46  { kChanDn, trNOOP("Key$Channel-") },
47  { kChanPrev, trNOOP("Key$PrevChannel") },
48  { kVolUp, trNOOP("Key$Volume+") },
49  { kVolDn, trNOOP("Key$Volume-") },
50  { kMute, trNOOP("Key$Mute") },
51  { kAudio, trNOOP("Key$Audio") },
52  { kSubtitles, trNOOP("Key$Subtitles") },
53  { kSchedule, trNOOP("Key$Schedule") },
54  { kChannels, trNOOP("Key$Channels") },
55  { kTimers, trNOOP("Key$Timers") },
56  { kRecordings, trNOOP("Key$Recordings") },
57  { kSetup, trNOOP("Key$Setup") },
58  { kCommands, trNOOP("Key$Commands") },
59  { kUser0, trNOOP("Key$User0") },
60  { kUser1, trNOOP("Key$User1") },
61  { kUser2, trNOOP("Key$User2") },
62  { kUser3, trNOOP("Key$User3") },
63  { kUser4, trNOOP("Key$User4") },
64  { kUser5, trNOOP("Key$User5") },
65  { kUser6, trNOOP("Key$User6") },
66  { kUser7, trNOOP("Key$User7") },
67  { kUser8, trNOOP("Key$User8") },
68  { kUser9, trNOOP("Key$User9") },
69  { kNone, "" },
70  { k_Setup, "_Setup" },
71  { kNone, NULL },
72  };
73 
74 // --- cKey ------------------------------------------------------------------
75 
77 {
78  remote = code = NULL;
79  key = kNone;
80 }
81 
82 cKey::cKey(const char *Remote, const char *Code, eKeys Key)
83 {
84  remote = strdup(Remote);
85  code = strdup(Code);
86  key = Key;
87 }
88 
90 {
91  free(remote);
92  free(code);
93 }
94 
95 bool cKey::Parse(char *s)
96 {
97  char *p = strchr(s, '.');
98  if (p) {
99  *p++ = 0;
100  remote = strdup(s);
101  char *q = strpbrk(p, " \t");
102  if (q) {
103  *q++ = 0;
104  key = FromString(p);
105  if (key != kNone) {
106  q = skipspace(q);
107  if (*q) {
108  code = strdup(q);
109  return true;
110  }
111  }
112  }
113  }
114  return false;
115 }
116 
117 bool cKey::Save(FILE *f)
118 {
119  return fprintf(f, "%s.%-10s %s\n", remote, ToString(key), code) > 0;
120 }
121 
122 eKeys cKey::FromString(const char *Name)
123 {
124  if (Name) {
125  for (tKey *k = keyTable; k->name; k++) {
126  const char *n = k->name;
127  const char *p = strchr(n, '$');
128  if (p)
129  n = p + 1;
130  if (strcasecmp(n, Name) == 0)
131  return k->type;
132  }
133  }
134  return kNone;
135 }
136 
137 const char *cKey::ToString(eKeys Key, bool Translate)
138 {
139  for (tKey *k = keyTable; k->name; k++) {
140  if (k->type == Key) {
141  const char *n = k->name;
142  if (Translate)
143  n = tr(n);
144  const char *p = strchr(n, '$');
145  if (p)
146  n = p + 1;
147  return n;
148  }
149  }
150  return NULL;
151 }
152 
153 // --- cKeys -----------------------------------------------------------------
154 
156 
157 bool cKeys::KnowsRemote(const char *Remote)
158 {
159  if (Remote) {
160  for (cKey *k = First(); k; k = Next(k)) {
161  if (strcmp(Remote, k->Remote()) == 0)
162  return true;
163  }
164  }
165  return false;
166 }
167 
168 eKeys cKeys::Get(const char *Remote, const char *Code)
169 {
170  if (Remote && Code) {
171  for (cKey *k = First(); k; k = Next(k)) {
172  if (strcmp(Remote, k->Remote()) == 0 && strcmp(Code, k->Code()) == 0)
173  return k->Key();
174  }
175  }
176  return kNone;
177 }
178 
179 const char *cKeys::GetSetup(const char *Remote)
180 {
181  if (Remote) {
182  for (cKey *k = First(); k; k = Next(k)) {
183  if (strcmp(Remote, k->Remote()) == 0 && k->Key() == k_Setup)
184  return k->Code();
185  }
186  }
187  return NULL;
188 }
189 
190 void cKeys::PutSetup(const char *Remote, const char *Setup)
191 {
192  if (!GetSetup(Remote))
193  Add(new cKey(Remote, Setup, k_Setup));
194  else
195  esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote);
196 }
197 
198 // --- cKeyMacro -------------------------------------------------------------
199 
201 {
202  numKeys = 0;
203  for (int i = 0; i < MAXKEYSINMACRO; i++)
204  macro[i] = kNone; // for compatibility with old code that doesn't know about NumKeys()
205  plugin = NULL;
206 }
207 
209 {
210  free(plugin);
211 }
212 
213 bool cKeyMacro::Parse(char *s)
214 {
215  int n = 0;
216  char *p;
217  char *strtok_next;
218  while ((p = strtok_r(s, " \t", &strtok_next)) != NULL) {
219  if (n < MAXKEYSINMACRO) {
220  if (*p == '@') {
221  if (plugin) {
222  esyslog("ERROR: only one @plugin allowed per macro");
223  return false;
224  }
225  if (!n) {
226  esyslog("ERROR: @plugin can't be first in macro");
227  return false;
228  }
229  macro[n] = k_Plugin;
230  if (n < MAXKEYSINMACRO) {
231  plugin = strdup(p + 1);
233  esyslog("ERROR: unknown plugin '%s'", plugin);
234  // this is not a fatal error - plugins may or may not be loaded
235  macro[--n] = kNone; // makes sure the key doesn't cause any side effects
236  }
237  }
238  else {
239  esyslog("ERROR: key macro too long");
240  return false;
241  }
242  }
243  else {
244  macro[n] = cKey::FromString(p);
245  if (macro[n] == kNone) {
246  esyslog("ERROR: unknown key '%s'", p);
247  return false;
248  }
249  }
250  n++;
251  s = NULL;
252  }
253  else {
254  esyslog("ERROR: key macro too long");
255  return false;
256  }
257  }
258  if (n < 2)
259  esyslog("ERROR: empty key macro"); // non fatal
260  numKeys = n;
261  return true;
262 }
263 
264 // --- cKeyMacros ------------------------------------------------------------
265 
267 
269 {
270  if (Key != kNone) {
271  for (cKeyMacro *k = First(); k; k = Next(k)) {
272  if (*k->Macro() == Key)
273  return k;
274  }
275  }
276  return NULL;
277 }