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:
14
configure.ac
14
configure.ac
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "out123.h"
|
||||
#include <sys/stat.h>
|
||||
#include "common.h"
|
||||
#include "terms.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
60
src/local.c
60
src/local.c
@@ -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!
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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:
|
||||
|
139
src/term.c
139
src/term.c
@@ -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
31
src/term_none.c
Normal 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
199
src/term_posix.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user