~ubuntu-branches/ubuntu/precise/mplayer2/precise-proposed

« back to all changes in this revision

Viewing changes to input/input.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2012-01-12 22:59:30 UTC
  • mfrom: (5.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20120112225930-jsg10o7na7nk73w5
Tags: 2.0-426-gc32b3ed-2
* Upload to unstable
* don't build-depend on libcdparanoia-dev on the hurd

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <sys/time.h>
30
30
#include <fcntl.h>
31
31
#include <ctype.h>
 
32
#include <assert.h>
32
33
 
33
34
#include "input.h"
34
 
#ifdef MP_DEBUG
35
 
#include <assert.h>
36
 
#endif
37
35
#include "mp_fifo.h"
38
36
#include "keycodes.h"
39
37
#include "osdep/timer.h"
58
56
 
59
57
#include "ar.h"
60
58
 
61
 
typedef struct mp_cmd_bind {
 
59
#define MP_MAX_KEY_DOWN 32
 
60
 
 
61
struct cmd_bind {
62
62
    int input[MP_MAX_KEY_DOWN + 1];
63
63
    char *cmd;
64
 
} mp_cmd_bind_t;
 
64
};
65
65
 
66
 
typedef struct mp_key_name {
 
66
struct key_name {
67
67
    int key;
68
68
    char *name;
69
 
} mp_key_name_t;
 
69
};
70
70
 
71
71
/// This array defines all known commands.
72
72
/// The first field is an id used to recognize the command without too many strcmp.
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}} } },
193
192
#endif
194
193
 
195
 
#ifdef CONFIG_MENU
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}} } },
201
 
#endif
202
 
 
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}} } },
224
215
/// The names of the keys as used in input.conf
225
216
/// If you add some new keys, you also need to add them here
226
217
 
227
 
