Package: lirc-x
Version: 0.7.1pre2-2
Severity: normal
Tags: patch

Here is another patch for irxexec to make it really work in a
"production" environment (see http://www.j-pfennig.de/zapdvb). While bug
326703 made irxevent almost unusable the lack of an X11 error makes it to
too instable to be used with applications like mplayer (e.g. apps that
create a high cpu load). The symptom:

>From time to time irxevet reports a BadWindow X11 error and dies.

The attached patch adds such a handler, as well as the options -d
(daemon) and -v (verbose). This is just the version that can be
downloaded from http://www.j-pfennig.de/zapdvb/download.html .

Unfortunately it is difficult to contact the LIRC project, their
mail-list is not accessible to most german users that have an internet
domain but no postmaster E-Mail account. I hope that this message
somehow finds it's way upstream.

Juergen Pfennig

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.11-7-amd
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)

Versions of packages lirc-x depends on:
ii  libc6                    2.3.2.ds1-22    GNU C Library: Shared libraries an
ii  libice6                  4.3.0.dfsg.1-14 Inter-Client Exchange library
ii  liblircclient0           0.7.1pre2-2     LIRC client library
ii  libsm6                   4.3.0.dfsg.1-14 X Window System Session Management
ii  libx11-6                 4.3.0.dfsg.1-14 X Window System protocol client li
ii  lirc                     0.7.1pre2-2     Linux Infra-red Remote Control sup
ii  xlibs                    4.3.0.dfsg.1-14 X Keyboard Extension (XKB) configu

-- no debconf information
--- irxevent.c.orig	2004-03-25 21:02:24.000000000 +0100
+++ irxevent.c	2005-09-15 10:40:36.000000000 +0200
@@ -94,15 +94,20 @@
 
 #define DEBUG
 #ifdef DEBUG
-void debugprintf(char *format_str, ...)
+
+static int bVerbose = 0;
+static int bInError = 0;
+
+static void debugprintf(char *format_str, ...)
 {
         va_list ap;
         va_start(ap,format_str);
-        vfprintf(stderr,format_str,ap);
+        if(bVerbose)
+		vfprintf(stderr,format_str,ap);
         va_end(ap);
 }
 #else
-void debugprintf(char *format_str, ...)
+static void debugprintf(char *format_str, ...)
 {
 }
 #endif
@@ -125,18 +130,18 @@
   {NULL,0},
 };
 
-const char *key_delimiter ="-";
-const char *active_window_name ="CurrentWindow";
-const char *root_window_name ="RootWindow";
+static const char *key_delimiter ="-";
+static const char *active_window_name ="CurrentWindow";
+static const char *root_window_name ="RootWindow";
 
 
-char *progname;
-Display *dpy;
-Window root;
-XEvent xev;
-Window w,subw;
+static char *progname;
+static Display *dpy;
+static Window root;
+static XEvent xev;
+static Window subw;
 
-Time fake_timestamp()
+static Time fake_timestamp()
      /*seems that xfree86 computes the timestamps like this     */
      /*strange but it relies on the *1000-32bit-wrap-around     */
      /*if anybody knows exactly how to do it, please contact me */
@@ -151,7 +156,7 @@
   return (Time)tint;
 }
 
-Window find_window(Window top,char *name)
+static Window find_window(Window top,char *name)
 {
   char *wname,*iname;
   XClassHint xch;
@@ -210,7 +215,7 @@
   return(top);
 }
 
