summaryrefslogtreecommitdiffstats
path: root/input
diff options
context:
space:
mode:
Diffstat (limited to 'input')
-rw-r--r--input/cmd_list.c6
-rw-r--r--input/cmd_list.h7
-rw-r--r--input/input.c193
-rw-r--r--input/input.h23
-rw-r--r--input/ipc-unix.c14
-rw-r--r--input/ipc-win.c8
-rw-r--r--input/pipe-win32.c2
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"