static const mp_key_name_t key_names[] = {
 
218
static const struct key_name key_names[] = {
228
219
  { ' ', "SPACE" },
229
220
  { '#', "SHARP" },
230
221
  { KEY_ENTER, "ENTER" },
277
268
  { MOUSE_BTN7, "MOUSE_BTN7" },
278
269
  { MOUSE_BTN8, "MOUSE_BTN8" },
279
270
  { MOUSE_BTN9, "MOUSE_BTN9" },
 
271
  { MOUSE_BTN10, "MOUSE_BTN10" },
 
272
  { MOUSE_BTN11, "MOUSE_BTN11" },
 
273
  { MOUSE_BTN12, "MOUSE_BTN12" },
 
274
  { MOUSE_BTN13, "MOUSE_BTN13" },
 
275
  { MOUSE_BTN14, "MOUSE_BTN14" },
 
276
  { MOUSE_BTN15, "MOUSE_BTN15" },
 
277
  { MOUSE_BTN16, "MOUSE_BTN16" },
 
278
  { MOUSE_BTN17, "MOUSE_BTN17" },
 
279
  { MOUSE_BTN18, "MOUSE_BTN18" },
 
280
  { MOUSE_BTN19, "MOUSE_BTN19" },
280
281
  { MOUSE_BTN0_DBL, "MOUSE_BTN0_DBL" },
281
282
  { MOUSE_BTN1_DBL, "MOUSE_BTN1_DBL" },
282
283
  { MOUSE_BTN2_DBL, "MOUSE_BTN2_DBL" },
287
288
  { MOUSE_BTN7_DBL, "MOUSE_BTN7_DBL" },
288
289
  { MOUSE_BTN8_DBL, "MOUSE_BTN8_DBL" },
289
290
  { MOUSE_BTN9_DBL, "MOUSE_BTN9_DBL" },
 
291
  { MOUSE_BTN10_DBL, "MOUSE_BTN10_DBL" },
 
292
  { MOUSE_BTN11_DBL, "MOUSE_BTN11_DBL" },
 
293
  { MOUSE_BTN12_DBL, "MOUSE_BTN12_DBL" },
 
294
  { MOUSE_BTN13_DBL, "MOUSE_BTN13_DBL" },
 
295
  { MOUSE_BTN14_DBL, "MOUSE_BTN14_DBL" },
 
296
  { MOUSE_BTN15_DBL, "MOUSE_BTN15_DBL" },
 
297
  { MOUSE_BTN16_DBL, "MOUSE_BTN16_DBL" },
 
298
  { MOUSE_BTN17_DBL, "MOUSE_BTN17_DBL" },
 
299
  { MOUSE_BTN18_DBL, "MOUSE_BTN18_DBL" },
 
300
  { MOUSE_BTN19_DBL, "MOUSE_BTN19_DBL" },
290
301
  { JOY_AXIS1_MINUS, "JOY_UP" },
291
302
  { JOY_AXIS1_PLUS, "JOY_DOWN" },
292
303
  { JOY_AXIS0_MINUS, "JOY_LEFT" },
360
371
  { 0, NULL }
361
372
};
362
373
 
363
 
struct mp_key_name modifier_names[] = {
 
374
struct key_name modifier_names[] = {
364
375
    { KEY_MODIFIER_SHIFT, "Shift" },
365
376
    { KEY_MODIFIER_CTRL,  "Ctrl" },
366
377
    { KEY_MODIFIER_ALT,   "Alt" },
374
385
// The first arg is a null terminated array of key codes.
375
386
// The second is the command
376
387
 
377
 
static const mp_cmd_bind_t def_cmd_binds[] = {
 
388
static const struct cmd_bind def_cmd_binds[] = {
378
389
 
379
390
  { { MOUSE_BTN0_DBL, 0 }, "vo_fullscreen" },
380
391
  { { MOUSE_BTN2, 0 }, "pause" },
447
458
  { { '8', 0 }, "saturation 1" },
448
459
  { { 'd', 0 }, "frame_drop" },
449
460
  { { 'D', 0 }, "step_property_osd deinterlace" },
450
 
  { { 'c', 0 }, "step_property_osd yuv_colorspace" },
 
461
  { { 'c', 0 }, "step_property_osd colormatrix" },
451
462
  { { 'r', 0 }, "sub_pos -1" },
452
463
  { { 't', 0 }, "sub_pos +1" },
453
464
  { { 'a', 0 }, "sub_alignment" },
454
465
  { { 'v', 0 }, "sub_visibility" },
 
466
  { { 'V', 0 }, "step_property_osd ass_vsfilter_aspect_compat" },
455
467
  { { 'j', 0 }, "sub_select" },
456
468
  { { 'J', 0 }, "sub_select -3" },
457
469
  { { 'F', 0 }, "forced_subs_only" },
495
507
  { { 'C', 0 }, "step_property_osd capturing" },
496
508
  { { 's', 0 }, "screenshot 0" },
497
509
  { { 'S', 0 }, "screenshot 1" },
 
510
  { { KEY_MODIFIER_ALT + 's', 0 }, "screenshot 0 1" },
 
511
  { { KEY_MODIFIER_ALT + 'S', 0 }, "screenshot 1 1" },
498
512
  { { 'w', 0 }, "panscan -0.1" },
499
513
  { { 'e', 0 }, "panscan +0.1" },
500
514
 
531
545
#define MP_MAX_CMD_FD 10
532
546
#endif
533
547
 
534
 
#define CMD_QUEUE_SIZE 100
535
 
 
536
 
typedef struct mp_input_fd {
 
548
struct input_fd {
537
549
    int fd;
538
550
    union {
539
 
        mp_key_func_t key;
540
 
        mp_cmd_func_t cmd;
 
551
        int (*key)(void *ctx, int fd);
 
552
        int (*cmd)(int fd, char *dest, int size);
541
553
    } read_func;
542
 
    mp_close_func_t close_func;
 
554
    int (*close_func)(int fd);
543
555
    void *ctx;
544
556
    unsigned eof : 1;
545
557
    unsigned drop : 1;
549
561
    // These fields are for the cmd fds.
550
562
    char *buffer;
551
563
    int pos, size;
552
 
} mp_input_fd_t;
553
 
 
554
 
typedef struct mp_cmd_filter mp_cmd_filter_t;
555
 
 
556
 
struct mp_cmd_filter {
557
 
    mp_input_cmd_filter filter;
558
 
    void *ctx;
559
 
    mp_cmd_filter_t *next;
560
564
};
561
565
 
562
 
typedef struct mp_cmd_bind_section mp_cmd_bind_section_t;
563
 
 
564
 
struct mp_cmd_bind_section {
565
 
    mp_cmd_bind_t *cmd_binds;
 
566
struct cmd_bind_section {
 
567
    struct cmd_bind *cmd_binds;
566
568
    char *section;
567
 
    mp_cmd_bind_section_t *next;
 
569
    struct cmd_bind_section *next;
 
570
};
 
571
 
 
572
struct cmd_queue {
 
573
    struct mp_cmd *first;
 
574
    struct mp_cmd *last;
 
575
    int num_cmds;
 
576
    int num_abort_cmds;
568
577
};
569
578
 
570
579
struct input_ctx {
575
584
    // Autorepeat config
576
585
    unsigned int ar_delay;
577
586
    unsigned int ar_rate;
 
587
    // Maximum number of queued commands from keypresses (limit to avoid
 
588
    // repeated slow commands piling up)
 
589
    int key_fifo_size;
578
590
 
579
591
    // these are the keys currently down
580
592
    int key_down[MP_MAX_KEY_DOWN];
583
595
 
584
596
    bool default_bindings;
585
597
    // List of command binding sections
586
 
    mp_cmd_bind_section_t *cmd_bind_sections;
 
598
    struct cmd_bind_section *cmd_bind_sections;
587
599
    // Name of currently used command section
588
600
    char *section;
589
601
    // The command binds of current section
590
 
    mp_cmd_bind_t *cmd_binds;
591
 
    mp_cmd_bind_t *cmd_binds_default;
592
 
 
593
 
    mp_input_fd_t key_fds[MP_MAX_KEY_FD];
 
602
    struct cmd_bind *cmd_binds;
 
603
    struct cmd_bind *cmd_binds_default;
 
604
 
 
605
    // Used to track whether we managed to read something while checking
 
606
    // events sources. If yes, the sources may have more queued.
 
607
    bool got_new_events;
 
608
 
 
609
    struct input_fd key_fds[MP_MAX_KEY_FD];
594
610
    unsigned int num_key_fd;
595
611
 
596
 
    mp_input_fd_t cmd_fds[MP_MAX_CMD_FD];
 
612
    struct input_fd cmd_fds[MP_MAX_CMD_FD];
597
613
    unsigned int num_cmd_fd;
598
614
 
599
 
    mp_cmd_t *cmd_queue[CMD_QUEUE_SIZE];
600
 
    unsigned int cmd_queue_length, cmd_queue_start, cmd_queue_end;
 
615
    struct cmd_queue key_cmd_queue;
 
616
    struct cmd_queue control_cmd_queue;
601
617
};
602
618
 
603
619
 
604
 
static mp_cmd_filter_t *cmd_filters = NULL;
605
 
 
606
 
// Callback to allow the menu filter to grab the incoming keys
607
 
int (*mp_input_key_cb)(int code) = NULL;
608
 
 
609
620
int async_quit_request;
610
621
 
611
622
static int print_key_list(m_option_t *cfg);
626
637
};
627
638
 
628
639
static const m_option_t mp_input_opts[] = {
629
 
    { "input", &input_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
 
640
    { "input", (void *)&input_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
630
641
    OPT_MAKE_FLAGS("joystick", input.use_joystick, CONF_GLOBAL),
631
642
    OPT_MAKE_FLAGS("lirc", input.use_lirc, CONF_GLOBAL),
632
643
    OPT_MAKE_FLAGS("lircc", input.use_lircc, CONF_GLOBAL),
636
647
 
637
648
static int default_cmd_func(int fd, char *buf, int l);
638
649
 
639
 
static char *get_key_name(int key)
 
650
static char *get_key_name(int key, char *ret)
640
651
{
641
 
    char *ret = talloc_strdup(NULL, "");
642
652
    for (int i = 0; modifier_names[i].name; i++) {
643
653
        if (modifier_names[i].key & key) {
644
654
            ret = talloc_asprintf_append_buffer(ret, "%s+",
658
668
    return talloc_asprintf_append_buffer(ret, "%#-8x", key);
659
669
}
660
670
 
 
671
static char *get_key_combo_name(int *keys, int max)
 
672
{
 
673
    char *ret = talloc_strdup(NULL, "");
 
674
    while (1) {
 
675
        ret = get_key_name(*keys, ret);
 
676
        if (--max && *++keys)
 
677
            talloc_asprintf_append_buffer(ret, "-");
 
678
        else
 
679
            break;
 
680
    }
 
681
    return ret;
 
682
}
 
683
 
 
684
static bool is_abort_cmd(int cmd_id)
 
685
{
 
686
    switch (cmd_id) {
 
687
    case MP_CMD_QUIT:
 
688
    case MP_CMD_PLAY_TREE_STEP:
 
689
    case MP_CMD_PLAY_TREE_UP_STEP:
 
690
    case MP_CMD_PLAY_ALT_SRC_STEP:
 
691
        return true;
 
692
    }
 
693
    return false;
 
694
}
 
695
 
 
696
static void queue_pop(struct cmd_queue *queue)
 
697
{
 
698
    assert(queue->num_cmds > 0);
 
699
    struct mp_cmd *cmd = queue->first;
 
700
    queue->first = cmd->queue_next;
 
701
    queue->num_cmds--;
 
702
    queue->num_abort_cmds -= is_abort_cmd(cmd->id);
 
703
}
 
704
 
 
705
static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd,
 
706
                      bool at_head)
 
707
{
 
708
    if (!queue->num_cmds) {
 
709
        queue->first = cmd;
 
710
        queue->last = cmd;
 
711
    } else if (at_head) {
 
712
        queue->first->queue_prev = cmd;
 
713
        cmd->queue_next = queue->first;
 
714
        queue->first = cmd;
 
715
    } else {
 
716
        queue->last->queue_next = cmd;
 
717
        cmd->queue_prev = queue->last;
 
718
        queue->last = cmd;
 
719
    }
 
720
    queue->num_cmds++;
 
721
    queue->num_abort_cmds += is_abort_cmd(cmd->id);
 
722
}
 
723
 
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))
663
727
{
664
728
    if (ictx->num_cmd_fd == MP_MAX_CMD_FD) {
665
729
        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many command file descriptors, "
672
736
        return 0;
673
737
    }
674
738
 
675
 
    ictx->cmd_fds[ictx->num_cmd_fd] = (struct mp_input_fd){
 
739
    ictx->cmd_fds[ictx->num_cmd_fd] = (struct input_fd){
676
740
        .fd = fd,
677
741
        .read_func.cmd = read_func ? read_func : default_cmd_func,
678
742
        .close_func = close_func,
685
749
 
686
750
void mp_input_rm_cmd_fd(struct input_ctx *ictx, int fd)
687
751
{
688
 
    struct mp_input_fd *cmd_fds = ictx->cmd_fds;
 
752
    struct input_fd *cmd_fds = ictx->cmd_fds;
689
753
    unsigned int i;
690
754
 
691
755
    for (i = 0; i < ictx->num_cmd_fd; i++) {
700
764
 
701
765
    if (i + 1 < ictx->num_cmd_fd)
702
766
        memmove(&cmd_fds[i], &cmd_fds[i + 1],
703
 
                (ictx->num_cmd_fd - i - 1) * sizeof(mp_input_fd_t));
 
767
                (ictx->num_cmd_fd - i - 1) * sizeof(struct input_fd));
704
768
    ictx->num_cmd_fd--;
705
769
}
706
770
 
707
771
void mp_input_rm_key_fd(struct input_ctx *ictx, int fd)
708
772
{
709
 
    struct mp_input_fd *key_fds = ictx->key_fds;
 
773
    struct input_fd *key_fds = ictx->key_fds;
710
774
    unsigned int i;
711
775
 
712
776
    for (i = 0; i < ictx->num_key_fd; i++) {
720
784
 
721
785
    if (i + 1 < ictx->num_key_fd)
722
786
        memmove(&key_fds[i], &key_fds[i + 1],
723
 
                (ictx->num_key_fd - i - 1) * sizeof(mp_input_fd_t));
 
787
                (ictx->num_key_fd - i - 1) * sizeof(struct input_fd));
724
788
    ictx->num_key_fd--;
725
789
}
726
790
 
727
791
int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select,
728
 
                        mp_key_func_t read_func, mp_close_func_t close_func,
729
 
                        void *ctx)
 
792
                        int read_func(void *ctx, int fd),
 
793
                        int close_func(int fd), void *ctx)
730
794
{
731
795
    if (ictx->num_key_fd == MP_MAX_KEY_FD) {
732
796
        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many key file descriptors, "
739
803
        return 0;
740
804
    }
741
805
 
742
 
    ictx->key_fds[ictx->num_key_fd] = (struct mp_input_fd){
 
806
    ictx->key_fds[ictx->num_key_fd] = (struct input_fd){
743
807
        .fd = fd,
744
808
        .read_func.key = read_func,
745
809
        .close_func = close_func,
779
843
{
780
844
    int i, l;
781
845
    int pausing = 0;
782
 
    char *ptr, *e;
 
846
    char *ptr;
783
847
    const mp_cmd_t *cmd_def;
784
848
 
785
 
#ifdef MP_DEBUG
786
 
    assert(str != NULL);
787
 
#endif
788
 
 
789
849
    // Ignore heading spaces.
790
850
    while (str[0] == ' ' || str[0] == '\t')
791
851
        ++str;
849
909
            if (errno != 0) {
850
910
                mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d "
851
911
                        "isn't an integer.\n", cmd_def->name, i + 1);
852
 
                ptr = NULL;
 
912
                goto error;
853
913
            }
854
914
            break;
855
915
        case MP_CMD_ARG_FLOAT:
858
918
            if (errno != 0) {
859
919
                mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d "
860
920
                        "isn't a float.\n", cmd_def->name, i + 1);
861
 
                ptr = NULL;
 
921
                goto error;
862
922
            }
863
923
            break;
864
924
        case MP_CMD_ARG_STRING: {
865
 
            char term;
866
 
            char *ptr2 = ptr, *start;
867
 
 
868
 
            if (ptr[0] == '\'' || ptr[0] == '"') {
869
 
                term = ptr[0];
870
 
                ptr2++;
871
 
            } else
872
 
                term = ' ';
873
 
            start = ptr2;
 
925
            int term = ' ';
 
926
            if (*ptr == '\'' || *ptr == '"')
 
927
                term = *ptr++;
 
928
            char *argptr = talloc_size(cmd, strlen(ptr) + 1);
 
929
            cmd->args[i].v.s = argptr;
874
930
            while (1) {
875
 
                e = strchr(ptr2, term);
876
 
                if (!e)
877
 
                    break;
878
 
                if (e <= ptr2 || *(e - 1) != '\\')
879
 
                    break;
880
 
                ptr2 = e + 1;
881
 
            }
882
 
 
883
 
            if (term != ' ' && (!e || e[0] == '\0')) {
884
 
                mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is "
885
 
                        "unterminated.\n", cmd_def->name, i + 1);
886
 
                ptr = NULL;
887
 
                break;
888
 
            } else if (!e)
889
 
                e = ptr + strlen(ptr);
890
 
            l = e - start;
891
 
            ptr2 = start;
892
 
            for (e = strchr(ptr2, '\\'); e && e < start + l; e = strchr(ptr2, '\\')) {
893
 
                memmove(e, e + 1, strlen(e));
894
 
                ptr2 = e + 1;
895
 
                l--;
896
 
            }
897
 
            cmd->args[i].v.s = talloc_strndup(cmd, start, l);
898
 
            if (term != ' ')
899
 
                ptr += l + 2;
 
931
                if (*ptr == 0) {
 
932
                    if (term == ' ')
 
933
                        break;
 
934
                    mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is "
 
935
                            "unterminated.\n", cmd_def->name, i + 1);
 
936
                    goto error;
 
937
                }
 
938
                if (*ptr == term)
 
939
                    break;
 
940
                if (*ptr == '\\')
 
941
                    ptr++;
 
942
                if (*ptr != 0)
 
943
                    *argptr++ = *ptr++;
 
944
            }
 
945
            *argptr = 0;
900
946
            break;
901
947
        }
902
948
        case -1:
909
955
    cmd->nargs = i;
910
956
 
911
957
    if (cmd_def->nargs > cmd->nargs) {
912
 
/*      mp_msg(MSGT_INPUT, MSGL_ERR, "Got command '%s' but\n", str); */
913
958
        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s requires at least %d "
914
959
                "arguments, we found only %d so far.\n", cmd_def->name,
915
960
                cmd_def->nargs, cmd->nargs);
916
 
        mp_cmd_free(cmd);
917
 
        return NULL;
 
961
        goto error;
918
962
    }
919
963
 
920
964
    for (; i < MP_CMD_MAX_ARGS && cmd_def->args[i].type != -1; i++) {
921
 
        memcpy(&cmd->args[i], &cmd_def->args[i], sizeof(mp_cmd_arg_t));
 
965
        memcpy(&cmd->args[i], &cmd_def->args[i], sizeof(struct mp_cmd_arg));
922
966
        if (cmd_def->args[i].type == MP_CMD_ARG_STRING
923
967
            && cmd_def->args[i].v.s != NULL)
924
968
            cmd->args[i].v.s = talloc_strdup(cmd, cmd_def->args[i].v.s);
928
972
        cmd->args[i].type = -1;
929
973
 
930
974
    return cmd;
 
975
 
 
976
 error:
 
977
    mp_cmd_free(cmd);
 
978
    return NULL;
931
979
}
932
980
 
933
981
#define MP_CMD_MAX_SIZE 4096
934
982
 
935
 
static int read_cmd(mp_input_fd_t *mp_fd, char **ret)
 
983
static int read_cmd(struct input_fd *mp_fd, char **ret)
936
984
{
937
985
    char *end;
938
986
    *ret = NULL;
1033
1081
}
1034
1082
 
1035
1083
 
1036
 
void mp_input_add_cmd_filter(mp_input_cmd_filter func, void *ctx)
1037
 
{
1038
 
    mp_cmd_filter_t *filter = talloc_ptrtype(NULL, filter);
1039
 
 
1040
 
    filter->filter = func;
1041
 
    filter->ctx = ctx;
1042
 
    filter->next = cmd_filters;
1043
 
    cmd_filters = filter;
1044
 
}
1045
 
 
1046
 
 
1047
 
static char *find_bind_for_key(const mp_cmd_bind_t *binds, int n, int *keys)
 
1084
static char *find_bind_for_key(const struct cmd_bind *binds, int n, int *keys)
1048
1085
{
1049
1086
    int j;
1050
1087
 
1064
1101
    return binds[j].cmd;
1065
1102
}
1066
1103
 
1067
 
static mp_cmd_bind_section_t *get_bind_section(struct input_ctx *ictx,
 
1104
static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx,
1068
1105
                                               char *section)
1069
1106
{
1070
 
    mp_cmd_bind_section_t *bind_section = ictx->cmd_bind_sections;
 
1107
    struct cmd_bind_section *bind_section = ictx->cmd_bind_sections;
1071
1108
 
1072
1109
    if (section == NULL)
1073
1110
        section = "default";
1104
1141
        cmd = find_bind_for_key(def_cmd_binds, n, keys);
1105
1142
 
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);
1110
 
        if (n > 1) {
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);
1115
 
            }
1116
 
        }
1117
 
        mp_msg(MSGT_INPUT, MSGL_WARN, "                         \n");
1118
1148
        return NULL;
1119
1149
    }
1120
1150
    if (strcmp(cmd, "ignore") == 0)
1121
1151
        return NULL;
1122
1152
    ret =  mp_input_parse_cmd(cmd);
1123
1153
    if (!ret) {
1124
 
        char *key_buf = get_key_name(ictx->key_down[0]);
1125
 
        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Invalid command for bound key %s",
1126
 
                key_buf);
 
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) {
1129
 
            unsigned int s;
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);
1134
 
            }
1135
 
        }
1136
 
        mp_msg(MSGT_INPUT, MSGL_ERR, " : %s             \n", cmd);
1137
1158
    }
1138
1159
    return ret;
1139
1160
}
1153
1174
    if (unmod < 256 && unmod != KEY_ENTER && unmod != KEY_TAB)
