summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/input/input.c2
-rw-r--r--core/mp_msg.c18
-rw-r--r--osdep/getch2-win.c3
-rw-r--r--osdep/getch2.c113
-rw-r--r--osdep/getch2.h5
5 files changed, 124 insertions, 17 deletions
diff --git a/core/input/input.c b/core/input/input.c
index 1eedadf039..8b473dda43 100644
--- a/core/input/input.c
+++ b/core/input/input.c
@@ -32,6 +32,7 @@
#include <assert.h>
#include "osdep/io.h"
+#include "osdep/getch2.h"
#include "input.h"
#include "core/mp_fifo.h"
@@ -1503,6 +1504,7 @@ static void read_all_fd_events(struct input_ctx *ictx, int time)
static void read_all_events(struct input_ctx *ictx, int time)
{
+ getch2_poll();
#ifdef CONFIG_COCOA
cocoa_events_read_all_events(ictx, time);
#else
diff --git a/core/mp_msg.c b/core/mp_msg.c
index 2e6f148438..85cbe9c1fa 100644
--- a/core/mp_msg.c
+++ b/core/mp_msg.c
@@ -31,6 +31,10 @@
#include <libintl.h>
#endif
+#ifndef __MINGW32__
+#include <signal.h>
+#endif
+
#include "core/mp_msg.h"
/* maximum message length of mp_msg */
@@ -79,6 +83,13 @@ void mp_msg_init(void){
GetConsoleScreenBufferInfo(hSTDOUT, &cinfo);
stdoutAttrs = cinfo.wAttributes;
#endif
+#ifndef __MINGW32__
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGTTOU, &sa, NULL); // just write to stdout if you have to
+#endif
int i;
char *env = getenv("MPV_VERBOSE");
if (env)
@@ -98,6 +109,13 @@ void mp_msg_init(void){
int mp_msg_test(int mod, int lev)
{
+#ifndef __MINGW32__
+ if (lev == MSGL_STATUS) {
+ // skip status line output if we are not in the foreground process group
+ if (tcgetpgrp(0) != getpgrp())
+ return false;
+ }
+#endif
return lev <= (mp_msg_levels[mod] == -2 ? mp_msg_level_all + verbose : mp_msg_levels[mod]);
}
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);