1
0
mirror of http://mpg123.de/trunk/.git synced 2025-08-06 10:02:38 +03:00

term: the new switchery to later enable term_type=win32

git-svn-id: svn://scm.orgis.org/mpg123/trunk@5082 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
thor
2022-05-14 13:26:37 +00:00
parent dda6ab2132
commit 8c1ee49d76
9 changed files with 268 additions and 195 deletions

View File

@@ -1209,11 +1209,13 @@ if test "x$have_mmap" = "xno"; then
AC_CHECK_FUNCS([shmget shmat shmdt shmctl],[], [buffer=disabled])
fi
term_type=none
# Check if system supports termios
AC_SYS_POSIX_TERMIOS
if test "x$ac_cv_sys_posix_termios" = "xyes"; then
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
[Define this if you have the POSIX termios library])
term_type=posix
fi
AC_CHECK_FUNCS( random )
@@ -2659,6 +2661,12 @@ AM_CONDITIONAL([NET123_EXEC], [ test x$network_type = xexec ])
AM_CONDITIONAL([NET123_WINHTTP], [ test x$network_type = xwinhttp ])
AM_CONDITIONAL([NET123_WININET], [ test x$network_type = xwininet ])
dnl ############## Terminal choice
AM_CONDITIONAL( [TERM_POSIX], [test "x$term_type" = xposix] )
AM_CONDITIONAL( [TERM_NONE], [test "x$term_type" = xnone] )
AM_CONDITIONAL( [TERM_WIN32], [test "x$term_type" = xwin32] )
dnl ############## FIFO enable
if test x"$fifo" = xauto; then
@@ -2718,6 +2726,11 @@ AC_CONFIG_FILES([
src/libsyn123/syn123.h
])
AM_CONDITIONAL( [TERM_POSIX], [test "x$term_type" = xposix] )
AM_CONDITIONAL( [TERM_NONE], [test "x$term_type" = xnone] )
AC_OUTPUT
@@ -2732,6 +2745,7 @@ echo "
Compiler Optimization ... $with_optimization
Gapless Support ......... $gapless
Debugging ............... $debugging
Terminal control ........ $term_type
Extreme debugging ....... $xdebugging
Seek table size ......... $seektable
FIFO support ............ $fifo

View File

@@ -75,6 +75,7 @@ src_mpg123_SOURCES = \
src/streamdump.c \
src/term.c \
src/term.h \
src/terms.h \
src/win32_support.h
# Does that finally work to build/link the correct object file?
@@ -105,6 +106,18 @@ src_mpg123_strip_SOURCES = \
src/getlopt.c \
src/getlopt.h
if TERM_POSIX
src_mpg123_SOURCES += src/term_posix.c
endif
if TERM_WIN32
src_mpg123_SOURCES += src/term_win32.c
endif
if TERM_NONE
src_mpg123_SOURCES += src/term_none.c
endif
if NET123_EXEC
src_mpg123_SOURCES += src/net123.h src/net123_exec.c
endif

View File

@@ -15,6 +15,7 @@
#include "out123.h"
#include <sys/stat.h>
#include "common.h"
#include "terms.h"
#include "debug.h"

View File