1154
1175
        code &= ~KEY_MODIFIER_SHIFT;
1155
1176
 
1156
 
    if (mp_input_key_cb) {
1157
 
        if (code & MP_KEY_DOWN)
1158
 
            return NULL;
1159
 
        code &= ~(MP_KEY_DOWN | MP_NO_REPEAT_KEY);
1160
 
        if (mp_input_key_cb(code))
1161
 
            return NULL;
1162
 
    }
1163
 
 
1164
1177
    if (code & MP_KEY_DOWN) {
1165
1178
        if (ictx->num_key_down > MP_MAX_KEY_DOWN) {
1166
1179
            mp_tmsg(MSGT_INPUT, MSGL_ERR, "Too many key down events "
1253
1266
    return NULL;
1254
1267
}
1255
1268
 
 
1269
void mp_input_feed_key(struct input_ctx *ictx, int code)
 
1270
{
 
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;
 
1276
        return;
 
1277
    }
 
1278
    struct mp_cmd *cmd = interpret_key(ictx, code);
 
1279
    if (!cmd)
 
1280
        return;
 
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))
 
1284
        return;
 
1285
    queue_add(queue, cmd, false);
 
1286
}
 
1287
 
 
1288
static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd)
 
1289
{
 
1290
    int r;
 
1291
    char *text;
 
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);
 
