aboutsummaryrefslogtreecommitdiffhomepage
path: root/input
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2014-09-10 03:16:43 +0200
committerGravatar wm4 <wm4@nowhere>2014-09-10 03:24:45 +0200
commite9b756c7ad7d51b41b2ccf0f72eb904b0eea2169 (patch)
tree10f6909622b28c8e5e7376137d1651e44055d50f /input
parent564b957cc31a33124a935ea8678e5bbb710fc082 (diff)
input: remove central select() call
This is now unused. Get rid of it and all surrounding infrastructure, and replace the remaining "wakeup pipe" with a semaphore.
Diffstat (limited to 'input')
-rw-r--r--input/input.c404
-rw-r--r--input/input.h41
-rw-r--r--input/lirc.c4
3 files changed, 37 insertions, 412 deletions
diff --git a/input/input.c b/input/input.c
index cc4cc6285c..5415b369d7 100644
--- a/input/input.c
+++ b/input/input.c
@@ -35,6 +35,7 @@
#include <libavutil/common.h>
#include "osdep/io.h"
+#include "osdep/semaphore.h"
#include "misc/rendezvous.h"
#include "input.h"
@@ -80,24 +81,7 @@ struct cmd_bind_section {
struct cmd_bind_section *next;
};
-#define MP_MAX_FDS 10
-
-struct input_fd {
- struct mp_log *log;
- int fd;
- int (*read_key)(void *ctx, int fd);
- int (*read_cmd)(void *ctx, int fd, char *dest, int size);
- int (*close_func)(void *ctx, int fd);
- void *ctx;
- unsigned eof : 1;
- unsigned drop : 1;
- unsigned dead : 1;
- unsigned got_cmd : 1;
- unsigned select : 1;
- // These fields are for the cmd fds.
- char *buffer;
- int pos, size;
-};
+#define MP_MAX_SOURCES 10
#define MAX_ACTIVE_SECTIONS 50
@@ -112,9 +96,7 @@ struct cmd_queue {
struct input_ctx {
pthread_mutex_t mutex;
- pthread_cond_t wakeup;
- pthread_t mainthread;
- bool mainthread_set;
+ sem_t wakeup;
struct mp_log *log;
struct mpv_global *global;
struct input_opts *opts;
@@ -170,16 +152,10 @@ struct input_ctx {
unsigned int mouse_event_counter;
- struct input_fd fds[MP_MAX_FDS];
- unsigned int num_fds;
- struct mp_input_src *sources[MP_MAX_FDS];
+ struct mp_input_src *sources[MP_MAX_SOURCES];
int num_sources;
struct cmd_queue cmd_queue;
-
- bool need_wakeup;
- bool in_select;
- int wakeup_pipe[2];
};
static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
@@ -812,283 +788,13 @@ unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx)
return ret;
}
-int input_default_read_cmd(void *ctx, int fd, char *buf, int l)
-{
- while (1) {
- int r = read(fd, buf, l);
- // Error ?
- if (r < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN)
- return MP_INPUT_NOTHING;
- return MP_INPUT_ERROR;
- // EOF ?
- }
- return r;
- }
-}
-
-int mp_input_add_fd(struct input_ctx *ictx, int unix_fd, int select,
- int read_cmd_func(void *ctx, int fd, char *dest, int size),
- int read_key_func(void *ctx, int fd),
- int close_func(void *ctx, int fd), void *ctx)
-{
- if (select && unix_fd < 0) {
- MP_ERR(ictx, "Invalid fd %d in mp_input_add_fd", unix_fd);
- return 0;
- }
-
- input_lock(ictx);
- struct input_fd *fd = NULL;
- if (ictx->num_fds == MP_MAX_FDS) {
- MP_ERR(ictx, "Too many file descriptors.\n");
- } else {
- fd = &ictx->fds[ictx->num_fds];
- *fd = (struct input_fd){
- .log = ictx->log,
- .fd = unix_fd,
- .select = select,
- .read_cmd = read_cmd_func,
- .read_key = read_key_func,
- .close_func = close_func,
- .ctx = ctx,
- };
- ictx->num_fds++;
- }
- input_unlock(ictx);
- return !!fd;
-}
-
-static void mp_input_rm_fd(struct input_ctx *ictx, int fd)
-{
- struct input_fd *fds = ictx->fds;
- unsigned int i;
-
- for (i = 0; i < ictx->num_fds; i++) {
- if (fds[i].fd == fd)
- break;
- }
- if (i == ictx->num_fds)
- return;
- if (fds[i].close_func)
- fds[i].close_func(fds[i].ctx, fds[i].fd);
- talloc_free(fds[i].buffer);
-
- if (i + 1 < ictx->num_fds)
- memmove(&fds[i], &fds[i + 1],
- (ictx->num_fds - i - 1) * sizeof(struct input_fd));
- ictx->num_fds--;
-}
-
-void mp_input_rm_key_fd(struct input_ctx *ictx, int fd)
-{
- input_lock(ictx);
- mp_input_rm_fd(ictx, fd);
- input_unlock(ictx);
-}
-
-#define MP_CMD_MAX_SIZE 4096
-
-static int read_cmd(struct input_fd *mp_fd, char **ret)
-{
- char *end;
- *ret = NULL;
-
- // Allocate the buffer if it doesn't exist
- if (!mp_fd->buffer) {
- mp_fd->buffer = talloc_size(NULL, MP_CMD_MAX_SIZE);
- mp_fd->pos = 0;
- mp_fd->size = MP_CMD_MAX_SIZE;
- }
-
- // Get some data if needed/possible
- while (!mp_fd->got_cmd && !mp_fd->eof && (mp_fd->size - mp_fd->pos > 1)) {
- int r = mp_fd->read_cmd(mp_fd->ctx, mp_fd->fd, mp_fd->buffer + mp_fd->pos,
- mp_fd->size - 1 - mp_fd->pos);
- // Error ?
- if (r < 0) {
- switch (r) {
- case MP_INPUT_ERROR:
- case MP_INPUT_DEAD:
- MP_ERR(mp_fd, "Error while reading command file descriptor %d: %s\n",
- mp_fd->fd, strerror(errno));
- case MP_INPUT_NOTHING:
- return r;
- case MP_INPUT_RETRY:
- continue;
- }
- // EOF ?
- } else if (r == 0) {
- mp_fd->eof = 1;
- break;
- }
- mp_fd->pos += r;
- break;
- }
-
- mp_fd->got_cmd = 0;
-
- while (1) {
- int l = 0;
- // Find the cmd end
- mp_fd->buffer[mp_fd->pos] = '\0';
- end = strchr(mp_fd->buffer, '\r');
- if (end)
- *end = '\n';
- end = strchr(mp_fd->buffer, '\n');
- // No cmd end ?
- if (!end) {
- // If buffer is full we must drop all until the next \n
- if (mp_fd->size - mp_fd->pos <= 1) {
- MP_ERR(mp_fd, "Command buffer of file descriptor %d is full: "
- "dropping content.\n", mp_fd->fd);
- mp_fd->pos = 0;
- mp_fd->drop = 1;
- }
- break;
- }
- // We already have a cmd : set the got_cmd flag
- else if ((*ret)) {
- mp_fd->got_cmd = 1;
- break;
- }
-
- l = end - mp_fd->buffer;
-
- // Not dropping : put the cmd in ret
- if (!mp_fd->drop)
- *ret = talloc_strndup(NULL, mp_fd->buffer, l);
- else
- mp_fd->drop = 0;
- mp_fd->pos -= l + 1;
- memmove(mp_fd->buffer, end + 1, mp_fd->pos);
- }
-
- if (*ret)
- return 1;
- else
- return MP_INPUT_NOTHING;
-}
-
-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) {
- mp_input_wakeup(ictx);
- struct mp_cmd *cmd = mp_input_parse_cmd(ictx, bstr0(text), "<pipe>");
- talloc_free(text);
- if (cmd)
- queue_add_tail(&ictx->cmd_queue, cmd);
- if (!cmd_fd->got_cmd)
- return;
- }
- if (r == MP_INPUT_ERROR)
- MP_ERR(ictx, "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_key(key_fd->ctx, key_fd->fd);
- if (code >= 0 || code == MP_INPUT_RELEASE_ALL) {
- mp_input_feed_key(ictx, code, 1);
- return;
- }
-
- if (code == MP_INPUT_ERROR)
- MP_ERR(ictx, "Error on key input file descriptor %d\n", key_fd->fd);
- else if (code == MP_INPUT_DEAD) {
- MP_ERR(ictx, "Dead key input on file descriptor %d\n", key_fd->fd);
- key_fd->dead = true;
- }
-}
-
-static void read_fd(struct input_ctx *ictx, struct input_fd *fd)
-{
- if (fd->read_cmd) {
- read_cmd_fd(ictx, fd);
- } else {
- read_key_fd(ictx, fd);
- }
-}
-
-static void remove_dead_fds(struct input_ctx *ictx)
-{
- for (int i = 0; i < ictx->num_fds; i++) {
- if (ictx->fds[i].dead) {
- mp_input_rm_fd(ictx, ictx->fds[i].fd);
- i--;
- }
- }
-}
-
-#if HAVE_POSIX_SELECT
-
-static void input_wait_read(struct input_ctx *ictx, int time)
-{
- fd_set fds;
- FD_ZERO(&fds);
- int max_fd = 0;
- for (int i = 0; i < ictx->num_fds; i++) {
- if (!ictx->fds[i].select)
- continue;
- if (ictx->fds[i].fd > max_fd)
- max_fd = ictx->fds[i].fd;
- FD_SET(ictx->fds[i].fd, &fds);
- }
- struct timeval tv, *time_val;
- tv.tv_sec = time / 1000;
- tv.tv_usec = (time % 1000) * 1000;
- time_val = &tv;
- ictx->in_select = true;
- input_unlock(ictx);
- if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
- if (errno != EINTR)
- MP_ERR(ictx, "Select error: %s\n", strerror(errno));
- FD_ZERO(&fds);
- }
- input_lock(ictx);
- ictx->in_select = false;
- for (int i = 0; i < ictx->num_fds; i++) {
- if (ictx->fds[i].select && !FD_ISSET(ictx->fds[i].fd, &fds))
- continue;
- read_fd(ictx, &ictx->fds[i]);
- }
-}
-
-#else
-
-static void input_wait_read(struct input_ctx *ictx, int time)
-{
- if (time > 0)
- mpthread_cond_timedwait_rel(&ictx->wakeup, &ictx->mutex, time / 1000.0);
-
- for (int i = 0; i < ictx->num_fds; i++)
- read_fd(ictx, &ictx->fds[i]);
-}
-
-#endif
-
-/**
- * \param time time to wait at most for an event in milliseconds
- */
-static void read_events(struct input_ctx *ictx, int time)
+// adjust min time to wait until next repeat event
+static void adjust_max_wait_time(struct input_ctx *ictx, double *time)
{
if (ictx->last_key_down && ictx->ar_rate > 0 && ictx->ar_state >= 0) {
- time = FFMIN(time, 1000 / ictx->ar_rate);
- time = FFMIN(time, ictx->ar_delay);
+ *time = FFMIN(*time, 1000 / ictx->ar_rate);
+ *time = FFMIN(*time, ictx->ar_delay);
}
- time = FFMAX(time, 0);
-
- if (ictx->need_wakeup)
- time = 0;
-
- remove_dead_fds(ictx);
-
- input_wait_read(ictx, time);
}
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
@@ -1132,20 +838,33 @@ void mp_input_wait(struct input_ctx *ictx, double seconds)
{
input_lock(ictx);
if (ictx->cmd_queue.first)
- seconds = 0;
+ seconds = -1;
+ adjust_max_wait_time(ictx, &seconds);
+ input_unlock(ictx);
+ while (sem_trywait(&ictx->wakeup) == 0)
+ seconds = -1;
if (seconds > 0) {
MP_STATS(ictx, "start sleep");
- read_events(ictx, MPMIN(seconds * 1000, INT_MAX));
+ struct timespec ts =
+ mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), seconds));
+ sem_timedwait(&ictx->wakeup, &ts);
MP_STATS(ictx, "end sleep");
}
- ictx->need_wakeup = false;
- input_unlock(ictx);
+}
+
+void mp_input_wakeup(struct input_ctx *ictx)
+{
+ sem_post(&ictx->wakeup);
+}
+
+void mp_input_wakeup_nolock(struct input_ctx *ictx)
+{
+ mp_input_wakeup(ictx);
}
mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx)
{
input_lock(ictx);
- read_events(ictx, 0);
struct cmd_queue *queue = &ictx->cmd_queue;
if (!queue->first) {
struct mp_cmd *repeated = check_autorepeat(ictx);
@@ -1480,15 +1199,6 @@ done:
return r;
}
-#ifndef __MINGW32__
-static int read_wakeup(void *ctx, int fd)
-{
- char buf[100];
- read(fd, buf, sizeof(buf));
- return MP_INPUT_NOTHING;
-}
-#endif
-
struct input_ctx *mp_input_init(struct mpv_global *global)
{
struct input_opts *input_conf = global->opts->input_opts;
@@ -1506,11 +1216,14 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
.default_bindings = input_conf->default_bindings,
.mouse_section = "default",
.test = input_conf->test,
- .wakeup_pipe = {-1, -1},
};
+ if (sem_init(&ictx->wakeup, 0, 0)) {
+ MP_FATAL(ictx, "mpv doesn't work on systems without POSIX semaphores.\n");
+ abort();
+ }
+
mpthread_mutex_init_recursive(&ictx->mutex);
- pthread_cond_init(&ictx->wakeup, NULL);
// Setup default section, so that it does nothing.
mp_input_enable_section(ictx, NULL, MP_INPUT_ALLOW_VO_DRAGGING |
@@ -1527,15 +1240,6 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
parse_config(ictx, true, line, "<builtin>", NULL);
}
-#ifndef __MINGW32__
- int ret = mp_make_wakeup_pipe(ictx->wakeup_pipe);
- if (ret < 0)
- MP_ERR(ictx, "Failed to initialize wakeup pipe.\n");
- else
- mp_input_add_fd(ictx, ictx->wakeup_pipe[0], true, NULL, read_wakeup,
- NULL, NULL);
-#endif
-
bool config_ok = false;
if (input_conf->config_file)
config_ok = parse_config_file(ictx, input_conf->config_file, true);
@@ -1607,60 +1311,18 @@ void mp_input_uninit(struct input_ctx *ictx)
}
#endif
- for (int i = 0; i < ictx->num_fds; i++) {
- if (ictx->fds[i].close_func)
- ictx->fds[i].close_func(ictx->fds[i].ctx, ictx->fds[i].fd);
- }
close_input_sources(ictx);
- for (int i = 0; i < 2; i++) {
- if (ictx->wakeup_pipe[i] != -1)
- close(ictx->wakeup_pipe[i]);
- }
clear_queue(&ictx->cmd_queue);
talloc_free(ictx->current_down_cmd);
pthread_mutex_destroy(&ictx->mutex);
- pthread_cond_destroy(&ictx->wakeup);
+ sem_destroy(&ictx->wakeup);
talloc_free(ictx);
}
-void mp_input_wakeup(struct input_ctx *ictx)
-{
- input_lock(ictx);
- bool send_wakeup = ictx->in_select;
- ictx->need_wakeup = true;
- pthread_cond_signal(&ictx->wakeup);
- input_unlock(ictx);
- // Safe without locking
- if (send_wakeup && ictx->wakeup_pipe[1] >= 0)
- write(ictx->wakeup_pipe[1], &(char){0}, 1);
-}
-
-void mp_input_wakeup_nolock(struct input_ctx *ictx)
-{
- if (ictx->wakeup_pipe[1] >= 0) {
- write(ictx->wakeup_pipe[1], &(char){0}, 1);
- } else {
- // Not race condition free. Done for the sake of jackaudio+windows.
- ictx->need_wakeup = true;
- pthread_cond_signal(&ictx->wakeup);
- }
-}
-
-void mp_input_set_main_thread(struct input_ctx *ictx)
-{
- ictx->mainthread = pthread_self();
- ictx->mainthread_set = true;
-}
-
bool mp_input_check_interrupt(struct input_ctx *ictx)
{
input_lock(ictx);
bool res = queue_has_abort_cmds(&ictx->cmd_queue);
- if (!res && ictx->mainthread_set &&
- pthread_equal(ictx->mainthread, pthread_self()))
- {
- read_events(ictx, 0);
- }
input_unlock(ictx);
return res;
}
@@ -1697,7 +1359,7 @@ struct mp_input_src_internal {
struct mp_input_src *mp_input_add_src(struct input_ctx *ictx)
{
input_lock(ictx);
- if (ictx->num_sources == MP_MAX_FDS) {
+ if (ictx->num_sources == MP_MAX_SOURCES) {
input_unlock(ictx);
return NULL;
}
diff --git a/input/input.h b/input/input.h
index ff3740e21b..56544a99ee 100644
--- a/input/input.h
+++ b/input/input.h
@@ -25,18 +25,8 @@
#include "cmd_list.h"
#include "cmd_parse.h"
-// Error codes for the drivers
-
-// An error occurred but we can continue
-#define MP_INPUT_ERROR -1
-// A fatal error occurred, this driver should be removed
-#define MP_INPUT_DEAD -2
-// No input was available
-#define MP_INPUT_NOTHING -3
-//! Input will be available if you try again
-#define MP_INPUT_RETRY -4
-// Key FIFO was full - release events may be lost, zero button-down status
-#define MP_INPUT_RELEASE_ALL -5
+// For mp_input_put_key(): release all keys that are down.
+#define MP_INPUT_RELEASE_ALL -1
enum mp_cmd_flags {
MP_ON_OSD_NO = 0, // prefer not using OSD
@@ -142,28 +132,6 @@ void mp_input_src_kill(struct mp_input_src *src);
// Feed text data, which will be split into lines of commands.
void mp_input_src_feed_cmd_text(struct mp_input_src *src, char *buf, size_t len);
-/* Add a new command input source. (Old version.)
- * "fd" is a file descriptor (use -1 if you don't use any fd)
- * "select" tells whether to use select() on the fd to determine when to
- * try reading.
- * "read_cmd_func" is optional. It must return either text data or one of the
- * MP_INPUT error codes above. For return values >= 0, it behaves like UNIX
- * read() and returns the number of bytes copied to the dest buffer.
- * "read_key_func" is optional. It returns either key codes (ASCII, keycodes.h),
- * or MP_INPUT error codes.
- * "close_func" will be called when closing. Can be NULL. Its return value
- * is ignored (it's only there to allow using standard close() as the func).
- * "ctx" is for free use, and is passed to the callbacks.
- */
-int mp_input_add_fd(struct input_ctx *ictx, int fd, int select,
- int read_cmd_func(void *ctx, int fd, char *dest, int size),
- int read_key_func(void *ctx, int fd),
- int close_func(void *ctx, int fd), void *ctx);
-
-/* Can be passed as read_func for above function in order to read() from the FD.
- */
-int input_default_read_cmd(void *ctx, int fd, char *buf, int l);
-
// Process keyboard input. code is a key code from keycodes.h, possibly
// with modifiers applied. MP_INPUT_RELEASE_ALL is also a valid value.
void mp_input_put_key(struct input_ctx *ictx, int code);
@@ -191,9 +159,6 @@ struct mp_rect;
void mp_input_set_mouse_transform(struct input_ctx *ictx, struct mp_rect *dst,
struct mp_rect *src);
-// As for the cmd one you usually don't need this function.
-void mp_input_rm_key_fd(struct input_ctx *ictx, int fd);
-
// Add a command to the command queue.
int mp_input_queue_cmd(struct input_ctx *ictx, struct mp_cmd *cmd);
@@ -278,6 +243,4 @@ void mp_input_add_pipe(struct input_ctx *ictx, const char *filename);
void mp_input_joystick_add(struct input_ctx *ictx, char *dev);
void mp_input_lirc_add(struct input_ctx *ictx, char *lirc_configfile);
-void mp_input_set_main_thread(struct input_ctx *ictx);
-
#endif /* MPLAYER_INPUT_H */
diff --git a/input/lirc.c b/input/lirc.c
index ce3b979149..2805043c03 100644
--- a/input/lirc.c
+++ b/input/lirc.c
@@ -93,10 +93,10 @@ static int mp_input_lirc_read(void *pctx,int fd,char* dest, int s) {
// Nothing in the buffer, poll the lirc fd
if(lirc_nextcode(&code) != 0) {
MP_ERR(ctx, "Lirc error.\n");
- return MP_INPUT_DEAD;
+ return -1;
}
- if(!code) return MP_INPUT_NOTHING;
+ if(!code) return 0;
// We put all cmds in a single buffer separated by \n
while((r = lirc_code2char(ctx->lirc_config,code,&c))==0 && c!=NULL) {