@@ -112,66 +112,6 @@ static int is_utf8(const char *lang)
return 0;
}
int term_have_fun(int fd, int want_visuals)
{
if(term_is_fun > -1)
return term_is_fun;
else
term_is_fun = 0;
#ifdef HAVE_TERMIOS
if(term_width(fd) > 0 && want_visuals)
{
/* Only play with non-dumb terminals. */
char *tname = compat_getenv("TERM");
if(tname)
{
if(strcmp(tname, "") && strcmp(tname, "dumb"))
term_is_fun = 1;
free(tname);
}
}
#endif
return term_is_fun;
}
/* Also serves as a way to detect if we have an interactive terminal. */
int term_width(int fd)
{
#ifdef HAVE_TERMIOS
/* POSIX */
struct winsize geometry;
geometry.ws_col = 0;
if(ioctl(fd, TIOCGWINSZ, &geometry) >= 0)
return (int)geometry.ws_col;
#elif defined(WIN32)
CONSOLE_SCREEN_BUFFER_INFO pinfo;
HANDLE hStdout;
DWORD handle;
switch(fd){
case STDIN_FILENO:
handle = STD_INPUT_HANDLE;
break;
case STDOUT_FILENO:
handle = STD_OUTPUT_HANDLE;
break;
case STDERR_FILENO:
handle = STD_ERROR_HANDLE;
break;
default:
return -1;
}
hStdout = GetStdHandle(handle);
if(hStdout == INVALID_HANDLE_VALUE || hStdout == NULL)
return -1;
if(GetConsoleScreenBufferInfo(hStdout, &pinfo)){
return pinfo.dwMaximumWindowSize.X;
}
#endif
return -1;
}
// Moved encoding stuff over from metaprint.c and removed references to libmpg123,
// meaning no mpg123_string for you!

View File

@@ -36,6 +36,7 @@
#include "sysutil.h"
#include "getlopt.h"
#include "term.h"
#include "terms.h"
#include "playlist.h"
#include "metaprint.h"
#include "httpget.h"

View File