1295
        talloc_free(text);
 
1296
        if (cmd)
 
1297
            queue_add(&ictx->control_cmd_queue, cmd, false);
 
1298
        if (!cmd_fd->got_cmd)
 
1299
            return;
 
1300
    }
 
1301
    if (r == MP_INPUT_ERROR)
 
1302
        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Error on command file descriptor %d\n",
 
1303
                cmd_fd->fd);
 
1304
    else if (r == MP_INPUT_DEAD)
 
1305
        cmd_fd->dead = true;
 
1306
}
 
1307
 
 
1308
static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd)
 
1309
{
 
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);
 
1313
        return;
 
1314
    }
 
1315
 
 
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;
 
1323
    }
 
1324
}
1256
1325
 
1257
1326
/**
1258
1327
 * \param time time to wait at most for an event in milliseconds
1259
1328
 */
1260
 
static mp_cmd_t *read_events(struct input_ctx *ictx, int time)
 
1329
static void read_events(struct input_ctx *ictx, int time)
1261
1330
{
1262
 
    int i;
1263
 
    int got_cmd = 0;
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);
1269
1337
            i--;
1270
 
        }
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);
1274
1343
            i--;
1275
 
        } else if (cmd_fds[i].got_cmd)
1276
 
            got_cmd = 1;
 
