diff options
author | wm4 <wm4@nowhere> | 2014-08-21 22:15:32 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-08-21 22:45:58 +0200 |
commit | 58a9610acfc264cd93def625157774a8dc0e79ed (patch) | |
tree | 604ef9999e2dd378038775457b4dcae09d60a63e /osdep/terminal-win.c | |
parent | 5890e59dbc90e6ed1ae9ccec173006655895918e (diff) | |
download | mpv-58a9610acfc264cd93def625157774a8dc0e79ed.tar.bz2 mpv-58a9610acfc264cd93def625157774a8dc0e79ed.tar.xz |
terminal-win: read input from a thread
Surprisingly, WaitFor* works on console handles. We can simply run the
code for reading the console in a thread, and don't have to worry about
crazy win32 crap in the rest of the player's input code anymore.
This also fixes the issue that you couldn't unpause the player from the
terminal, because the player would stop polling for input.
Diffstat (limited to 'osdep/terminal-win.c')
-rw-r--r-- | osdep/terminal-win.c | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/osdep/terminal-win.c b/osdep/terminal-win.c index af8b3aa47b..22751b31f8 100644 --- a/osdep/terminal-win.c +++ b/osdep/terminal-win.c @@ -30,6 +30,8 @@ #include <string.h> #include <windows.h> #include <io.h> +#include <pthread.h> +#include <assert.h> #include "common/common.h" #include "input/keycodes.h" #include "input/input.h" @@ -51,6 +53,11 @@ static const unsigned char ansi2win32[8] = { FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED, }; +static bool running; +static HANDLE death; +static pthread_t input_thread; +static struct input_ctx *input_ctx; + void terminal_get_size(int *w, int *h) { CONSOLE_SCREEN_BUFFER_INFO cinfo; @@ -60,23 +67,21 @@ void terminal_get_size(int *w, int *h) } } -static int getch2_status = 0; - -static int getch2_internal(void) +static void read_input(void) { DWORD retval; HANDLE in = GetStdHandle(STD_INPUT_HANDLE); /*check if there are input events*/ if (!GetNumberOfConsoleInputEvents(in, &retval)) - return -1; + return; if (retval <= 0) - return -1; + return; /*read all events*/ INPUT_RECORD eventbuffer[128]; if (!ReadConsoleInput(in, eventbuffer, MP_ARRAY_SIZE(eventbuffer), &retval)) - return -1; + return; /*filter out keyevents*/ for (int i = 0; i < retval; i++) { @@ -90,11 +95,14 @@ static int getch2_internal(void) bool ext = record->dwControlKeyState & ENHANCED_KEY; int mpkey = mp_w32_vkey_to_mpkey(vkey, ext); - if (mpkey) - return mpkey; - - /*only characters should be remaining*/ - return eventbuffer[i].Event.KeyEvent.uChar.UnicodeChar; + if (mpkey) { + mp_input_put_key(input_ctx, mpkey); + } else { + /*only characters should be remaining*/ + int c = eventbuffer[i].Event.KeyEvent.uChar.UnicodeChar; + if (c > 0) + mp_input_put_key(input_ctx, c); + } } break; } @@ -106,29 +114,38 @@ static int getch2_internal(void) break; } } - return -1; -} - -static bool getch2(struct input_ctx *ctx) -{ - int r = getch2_internal(); - if (r >= 0) - mp_input_put_key(ctx, r); - return true; + return; } -static int read_keys(void *ctx, int fd) +static void *input_thread_fn(void *ptr) { - if (getch2(ctx)) - return MP_INPUT_NOTHING; - return MP_INPUT_DEAD; + HANDLE in = GetStdHandle(STD_INPUT_HANDLE); + HANDLE stuff[2] = {in, death}; + while (1) { + DWORD r = WaitForMultipleObjects(2, stuff, FALSE, INFINITE); + if (r != WAIT_OBJECT_0) + break; + read_input(); + } + return NULL; } void terminal_setup_getch(struct input_ctx *ictx) { - mp_input_add_fd(ictx, 0, 1, NULL, read_keys, NULL, ictx); + assert(!running); + HANDLE in = GetStdHandle(STD_INPUT_HANDLE); - getch2_status = !!GetNumberOfConsoleInputEvents(in, &(DWORD){0}); + if (GetNumberOfConsoleInputEvents(in, &(DWORD){0})) { + input_ctx = ictx; + death = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!death) + return; + if (pthread_create(&input_thread, NULL, input_thread_fn, NULL)) { + CloseHandle(death); + return; + } + running = true; + } } void getch2_poll(void) @@ -137,7 +154,12 @@ void getch2_poll(void) void terminal_uninit(void) { - getch2_status = 0; + if (running) { + SetEvent(death); + pthread_join(input_thread, NULL); + input_ctx = NULL; + running = false; + } } bool terminal_in_background(void) |