/* * keys.c: Remote control Key handling * * See the main source file 'vdr.c' for copyright information and * how to reach the author. * * $Id: keys.c 2.2 2012/12/04 12:52:52 kls Exp $ */ #include "keys.h" #include "plugin.h" static tKey keyTable[] = { // "Up" and "Down" must be the first two keys! { kUp, trNOOP("Key$Up") }, { kDown, trNOOP("Key$Down") }, { kMenu, trNOOP("Key$Menu") }, { kOk, trNOOP("Key$Ok") }, { kBack, trNOOP("Key$Back") }, { kLeft, trNOOP("Key$Left") }, { kRight, trNOOP("Key$Right") }, { kRed, trNOOP("Key$Red") }, { kGreen, trNOOP("Key$Green") }, { kYellow, trNOOP("Key$Yellow") }, { kBlue, trNOOP("Key$Blue") }, { k0, "0" }, { k1, "1" }, { k2, "2" }, { k3, "3" }, { k4, "4" }, { k5, "5" }, { k6, "6" }, { k7, "7" }, { k8, "8" }, { k9, "9" }, { kInfo, trNOOP("Key$Info") }, { kPlayPause, trNOOP("Key$Play/Pause") }, { kPlay, trNOOP("Key$Play") }, { kPause, trNOOP("Key$Pause") }, { kStop, trNOOP("Key$Stop") }, { kRecord, trNOOP("Key$Record") }, { kFastFwd, trNOOP("Key$FastFwd") }, { kFastRew, trNOOP("Key$FastRew") }, { kNext, trNOOP("Key$Next") }, { kPrev, trNOOP("Key$Prev") }, { kPower, trNOOP("Key$Power") }, { kChanUp, trNOOP("Key$Channel+") }, { kChanDn, trNOOP("Key$Channel-") }, { kChanPrev, trNOOP("Key$PrevChannel") }, { kVolUp, trNOOP("Key$Volume+") }, { kVolDn, trNOOP("Key$Volume-") }, { kMute, trNOOP("Key$Mute") }, { kAudio, trNOOP("Key$Audio") }, { kSubtitles, trNOOP("Key$Subtitles") }, { kSchedule, trNOOP("Key$Schedule") }, { kChannels, trNOOP("Key$Channels") }, { kTimers, trNOOP("Key$Timers") }, { kRecordings, trNOOP("Key$Recordings") }, { kSetup, trNOOP("Key$Setup") }, { kCommands, trNOOP("Key$Commands") }, { kUser0, trNOOP("Key$User0") }, { kUser1, trNOOP("Key$User1") }, { kUser2, trNOOP("Key$User2") }, { kUser3, trNOOP("Key$User3") }, { kUser4, trNOOP("Key$User4") }, { kUser5, trNOOP("Key$User5") }, { kUser6, trNOOP("Key$User6") }, { kUser7, trNOOP("Key$User7") }, { kUser8, trNOOP("Key$User8") }, { kUser9, trNOOP("Key$User9") }, { kNone, "" }, { k_Setup, "_Setup" }, { kNone, NULL }, }; // --- cKey ------------------------------------------------------------------ cKey::cKey(void) { remote = code = NULL; key = kNone; } cKey::cKey(const char *Remote, const char *Code, eKeys Key) { remote = strdup(Remote); code = strdup(Code); key = Key; } cKey::~cKey() { free(remote); free(code); } bool cKey::Parse(char *s) { char *p = strchr(s, '.'); if (p) { *p++ = 0; remote = strdup(s); char *q = strpbrk(p, " \t"); if (q) { *q++ = 0; key = FromString(p); if (key != kNone) { q = skipspace(q); if (*q) { code = strdup(q); return true; } } } } return false; } bool cKey::Save(FILE *f) { return fprintf(f, "%s.%-10s %s\n", remote, ToString(key), code) > 0; } eKeys cKey::FromString(const char *Name) { if (Name) { for (tKey *k = keyTable; k->name; k++) { const char *n = k->name; const char *p = strchr(n, '$'); if (p) n = p + 1; if (strcasecmp(n, Name) == 0) return k->type; } } return kNone; } const char *cKey::ToString(eKeys Key, bool Translate) { for (tKey *k = keyTable; k->name; k++) { if (k->type == Key) { const char *n = k->name; if (Translate) n = tr(n); const char *p = strchr(n, '$'); if (p) n = p + 1; return n; } } return NULL; } // --- cKeys ----------------------------------------------------------------- cKeys Keys; bool cKeys::KnowsRemote(const char *Remote) { if (Remote) { for (cKey *k = First(); k; k = Next(k)) { if (strcmp(Remote, k->Remote()) == 0) return true; } } return false; } eKeys cKeys::Get(const char *Remote, const char *Code) { if (Remote && Code) { for (cKey *k = First(); k; k = Next(k)) { if (strcmp(Remote, k->Remote()) == 0 && strcmp(Code, k->Code()) == 0) return k->Key(); } } return kNone; } const char *cKeys::GetSetup(const char *Remote) { if (Remote) { for (cKey *k = First(); k; k = Next(k)) { if (strcmp(Remote, k->Remote()) == 0 && k->Key() == k_Setup) return k->Code(); } } return NULL; } void cKeys::PutSetup(const char *Remote, const char *Setup) { if (!GetSetup(Remote)) Add(new cKey(Remote, Setup, k_Setup)); else esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote); } // --- cKeyMacro ------------------------------------------------------------- cKeyMacro::cKeyMacro(void) { numKeys = 0; for (int i = 0; i < MAXKEYSINMACRO; i++) macro[i] = kNone; // for compatibility with old code that doesn't know about NumKeys() plugin = NULL; } cKeyMacro::~cKeyMacro() { free(plugin); } bool cKeyMacro::Parse(char *s) { int n = 0; char *p; char *strtok_next; while ((p = strtok_r(s, " \t", &strtok_next)) != NULL) { if (n < MAXKEYSINMACRO) { if (*p == '@') { if (plugin) { esyslog("ERROR: only one @plugin allowed per macro"); return false; } if (!n) { esyslog("ERROR: @plugin can't be first in macro"); return false; } macro[n] = k_Plugin; if (n < MAXKEYSINMACRO) { plugin = strdup(p + 1); if (!cPluginManager::GetPlugin(plugin)) { esyslog("ERROR: unknown plugin '%s'", plugin); // this is not a fatal error - plugins may or may not be loaded macro[--n] = kNone; // makes sure the key doesn't cause any side effects } } else { esyslog("ERROR: key macro too long"); return false; } } else { macro[n] = cKey::FromString(p); if (macro[n] == kNone) { esyslog("ERROR: unknown key '%s'", p); return false; } } n++; s = NULL; } else { esyslog("ERROR: key macro too long"); return false; } } if (n < 2) esyslog("ERROR: empty key macro"); // non fatal numKeys = n; return true; } // --- cKeyMacros ------------------------------------------------------------ cKeyMacros KeyMacros; const cKeyMacro *cKeyMacros::Get(eKeys Key) { if (Key != kNone) { for (cKeyMacro *k = First(); k; k = Next(k)) { if (*k->Macro() == Key) return k; } } return NULL; }