174
174
{ MP_CMD_SWITCH_RATIO, "switch_ratio", 0, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
175
175
{ MP_CMD_VO_FULLSCREEN, "vo_fullscreen", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
176
176
{ MP_CMD_VO_ONTOP, "vo_ontop", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
177
{ MP_CMD_FILE_FILTER, "file_filter", 1, { { MP_CMD_ARG_INT, {0}}, {-1,{0}}}},
178
177
{ MP_CMD_VO_ROOTWIN, "vo_rootwin", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
179
178
{ MP_CMD_VO_BORDER, "vo_border", 0, { {MP_CMD_ARG_INT,{-1}}, {-1,{0}} } },
180
{ MP_CMD_SCREENSHOT, "screenshot", 0, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
179
{ MP_CMD_SCREENSHOT, "screenshot", 0, { {MP_CMD_ARG_INT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
181
180
{ MP_CMD_PANSCAN, "panscan",1, { {MP_CMD_ARG_FLOAT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
182
181
{ MP_CMD_SWITCH_VSYNC, "switch_vsync", 0, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
183
182
{ MP_CMD_LOADFILE, "loadfile", 1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
192
191
{ MP_CMD_DVDNAV, "dvdnav", 1, { {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } },
196
{ MP_CMD_MENU, "menu",1, { {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } },
197
{ MP_CMD_SET_MENU, "set_menu",1, { {MP_CMD_ARG_STRING, {0}}, {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } },
198
{ MP_CMD_CHELP, "help", 0, { {-1,{0}} } },
199
{ MP_CMD_CEXIT, "exit", 0, { {-1,{0}} } },
200
{ MP_CMD_CHIDE, "hide", 0, { {MP_CMD_ARG_INT,{3000}}, {-1,{0}} } },
203
194
{ MP_CMD_GET_VO_FULLSCREEN, "get_vo_fullscreen", 0, { {-1,{0}} } },
204
195
{ MP_CMD_GET_SUB_VISIBILITY, "get_sub_visibility", 0, { {-1,{0}} } },
205
196
{ MP_CMD_KEYDOWN_EVENTS, "key_down_event", 1, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
658
668
return talloc_asprintf_append_buffer(ret, "%#-8x", key);
671
static char *get_key_combo_name(int *keys, int max)
673
char *ret = talloc_strdup(NULL, "");
675
ret = get_key_name(*keys, ret);
676
if (--max && *++keys)
677
talloc_asprintf_append_buffer(ret, "-");
684
static bool is_abort_cmd(int cmd_id)
688
case MP_CMD_PLAY_TREE_STEP:
689
case MP_CMD_PLAY_TREE_UP_STEP:
690
case MP_CMD_PLAY_ALT_SRC_STEP:
696
static void queue_pop(struct cmd_queue *queue)
698
assert(queue->num_cmds > 0);
699
struct mp_cmd *cmd = queue->first;
700
queue->first = cmd->queue_next;
702
queue->num_abort_cmds -= is_abort_cmd(cmd->id);
705
static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd,
708
if (!queue->num_cmds) {
711
} else if (at_head) {
712
queue->first->queue_prev = cmd;
713
cmd->queue_next = queue->first;
716
queue->last->queue_next = cmd;
717
cmd->queue_prev = queue->last;
721
queue->num_abort_cmds += is_abort_cmd(cmd->id);
661
724
int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select,
662
mp_cmd_func_t read_func, mp_close_func_t close_func)
725
int read_func(int fd, char *dest, int size),
726
int close_func(int fd))
664
728
if (ictx->num_cmd_fd == MP_MAX_CMD_FD) {
665
729
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many command file descriptors, "
1104
1141
cmd = find_bind_for_key(def_cmd_binds, n, keys);
1106
1143
if (cmd == NULL) {
1107
char *key_buf = get_key_name(keys[0]);
1108
mp_tmsg(MSGT_INPUT, MSGL_WARN, "No bind found for key '%s'.", key_buf);
1144
char *key_buf = get_key_combo_name(keys, n);
1145
mp_tmsg(MSGT_INPUT, MSGL_WARN,
1146
"No bind found for key '%s'.\n", key_buf);
1109
1147
talloc_free(key_buf);
1111
for (int s = 1; s < n; s++) {
1112
key_buf = get_key_name(keys[s]);
1113
mp_msg(MSGT_INPUT, MSGL_WARN, "-%s", key_buf);
1114
talloc_free(key_buf);
1117
mp_msg(MSGT_INPUT, MSGL_WARN, " \n");
1120
1150
if (strcmp(cmd, "ignore") == 0)
1122
1152
ret = mp_input_parse_cmd(cmd);
1124
char *key_buf = get_key_name(ictx->key_down[0]);
1125
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Invalid command for bound key %s",
1154
char *key_buf = get_key_combo_name(keys, n);
1155
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1156
"Invalid command for bound key '%s': '%s'\n", key_buf, cmd);
1127
1157
talloc_free(key_buf);
1128
if (ictx->num_key_down > 1) {
1130
for (s = 1; s < ictx->num_key_down; s++) {
1131
char *key_buf = get_key_name(ictx->key_down[s]);
1132
mp_msg(MSGT_INPUT, MSGL_ERR, "-%s", key_buf);
1133
talloc_free(key_buf);
1136
mp_msg(MSGT_INPUT, MSGL_ERR, " : %s \n", cmd);
1269
void mp_input_feed_key(struct input_ctx *ictx, int code)
1271
ictx->got_new_events = true;
1272
if (code == MP_INPUT_RELEASE_ALL) {
1273
memset(ictx->key_down, 0, sizeof(ictx->key_down));
1274
ictx->num_key_down = 0;
1275
ictx->last_key_down = 0;
1278
struct mp_cmd *cmd = interpret_key(ictx, code);
1281
struct cmd_queue *queue = &ictx->key_cmd_queue;
1282
if (queue->num_cmds >= ictx->key_fifo_size &&
1283
(!is_abort_cmd(cmd->id) || queue->num_abort_cmds))
1285
queue_add(queue, cmd, false);
1288
static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd)
1292
while ((r = read_cmd(cmd_fd, &text)) >= 0) {
1293
ictx->got_new_events = true;
1294
struct mp_cmd *cmd = mp_input_parse_cmd(text);
1297
queue_add(&ictx->control_cmd_queue, cmd, false);
1298
if (!cmd_fd->got_cmd)
1301
if (r == MP_INPUT_ERROR)
1302
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command file descriptor %d\n",
1304
else if (r == MP_INPUT_DEAD)
1305
cmd_fd->dead = true;
1308
static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd)
1310
int code = key_fd->read_func.key(key_fd->ctx, key_fd->fd);
1311
if (code >= 0 || code == MP_INPUT_RELEASE_ALL) {
1312
mp_input_feed_key(ictx, code);
1316
if (code == MP_INPUT_ERROR)
1317
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1318
"Error on key input file descriptor %d\n", key_fd->fd);
1319
else if (code == MP_INPUT_DEAD) {
1320
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1321
"Dead key input on file descriptor %d\n", key_fd->fd);
1322
key_fd->dead = true;
1258
1327
* \param time time to wait at most for an event in milliseconds
1260
static mp_cmd_t *read_events(struct input_ctx *ictx, int time)
1329
static void read_events(struct input_ctx *ictx, int time)
1264
struct mp_input_fd *key_fds = ictx->key_fds;
1265
struct mp_input_fd *cmd_fds = ictx->cmd_fds;
1266
for (i = 0; i < ictx->num_key_fd; i++)
1331
ictx->got_new_events = false;
1332
struct input_fd *key_fds = ictx->key_fds;
1333
struct input_fd *cmd_fds = ictx->cmd_fds;
1334
for (int i = 0; i < ictx->num_key_fd; i++)
1267
1335
if (key_fds[i].dead) {
1268
1336
mp_input_rm_key_fd(ictx, key_fds[i].fd);
1271
for (i = 0; i < ictx->num_cmd_fd; i++)
1338
} else if (time && key_fds[i].no_select)
1339
read_key_fd(ictx, &key_fds[i]);
1340
for (int i = 0; i < ictx->num_cmd_fd; i++)
1272
1341
if (cmd_fds[i].dead || cmd_fds[i].eof) {
1273
1342
mp_input_rm_cmd_fd(ictx, cmd_fds[i].fd);
1275
} else if (cmd_fds[i].got_cmd)
1344
} else if (time && cmd_fds[i].no_select)
1345
read_cmd_fd(ictx, &cmd_fds[i]);
1346
if (ictx->got_new_events)
1277
1348
#ifdef HAVE_POSIX_SELECT
1282
for (i = 0; i < ictx->num_key_fd; i++) {
1283
if (key_fds[i].no_select)
1285
if (key_fds[i].fd > max_fd)
1286
max_fd = key_fds[i].fd;
1287
FD_SET(key_fds[i].fd, &fds);
1289
for (i = 0; i < ictx->num_cmd_fd; i++) {
1290
if (cmd_fds[i].no_select)
1292
if (cmd_fds[i].fd > max_fd)
1293
max_fd = cmd_fds[i].fd;
1294
FD_SET(cmd_fds[i].fd, &fds);
1296
struct timeval tv, *time_val;
1298
tv.tv_sec = time / 1000;
1299
tv.tv_usec = (time % 1000) * 1000;
1303
if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
1305
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
1352
for (int i = 0; i < ictx->num_key_fd; i++) {
1353
if (key_fds[i].no_select)
1355
if (key_fds[i].fd > max_fd)
1356
max_fd = key_fds[i].fd;
1357
FD_SET(key_fds[i].fd, &fds);
1359
for (int i = 0; i < ictx->num_cmd_fd; i++) {
1360
if (cmd_fds[i].no_select)
1362
if (cmd_fds[i].fd > max_fd)
1363
max_fd = cmd_fds[i].fd;
1364
FD_SET(cmd_fds[i].fd, &fds);
1366
struct timeval tv, *time_val;
1368
tv.tv_sec = time / 1000;
1369
tv.tv_usec = (time % 1000) * 1000;
1373
if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
1375
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
1311
if (!got_cmd && time)
1312
1381
usec_sleep(time * 1000);
1316
for (i = 0; i < ictx->num_key_fd; i++) {
1385
for (int i = 0; i < ictx->num_key_fd; i++) {
1317
1386
#ifdef HAVE_POSIX_SELECT
1318
1387
if (!key_fds[i].no_select && !FD_ISSET(key_fds[i].fd, &fds))
1324
code = key_fds[i].read_func.key(key_fds[i].ctx, key_fds[i].fd);
1326
if (code == MP_INPUT_RELEASE_ALL) {
1327
memset(ictx->key_down, 0, sizeof(ictx->key_down));
1328
ictx->num_key_down = 0;
1329
ictx->last_key_down = 0;
1334
mp_cmd_t *ret = interpret_key(ictx, code);
1338
if (code == MP_INPUT_ERROR)
1339
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on key input "
1340
"file descriptor %d\n", key_fds[i].fd);
1341
else if (code == MP_INPUT_DEAD) {
1342
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Dead key input on "
1343
"file descriptor %d\n", key_fds[i].fd);
1344
key_fds[i].dead = 1;
1390
read_key_fd(ictx, &key_fds[i]);
1347
mp_cmd_t *autorepeat_cmd = check_autorepeat(ictx);
1349
return autorepeat_cmd;
1351
for (i = 0; i < ictx->num_cmd_fd; i++) {
1393
for (int i = 0; i < ictx->num_cmd_fd; i++) {
1352
1394
#ifdef HAVE_POSIX_SELECT
1353
if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds) &&
1354
!cmd_fds[i].got_cmd)
1395
if (!cmd_fds[i].no_select && !FD_ISSET(cmd_fds[i].fd, &fds))
1359
while ((r = read_cmd(&cmd_fds[i], &cmd)) >= 0) {
1360
mp_cmd_t *ret = mp_input_parse_cmd(cmd);
1365
if (r == MP_INPUT_ERROR)
1366
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command "
1367
"file descriptor %d\n", cmd_fds[i].fd);
1368
else if (r == MP_INPUT_DEAD)
1369
cmd_fds[i].dead = 1;
1398
read_cmd_fd(ictx, &cmd_fds[i]);
1402
/* To support blocking file descriptors we don't loop the read over
1403
* every source until it's known to be empty. Instead we use this wrapper
1404
* to run select() again.
1406
static void read_all_events(struct input_ctx *ictx, int time)
1409
read_events(ictx, time);
1410
if (!ictx->got_new_events)
1376
1416
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
1378
if (!cmd || ictx->cmd_queue_length >= CMD_QUEUE_SIZE)
1418
ictx->got_new_events = true;
1380
ictx->cmd_queue[ictx->cmd_queue_end] = cmd;
1381
ictx->cmd_queue_end = (ictx->cmd_queue_end + 1) % CMD_QUEUE_SIZE;
1382
ictx->cmd_queue_length++;
1421
queue_add(&ictx->control_cmd_queue, cmd, true);
1386
static mp_cmd_t *get_queued_cmd(struct input_ctx *ictx, int peek_only)
1390
if (ictx->cmd_queue_length == 0)
1393
ret = ictx->cmd_queue[ictx->cmd_queue_start];
1396
ictx->cmd_queue_length--;
1397
ictx->cmd_queue_start = (ictx->cmd_queue_start + 1) % CMD_QUEUE_SIZE;
1404
1426
* \param peek_only when set, the returned command stays in the queue.
1405
1427
* Do not free the returned cmd whe you set this!
1407
1429
mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
1409
mp_cmd_t *ret = NULL;
1410
mp_cmd_filter_t *cf;
1413
1431
if (async_quit_request)
1414
1432
return mp_input_parse_cmd("quit 1");
1417
ret = get_queued_cmd(ictx, peek_only);
1421
ret = read_events(ictx, time);
1424
ret = get_queued_cmd(ictx, peek_only);
1431
for (cf = cmd_filters; cf; cf = cf->next) {
1432
if (cf->filter(ret, cf->ctx)) {
1433
if (peek_only && from_queue)
1434
// The filter ate the cmd, so we remove it from queue
1435
ret = get_queued_cmd(ictx, 0);
1434
if (ictx->control_cmd_queue.num_cmds || ictx->key_cmd_queue.num_cmds)
1436
read_all_events(ictx, time);
1438
struct cmd_queue *queue = &ictx->control_cmd_queue;
1439
if (!queue->num_cmds)
1440
queue = &ictx->key_cmd_queue;
1441
if (!queue->num_cmds) {
1442
ret = check_autorepeat(ictx);
1445
queue_add(queue, ret, false);
1441
if (!from_queue && peek_only)
1442
mp_input_queue_cmd(ictx, ret);
1448
mp_cmd_free(mp_cmd_t *cmd) {
1455
void mp_cmd_free(mp_cmd_t *cmd)
1449
1457
talloc_free(cmd);
1453
mp_cmd_clone(mp_cmd_t *cmd) {
1460
mp_cmd_t *mp_cmd_clone(mp_cmd_t *cmd)
1457
assert(cmd != NULL);
1460
1465
ret = talloc_memdup(NULL, cmd, sizeof(mp_cmd_t));
1461
1466
ret->name = talloc_strdup(ret, cmd->name);
1604
1606
} else if (r == 0) {
1608
buffer[bs - 1] = '\0';
1611
// Empty buffer : return
1613
1614
mp_msg(MSGT_INPUT, MSGL_V, "Input config file %s parsed: "
1614
1615
"%d binds\n", file, n_binds);
1621
1619
if (comments) {
1622
iter += strcspn(iter, "\n");
1623
if (*iter == 0) { // Buffer was full of comment
1629
memmove(buffer, iter, r + 1);
1635
// Find the wanted key
1637
// Jump beginning space
1638
iter += strspn(iter, SPACE_CHAR);
1639
if (*iter == 0) { // Buffer was full of space char
1643
if (iter[0] == '#') { // Comments
1647
// Find the end of the key code name
1648
end = iter + strcspn(iter, SPACE_CHAR);
1649
if (*end == 0) { // Key name doesn't fit in the buffer
1650
if (buffer == iter) {
1651
if (eof && (buffer - iter) == bs)
1652
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1653
"Unfinished binding %s\n", iter);
1655
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Buffer is too small "
1656
"for this key name: %s\n", iter);
1659
memmove(buffer, iter, end - iter);
1664
char name[end - iter + 1];
1665
strncpy(name, iter, end - iter);
1666
name[end - iter] = '\0';
1667
if (!get_input_from_name(name, keys)) {
1668
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Unknown key '%s'\n", name);
1673
if (bs > (end - buffer))
1674
memmove(buffer, end, bs - (end - buffer));
1677
} else { // Get the command
1678
while (iter[0] == ' ' || iter[0] == '\t')
1681
if (iter[0] == '\n' || iter[0] == '\r') {
1683
char *key_buf = get_key_name(keys[0]);
1684
mp_tmsg(MSGT_INPUT, MSGL_ERR, "No command found for key %s",
1686
talloc_free(key_buf);
1687
for (i = 1; keys[i] != 0; i++) {
1688
char *key_buf = get_key_name(keys[i]);
1689
mp_msg(MSGT_INPUT, MSGL_ERR, "-%s", key_buf);
1690
talloc_free(key_buf);
1692
mp_msg(MSGT_INPUT, MSGL_ERR, "\n");
1694
if (iter > buffer) {
1695
memmove(buffer, iter, bs - (iter - buffer));
1696
bs -= (iter - buffer);
1700
end = iter + strcspn(iter, "\n\r");
1701
if (*end == 0 && !(eof && ((end + 1) - buffer) == bs)) {
1702
if (iter == buffer) {
1703
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Buffer is too small "
1704
"for command %s\n", buffer);
1708
memmove(buffer, iter, end - iter);
1713
char cmd[end - iter + 1];
1714
strncpy(cmd, iter, end - iter);
1715
cmd[end - iter] = '\0';
1716
//printf("Set bind %d => %s\n",keys[0],cmd);
1717
bind_keys(ictx, keys, cmd);
1722
if (bs > (end - buffer))
1723
memmove(buffer, end, bs - (end - buffer));
1724
bs -= (end - buffer);
1725
buffer[bs - 1] = '\0';
1620
int idx = bstrchr(buf, '\n');
1622
buf = bstr_cut(buf, idx + 1);
1625
buf = bstr_cut(buf, buf.len);
1628
buf = bstr_lstrip(buf);
1629
if (buf.start != buffer)
1631
if (buf.start[0] == '#') {
1635
int eol = bstrchr(buf, '\n');
1640
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1641
"Key binding is too long: %.*s\n", BSTR_P(buf));
1646
struct bstr line = bstr_splice(buf, 0, eol);
1647
buf = bstr_cut(buf, eol);
1648
struct bstr command;
1649
// Find the key name starting a line
1650
struct bstr keyname = bstr_split(line, SPACE_CHAR, &command);
1651
command = bstr_strip(command);
1652
if (command.len == 0) {
1653
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1654
"Unfinished key binding: %.*s\n", BSTR_P(line));
1657
char *name = bstrdup0(NULL, keyname);
1658
if (!get_input_from_name(name, keys)) {
1660
mp_tmsg(MSGT_INPUT, MSGL_ERR,
1661
"Unknown key '%.*s'\n", BSTR_P(keyname));
1665
char *cmd = bstrdup0(NULL, command);
1666
bind_keys(ictx, keys, cmd);
1729
mp_tmsg(MSGT_INPUT, MSGL_ERR, "What are we doing here?\n");
1731
mp_input_set_section(ictx, NULL);
1735
1672
void mp_input_set_section(struct input_ctx *ictx, char *name)
1737
mp_cmd_bind_section_t *bind_section = NULL;
1674
struct cmd_bind_section *bind_section = NULL;
1739
1676
ictx->cmd_binds = NULL;
1740
1677
ictx->cmd_binds_default = NULL;