Package: mplayer Version: 1.0~rc2-7+lenny1 Tags: upstream When LIRC codes begin with modifiers, the LIRC input stream can get `delayed by one'. The attached patch fixes the bug for me.
An example is my `Windows Media Center' IR remote, that sends virtually everything as `keyboard' hotkeys (its receiver emulates a USB keyboard, which I drive with the help of inputlirc Debian package). E.g., PAUSE is KEY_LEFTCTRL code followed by KEY_P code (for ^P). Other keys have up to three modifiers. Mplayer regularly calls mp_input_lirc_read() function to poll for LIRC input. The function uses select(2) to check for LIRC input. Upon a PAUSE keypress, lirc_nextcode() gobbles up all available input on the fd, putting it in its static internal buffer, then returns the `codes' one by one (KEY_LEFTCTRL first). When given to lirc_code2char(), this code produces no command, only changing internal state of the LIRC client library. The end result of mp_input_lirc_read() call is no command (the MP_INPUT_RETRY hoop doesn't help). Continuing calls to mp_input_lirc_read() do nothing at all, since select(2) is used again, and all the codes produced by the remote so far are stuck in lirc_nextcode() internal buffer. So, until more keypresses arrive, the PAUSE won't be delivered. And when they do arrive, the last keypress is almost always delayed again for the same reason. The solution is to do away with the (expensive and unnecessary) select(2) polling, using lirc_nextcode() as the polling mechanism instead. In order for that not to block on no LIRC input, O_NONBLOCK is applied to the LIRC fd. The situation seems to be the same in the upstream SVN HEAD at the moment. Cheers, -- /Awesome Walrus <[EMAIL PROTECTED]>
#! /bin/sh /usr/share/dpatch/dpatch-run ## dpatch by Awesome Walrus <[EMAIL PROTECTED]> ## ## DP: When LIRC codes begin with modifiers, the LIRC input stream can get ## DP: `delayed by one'. ## DP: ## DP: An example is my `Windows Media Center' IR remote, that sends virtually ## DP: everything as `keyboard' hotkeys (its receiver emulates a USB keyboard, ## DP: which I drive with the help of inputlirc Debian package). E.g., PAUSE is ## DP: KEY_LEFTCTRL code followed by KEY_P code (for ^P). Other keys have up to ## DP: three modifiers. ## DP: ## DP: Mplayer regularly calls mp_input_lirc_read() function to poll for LIRC ## DP: input. The function uses select(2) to check for LIRC input. ## DP: ## DP: Upon a PAUSE keypress, lirc_nextcode() gobbles up all available input on ## DP: the fd, putting it in its static internal buffer, then returns the ## DP: `codes' one by one (KEY_LEFTCTRL first). When given to lirc_code2char(), ## DP: this code produces no command, only changing internal state of the LIRC ## DP: client library. The end result of mp_input_lirc_read() call is no ## DP: command (the MP_INPUT_RETRY hoop doesn't help). ## DP: ## DP: Continuing calls to mp_input_lirc_read() do nothing at all, since ## DP: select(2) is used again, and all the codes produced by the remote so far ## DP: are stuck in lirc_nextcode() internal buffer. So, until more keypresses ## DP: arrive, the PAUSE won't be delivered. And when they do arrive, the last ## DP: keypress is almost always delayed again for the same reason. ## DP: ## DP: The solution is to do away with the (expensive and unnecessary) select(2) ## DP: polling, using lirc_nextcode() as the polling mechanism instead. In ## DP: order for that not to block on no LIRC input, O_NONBLOCK is applied to ## DP: the LIRC fd. @DPATCH@ --- mplayer-1.0~rc2/input/lirc.c 2007-10-08 08:49:26.000000000 +1300 +++ lirc.c 2008-11-18 01:40:23.975515177 +1300 @@ -3,6 +3,7 @@ #include <lirc/lirc_client.h> #include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> @@ -21,7 +22,8 @@ int mp_input_lirc_init(void) { - int lirc_sock; + int lirc_sock, + mode; mp_msg(MSGT_LIRC,MSGL_V,MSGTR_SettingUpLIRC); if((lirc_sock=lirc_init("mplayer",1))==-1){ @@ -36,12 +38,18 @@ return -1; } + if ((mode = fcntl(lirc_sock, F_GETFL)) < 0 || + fcntl(lirc_sock, F_SETFL, mode | O_NONBLOCK) < 0) { + mp_msg(MSGT_LIRC, MSGL_ERR, "setting non-blocking mode failed: %s\n", + strerror(errno)); + lirc_deinit(); + return -1; + } + return lirc_sock; } int mp_input_lirc_read(int fd,char* dest, int s) { - fd_set fds; - struct timeval tv; int r,cl = 0; char *code = NULL,*c = NULL; @@ -59,21 +67,7 @@ return w; } - // Nothing in the buffer, pool the lirc fd - FD_ZERO(&fds); - FD_SET(fd,&fds); - memset(&tv,0,sizeof(tv)); - while((r = select(fd+1,&fds,NULL,NULL,&tv)) <= 0) { - if(r < 0) { - if(errno == EINTR) - continue; - mp_msg(MSGT_INPUT,MSGL_ERR,"Select error : %s\n",strerror(errno)); - return MP_INPUT_ERROR; - } else - return MP_INPUT_NOTHING; - } - - // There's something to read + // Nothing in the buffer, poll the lirc fd if(lirc_nextcode(&code) != 0) { mp_msg(MSGT_INPUT,MSGL_ERR,"Lirc error :(\n"); return MP_INPUT_DEAD;