-Window find_sub_sub_window(Window top,int *x, int *y)
+static Window find_sub_sub_window(Window top,int *x, int *y)
 {
   Window base;
   Window *children,foo,target=0;
@@ -254,7 +259,7 @@
 
 
 
-Window find_sub_window(Window top,char *name,int *x, int *y)
+static Window find_sub_window(Window top,char *name,int *x, int *y)
 {
   Window base;
   Window *children,foo,target=0;
@@ -297,7 +302,7 @@
 }
 
 
-Window find_window_focused(Window top,char *name) 
+static Window find_window_focused(Window top,char *name) 
 {
   int tmp;
   Window w, cur, *children, foo;
@@ -330,7 +335,7 @@
   return(0);
 }
 
-void make_button(int button,int x,int y,XButtonEvent *xev)
+static void make_button(int button,int x,int y,XButtonEvent *xev)
 {
   xev->type = ButtonPress;
   xev->display=dpy;
@@ -346,7 +351,7 @@
   return;
 }
 
-void make_key(char *keyname,int x, int y,XKeyEvent *xev)
+static void make_key(char *keyname,int x, int y,XKeyEvent *xev)
 {
   char *part, *part2;
   struct keymodlist_t *kmlptr;
@@ -389,7 +394,7 @@
   return ;
 }
 
-void sendfocus(Window w,int in_out)
+static void sendfocus(Window w,int in_out)
 {
   XFocusChangeEvent focev;
 
@@ -404,7 +409,7 @@
   return;
 }
 
-void sendpointer_enter_or_leave(Window w,int in_out)
+static void sendpointer_enter_or_leave(Window w,int in_out)
 {
   XCrossingEvent crossev;
   crossev.type=in_out;
@@ -427,7 +432,7 @@
   return;
 }
 
-void sendkey(char *keyname,int x,int y,Window w,Window s)
+static void sendkey(char *keyname,int x,int y,Window w,Window s)
 {
   make_key(keyname ,x,y,(XKeyEvent*)&xev);
   xev.xkey.window=w;
@@ -445,7 +450,7 @@
   return;
 }
 
-void sendbutton(int button, int x, int y, Window w,Window s)
+static void sendbutton(int button, int x, int y, Window w,Window s)
 {
   make_button(button,x,y,(XButtonEvent*)&xev);
   xev.xbutton.window=w;
@@ -467,6 +472,17 @@
   return;
 }
 
+int errorHandler(Display* di, XErrorEvent* ev)
+{
+  if(bInError || ev==NULL || di==NULL) return 1;      // only 1 msg per key
+  char buff[512]; buff[0] = 0;
+  XGetErrorText(di, ev->error_code, buff, sizeof(buff)-1);
+  if(buff[0]) {
+     fprintf(stderr, "X11 error: %s\n", buff);
+     bInError = 1;
+  }
+  return 1;
+}
 
 int check(char *s)
 {
@@ -503,7 +519,9 @@
 
 static struct option long_options[] =
 {
-	{"help", no_argument, NULL, 'h'},
+	{"daemon",  no_argument, NULL, 'd'},
+	{"help",    no_argument, NULL, 'h'},
+	{"verbose", no_argument, NULL, 'v'},
 	{"version", no_argument, NULL, 'V'},
 	{0, 0, 0, 0}
 };
@@ -517,18 +535,27 @@
   char *config_file=NULL;
   int c;
   int WindowID;
+  int bDaemon = 0;
 
   progname=argv[0];
 
-  while ((c = getopt_long(argc, argv, "hV", long_options, NULL)) != EOF) {
+  while ((c = getopt_long(argc, argv, "dhvV", long_options, NULL)) != EOF) {
     switch (c) {
+    case 'd':
+      bDaemon = 1; continue;
     case 'h':
-      printf("Usage: %s [config file]\n", argv[0]);
-      printf("\t -h --help \t\tdisplay usage summary\n");
-      printf("\t -V --version \t\tdisplay version\n");
+      printf("Usage: %s [option]... [config file]\n"
+             "       -d --daemon     fork and run in background\n"
+             "       -h --help       display usage summary\n"
+             "       -v --verbose    report what happens\n"
+             "       -V --version    display version\n", progname);
       return(EXIT_SUCCESS);
+    case 'v':
+      bVerbose = 1;
+      // fall through...
     case 'V':
-      printf("%s %s\n", progname, VERSION);
+      printf("%s %s (zapdvb 2005_09_15)\n", progname, VERSION);
+      if(bVerbose) break;
       return(EXIT_SUCCESS);
     case '?':
       fprintf(stderr, "unrecognized option: -%c\n", optopt);
@@ -552,20 +579,32 @@
   }
   root=RootWindow(dpy,DefaultScreen(dpy));
 
+  // windows may get closed at wrong time. Override default error handler...
+  XSetErrorHandler(errorHandler);
+  
   if(lirc_init("irxevent",1)==-1) exit(EXIT_FAILURE);
 
   if(lirc_readconfig(config_file,&config,check)==0)
     {
+
+     if(bDaemon) {
+	if(daemon(1, 0) < 0) {
+	   perror("Failed to run as daemon");
+	   exit(2);
+        }
+     }
+     
       char *ir;
       char *c;
       int ret;
-      
+ 
       while(lirc_nextcode(&ir)==0)
 	{
 	  if(ir==NULL) continue;
 	  while((ret=lirc_code2char(config,ir,&c))==0 && c!=NULL)
 	    {
-	      debugprintf("Recieved code: %s Sending event: \n",ir);
+	      debugprintf("Received code: %s Sending event: \n",ir);
+	      bInError = 0;   // reset error state, want to see error msg
 	      
 	      *windowname=0;
 	      if(2==sscanf(c,"Key %s Focus WindowID %i",keyname,&WindowID) ||
@@ -605,6 +644,8 @@
 			4==sscanf(c,"xy_Key %d %d %s %s\n",&pointer_x,&pointer_y,keyname,windowname)) {
 		debugprintf("name: %s\n",windowname);
 		WindowID=find_window(root,windowname);
+		if(WindowID == 0) 
+			continue;
 	      }
 	      
 	      switch(c[0])

Reply via email to