[ANNOUNCE] improved LIRC remote for VDR-1.5.12

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux