From 3b22404e07df265af221112e2970084a15766c9a Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 23 Jan 2013 15:47:49 +0100 Subject: mp_msg, getch2: unix tty background support Now, when backgrounded, mpv plays and outputs messages to stdout, but statusline is not output. Background<->foreground transitions are detected by signals and polling the process groups. --- osdep/getch2-win.c | 3 ++ osdep/getch2.c | 113 +++++++++++++++++++++++++++++++++++++++++++++-------- osdep/getch2.h | 5 ++- 3 files changed, 104 insertions(+), 17 deletions(-) (limited to 'osdep') diff --git a/osdep/getch2-win.c b/osdep/getch2-win.c index c7607cee47..4bef70b418 100644 --- a/osdep/getch2-win.c +++ b/osdep/getch2-win.c @@ -166,6 +166,9 @@ bool getch2(struct mp_fifo *fifo) return true; } +void getch2_poll(void){ +} + void getch2_enable(void) { DWORD retval; diff --git a/osdep/getch2.c b/osdep/getch2.c index c722922f88..63aaa75bf1 100644 --- a/osdep/getch2.c +++ b/osdep/getch2.c @@ -55,11 +55,13 @@ #include "core/bstr.h" #include "core/mp_fifo.h" +#include "core/input/input.h" #include "core/input/keycodes.h" #include "getch2.h" #ifdef HAVE_TERMIOS -static struct termios tio_orig; +static volatile struct termios tio_orig; +static volatile int tio_orig_set; #endif static int getch2_len=0; static unsigned char getch2_buf[BUF_LEN]; @@ -284,39 +286,118 @@ bool getch2(struct mp_fifo *fifo) return true; } -static volatile int getch2_status=0; +static volatile int getch2_active=0; +static volatile int getch2_enabled=0; -static void do_enable_getch2(void) +static void do_activate_getch2(void) { + if (getch2_active) + return; #ifdef HAVE_TERMIOS struct termios tio_new; tcgetattr(0,&tio_new); + if (!tio_orig_set) { + tio_orig = tio_new; + tio_orig_set = 1; + } tio_new.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ tio_new.c_cc[VMIN] = 1; tio_new.c_cc[VTIME] = 0; tcsetattr(0,TCSANOW,&tio_new); #endif + getch2_active=1; +} + +static void do_deactivate_getch2(void) +{ + if (!getch2_active) + return; +#ifdef HAVE_TERMIOS + if (tio_orig_set) { + // once set, it will never be set again + // so we can cast away volatile here + tcsetattr(0, TCSANOW, (const struct termios *) &tio_orig); + } +#endif + getch2_active=0; +} + +// sigaction wrapper +static int setsigaction(int signo, void (*handler) (int), + int flags, bool do_mask) +{ + struct sigaction sa; + sa.sa_handler = handler; + if(do_mask) + sigfillset(&sa.sa_mask); + else + sigemptyset(&sa.sa_mask); + sa.sa_flags = flags; + return sigaction(signo, &sa, NULL); +} + +void getch2_poll(void){ + if (!getch2_enabled) + return; + + // check if we are in the foreground process group + int newstatus = (tcgetpgrp(0) == getpgrp()); + + // and activate getch2 if we are, deactivate otherwise + if (newstatus) + do_activate_getch2(); + else + do_deactivate_getch2(); +} + +static void stop_sighandler(int signum) +{ + do_deactivate_getch2(); + + // note: for this signal, we use SA_RESETHAND but do NOT mask signals + // so this will invoke the default handler + raise(SIGTSTP); } static void continue_sighandler(int signum) { - if (getch2_status) - do_enable_getch2(); + // SA_RESETHAND has reset SIGTSTP, so we need to restore it here + setsigaction(SIGTSTP, stop_sighandler, SA_RESETHAND, false); + + getch2_poll(); +} + +static void quit_request_sighandler(int signum) +{ + async_quit_request = 1; } void getch2_enable(void){ -#ifdef HAVE_TERMIOS - tcgetattr(0,&tio_orig); - do_enable_getch2(); -#endif - getch2_status=1; - signal(SIGCONT,continue_sighandler); + if (getch2_enabled) + return; + + // handlers to fix terminal settings + setsigaction(SIGCONT, continue_sighandler, 0, true); + setsigaction(SIGTSTP, stop_sighandler, SA_RESETHAND, false); + setsigaction(SIGINT, quit_request_sighandler, SA_RESETHAND, false); + setsigaction(SIGTTIN, SIG_IGN, 0, true); + + do_activate_getch2(); + + getch2_enabled = 1; } void getch2_disable(void){ - if(!getch2_status) return; // already disabled / never enabled - getch2_status=0; -#ifdef HAVE_TERMIOS - tcsetattr(0,TCSANOW,&tio_orig); -#endif + if (!getch2_enabled) + return; + + // restore signals + setsigaction(SIGCONT, SIG_DFL, 0, false); + setsigaction(SIGTSTP, SIG_DFL, 0, false); + setsigaction(SIGINT, SIG_DFL, 0, false); + setsigaction(SIGTTIN, SIG_DFL, 0, false); + + do_deactivate_getch2(); + + getch2_enabled = 0; } diff --git a/osdep/getch2.h b/osdep/getch2.h index 85899b3ce3..5a04c4228e 100644 --- a/osdep/getch2.h +++ b/osdep/getch2.h @@ -41,10 +41,13 @@ void get_screen_size(void); /* Load key definitions from the TERMCAP database. 'termtype' can be NULL */ int load_termcap(char *termtype); -/* Enable and disable STDIN line-buffering */ +/* Initialize getch2 */ void getch2_enable(void); 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 mp_fifo; bool getch2(struct mp_fifo *fifo); -- cgit v1.2.3