0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

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.
This commit is contained in:
Rudolf Polzer 2013-01-23 15:47:49 +01:00
parent d275e21d6a
commit 3b22404e07
5 changed files with 124 additions and 17 deletions

View File

@ -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

View File

@ -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 */
@ -78,6 +82,13 @@ void mp_msg_init(void){
SetConsoleMode(hSTDERR, cmode);
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");
@ -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]);
}

View File

@ -166,6 +166,9 @@ bool getch2(struct mp_fifo *fifo)
return true;
}
void getch2_poll(void){
}
void getch2_enable(void)
{
DWORD retval;

View File

@ -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;
}

View File

@ -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);