mirror of
https://github.com/mpv-player/mpv
synced 2024-12-17 12:25:03 +00:00
input: rework how input sources are added
Until now, there were two functions to add input sources (stuff like stdin input, slave mode, lirc, joystick). Unify them to a single function (mp_input_add_fd()), and make sure the associated callbacks always have a context parameter. Change the lirc and joystick code such that they take store their state in a context struct (probably worthless), and use the new mp_msg replacements (the point of this refactoring). Additionally, get rid of the ugly USE_FD0_CMD_SELECT etc. ifdeffery in the terminal handling code.
This commit is contained in:
parent
dadf3a9a46
commit
ed71606e65
120
input/input.c
120
input/input.c
@ -504,8 +504,8 @@ struct input_fd {
|
||||
struct mp_log *log;
|
||||
int fd;
|
||||
int (*read_key)(void *ctx, int fd);
|
||||
int (*read_cmd)(int fd, char *dest, int size);
|
||||
int (*close_func)(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;
|
||||
@ -540,6 +540,7 @@ struct cmd_queue {
|
||||
struct input_ctx {
|
||||
pthread_mutex_t mutex;
|
||||
struct mp_log *log;
|
||||
struct mpv_global *global;
|
||||
|
||||
bool using_alt_gr;
|
||||
bool using_ar;
|
||||
@ -628,6 +629,9 @@ const m_option_t mp_input_opts[] = {
|
||||
OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL),
|
||||
OPT_FLAG("lirc", input.use_lirc, CONF_GLOBAL),
|
||||
OPT_FLAG("right-alt-gr", input.use_alt_gr, CONF_GLOBAL),
|
||||
#if HAVE_LIRC
|
||||
OPT_STRING("lircconf", input.lirc_configfile, CONF_GLOBAL),
|
||||
#endif
|
||||
#if HAVE_COCOA
|
||||
OPT_FLAG("ar", input.use_ar, CONF_GLOBAL),
|
||||
OPT_FLAG("media-keys", input.use_media_keys, CONF_GLOBAL),
|
||||
@ -635,8 +639,6 @@ const m_option_t mp_input_opts[] = {
|
||||
{ NULL, NULL, 0, 0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static int default_cmd_func(int fd, char *buf, int l);
|
||||
|
||||
static const char builtin_input_conf[] =
|
||||
#include "input/input_conf.h"
|
||||
;
|
||||
@ -752,68 +754,37 @@ static struct mp_cmd *queue_peek_tail(struct cmd_queue *queue)
|
||||
return cur;
|
||||
}
|
||||
|
||||
static struct input_fd *mp_input_add_fd(struct input_ctx *ictx)
|
||||
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");
|
||||
return NULL;
|
||||
} else {
|
||||
fd = &ictx->fds[ictx->num_fds];
|
||||
}
|
||||
|
||||
struct input_fd *fd = &ictx->fds[ictx->num_fds];
|
||||
*fd = (struct input_fd){
|
||||
.log = ictx->log,
|
||||
.fd = -1,
|
||||
.fd = unix_fd,
|
||||
.select = select,
|
||||
.read_cmd = read_cmd_func,
|
||||
.read_key = read_key_func,
|
||||
.close_func = close_func,
|
||||
.ctx = ctx,
|
||||
};
|
||||
ictx->num_fds++;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int mp_input_add_cmd_fd(struct input_ctx *ictx, int unix_fd, int select,
|
||||
int read_func(int fd, char *dest, int size),
|
||||
int close_func(int fd))
|
||||
{
|
||||
if (select && unix_fd < 0) {
|
||||
MP_ERR(ictx, "Invalid fd %d in mp_input_add_cmd_fd", unix_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
input_lock(ictx);
|
||||
struct input_fd *fd = mp_input_add_fd(ictx);
|
||||
if (fd) {
|
||||
fd->fd = unix_fd;
|
||||
fd->select = select;
|
||||
fd->read_cmd = read_func ? read_func : default_cmd_func;
|
||||
fd->close_func = close_func;
|
||||
}
|
||||
input_unlock(ictx);
|
||||
return !!fd;
|
||||
}
|
||||
|
||||
int mp_input_add_key_fd(struct input_ctx *ictx, int unix_fd, int select,
|
||||
int read_func(void *ctx, int fd),
|
||||
int close_func(int fd), void *ctx)
|
||||
{
|
||||
if (select && unix_fd < 0) {
|
||||
MP_ERR(ictx, "Invalid fd %d in mp_input_add_key_fd", unix_fd);
|
||||
return 0;
|
||||
}
|
||||
assert(read_func);
|
||||
|
||||
input_lock(ictx);
|
||||
struct input_fd *fd = mp_input_add_fd(ictx);
|
||||
if (fd) {
|
||||
fd->fd = unix_fd;
|
||||
fd->select = select;
|
||||
fd->read_key = read_func;
|
||||
fd->close_func = close_func;
|
||||
fd->ctx = ctx;
|
||||
}
|
||||
input_unlock(ictx);
|
||||
return !!fd;
|
||||
}
|
||||
|
||||
|
||||
static void mp_input_rm_fd(struct input_ctx *ictx, int fd)
|
||||
{
|
||||
struct input_fd *fds = ictx->fds;
|
||||
@ -826,7 +797,7 @@ static void mp_input_rm_fd(struct input_ctx *ictx, int fd)
|
||||
if (i == ictx->num_fds)
|
||||
return;
|
||||
if (fds[i].close_func)
|
||||
fds[i].close_func(fds[i].fd);
|
||||
fds[i].close_func(fds[i].ctx, fds[i].fd);
|
||||
talloc_free(fds[i].buffer);
|
||||
|
||||
if (i + 1 < ictx->num_fds)
|
||||
@ -1205,7 +1176,7 @@ static int read_cmd(struct input_fd *mp_fd, char **ret)
|
||||
|
||||
// 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->fd, mp_fd->buffer + mp_fd->pos,
|
||||
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) {
|
||||
@ -1272,7 +1243,7 @@ static int read_cmd(struct input_fd *mp_fd, char **ret)
|
||||
return MP_INPUT_NOTHING;
|
||||
}
|
||||
|
||||
static int default_cmd_func(int fd, char *buf, int l)
|
||||
int input_default_read_cmd(void *ctx, int fd, char *buf, int l)
|
||||
{
|
||||
while (1) {
|
||||
int r = read(fd, buf, l);
|
||||
@ -2377,12 +2348,18 @@ void mp_input_define_section(struct input_ctx *ictx, char *name, char *location,
|
||||
input_unlock(ictx);
|
||||
}
|
||||
|
||||
static int close_fd(void *ctx, int fd)
|
||||
{
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
struct input_ctx *mp_input_init(struct mpv_global *global)
|
||||
{
|
||||
struct input_conf *input_conf = &global->opts->input;
|
||||
|
||||
struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
|
||||
*ictx = (struct input_ctx){
|
||||
.global = global,
|
||||
.log = mp_log_new(ictx, global->log, "input"),
|
||||
.key_fifo_size = input_conf->key_fifo_size,
|
||||
.doubleclick_time = input_conf->doubleclick_time,
|
||||
@ -2432,8 +2409,8 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
|
||||
if (ret < 0)
|
||||
MP_ERR(ictx, "Failed to initialize wakeup pipe: %s\n", strerror(errno));
|
||||
else
|
||||
mp_input_add_key_fd(ictx, ictx->wakeup_pipe[0], true, read_wakeup,
|
||||
NULL, NULL);
|
||||
mp_input_add_fd(ictx, ictx->wakeup_pipe[0], true, NULL, read_wakeup,
|
||||
NULL, NULL);
|
||||
#endif
|
||||
|
||||
bool config_ok = false;
|
||||
@ -2446,28 +2423,17 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
|
||||
talloc_free(file);
|
||||
}
|
||||
if (!config_ok) {
|
||||
MP_VERBOSE(ictx, "Falling back on default (hardcoded) "
|
||||
"input config\n");
|
||||
MP_VERBOSE(ictx, "Falling back on default (hardcoded) input config\n");
|
||||
}
|
||||
|
||||
#if HAVE_JOYSTICK
|
||||
if (input_conf->use_joystick) {
|
||||
int fd = mp_input_joystick_init(input_conf->js_dev);
|
||||
if (fd < 0)
|
||||
MP_ERR(ictx, "Can't init input joystick\n");
|
||||
else
|
||||
mp_input_add_key_fd(ictx, fd, 1, mp_input_joystick_read,
|
||||
close, NULL);
|
||||
}
|
||||
if (input_conf->use_joystick)
|
||||
mp_input_joystick_init(ictx, ictx->log, input_conf->js_dev);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIRC
|
||||
if (input_conf->use_lirc) {
|
||||
int fd = mp_input_lirc_init();
|
||||
if (fd > 0)
|
||||
mp_input_add_cmd_fd(ictx, fd, 0, mp_input_lirc_read,
|
||||
mp_input_lirc_close);
|
||||
}
|
||||
if (input_conf->use_lirc)
|
||||
mp_input_lirc_init(ictx, ictx->log, input_conf->lirc_configfile);
|
||||
#endif
|
||||
|
||||
if (input_conf->use_alt_gr) {
|
||||
@ -2499,7 +2465,7 @@ struct input_ctx *mp_input_init(struct mpv_global *global)
|
||||
#endif
|
||||
int in_file_fd = open(input_conf->in_file, mode);
|
||||
if (in_file_fd >= 0)
|
||||
mp_input_add_cmd_fd(ictx, in_file_fd, 1, NULL, close);
|
||||
mp_input_add_fd(ictx, in_file_fd, 1, input_default_read_cmd, NULL, close_fd, NULL);
|
||||
else
|
||||
MP_ERR(ictx, "Can't open %s: %s\n", input_conf->in_file,
|
||||
strerror(errno));
|
||||
@ -2534,7 +2500,7 @@ void mp_input_uninit(struct input_ctx *ictx)
|
||||
|
||||
for (int i = 0; i < ictx->num_fds; i++) {
|
||||
if (ictx->fds[i].close_func)
|
||||
ictx->fds[i].close_func(ictx->fds[i].fd);
|
||||
ictx->fds[i].close_func(ictx->fds[i].ctx, ictx->fds[i].fd);
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (ictx->wakeup_pipe[i] != -1)
|
||||
|
@ -171,25 +171,26 @@ typedef struct mp_cmd {
|
||||
bool mp_input_is_abort_cmd(int cmd_id);
|
||||
|
||||
/* Add a new command input source.
|
||||
* "fd" is a file descriptor (use a negative value if you don't use any fd)
|
||||
* "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_func" is optional. If NULL a default function which reads data
|
||||
* directly from the fd will be used. It must return either text data
|
||||
* or one of the MP_INPUT error codes above.
|
||||
* "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_cmd_fd(struct input_ctx *ictx, int fd, int select,
|
||||
int read_func(int fd, char *dest, int size),
|
||||
int close_func(int fd));
|
||||
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);
|
||||
|
||||
/* The args are similar to the cmd version above, except you must give
|
||||
* a read_func, and it should return key codes (ASCII plus keycodes.h).
|
||||
/* Can be passed as read_func for above function in order to read() from the FD.
|
||||
*/
|
||||
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);
|
||||
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.
|
||||
|
@ -43,22 +43,37 @@
|
||||
|
||||
#include <linux/joystick.h>
|
||||
|
||||
int axis[256];
|
||||
int btns = 0;
|
||||
static int mp_input_joystick_read(void *ctx, int fd);
|
||||
|
||||
int mp_input_joystick_init(char* dev) {
|
||||
struct ctx {
|
||||
struct mp_log *log;
|
||||
int axis[256];
|
||||
int btns;
|
||||
};
|
||||
|
||||
static int close_js(void *ctx, int fd)
|
||||
{
|
||||
talloc_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_input_joystick_init(struct input_ctx *ictx, struct mp_log *log, char *dev)
|
||||
{
|
||||
int fd,l=0;
|
||||
int initialized = 0;
|
||||
struct js_event ev;
|
||||
|
||||
mp_msg(MSGT_INPUT,MSGL_V,"Opening joystick device %s\n",dev ? dev : JS_DEV);
|
||||
mp_verbose(log, "Opening joystick device %s\n",dev ? dev : JS_DEV);
|
||||
|
||||
fd = open( dev ? dev : JS_DEV , O_RDONLY | O_NONBLOCK );
|
||||
if(fd < 0) {
|
||||
mp_msg(MSGT_INPUT,MSGL_ERR,"Can't open joystick device %s: %s\n",dev ? dev : JS_DEV,strerror(errno));
|
||||
mp_err(log, "Can't open joystick device %s: %s\n",dev ? dev : JS_DEV,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ctx *ctx = talloc_ptrtype(NULL, ctx);
|
||||
*ctx = (struct ctx) {.log = log};
|
||||
|
||||
while(! initialized) {
|
||||
l = 0;
|
||||
while((unsigned int)l < sizeof(struct js_event)) {
|
||||
@ -70,27 +85,30 @@ int mp_input_joystick_init(char* dev) {
|
||||
initialized = 1;
|
||||
break;
|
||||
}
|
||||
mp_msg(MSGT_INPUT,MSGL_ERR,"Error while reading joystick device: %s\n",strerror(errno));
|
||||
MP_ERR(ctx, "Error while reading joystick device: %s\n",strerror(errno));
|
||||
close(fd);
|
||||
talloc_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
l += r;
|
||||
}
|
||||
if((unsigned int)l < sizeof(struct js_event)) {
|
||||
if(l > 0)
|
||||
mp_msg(MSGT_INPUT,MSGL_WARN,"Joystick: We lose %d bytes of data\n",l);
|
||||
MP_WARN(ctx, "Joystick: We lose %d bytes of data\n",l);
|
||||
break;
|
||||
}
|
||||
if(ev.type == JS_EVENT_BUTTON)
|
||||
btns |= (ev.value << ev.number);
|
||||
ctx->btns |= (ev.value << ev.number);
|
||||
if(ev.type == JS_EVENT_AXIS)
|
||||
axis[ev.number] = ev.value;
|
||||
ctx->axis[ev.number] = ev.value;
|
||||
}
|
||||
|
||||
mp_input_add_fd(ictx, fd, 1, NULL, mp_input_joystick_read, close_js, ctx);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int mp_input_joystick_read(void *ctx, int fd) {
|
||||
static int mp_input_joystick_read(void *pctx, int fd) {
|
||||
struct ctx *ctx = pctx;
|
||||
struct js_event ev;
|
||||
int l=0;
|
||||
|
||||
@ -102,9 +120,9 @@ int mp_input_joystick_read(void *ctx, int fd) {
|
||||
else if(errno == EAGAIN)
|
||||
return MP_INPUT_NOTHING;
|
||||
if( r < 0)
|
||||
mp_msg(MSGT_INPUT,MSGL_ERR,"Error while reading joystick device: %s\n",strerror(errno));
|
||||
MP_ERR(ctx, "Error while reading joystick device: %s\n",strerror(errno));
|
||||
else
|
||||
mp_msg(MSGT_INPUT,MSGL_ERR,"Error while reading joystick device: %s\n","EOF");
|
||||
MP_ERR(ctx, "Error while reading joystick device: %s\n","EOF");
|
||||
return MP_INPUT_DEAD;
|
||||
}
|
||||
l += r;
|
||||
@ -112,49 +130,49 @@ int mp_input_joystick_read(void *ctx, int fd) {
|
||||
|
||||
if((unsigned int)l < sizeof(struct js_event)) {
|
||||
if(l > 0)
|
||||
mp_msg(MSGT_INPUT,MSGL_WARN,"Joystick: We lose %d bytes of data\n",l);
|
||||
MP_WARN(ctx, "Joystick: We lose %d bytes of data\n",l);
|
||||
return MP_INPUT_NOTHING;
|
||||
}
|
||||
|
||||
if(ev.type & JS_EVENT_INIT) {
|
||||
mp_msg(MSGT_INPUT,MSGL_WARN,"Joystick: warning init event, we have lost sync with driver.\n");
|
||||
MP_WARN(ctx, "Joystick: warning init event, we have lost sync with driver.\n");
|
||||
ev.type &= ~JS_EVENT_INIT;
|
||||
if(ev.type == JS_EVENT_BUTTON) {
|
||||
int s = (btns >> ev.number) & 1;
|
||||
int s = (ctx->btns >> ev.number) & 1;
|
||||
if(s == ev.value) // State is the same : ignore
|
||||
return MP_INPUT_NOTHING;
|
||||
}
|
||||
if(ev.type == JS_EVENT_AXIS) {
|
||||
if( ( axis[ev.number] == 1 && ev.value > JOY_AXIS_DELTA) ||
|
||||
(axis[ev.number] == -1 && ev.value < -JOY_AXIS_DELTA) ||
|
||||
(axis[ev.number] == 0 && ev.value >= -JOY_AXIS_DELTA && ev.value <= JOY_AXIS_DELTA)
|
||||
if( ( ctx->axis[ev.number] == 1 && ev.value > JOY_AXIS_DELTA) ||
|
||||
(ctx->axis[ev.number] == -1 && ev.value < -JOY_AXIS_DELTA) ||
|
||||
(ctx->axis[ev.number] == 0 && ev.value >= -JOY_AXIS_DELTA && ev.value <= JOY_AXIS_DELTA)
|
||||
) // State is the same : ignore
|
||||
return MP_INPUT_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type & JS_EVENT_BUTTON) {
|
||||
btns &= ~(1 << ev.number);
|
||||
btns |= (ev.value << ev.number);
|
||||
ctx->btns &= ~(1 << ev.number);
|
||||
ctx->btns |= (ev.value << ev.number);
|
||||
if(ev.value == 1)
|
||||
return (MP_JOY_BTN0 + ev.number) | MP_KEY_STATE_DOWN;
|
||||
else
|
||||
return (MP_JOY_BTN0 + ev.number) | MP_KEY_STATE_UP;
|
||||
} else if(ev.type & JS_EVENT_AXIS) {
|
||||
if(ev.value < -JOY_AXIS_DELTA && axis[ev.number] != -1) {
|
||||
axis[ev.number] = -1;
|
||||
if(ev.value < -JOY_AXIS_DELTA && ctx->axis[ev.number] != -1) {
|
||||
ctx->axis[ev.number] = -1;
|
||||
return (MP_JOY_AXIS0_MINUS+(2*ev.number)) | MP_KEY_STATE_DOWN;
|
||||
} else if(ev.value > JOY_AXIS_DELTA && axis[ev.number] != 1) {
|
||||
axis[ev.number] = 1;
|
||||
} else if(ev.value > JOY_AXIS_DELTA && ctx->axis[ev.number] != 1) {
|
||||
ctx->axis[ev.number] = 1;
|
||||
return (MP_JOY_AXIS0_PLUS+(2*ev.number)) | MP_KEY_STATE_DOWN;
|
||||
} else if(ev.value <= JOY_AXIS_DELTA && ev.value >= -JOY_AXIS_DELTA && axis[ev.number] != 0) {
|
||||
int r = axis[ev.number] == 1 ? MP_JOY_AXIS0_PLUS+(2*ev.number) : MP_JOY_AXIS0_MINUS+(2*ev.number);
|
||||
axis[ev.number] = 0;
|
||||
} else if(ev.value <= JOY_AXIS_DELTA && ev.value >= -JOY_AXIS_DELTA && ctx->axis[ev.number] != 0) {
|
||||
int r = ctx->axis[ev.number] == 1 ? MP_JOY_AXIS0_PLUS+(2*ev.number) : MP_JOY_AXIS0_MINUS+(2*ev.number);
|
||||
ctx->axis[ev.number] = 0;
|
||||
return r | MP_KEY_STATE_UP;
|
||||
} else
|
||||
return MP_INPUT_NOTHING;
|
||||
} else {
|
||||
mp_msg(MSGT_INPUT,MSGL_WARN,"Joystick warning unknown event type %d\n",ev.type);
|
||||
MP_WARN(ctx, "Joystick warning unknown event type %d\n",ev.type);
|
||||
return MP_INPUT_ERROR;
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
#ifndef MPLAYER_JOYSTICK_H
|
||||
#define MPLAYER_JOYSTICK_H
|
||||
|
||||
int mp_input_joystick_init(char* dev);
|
||||
|
||||
int mp_input_joystick_read(void *ctx, int fd);
|
||||
struct input_ctx;
|
||||
struct mp_log;
|
||||
int mp_input_joystick_init(struct input_ctx *ictx, struct mp_log *log, char *dev);
|
||||
|
||||
#endif /* MPLAYER_JOYSTICK_H */
|
||||
|
72
input/lirc.c
72
input/lirc.c
@ -30,94 +30,108 @@
|
||||
#include "input.h"
|
||||
#include "lirc.h"
|
||||
|
||||
static struct lirc_config *lirc_config;
|
||||
char *lirc_configfile;
|
||||
static int mp_input_lirc_read(void *ctx, int fd,char* dest, int s);
|
||||
static int mp_input_lirc_close(void *ctx, int fd);
|
||||
|
||||
static char* cmd_buf = NULL;
|
||||
struct ctx {
|
||||
struct mp_log *log;
|
||||
struct lirc_config *lirc_config;
|
||||
char* cmd_buf;
|
||||
};
|
||||
|
||||
int
|
||||
mp_input_lirc_init(void) {
|
||||
int mp_input_lirc_init(struct input_ctx *ictx, struct mp_log *log,
|
||||
char *lirc_configfile)
|
||||
{
|
||||
int lirc_sock;
|
||||
int mode;
|
||||
|
||||
mp_msg(MSGT_LIRC,MSGL_V,"Setting up LIRC support...\n");
|
||||
mp_verbose(log,"Setting up LIRC support...\n");
|
||||
if((lirc_sock=lirc_init("mpv",0))==-1){
|
||||
mp_msg(MSGT_LIRC,MSGL_V,"Failed to open LIRC support. You will not be able to use your remote control.\n");
|
||||
mp_verbose(log,"Failed to open LIRC support. You will not be able to use your remote control.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode = fcntl(lirc_sock, F_GETFL);
|
||||
if (mode < 0 || fcntl(lirc_sock, F_SETFL, mode | O_NONBLOCK) < 0) {
|
||||
mp_msg(MSGT_LIRC, MSGL_ERR, "setting non-blocking mode failed: %s\n",
|
||||
strerror(errno));
|
||||
mp_err(log, "setting non-blocking mode failed: %s\n", strerror(errno));
|
||||
lirc_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct lirc_config *lirc_config = NULL;
|
||||
if(lirc_readconfig( lirc_configfile,&lirc_config,NULL )!=0 ){
|
||||
mp_msg(MSGT_LIRC,MSGL_ERR,"Failed to read LIRC config file %s.\n",
|
||||
mp_err(log, "Failed to read LIRC config file %s.\n",
|
||||
lirc_configfile == NULL ? "~/.lircrc" : lirc_configfile);
|
||||
lirc_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ctx *ctx = talloc_ptrtype(NULL, ctx);
|
||||
*ctx = (struct ctx){
|
||||
.log = log,
|
||||
.lirc_config = lirc_config,
|
||||
};
|
||||
mp_input_add_fd(ictx, lirc_sock, 0, mp_input_lirc_read, NULL, mp_input_lirc_close, ctx);
|
||||
|
||||
return lirc_sock;
|
||||
}
|
||||
|
||||
int mp_input_lirc_read(int fd,char* dest, int s) {
|
||||
static int mp_input_lirc_read(void *pctx,int fd,char* dest, int s) {
|
||||
int r,cl = 0;
|
||||
char *code = NULL,*c = NULL;
|
||||
struct ctx *ctx = pctx;
|
||||
|
||||
// We have something in the buffer return it
|
||||
if(cmd_buf != NULL) {
|
||||
int l = strlen(cmd_buf), w = l > s ? s : l;
|
||||
memcpy(dest,cmd_buf,w);
|
||||
if(ctx->cmd_buf != NULL) {
|
||||
int l = strlen(ctx->cmd_buf), w = l > s ? s : l;
|
||||
memcpy(dest,ctx->cmd_buf,w);
|
||||
l -= w;
|
||||
if(l > 0)
|
||||
memmove(cmd_buf,&cmd_buf[w],l+1);
|
||||
memmove(ctx->cmd_buf,&ctx->cmd_buf[w],l+1);
|
||||
else {
|
||||
free(cmd_buf);
|
||||
cmd_buf = NULL;
|
||||
free(ctx->cmd_buf);
|
||||
ctx->cmd_buf = NULL;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
// Nothing in the buffer, poll the lirc fd
|
||||
if(lirc_nextcode(&code) != 0) {
|
||||
mp_msg(MSGT_LIRC,MSGL_ERR,"Lirc error :(\n");
|
||||
MP_ERR(ctx, "Lirc error.\n");
|
||||
return MP_INPUT_DEAD;
|
||||
}
|
||||
|
||||
if(!code) return MP_INPUT_NOTHING;
|
||||
|
||||
// We put all cmds in a single buffer separated by \n
|
||||
while((r = lirc_code2char(lirc_config,code,&c))==0 && c!=NULL) {
|
||||
while((r = lirc_code2char(ctx->lirc_config,code,&c))==0 && c!=NULL) {
|
||||
int l = strlen(c);
|
||||
if(l <= 0)
|
||||
continue;
|
||||
cmd_buf = realloc(cmd_buf,cl+l+2);
|
||||
memcpy(&cmd_buf[cl],c,l);
|
||||
ctx->cmd_buf = realloc(ctx->cmd_buf,cl+l+2);
|
||||
memcpy(&ctx->cmd_buf[cl],c,l);
|
||||
cl += l+1;
|
||||
cmd_buf[cl-1] = '\n';
|
||||
cmd_buf[cl] = '\0';
|
||||
ctx->cmd_buf[cl-1] = '\n';
|
||||
ctx->cmd_buf[cl] = '\0';
|
||||
}
|
||||
|
||||
free(code);
|
||||
|
||||
if(r < 0)
|
||||
return MP_INPUT_DEAD;
|
||||
else if(cmd_buf) // return the first command in the buffer
|
||||
return mp_input_lirc_read(fd,dest,s);
|
||||
else if(ctx->cmd_buf) // return the first command in the buffer
|
||||
return mp_input_lirc_read(ctx,fd,dest,s);
|
||||
else
|
||||
return MP_INPUT_RETRY;
|
||||
|
||||
}
|
||||
|
||||
int mp_input_lirc_close(int fd)
|
||||
static int mp_input_lirc_close(void *pctx,int fd)
|
||||
{
|
||||
free(cmd_buf);
|
||||
cmd_buf = NULL;
|
||||
lirc_freeconfig(lirc_config);
|
||||
struct ctx *ctx = pctx;
|
||||
free(ctx->cmd_buf);
|
||||
lirc_freeconfig(ctx->lirc_config);
|
||||
lirc_deinit();
|
||||
talloc_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
11
input/lirc.h
11
input/lirc.h
@ -19,12 +19,9 @@
|
||||
#ifndef MPLAYER_LIRC_H
|
||||
#define MPLAYER_LIRC_H
|
||||
|
||||
int
|
||||
mp_input_lirc_init(void);
|
||||
|
||||
int
|
||||
mp_input_lirc_read(int fd,char* dest, int s);
|
||||
|
||||
int mp_input_lirc_close(int fd);
|
||||
struct input_ctx;
|
||||
struct mp_log;
|
||||
int mp_input_lirc_init(struct input_ctx *ictx, struct mp_log *log,
|
||||
char *lirc_configfile);
|
||||
|
||||
#endif /* MPLAYER_LIRC_H */
|
||||
|
@ -574,10 +574,6 @@ const m_option_t mp_opts[] = {
|
||||
OPT_STRING("stream-capture", stream_capture, 0),
|
||||
OPT_STRING("stream-dump", stream_dump, 0),
|
||||
|
||||
#if HAVE_LIRC
|
||||
{"lircconf", &lirc_configfile, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
|
||||
#endif
|
||||
|
||||
OPT_CHOICE_OR_INT("loop", loop_times, M_OPT_GLOBAL, 2, 10000,
|
||||
({"no", -1}, {"1", -1},
|
||||
{"inf", 0})),
|
||||
|
@ -254,6 +254,7 @@ typedef struct MPOpts {
|
||||
char *in_file;
|
||||
int use_joystick;
|
||||
int use_lirc;
|
||||
char *lirc_configfile;
|
||||
int use_lircc;
|
||||
int use_alt_gr;
|
||||
int use_ar;
|
||||
|
@ -358,7 +358,7 @@ static void walk_buf(unsigned int count) {
|
||||
getch2_pos = 0;
|
||||
}
|
||||
|
||||
bool getch2(struct input_ctx *input_ctx)
|
||||
static bool getch2(struct input_ctx *input_ctx)
|
||||
{
|
||||
int retval = read(0, &getch2_buf[getch2_pos], BUF_LEN - getch2_len - getch2_pos);
|
||||
/* Return false on EOF to stop running select() on the FD, as it'd
|
||||
@ -437,6 +437,18 @@ bool getch2(struct input_ctx *input_ctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int read_keys(void *ctx, int fd)
|
||||
{
|
||||
if (getch2(ctx))
|
||||
return MP_INPUT_NOTHING;
|
||||
return MP_INPUT_DEAD;
|
||||
}
|
||||
|
||||
void terminal_setup_getch(struct input_ctx *ictx)
|
||||
{
|
||||
mp_input_add_fd(ictx, 0, 1, NULL, read_keys, NULL, ictx);
|
||||
}
|
||||
|
||||
static volatile int getch2_active = 0;
|
||||
static volatile int getch2_enabled = 0;
|
||||
|
||||
@ -593,6 +605,11 @@ void terminal_set_foreground_color(FILE *stream, int c)
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_setup_stdin_cmd_input(struct input_ctx *ictx)
|
||||
{
|
||||
mp_input_add_fd(ictx, 0, 1, input_default_read_cmd, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int terminal_init(void)
|
||||
{
|
||||
load_termcap(NULL);
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include "input/input.h"
|
||||
#include "terminal.h"
|
||||
|
||||
int screen_width = 80;
|
||||
int screen_height = 24;
|
||||
char *erase_to_end_of_line = NULL;
|
||||
|
||||
#define hSTDOUT GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
#define hSTDERR GetStdHandle(STD_ERROR_HANDLE)
|
||||
static short stdoutAttrs = 0;
|
||||
@ -47,7 +51,7 @@ static const unsigned char ansi2win32[8] = {
|
||||
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
|
||||
};
|
||||
|
||||
int mp_input_slave_cmd_func(int fd, char *dest, int size)
|
||||
static int mp_input_slave_cmd_func(void *ctx, int fd, char *dest, int size)
|
||||
{
|
||||
DWORD retval;
|
||||
HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
@ -66,9 +70,10 @@ int mp_input_slave_cmd_func(int fd, char *dest, int size)
|
||||
return MP_INPUT_NOTHING;
|
||||
}
|
||||
|
||||
int screen_width = 80;
|
||||
int screen_height = 24;
|
||||
char *erase_to_end_of_line = NULL;
|
||||
void terminal_setup_stdin_cmd_input(struct input_ctx *ictx)
|
||||
{
|
||||
mp_input_add_fd(ictx, 0, 0, mp_input_slave_cmd_func, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void get_screen_size(void)
|
||||
{
|
||||
@ -172,7 +177,7 @@ static int getch2_internal(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool getch2(struct input_ctx *ctx)
|
||||
static bool getch2(struct input_ctx *ctx)
|
||||
{
|
||||
int r = getch2_internal();
|
||||
if (r >= 0)
|
||||
@ -180,6 +185,18 @@ bool getch2(struct input_ctx *ctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int read_keys(void *ctx, int fd)
|
||||
{
|
||||
if (getch2(ctx))
|
||||
return MP_INPUT_NOTHING;
|
||||
return MP_INPUT_DEAD;
|
||||
}
|
||||
|
||||
void terminal_setup_getch(struct input_ctx *ictx)
|
||||
{
|
||||
mp_input_add_fd(ictx, 0, 1, NULL, read_keys, NULL, ictx);
|
||||
}
|
||||
|
||||
void getch2_poll(void)
|
||||
{
|
||||
}
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct input_ctx;
|
||||
|
||||
/* Screen size. Initialized by load_termcap() and get_screen_size() */
|
||||
extern int screen_width;
|
||||
extern int screen_height;
|
||||
@ -37,6 +39,12 @@ extern char * erase_to_end_of_line;
|
||||
/* Global initialization for terminal output. */
|
||||
int terminal_init(void);
|
||||
|
||||
/* Setup ictx to read input commands from stdin (slave mode) */
|
||||
void terminal_setup_stdin_cmd_input(struct input_ctx *ictx);
|
||||
|
||||
/* Setup ictx to read keys from the terminal */
|
||||
void terminal_setup_getch(struct input_ctx *ictx);
|
||||
|
||||
/* Return whether the process has been backgrounded. */
|
||||
bool terminal_in_background(void);
|
||||
|
||||
@ -54,18 +62,4 @@ void getch2_disable(void);
|
||||
/* Enable and disable STDIN line-buffering */
|
||||
void getch2_poll(void);
|
||||
|
||||
/* Read a character or a special key code (see keycodes.h) */
|
||||
struct input_ctx;
|
||||
bool getch2(struct input_ctx *ictx);
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
// slave cmd function for Windows
|
||||
int mp_input_slave_cmd_func(int fd,char* dest,int size);
|
||||
#define USE_FD0_CMD_SELECT 0
|
||||
#define MP_INPUT_SLAVE_CMD_FUNC mp_input_slave_cmd_func
|
||||
#else
|
||||
#define USE_FD0_CMD_SELECT 1
|
||||
#define MP_INPUT_SLAVE_CMD_FUNC NULL
|
||||
#endif
|
||||
|
||||
#endif /* MPLAYER_GETCH2_H */
|
||||
|
@ -270,28 +270,6 @@ static void osdep_preinit(int *p_argc, char ***p_argv)
|
||||
mp_time_init();
|
||||
}
|
||||
|
||||
static int read_keys(void *ctx, int fd)
|
||||
{
|
||||
if (getch2(ctx))
|
||||
return MP_INPUT_NOTHING;
|
||||
return MP_INPUT_DEAD;
|
||||
}
|
||||
|
||||
static void init_input(struct MPContext *mpctx)
|
||||
{
|
||||
mpctx->input = mp_input_init(mpctx->global);
|
||||
if (mpctx->opts->slave_mode)
|
||||
mp_input_add_cmd_fd(mpctx->input, 0, USE_FD0_CMD_SELECT, MP_INPUT_SLAVE_CMD_FUNC, NULL);
|
||||
else if (mpctx->opts->consolecontrols)
|
||||
mp_input_add_key_fd(mpctx->input, 0, 1, read_keys, NULL, mpctx->input);
|
||||
// Set the libstream interrupt callback
|
||||
stream_set_interrupt_callback(mp_input_check_interrupt, mpctx->input);
|
||||
|
||||
#if HAVE_COCOA
|
||||
cocoa_set_input_context(mpctx->input);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int cfg_include(void *ctx, char *filename, int flags)
|
||||
{
|
||||
struct MPContext *mpctx = ctx;
|
||||
@ -379,7 +357,11 @@ static int mpv_main(int argc, char *argv[])
|
||||
set_priority();
|
||||
#endif
|
||||
|
||||
init_input(mpctx);
|
||||
mpctx->input = mp_input_init(mpctx->global);
|
||||
stream_set_interrupt_callback(mp_input_check_interrupt, mpctx->input);
|
||||
#if HAVE_COCOA
|
||||
cocoa_set_input_context(mpctx->input);
|
||||
#endif
|
||||
|
||||
#if HAVE_ENCODING
|
||||
if (opts->encode_output.file && *opts->encode_output.file) {
|
||||
@ -397,6 +379,11 @@ static int mpv_main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mpctx->opts->slave_mode)
|
||||
terminal_setup_stdin_cmd_input(mpctx->input);
|
||||
else if (mpctx->opts->consolecontrols)
|
||||
terminal_setup_getch(mpctx->input);
|
||||
|
||||
if (opts->consolecontrols)
|
||||
getch2_enable();
|
||||
|
||||
|
@ -434,8 +434,8 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags)
|
||||
if (vo->config_ok)
|
||||
vo->params = talloc_memdup(vo, &p2, sizeof(p2));
|
||||
if (vo->registered_fd == -1 && vo->event_fd != -1 && vo->config_ok) {
|
||||
mp_input_add_key_fd(vo->input_ctx, vo->event_fd, 1, event_fd_callback,
|
||||
NULL, vo);
|
||||
mp_input_add_fd(vo->input_ctx, vo->event_fd, 1, NULL, event_fd_callback,
|
||||
NULL, vo);
|
||||
vo->registered_fd = vo->event_fd;
|
||||
}
|
||||
vo->frame_loaded = false;
|
||||
|
Loading…
Reference in New Issue
Block a user