vdr
1.7.27
|
00001 /* 00002 * keys.c: Remote control Key handling 00003 * 00004 * See the main source file 'vdr.c' for copyright information and 00005 * how to reach the author. 00006 * 00007 * $Id: keys.c 2.1 2010/04/05 10:05:58 kls Exp $ 00008 */ 00009 00010 #include "keys.h" 00011 #include "plugin.h" 00012 00013 static tKey keyTable[] = { // "Up" and "Down" must be the first two keys! 00014 { kUp, trNOOP("Key$Up") }, 00015 { kDown, trNOOP("Key$Down") }, 00016 { kMenu, trNOOP("Key$Menu") }, 00017 { kOk, trNOOP("Key$Ok") }, 00018 { kBack, trNOOP("Key$Back") }, 00019 { kLeft, trNOOP("Key$Left") }, 00020 { kRight, trNOOP("Key$Right") }, 00021 { kRed, trNOOP("Key$Red") }, 00022 { kGreen, trNOOP("Key$Green") }, 00023 { kYellow, trNOOP("Key$Yellow") }, 00024 { kBlue, trNOOP("Key$Blue") }, 00025 { k0, "0" }, 00026 { k1, "1" }, 00027 { k2, "2" }, 00028 { k3, "3" }, 00029 { k4, "4" }, 00030 { k5, "5" }, 00031 { k6, "6" }, 00032 { k7, "7" }, 00033 { k8, "8" }, 00034 { k9, "9" }, 00035 { kInfo, trNOOP("Key$Info") }, 00036 { kPlay, trNOOP("Key$Play") }, 00037 { kPause, trNOOP("Key$Pause") }, 00038 { kStop, trNOOP("Key$Stop") }, 00039 { kRecord, trNOOP("Key$Record") }, 00040 { kFastFwd, trNOOP("Key$FastFwd") }, 00041 { kFastRew, trNOOP("Key$FastRew") }, 00042 { kNext, trNOOP("Key$Next") }, 00043 { kPrev, trNOOP("Key$Prev") }, 00044 { kPower, trNOOP("Key$Power") }, 00045 { kChanUp, trNOOP("Key$Channel+") }, 00046 { kChanDn, trNOOP("Key$Channel-") }, 00047 { kChanPrev, trNOOP("Key$PrevChannel") }, 00048 { kVolUp, trNOOP("Key$Volume+") }, 00049 { kVolDn, trNOOP("Key$Volume-") }, 00050 { kMute, trNOOP("Key$Mute") }, 00051 { kAudio, trNOOP("Key$Audio") }, 00052 { kSubtitles, trNOOP("Key$Subtitles") }, 00053 { kSchedule, trNOOP("Key$Schedule") }, 00054 { kChannels, trNOOP("Key$Channels") }, 00055 { kTimers, trNOOP("Key$Timers") }, 00056 { kRecordings, trNOOP("Key$Recordings") }, 00057 { kSetup, trNOOP("Key$Setup") }, 00058 { kCommands, trNOOP("Key$Commands") }, 00059 { kUser0, trNOOP("Key$User0") }, 00060 { kUser1, trNOOP("Key$User1") }, 00061 { kUser2, trNOOP("Key$User2") }, 00062 { kUser3, trNOOP("Key$User3") }, 00063 { kUser4, trNOOP("Key$User4") }, 00064 { kUser5, trNOOP("Key$User5") }, 00065 { kUser6, trNOOP("Key$User6") }, 00066 { kUser7, trNOOP("Key$User7") }, 00067 { kUser8, trNOOP("Key$User8") }, 00068 { kUser9, trNOOP("Key$User9") }, 00069 { kNone, "" }, 00070 { k_Setup, "_Setup" }, 00071 { kNone, NULL }, 00072 }; 00073 00074 // --- cKey ------------------------------------------------------------------ 00075 00076 cKey::cKey(void) 00077 { 00078 remote = code = NULL; 00079 key = kNone; 00080 } 00081 00082 cKey::cKey(const char *Remote, const char *Code, eKeys Key) 00083 { 00084 remote = strdup(Remote); 00085 code = strdup(Code); 00086 key = Key; 00087 } 00088 00089 cKey::~cKey() 00090 { 00091 free(remote); 00092 free(code); 00093 } 00094 00095 bool cKey::Parse(char *s) 00096 { 00097 char *p = strchr(s, '.'); 00098 if (p) { 00099 *p++ = 0; 00100 remote = strdup(s); 00101 char *q = strpbrk(p, " \t"); 00102 if (q) { 00103 *q++ = 0; 00104 key = FromString(p); 00105 if (key != kNone) { 00106 q = skipspace(q); 00107 if (*q) { 00108 code = strdup(q); 00109 return true; 00110 } 00111 } 00112 } 00113 } 00114 return false; 00115 } 00116 00117 bool cKey::Save(FILE *f) 00118 { 00119 return fprintf(f, "%s.%-10s %s\n", remote, ToString(key), code) > 0; 00120 } 00121 00122 eKeys cKey::FromString(const char *Name) 00123 { 00124 if (Name) { 00125 for (tKey *k = keyTable; k->name; k++) { 00126 const char *n = k->name; 00127 const char *p = strchr(n, '$'); 00128 if (p) 00129 n = p + 1; 00130 if (strcasecmp(n, Name) == 0) 00131 return k->type; 00132 } 00133 } 00134 return kNone; 00135 } 00136 00137 const char *cKey::ToString(eKeys Key, bool Translate) 00138 { 00139 for (tKey *k = keyTable; k->name; k++) { 00140 if (k->type == Key) { 00141 const char *n = k->name; 00142 if (Translate) 00143 n = tr(n); 00144 const char *p = strchr(n, '$'); 00145 if (p) 00146 n = p + 1; 00147 return n; 00148 } 00149 } 00150 return NULL; 00151 } 00152 00153 // --- cKeys ----------------------------------------------------------------- 00154 00155 cKeys Keys; 00156 00157 bool cKeys::KnowsRemote(const char *Remote) 00158 { 00159 if (Remote) { 00160 for (cKey *k = First(); k; k = Next(k)) { 00161 if (strcmp(Remote, k->Remote()) == 0) 00162 return true; 00163 } 00164 } 00165 return false; 00166 } 00167 00168 eKeys cKeys::Get(const char *Remote, const char *Code) 00169 { 00170 if (Remote && Code) { 00171 for (cKey *k = First(); k; k = Next(k)) { 00172 if (strcmp(Remote, k->Remote()) == 0 && strcmp(Code, k->Code()) == 0) 00173 return k->Key(); 00174 } 00175 } 00176 return kNone; 00177 } 00178 00179 const char *cKeys::GetSetup(const char *Remote) 00180 { 00181 if (Remote) { 00182 for (cKey *k = First(); k; k = Next(k)) { 00183 if (strcmp(Remote, k->Remote()) == 0 && k->Key() == k_Setup) 00184 return k->Code(); 00185 } 00186 } 00187 return NULL; 00188 } 00189 00190 void cKeys::PutSetup(const char *Remote, const char *Setup) 00191 { 00192 if (!GetSetup(Remote)) 00193 Add(new cKey(Remote, Setup, k_Setup)); 00194 else 00195 esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote); 00196 } 00197 00198 // --- cKeyMacro ------------------------------------------------------------- 00199 00200 cKeyMacro::cKeyMacro(void) 00201 { 00202 numKeys = 0; 00203 for (int i = 0; i < MAXKEYSINMACRO; i++) 00204 macro[i] = kNone; // for compatibility with old code that doesn't know about NumKeys() 00205 plugin = NULL; 00206 } 00207 00208 cKeyMacro::~cKeyMacro() 00209 { 00210 free(plugin); 00211 } 00212 00213 bool cKeyMacro::Parse(char *s) 00214 { 00215 int n = 0; 00216 char *p; 00217 char *strtok_next; 00218 while ((p = strtok_r(s, " \t", &strtok_next)) != NULL) { 00219 if (n < MAXKEYSINMACRO) { 00220 if (*p == '@') { 00221 if (plugin) { 00222 esyslog("ERROR: only one @plugin allowed per macro"); 00223 return false; 00224 } 00225 if (!n) { 00226 esyslog("ERROR: @plugin can't be first in macro"); 00227 return false; 00228 } 00229 macro[n] = k_Plugin; 00230 if (n < MAXKEYSINMACRO) { 00231 plugin = strdup(p + 1); 00232 if (!cPluginManager::GetPlugin(plugin)) { 00233 esyslog("ERROR: unknown plugin '%s'", plugin); 00234 // this is not a fatal error - plugins may or may not be loaded 00235 macro[--n] = kNone; // makes sure the key doesn't cause any side effects 00236 } 00237 } 00238 else { 00239 esyslog("ERROR: key macro too long"); 00240 return false; 00241 } 00242 } 00243 else { 00244 macro[n] = cKey::FromString(p); 00245 if (macro[n] == kNone) { 00246 esyslog("ERROR: unknown key '%s'", p); 00247 return false; 00248 } 00249 } 00250 n++; 00251 s = NULL; 00252 } 00253 else { 00254 esyslog("ERROR: key macro too long"); 00255 return false; 00256 } 00257 } 00258 if (n < 2) 00259 esyslog("ERROR: empty key macro"); // non fatal 00260 numKeys = n; 00261 return true; 00262 } 00263 00264 // --- cKeyMacros ------------------------------------------------------------ 00265 00266 cKeyMacros KeyMacros; 00267 00268 const cKeyMacro *cKeyMacros::Get(eKeys Key) 00269 { 00270 if (Key != kNone) { 00271 for (cKeyMacro *k = First(); k; k = Next(k)) { 00272 if (*k->Macro() == Key) 00273 return k; 00274 } 00275 } 00276 return NULL; 00277 }