Hi, I was quite annoyed how I could operate my EPIA MII-6000E using a LIRC remote. It was almost not possible to navigate through the OSD in a fast way. The attached patch allows now to define timeouts and frequencies for example in Make.config, so there is no need to patch every VDR version. Furthermore, frequencies are now defined in unit 1/s instead of the unit ms (which defined the period), making values more intuitive. There's now an additional frequency which defines, how fast a user is allowed to press the same button repeatedly. The originally used REPEATDELAY allowed only 2.85 button presses per second. On slow and busy machines like my EPIA it happened often that several button presses were read by VDR in a single read, but only the first one got processed. The code now reads only a single button press from LIRC's socket, so button presses don't get lost (although presses of the same button will be skipped as the timeouts don't get reached). To make it less likely that button presses get processed in chunks a further define allows to decrease the thread's niceness which means to boost it's priority. This feature requires VDR to be run as root. This is my setup which follows some common settings found in mainboard bioses for keyboard repeat delay and frequency. > #vdr > REMOTE=LIRC > LIRC_PUSHFREQ=64 # 1/s > LIRC_REPEATDELAY=250 # ms > LIRC_REPEATFREQ=32 # 1/s > #LIRC_REPEATTIMEOUT=500 # ms > #LIRC_RECONNECTDELAY=3000 # ms > LIRC_PRIORITYBOOST=1 Bye. -- Dipl.-Inform. (FH) Reinhard Nissl mailto:rnissl@xxxxxx
--- ../vdr-1.5.12-dvbs2-other/lirc.c 2006-05-28 10:48:13.000000000 +0200 +++ lirc.c 2008-01-08 22:28:38.000000000 +0100 @@ -13,10 +13,24 @@ #include <netinet/in.h> #include <sys/socket.h> -#define REPEATDELAY 350 // ms -#define REPEATFREQ 100 // ms -#define REPEATTIMEOUT 500 // ms -#define RECONNECTDELAY 3000 // ms +#ifndef LIRC_PUSHFREQ +#define LIRC_PUSHFREQ 3 // 1/s +#endif +#ifndef LIRC_REPEATDELAY +#define LIRC_REPEATDELAY 350 // ms +#endif +#ifndef LIRC_REPEATFREQ +#define LIRC_REPEATFREQ 10 // 1/s +#endif +#ifndef LIRC_REPEATTIMEOUT +#define LIRC_REPEATTIMEOUT 500 // ms +#endif +#ifndef LIRC_RECONNECTDELAY +#define LIRC_RECONNECTDELAY 3000 // ms +#endif +#ifndef LIRC_PRIORITYBOOST +#define LIRC_PRIORITYBOOST 0 +#endif cLircRemote::cLircRemote(const char *DeviceName) :cRemote("LIRC") @@ -68,17 +82,33 @@ void cLircRemote::Action(void) bool repeat = false; int timeout = -1; + if (LIRC_PRIORITYBOOST) + SetPriority(GetPriority() - LIRC_PRIORITYBOOST); while (Running() && f >= 0) { - bool ready = cFile::FileReady(f, timeout); - int ret = ready ? safe_read(f, buf, sizeof(buf)) : -1; + int ret = -1; + if (ready) { + // read one line of the line oriented lirc protocol + for (ret = 0; ret < (int)sizeof(buf); ret++) { + int ch = readchar(f); + if (ch < 0) { + ret = -1; + break; + } + if (ch == '\n') { + buf[ret++] = '\0'; + break; + } + buf[ret] = ch; + } + } if (ready && ret <= 0 ) { - esyslog("ERROR: lircd connection broken, trying to reconnect every %.1f seconds", float(RECONNECTDELAY) / 1000); + esyslog("ERROR: lircd connection broken, trying to reconnect every %.1f seconds", float(LIRC_RECONNECTDELAY) / 1000); close(f); f = -1; while (Running() && f < 0) { - cCondWait::SleepMs(RECONNECTDELAY); + cCondWait::SleepMs(LIRC_RECONNECTDELAY); if (Connect()) { isyslog("reconnected to lircd"); break; @@ -94,7 +124,7 @@ void cLircRemote::Action(void) continue; } if (count == 0) { - if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < REPEATDELAY) + if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < (1000 / LIRC_PUSHFREQ)) continue; // skip keys coming in too fast if (repeat) Put(LastKeyName, false, true); @@ -104,18 +134,18 @@ void cLircRemote::Action(void) timeout = -1; } else { - if (LastTime.Elapsed() < REPEATFREQ) + if (LastTime.Elapsed() < (1000 / LIRC_REPEATFREQ)) continue; // repeat function kicks in after a short delay (after last key instead of first key) - if (FirstTime.Elapsed() < REPEATDELAY) + if (FirstTime.Elapsed() < LIRC_REPEATDELAY) continue; // skip keys coming in too fast (for count != 0 as well) repeat = true; - timeout = REPEATDELAY; + timeout = LIRC_REPEATDELAY; } LastTime.Set(); Put(KeyName, repeat); } else if (repeat) { // the last one was a repeat, so let's generate a release - if (LastTime.Elapsed() >= REPEATTIMEOUT) { + if (LastTime.Elapsed() >= LIRC_REPEATTIMEOUT) { Put(LastKeyName, false, true); repeat = false; *LastKeyName = 0; --- ../vdr-1.5.12-dvbs2-other/Makefile 2008-01-01 22:55:18.000000000 +0100 +++ Makefile 2008-01-08 22:23:41.000000000 +0100 @@ -58,6 +59,25 @@ RCU_DEVICE ?= /dev/ttyS1 DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\" -DRCU_DEVICE=\"$(RCU_DEVICE)\" +ifdef LIRC_PUSHFREQ +DEFINES += -DLIRC_PUSHFREQ=$(LIRC_PUSHFREQ) +endif +ifdef LIRC_REPEATDELAY +DEFINES += -DLIRCD_REPEATDELAY=$(LIRC_REPEATDELAY) +endif +ifdef LIRC_REPEATFREQ +DEFINES += -DLIRC_REPEATFREQ=$(LIRC_REPEATFREQ) +endif +ifdef LIRC_REPEATTIMEOUT +DEFINES += -DLIRC_REPEATTIMEOUT=$(LIRC_REPEATTIMEOUT) +endif +ifdef LIRC_RECONNECTDELAY +DEFINES += -DLIRC_RECONNECTDELAY=$(LIRC_RECONNECTDELAY) +endif +ifdef LIRC_PRIORITYBOOST +DEFINES += -DLIRC_PRIORITYBOOST=$(LIRC_PRIORITYBOOST) +endif + DEFINES += -D_GNU_SOURCE DEFINES += -DVIDEODIR=\"$(VIDEODIR)\" --- ../vdr-1.5.12-dvbs2-other/thread.c 2007-10-19 16:30:13.000000000 +0200 +++ thread.c 2008-01-08 22:39:48.000000000 +0100 @@ -218,9 +218,20 @@ cThread::~cThread() free(description); } +int cThread::GetPriority(void) +{ + errno = 0; + int Priority = getpriority(PRIO_PROCESS, 0); + if (Priority == -1 && errno != 0) { + LOG_ERROR; + Priority = 0; + } + return Priority; +} + void cThread::SetPriority(int Priority) { - if (setpriority(PRIO_PROCESS, 0, Priority) < 0) + if (setpriority(PRIO_PROCESS, 0, max(-20, min(Priority, 19))) < 0) LOG_ERROR; } --- ../vdr-1.5.12-dvbs2-other/thread.h 2007-02-24 17:13:28.000000000 +0100 +++ thread.h 2008-01-07 22:52:19.000000000 +0100 @@ -86,6 +86,7 @@ private: static tThreadId mainThreadId; static void *StartThread(cThread *Thread); protected: + int GetPriority(void); void SetPriority(int Priority); void Lock(void) { mutex.Lock(); } void Unlock(void) { mutex.Unlock(); } --- ../vdr-1.5.12-dvbs2-other/tools.c 2008-01-01 22:55:18.000000000 +0100 +++ tools.c 2008-01-06 01:50:17.000000000 +0100 @@ -84,6 +84,14 @@ ssize_t safe_write(int filedes, const vo return p < 0 ? p : written; } +int readchar(int filedes) +{ + char c; + if (safe_read(filedes, &c, sizeof(c)) != 1) + return -1; + return c; +} + void writechar(int filedes, char c) { safe_write(filedes, &c, sizeof(c)); --- ../vdr-1.5.12-dvbs2-other/tools.h 2008-01-01 22:55:18.000000000 +0100 +++ tools.h 2008-01-06 01:57:03.000000000 +0100 @@ -164,6 +164,7 @@ public: ssize_t safe_read(int filedes, void *buffer, size_t size); ssize_t safe_write(int filedes, const void *buffer, size_t size); +int readchar(int filedes); void writechar(int filedes, char c); int WriteAllOrNothing(int fd, const uchar *Data, int Length, int TimeoutMs = 0, int RetryMs = 0); ///< Writes either all Data to the given file descriptor, or nothing at all.
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr