diff options
Diffstat (limited to 'input')
-rw-r--r-- | input/cmd_list.c | 6 | ||||
-rw-r--r-- | input/cmd_list.h | 7 | ||||
-rw-r--r-- | input/input.c | 193 | ||||
-rw-r--r-- | input/input.h | 23 | ||||
-rw-r--r-- | input/ipc-unix.c | 14 | ||||
-rw-r--r-- | input/ipc-win.c | 8 | ||||
-rw-r--r-- | input/pipe-win32.c | 2 |
7 files changed, 145 insertions, 108 deletions
diff --git a/input/cmd_list.c b/input/cmd_list.c index 8cc6210a91..53cc375b3a 100644 --- a/input/cmd_list.c +++ b/input/cmd_list.c @@ -186,8 +186,6 @@ const struct mp_cmd_def mp_cmds[] = { { MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } }, { MP_CMD_VF_COMMAND, "vf-command", { ARG_STRING, ARG_STRING, ARG_STRING } }, - { MP_CMD_VO_CMDLINE, "vo-cmdline", { ARG_STRING } }, - { MP_CMD_SCRIPT_BINDING, "script-binding", { ARG_STRING }, .allow_auto_repeat = true, .on_updown = true}, @@ -226,6 +224,10 @@ const struct mp_cmd_def mp_cmds[] = { {"reselect", 1})), }}, + { MP_CMD_APPLY_PROFILE, "apply-profile", {ARG_STRING } }, + + { MP_CMD_LOAD_SCRIPT, "load-script", {ARG_STRING} }, + {0} }; diff --git a/input/cmd_list.h b/input/cmd_list.h index 4e324bf01c..1c2330b589 100644 --- a/input/cmd_list.h +++ b/input/cmd_list.h @@ -99,9 +99,6 @@ enum mp_command_type { MP_CMD_VF, MP_CMD_VF_COMMAND, - /// Video output commands - MP_CMD_VO_CMDLINE, - /// Internal for Lua scripts MP_CMD_SCRIPT_BINDING, MP_CMD_SCRIPT_MESSAGE, @@ -117,6 +114,10 @@ enum mp_command_type { MP_CMD_RESCAN_EXTERNAL_FILES, + MP_CMD_APPLY_PROFILE, + + MP_CMD_LOAD_SCRIPT, + // Internal MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p }; diff --git a/input/input.c b/input/input.c index dd9486f12a..9525dbcbb1 100644 --- a/input/input.c +++ b/input/input.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdbool.h> #include <unistd.h> +#include <math.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -34,7 +35,6 @@ #include <libavutil/common.h> #include "osdep/io.h" -#include "osdep/semaphore.h" #include "misc/rendezvous.h" #include "input.h" @@ -73,6 +73,7 @@ struct cmd_bind { }; struct cmd_bind_section { + char *owner; struct cmd_bind *binds; int num_binds; char *section; @@ -96,15 +97,13 @@ struct cmd_queue { struct input_ctx { pthread_mutex_t mutex; - sem_t wakeup; struct mp_log *log; struct mpv_global *global; + struct m_config_cache *opts_cache; struct input_opts *opts; - bool using_alt_gr; bool using_ar; bool using_cocoa_media_keys; - bool win_drag; // Autorepeat stuff short ar_state; @@ -146,6 +145,9 @@ struct input_ctx { struct cmd_queue cmd_queue; struct mp_cancel *cancel; + + void (*wakeup_cb)(void *ctx); + void *wakeup_ctx; }; static int parse_config(struct input_ctx *ictx, bool builtin, bstr data, @@ -170,28 +172,30 @@ struct input_opts { int enable_mouse_movements; int vo_key_input; int test; + int allow_win_drag; }; const struct m_sub_options input_config = { .opts = (const m_option_t[]) { - OPT_STRING("conf", config_file, CONF_GLOBAL | M_OPT_FILE), - OPT_INT("ar-delay", ar_delay, CONF_GLOBAL), - OPT_INT("ar-rate", ar_rate, CONF_GLOBAL), - OPT_PRINT("keylist", mp_print_key_list), - OPT_PRINT("cmdlist", mp_print_cmd_list), - OPT_FLAG("default-bindings", default_bindings, CONF_GLOBAL), - OPT_FLAG("test", test, CONF_GLOBAL), - OPT_INTRANGE("doubleclick-time", doubleclick_time, 0, 0, 1000), - OPT_FLAG("right-alt-gr", use_alt_gr, CONF_GLOBAL), - OPT_INTRANGE("key-fifo-size", key_fifo_size, CONF_GLOBAL, 2, 65000), - OPT_FLAG("cursor", enable_mouse_movements, CONF_GLOBAL), - OPT_FLAG("vo-keyboard", vo_key_input, CONF_GLOBAL), - OPT_FLAG("x11-keyboard", vo_key_input, CONF_GLOBAL), // old alias + OPT_STRING("input-conf", config_file, M_OPT_FIXED | M_OPT_FILE), + OPT_INT("input-ar-delay", ar_delay, 0), + OPT_INT("input-ar-rate", ar_rate, 0), + OPT_PRINT("input-keylist", mp_print_key_list), + OPT_PRINT("input-cmdlist", mp_print_cmd_list), + OPT_FLAG("input-default-bindings", default_bindings, 0), + OPT_FLAG("input-test", test, 0), + OPT_INTRANGE("input-doubleclick-time", doubleclick_time, 0, 0, 1000), + OPT_FLAG("input-right-alt-gr", use_alt_gr, 0), + OPT_INTRANGE("input-key-fifo-size", key_fifo_size, 0, 2, 65000), + OPT_FLAG("input-cursor", enable_mouse_movements, 0), + OPT_FLAG("input-vo-keyboard", vo_key_input, 0), #if HAVE_COCOA - OPT_FLAG("appleremote", use_appleremote, CONF_GLOBAL), - OPT_FLAG("media-keys", use_media_keys, CONF_GLOBAL), - OPT_FLAG("app-events", use_app_events, CONF_GLOBAL), + OPT_FLAG("input-appleremote", use_appleremote, 0), + OPT_FLAG("input-media-keys", use_media_keys, 0), + OPT_FLAG("input-app-events", use_app_events, M_OPT_FIXED), #endif + OPT_FLAG("window-dragging", allow_win_drag, 0), + OPT_REPLACED("input-x11-keyboard", "input-vo-keyboard"), {0} }, .size = sizeof(struct input_opts), @@ -209,7 +213,9 @@ const struct m_sub_options input_config = { #endif .default_bindings = 1, .vo_key_input = 1, + .allow_win_drag = 1, }, + .change_flags = UPDATE_INPUT, }; static const char builtin_input_conf[] = @@ -845,33 +851,18 @@ static mp_cmd_t *check_autorepeat(struct input_ctx *ictx) return NULL; } -void mp_input_wait(struct input_ctx *ictx, double seconds) +double mp_input_get_delay(struct input_ctx *ictx) { input_lock(ictx); + double seconds = INFINITY; 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"); - 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"); - } -} - -void mp_input_wakeup_nolock(struct input_ctx *ictx) -{ - // Some audio APIs discourage use of locking in their audio callback, - // and these audio callbacks happen to call mp_input_wakeup_nolock() - // when new data is needed. This is why we use semaphores here. - sem_post(&ictx->wakeup); + return seconds; } void mp_input_wakeup(struct input_ctx *ictx) { - mp_input_wakeup_nolock(ictx); + ictx->wakeup_cb(ictx->wakeup_ctx); } mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx) @@ -996,7 +987,8 @@ bool mp_input_test_mouse_active(struct input_ctx *ictx, int x, int y) bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y) { input_lock(ictx); - bool r = !ictx->win_drag || test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING); + bool r = !ictx->opts->allow_win_drag || + test_mouse(ictx, x, y, MP_INPUT_ALLOW_VO_DRAGGING); input_unlock(ictx); return r; } @@ -1021,13 +1013,19 @@ static void remove_binds(struct cmd_bind_section *bs, bool builtin) } void mp_input_define_section(struct input_ctx *ictx, char *name, char *location, - char *contents, bool builtin) + char *contents, bool builtin, char *owner) { if (!name || !name[0]) return; // parse_config() changes semantics with restrict_section==empty input_lock(ictx); // Delete: struct cmd_bind_section *bs = get_bind_section(ictx, bstr0(name)); + if ((!bs->owner || (owner && strcmp(bs->owner, owner) != 0)) && + strcmp(bs->section, "default") != 0) + { + talloc_free(bs->owner); + bs->owner = talloc_strdup(bs, owner); + } remove_binds(bs, builtin); if (contents && contents[0]) { // Redefine: @@ -1039,6 +1037,21 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location, input_unlock(ictx); } +void mp_input_remove_sections_by_owner(struct input_ctx *ictx, char *owner) +{ + input_lock(ictx); + struct cmd_bind_section *bs = ictx->cmd_bind_sections; + while (bs) { + if (bs->owner && owner && strcmp(bs->owner, owner) == 0) { + mp_input_disable_section(ictx, bs->section); + remove_binds(bs, false); + remove_binds(bs, true); + } + bs = bs->next; + } + input_unlock(ictx); +} + static bool bind_matches_key(struct cmd_bind *bind, int num_keys, const int *keys) { if (bind->num_keys != num_keys) @@ -1195,22 +1208,23 @@ done: return r; } -struct input_ctx *mp_input_init(struct mpv_global *global) +struct input_ctx *mp_input_init(struct mpv_global *global, + void (*wakeup_cb)(void *ctx), + void *wakeup_ctx) { struct input_ctx *ictx = talloc_ptrtype(NULL, ictx); *ictx = (struct input_ctx){ .global = global, - .opts = talloc_zero(ictx, struct input_opts), // replaced later .ar_state = -1, .log = mp_log_new(ictx, global->log, "input"), .mouse_section = "default", + .opts_cache = m_config_cache_alloc(ictx, global, &input_config), + .wakeup_cb = wakeup_cb, + .wakeup_ctx = wakeup_ctx, }; - if (sem_init(&ictx->wakeup, 0, 0)) { - MP_FATAL(ictx, "mpv doesn't work on systems without POSIX semaphores.\n"); - abort(); - } + ictx->opts = ictx->opts_cache->opts; mpthread_mutex_init_recursive(&ictx->mutex); @@ -1221,13 +1235,45 @@ struct input_ctx *mp_input_init(struct mpv_global *global) return ictx; } -void mp_input_load(struct input_ctx *ictx) +static void reload_opts(struct input_ctx *ictx, bool shutdown) +{ + m_config_cache_update(ictx->opts_cache); + +#if HAVE_COCOA + struct input_opts *opts = ictx->opts; + + if (ictx->using_ar != (opts->use_appleremote && !shutdown)) { + ictx->using_ar = !ictx->using_ar; + if (ictx->using_ar) { + cocoa_init_apple_remote(); + } else { + cocoa_uninit_apple_remote(); + } + } + + if (ictx->using_cocoa_media_keys != (opts->use_media_keys && !shutdown)) { + ictx->using_cocoa_media_keys = !ictx->using_cocoa_media_keys; + if (ictx->using_cocoa_media_keys) { + cocoa_init_media_keys(); + } else { + cocoa_uninit_media_keys(); + } + } +#endif +} + +void mp_input_update_opts(struct input_ctx *ictx) +{ + input_lock(ictx); + reload_opts(ictx, false); + input_unlock(ictx); +} + +void mp_input_load_config(struct input_ctx *ictx) { - struct input_opts *input_conf = - m_sub_options_copy(ictx, &input_config, ictx->global->opts->input_opts); + input_lock(ictx); - talloc_free(ictx->opts); - ictx->opts = input_conf; + reload_opts(ictx, false); // "Uncomment" the default key bindings in etc/input.conf and add them. // All lines that do not start with '# ' are parsed. @@ -1240,8 +1286,8 @@ void mp_input_load(struct input_ctx *ictx) } bool config_ok = false; - if (input_conf->config_file) - config_ok = parse_config_file(ictx, input_conf->config_file, true); + if (ictx->opts->config_file && ictx->opts->config_file[0]) + config_ok = parse_config_file(ictx, ictx->opts->config_file, true); if (!config_ok) { // Try global conf dir void *tmp = talloc_new(NULL); @@ -1251,32 +1297,17 @@ void mp_input_load(struct input_ctx *ictx) talloc_free(tmp); } - if (input_conf->use_alt_gr) { - ictx->using_alt_gr = true; - } - #if HAVE_COCOA - if (input_conf->use_app_events) { + if (ictx->opts->use_app_events) cocoa_start_event_monitor(); - } - - if (input_conf->use_appleremote) { - cocoa_init_apple_remote(); - ictx->using_ar = true; - } - - if (input_conf->use_media_keys) { - cocoa_init_media_keys(); - ictx->using_cocoa_media_keys = true; - } #endif - ictx->win_drag = ictx->global->opts->allow_win_drag; - #if defined(__MINGW32__) if (ictx->global->opts->input_file && *ictx->global->opts->input_file) mp_input_pipe_add(ictx, ictx->global->opts->input_file); #endif + + input_unlock(ictx); } static void clear_queue(struct cmd_queue *queue) @@ -1293,21 +1324,14 @@ void mp_input_uninit(struct input_ctx *ictx) if (!ictx) return; -#if HAVE_COCOA - if (ictx->using_ar) { - cocoa_uninit_apple_remote(); - } - - if (ictx->using_cocoa_media_keys) { - cocoa_uninit_media_keys(); - } -#endif + input_lock(ictx); + reload_opts(ictx, true); + input_unlock(ictx); close_input_sources(ictx); clear_queue(&ictx->cmd_queue); talloc_free(ictx->current_down_cmd); pthread_mutex_destroy(&ictx->mutex); - sem_destroy(&ictx->wakeup); talloc_free(ictx); } @@ -1320,7 +1344,10 @@ void mp_input_set_cancel(struct input_ctx *ictx, struct mp_cancel *cancel) bool mp_input_use_alt_gr(struct input_ctx *ictx) { - return ictx->using_alt_gr; + input_lock(ictx); + bool r = ictx->opts->use_alt_gr; + input_unlock(ictx); + return r; } struct mp_cmd *mp_input_parse_cmd(struct input_ctx *ictx, bstr str, diff --git a/input/input.h b/input/input.h index a5710b6065..5b5edd580d 100644 --- a/input/input.h +++ b/input/input.h @@ -196,9 +196,13 @@ void mp_input_disable_all_sections(struct input_ctx *ictx); // builtin: create as builtin section; this means if the user defines bindings // using "{name}", they won't be ignored or overwritten - instead, // they are preferred to the bindings defined with this call +// owner: string ID of the client which defined this, or NULL // If the section already exists, its bindings are removed and replaced. void mp_input_define_section(struct input_ctx *ictx, char *name, char *location, - char *contents, bool builtin); + char *contents, bool builtin, char *owner); + +// Remove all sections that have been defined by the given owner. +void mp_input_remove_sections_by_owner(struct input_ctx *ictx, char *owner); // Define where on the screen the named input section should receive. // Setting a rectangle of size 0 unsets the mouse area. @@ -219,22 +223,23 @@ bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y); // Initialize the input system struct mpv_global; -struct input_ctx *mp_input_init(struct mpv_global *global); +struct input_ctx *mp_input_init(struct mpv_global *global, + void (*wakeup_cb)(void *ctx), + void *wakeup_ctx); + +void mp_input_load_config(struct input_ctx *ictx); -// Load config, options, and devices. -void mp_input_load(struct input_ctx *ictx); +void mp_input_update_opts(struct input_ctx *ictx); void mp_input_uninit(struct input_ctx *ictx); -// Sleep for the given amount of seconds, until mp_input_wakeup() is called, -// or new input arrives. seconds<=0 returns immediately. -void mp_input_wait(struct input_ctx *ictx, double seconds); +// Return number of seconds until the next autorepeat event will be generated. +// Returns INFINITY if no autorepeated key is active. +double mp_input_get_delay(struct input_ctx *ictx); // Wake up sleeping input loop from another thread. void mp_input_wakeup(struct input_ctx *ictx); -void mp_input_wakeup_nolock(struct input_ctx *ictx); - // Used to asynchronously abort playback. Needed because the core still can // block on network in some situations. struct mp_cancel; diff --git a/input/ipc-unix.c b/input/ipc-unix.c index 0f4b7132e4..e4b98edfc9 100644 --- a/input/ipc-unix.c +++ b/input/ipc-unix.c @@ -20,6 +20,7 @@ #include <unistd.h> #include <poll.h> +#include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> @@ -97,6 +98,11 @@ static void *client_thread(void *p) { pthread_detach(pthread_self()); + // We don't use MSG_NOSIGNAL because the moldy fruit OS doesn't support it. + struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART }; + sigfillset(&sa.sa_mask); + sigaction(SIGPIPE, &sa, NULL); + int rc; struct client_arg *arg = p; @@ -118,15 +124,11 @@ static void *client_thread(void *p) }; fcntl(arg->client_fd, F_SETFL, fcntl(arg->client_fd, F_GETFL, 0) | O_NONBLOCK); - mpv_suspend(arg->client); while (1) { rc = poll(fds, 2, 0); - if (rc == 0) { - mpv_resume(arg->client); + if (rc == 0) rc = poll(fds, 2, -1); - mpv_suspend(arg->client); - } if (rc < 0) { MP_ERR(arg, "Poll error\n"); continue; @@ -337,6 +339,8 @@ static void *ipc_thread(void *p) goto done; } + MP_VERBOSE(arg, "Listening to IPC socket.\n"); + int client_num = 0; struct pollfd fds[2] = { diff --git a/input/ipc-win.c b/input/ipc-win.c index b0010cba7d..6908683d8d 100644 --- a/input/ipc-win.c +++ b/input/ipc-win.c @@ -222,7 +222,6 @@ static void *client_thread(void *p) MP_VERBOSE(arg, "Client connected\n"); mpv_set_wakeup_callback(arg->client, wakeup_cb, wakeup_event); - mpv_suspend(arg->client); // Do the first read operation on the pipe if ((ioerr = async_read(arg->client_h, buf, 4096, &ol))) { @@ -233,11 +232,8 @@ static void *client_thread(void *p) while (1) { HANDLE handles[] = { wakeup_event, ol.hEvent }; int n = WaitForMultipleObjects(2, handles, FALSE, 0); - if (n == WAIT_TIMEOUT) { - mpv_resume(arg->client); + if (n == WAIT_TIMEOUT) n = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - mpv_suspend(arg->client); - } switch (n) { case WAIT_OBJECT_0: // wakeup_event @@ -381,6 +377,8 @@ static void *ipc_thread(void *p) goto done; } + MP_VERBOSE(arg, "Listening to IPC pipe.\n"); + while (1) { DWORD err = ConnectNamedPipe(server, &ol) ? 0 : GetLastError(); diff --git a/input/pipe-win32.c b/input/pipe-win32.c index 3d47fb66c1..a0a0bfef24 100644 --- a/input/pipe-win32.c +++ b/input/pipe-win32.c @@ -19,7 +19,7 @@ #include <io.h> #include "common/msg.h" -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "osdep/io.h" #include "input.h" |