From b90e708733789290c633e620f24bd6eb08dd0c2d Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 15 Dec 2002 10:58:00 +0100 Subject: [PATCH] Implemented raw keyboard input --- CONTRIBUTORS | 3 +++ HISTORY | 6 +++++ keys.h | 7 +++++- menuitems.c | 45 +++++++++++++++++++++++++++++++---- remote.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--- remote.h | 32 ++++++++++++++++++++++++- 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 8095e879..4be761c8 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -514,3 +514,6 @@ Thomas Sailer Sven Goethel for making switching audio channels work without stopping/restarting the DMX + +Jan Rieger + for suggestions and testing raw keyboard input diff --git a/HISTORY b/HISTORY index 1932905b..7e2a7102 100644 --- a/HISTORY +++ b/HISTORY @@ -1887,3 +1887,9 @@ Video Disk Recorder Revision History - No longer stopping/restarting the DMX when switching audio channels (thanks to Sven Goethel). - Fixed high CPU load in 'Transfer Mode' (thanks to Oliver Endriss). +- If a PC keyboard is used as remote control, the string entry fields in the + menus now accept character input directly (however, this works only for keys that + are not otherwise defined as remote control keys). Also, plugins can switch the + cKbdRemote class into "raw mode", where all keyboard input will be made available + through the new 'kKbd' key code and none of it will be processed as normal remote + control functions (thanks to Jan Rieger for suggestions and testing). diff --git a/keys.h b/keys.h index 02c513ae..eb4b5b34 100644 --- a/keys.h +++ b/keys.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: keys.h 1.4 2002/12/01 10:43:26 kls Exp $ + * $Id: keys.h 1.5 2002/12/14 15:49:42 kls Exp $ */ #ifndef __KEYS_H @@ -46,6 +46,7 @@ enum eKeys { // "Up" and "Down" must be the first two keys! kCommands, kUser1, kUser2, kUser3, kUser4, kUser5, kUser6, kUser7, kUser8, kUser9, kNone, + kKbd, // The following codes are used internally: k_Plugin, k_Setup, @@ -69,6 +70,10 @@ enum eKeys { // "Up" and "Down" must be the first two keys! #define NORMALKEY(k) (eKeys((k) & ~k_Repeat)) #define ISMODELESSKEY(k) (RAWKEY(k) > k9) +#define BASICKEY(k) (eKeys((k) & 0xFFFF)) +#define KBDKEY(k) (eKeys(((k) << 16) | kKbd)) +#define KEYKBD(k) (((k) >> 16) & 0xFFFF) + struct tKey { eKeys type; char *name; diff --git a/menuitems.c b/menuitems.c index 97d81ad1..da65db10 100644 --- a/menuitems.c +++ b/menuitems.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.c 1.9 2002/09/08 14:51:28 kls Exp $ + * $Id: menuitems.c 1.10 2002/12/15 10:58:00 kls Exp $ */ #include "menuitems.h" @@ -284,7 +284,7 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key) uppercase = isupper(value[pos]); break; case kRight|k_Repeat: - case kRight: if (pos < length && pos < int(strlen(value)) ) { + case kRight: if (pos < length - 2 && pos < int(strlen(value)) ) { if (++pos >= int(strlen(value))) { if (pos >= 2 && value[pos - 1] == ' ' && value[pos - 2] == ' ') pos--; // allow only two blanks at the end @@ -306,7 +306,7 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key) case kDown: if (pos >= 0) { if (insert && newchar) { // create a new character in insert mode - if (int(strlen(value)) < length) { + if (int(strlen(value)) < length - 1) { memmove(value + pos + 1, value + pos, strlen(value) - pos + 1); value[pos] = ' '; } @@ -328,7 +328,44 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key) break; } // run into default - default: return cMenuEditItem::ProcessKey(Key); + default: if (pos >= 0 && BASICKEY(Key) == kKbd) { + int c = KEYKBD(Key); + if (c <= 0xFF) { + const char *p = strchr(allowed, tolower(c)); + if (p) { + int l = strlen(value); + if (insert && l < length - 1) + memmove(value + pos + 1, value + pos, l - pos + 1); + value[pos] = c; + if (pos < length - 2) + pos++; + if (pos >= l) { + value[pos] = ' '; + value[pos + 1] = 0; + } + } + else { + switch (c) { + case 0x7F: // backspace + if (pos > 0) { + pos--; + return ProcessKey(kYellow); + } + break; + } + } + } + else { + switch (c) { + case kfHome: pos = 0; break; + case kfEnd: pos = strlen(value) - 1; break; + case kfIns: return ProcessKey(kGreen); + case kfDel: return ProcessKey(kYellow); + } + } + } + else + return cMenuEditItem::ProcessKey(Key); } Set(); return osContinue; diff --git a/remote.c b/remote.c index d4f1702b..da28f389 100644 --- a/remote.c +++ b/remote.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remote.c 1.34 2002/12/08 13:37:13 kls Exp $ + * $Id: remote.c 1.35 2002/12/15 10:09:27 kls Exp $ */ #include "remote.h" @@ -149,6 +149,39 @@ cRemotes Remotes; // --- cKbdRemote ------------------------------------------------------------ +struct tKbdMap { + eKbdFunc func; + uint64 code; + }; + +static tKbdMap KbdMap[] = { + { kfF1, 0x0000001B5B31317EULL }, + { kfF2, 0x0000001B5B31327EULL }, + { kfF3, 0x0000001B5B31337EULL }, + { kfF4, 0x0000001B5B31347EULL }, + { kfF5, 0x0000001B5B31357EULL }, + { kfF6, 0x0000001B5B31377EULL }, + { kfF7, 0x0000001B5B31387EULL }, + { kfF8, 0x0000001B5B31397EULL }, + { kfF9, 0x0000001B5B32307EULL }, + { kfF10, 0x0000001B5B32317EULL }, + { kfF11, 0x0000001B5B32327EULL }, + { kfF12, 0x0000001B5B32337EULL }, + { kfUp, 0x00000000001B5B41ULL }, + { kfDown, 0x00000000001B5B42ULL }, + { kfLeft, 0x00000000001B5B44ULL }, + { kfRight, 0x00000000001B5B43ULL }, + { kfHome, 0x00000000001B5B48ULL }, + { kfEnd, 0x00000000001B5B46ULL }, + { kfPgUp, 0x000000001B5B357EULL }, + { kfPgDown, 0x000000001B5B367EULL }, + { kfIns, 0x000000001B5B327EULL }, + { kfDel, 0x000000001B5B337EULL }, + { kfNone, 0x0000000000000000ULL } + }; + +bool cKbdRemote::rawMode = false; + cKbdRemote::cKbdRemote(void) :cRemote("KBD") { @@ -172,6 +205,29 @@ cKbdRemote::~cKbdRemote() tcsetattr(STDIN_FILENO, TCSANOW, &savedTm); } +void cKbdRemote::SetRawMode(bool RawMode) +{ + rawMode = RawMode; +} + +uint64 cKbdRemote::MapFuncToCode(int Func) +{ + for (tKbdMap *p = KbdMap; p->func != kfNone; p++) { + if (p->func == Func) + return p->code; + } + return (Func <= 0xFF) ? Func : 0; +} + +int cKbdRemote::MapCodeToFunc(uint64 Code) +{ + for (tKbdMap *p = KbdMap; p->func != kfNone; p++) { + if (p->code == Code) + return p->func; + } + return (Code <= 0xFF) ? Code : kfNone; +} + void cKbdRemote::Action(void) { dsyslog("KBD remote control thread started (pid=%d)", getpid()); @@ -198,8 +254,13 @@ void cKbdRemote::Action(void) // key (if somebody knows how to clean this up, please let me know): if (Command == 0x1B && time_ms() - t0 < 100) continue; - if (Command) - Put(Command); + if (Command) { + if (rawMode || !Put(Command)) { + int func = MapCodeToFunc(Command); + if (func) + Put(KBDKEY(func)); + } + } break; } else { diff --git a/remote.h b/remote.h index 1c087d0f..0b8c7a30 100644 --- a/remote.h +++ b/remote.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remote.h 1.22 2002/12/08 13:37:02 kls Exp $ + * $Id: remote.h 1.23 2002/12/15 09:58:32 kls Exp $ */ #ifndef __REMOTE_H @@ -51,14 +51,44 @@ class cRemotes : public cList {}; extern cRemotes Remotes; +enum eKbdFunc { + kfNone, + kfF1 = 0x100, + kfF2, + kfF3, + kfF4, + kfF5, + kfF6, + kfF7, + kfF8, + kfF9, + kfF10, + kfF11, + kfF12, + kfUp, + kfDown, + kfLeft, + kfRight, + kfHome, + kfEnd, + kfPgUp, + kfPgDown, + kfIns, + kfDel, + }; + class cKbdRemote : public cRemote, private cThread { private: bool active; + static bool rawMode; struct termios savedTm; virtual void Action(void); + int MapCodeToFunc(uint64 Code); public: cKbdRemote(void); virtual ~cKbdRemote(); + uint64 MapFuncToCode(int Func); + static void SetRawMode(bool RawMode); }; #endif //__REMOTE_H