summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-07-17 04:47:50 +0300
committerUoti Urpala <uau@mplayer2.org>2011-07-17 07:36:09 +0300
commit82b8f89baeafc2b2b39381f2ee14e4a2b2619b4c (patch)
treeb7bd847d8666233ef289224162e1e5a8668b685d
parent1916b95b8d3737ac783eb6351664f9892824e5c5 (diff)
downloadmpv-82b8f89baeafc2b2b39381f2ee14e4a2b2619b4c.tar.bz2
mpv-82b8f89baeafc2b2b39381f2ee14e4a2b2619b4c.tar.xz
input: rework event reading and command queuing
Rework much of the logic related to reading from event sources and queuing commands. The two biggest architecture changes are: - The code buffering keycodes in mp_fifo.c is gone. Instead key input is now immediately fed to input.c and interpreted as commands, and then the commands are buffered instead. - mp_input_get_cmd() now always tries to read every available event from every event source and convert them to (buffered) commands. Before it would only process new events until one new command became available. Some relevant behavior changes: - Before commands could be lost when stream code called mp_input_check_interrupt() which read commands (to see if they were of types that triggered aborts during slow IO tasks) and then threw them away. This was especially an issue if cache was enabled and slow to read. Fixed - now it's possible to check whether there are queued commands which will abort playback of the current file without throwing other commands away. - mp_input_check_interrupt() now prints a message if it returns true. This is especially useful because the failures caused by aborted stream reads can trigger error messages from other code that was doing the read; the new message makes it more obvious what the cause of the subsequent error messages is. - It's now possible to again avoid making stdin non-blocking (which caused some issues) without reintroducing extra latency. The change will be done in a subsequent commit. - Event sources that do not support select() should now have somewhat lower latency in certain situations as they will be checked both before and after select()/sleep in input reading; before the sleep always happened first even if such sources already had queued input. Before the key fifo was also handled in this manner (first key triggered select, but if multiple were read then rest could be delayed; however in most cases this didn't add latency in practice as after central code started doing command handling it queried for further commands with a max sleep time of 0). - Key fifo limiting is more accurate now: it now counts actual commands intead of keycodes, and all queued keys are read immediately from input devices so they can be counted correctly. - Since keypresses are now interpreted immediately, commands which change keybindings will no longer affect following keypresses that have already been read before the command is executed. This should not be an issue in practice with current keybinding behavior.
-rw-r--r--cfg-mplayer.h2
-rw-r--r--defaultopts.c2
-rw-r--r--input/input.c356
-rw-r--r--input/input.h5
-rw-r--r--libvo/video_out.c2
-rw-r--r--mp_fifo.c73
-rw-r--r--mp_fifo.h4
-rw-r--r--mplayer.c5
-rw-r--r--options.h2
9 files changed, 224 insertions, 227 deletions
diff --git a/cfg-mplayer.h b/cfg-mplayer.h
index b3b0ab91c3..93fb58f480 100644
--- a/cfg-mplayer.h
+++ b/cfg-mplayer.h
@@ -988,7 +988,7 @@ const m_option_t mplayer_opts[]={
{"slave", &slave_mode, CONF_TYPE_FLAG,CONF_GLOBAL , 0, 1, NULL},
OPT_MAKE_FLAGS("idle", player_idle_mode, CONF_GLOBAL),
{"use-stdin", "-use-stdin has been renamed to -noconsolecontrols, use that instead.", CONF_TYPE_PRINT, 0, 0, 0, NULL},
- OPT_INTRANGE("key-fifo-size", key_fifo_size, CONF_GLOBAL, 2, 65000),
+ OPT_INTRANGE("key-fifo-size", input.key_fifo_size, CONF_GLOBAL, 2, 65000),
OPT_MAKE_FLAGS("consolecontrols", consolecontrols, CONF_GLOBAL),
{"mouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL},
{"nomouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 1, 0, NULL},
diff --git a/defaultopts.c b/defaultopts.c
index 8bb927bb54..b498fef026 100644
--- a/defaultopts.c
+++ b/defaultopts.c
@@ -32,7 +32,6 @@ void set_default_mplayer_options(struct MPOpts *opts)
.initial_audio_sync = 1,
.term_osd = 1,
.term_osd_esc = "\x1b[A\r\x1b[K",
- .key_fifo_size = 7,
.consolecontrols = 1,
.doubleclick_time = 300,
.audio_id = -1,
@@ -58,6 +57,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
},
.input = {
.config_file = "input.conf",
+ .key_fifo_size = 7,
.ar_delay = 100,
.ar_rate = 8,
.use_joystick = 1,
diff --git a/input/input.c b/input/input.c
index b8ff15a0c7..fe7acbb3e7 100644
--- a/input/input.c
+++ b/input/input.c
@@ -29,6 +29,7 @@
#include <sys/time.h>
#include <fcntl.h>
#include <ctype.h>
+#include <assert.h>
#include "input.h"
#include "mp_fifo.h"
@@ -550,8 +551,6 @@ static const struct cmd_bind def_cmd_binds[] = {
#define MP_MAX_CMD_FD 10
#endif
-#define CMD_QUEUE_SIZE 100
-
struct input_fd {
int fd;
union {
@@ -582,6 +581,13 @@ struct cmd_bind_section {
struct cmd_bind_section *next;
};
+struct cmd_queue {
+ struct mp_cmd *first;
+ struct mp_cmd *last;
+ int num_cmds;
+ int num_abort_cmds;
+};
+
struct input_ctx {
// Autorepeat stuff
short ar_state;
@@ -590,6 +596,9 @@ struct input_ctx {
// Autorepeat config
unsigned int ar_delay;
unsigned int ar_rate;
+ // Maximum number of queued commands from keypresses (limit to avoid
+ // repeated slow commands piling up)
+ int key_fifo_size;
// these are the keys currently down
int key_down[MP_MAX_KEY_DOWN];
@@ -605,14 +614,18 @@ struct input_ctx {
struct cmd_bind *cmd_binds;
struct cmd_bind *cmd_binds_default;
+ // Used to track whether we managed to read something while checking
+ // events sources. If yes, the sources may have more queued.
+ bool got_new_events;
+
struct input_fd key_fds[MP_MAX_KEY_FD];
unsigned int num_key_fd;
struct input_fd cmd_fds[MP_MAX_CMD_FD];
unsigned int num_cmd_fd;
- mp_cmd_t *cmd_queue[CMD_QUEUE_SIZE];
- unsigned int cmd_queue_length, cmd_queue_start, cmd_queue_end;
+ struct cmd_queue key_cmd_queue;
+ struct cmd_queue control_cmd_queue;
};
@@ -685,6 +698,46 @@ static char *get_key_combo_name(int *keys, int max)
return ret;
}
+static bool is_abort_cmd(int cmd_id)
+{
+ switch (cmd_id) {
+ case MP_CMD_QUIT:
+ case MP_CMD_PLAY_TREE_STEP:
+ case MP_CMD_PLAY_TREE_UP_STEP:
+ case MP_CMD_PLAY_ALT_SRC_STEP:
+ return true;
+ }
+ return false;
+}
+
+static void queue_pop(struct cmd_queue *queue)
+{
+ assert(queue->num_cmds > 0);
+ struct mp_cmd *cmd = queue->first;
+ queue->first = cmd->queue_next;
+ queue->num_cmds--;
+ queue->num_abort_cmds -= is_abort_cmd(cmd->id);
+}
+
+static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd,
+ bool at_head)
+{
+ if (!queue->num_cmds) {
+ queue->first = cmd;
+ queue->last = cmd;
+ } else if (at_head) {
+ queue->first->queue_prev = cmd;
+ cmd->queue_next = queue->first;
+ queue->first = cmd;
+ } else {
+ queue->last->queue_next = cmd;
+ cmd->queue_prev = queue->last;
+ queue->last = cmd;
+ }
+ queue->num_cmds++;
+ queue->num_abort_cmds += is_abort_cmd(cmd->id);
+}
+
int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select,
int read_func(int fd, char *dest, int size),
int close_func(int fd))
@@ -1261,193 +1314,199 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx)
return NULL;
}
+void mp_input_feed_key(struct input_ctx *ictx, int code)
+{
+ ictx->got_new_events = true;
+ if (code == MP_INPUT_RELEASE_ALL) {
+ memset(ictx->key_down, 0, sizeof(ictx->key_down));
+ ictx->num_key_down = 0;
+ ictx->last_key_down = 0;
+ return;
+ }
+ struct mp_cmd *cmd = interpret_key(ictx, code);
+ if (!cmd)
+ return;
+ struct cmd_queue *queue = &ictx->key_cmd_queue;
+ if (queue->num_cmds >= ictx->key_fifo_size &&
+ (!is_abort_cmd(cmd->id) || queue->num_abort_cmds))
+ return;
+ queue_add(queue, cmd, false);
+}
+
+static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd)
+{
+ int r;
+ char *text;
+ while ((r = read_cmd(cmd_fd, &text)) >= 0) {
+ ictx->got_new_events = true;
+ struct mp_cmd *cmd = mp_input_parse_cmd(text);
+ talloc_free(text);
+ if (cmd)
+ queue_add(&ictx->control_cmd_queue, cmd, false);
+ if (!cmd_fd->got_cmd)
+ return;
+ }
+ if (r == MP_INPUT_ERROR)
+ mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command file descriptor %d\n",
+ cmd_fd->fd);
+ else if (r == MP_INPUT_DEAD)
+ cmd_fd->dead = true;
+}
+
+static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd)
+{
+ int code = key_fd->read_func.key(key_fd->ctx, key_fd->fd);
+ if (code >= 0 || code == MP_INPUT_RELEASE_ALL) {
+ mp_input_feed_key(ictx, code);
+ return;
+ }
+
+ if (code == MP_INPUT_ERROR)
+ mp_tmsg(MSGT_INPUT, MSGL_ERR,
+ "Error on key input file descriptor %d\n", key_fd->fd);
+ else if (code == MP_INPUT_DEAD) {
+ mp_tmsg(MSGT_INPUT, MSGL_ERR,
+ "Dead key input on file descriptor %d\n", key_fd->fd);
+ key_fd->dead = true;
+ }
+}
/**
* \param time time to wait at most for an event in milliseconds
*/
-static mp_cmd_t *read_events(struct input_ctx *ictx, int time)
+static void read_events(struct input_ctx *ictx, int time)
{
- int i;
- int got_cmd = 0;
+ ictx->got_new_events = false;
struct input_fd *key_fds = ictx->key_fds;
struct input_fd *cmd_fds = ictx->cmd_fds;
- for (i = 0; i < ictx->num_key_fd; i++)
+ for (int i = 0; i < ictx->num_key_fd; i++)
if (key_fds[i].dead) {
mp_input_rm_key_fd(ictx, key_fds[i].fd);
i--;
- }
- for (i = 0; i < ictx->num_cmd_fd; i++)
+ } else if (time && key_fds[i].no_select)
+ read_key_fd(ictx, &key_fds[i]);
+ for (int i = 0; i < ictx->num_cmd_fd; i++)
if (cmd_fds[i].dead || cmd_fds[i].eof) {
mp_input_rm_cmd_fd(ictx, cmd_fds[i].fd);
i--;
- } else if (cmd_fds[i].got_cmd)
- got_cmd = 1;
+ } else if (time && cmd_fds[i].no_select)
+ read_cmd_fd(ictx, &cmd_fds[i]);
+ if (ictx->got_new_events)
+ time = 0;
#ifdef HAVE_POSIX_SELECT
fd_set fds;
FD_ZERO(&fds);
- if (!got_cmd) {
- int max_fd = 0;
- for (i = 0; i < ictx->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);
- }
- for (i = 0; i < ictx->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);
- }
- 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_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
- strerror(errno));
- FD_ZERO(&fds);
- }
+ int max_fd = 0;
+ for (int i = 0; i < ictx->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);
+ }
+ for (int i = 0; i < ictx->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);
+ }
+ 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_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
+ strerror(errno));
+ FD_ZERO(&fds);
}
#else
- if (!got_cmd && time)
+ if (time)
usec_sleep(time * 1000);
#endif
- for (i = 0; i < ictx->num_key_fd; i++) {
+ for (int i = 0; i < ictx->num_key_fd; i++) {
#ifdef HAVE_POSIX_SELECT
if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds))
continue;
#endif
-
- int code;
- while (1) {
- code = key_fds[i].read_func.key(key_fds[i].ctx, key_fds[i].fd);
- if (code < 0) {
- if (code == MP_INPUT_RELEASE_ALL) {
- memset(ictx->key_down, 0, sizeof(ictx->key_down));
- ictx->num_key_down = 0;
- ictx->last_key_down = 0;
- continue;
- }
- break;
- }
- mp_cmd_t *ret = interpret_key(ictx, code);
- if (ret)
- return ret;
- }
- if (code == MP_INPUT_ERROR)
- mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on key input "
- "file descriptor %d\n", key_fds[i].fd);
- else if (code == MP_INPUT_DEAD) {
- mp_tmsg(MSGT_INPUT, MSGL_ERR, "Dead key input on "
- "file descriptor %d\n", key_fds[i].fd);
- key_fds[i].dead = 1;
- }
+ read_key_fd(ictx, &key_fds[i]);
}
- mp_cmd_t *autorepeat_cmd = check_autorepeat(ictx);
- if (autorepeat_cmd)
- return autorepeat_cmd;
- for (i = 0; i < ictx->num_cmd_fd; i++) {
+ for (int i = 0; i < ictx->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)
+ if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds))
continue;
#endif
- char *cmd;
- int r;
- while ((r = read_cmd(&cmd_fds[i], &cmd)) >= 0) {
- mp_cmd_t *ret = mp_input_parse_cmd(cmd);
- talloc_free(cmd);
- if (ret)
- return ret;
- }
- if (r == MP_INPUT_ERROR)
- mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command "
- "file descriptor %d\n", cmd_fds[i].fd);
- else if (r == MP_INPUT_DEAD)
- cmd_fds[i].dead = 1;
+ read_cmd_fd(ictx, &cmd_fds[i]);
}
-
- return NULL;
}
+/* To support blocking file descriptors we don't loop the read over
+ * every source until it's known to be empty. Instead we use this wrapper
+ * to run select() again.
+ */
+static void read_all_events(struct input_ctx *ictx, int time)
+{
+ while (1) {
+ read_events(ictx, time);
+ if (!ictx->got_new_events)
+ return;
+ time = 0;
+ }
+}
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
{
- if (!cmd || ictx->cmd_queue_length >= CMD_QUEUE_SIZE)
+ ictx->got_new_events = true;
+ if (!cmd)
return 0;
- ictx->cmd_queue[ictx->cmd_queue_end] = cmd;
- ictx->cmd_queue_end = (ictx->cmd_queue_end + 1) % CMD_QUEUE_SIZE;
- ictx->cmd_queue_length++;
+ queue_add(&ictx->control_cmd_queue, cmd, true);
return 1;
}
-static mp_cmd_t *get_queued_cmd(struct input_ctx *ictx, int peek_only)
-{
- mp_cmd_t *ret;
-
- if (ictx->cmd_queue_length == 0)
- return NULL;
-
- ret = ictx->cmd_queue[ictx->cmd_queue_start];
-
- if (!peek_only) {
- ictx->cmd_queue_length--;
- ictx->cmd_queue_start = (ictx->cmd_queue_start + 1) % CMD_QUEUE_SIZE;
- }
-
- return ret;
-}
-
/**
* \param peek_only when set, the returned command stays in the queue.
* Do not free the returned cmd whe you set this!
*/
mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
{
- mp_cmd_t *ret = NULL;
- struct cmd_filter *cf;
- int from_queue;
-
if (async_quit_request)
return mp_input_parse_cmd("quit 1");
- while (1) {
- from_queue = 1;
- ret = get_queued_cmd(ictx, peek_only);
- if (ret)
- break;
- from_queue = 0;
- ret = read_events(ictx, time);
- if (!ret) {
- from_queue = 1;
- ret = get_queued_cmd(ictx, peek_only);
- }
- break;
- }
- if (!ret)
- return NULL;
- for (cf = cmd_filters; cf; cf = cf->next) {
+ if (ictx->control_cmd_queue.num_cmds || ictx->key_cmd_queue.num_cmds)
+ time = 0;
+ read_all_events(ictx, time);
+ struct mp_cmd *ret;
+ struct cmd_queue *queue = &ictx->control_cmd_queue;
+ if (!queue->num_cmds)
+ queue = &ictx->key_cmd_queue;
+ if (!queue->num_cmds) {
+ queue = NULL;
+ ret = check_autorepeat(ictx);
+ if (!ret)
+ return NULL;
+ } else
+ ret = queue->first;
+
+ for (struct cmd_filter *cf = cmd_filters; cf; cf = cf->next) {
if (cf->filter(ret, cf->ctx)) {
- if (peek_only && from_queue)
- // The filter ate the cmd, so we remove it from queue
- ret = get_queued_cmd(ictx, 0);
+ // The filter ate the cmd, so remove it from the queue
+ if (queue)
+ queue_pop(queue);
mp_cmd_free(ret);
- return NULL;
+ // Retry with next command
+ return mp_input_get_cmd(ictx, 0, peek_only);
}
}
- if (!from_queue && peek_only)
- mp_input_queue_cmd(ictx, ret);
+ if (!peek_only && queue)
+ queue_pop(queue);
return ret;
}
@@ -1752,6 +1811,7 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf)
{
struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
*ictx = (struct input_ctx){
+ .key_fifo_size = input_conf->key_fifo_size,
.ar_state = -1,
.ar_delay = input_conf->ar_delay,
.ar_rate = input_conf->ar_rate,
@@ -1917,19 +1977,15 @@ static int print_cmd_list(m_option_t *cfg)
*/
int mp_input_check_interrupt(struct input_ctx *ictx, int time)
{
- mp_cmd_t *cmd;
- if ((cmd = mp_input_get_cmd(ictx, time, 1)) == NULL)
- return 0;
- switch (cmd->id) {
- case MP_CMD_QUIT:
- case MP_CMD_PLAY_TREE_STEP:
- case MP_CMD_PLAY_TREE_UP_STEP:
- case MP_CMD_PLAY_ALT_SRC_STEP:
- // The cmd will be executed when we are back in the main loop
- return 1;
+ for (int i = 0; ; i++) {
+ if (async_quit_request || ictx->key_cmd_queue.num_abort_cmds ||
+ ictx->control_cmd_queue.num_abort_cmds) {
+ mp_tmsg(MSGT_INPUT, MSGL_WARN, "Received command to move to "
+ "another file. Aborting current processing.\n");
+ return true;
+ }
+ if (i)
+ return false;
+ read_all_events(ictx, time);
}
- // remove the cmd from the queue
- cmd = mp_input_get_cmd(ictx, time, 0);
- mp_cmd_free(cmd);
- return 0;
}
diff --git a/input/input.h b/input/input.h
index ebabc16491..aaacfbe164 100644
--- a/input/input.h
+++ b/input/input.h
@@ -202,6 +202,8 @@ typedef struct mp_cmd {
int nargs;
struct mp_cmd_arg args[MP_CMD_MAX_ARGS];
int pausing;
+ struct mp_cmd *queue_prev;
+ struct mp_cmd *queue_next;
} mp_cmd_t;
@@ -234,6 +236,9 @@ int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select,
int read_func(void *ctx, int fd),
int close_func(int fd), void *ctx);
+// Feed a keypress (alternative to being returned from read_func above)
+void mp_input_feed_key(struct input_ctx *ictx, int code);
+
// As for the cmd one you usually don't need this function.
void mp_input_rm_key_fd(struct input_ctx *ictx, int fd);
diff --git a/libvo/video_out.c b/libvo/video_out.c
index 443ef87cde..8b6292978f 100644
--- a/libvo/video_out.c
+++ b/libvo/video_out.c
@@ -434,7 +434,7 @@ static int event_fd_callback(void *ctx, int fd)
{
struct vo *vo = ctx;
vo_check_events(vo);
- return mplayer_get_key(vo->key_fifo, 0);
+ return MP_INPUT_NOTHING;
}
int vo_config(struct vo *vo, uint32_t width, uint32_t height,
diff --git a/mp_fifo.c b/mp_fifo.c
index 4bda7209e0..ffb3608fbf 100644
--- a/mp_fifo.c
+++ b/mp_fifo.c
@@ -29,86 +29,23 @@
struct mp_fifo {
struct MPOpts *opts;
- int *data;
- int readpos;
- int size;
- int num_entries;
- int max_up;
- int num_up;
+ struct input_ctx *input;
int last_key_down;
unsigned last_down_time;
};
-struct mp_fifo *mp_fifo_create(struct MPOpts *opts)
+struct mp_fifo *mp_fifo_create(struct input_ctx *input, struct MPOpts *opts)
{
struct mp_fifo *fifo = talloc_zero(NULL, struct mp_fifo);
+ fifo->input = input;
fifo->opts = opts;
- /* Typical mouse wheel use will generate a sequence repeating 3 events:
- * down, doubleclick, up, down, doubleclick, up, ...
- * Normally only one of those event types triggers a command,
- * so allow opts->key_fifo_size such repeats.
- */
- fifo->max_up = opts->key_fifo_size;
- fifo->size = opts->key_fifo_size * 3;
- fifo->data = talloc_array_ptrtype(fifo, fifo->data, fifo->size);
return fifo;
}
-static bool is_up(int code)
-{
- return code > 0 && !(code & MP_KEY_DOWN)
- && !(code >= MOUSE_BTN0_DBL && code < MOUSE_BTN_DBL_END);
-}
-
-static int fifo_peek(struct mp_fifo *fifo, int offset)
-{
- return fifo->data[(fifo->readpos + offset) % fifo->size];
-}
-
-static int fifo_read(struct mp_fifo *fifo)
-{
- int code = fifo_peek(fifo, 0);
- fifo->readpos += 1;
- fifo->readpos %= fifo->size;
- fifo->num_entries--;
- fifo->num_up -= is_up(code);
- assert(fifo->num_entries >= 0);
- assert(fifo->num_up >= 0);
- return code;
-}
-
-static void fifo_write(struct mp_fifo *fifo, int code)
-{
- fifo->data[(fifo->readpos + fifo->num_entries) % fifo->size] = code;
- fifo->num_entries++;
- fifo->num_up += is_up(code);
- assert(fifo->num_entries <= fifo->size);
- assert(fifo->num_up <= fifo->max_up);
-}
-
-static void mplayer_put_key_internal(struct mp_fifo *fifo, int code)
-{
- // Clear key-down state if we're forced to drop entries
- if (fifo->num_entries >= fifo->size - 1
- || fifo->num_up >= fifo->max_up) {
- if (fifo_peek(fifo, fifo->num_entries - 1) != MP_INPUT_RELEASE_ALL)
- fifo_write(fifo, MP_INPUT_RELEASE_ALL);
- } else
- fifo_write(fifo, code);
-}
-
-int mplayer_get_key(void *ctx, int fd)
-{
- struct mp_fifo *fifo = ctx;
- if (!fifo->num_entries)
- return MP_INPUT_NOTHING;
- return fifo_read(fifo);
-}
-
static void put_double(struct mp_fifo *fifo, int code)
{
if (code >= MOUSE_BTN0 && code < MOUSE_BTN_END)
- mplayer_put_key_internal(fifo, code - MOUSE_BTN0 + MOUSE_BTN0_DBL);
+ mp_input_feed_key(fifo->input, code - MOUSE_BTN0 + MOUSE_BTN0_DBL);
}
void mplayer_put_key(struct mp_fifo *fifo, int code)
@@ -120,7 +57,7 @@ void mplayer_put_key(struct mp_fifo *fifo, int code)
&& (code & ~MP_KEY_DOWN) >= MOUSE_BTN0_DBL
&& (code & ~MP_KEY_DOWN) < MOUSE_BTN_DBL_END)
return;
- mplayer_put_key_internal(fifo, code);
+ mp_input_feed_key(fifo->input, code);
if (code & MP_KEY_DOWN) {
code &= ~MP_KEY_DOWN;
if (fifo->last_key_down == code
diff --git a/mp_fifo.h b/mp_fifo.h
index 125b67eb2c..01c1fb0c37 100644
--- a/mp_fifo.h
+++ b/mp_fifo.h
@@ -20,11 +20,11 @@
#define MPLAYER_MP_FIFO_H
struct mp_fifo;
-int mplayer_get_key(void *ctx, int fd);
void mplayer_put_key(struct mp_fifo *fifo, int code);
// Can be freed with talloc_free()
+struct input_ctx;
struct MPOpts;
-struct mp_fifo *mp_fifo_create(struct MPOpts *opts);
+struct mp_fifo *mp_fifo_create(struct input_ctx *input, struct MPOpts *opts);
#ifdef IS_OLD_VO
diff --git a/mplayer.c b/mplayer.c
index c8216fae90..c10cb61223 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -3732,7 +3732,7 @@ static void run_playloop(struct MPContext *mpctx)
static int read_keys(void *ctx, int fd)
{
getch2(ctx);
- return mplayer_get_key(ctx, 0);
+ return MP_INPUT_NOTHING;
}
static bool attachment_is_font(struct demux_attachment *att)
@@ -3887,7 +3887,6 @@ int i;
}
}
}
- mpctx->key_fifo = mp_fifo_create(opts);
print_version("MPlayer2");
@@ -4079,7 +4078,7 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){
// Init input system
current_module = "init_input";
mpctx->input = mp_input_init(&opts->input);
- mp_input_add_key_fd(mpctx->input, -1,0,mplayer_get_key,NULL, mpctx->key_fifo);
+ mpctx->key_fifo = mp_fifo_create(mpctx->input, opts);
if(slave_mode) {
#if USE_FD0_CMD_SELECT
int flags = fcntl(0, F_GETFL);
diff --git a/options.h b/options.h
index 521d3a9751..61f77053bc 100644
--- a/options.h
+++ b/options.h
@@ -59,7 +59,6 @@ typedef struct MPOpts {
char *term_osd_esc;
char *playing_msg;
int player_idle_mode;
- int key_fifo_size;
int consolecontrols;
int doubleclick_time;
int list_properties;
@@ -123,6 +122,7 @@ typedef struct MPOpts {
struct input_conf {
char *config_file;
+ int key_fifo_size;
unsigned int ar_delay;
unsigned int ar_rate;
char *js_dev;