summaryrefslogtreecommitdiffstats
path: root/input
diff options
context:
space:
mode:
authoruau <uau@b3059339-0415-0410-9bf9-f77b7e298cf2>2007-08-25 04:28:11 +0000
committeruau <uau@b3059339-0415-0410-9bf9-f77b7e298cf2>2007-08-25 04:28:11 +0000
commit24802b1def3b48375a54e2fe9bbb1d19953286c8 (patch)
treea0e61237e769a4b01a1645705df0b21ac8947a64 /input
parent7eb3bc0cf8cb9830cf348cb4f4da1af5175718fb (diff)
downloadmpv-24802b1def3b48375a54e2fe9bbb1d19953286c8.tar.bz2
mpv-24802b1def3b48375a54e2fe9bbb1d19953286c8.tar.xz
Use a single select() for both key and slave input
Previous code used two separate select() calls one after another, so that whenever it was running select() on one set of fds events in the other set would go unnoticed until later. Now there's a single select() which allows reacting immediately to any input source. The behavior of the new code differs somewhat from the old; for example multiple fds that stay readable are no longer handled in a round-robin fashion and the total amount the process sleeps can differ. Some tuning might be required later. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24151 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'input')
-rw-r--r--input/input.c312
1 files changed, 117 insertions, 195 deletions
diff --git a/input/input.c b/input/input.c
index bdef163782..ff51e1b70c 100644
--- a/input/input.c
+++ b/input/input.c
@@ -991,126 +991,25 @@ mp_input_get_cmd_from_keys(int n,int* keys, int paused) {
return ret;
}
-int
-mp_input_read_key_code(int time) {
-#ifdef HAVE_POSIX_SELECT
- fd_set fds;
- struct timeval tv,*time_val;
-#endif
- int i,n=0,max_fd = 0, did_sleep = 0;
- static int last_loop = 0;
-
- if(num_key_fd == 0)
- {
- if (time)
- usec_sleep(time * 1000);
- return MP_INPUT_NOTHING;
- }
-
-#ifdef HAVE_POSIX_SELECT
- FD_ZERO(&fds);
-#endif
- // Remove fd marked as dead and build the fd_set
- // n == number of fd's to be select() checked
- for(i = 0; (unsigned int)i < num_key_fd; i++) {
- if (key_fds[i].dead) {
- mp_input_rm_key_fd(key_fds[i].fd);
- i--;
- continue;
- } else if (key_fds[i].no_select)
- continue;
- if(key_fds[i].fd > max_fd)
- max_fd = key_fds[i].fd;
-#ifdef HAVE_POSIX_SELECT
- FD_SET(key_fds[i].fd,&fds);
-#endif
- n++;
- }
-
-#ifdef HAVE_POSIX_SELECT
-// if we have fd's without MP_FD_NO_SELECT flag, call select():
-if(n>0){
-
- if(time >= 0 ) {
- tv.tv_sec=time/1000;
- tv.tv_usec = (time%1000)*1000;
- time_val = &tv;
- } else
- time_val = NULL;
-
- while(1) {
- if(select(max_fd+1,&fds,NULL,NULL,time_val) < 0) {
- if(errno == EINTR)
- continue;
- mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrSelect,strerror(errno));
- }
- break;
- }
- did_sleep = 1;
-
-}
-#endif
-
- for(i = last_loop + 1 ; i != last_loop ; i++) {
- int code = -1;
- // This is to check all fds in turn
- if((unsigned int)i >= num_key_fd) {
- i = -1;
- last_loop++;
- last_loop %= (num_key_fd+1);
- continue;
- }
-#ifdef HAVE_POSIX_SELECT
- // No input from this fd
- if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds))
- continue;
-#endif
- if(key_fds[i].fd == 0) { // stdin is handled by getch2
- getch2();
- code = mplayer_get_key(0);
- if(code < 0)
- code = MP_INPUT_NOTHING;
- }
- else
- code = ((mp_key_func_t)key_fds[i].read_func)(key_fds[i].fd);
-
- if(code >= 0)
- return code;
-
- if(code == MP_INPUT_ERROR)
- mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrOnKeyInFd,key_fds[i].fd);
- else if(code == MP_INPUT_DEAD) {
- mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrDeadKeyOnFd,key_fds[i].fd);
- key_fds[i].dead = 1;
- }
- }
- if (time && !did_sleep)
- usec_sleep(time * 1000);
- return MP_INPUT_NOTHING;
-}
-
static mp_cmd_t*
-mp_input_read_keys(int time,int paused) {
- int code = mp_input_read_key_code(time);
+interpret_key(int code, int paused)
+{
unsigned int j;
mp_cmd_t* ret;
if(mp_input_key_cb) {
- for( ; code >= 0 ; code = mp_input_read_key_code(0) ) {
- if(code & MP_KEY_DOWN) continue;
+ if (code & MP_KEY_DOWN)
+ return NULL;
code &= ~(MP_KEY_DOWN|MP_NO_REPEAT_KEY);
mp_input_key_cb(code);
- }
return NULL;
}
- for( ; code >= 0 ; code = mp_input_read_key_code(0) ) {
- // key pushed
if(code & MP_KEY_DOWN) {
if(num_key_down > MP_MAX_KEY_DOWN) {
mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_Err2ManyKeyDowns);
- continue;
+ return NULL;
}
code &= ~MP_KEY_DOWN;
// Check if we don't already have this key as pushed
@@ -1119,12 +1018,12 @@ mp_input_read_keys(int time,int paused) {
break;
}
if(j != num_key_down)
- continue;
+ return NULL;
key_down[num_key_down] = code;
num_key_down++;
last_key_down = GetTimer();
ar_state = 0;
- continue;
+ return NULL;
}
// key released
// Check if the key is in the down key, driver which can't send push event
@@ -1136,7 +1035,7 @@ mp_input_read_keys(int time,int paused) {
if(j == num_key_down) { // key was not in the down keys : add it
if(num_key_down > MP_MAX_KEY_DOWN) {
mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_Err2ManyKeyDowns);
- continue;
+ return NULL;
}
key_down[num_key_down] = code;
num_key_down++;
@@ -1154,10 +1053,11 @@ mp_input_read_keys(int time,int paused) {
mp_cmd_free(ar_cmd);
ar_cmd = NULL;
}
- if(ret)
- return ret;
- }
+ return ret;
+}
+static mp_cmd_t *check_autorepeat(int paused)
+{
// No input : autorepeat ?
if(ar_rate > 0 && ar_state >=0 && num_key_down > 0 && ! (key_down[num_key_down-1] & MP_NO_REPEAT_KEY)) {
unsigned int t = GetTimer();
@@ -1177,103 +1077,127 @@ mp_input_read_keys(int time,int paused) {
return mp_cmd_clone(ar_cmd);
}
}
-
return NULL;
}
-static mp_cmd_t*
-mp_input_read_cmds(int time) {
-#ifdef HAVE_POSIX_SELECT
- fd_set fds;
- struct timeval tv,*time_val;
-#endif
- int i,n = 0,max_fd = 0,got_cmd = 0;
- mp_cmd_t* ret;
- static int last_loop = 0;
-
- if(num_cmd_fd == 0)
- return NULL;
+static mp_cmd_t *read_events(int time, int paused)
+{
+ int i;
+ int got_cmd = 0;
+ for (i = 0; i < num_key_fd; i++)
+ if (key_fds[i].dead) {
+ mp_input_rm_key_fd(key_fds[i].fd);
+ i--;
+ }
+ for (i = 0; i < num_cmd_fd; i++)
+ if (cmd_fds[i].dead || cmd_fds[i].eof) {
+ mp_input_rm_cmd_fd(cmd_fds[i].fd);
+ i--;
+ }
+ else if (cmd_fds[i].got_cmd)
+ got_cmd = 1;
#ifdef HAVE_POSIX_SELECT
- FD_ZERO(&fds);
-#endif
- for(i = 0; (unsigned int)i < num_cmd_fd ; i++) {
- if (cmd_fds[i].dead || cmd_fds[i].eof) {
- mp_input_rm_cmd_fd(cmd_fds[i].fd);
- i--;
- continue;
- } else if (cmd_fds[i].no_select)
- continue;
- if (cmd_fds[i].got_cmd)
- got_cmd = 1;
- if(cmd_fds[i].fd > max_fd)
- max_fd = cmd_fds[i].fd;
-#ifdef HAVE_POSIX_SELECT
- FD_SET(cmd_fds[i].fd,&fds);
+ int max_fd = 0, num_fd = 0;
+ fd_set fds;
+ FD_ZERO(&fds);
+ if (!got_cmd) {
+ for (i = 0; i < num_key_fd; i++) {
+ if (key_fds[i].no_select)
+ continue;
+ if (key_fds[i].fd > max_fd)
+ max_fd = key_fds[i].fd;
+ FD_SET(key_fds[i].fd, &fds);
+ num_fd++;
+ }
+ for (i = 0; i < num_cmd_fd; i++) {
+ if (cmd_fds[i].no_select)
+ continue;
+ if (cmd_fds[i].fd > max_fd)
+ max_fd = cmd_fds[i].fd;
+ FD_SET(cmd_fds[i].fd, &fds);
+ num_fd++;
+ }
+ if (num_fd > 0) {
+ struct timeval tv, *time_val;
+ if (time >= 0) {
+ tv.tv_sec = time / 1000;
+ tv.tv_usec = (time % 1000) * 1000;
+ time_val = &tv;
+ }
+ else
+ time_val = NULL;
+ if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
+ if (errno != EINTR)
+ mp_msg(MSGT_INPUT, MSGL_ERR, MSGTR_INPUT_INPUT_ErrSelect,
+ strerror(errno));
+ FD_ZERO(&fds);
+ }
+ }
+ }
+#else
+ if (!got_cmd)
+ usec_sleep(time * 1000);
#endif
- n++;
- }
- if(num_cmd_fd == 0)
- return NULL;
+ for (i = 0; i < num_key_fd; i++) {
#ifdef HAVE_POSIX_SELECT
- if(time >= 0) {
- tv.tv_sec=time/1000;
- tv.tv_usec = (time%1000)*1000;
- time_val = &tv;
- } else
- time_val = NULL;
-
- while(n > 0) {
- if((i = select(max_fd+1,&fds,NULL,NULL,time_val)) <= 0) {
- if(i < 0) {
- if(errno == EINTR)
- continue;
- mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrSelect,strerror(errno));
- }
- if(!got_cmd)
- return NULL;
- }
- break;
- }
+ if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds))
+ continue;
#endif
- for(i = last_loop + 1; i != last_loop ; i++) {
- int r = 0;
- char* cmd;
- if((unsigned int)i >= num_cmd_fd) {
- i = -1;
- last_loop++;
- last_loop %= (num_cmd_fd+1);
- continue;
+ int code;
+ if (key_fds[i].fd == 0) { // getch2 handler special-cased for now
+ getch2();
+ code = mplayer_get_key(0);
+ if (code < 0)
+ code = MP_INPUT_NOTHING;
+ }
+ else
+ code = ((mp_key_func_t)key_fds[i].read_func)(key_fds[i].fd);
+ if (code >= 0) {
+ mp_cmd_t *ret = interpret_key(code, paused);
+ if (ret)
+ return ret;
+ }
+ else if (code == MP_INPUT_ERROR)
+ mp_msg(MSGT_INPUT, MSGL_ERR, MSGTR_INPUT_INPUT_ErrOnKeyInFd,
+ key_fds[i].fd);
+ else if (code == MP_INPUT_DEAD) {
+ mp_msg(MSGT_INPUT, MSGL_ERR, MSGTR_INPUT_INPUT_ErrDeadKeyOnFd,
+ key_fds[i].fd);
+ key_fds[i].dead = 1;
+ }
}
+ mp_cmd_t *autorepeat_cmd = check_autorepeat(paused);
+ if (autorepeat_cmd)
+ return autorepeat_cmd;
+
+ for (i = 0; i < num_cmd_fd; i++) {
#ifdef HAVE_POSIX_SELECT
- if (!cmd_fds[i].no_select && ! FD_ISSET(cmd_fds[i].fd, &fds)
- && !cmd_fds[i].got_cmd)
- continue;
+ if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds))
+ continue;
#endif
-
- r = mp_input_read_cmd(&cmd_fds[i],&cmd);
- if(r < 0) {
- if(r == MP_INPUT_ERROR)
- mp_msg(MSGT_INPUT,MSGL_ERR,MSGTR_INPUT_INPUT_ErrOnCmdFd,cmd_fds[i].fd);
- else if(r == MP_INPUT_DEAD)
- cmd_fds[i].dead = 1;
- continue;
+ char *cmd;
+ int r = mp_input_read_cmd(&cmd_fds[i], &cmd);
+ if (r >= 0) {
+ mp_cmd_t *ret = mp_input_parse_cmd(cmd);
+ free(cmd);
+ if (ret)
+ return ret;
+ }
+ else if (r == MP_INPUT_ERROR)
+ mp_msg(MSGT_INPUT, MSGL_ERR, MSGTR_INPUT_INPUT_ErrOnCmdFd,
+ cmd_fds[i].fd);
+ else if (r == MP_INPUT_DEAD)
+ cmd_fds[i].dead = 1;
}
- ret = mp_input_parse_cmd(cmd);
- free(cmd);
- if(!ret)
- continue;
- last_loop = i;
- return ret;
- }
-
- last_loop = 0;
- return NULL;
+
+ return NULL;
}
+
int
mp_input_queue_cmd(mp_cmd_t* cmd) {
if(cmd_queue_length >= CMD_QUEUE_SIZE)
@@ -1316,9 +1240,7 @@ mp_input_get_cmd(int time, int paused, int peek_only) {
ret = mp_input_get_queued_cmd(peek_only);
if(ret) break;
from_queue = 0;
- ret = mp_input_read_keys(time,paused);
- if(ret) break;
- ret = mp_input_read_cmds(time);
+ ret = read_events(time, paused);
break;
}
if(!ret) return NULL;