1344
        } else if (time && cmd_fds[i].no_select)
 
1345
            read_cmd_fd(ictx, &cmd_fds[i]);
 
1346
    if (ictx->got_new_events)
 
1347
        time = 0;
1277
1348
#ifdef HAVE_POSIX_SELECT
1278
1349
    fd_set fds;
1279
1350
    FD_ZERO(&fds);
1280
 
    if (!got_cmd) {
1281
 
        int max_fd = 0;
1282
 
        for (i = 0; i < ictx->num_key_fd; i++) {
1283
 
            if (key_fds[i].no_select)
1284
 
                continue;
1285
 
            if (key_fds[i].fd > max_fd)
1286
 
                max_fd = key_fds[i].fd;
1287
 
            FD_SET(key_fds[i].fd, &fds);
1288
 
        }
1289
 
        for (i = 0; i < ictx->num_cmd_fd; i++) {
1290
 
            if (cmd_fds[i].no_select)
1291
 
                continue;
1292
 
            if (cmd_fds[i].fd > max_fd)
1293
 
                max_fd = cmd_fds[i].fd;
1294
 
            FD_SET(cmd_fds[i].fd, &fds);
1295
 
        }
1296
 
        struct timeval tv, *time_val;
1297
 
        if (time >= 0) {
1298
 
            tv.tv_sec = time / 1000;
1299
 
            tv.tv_usec = (time % 1000) * 1000;
1300
 
            time_val = &tv;
1301
 
        } else
1302
 
            time_val = NULL;
1303
 
        if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
1304
 
            if (errno != EINTR)
1305
 
                mp_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
1306
 
                        strerror(errno));
1307
 
            FD_ZERO(&fds);
1308
 
        }
 
1351
    int max_fd = 0;
 
1352
    for (int i = 0; i < ictx->num_key_fd; i++) {
 
1353
        if (key_fds[i].no_select)
 
1354
            continue;
 
1355
        if (key_fds[i].fd > max_fd)
 
1356
            max_fd = key_fds[i].fd;
 
1357
        FD_SET(key_fds[i].fd, &fds);
 
1358
    }
 
1359
    for (int i = 0; i < ictx->num_cmd_fd; i++) {
 
1360
        if (cmd_fds[i].no_select)
 
1361
            continue;
 
1362
        if (cmd_fds[i].fd > max_fd)
 
1363
            max_fd = cmd_fds[i].fd;
 
1364
        FD_SET(cmd_fds[i].fd, &fds);
 
1365
    }
 
1366
    struct timeval tv, *time_val;
 
1367
    if (time >= 0) {
 
1368
        tv.tv_sec = time / 1000;
 
1369
        tv.tv_usec = (time % 1000) * 1000;
 
1370
        time_val = &tv;
 
1371
    } else
 
1372
        time_val = NULL;
 
1373
    if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) {
 
1374
        if (errno != EINTR)
 
1375
            mp_tmsg(MSGT_INPUT, MSGL_ERR, "Select error: %s\n",
 
1376
                    strerror(errno));
 
1377
        FD_ZERO(&fds);
1309
1378
    }
1310
1379
#else
1311
 
    if (!got_cmd && time)
 
1380
    if (time)
1312
1381
        usec_sleep(time * 1000);
1313
1382
#endif
1314
1383
 
1315
1384
 
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))
1319
1388
            continue;
1320
1389
#endif
1321
 
 
1322
 
        int code;
1323
 
        while (1) {
1324
 
            code = key_fds[i].read_func.key(key_fds[i].ctx, key_fds[i].fd);
1325
 
            if (code < 0) {
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;
1330
 
                    continue;
1331
 
                }
1332
 
                break;
1333
 
            }
1334
 
            mp_cmd_t *ret = interpret_key(ictx, code);
1335
 
            if (ret)
1336
 
                return ret;
1337
 
        }
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;
1345
 
        }
 
1390
        read_key_fd(ictx, &key_fds[i]);
1346
1391
    }
1347
 
    mp_cmd_t *autorepeat_cmd = check_autorepeat(ictx);
1348
 
    if (autorepeat_cmd)
1349
 
        return autorepeat_cmd;
1350
1392
 
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))
1355
1396
            continue;
1356
1397
#endif
1357
 
        char *cmd;
1358
 
        int r;