@@ -88,9 +88,6 @@ enum runmodes
static int runmode = RUN_MAIN;
int stdout_is_term = FALSE; // It's an interactive terminal.
int stderr_is_term = FALSE; // It's an interactive terminal.
static FILE* input = NULL;
static char *encoding_name = NULL;
static int encoding = MPG123_ENC_SIGNED_16;
@@ -1511,8 +1508,6 @@ int main(int sys_argc, char ** sys_argv)
_wildcard(&argc,&argv);
#endif
stderr_is_term = term_width(STDERR_FILENO) >= 0;
stdout_is_term = term_width(STDOUT_FILENO) >= 0;
while ((result = getlopt(argc, argv, opts)))
switch (result) {
case GLO_UNKNOWN:

View File

@@ -8,30 +8,21 @@
#include "mpg123app.h"
#ifdef HAVE_TERMIOS
#include <termios.h>
#include <ctype.h>
#include "term.h"
#include "terms.h"
#include "common.h"
#include "playlist.h"
#include "metaprint.h"
#include "debug.h"
static int term_enable = 0;
// This now always refers to a freshly opened terminal descriptor (e.g. /dev/tty).
// Printouts to stderr are independent of this.
static int term_fd = -1;
static struct termios old_tio;
int seeking = FALSE;
extern out123_handle *ao;
/* Buffered key from a signal or whatnot.
We ignore the null character... */
static char prekey = 0;
/* Hm, next step would be some system in this, plus configurability...
Two keys for everything? It's just stop/pause for now... */
struct keydef { const char key; const char key2; const char* desc; };
@@ -74,51 +65,6 @@ struct keydef term_help[] =
,{ MPG123_TREBLE_DOWN_KEY, 0, "less treble" }
};
void term_sigcont(int sig);
static void term_sigusr(int sig);
/* This must call only functions safe inside a signal handler. */
int term_setup(struct termios *pattern)
{
mdebug("setup on fd %d", term_fd);
/* One might want to use sigaction instead. */
signal(SIGCONT, term_sigcont);
signal(SIGUSR1, term_sigusr);
signal(SIGUSR2, term_sigusr);
#ifndef __OS2__
struct termios tio = *pattern;
tio.c_lflag &= ~(ICANON|ECHO);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
return tcsetattr(term_fd,TCSANOW,&tio);
#else
return 0;
#endif
}
void term_sigcont(int sig)
{
term_enable = 0;
if (term_setup(&old_tio) < 0)
{
fprintf(stderr,"Can't set terminal attributes\n");
return;
}
term_enable = 1;
}
static void term_sigusr(int sig)
{
switch(sig)
{
case SIGUSR1: prekey=*param.term_usr1; break;
case SIGUSR2: prekey=*param.term_usr2; break;
}
}
/* initialze terminal */
void term_init(void)
{
@@ -133,41 +79,15 @@ void term_init(void)
return;
term_enable = 0;
const char *term_name;
#ifdef HAVE_CTERMID
term_name = ctermid(NULL);
#else
term_name = "/dev/tty";
#endif
if(term_name)
mdebug("accessing terminal for control via %s", term_name);
errno = 0;
if(term_setup() < 0)
{
if(errno)
merror("failed to set up terminal: %s", strerror(errno));
else
{
error("no controlling terminal");
error("failed to set up terminal");
return;
}
term_fd = open(term_name, O_RDONLY);
if(term_fd < 0)
{
merror("failed to open terminal: %s", strerror(errno));
return;
}
// Testing if OS2 works without the attr fun, at all.
#ifndef __OS2__
if(tcgetattr(term_fd, &old_tio) < 0)
{
merror("failed to get terminal attributes: %s", strerror(errno));
return;
}
if(term_setup(&old_tio) < 0)
{
close(term_fd);
error("failure setting terminal attributes");
return;
}
#endif
term_enable = 1;
}
@@ -286,37 +206,6 @@ static void seekmode(mpg123_handle *mh, out123_handle *ao)
}
}
/* Get the next pressed key, if any.
Returns 1 when there is a key, 0 if not. */
static int get_key(int do_delay, char *val)
{
fd_set r;
struct timeval t;
/* Shortcut: If some other means sent a key, use it. */
if(prekey)
{
debug1("Got prekey: %c\n", prekey);
*val = prekey;
prekey = 0;
return 1;
}
t.tv_sec=0;
t.tv_usec=(do_delay) ? 10*1000 : 0;
FD_ZERO(&r);
FD_SET(term_fd,&r);
if(select(term_fd+1,&r,NULL,NULL,&t) > 0 && FD_ISSET(term_fd,&r))
{
if(read(term_fd,val,1) <= 0)
return 0; /* Well, we couldn't read the key, so there is none. */
else
return 1;
}
else return 0;
}
static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
{
debug1("term_handle_key: %c", val);
@@ -622,7 +511,7 @@ static void term_handle_input(mpg123_handle *fr, out123_handle *ao, int do_delay
{
char val;
/* Do we really want that while loop? This means possibly handling multiple inputs that come very rapidly in one go. */
while(get_key(do_delay, &val))
while(term_get_key(do_delay, &val))
{
term_handle_key(fr, ao, val);
}
@@ -638,15 +527,5 @@ void term_exit(void)
if(!term_enable) return;
#ifndef __OS2__
debug("reset attrbutes");
tcsetattr(term_fd,TCSAFLUSH,&old_tio);
#endif
if(term_fd > -1)
close(term_fd);
term_fd = -1;
term_restore();
}
#endif

31
src/term_none.c Normal file
View File

@@ -0,0 +1,31 @@
/*
term_none: no-op terminal, nothing at all
copyright 2008-2022 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Thomas Orgis and Jonathan Yong
*/
int term_have_fun(int fd, int want_visuals)
{
return 0;
}
int term_width(int fd)
{
return -1;
}
int term_setup(void)
{
return -1;
}
void term_restore(void)
{
}
int term_get_key(int do_delay, char *val)
{
return 0;
}

199
src/term_posix.c Normal file
View File

@@ -0,0 +1,199 @@
/*
term_posix: POSIX-specifc terminal functionality
HAVE_TERMIOS is a prerequisite.
copyright 2008-2022 by the mpg123 project - free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Thomas Orgis
*/
#include "config.h"
#include "compat.h"
#ifndef HAVE_TERMIOS
#error "No TERMIOS? Here?"
#endif
// for param struct
#include "mpg123app.h"
#include <termios.h>
#include <sys/ioctl.h>
#include "terms.h"
#include "debug.h"
static int term_is_fun = -1;
// This now always refers to a ;freshly opened terminal descriptor (e.g. /dev/tty).
// Printouts to stderr are independent of this.
static int term_fd = -1;
static struct termios old_tio;
/* Buffered key from a signal or whatnot.
We ignore the null character... */
static char prekey = 0;
int term_have_fun(int fd, int want_visuals)
{
if(term_is_fun > -1)
return term_is_fun;
else
term_is_fun = 0;
if(term_width(fd) > 0 && want_visuals)
{
/* Only play with non-dumb terminals. */
char *tname = compat_getenv("TERM");
if(tname)
{
if(strcmp(tname, "") && strcmp(tname, "dumb"))
term_is_fun = 1;
free(tname);
}
}
return term_is_fun;
}
/* Also serves as a way to detect if we have an interactive terminal. */
int term_width(int fd)
{
struct winsize geometry;
geometry.ws_col = 0;
if(ioctl(fd, TIOCGWINSZ, &geometry) >= 0)
return (int)geometry.ws_col;
return -1;
}
static int term_setup_detail(struct termios *pattern);
static void term_sigcont(int sig)
{
if(term_setup_detail(&old_tio) < 0)
{
debug("Can't set terminal attributes");
return;
}
}
static void term_sigusr(int sig)
{
switch(sig)
{
case SIGUSR1: prekey=*param.term_usr1; break;
case SIGUSR2: prekey=*param.term_usr2; break;
}
}
/* This must call only functions safe inside a signal handler. */
static int term_setup_detail(struct termios *pattern)
{
mdebug("setup on fd %d", term_fd);
/* One might want to use sigaction instead. */
signal(SIGCONT, term_sigcont);
signal(SIGUSR1, term_sigusr);
signal(SIGUSR2, term_sigusr);
struct termios tio = *pattern;
tio.c_lflag &= ~(ICANON|ECHO);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
#ifdef __OS2__
// Do not care for the error until OS/2 is known to work.
tcsetattr(term_fd,TCSANOW,&tio);
return 0;
#else
return tcsetattr(term_fd,TCSANOW,&tio);
#endif
}
int term_setup(void)
{
if(term_fd < 0)
{
const char *term_name;
#ifdef HAVE_CTERMID
term_name = ctermid(NULL);
#else
term_name = "/dev/tty";
#endif
if(term_name)
mdebug("accessing terminal for control via %s", term_name);
else
{
error("no controlling terminal");
return -1;
}
term_fd = open(term_name, O_RDONLY);
if(term_fd < 0)
{
merror("failed to open terminal: %s", strerror(errno));
return -1;
}
}
if(tcgetattr(term_fd, &old_tio) < 0)
{
// For now, this always fails on OS/2, but they might fix things.
// So just try to move on.
#ifndef __OS2__
merror("failed to get terminal attributes: %s", strerror(errno));
return -1;
#endif
}
errno = 0;
if(term_setup_detail(&old_tio) < 0)
{
close(term_fd);
term_fd = -1;
if(errno)
merror("failure setting terminal attributes: %s", strerror(errno));
else
error("failure setting terminal attributes");
return -1;
}
return 0;
}
/* Get the next pressed key, if any.
Returns 1 when there is a key, 0 if not. */
int term_get_key(int do_delay, char *val)
{
fd_set r;
struct timeval t;
/* Shortcut: If some other means sent a key, use it. */
if(prekey)
{
debug1("Got prekey: %c\n", prekey);
*val = prekey;
prekey = 0;
return 1;
}
t.tv_sec=0;
t.tv_usec=(do_delay) ? 10*1000 : 0;
FD_ZERO(&r);
FD_SET(term_fd,&r);
if(select(term_fd+1,&r,NULL,NULL,&t) > 0 && FD_ISSET(term_fd,&r))
{
if(read(term_fd,val,1) <= 0)
return 0; /* Well, we couldn't read the key, so there is none. */
else
return 1;
}
else return 0;
}
void term_restore(void)
{
debug("reset attrbutes");
tcsetattr(term_fd,TCSAFLUSH,&old_tio);
if(term_fd > -1)
close(term_fd);
term_fd = -1;
}