Home

Dokumentation

Impressum

Dokumentation VDR
 

Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

remote.c

Go to the documentation of this file.
00001 
00010 #include "remote.h"
00011 #include <fcntl.h>
00012 #include <netinet/in.h>
00013 #include <string.h>
00014 #include <sys/types.h>
00015 #include <sys/time.h>
00016 #include <unistd.h>
00017 #include "tools.h"
00018 
00023 eKeys cRemote::keys[MaxKeys];
00024 int cRemote::in = 0;
00025 int cRemote::out = 0;
00026 cRemote *cRemote::learning = NULL;
00027 char *cRemote::unknownCode = NULL;
00028 cMutex cRemote::mutex;
00029 cCondVar cRemote::keyPressed;
00030 const char *cRemote::plugin = NULL;
00031 
00032 cRemote::cRemote(const char *Name)
00033 {
00034   name = Name ? strdup(Name) : NULL;
00035   Remotes.Add(this);
00036 }
00037 
00038 cRemote::~cRemote()
00039 {
00040   free(name);
00041 }
00042 
00043 const char *cRemote::GetSetup(void)
00044 {
00045   return Keys.GetSetup(Name());
00046 }
00047 
00048 void cRemote::PutSetup(const char *Setup)
00049 {
00050   Keys.PutSetup(Name(), Setup);
00051 }
00052 
00053 void cRemote::Clear(void)
00054 {
00055   cMutexLock MutexLock(&mutex);
00056   in = out = 0;
00057   if (learning) {
00058      free(unknownCode);
00059      unknownCode = NULL;
00060      }
00061 }
00062 
00063 bool cRemote::Put(eKeys Key)
00064 {
00065   if (Key != kNone) {
00066      cMutexLock MutexLock(&mutex);
00067      if (in != out && (keys[out] & k_Repeat) && (Key & k_Release))
00068         Clear();
00069      int d = out - in;
00070      if (d <= 0)
00071         d = MaxKeys + d;
00072      if (d - 1 > 0) {
00073         keys[in] = Key;
00074         if (++in >= MaxKeys)
00075            in = 0;
00076         keyPressed.Broadcast();
00077         return true;
00078         }
00079      return false;
00080      }
00081   return true; // only a real key shall report an overflow!
00082 }
00083 
00084 bool cRemote::PutMacro(eKeys Key)
00085 {
00086   const cKeyMacro *km = KeyMacros.Get(Key);
00087   if (km) {
00088      plugin = km->Plugin();
00089      for (int i = 1; i < MAXKEYSINMACRO; i++) {
00090          if (km->Macro()[i] != kNone) {
00091             if (!Put(km->Macro()[i]))
00092                return false;
00093             }
00094          else
00095             break;
00096          }
00097      }
00098   return true;
00099 }
00100 
00101 bool cRemote::Put(uint64 Code, bool Repeat, bool Release)
00102 {
00103   char buffer[32];
00104   snprintf(buffer, sizeof(buffer), "%016LX", Code);
00105   return Put(buffer, Repeat, Release);
00106 }
00107 
00108 bool cRemote::Put(const char *Code, bool Repeat, bool Release)
00109 {
00110   if (learning && this != learning)
00111      return false;
00112   eKeys Key = Keys.Get(Name(), Code);
00113   if (Key != kNone) {
00114      if (Repeat)
00115         Key = eKeys(Key | k_Repeat);
00116      if (Release)
00117         Key = eKeys(Key | k_Release);
00118      return Put(Key);
00119      }
00120   if (learning) {
00121      free(unknownCode);
00122      unknownCode = strdup(Code);
00123      keyPressed.Broadcast();
00124      }
00125   return false;
00126 }
00127 
00128 eKeys cRemote::Get(int WaitMs, char **UnknownCode)
00129 {
00130   for (;;) {
00131       cMutexLock MutexLock(&mutex);
00132       if (in != out) {
00133          eKeys k = keys[out];
00134          if (++out >= MaxKeys)
00135             out = 0;
00136          return k;
00137          }
00138       else if (!WaitMs || !keyPressed.TimedWait(mutex, WaitMs)) {
00139          if (learning && UnknownCode) {
00140             *UnknownCode = unknownCode;
00141             unknownCode = NULL;
00142             }
00143          return kNone;
00144          }
00145       }
00146 }
00147 
00152 cRemotes Remotes;
00153 
00158 struct tKbdMap {
00159   eKbdFunc func;
00160   uint64 code;
00161   };
00162 
00163 static tKbdMap KbdMap[] = {
00164   { kfF1,     0x0000001B5B31317EULL },
00165   { kfF2,     0x0000001B5B31327EULL },
00166   { kfF3,     0x0000001B5B31337EULL },
00167   { kfF4,     0x0000001B5B31347EULL },
00168   { kfF5,     0x0000001B5B31357EULL },
00169   { kfF6,     0x0000001B5B31377EULL },
00170   { kfF7,     0x0000001B5B31387EULL },
00171   { kfF8,     0x0000001B5B31397EULL },
00172   { kfF9,     0x0000001B5B32307EULL },
00173   { kfF10,    0x0000001B5B32317EULL },
00174   { kfF11,    0x0000001B5B32327EULL },
00175   { kfF12,    0x0000001B5B32337EULL },
00176   { kfUp,     0x00000000001B5B41ULL },
00177   { kfDown,   0x00000000001B5B42ULL },
00178   { kfLeft,   0x00000000001B5B44ULL },
00179   { kfRight,  0x00000000001B5B43ULL },
00180   { kfHome,   0x00000000001B5B48ULL },
00181   { kfEnd,    0x00000000001B5B46ULL },
00182   { kfPgUp,   0x000000001B5B357EULL },
00183   { kfPgDown, 0x000000001B5B367EULL },
00184   { kfIns,    0x000000001B5B327EULL },
00185   { kfDel,    0x000000001B5B337EULL },
00186   { kfNone,   0x0000000000000000ULL }
00187   };
00188 
00189 bool cKbdRemote::kbdAvailable = false;
00190 bool cKbdRemote::rawMode = false;
00191 
00192 cKbdRemote::cKbdRemote(void)
00193 :cRemote("KBD")
00194 {
00195   active = false;
00196   tcgetattr(STDIN_FILENO, &savedTm);
00197   struct termios tm;
00198   if (tcgetattr(STDIN_FILENO, &tm) == 0) {
00199      tm.c_iflag = 0;
00200      tm.c_lflag &= ~(ICANON | ECHO);
00201      tm.c_cc[VMIN] = 0;
00202      tm.c_cc[VTIME] = 0;
00203      tcsetattr(STDIN_FILENO, TCSANOW, &tm);
00204      }
00205   kbdAvailable = true;
00206   Start();
00207 }
00208 
00209 cKbdRemote::~cKbdRemote()
00210 {
00211   kbdAvailable = false;
00212   active = false;
00213   Cancel(3);
00214   tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
00215 }
00216 
00217 void cKbdRemote::SetRawMode(bool RawMode)
00218 {
00219   rawMode = RawMode;
00220 }
00221 
00222 uint64 cKbdRemote::MapFuncToCode(int Func)
00223 {
00224   for (tKbdMap *p = KbdMap; p->func != kfNone; p++) {
00225       if (p->func == Func)
00226          return p->code;
00227       }
00228   return (Func <= 0xFF) ? Func : 0;
00229 }
00230 
00231 int cKbdRemote::MapCodeToFunc(uint64 Code)
00232 {
00233   for (tKbdMap *p = KbdMap; p->func != kfNone; p++) {
00234       if (p->code == Code)
00235          return p->func;
00236       }
00237   return (Code <= 0xFF) ? Code : kfNone;
00238 }
00239 
00240 void cKbdRemote::Action(void)
00241 {
00242   dsyslog("KBD remote control thread started (pid=%d)", getpid());
00243   cPoller Poller(STDIN_FILENO);
00244   active = true;
00245   while (active) {
00246         if (Poller.Poll(100)) {
00247            uint64 Command = 0;
00248            uint i = 0;
00249            int t0 = time_ms();
00250            while (active && i < sizeof(Command)) {
00251                  uchar ch;
00252                  int r = read(STDIN_FILENO, &ch, 1);
00253                  if (r == 1) {
00254                     Command <<= 8;
00255                     Command |= ch;
00256                     i++;
00257                     }
00258                  else if (r == 0) {
00259                     // don't know why, but sometimes special keys that start with
00260                     // 0x1B ('ESC') cause a short gap between the 0x1B and the rest
00261                     // of their codes, so we'll need to wait some 100ms to see if
00262                     // there is more coming up - or whether this really is the 'ESC'
00263                     // key (if somebody knows how to clean this up, please let me know):
00264                     if (Command == 0x1B && time_ms() - t0 < 100)
00265                        continue;
00266                     if (Command) {
00267                        if (rawMode || !Put(Command)) {
00268                           int func = MapCodeToFunc(Command);
00269                           if (func)
00270                              Put(KBDKEY(func));
00271                           }
00272                        }
00273                     break;
00274                     }
00275                  else {
00276                     LOG_ERROR;
00277                     break;
00278                     }
00279                  }
00280            }
00281         }
00282   dsyslog("KBD remote control thread ended (pid=%d)", getpid());
00283 }

Generated on Wed Feb 5 23:30:11 2003 for VDR by doxygen1.3-rc2