1359
 
        while ((r = read_cmd(&cmd_fds[i], &cmd)) >= 0) {
1360
 
            mp_cmd_t *ret = mp_input_parse_cmd(cmd);
1361
 
            talloc_free(cmd);
1362
 
            if (ret)
1363
 
                return ret;
1364
 
        }
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;
1370
 
    }
1371
 
 
1372
 
    return NULL;
1373
 
}
1374
 
 
 
1398
        read_cmd_fd(ictx, &cmd_fds[i]);
 
1399
    }
 
1400
}
 
1401
 
 
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.
 
1405
 */
 
1406
static void read_all_events(struct input_ctx *ictx, int time)
 
1407
{
 
1408
    while (1) {
 
1409
        read_events(ictx, time);
 
1410
        if (!ictx->got_new_events)
 
1411
            return;
 
1412
        time = 0;
 
1413
    }
 
1414
}
1375
1415
 
1376
1416
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
1377
1417
{
1378
 
    if (!cmd || ictx->cmd_queue_length >= CMD_QUEUE_SIZE)
 
1418
    ictx->got_new_events = true;
 
1419
    if (!cmd)
1379
1420
        return 0;
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);
1383
1422
    return 1;
1384
1423
}
1385
1424
 
1386
 
static mp_cmd_t *get_queued_cmd(struct input_ctx *ictx, int peek_only)
1387
 
{
1388
 
    mp_cmd_t *ret;
1389
 
 
1390
 
    if (ictx->cmd_queue_length == 0)
1391
 
        return NULL;
1392
 
 
1393
 
    ret = ictx->cmd_queue[ictx->cmd_queue_start];
1394
 
 
1395
 
    if (!peek_only) {
1396
 
        ictx->cmd_queue_length--;
1397
 
        ictx->cmd_queue_start = (ictx->cmd_queue_start + 1) % CMD_QUEUE_SIZE;
1398
 
    }
1399
 
 
1400
 
    return ret;
1401
 
}
1402
 
 
1403
1425
/**
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!
1406
1428
 */
1407
1429
mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
1408
1430
{
1409
 
    mp_cmd_t *ret = NULL;
1410
 
    mp_cmd_filter_t *cf;
1411
 
    int from_queue;
1412
 
 
1413
1431
    if (async_quit_request)
1414
1432
        return mp_input_parse_cmd("quit 1");
1415
 
    while (1) {
1416
 
        from_queue = 1;
1417
 
        ret = get_queued_cmd(ictx, peek_only);
1418
 
        if (ret)
1419
 
            break;
1420
 
        from_queue = 0;
1421
 
        ret = read_events(ictx, time);
1422
 
        if (!ret) {
1423
 
            from_queue = 1;
1424
 
            ret = get_queued_cmd(ictx, peek_only);
1425
 
        }
1426
 
        break;
1427
 
    }
1428
 
    if (!ret)
1429
 
        return NULL;
1430
1433
 
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);
1436
 
            mp_cmd_free(ret);
 
1434
    if (ictx->control_cmd_queue.num_cmds || ictx->key_cmd_queue.num_cmds)
 
1435
        time = 0;
 
1436
    read_all_events(ictx, time);
 
1437
    struct mp_cmd *ret;
 
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);
 
1443
        if (!ret)
1437
1444
            return NULL;
1438
 
        }
1439
 
    }
 
1445
        queue_add(queue, ret, false);
 
1446
    } else
 
1447
        ret = queue->first;
1440
1448
 
1441
 
    if (!from_queue && peek_only)
1442
 
        mp_input_queue_cmd(ictx, ret);
 
1449
    if (!peek_only)
 
1450
        queue_pop(queue);
1443
1451
 
1444
1452
    return ret;
1445
1453
}
1446
1454
 
1447
 
void
1448
 
mp_cmd_free(mp_cmd_t *cmd) {
 
1455
void mp_cmd_free(mp_cmd_t *cmd)
 
1456
{
1449
1457
    talloc_free(cmd);
1450
1458
}
1451
1459
 
1452
 
mp_cmd_t *
1453
 
mp_cmd_clone(mp_cmd_t *cmd) {
 
1460
mp_cmd_t *mp_cmd_clone(mp_cmd_t *cmd)
 
1461
{
1454
1462
    mp_cmd_t *ret;
1455
1463
    int i;
1456
 
#ifdef MP_DEBUG
1457
 
    assert(cmd != NULL);
1458
 
#endif
1459
1464
 
1460
1465
    ret = talloc_memdup(NULL, cmd, sizeof(mp_cmd_t));
1461
1466
    ret->name = talloc_strdup(ret, cmd->name);
1471
1476
{
1472
1477
    int modifiers = 0;
1473
1478
    const char *p;
1474
 
    while (p = strchr(name, '+')) {
1475
 
        for (struct mp_key_name *m = modifier_names; m->name; m++)
1476
 
            if (!bstrcasecmp(BSTR(m->name), (struct bstr){(char *)name, p - name})) {
 
1479
    while ((p = strchr(name, '+'))) {
 
1480
        for (struct key_name *m = modifier_names; m->name; m++)
 
1481
            if (!bstrcasecmp(bstr(m->name),
 
1482
                             (struct bstr){(char *)name, p - name})) {
1477
1483
                modifiers |= m->key;
1478
1484
                goto found;
1479
1485
            }
1523
1529
    return 1;
1524
1530
}
1525
1531
 
1526
 
#define BS_MAX 256
1527
1532
#define SPACE_CHAR " \n\r\t"
1528
1533
 
1529
1534
static void bind_keys(struct input_ctx *ictx,
1530
1535
                      const int keys[MP_MAX_KEY_DOWN + 1], char *cmd)
1531
1536
{
1532
1537
    int i = 0, j;
1533
 
    mp_cmd_bind_t *bind = NULL;
1534
 
    mp_cmd_bind_section_t *bind_section = NULL;
 
1538
    struct cmd_bind *bind = NULL;
 
1539
    struct cmd_bind_section *bind_section = NULL;
1535
1540
    char *section = NULL, *p;
1536
1541
 
1537
 
#ifdef MP_DEBUG
1538
 
    assert(keys != NULL);
1539
 
    assert(cmd != NULL);
1540
 
#endif
1541
 
 
1542
1542
    if (*cmd == '{' && (p = strchr(cmd, '}'))) {
1543
1543
        *p = 0;
1544
1544
        section = ++cmd;
1562
1562
    if (!bind) {
1563
1563
        bind_section->cmd_binds = talloc_realloc(bind_section,
1564
1564
                                                 bind_section->cmd_binds,
1565
 
                                                 mp_cmd_bind_t, i + 2);
1566
 
        memset(&bind_section->cmd_binds[i], 0, 2 * sizeof(mp_cmd_bind_t));
 
1565
                                                 struct cmd_bind, i + 2);
 
1566
        memset(&bind_section->cmd_binds[i], 0, 2 * sizeof(struct cmd_bind));
1567
1567
        bind = &bind_section->cmd_binds[i];
1568
1568
    }
1569
1569
    talloc_free(bind->cmd);
1573
1573
 
1574
1574
static int parse_config(struct input_ctx *ictx, char *file)
1575
1575
{
1576
 
    int fd;
1577
 
    int bs = 0, r, eof = 0, comments = 0;
1578
 
    char *iter, *end;
1579
 
    char buffer[BS_MAX];
1580
 
    int n_binds = 0, keys[MP_MAX_KEY_DOWN + 1] = { 0 };
1581
 
 
1582
 
    fd = open(file, O_RDONLY);
 
1576
    int fd = open(file, O_RDONLY);
1583
1577
 
1584
1578
    if (fd < 0) {
1585
1579
        mp_msg(MSGT_INPUT, MSGL_V, "Can't open input config file %s: %s\n",
1589
1583
 
1590
1584
    mp_msg(MSGT_INPUT, MSGL_V, "Parsing input config file %s\n", file);
1591
1585
 
 
1586
 
 
1587
    unsigned char buffer[512];
 
1588
    struct bstr buf = { buffer, 0 };
 
1589
    bool eof = false, comments = false;
 
1590
    int n_binds = 0, keys[MP_MAX_KEY_DOWN + 1];
 
1591
 
1592
1592
    while (1) {
1593
 
        if (!eof && bs < BS_MAX - 1) {
1594
 
            if (bs > 0)
1595
 
                bs--;
1596
 
            r = read(fd, buffer + bs, BS_MAX - 1 - bs);
 
1593
        if (buf.start != buffer) {
 
1594
            memmove(buffer, buf.start, buf.len);
 
1595
            buf.start = buffer;
 
1596
        }
 
1597
        if (!eof && buf.len < sizeof(buffer)) {
 
1598
            int r = read(fd, buffer + buf.len, sizeof(buffer) - buf.len);
1597
1599
            if (r < 0) {
1598
1600
                if (errno == EINTR)
1599
1601
                    continue;
1602
1604
                close(fd);
1603
1605
                return 0;
1604
1606
            } else if (r == 0) {
1605
 
                eof = 1;
 
1607
                eof = true;
1606
1608
            } else {
1607
 
                bs += r + 1;
1608
 
                buffer[bs - 1] = '\0';
 
1609
                buf.len += r;
 
1610
                continue;
1609
1611
            }
1610
1612
        }
1611
 
        // Empty buffer : return
1612
 
        if (bs <= 1) {
 
1613
        if (buf.len == 0) {
1613
1614
            mp_msg(MSGT_INPUT, MSGL_V, "Input config file %s parsed: "
1614
1615
                   "%d binds\n", file, n_binds);
1615
1616
            close(fd);
1616
1617
            return 1;
1617
1618
        }
1618
 
 
1619
 
        iter = buffer;
1620
 
 
1621
1619
        if (comments) {
1622
 
            iter += strcspn(iter, "\n");
1623
 
            if (*iter == 0) { // Buffer was full of comment
1624
 
                bs = 0;
1625
 
                continue;
1626
 
            }
1627
 
            iter++;
1628
 
            r = strlen(iter);
1629
 
            memmove(buffer, iter, r + 1);
1630
 
            bs = r + 1;
1631
 
            comments = 0;
1632
 
            continue;
1633
 
        }
1634
 
 
1635
 
        // Find the wanted key
1636
 
        if (keys[0] == 0) {
1637
 
            // Jump beginning space
1638
 
            iter += strspn(iter, SPACE_CHAR);
1639
 
            if (*iter == 0) { // Buffer was full of space char
1640
 
                bs = 0;
1641
 
                continue;
1642
 
            }
1643
 
            if (iter[0] == '#') { // Comments
1644
 
                comments = 1;
1645
 
                continue;
1646
 
            }
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);
1654
 
                    else
1655
 
                        mp_tmsg(MSGT_INPUT, MSGL_ERR, "Buffer is too small "
1656
 
                                "for this key name: %s\n", iter);
1657
 
                    return 0;
1658
 
                }
1659
 
                memmove(buffer, iter, end - iter);
1660
 
                bs = end - iter;
1661
 
                continue;
1662
 
            }
1663
 
            {
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);
1669
 
                    close(fd);
1670
 
                    return 0;
1671
 
                }
1672
 
            }
1673
 
            if (bs > (end - buffer))
1674
 
                memmove(buffer, end, bs - (end - buffer));
1675
 
            bs -= end - buffer;
1676
 
            continue;
1677
 
        } else { // Get the command
1678
 
            while (iter[0] == ' ' || iter[0] == '\t')
1679
 
                iter++;
1680
 
            // Found new line
1681
 
            if (iter[0] == '\n' || iter[0] == '\r') {
1682
 
                int i;
1683
 
                char *key_buf  = get_key_name(keys[0]);
1684
 
                mp_tmsg(MSGT_INPUT, MSGL_ERR, "No command found for key %s",
1685
 
                        key_buf);
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);
1691
 
                }
1692
 
                mp_msg(MSGT_INPUT, MSGL_ERR, "\n");
1693
 
                keys[0] = 0;
1694
 
                if (iter > buffer) {
1695
 
                    memmove(buffer, iter, bs - (iter - buffer));
1696
 
                    bs -= (iter - buffer);
1697
 
                }
1698
 
                continue;
1699
 
            }
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);
1705
 
                    close(fd);
1706
 
                    return 0;
1707
 
                }
1708
 
                memmove(buffer, iter, end - iter);
1709
 
                bs = end - iter;
1710
 
                continue;
1711
 
            }
1712
 
            {
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);
1718
 
                n_binds++;
1719
 
            }
1720
 
            keys[0] = 0;
1721
 
            end++;
1722
 
            if (bs > (end - buffer))
1723
 
                memmove(buffer, end, bs - (end - buffer));
1724
 
            bs -= (end - buffer);
1725
 
            buffer[bs - 1] = '\0';
1726
 
            continue;
1727
 
        }
 
1620
            int idx = bstrchr(buf, '\n');
 
1621
            if (idx >= 0) {
 
1622
                buf = bstr_cut(buf, idx + 1);
 
1623
                comments = false;
 
1624
            } else
 
1625
                buf = bstr_cut(buf, buf.len);
 
1626
            continue;
 
1627
        }
 
1628
        buf = bstr_lstrip(buf);
 
1629
        if (buf.start != buffer)
 
1630
            continue;
 
1631
        if (buf.start[0] == '#') {
 
1632
            comments = true;
 
1633
            continue;
 
1634
        }
 
1635
        int eol = bstrchr(buf, '\n');
 
1636
        if (eol < 0) {
 
1637
            if (eof) {
 
1638
                eol = buf.len;
 
1639
            } else {
 
1640
                mp_tmsg(MSGT_INPUT, MSGL_ERR,
 
1641
                        "Key binding is too long: %.*s\n", BSTR_P(buf));
 
1642
                comments = true;
 
1643
                continue;
 
1644
            }
 
1645
        }
 
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));
 
