summaryrefslogtreecommitdiffstats
path: root/osdep/terminal-win.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-21 22:15:32 +0200
committerwm4 <wm4@nowhere>2014-08-21 22:45:58 +0200
commit58a9610acfc264cd93def625157774a8dc0e79ed (patch)
tree604ef9999e2dd378038775457b4dcae09d60a63e /osdep/terminal-win.c
parent5890e59dbc90e6ed1ae9ccec173006655895918e (diff)
downloadmpv-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.c76
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)