vdr  1.7.27
keys.c
Go to the documentation of this file.
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 }