1655
            continue;
 
1656
        }
 
1657
        char *name = bstrdup0(NULL, keyname);
 
1658
        if (!get_input_from_name(name, keys)) {
 
1659
            talloc_free(name);
 
1660
            mp_tmsg(MSGT_INPUT, MSGL_ERR,
 
1661
                    "Unknown key '%.*s'\n", BSTR_P(keyname));
 
1662
            continue;
 
1663
        }
 
1664
        talloc_free(name);
 
1665
        char *cmd = bstrdup0(NULL, command);
 
1666
        bind_keys(ictx, keys, cmd);
 
1667
        n_binds++;
 
1668
        talloc_free(cmd);
1728
1669
    }
1729
 
    mp_tmsg(MSGT_INPUT, MSGL_ERR, "What are we doing here?\n");
1730
 
    close(fd);
1731
 
    mp_input_set_section(ictx, NULL);
1732
 
    return 0;
1733
1670
}
1734
1671
 
1735
1672
void mp_input_set_section(struct input_ctx *ictx, char *name)
1736
1673
{
1737
 
    mp_cmd_bind_section_t *bind_section = NULL;
 
1674
    struct cmd_bind_section *bind_section = NULL;
1738
1675
 
1739
1676
    ictx->cmd_binds = NULL;
1740
1677
    ictx->cmd_binds_default = NULL;
1760
1697
{
1761
1698
    struct input_ctx *ictx = talloc_ptrtype(NULL, ictx);
1762
1699
    *ictx = (struct input_ctx){
 
1700
        .key_fifo_size = input_conf->key_fifo_size,
1763
1701
        .ar_state = -1,
1764
1702
        .ar_delay = input_conf->ar_delay,
1765
1703
        .ar_rate = input_conf->ar_rate,
1795
1733
            mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't init input joystick\n");
1796
1734
        else
1797
1735
            mp_input_add_key_fd(ictx, fd, 1, mp_input_joystick_read,
1798
 
                                (mp_close_func_t)close, NULL);
 
1736
                                close, NULL);
1799
1737
    }
1800
1738
#endif
1801
1739
 
1812
1750
    if (input_conf->use_lircc) {
1813
1751
        int fd = lircc_init("mplayer", NULL);
1814
1752
        if (fd >= 0)
1815
 
            mp_input_add_cmd_fd(ictx, fd, 1, NULL,
1816
 
                                (mp_close_func_t)lircc_cleanup);
 
1753
            mp_input_add_cmd_fd(ictx, fd, 1, NULL, lircc_cleanup);
1817
1754
    }
1818
1755
#endif
1819
1756
 
1834
1771
            mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't init Apple Remote.\n");
1835
1772
        else
1836
1773
            mp_input_add_key_fd(ictx, fd, 1, mp_input_appleir_read,
1837
 
                                (mp_close_func_t)close, NULL);
 
1774
                                close, NULL);
1838
1775
    }
1839
1776
#endif
1840
1777
 
1848
1785
            mode = O_RDWR | O_NONBLOCK;
1849
1786
        int in_file_fd = open(input_conf->in_file, mode);
1850
1787
        if (in_file_fd >= 0)
1851
 
            mp_input_add_cmd_fd(ictx, in_file_fd, 1, NULL,
1852
 
                                (mp_close_func_t)close);
 
1788
            mp_input_add_cmd_fd(ictx, in_file_fd, 1, NULL, close);
1853
1789
        else
1854
1790
            mp_tmsg(MSGT_INPUT, MSGL_ERR, "Can't open %s: %s\n",
1855
1791
                    input_conf->in_file, strerror(errno));
1927
1863
 */
1928
1864
int mp_input_check_interrupt(struct input_ctx *ictx, int time)
1929
1865
{
1930
 
    mp_cmd_t *cmd;
1931
 
    if ((cmd = mp_input_get_cmd(ictx, time, 1)) == NULL)
1932
 
        return 0;
1933
 
    switch (cmd->id) {
1934
 
    case MP_CMD_QUIT:
1935
 
    case MP_CMD_PLAY_TREE_STEP:
1936
 
    case MP_CMD_PLAY_TREE_UP_STEP:
1937
 
    case MP_CMD_PLAY_ALT_SRC_STEP:
1938
 
        // The cmd will be executed when we are back in the main loop
1939
 
        return 1;
 
1866
    for (int i = 0; ; i++) {
 
1867
        if (async_quit_request || ictx->key_cmd_queue.num_abort_cmds ||
 
1868
                ictx->control_cmd_queue.num_abort_cmds) {
 
1869
            mp_tmsg(MSGT_INPUT, MSGL_WARN, "Received command to move to "
 
1870
                   "another file. Aborting current processing.\n");
 
1871
            return true;
 
1872
        }
 
1873
        if (i)
 
1874
            return false;
 
1875
        read_all_events(ictx, time);
1940
1876
    }
1941
 
    // remove the cmd from the queue
1942
 
    cmd = mp_input_get_cmd(ictx, time, 0);
1943
 
    mp_cmd_free(cmd);
1944
 
    return 0;
1945
1877
}