mpg123-1.31.0

This commit is contained in:
Ozkan Sezer
2022-10-28 22:39:00 +03:00
parent b26727f0be
commit cd6cf37dee
53 changed files with 1275 additions and 1229 deletions

View File

@@ -58,6 +58,7 @@ EXTRA_DIST += \
NEWS.libout123 \ NEWS.libout123 \
NEWS.libsyn123 \ NEWS.libsyn123 \
ports/cmake/CMakeLists.txt \ ports/cmake/CMakeLists.txt \
ports/cmake/linux_i686.toolchain.cmake \
ports/cmake/mpg123-config.cmake.in \ ports/cmake/mpg123-config.cmake.in \
ports/cmake/cmake/search_libs.cmake \ ports/cmake/cmake/search_libs.cmake \
ports/cmake/cmake/read_api_version.cmake \ ports/cmake/cmake/read_api_version.cmake \

View File

@@ -375,22 +375,23 @@ check_PROGRAMS = src/tests/decode_fixed$(EXEEXT) \
@TERM_POSIX_TRUE@am__append_98 = src/term_posix.c @TERM_POSIX_TRUE@am__append_98 = src/term_posix.c
@TERM_WIN32_TRUE@am__append_99 = src/term_win32.c @TERM_WIN32_TRUE@am__append_99 = src/term_win32.c
@TERM_NONE_TRUE@am__append_100 = src/term_none.c @TERM_NONE_TRUE@am__append_100 = src/term_none.c
@NET123_EXEC_TRUE@am__append_101 = src/net123.h src/net123_exec.c @NET123_TRUE@am__append_101 = src/net123.h
@NET123_WINHTTP_TRUE@am__append_102 = src/net123.h src/net123_winhttp.c @NET123_EXEC_TRUE@am__append_102 = src/net123_exec.c
@NET123_WINHTTP_TRUE@am__append_103 = -lwinhttp @NET123_WINHTTP_TRUE@am__append_103 = src/net123_winhttp.c
@NET123_WININET_TRUE@am__append_104 = src/net123.h src/net123_wininet.c @NET123_WINHTTP_TRUE@am__append_104 = -lwinhttp
@NET123_WININET_TRUE@am__append_105 = -lwininet @NET123_WININET_TRUE@am__append_105 = src/net123_wininet.c
@WIN32_CODES_TRUE@am__append_106 = \ @NET123_WININET_TRUE@am__append_106 = -lwininet
@WIN32_CODES_TRUE@ src/win32_support.c @WIN32_CODES_TRUE@am__append_107 = \
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__append_107 = src/win32_net.c
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__append_108 = -lws2_32
@WIN32_CODES_TRUE@am__append_109 = \
@WIN32_CODES_TRUE@ src/win32_support.c @WIN32_CODES_TRUE@ src/win32_support.c
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__append_108 = src/win32_net.c
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__append_109 = -lws2_32
@WIN32_CODES_TRUE@am__append_110 = \ @WIN32_CODES_TRUE@am__append_110 = \
@WIN32_CODES_TRUE@ src/win32_support.c @WIN32_CODES_TRUE@ src/win32_support.c
@WIN32_CODES_TRUE@am__append_111 = \
@WIN32_CODES_TRUE@ src/win32_support.c
subdir = . subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
@@ -1128,11 +1129,12 @@ am__src_mpg123_SOURCES_DIST = src/audio.c src/audio.h src/common.c \
@TERM_POSIX_TRUE@am__objects_70 = src/term_posix.$(OBJEXT) @TERM_POSIX_TRUE@am__objects_70 = src/term_posix.$(OBJEXT)
@TERM_WIN32_TRUE@am__objects_71 = src/term_win32.$(OBJEXT) @TERM_WIN32_TRUE@am__objects_71 = src/term_win32.$(OBJEXT)
@TERM_NONE_TRUE@am__objects_72 = src/term_none.$(OBJEXT) @TERM_NONE_TRUE@am__objects_72 = src/term_none.$(OBJEXT)
@NET123_EXEC_TRUE@am__objects_73 = src/net123_exec.$(OBJEXT) am__objects_73 =
@NET123_WINHTTP_TRUE@am__objects_74 = src/net123_winhttp.$(OBJEXT) @NET123_EXEC_TRUE@am__objects_74 = src/net123_exec.$(OBJEXT)
@NET123_WININET_TRUE@am__objects_75 = src/net123_wininet.$(OBJEXT) @NET123_WINHTTP_TRUE@am__objects_75 = src/net123_winhttp.$(OBJEXT)
@WIN32_CODES_TRUE@am__objects_76 = src/win32_support.$(OBJEXT) @NET123_WININET_TRUE@am__objects_76 = src/net123_wininet.$(OBJEXT)
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__objects_77 = src/win32_net.$(OBJEXT) @WIN32_CODES_TRUE@am__objects_77 = src/win32_support.$(OBJEXT)
@NETWORK_WINSOCK_TRUE@@WIN32_CODES_TRUE@am__objects_78 = src/win32_net.$(OBJEXT)
am_src_mpg123_OBJECTS = src/audio.$(OBJEXT) src/common.$(OBJEXT) \ am_src_mpg123_OBJECTS = src/audio.$(OBJEXT) src/common.$(OBJEXT) \
src/sysutil.$(OBJEXT) src/control_generic.$(OBJEXT) \ src/sysutil.$(OBJEXT) src/control_generic.$(OBJEXT) \
src/equalizer.$(OBJEXT) src/getlopt.$(OBJEXT) \ src/equalizer.$(OBJEXT) src/getlopt.$(OBJEXT) \
@@ -1142,7 +1144,8 @@ am_src_mpg123_OBJECTS = src/audio.$(OBJEXT) src/common.$(OBJEXT) \
src/playlist.$(OBJEXT) src/streamdump.$(OBJEXT) \ src/playlist.$(OBJEXT) src/streamdump.$(OBJEXT) \
src/term.$(OBJEXT) $(am__objects_70) $(am__objects_71) \ src/term.$(OBJEXT) $(am__objects_70) $(am__objects_71) \
$(am__objects_72) $(am__objects_73) $(am__objects_74) \ $(am__objects_72) $(am__objects_73) $(am__objects_74) \
$(am__objects_75) $(am__objects_76) $(am__objects_77) $(am__objects_75) $(am__objects_76) $(am__objects_77) \
$(am__objects_78)
src_mpg123_OBJECTS = $(am_src_mpg123_OBJECTS) src_mpg123_OBJECTS = $(am_src_mpg123_OBJECTS)
am__DEPENDENCIES_1 = am__DEPENDENCIES_1 =
src_mpg123_DEPENDENCIES = src/compat/libcompat.la \ src_mpg123_DEPENDENCIES = src/compat/libcompat.la \
@@ -1155,7 +1158,7 @@ src_mpg123_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
am__src_mpg123_id3dump_SOURCES_DIST = src/mpg123-id3dump.c \ am__src_mpg123_id3dump_SOURCES_DIST = src/mpg123-id3dump.c \
src/getlopt.c src/getlopt.h src/win32_support.c src/getlopt.c src/getlopt.h src/win32_support.c
am_src_mpg123_id3dump_OBJECTS = src/mpg123-id3dump.$(OBJEXT) \ am_src_mpg123_id3dump_OBJECTS = src/mpg123-id3dump.$(OBJEXT) \
src/getlopt.$(OBJEXT) $(am__objects_76) src/getlopt.$(OBJEXT) $(am__objects_77)
src_mpg123_id3dump_OBJECTS = $(am_src_mpg123_id3dump_OBJECTS) src_mpg123_id3dump_OBJECTS = $(am_src_mpg123_id3dump_OBJECTS)
src_mpg123_id3dump_DEPENDENCIES = src/compat/libcompat.la \ src_mpg123_id3dump_DEPENDENCIES = src/compat/libcompat.la \
src/libmpg123/libmpg123.la src/libmpg123/libmpg123.la
@@ -1170,7 +1173,7 @@ am__src_out123_SOURCES_DIST = src/sysutil.c src/sysutil.h src/common.h \
src/win32_support.h src/win32_support.c src/win32_support.h src/win32_support.c
am_src_out123_OBJECTS = src/sysutil.$(OBJEXT) src/getlopt.$(OBJEXT) \ am_src_out123_OBJECTS = src/sysutil.$(OBJEXT) src/getlopt.$(OBJEXT) \
src/local.$(OBJEXT) src/filters.$(OBJEXT) src/out123.$(OBJEXT) \ src/local.$(OBJEXT) src/filters.$(OBJEXT) src/out123.$(OBJEXT) \
$(am__objects_76) $(am__objects_77)
src_out123_OBJECTS = $(am_src_out123_OBJECTS) src_out123_OBJECTS = $(am_src_out123_OBJECTS)
src_out123_DEPENDENCIES = src/compat/libcompat.la \ src_out123_DEPENDENCIES = src/compat/libcompat.la \
src/libsyn123/libsyn123.la src/libout123/libout123.la src/libsyn123/libsyn123.la src/libout123/libout123.la
@@ -2031,7 +2034,9 @@ EXTRA_DIST = src/tests/testtext.sh src/tests/decode_fixed.sh \
doc/examples/dump_seekindex.c doc/examples/extract_frames.c \ doc/examples/dump_seekindex.c doc/examples/extract_frames.c \
doc/examples/Makefile mpg123.spec makedll.sh windows-builds.sh \ doc/examples/Makefile mpg123.spec makedll.sh windows-builds.sh \
equalize.dat NEWS.libmpg123 NEWS.libout123 NEWS.libsyn123 \ equalize.dat NEWS.libmpg123 NEWS.libout123 NEWS.libsyn123 \
ports/cmake/CMakeLists.txt ports/cmake/mpg123-config.cmake.in \ ports/cmake/CMakeLists.txt \
ports/cmake/linux_i686.toolchain.cmake \
ports/cmake/mpg123-config.cmake.in \
ports/cmake/cmake/search_libs.cmake \ ports/cmake/cmake/search_libs.cmake \
ports/cmake/cmake/read_api_version.cmake \ ports/cmake/cmake/read_api_version.cmake \
ports/cmake/cmake/CheckCPUArch.cmake \ ports/cmake/cmake/CheckCPUArch.cmake \
@@ -2880,8 +2885,8 @@ src_libsyn123_libsyn123_la_SOURCES = \
src_mpg123_LDADD = src/compat/libcompat.la src/libmpg123/libmpg123.la \ src_mpg123_LDADD = src/compat/libcompat.la src/libmpg123/libmpg123.la \
src/libout123/libout123.la src/libsyn123/libsyn123.la \ src/libout123/libout123.la src/libsyn123/libsyn123.la \
@PROG_LIBS@ $(am__append_103) $(am__append_105) \ @PROG_LIBS@ $(am__append_104) $(am__append_106) \
$(am__append_108) $(am__append_109)
src_mpg123_LDFLAGS = @EXEC_LT_LDFLAGS@ src_mpg123_LDFLAGS = @EXEC_LT_LDFLAGS@
src_out123_LDADD = \ src_out123_LDADD = \
src/compat/libcompat.la \ src/compat/libcompat.la \
@@ -2911,16 +2916,16 @@ src_mpg123_SOURCES = src/audio.c src/audio.h src/common.c src/common.h \
src/playlist.h src/streamdump.h src/streamdump.c src/term.c \ src/playlist.h src/streamdump.h src/streamdump.c src/term.c \
src/term.h src/terms.h src/win32_support.h $(am__append_98) \ src/term.h src/terms.h src/win32_support.h $(am__append_98) \
$(am__append_99) $(am__append_100) $(am__append_101) \ $(am__append_99) $(am__append_100) $(am__append_101) \
$(am__append_102) $(am__append_104) $(am__append_106) \ $(am__append_102) $(am__append_103) $(am__append_105) \
$(am__append_107) $(am__append_107) $(am__append_108)
# Replace common.h by sysutil.h! # Replace common.h by sysutil.h!
src_out123_SOURCES = src/sysutil.c src/sysutil.h src/common.h \ src_out123_SOURCES = src/sysutil.c src/sysutil.h src/common.h \
src/getlopt.c src/getlopt.h src/local.h src/local.c \ src/getlopt.c src/getlopt.h src/local.h src/local.c \
src/filters.h src/filters.c src/out123.c src/mpg123app.h \ src/filters.h src/filters.c src/out123.c src/mpg123app.h \
src/win32_support.h $(am__append_109) src/win32_support.h $(am__append_110)
src_mpg123_id3dump_SOURCES = src/mpg123-id3dump.c src/getlopt.c \ src_mpg123_id3dump_SOURCES = src/mpg123-id3dump.c src/getlopt.c \
src/getlopt.h $(am__append_110) src/getlopt.h $(am__append_111)
src_mpg123_strip_SOURCES = \ src_mpg123_strip_SOURCES = \
src/mpg123-strip.c \ src/mpg123-strip.c \
src/getlopt.c \ src/getlopt.c \

47
NEWS
View File

@@ -1,3 +1,50 @@
1.31.0
------
- mpg123:
-- Finally make terminal control work on Windows, for real. Building it
was broken in 1.30.x.
-- The --control / -C switch will make mpg123 abort now if terminal
control cannot be enabled.
-- Revert to internal network code for plain HTTP to ensure continued
support for original shoutcast servers that do not talk proper HTTP.
External backends are built at the same time and can be enforced using
--network <backend>.
-- Try-witout-port for internal network code is gone. We do not need to
keep each ancient hack for specific hosts.
-- Handle redirections independently of the backend behind net123.
-- Set proxy environment variables when --proxy is specified, for net123
backends to use.
-- Continue reading for long commands in generic control, avoiding
unnecessary unfinished command errors.
-- Change error message from 'unknown command' to
'unknown command with arguments' to avoid confusion why 'help foo'
is unknown, as opposed to 'help'.
-- Reduce CPU load while just waiting for terminal input
(thanks to bolshoytoster on github).
-- Condense terminal control help output and excessive vertical whitespace
in printouts (inspired by Volkmar Klatt).
-- Fix interaction of pause (looping) with buffer, adding --pauseloop
to set the loop interval.
-- Numeric option arguments are strictly checked now for conversion errors.
This also catches -devbuffer, which was interpretd as -d 0 before. This
also applies to out123.
- libout123:
-- Add same interruption handling to out123_write() as to
unintr_write(), adding EAGAIN to fix bug 342 (thanks to Steffen Nurpmeso)
for certain ALSA setups.
-- Add --devbuffer support to win32 output and change default to 0.25 seconds.
-- Fix race condition to deadlock on buffer_sync_param() where parameters after
the command byte got read as more commands. This got triggered easily by
using the pause key in terminal mode with buffer (which was discouraged
before because of buffer flushing). Generally, changing parameters with
active buffer process was dangerous since libout123 entered the scene.
- some build fixes for compiler pickyness
- Disable largefile renames also for non-sensitive POSIX systems
(in some distant future, the alias symbols could go away, then …
bug 330).
- Fix Android NDK x86 builds with GLOBAL_VAR_PTR use in assembly (bug 345).
1.30.2 1.30.2
------ ------
- Only use EWOULDBLOCK if the macro is defined (FreeBSD misses it for - Only use EWOULDBLOCK if the macro is defined (FreeBSD misses it for

315
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for mpg123 1.30.2. # Generated by GNU Autoconf 2.69 for mpg123 1.31.0.
# #
# Report bugs to <maintainer@mpg123.org>. # Report bugs to <maintainer@mpg123.org>.
# #
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='mpg123' PACKAGE_NAME='mpg123'
PACKAGE_TARNAME='mpg123' PACKAGE_TARNAME='mpg123'
PACKAGE_VERSION='1.30.2' PACKAGE_VERSION='1.31.0'
PACKAGE_STRING='mpg123 1.30.2' PACKAGE_STRING='mpg123 1.31.0'
PACKAGE_BUGREPORT='maintainer@mpg123.org' PACKAGE_BUGREPORT='maintainer@mpg123.org'
PACKAGE_URL='' PACKAGE_URL=''
@@ -653,6 +653,8 @@ NET123_WINHTTP_FALSE
NET123_WINHTTP_TRUE NET123_WINHTTP_TRUE
NET123_EXEC_FALSE NET123_EXEC_FALSE
NET123_EXEC_TRUE NET123_EXEC_TRUE
NET123_FALSE
NET123_TRUE
NETWORK_WINSOCK_FALSE NETWORK_WINSOCK_FALSE
NETWORK_WINSOCK_TRUE NETWORK_WINSOCK_TRUE
WIN32_CODES_FALSE WIN32_CODES_FALSE
@@ -793,9 +795,7 @@ SUN_LDFLAGS
SUN_LIBS SUN_LIBS
HAVE_SNDIO_FALSE HAVE_SNDIO_FALSE
HAVE_SNDIO_TRUE HAVE_SNDIO_TRUE
SNDIO_CFLAGS
SNDIO_LDFLAGS SNDIO_LDFLAGS
SNDIO_LIBS
HAVE_COREAUDIO_FALSE HAVE_COREAUDIO_FALSE
HAVE_COREAUDIO_TRUE HAVE_COREAUDIO_TRUE
COREAUDIO_CFLAGS COREAUDIO_CFLAGS
@@ -821,6 +821,8 @@ HAVE_TINYALSA_TRUE
TINYALSA_CFLAGS TINYALSA_CFLAGS
TINYALSA_LDFLAGS TINYALSA_LDFLAGS
TINYALSA_LIBS TINYALSA_LIBS
SNDIO_LIBS
SNDIO_CFLAGS
SDL_LIBS SDL_LIBS
SDL_CFLAGS SDL_CFLAGS
ESD_LIBS ESD_LIBS
@@ -888,10 +890,10 @@ HAVE_FLOATDCT_TRUE
INCLUDE_SYS_TYPE_H INCLUDE_SYS_TYPE_H
INCLUDE_STDLIB_H INCLUDE_STDLIB_H
INCLUDE_STDIO_H INCLUDE_STDIO_H
BUILD_NO_LARGENAME
HAVE_LFS_ALIAS_FALSE HAVE_LFS_ALIAS_FALSE
HAVE_LFS_ALIAS_TRUE HAVE_LFS_ALIAS_TRUE
LFS_ALIAS_BITS LFS_ALIAS_BITS
BUILD_NO_LARGENAME
HAVE_LFS_WRAP_FALSE HAVE_LFS_WRAP_FALSE
HAVE_LFS_WRAP_TRUE HAVE_LFS_WRAP_TRUE
YASMFLAGS YASMFLAGS
@@ -1132,7 +1134,9 @@ PULSE_LIBS
ESD_CFLAGS ESD_CFLAGS
ESD_LIBS ESD_LIBS
SDL_CFLAGS SDL_CFLAGS
SDL_LIBS' SDL_LIBS
SNDIO_CFLAGS
SNDIO_LIBS'
# Initialize some variables set by options. # Initialize some variables set by options.
@@ -1683,7 +1687,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures mpg123 1.30.2 to adapt to many kinds of systems. \`configure' configures mpg123 1.31.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1754,7 +1758,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of mpg123 1.30.2:";; short | recursive ) echo "Configuration of mpg123 1.31.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1891,8 +1895,12 @@ Optional Packages:
--with-seektable=<size> choose size of seek index table (0 disables it), default 1000 --with-seektable=<size> choose size of seek index table (0 disables it), default 1000
--with-network=<type> Available options, depending on platform, are auto, --with-network=<type> Available options, depending on platform, are auto,
none, internal, winhttp, wininet, and exec (wget or none, internal, winhttp, wininet (or wininethttp for
curl binaries). both), and exec (wget or curl binaries). The
internal code is always built in addition to
external options for plain HTTP (esp. Shoutcast v1)
support. The external option is for HTTPS by
default, but can be used for HTTP, too.
Some influential environment variables: Some influential environment variables:
CC C compiler command CC C compiler command
@@ -1921,6 +1929,9 @@ Some influential environment variables:
ESD_LIBS linker flags for ESD, overriding pkg-config ESD_LIBS linker flags for ESD, overriding pkg-config
SDL_CFLAGS C compiler flags for SDL, overriding pkg-config SDL_CFLAGS C compiler flags for SDL, overriding pkg-config
SDL_LIBS linker flags for SDL, overriding pkg-config SDL_LIBS linker flags for SDL, overriding pkg-config
SNDIO_CFLAGS
C compiler flags for SNDIO, overriding pkg-config
SNDIO_LIBS linker flags for SNDIO, overriding pkg-config
Use these variables to override the choices made by `configure' or to help Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations. it to find libraries and programs with nonstandard names/locations.
@@ -1988,7 +1999,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
mpg123 configure 1.30.2 mpg123 configure 1.31.0
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2594,7 +2605,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by mpg123 $as_me 1.30.2, which was It was created by mpg123 $as_me 1.31.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@@ -2947,7 +2958,7 @@ API_VERSION=47
LIB_PATCHLEVEL=0 LIB_PATCHLEVEL=0
OUTAPI_VERSION=4 OUTAPI_VERSION=4
OUTLIB_PATCHLEVEL=4 OUTLIB_PATCHLEVEL=7
SYNAPI_VERSION=1 SYNAPI_VERSION=1
SYNLIB_PATCHLEVEL=4 SYNLIB_PATCHLEVEL=4
@@ -3553,7 +3564,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='mpg123' PACKAGE='mpg123'
VERSION='1.30.2' VERSION='1.31.0'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@@ -15594,8 +15605,10 @@ fi
if test "x$ac_cv_sys_file_offset_bits" = x || echo "$ac_cv_sys_file_offset_bits" | $GREP '[^0-9]' > /dev/null; then if test "x$ac_cv_sys_file_offset_bits" = x || echo "$ac_cv_sys_file_offset_bits" | $GREP '[^0-9]' > /dev/null; then
largefile_sensitive=no largefile_sensitive=no
BUILD_NO_LARGENAME=1
else else
largefile_sensitive=yes largefile_sensitive=yes
BUILD_NO_LARGENAME=0
fi fi
# Add dual-mode wrapper code. # Add dual-mode wrapper code.
if test x"$largefile_sensitive" = xyes ; then if test x"$largefile_sensitive" = xyes ; then
@@ -15606,6 +15619,8 @@ else
HAVE_LFS_WRAP_FALSE= HAVE_LFS_WRAP_FALSE=
fi fi
# Any non-sensitive platform does not bother with off_t-based function renaming.
# Using the lower level macros instead of AC_TYPE_* for compatibility with not freshest autoconf. # Using the lower level macros instead of AC_TYPE_* for compatibility with not freshest autoconf.
ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
@@ -16021,7 +16036,6 @@ done
fi fi
term_type=none
# Check if system supports termios # Check if system supports termios
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking POSIX termios" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking POSIX termios" >&5
$as_echo_n "checking POSIX termios... " >&6; } $as_echo_n "checking POSIX termios... " >&6; }
@@ -16054,6 +16068,34 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_posix_termios" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_posix_termios" >&5
$as_echo "$ac_cv_sys_posix_termios" >&6; } $as_echo "$ac_cv_sys_posix_termios" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have wincon.h" >&5
$as_echo_n "checking if we have wincon.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <windows.h>
#include <wincon.h>
void *v = &ReadConsoleInput;
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_header_wincon_h=yes
else
ac_cv_header_wincon_h=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_wincon_h" >&5
$as_echo "$ac_cv_header_wincon_h" >&6; }
if test "x$ac_cv_header_wincon_h" = "xyes"; then :
else
$as_echo "#define HAVE_WINCON_H 1" >>confdefs.h
fi
term_type=none
if test "x$ac_cv_sys_posix_termios" = "xyes"; then if test "x$ac_cv_sys_posix_termios" = "xyes"; then
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@@ -16061,9 +16103,12 @@ cat >>confdefs.h <<_ACEOF
_ACEOF _ACEOF
term_type=posix term_type=posix
elif test "x$ac_cv_header_windows_h" = "xyes" &&
test "x$ac_cv_header_wincon_h" = "xyes"; then
term_type=win32
fi fi
for ac_func in random for ac_func in random setenv unsetenv
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -16396,13 +16441,6 @@ fi
done done
# A Hack for MSVC builds by cmake: Disable largefile hackery.
# Maybe one time we support hat wretched environment directly, but
# for now configure lives in a world where large file support is
# properly defined and served by off_t.
BUILD_NO_LARGENAME=0
# Substitutions for the installable mpg123.h header # Substitutions for the installable mpg123.h header
if test "x$ac_cv_header_stdio_h" = "xyes"; then if test "x$ac_cv_header_stdio_h" = "xyes"; then
INCLUDE_STDIO_H="#include <stdio.h>" INCLUDE_STDIO_H="#include <stdio.h>"
@@ -18114,63 +18152,77 @@ $as_echo "$HAVE_WIN32_WASAPI" >&6; }
fi fi
;; ;;
sndio) sndio)
SNDIO_LIBS=-lsndio
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sio_open in -lsndio" >&5 pkg_failed=no
$as_echo_n "checking for sio_open in -lsndio... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SNDIO" >&5
if ${ac_cv_lib_sndio_sio_open+:} false; then : $as_echo_n "checking for SNDIO... " >&6; }
$as_echo_n "(cached) " >&6
if test -n "$SNDIO_CFLAGS"; then
pkg_cv_SNDIO_CFLAGS="$SNDIO_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sndio\""; } >&5
($PKG_CONFIG --exists --print-errors "sndio") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_SNDIO_CFLAGS=`$PKG_CONFIG --cflags "sndio" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else else
ac_check_lib_save_LIBS=$LIBS pkg_failed=yes
LIBS="-lsndio $LIBS" fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext else
/* end confdefs.h. */ pkg_failed=untried
fi
/* Override any GCC internal prototype to avoid an error. if test -n "$SNDIO_LIBS"; then
Use char because int might match the return type of a GCC pkg_cv_SNDIO_LIBS="$SNDIO_LIBS"
builtin and then its argument prototype would still apply. */ elif test -n "$PKG_CONFIG"; then
#ifdef __cplusplus if test -n "$PKG_CONFIG" && \
extern "C" { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sndio\""; } >&5
#endif ($PKG_CONFIG --exists --print-errors "sndio") 2>&5
char sio_open (); ac_status=$?
int $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
main () test $ac_status = 0; }; then
{ pkg_cv_SNDIO_LIBS=`$PKG_CONFIG --libs "sndio" 2>/dev/null`
return sio_open (); test "x$?" != "x0" && pkg_failed=yes
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_sndio_sio_open=yes
else else
ac_cv_lib_sndio_sio_open=no pkg_failed=yes
fi fi
rm -f core conftest.err conftest.$ac_objext \ else
conftest$ac_exeext conftest.$ac_ext pkg_failed=untried
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sndio_sio_open" >&5
$as_echo "$ac_cv_lib_sndio_sio_open" >&6; }
if test "x$ac_cv_lib_sndio_sio_open" = xyes; then :
for ac_header in sndio.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sndio.h" "ac_cv_header_sndio_h" "$ac_includes_default"
if test "x$ac_cv_header_sndio_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SNDIO_H 1
_ACEOF
output_modules="$output_modules sndio" HAVE_SNDIO="yes"
fi fi
done
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi fi
if test $_pkg_short_errors_supported = yes; then
SNDIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sndio" 2>&1`
else
SNDIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sndio" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$SNDIO_PKG_ERRORS" >&5
if test "x$HAVE_SNDIO" != xyes; then HAVE_SNDIO="no" check_failed=yes
check_failed=yes elif test $pkg_failed = untried; then
fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
HAVE_SNDIO="no" check_failed=yes
else
SNDIO_CFLAGS=$pkg_cv_SNDIO_CFLAGS
SNDIO_LIBS=$pkg_cv_SNDIO_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
output_modules="$output_modules sndio" HAVE_SNDIO="yes"
fi
;; ;;
sun) sun)
for ac_header in sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h for ac_header in sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h
@@ -18805,11 +18857,11 @@ fi
#for i in dummy tinyalsa alsa qsa coreaudio esd jack nas oss portaudio pulse sdl sndio sun win32 win32_wasapi aix alib arts hp os2 sgi mint openal #for i in dummy tinyalsa alsa qsa coreaudio esd jack nas oss portaudio pulse sdl sndio sun win32 win32_wasapi aix alib arts hp os2 sgi mint openal
#do echo $i; done | #do echo $i; done |
#perl -ne 'chomp; $big = uc($_); print <<EOT; #perl -ne 'chomp; $big = uc($_); print <<EOT;
#AM_CONDITIONAL([BUILD_${big}], [ test "$_" = \$default_output_module ]) #AM_CONDITIONAL([BUILD_${big}], [ test "$_" = "\$default_output_module" ])
#EOT #EOT
#' #'
if test "dummy" = $default_output_module ; then if test "dummy" = "$default_output_module" ; then
BUILD_DUMMY_TRUE= BUILD_DUMMY_TRUE=
BUILD_DUMMY_FALSE='#' BUILD_DUMMY_FALSE='#'
else else
@@ -18817,7 +18869,7 @@ else
BUILD_DUMMY_FALSE= BUILD_DUMMY_FALSE=
fi fi
if test "tinyalsa" = $default_output_module ; then if test "tinyalsa" = "$default_output_module" ; then
BUILD_TINYALSA_TRUE= BUILD_TINYALSA_TRUE=
BUILD_TINYALSA_FALSE='#' BUILD_TINYALSA_FALSE='#'
else else
@@ -18825,7 +18877,7 @@ else
BUILD_TINYALSA_FALSE= BUILD_TINYALSA_FALSE=
fi fi
if test "alsa" = $default_output_module ; then if test "alsa" = "$default_output_module" ; then
BUILD_ALSA_TRUE= BUILD_ALSA_TRUE=
BUILD_ALSA_FALSE='#' BUILD_ALSA_FALSE='#'
else else
@@ -18833,7 +18885,7 @@ else
BUILD_ALSA_FALSE= BUILD_ALSA_FALSE=
fi fi
if test "qsa" = $default_output_module ; then if test "qsa" = "$default_output_module" ; then
BUILD_QSA_TRUE= BUILD_QSA_TRUE=
BUILD_QSA_FALSE='#' BUILD_QSA_FALSE='#'
else else
@@ -18841,7 +18893,7 @@ else
BUILD_QSA_FALSE= BUILD_QSA_FALSE=
fi fi
if test "coreaudio" = $default_output_module ; then if test "coreaudio" = "$default_output_module" ; then
BUILD_COREAUDIO_TRUE= BUILD_COREAUDIO_TRUE=
BUILD_COREAUDIO_FALSE='#' BUILD_COREAUDIO_FALSE='#'
else else
@@ -18849,7 +18901,7 @@ else
BUILD_COREAUDIO_FALSE= BUILD_COREAUDIO_FALSE=
fi fi
if test "esd" = $default_output_module ; then if test "esd" = "$default_output_module" ; then
BUILD_ESD_TRUE= BUILD_ESD_TRUE=
BUILD_ESD_FALSE='#' BUILD_ESD_FALSE='#'
else else
@@ -18857,7 +18909,7 @@ else
BUILD_ESD_FALSE= BUILD_ESD_FALSE=
fi fi
if test "jack" = $default_output_module ; then if test "jack" = "$default_output_module" ; then
BUILD_JACK_TRUE= BUILD_JACK_TRUE=
BUILD_JACK_FALSE='#' BUILD_JACK_FALSE='#'
else else
@@ -18865,7 +18917,7 @@ else
BUILD_JACK_FALSE= BUILD_JACK_FALSE=
fi fi
if test "nas" = $default_output_module ; then if test "nas" = "$default_output_module" ; then
BUILD_NAS_TRUE= BUILD_NAS_TRUE=
BUILD_NAS_FALSE='#' BUILD_NAS_FALSE='#'
else else
@@ -18873,7 +18925,7 @@ else
BUILD_NAS_FALSE= BUILD_NAS_FALSE=
fi fi
if test "oss" = $default_output_module ; then if test "oss" = "$default_output_module" ; then
BUILD_OSS_TRUE= BUILD_OSS_TRUE=
BUILD_OSS_FALSE='#' BUILD_OSS_FALSE='#'
else else
@@ -18881,7 +18933,7 @@ else
BUILD_OSS_FALSE= BUILD_OSS_FALSE=
fi fi
if test "portaudio" = $default_output_module ; then if test "portaudio" = "$default_output_module" ; then
BUILD_PORTAUDIO_TRUE= BUILD_PORTAUDIO_TRUE=
BUILD_PORTAUDIO_FALSE='#' BUILD_PORTAUDIO_FALSE='#'
else else
@@ -18889,7 +18941,7 @@ else
BUILD_PORTAUDIO_FALSE= BUILD_PORTAUDIO_FALSE=
fi fi
if test "pulse" = $default_output_module ; then if test "pulse" = "$default_output_module" ; then
BUILD_PULSE_TRUE= BUILD_PULSE_TRUE=
BUILD_PULSE_FALSE='#' BUILD_PULSE_FALSE='#'
else else
@@ -18897,7 +18949,7 @@ else
BUILD_PULSE_FALSE= BUILD_PULSE_FALSE=
fi fi
if test "sdl" = $default_output_module ; then if test "sdl" = "$default_output_module" ; then
BUILD_SDL_TRUE= BUILD_SDL_TRUE=
BUILD_SDL_FALSE='#' BUILD_SDL_FALSE='#'
else else
@@ -18905,7 +18957,7 @@ else
BUILD_SDL_FALSE= BUILD_SDL_FALSE=
fi fi
if test "sndio" = $default_output_module ; then if test "sndio" = "$default_output_module" ; then
BUILD_SNDIO_TRUE= BUILD_SNDIO_TRUE=
BUILD_SNDIO_FALSE='#' BUILD_SNDIO_FALSE='#'
else else
@@ -18913,7 +18965,7 @@ else
BUILD_SNDIO_FALSE= BUILD_SNDIO_FALSE=
fi fi
if test "sun" = $default_output_module ; then if test "sun" = "$default_output_module" ; then
BUILD_SUN_TRUE= BUILD_SUN_TRUE=
BUILD_SUN_FALSE='#' BUILD_SUN_FALSE='#'
else else
@@ -18921,7 +18973,7 @@ else
BUILD_SUN_FALSE= BUILD_SUN_FALSE=
fi fi
if test "win32" = $default_output_module ; then if test "win32" = "$default_output_module" ; then
BUILD_WIN32_TRUE= BUILD_WIN32_TRUE=
BUILD_WIN32_FALSE='#' BUILD_WIN32_FALSE='#'
else else
@@ -18929,7 +18981,7 @@ else
BUILD_WIN32_FALSE= BUILD_WIN32_FALSE=
fi fi
if test "win32_wasapi" = $default_output_module ; then if test "win32_wasapi" = "$default_output_module" ; then
BUILD_WIN32_WASAPI_TRUE= BUILD_WIN32_WASAPI_TRUE=
BUILD_WIN32_WASAPI_FALSE='#' BUILD_WIN32_WASAPI_FALSE='#'
else else
@@ -18937,7 +18989,7 @@ else
BUILD_WIN32_WASAPI_FALSE= BUILD_WIN32_WASAPI_FALSE=
fi fi
if test "aix" = $default_output_module ; then if test "aix" = "$default_output_module" ; then
BUILD_AIX_TRUE= BUILD_AIX_TRUE=
BUILD_AIX_FALSE='#' BUILD_AIX_FALSE='#'
else else
@@ -18945,7 +18997,7 @@ else
BUILD_AIX_FALSE= BUILD_AIX_FALSE=
fi fi
if test "alib" = $default_output_module ; then if test "alib" = "$default_output_module" ; then
BUILD_ALIB_TRUE= BUILD_ALIB_TRUE=
BUILD_ALIB_FALSE='#' BUILD_ALIB_FALSE='#'
else else
@@ -18953,7 +19005,7 @@ else
BUILD_ALIB_FALSE= BUILD_ALIB_FALSE=
fi fi
if test "arts" = $default_output_module ; then if test "arts" = "$default_output_module" ; then
BUILD_ARTS_TRUE= BUILD_ARTS_TRUE=
BUILD_ARTS_FALSE='#' BUILD_ARTS_FALSE='#'
else else
@@ -18961,7 +19013,7 @@ else
BUILD_ARTS_FALSE= BUILD_ARTS_FALSE=
fi fi
if test "hp" = $default_output_module ; then if test "hp" = "$default_output_module" ; then
BUILD_HP_TRUE= BUILD_HP_TRUE=
BUILD_HP_FALSE='#' BUILD_HP_FALSE='#'
else else
@@ -18969,7 +19021,7 @@ else
BUILD_HP_FALSE= BUILD_HP_FALSE=
fi fi
if test "os2" = $default_output_module ; then if test "os2" = "$default_output_module" ; then
BUILD_OS2_TRUE= BUILD_OS2_TRUE=
BUILD_OS2_FALSE='#' BUILD_OS2_FALSE='#'
else else
@@ -18977,7 +19029,7 @@ else
BUILD_OS2_FALSE= BUILD_OS2_FALSE=
fi fi
if test "sgi" = $default_output_module ; then if test "sgi" = "$default_output_module" ; then
BUILD_SGI_TRUE= BUILD_SGI_TRUE=
BUILD_SGI_FALSE='#' BUILD_SGI_FALSE='#'
else else
@@ -18985,7 +19037,7 @@ else
BUILD_SGI_FALSE= BUILD_SGI_FALSE=
fi fi
if test "mint" = $default_output_module ; then if test "mint" = "$default_output_module" ; then
BUILD_MINT_TRUE= BUILD_MINT_TRUE=
BUILD_MINT_FALSE='#' BUILD_MINT_FALSE='#'
else else
@@ -18993,7 +19045,7 @@ else
BUILD_MINT_FALSE= BUILD_MINT_FALSE=
fi fi
if test "openal" = $default_output_module ; then if test "openal" = "$default_output_module" ; then
BUILD_OPENAL_TRUE= BUILD_OPENAL_TRUE=
BUILD_OPENAL_FALSE='#' BUILD_OPENAL_FALSE='#'
else else
@@ -19524,6 +19576,11 @@ $as_echo "winhttp" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: wininet" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: wininet" >&5
$as_echo "wininet" >&6; } $as_echo "wininet" >&6; }
;; ;;
wininethttp)
network_type="wininethttp"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: wininethttp" >&5
$as_echo "wininethttp" >&6; }
;;
internal) internal)
network_type="internal" network_type="internal"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: internal" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: internal" >&5
@@ -19559,7 +19616,7 @@ $as_echo_n "checking for automatic network support... " >&6; }
if test "x$have_fork" = "xyes"; then if test "x$have_fork" = "xyes"; then
network_type=exec network_type=exec
elif test "x$win32_specific_codes" = "xenabled"; then elif test "x$win32_specific_codes" = "xenabled"; then
network_type=wininet network_type=wininethttp
elif test "x$have_network" = "xyes"; then elif test "x$have_network" = "xyes"; then
network_type="internal" network_type="internal"
else else
@@ -19578,7 +19635,7 @@ fi
if test x$network_type = xexec -a x$have_fork != xyes; then if test x$network_type = xexec -a x$have_fork != xyes; then
as_fn_error $? "exec network support selected but fork not available" "$LINENO" 5 as_fn_error $? "exec network support selected but fork not available" "$LINENO" 5
fi fi
if test x$network_type = xwininet -o x$network_type = xwinhttp && test x$win32_specific_codes != xenabled; then if test x$network_type = xwininet -o x$network_type = xwinhttp -o x$network_type = xwininethttp && test x$win32_specific_codes != xenabled; then
as_fn_error $? "wininet or winhttp is currently only for Windows" "$LINENO" 5 as_fn_error $? "wininet or winhttp is currently only for Windows" "$LINENO" 5
fi fi
@@ -19595,7 +19652,7 @@ fi
if test x"$ipv6" = xauto; then if test x"$ipv6" = xauto; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking IPv6 use" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking IPv6 use" >&5
$as_echo_n "checking IPv6 use... " >&6; } $as_echo_n "checking IPv6 use... " >&6; }
if test x"$have_ipv6" = xyes -a x"$network_type" = xinternal; then if test x"$have_ipv6" = xyes -a x"$network_type" != xdisabled; then
ipv6=enabled ipv6=enabled
else else
ipv6=disabled ipv6=disabled
@@ -19604,13 +19661,13 @@ $as_echo_n "checking IPv6 use... " >&6; }
$as_echo "$ipv6" >&6; } $as_echo "$ipv6" >&6; }
fi fi
if test x$network_type = xinternal -a x$network_internal = xwinsock2; then if test x$network_type != xdisabled -a x$network_internal = xwinsock2; then
$as_echo "#define WANT_WIN32_SOCKETS 1" >>confdefs.h $as_echo "#define WANT_WIN32_SOCKETS 1" >>confdefs.h
fi fi
if test x$network_type = xinternal -a x$network_internal = xwinsock2 ; then if test x$network_type != xdisabled -a x$network_internal = xwinsock2 ; then
NETWORK_WINSOCK_TRUE= NETWORK_WINSOCK_TRUE=
NETWORK_WINSOCK_FALSE='#' NETWORK_WINSOCK_FALSE='#'
else else
@@ -19618,6 +19675,14 @@ else
NETWORK_WINSOCK_FALSE= NETWORK_WINSOCK_FALSE=
fi fi
if test x$network_type != xdisabled ; then
NET123_TRUE=
NET123_FALSE='#'
else
NET123_TRUE='#'
NET123_FALSE=
fi
if test x$network_type = xexec ; then if test x$network_type = xexec ; then
NET123_EXEC_TRUE= NET123_EXEC_TRUE=
NET123_EXEC_FALSE='#' NET123_EXEC_FALSE='#'
@@ -19626,7 +19691,7 @@ else
NET123_EXEC_FALSE= NET123_EXEC_FALSE=
fi fi
if test x$network_type = xwinhttp ; then if test x$network_type = xwinhttp || test x$network_type = xwininethttp ; then
NET123_WINHTTP_TRUE= NET123_WINHTTP_TRUE=
NET123_WINHTTP_FALSE='#' NET123_WINHTTP_FALSE='#'
else else
@@ -19634,7 +19699,7 @@ else
NET123_WINHTTP_FALSE= NET123_WINHTTP_FALSE=
fi fi
if test x$network_type = xwininet ; then if test x$network_type = xwininet || test x$network_type = xwininethttp ; then
NET123_WININET_TRUE= NET123_WININET_TRUE=
NET123_WININET_FALSE='#' NET123_WININET_FALSE='#'
else else
@@ -19643,6 +19708,32 @@ else
fi fi
case "$network_type" in
exec)
$as_echo "#define NET123_EXEC 1" >>confdefs.h
;;
winhttp)
$as_echo "#define NET123_WINHTTP 1" >>confdefs.h
;;
wininet)
$as_echo "#define NET123_WININET 1" >>confdefs.h
;;
wininethttp)
$as_echo "#define NET123_WININET 1" >>confdefs.h
$as_echo "#define NET123_WINHTTP 1" >>confdefs.h
;;
esac
if test "x$term_type" = xposix ; then if test "x$term_type" = xposix ; then
TERM_POSIX_TRUE= TERM_POSIX_TRUE=
@@ -19688,7 +19779,7 @@ $as_echo "$as_me: WARNING: You forced FIFO code while I think there is no mkfif
fi fi
fi fi
if test x"$network_type" = xinternal; then if test x"$network_type" != xdisabled; then
$as_echo "#define NETWORK 1" >>confdefs.h $as_echo "#define NETWORK 1" >>confdefs.h
@@ -20235,6 +20326,10 @@ if test -z "${NETWORK_WINSOCK_TRUE}" && test -z "${NETWORK_WINSOCK_FALSE}"; then
as_fn_error $? "conditional \"NETWORK_WINSOCK\" was never defined. as_fn_error $? "conditional \"NETWORK_WINSOCK\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5 Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi fi
if test -z "${NET123_TRUE}" && test -z "${NET123_FALSE}"; then
as_fn_error $? "conditional \"NET123\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${NET123_EXEC_TRUE}" && test -z "${NET123_EXEC_FALSE}"; then if test -z "${NET123_EXEC_TRUE}" && test -z "${NET123_EXEC_FALSE}"; then
as_fn_error $? "conditional \"NET123_EXEC\" was never defined. as_fn_error $? "conditional \"NET123_EXEC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -20656,7 +20751,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by mpg123 $as_me 1.30.2, which was This file was extended by mpg123 $as_me 1.31.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -20722,7 +20817,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
mpg123 config.status 1.30.2 mpg123 config.status 1.31.0
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
@@ -22433,9 +22528,11 @@ echo "
Extreme debugging ....... $xdebugging Extreme debugging ....... $xdebugging
Seek table size ......... $seektable Seek table size ......... $seektable
FIFO support ............ $fifo FIFO support ............ $fifo
Buffer .................. $buffer Buffer .................. $buffer"
Network (http streams) .. $network_type" if test x$network_type != xdisabled; then
if test x$network_type = xinternal; then if test x$network_type != xinternal; then
echo " External network ........ $network_type"
fi
echo " Internal network type ... $network_internal echo " Internal network type ... $network_internal
IPv6 (getaddrinfo) ...... $ipv6" IPv6 (getaddrinfo) ...... $ipv6"
fi fi

View File

@@ -9,7 +9,7 @@ dnl 2.69 at least.
AC_PREREQ([2.69]) AC_PREREQ([2.69])
dnl ############# Initialisation dnl ############# Initialisation
AC_INIT([mpg123], [1.30.2], [maintainer@mpg123.org]) AC_INIT([mpg123], [1.31.0], [maintainer@mpg123.org])
dnl Increment API_VERSION when the API gets changes (new functions). dnl Increment API_VERSION when the API gets changes (new functions).
dnl libmpg123 dnl libmpg123
@@ -18,7 +18,7 @@ LIB_PATCHLEVEL=0
dnl libout123 dnl libout123
OUTAPI_VERSION=4 OUTAPI_VERSION=4
OUTLIB_PATCHLEVEL=4 OUTLIB_PATCHLEVEL=7
dnl libsyn123 dnl libsyn123
SYNAPI_VERSION=1 SYNAPI_VERSION=1
@@ -1126,11 +1126,15 @@ dnl sensitive to largefile changes, i.e. FreeBSD always using 64 bit off_t.
if test "x$ac_cv_sys_file_offset_bits" = x || echo "$ac_cv_sys_file_offset_bits" | $GREP '@<:@^0-9@:>@' > /dev/null; then if test "x$ac_cv_sys_file_offset_bits" = x || echo "$ac_cv_sys_file_offset_bits" | $GREP '@<:@^0-9@:>@' > /dev/null; then
dnl if it has non-numeric chars or is empty... ignore... dnl if it has non-numeric chars or is empty... ignore...
largefile_sensitive=no largefile_sensitive=no
BUILD_NO_LARGENAME=1
else else
largefile_sensitive=yes largefile_sensitive=yes
BUILD_NO_LARGENAME=0
fi fi
# Add dual-mode wrapper code. # Add dual-mode wrapper code.
AM_CONDITIONAL([HAVE_LFS_WRAP], [ test x"$largefile_sensitive" = xyes ] ) AM_CONDITIONAL([HAVE_LFS_WRAP], [ test x"$largefile_sensitive" = xyes ] )
# Any non-sensitive platform does not bother with off_t-based function renaming.
AC_SUBST(BUILD_NO_LARGENAME)
# Using the lower level macros instead of AC_TYPE_* for compatibility with not freshest autoconf. # Using the lower level macros instead of AC_TYPE_* for compatibility with not freshest autoconf.
AC_CHECK_TYPE(size_t, unsigned long) AC_CHECK_TYPE(size_t, unsigned long)
@@ -1209,16 +1213,29 @@ if test "x$have_mmap" = "xno"; then
AC_CHECK_FUNCS([shmget shmat shmdt shmctl],[], [buffer=disabled]) AC_CHECK_FUNCS([shmget shmat shmdt shmctl],[], [buffer=disabled])
fi fi
term_type=none
# Check if system supports termios # Check if system supports termios
AC_SYS_POSIX_TERMIOS AC_SYS_POSIX_TERMIOS
AC_MSG_CHECKING([if we have wincon.h])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <windows.h>
#include <wincon.h>
void *v = &ReadConsoleInput;
])],[ac_cv_header_wincon_h=yes],[ac_cv_header_wincon_h=no])
AC_MSG_RESULT([$ac_cv_header_wincon_h])
AS_IF([test "x$ac_cv_header_wincon_h" = "xyes"],[],[AC_DEFINE([HAVE_WINCON_H],[1],[Define to 1 if you have the <wincon.h> header file.])])
term_type=none
if test "x$ac_cv_sys_posix_termios" = "xyes"; then if test "x$ac_cv_sys_posix_termios" = "xyes"; then
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1, AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
[Define this if you have the POSIX termios library]) [Define this if you have the POSIX termios library])
term_type=posix term_type=posix
elif test "x$ac_cv_header_windows_h" = "xyes" &&
test "x$ac_cv_header_wincon_h" = "xyes"; then
term_type=win32
fi fi
AC_CHECK_FUNCS( random ) AC_CHECK_FUNCS( random setenv unsetenv )
# Check for sched_setscheduler # Check for sched_setscheduler
AC_CHECK_FUNCS( sched_setscheduler setuid getuid) AC_CHECK_FUNCS( sched_setscheduler setuid getuid)
@@ -1292,13 +1309,6 @@ AC_SEARCH_LIBS(socket, socket)
AC_CHECK_FUNCS( getaddrinfo, [ have_ipv6=yes ], [ have_ipv6=no ] ) AC_CHECK_FUNCS( getaddrinfo, [ have_ipv6=yes ], [ have_ipv6=no ] )
# A Hack for MSVC builds by cmake: Disable largefile hackery.
# Maybe one time we support hat wretched environment directly, but
# for now configure lives in a world where large file support is
# properly defined and served by off_t.
BUILD_NO_LARGENAME=0
AC_SUBST(BUILD_NO_LARGENAME)
# Substitutions for the installable mpg123.h header # Substitutions for the installable mpg123.h header
if test "x$ac_cv_header_stdio_h" = "xyes"; then if test "x$ac_cv_header_stdio_h" = "xyes"; then
INCLUDE_STDIO_H="#include <stdio.h>" INCLUDE_STDIO_H="#include <stdio.h>"
@@ -1885,15 +1895,7 @@ int main(){
fi fi
;; ;;
sndio) sndio)
SNDIO_LIBS=-lsndio PKG_CHECK_MODULES(SNDIO, sndio, output_modules="$output_modules sndio" HAVE_SNDIO="yes", HAVE_SNDIO="no" check_failed=yes)
AC_CHECK_LIB([sndio], [sio_open],
[AC_CHECK_HEADERS([sndio.h],
[output_modules="$output_modules sndio" HAVE_SNDIO="yes"])
]
)
if test "x$HAVE_SNDIO" != xyes; then
check_failed=yes
fi
;; ;;
sun) sun)
AC_CHECK_HEADERS([sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h]) AC_CHECK_HEADERS([sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h])
@@ -2214,34 +2216,34 @@ fi
#for i in dummy tinyalsa alsa qsa coreaudio esd jack nas oss portaudio pulse sdl sndio sun win32 win32_wasapi aix alib arts hp os2 sgi mint openal #for i in dummy tinyalsa alsa qsa coreaudio esd jack nas oss portaudio pulse sdl sndio sun win32 win32_wasapi aix alib arts hp os2 sgi mint openal
#do echo $i; done | #do echo $i; done |
#perl -ne 'chomp; $big = uc($_); print <<EOT; #perl -ne 'chomp; $big = uc($_); print <<EOT;
#AM_CONDITIONAL([BUILD_${big}], [ test "$_" = \$default_output_module ]) #AM_CONDITIONAL([BUILD_${big}], [ test "$_" = "\$default_output_module" ])
#EOT #EOT
#' #'
AM_CONDITIONAL([BUILD_DUMMY], [ test "dummy" = $default_output_module ]) AM_CONDITIONAL([BUILD_DUMMY], [ test "dummy" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_TINYALSA], [ test "tinyalsa" = $default_output_module ]) AM_CONDITIONAL([BUILD_TINYALSA], [ test "tinyalsa" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_ALSA], [ test "alsa" = $default_output_module ]) AM_CONDITIONAL([BUILD_ALSA], [ test "alsa" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_QSA], [ test "qsa" = $default_output_module ]) AM_CONDITIONAL([BUILD_QSA], [ test "qsa" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_COREAUDIO], [ test "coreaudio" = $default_output_module ]) AM_CONDITIONAL([BUILD_COREAUDIO], [ test "coreaudio" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_ESD], [ test "esd" = $default_output_module ]) AM_CONDITIONAL([BUILD_ESD], [ test "esd" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_JACK], [ test "jack" = $default_output_module ]) AM_CONDITIONAL([BUILD_JACK], [ test "jack" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_NAS], [ test "nas" = $default_output_module ]) AM_CONDITIONAL([BUILD_NAS], [ test "nas" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_OSS], [ test "oss" = $default_output_module ]) AM_CONDITIONAL([BUILD_OSS], [ test "oss" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_PORTAUDIO], [ test "portaudio" = $default_output_module ]) AM_CONDITIONAL([BUILD_PORTAUDIO], [ test "portaudio" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_PULSE], [ test "pulse" = $default_output_module ]) AM_CONDITIONAL([BUILD_PULSE], [ test "pulse" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_SDL], [ test "sdl" = $default_output_module ]) AM_CONDITIONAL([BUILD_SDL], [ test "sdl" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_SNDIO], [ test "sndio" = $default_output_module ]) AM_CONDITIONAL([BUILD_SNDIO], [ test "sndio" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_SUN], [ test "sun" = $default_output_module ]) AM_CONDITIONAL([BUILD_SUN], [ test "sun" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_WIN32], [ test "win32" = $default_output_module ]) AM_CONDITIONAL([BUILD_WIN32], [ test "win32" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_WIN32_WASAPI], [ test "win32_wasapi" = $default_output_module ]) AM_CONDITIONAL([BUILD_WIN32_WASAPI], [ test "win32_wasapi" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_AIX], [ test "aix" = $default_output_module ]) AM_CONDITIONAL([BUILD_AIX], [ test "aix" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_ALIB], [ test "alib" = $default_output_module ]) AM_CONDITIONAL([BUILD_ALIB], [ test "alib" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_ARTS], [ test "arts" = $default_output_module ]) AM_CONDITIONAL([BUILD_ARTS], [ test "arts" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_HP], [ test "hp" = $default_output_module ]) AM_CONDITIONAL([BUILD_HP], [ test "hp" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_OS2], [ test "os2" = $default_output_module ]) AM_CONDITIONAL([BUILD_OS2], [ test "os2" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_SGI], [ test "sgi" = $default_output_module ]) AM_CONDITIONAL([BUILD_SGI], [ test "sgi" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_MINT], [ test "mint" = $default_output_module ]) AM_CONDITIONAL([BUILD_MINT], [ test "mint" = "$default_output_module" ])
AM_CONDITIONAL([BUILD_OPENAL], [ test "openal" = $default_output_module ]) AM_CONDITIONAL([BUILD_OPENAL], [ test "openal" = "$default_output_module" ])
default_modstring=`echo "$default_output_modules"|tr ' ' ,` default_modstring=`echo "$default_output_modules"|tr ' ' ,`
AC_DEFINE_UNQUOTED( DEFAULT_OUTPUT_MODULE, "$default_modstring", [The default audio output module(s) to use] ) AC_DEFINE_UNQUOTED( DEFAULT_OUTPUT_MODULE, "$default_modstring", [The default audio output module(s) to use] )
@@ -2577,7 +2579,10 @@ AC_ARG_ENABLE(network,
AC_MSG_CHECKING([for preferred network support]) AC_MSG_CHECKING([for preferred network support])
AC_ARG_WITH([network], AC_ARG_WITH([network],
[AS_HELP_STRING([--with-network=<type>], [Available options, depending on platform, are auto, none, internal, winhttp, wininet, and exec (wget or curl binaries).])], [AS_HELP_STRING([--with-network=<type>],
[Available options, depending on platform, are auto, none, internal, winhttp, wininet (or wininethttp for both), and exec (wget or curl binaries).
The internal code is always built in addition to external options for plain HTTP (esp. Shoutcast v1) support.
The external option is for HTTPS by default, but can be used for HTTP, too.])],
[ [
case "$withval" in case "$withval" in
exec) exec)
@@ -2592,6 +2597,10 @@ AC_ARG_WITH([network],
network_type="wininet" network_type="wininet"
AC_MSG_RESULT([wininet]) AC_MSG_RESULT([wininet])
;; ;;
wininethttp)
network_type="wininethttp"
AC_MSG_RESULT([wininethttp])
;;
internal) internal)
network_type="internal" network_type="internal"
AC_MSG_RESULT([internal]) AC_MSG_RESULT([internal])
@@ -2619,7 +2628,7 @@ if test x$network_type = xauto; then
if test "x$have_fork" = "xyes"; then if test "x$have_fork" = "xyes"; then
network_type=exec network_type=exec
elif test "x$win32_specific_codes" = "xenabled"; then elif test "x$win32_specific_codes" = "xenabled"; then
network_type=wininet network_type=wininethttp
elif test "x$have_network" = "xyes"; then elif test "x$have_network" = "xyes"; then
network_type="internal" network_type="internal"
else else
@@ -2635,7 +2644,7 @@ fi
if test x$network_type = xexec -a x$have_fork != xyes; then if test x$network_type = xexec -a x$have_fork != xyes; then
AC_MSG_ERROR([exec network support selected but fork not available]) AC_MSG_ERROR([exec network support selected but fork not available])
fi fi
if test x$network_type = xwininet -o x$network_type = xwinhttp && test x$win32_specific_codes != xenabled; then if test x$network_type = xwininet -o x$network_type = xwinhttp -o x$network_type = xwininethttp && test x$win32_specific_codes != xenabled; then
AC_MSG_ERROR([wininet or winhttp is currently only for Windows]) AC_MSG_ERROR([wininet or winhttp is currently only for Windows])
fi fi
@@ -2644,7 +2653,7 @@ AM_CONDITIONAL([WIN32_CODES], [ test "x$win32_specific_codes" = xenabled ])
if test x"$ipv6" = xauto; then if test x"$ipv6" = xauto; then
AC_MSG_CHECKING([IPv6 use]) AC_MSG_CHECKING([IPv6 use])
if test x"$have_ipv6" = xyes -a x"$network_type" = xinternal; then if test x"$have_ipv6" = xyes -a x"$network_type" != xdisabled; then
ipv6=enabled ipv6=enabled
else else
ipv6=disabled ipv6=disabled
@@ -2652,14 +2661,31 @@ if test x"$ipv6" = xauto; then
AC_MSG_RESULT([$ipv6]) AC_MSG_RESULT([$ipv6])
fi fi
if test x$network_type = xinternal -a x$network_internal = xwinsock2; then if test x$network_type != xdisabled -a x$network_internal = xwinsock2; then
AC_DEFINE([WANT_WIN32_SOCKETS], [1], [ Define to use Win32 sockets ]) AC_DEFINE([WANT_WIN32_SOCKETS], [1], [ Define to use Win32 sockets ])
fi fi
AM_CONDITIONAL([NETWORK_WINSOCK], [ test x$network_type = xinternal -a x$network_internal = xwinsock2 ]) AM_CONDITIONAL([NETWORK_WINSOCK], [ test x$network_type != xdisabled -a x$network_internal = xwinsock2 ])
AM_CONDITIONAL([NET123], [ test x$network_type != xdisabled ])
AM_CONDITIONAL([NET123_EXEC], [ test x$network_type = xexec ]) AM_CONDITIONAL([NET123_EXEC], [ test x$network_type = xexec ])
AM_CONDITIONAL([NET123_WINHTTP], [ test x$network_type = xwinhttp ]) AM_CONDITIONAL([NET123_WINHTTP], [ test x$network_type = xwinhttp || test x$network_type = xwininethttp ])
AM_CONDITIONAL([NET123_WININET], [ test x$network_type = xwininet ]) AM_CONDITIONAL([NET123_WININET], [ test x$network_type = xwininet || test x$network_type = xwininethttp ])
case "$network_type" in
exec)
AC_DEFINE(NET123_EXEC, 1, [ Define for executable-based networking (for HTTPS). ])
;;
winhttp)
AC_DEFINE(NET123_WINHTTP, 1, [ Define for winhttp networking (for HTTPS). ])
;;
wininet)
AC_DEFINE(NET123_WININET, 1, [ Define for wininet networking (for HTTPS). ])
;;
wininethttp)
AC_DEFINE(NET123_WININET, 1, [ Define for wininet networking (for HTTPS). ])
AC_DEFINE(NET123_WINHTTP, 1, [ Define for winhttp networking (for HTTPS). ])
;;
esac
dnl ############## Terminal choice dnl ############## Terminal choice
@@ -2685,7 +2711,7 @@ if test x"$fifo" = xenabled; then
fi fi
dnl ############## Network enable dnl ############## Network enable
if test x"$network_type" = xinternal; then if test x"$network_type" != xdisabled; then
AC_DEFINE(NETWORK, 1, [ Define if network support is enabled. ]) AC_DEFINE(NETWORK, 1, [ Define if network support is enabled. ])
if test x"$have_network" = xno; then if test x"$have_network" = xno; then
AC_MSG_WARN( [ You forced network code while I think there is support missing! ] ) AC_MSG_WARN( [ You forced network code while I think there is support missing! ] )
@@ -2742,9 +2768,11 @@ echo "
Extreme debugging ....... $xdebugging Extreme debugging ....... $xdebugging
Seek table size ......... $seektable Seek table size ......... $seektable
FIFO support ............ $fifo FIFO support ............ $fifo
Buffer .................. $buffer Buffer .................. $buffer"
Network (http streams) .. $network_type" if test x$network_type != xdisabled; then
if test x$network_type = xinternal; then if test x$network_type != xinternal; then
echo " External network ........ $network_type"
fi
echo " Internal network type ... $network_internal echo " Internal network type ... $network_internal
IPv6 (getaddrinfo) ...... $ipv6" IPv6 (getaddrinfo) ...... $ipv6"
fi fi

View File

@@ -421,6 +421,10 @@ Disable terminal control even if terminal is detected.
In an xterm, rxvt, screen, iris-ansi (compatible, TERM environment variable is examined), change the window's title to the name of song currently In an xterm, rxvt, screen, iris-ansi (compatible, TERM environment variable is examined), change the window's title to the name of song currently
playing. playing.
.TP .TP
\fB\-\^\-pauseloop \fIseconds
Set the length of the loop interval in terminal control paused mode, away from the default of 0.5 seconds, as a floating
point number.
.TP
\fB\-\^\-name \fIname \fB\-\^\-name \fIname
Set the name of this instance, possibly used in various places. This sets the client name for JACK output. Set the name of this instance, possibly used in various places. This sets the client name for JACK output.
.TP .TP

View File

@@ -3,7 +3,7 @@
# - devel packages for alsa, sdl, etc... to build the respective output modules. # - devel packages for alsa, sdl, etc... to build the respective output modules.
Summary: The fast console mpeg audio decoder/player. Summary: The fast console mpeg audio decoder/player.
Name: mpg123 Name: mpg123
Version: 1.30.2 Version: 1.31.0
Release: 1 Release: 1
URL: http://www.mpg123.org/ URL: http://www.mpg123.org/
License: GPL License: GPL

View File

@@ -11,15 +11,7 @@ sources); as the team lacks resource to test everything. But in any case,
the ports can provide a good starting point on the respective platform, to get the ports can provide a good starting point on the respective platform, to get
it to work with minimal fuzz. it to work with minimal fuzz.
- cmake: CMake build to get started on non-Unix-like platforms - cmake: CMake build to get started on non-Unix-like platforms, especially
- Delphi: mpg123_.pas for just libmpg123 on Windows
Unit for linking against libmpg123 (Win32, DLL).
...by Arthur Pires <arthurprs@gmail.com>
- Sony PSP: Sony_PSP/; building libmpg123 for the PSP (used for the MODO player). - Sony PSP: Sony_PSP/; building libmpg123 for the PSP (used for the MODO player).
...by Bastian Pflieger <wb@illogical.de> ...by Bastian Pflieger <wb@illogical.de>
- Xcode contains the project file for building and using libmpg123 with
Xcode for Mac and iOS (arm and simulator builds). Please add the
ports/Xcode folder to the header search path of your project so that
Xcode can find the right mpg123.h and config.h. Then drag the mpg123
Xcode project into your own project. Finally in your build target, build
phases, add mpg123-ios or mpg123-mac to the libraries to link.

View File

@@ -0,0 +1,7 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR "i686")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "c flags")
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -m32" CACHE STRING "asm flags")

View File

@@ -8,20 +8,25 @@ include(CheckSymbolExists)
include(CMakeDependentOption) include(CMakeDependentOption)
include(TestBigEndian) include(TestBigEndian)
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file("dirent.h" HAVE_DIRENT_H) check_include_file("dirent.h" HAVE_DIRENT_H)
check_include_file("dlfcn.h" HAVE_DLFCN_H) check_include_file("dlfcn.h" HAVE_DLFCN_H)
check_include_file("inttypes.h" HAVE_INTTYPES_H) check_include_file("inttypes.h" HAVE_INTTYPES_H)
check_include_file("langinfo.h" HAVE_LANGINFO_H) check_include_file("langinfo.h" HAVE_LANGINFO_H)
check_include_file("limits.h" HAVE_LIMITS_H) check_include_file("limits.h" HAVE_LIMITS_H)
check_include_file("locale.h" HAVE_LOCALE_H) check_include_file("locale.h" HAVE_LOCALE_H)
check_include_file("netdb.h" HAVE_NETDB_H)
check_include_file("netinet/in.h" HAVE_NETINET_IN_H)
check_include_file("sched.h" HAVE_SCHED_H) check_include_file("sched.h" HAVE_SCHED_H)
check_include_file("signal.h" HAVE_SIGNAL_H) check_include_file("signal.h" HAVE_SIGNAL_H)
check_include_file("stdio.h" HAVE_STDIO_H) check_include_file("stdio.h" HAVE_STDIO_H)
check_include_file("stdint.h" HAVE_STDINT_H) check_include_file("stdint.h" HAVE_STDINT_H)
check_include_file("stdlib.h" HAVE_STDLIB_H) check_include_file("stdlib.h" HAVE_STDLIB_H)
check_include_file("string.h" HAVE_STRING_H) check_include_file("string.h" HAVE_STRING_H)
check_include_file("strings.h" HAVE_STRINGS_H)
check_include_file("sys/ioctl.h" HAVE_SYS_IOCTL_H) check_include_file("sys/ioctl.h" HAVE_SYS_IOCTL_H)
check_include_file("sys/ipc.h" HAVE_SYS_IPC_H) check_include_file("sys/ipc.h" HAVE_SYS_IPC_H)
check_include_file("sys/param.h" HAVE_SYS_PARAM_H)
check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H) check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H)
check_include_file("sys/select.h" HAVE_SYS_SELECT_H) check_include_file("sys/select.h" HAVE_SYS_SELECT_H)
check_include_file("sys/shm.h" HAVE_SYS_SHM_H) check_include_file("sys/shm.h" HAVE_SYS_SHM_H)
@@ -46,6 +51,8 @@ check_function_exists(mkfifo HAVE_MKFIFO)
check_function_exists(mmap HAVE_MMAP) check_function_exists(mmap HAVE_MMAP)
check_function_exists(nl_langinfo HAVE_NL_LANGINFO) check_function_exists(nl_langinfo HAVE_NL_LANGINFO)
check_function_exists(random HAVE_RANDOM) check_function_exists(random HAVE_RANDOM)
check_function_exists(setenv HAVE_SETENV)
check_function_exists(unsetenv HAVE_UNSETENV)
check_function_exists(setlocale HAVE_SETLOCALE) check_function_exists(setlocale HAVE_SETLOCALE)
check_function_exists(setpriority HAVE_SETPRIORITY) check_function_exists(setpriority HAVE_SETPRIORITY)
check_function_exists(shmget HAVE_SHMGET) check_function_exists(shmget HAVE_SHMGET)
@@ -173,6 +180,10 @@ if(WIN32)
set(HAVE_MKFIFO ON) set(HAVE_MKFIFO ON)
endif() endif()
if(HAVE_NETDB_H AND HAVE_SYS_PARAM_H AND HAVE_SYS_SOCKET_H AND HAVE_NETINET_IN_H AND HAVE_ARPA_INET_H)
set(HAVE_NETWORK ON)
endif()
if(NO_MESSAGES) if(NO_MESSAGES)
set(NO_WARNING ON) set(NO_WARNING ON)
set(NO_ERRORMSG ON) set(NO_ERRORMSG ON)
@@ -313,6 +324,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -pedantic") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -pedantic")
endif() endif()
endif() endif()
cmake_dependent_option(NETWORK "network support (http streams / webradio)" ON "HAVE_NETWORK" OFF)
option(NEWOLD_WRITE_SAMPLE "enable new/old WRITE_SAMPLE macro for non-accurate 16 bit output, faster on certain CPUs (default on on x86-32)" OFF) option(NEWOLD_WRITE_SAMPLE "enable new/old WRITE_SAMPLE macro for non-accurate 16 bit output, faster on certain CPUs (default on on x86-32)" OFF)
cmake_dependent_option(NO_BUFFER "enable audio buffer code (default uses system whitelist... proper checks later)" OFF "HAVE_MMAP OR HAVE_SYS_IPC_H AND HAVE_SYS_SHM_H AND HAVE_SHMGET AND HAVE_SHMAT AND HAVE_SHMDT AND HAVE_SHMCTL" ON) cmake_dependent_option(NO_BUFFER "enable audio buffer code (default uses system whitelist... proper checks later)" OFF "HAVE_MMAP OR HAVE_SYS_IPC_H AND HAVE_SYS_SHM_H AND HAVE_SHMGET AND HAVE_SHMAT AND HAVE_SHMDT AND HAVE_SHMCTL" ON)
option(NO_DOWNSAMPLE "no downsampled decoding" OFF) option(NO_DOWNSAMPLE "no downsampled decoding" OFF)
@@ -342,7 +354,6 @@ option(SYN123_NO_CASES "include special cases for likely parameter values (chann
cmake_dependent_option(USE_MODULES "dynamically loadable output modules" ON "BUILD_SHARED_LIBS;HAVE_WIN_DL OR HAVE_UNIX_DL" OFF) cmake_dependent_option(USE_MODULES "dynamically loadable output modules" ON "BUILD_SHARED_LIBS;HAVE_WIN_DL OR HAVE_UNIX_DL" OFF)
option(USE_NEW_HUFFTABLE "use new huffman decoding scheme by Taihei (faster on modern CPUs at least, so on by default)" ON) option(USE_NEW_HUFFTABLE "use new huffman decoding scheme by Taihei (faster on modern CPUs at least, so on by default)" ON)
configure_file(config.cmake.h.in config.h)
include_directories( include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/../../../src/" "${CMAKE_CURRENT_SOURCE_DIR}/../../../src/"
@@ -370,7 +381,7 @@ if(UNIX)
if(BUILD_PROGRAMS) if(BUILD_PROGRAMS)
if(HAVE_FORK AND HAVE_EXECVP) if(HAVE_FORK AND HAVE_EXECVP AND NETWORK)
set(NET123 ON) set(NET123 ON)
set(NET123_EXEC ON) set(NET123_EXEC ON)
endif() endif()
@@ -449,3 +460,5 @@ if(UNIX)
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/") RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}/")
endif() endif()
endif() endif()
configure_file(config.cmake.h.in config.h)

View File

@@ -43,6 +43,7 @@
#cmakedefine HAVE_STDLIB_H 1 #cmakedefine HAVE_STDLIB_H 1
#cmakedefine HAVE_STRERROR 1 #cmakedefine HAVE_STRERROR 1
#cmakedefine HAVE_STRING_H 1 #cmakedefine HAVE_STRING_H 1
#cmakedefine HAVE_STRINGS_H 1
#cmakedefine HAVE_SYS_IOCTL_H 1 #cmakedefine HAVE_SYS_IOCTL_H 1
#cmakedefine HAVE_SYS_RESOURCE_H 1 #cmakedefine HAVE_SYS_RESOURCE_H 1
#cmakedefine HAVE_SYS_SELECT_H 1 #cmakedefine HAVE_SYS_SELECT_H 1
@@ -69,9 +70,13 @@
#define LFS_ALIAS_BITS @LFS_ALIAS_BITS@ #define LFS_ALIAS_BITS @LFS_ALIAS_BITS@
#define LT_MODULE_EXT "@CMAKE_SHARED_MODULE_SUFFIX@" #define LT_MODULE_EXT "@CMAKE_SHARED_MODULE_SUFFIX@"
// Define if network support is enabled.
#cmakedefine NETWORK 1
// Define for new-style network code. // Define for new-style network code.
#cmakedefine NET123 1 #cmakedefine NET123 1
#cmakedefine #cmakedefine NET123_EXEC 1
#cmakedefine NET123_WINHTTP 1
#cmakedefine NET123_WININET 1
// Define to disable downsampled decoding. // Define to disable downsampled decoding.
#cmakedefine NO_DOWNSAMPLE 1 #cmakedefine NO_DOWNSAMPLE 1

View File

@@ -214,6 +214,9 @@ endif()
set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME mpg123) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME mpg123)
target_compile_definitions(${TARGET} PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC>)
target_compile_definitions(${TARGET} PRIVATE target_compile_definitions(${TARGET} PRIVATE
${PLATFORM_DEFINITIONS} ${PLATFORM_DEFINITIONS}
$<$<BOOL:${HAVE_FPU}>:REAL_IS_FLOAT> $<$<BOOL:${HAVE_FPU}>:REAL_IS_FLOAT>

View File

@@ -118,17 +118,21 @@ if TERM_NONE
src_mpg123_SOURCES += src/term_none.c src_mpg123_SOURCES += src/term_none.c
endif endif
if NET123
src_mpg123_SOURCES += src/net123.h
endif
if NET123_EXEC if NET123_EXEC
src_mpg123_SOURCES += src/net123.h src/net123_exec.c src_mpg123_SOURCES += src/net123_exec.c
endif endif
if NET123_WINHTTP if NET123_WINHTTP
src_mpg123_SOURCES += src/net123.h src/net123_winhttp.c src_mpg123_SOURCES += src/net123_winhttp.c
src_mpg123_LDADD += -lwinhttp src_mpg123_LDADD += -lwinhttp
endif endif
if NET123_WININET if NET123_WININET
src_mpg123_SOURCES += src/net123.h src/net123_wininet.c src_mpg123_SOURCES += src/net123_wininet.c
src_mpg123_LDADD += -lwininet src_mpg123_LDADD += -lwininet
endif endif

View File

@@ -179,7 +179,6 @@ void print_stat(mpg123_handle *fr, long offset, out123_handle *ao, int draw_bar
off_t rframes; off_t rframes;
int spf; int spf;
double basevol, realvol; double basevol, realvol;
char *icy;
long rate; long rate;
int framesize; int framesize;
struct mpg123_frameinfo mi; struct mpg123_frameinfo mi;
@@ -222,7 +221,8 @@ void print_stat(mpg123_handle *fr, long offset, out123_handle *ao, int draw_bar
/* Some sensible logic around offsets and time. /* Some sensible logic around offsets and time.
Buffering makes the relationships between the numbers non-trivial. */ Buffering makes the relationships between the numbers non-trivial. */
rframes = frames-frame; rframes = frames-frame;
elapsed = decoded + offset*spf - buffered; /* May be negative, a countdown. */ // May be negative, a countdown. Buffer only confuses in paused (looping) mode, though.
elapsed = decoded + offset*spf - (paused ? 0 : buffered);
remain = elapsed > 0 ? length - elapsed : length; remain = elapsed > 0 ? length - elapsed : length;
if( MPG123_OK == mpg123_info(fr, &mi) if( MPG123_OK == mpg123_info(fr, &mi)
&& MPG123_OK == mpg123_getvolume(fr, &basevol, &realvol, NULL) ) && MPG123_OK == mpg123_getvolume(fr, &basevol, &realvol, NULL) )

View File

@@ -187,6 +187,9 @@
/* Define to 1 if you have the `sched_setscheduler' function. */ /* Define to 1 if you have the `sched_setscheduler' function. */
#undef HAVE_SCHED_SETSCHEDULER #undef HAVE_SCHED_SETSCHEDULER
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the `setlocale' function. */ /* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE #undef HAVE_SETLOCALE
@@ -214,9 +217,6 @@
/* Define to 1 if you have the <signal.h> header file. */ /* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H #undef HAVE_SIGNAL_H
/* Define to 1 if you have the <sndio.h> header file. */
#undef HAVE_SNDIO_H
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H #undef HAVE_STDINT_H
@@ -289,6 +289,9 @@
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
/* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV
/* Define to 1 if you have the <wchar.h> header file. */ /* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H #undef HAVE_WCHAR_H
@@ -301,6 +304,9 @@
/* Define to 1 if you have the <wctype.h> header file. */ /* Define to 1 if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H #undef HAVE_WCTYPE_H
/* Define to 1 if you have the <wincon.h> header file. */
#undef HAVE_WINCON_H
/* Define to 1 if you have the <windows.h> header file. */ /* Define to 1 if you have the <windows.h> header file. */
#undef HAVE_WINDOWS_H #undef HAVE_WINDOWS_H
@@ -338,6 +344,15 @@
/* Define to for new net123 network stack. */ /* Define to for new net123 network stack. */
#undef NET123 #undef NET123
/* Define for executable-based networking (for HTTPS). */
#undef NET123_EXEC
/* Define for winhttp networking (for HTTPS). */
#undef NET123_WINHTTP
/* Define for wininet networking (for HTTPS). */
#undef NET123_WININET
/* Define if network support is enabled. */ /* Define if network support is enabled. */
#undef NETWORK #undef NETWORK

View File

@@ -435,6 +435,10 @@ int control_generic (mpg123_handle *fr)
} }
#endif #endif
// Persist over loop iterations to remember unfinished commands.
char buf[REMOTE_BUFFER_SIZE]; // command buffer
short int last_len = 0; // length of partial command in there
while (alive) while (alive)
{ {
tv.tv_sec = 0; tv.tv_sec = 0;
@@ -510,16 +514,15 @@ int control_generic (mpg123_handle *fr)
short int len = 1; /* length of buffer */ short int len = 1; /* length of buffer */
char *cmd, *arg; /* variables for parsing, */ char *cmd, *arg; /* variables for parsing, */
char *comstr = NULL; /* gcc thinks that this could be used uninitialited... */ char *comstr = NULL; /* gcc thinks that this could be used uninitialited... */
char buf[REMOTE_BUFFER_SIZE];
short int counter; short int counter;
char *next_comstr = buf; /* have it initialized for first command */ char *next_comstr = buf; /* have it initialized for first command */
/* read as much as possible, maybe multiple commands */ /* read as much as possible, maybe multiple commands */
/* When there is nothing to read (EOF) or even an error, it is the end */ /* When there is nothing to read (EOF) or even an error, it is the end */
#ifdef WANT_WIN32_FIFO #ifdef WANT_WIN32_FIFO
len = win32_fifo_read(buf,REMOTE_BUFFER_SIZE); len = win32_fifo_read(buf+last_len,REMOTE_BUFFER_SIZE-last_len);
#else #else
len = read(control_file, buf, REMOTE_BUFFER_SIZE); len = read(control_file, buf+last_len, REMOTE_BUFFER_SIZE-last_len);
#endif #endif
if(len < 1) if(len < 1)
{ {
@@ -542,7 +545,9 @@ int control_generic (mpg123_handle *fr)
} }
debug1("read %i bytes of commands", len); debug1("read %i bytes of commands", len);
len += last_len; // on top of remembered piece
/* one command on a line - separation by \n -> C strings in a row */ /* one command on a line - separation by \n -> C strings in a row */
last_len = 0;
for(counter = 0; counter < len; ++counter) for(counter = 0; counter < len; ++counter)
{ {
/* line end is command end */ /* line end is command end */
@@ -746,7 +751,6 @@ int control_generic (mpg123_handle *fr)
/* Simple EQ: SEQ <BASS> <MID> <TREBLE> */ /* Simple EQ: SEQ <BASS> <MID> <TREBLE> */
if (!strcasecmp(cmd, "SEQ")) { if (!strcasecmp(cmd, "SEQ")) {
double b,m,t; double b,m,t;
int cn;
if(sscanf(arg, "%lf %lf %lf", &b, &m, &t) == 3) if(sscanf(arg, "%lf %lf %lf", &b, &m, &t) == 3)
{ {
mpg123_eq_bands(fr, MPG123_LR, 0, 0, b); mpg123_eq_bands(fr, MPG123_LR, 0, 0, b);
@@ -891,7 +895,7 @@ int control_generic (mpg123_handle *fr)
if (!strcasecmp(cmd, "LP") || !strcasecmp(cmd, "LOADPAUSED")){ generic_load(fr, arg, MODE_PAUSED); continue; } if (!strcasecmp(cmd, "LP") || !strcasecmp(cmd, "LOADPAUSED")){ generic_load(fr, arg, MODE_PAUSED); continue; }
/* no command matched */ /* no command matched */
generic_sendstr(0, "E Unknown command: %s", cmd); generic_send2str(0, "E Unknown command with arguments: %s %s", cmd, arg);
} /* end commands with arguments */ } /* end commands with arguments */
else generic_sendstr( 0, "E Unknown command or no arguments: %s" else generic_sendstr( 0, "E Unknown command or no arguments: %s"
, comstr ); , comstr );
@@ -899,30 +903,19 @@ int control_generic (mpg123_handle *fr)
} /* end of single command processing */ } /* end of single command processing */
} /* end of scanning the command buffer */ } /* end of scanning the command buffer */
/* // Last character not nulled if we did not use all command text.
when last command had no \n... should I discard it?
Ideally, I should remember the part and wait for next
read() to get the rest up to a \n. But that can go
to infinity. Too long commands too quickly are just
bad. Cannot/Won't change that. So, discard the unfinished
command and have fingers crossed that the rest of this
unfinished one qualifies as "unknown".
*/
if(buf[len-1] != 0) if(buf[len-1] != 0)
{ {
// All that jazz because I did not reserve space for a zero. if(next_comstr == buf && len == REMOTE_BUFFER_SIZE)
char *last_command;
size_t last_len = len-(size_t)(next_comstr-buf);
last_command = malloc(last_len+1);
if(last_command)
{ {
memcpy(last_command, next_comstr, last_len); generic_sendmsg("E Too long command, cannot parse.");
last_command[last_len] = 0; // Just skipping it, provoking further parsing erros, but maybe not fatal.
generic_sendstr(0, "E Unfinished command: %s", last_command); } else
free(last_command); {
last_len = len-(short)(next_comstr-buf);
mdebug("keeping %d bytes of old command", last_len);
memmove(buf, next_comstr, last_len);
} }
else
generic_sendmsg("E Unfinished command: <DOOM>");
} }
} /* end command reading & processing */ } /* end command reading & processing */
} /* end main (alive) loop */ } /* end main (alive) loop */

View File

@@ -106,15 +106,29 @@ static int performoption (int argc, char *argv[], topt *opt, topt *opts)
return (GLO_NOARG); return (GLO_NOARG);
loptarg = argv[loptind++]+loptchr; loptarg = argv[loptind++]+loptchr;
loptchr = 0; loptchr = 0;
errno = 0;
if (opt->var) { if (opt->var) {
char *endptr = NULL;
if (opt->flags & GLO_CHAR) /* var is *char */ if (opt->flags & GLO_CHAR) /* var is *char */
setcharoption(opt, loptarg); setcharoption(opt, loptarg);
else if(opt->flags & GLO_LONG) else if(opt->flags & (GLO_LONG | GLO_INT))
*((long *) opt->var) = atol(loptarg); {
else if(opt->flags & GLO_INT) long val = strtol(loptarg, &endptr, 10);
*((int *) opt->var) = atoi(loptarg); if(errno || endptr == loptarg || (endptr && *endptr))
return GLO_BADARG;
if(opt->flags & GLO_LONG)
*((long *) opt->var) = val;
else if(val <= INT_MAX && val >= INT_MIN)
*((int *) opt->var) = val;
else
return GLO_BADARG;
}
else if(opt->flags & GLO_DOUBLE) else if(opt->flags & GLO_DOUBLE)
*((double *) opt->var) = atof(loptarg); {
*((double *) opt->var) = strtod(loptarg, &endptr);
if(errno || endptr == loptarg || (endptr && *endptr))
return GLO_BADARG;
}
else prog_error(); else prog_error();
} }
#if 0 /* Oliver: What was this for?! --ThOr */ #if 0 /* Oliver: What was this for?! --ThOr */

View File

@@ -66,6 +66,7 @@ for .... no flag) */
#define GLO_UNKNOWN -1 #define GLO_UNKNOWN -1
#define GLO_NOARG -2 #define GLO_NOARG -2
#define GLO_CONTINUE -3 #define GLO_CONTINUE -3
#define GLO_BADARG -4
int getlopt (int argc, char *argv[], topt *opts); int getlopt (int argc, char *argv[], topt *opts);
// Helper to set a char parameter, avoiding memory leaks. // Helper to set a char parameter, avoiding memory leaks.

View File

@@ -153,74 +153,6 @@ debunk_result:
#ifdef NETWORK #ifdef NETWORK
#if !defined (WANT_WIN32_SOCKETS)
static int writestring (int fd, mpg123_string *string)
{
size_t result, bytes;
char *ptr = string->p;
bytes = string->fill ? string->fill-1 : 0;
while(bytes)
{
result = write(fd, ptr, bytes);
if(result < 0 && errno != EINTR)
{
merror("writing http string: %s", strerror(errno));
return FALSE;
}
else if(result == 0)
{
error("write: socket closed unexpectedly");
return FALSE;
}
ptr += result;
bytes -= result;
}
return TRUE;
}
static size_t readstring (mpg123_string *string, size_t maxlen, int fd)
{
int err;
debug2("Attempting readstring on %d for %"SIZE_P" bytes", fd, (size_p)maxlen);
string->fill = 0;
while(maxlen == 0 || string->fill < maxlen)
{
if(string->size-string->fill < 1)
if(!mpg123_grow_string(string, string->fill+4096))
{
error("Cannot allocate memory for reading.");
string->fill = 0;
return 0;
}
err = read(fd,string->p+string->fill,1);
/* Whoa... reading one byte at a time... one could ensure the line break in another way, but more work. */
if( err == 1)
{
string->fill++;
if(string->p[string->fill-1] == '\n') break;
}
else if(errno != EINTR)
{
error("Error reading from socket or unexpected EOF.");
string->fill = 0;
/* bail out to prevent endless loop */
return 0;
}
}
if(!mpg123_grow_string(string, string->fill+1))
{
string->fill=0;
}
else
{
string->p[string->fill] = 0;
string->fill++;
}
return string->fill;
}
#endif /* WANT_WIN32_SOCKETS */
void encode64 (char *source,char *destination) void encode64 (char *source,char *destination)
{ {
@@ -383,11 +315,10 @@ int translate_url(const char *url, mpg123_string *purl)
return TRUE; return TRUE;
} }
int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *port, mpg123_string *httpauth1, int *try_without_port) int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *port, mpg123_string *httpauth1, const char * const *client_head)
{ {
char* ttemp; char* ttemp;
int ret = TRUE; int ret = TRUE;
const char *icy = param.talk_icy ? icy_yes : icy_no;
/* hm, my test redirection had troubles with line break before HTTP/1.0 */ /* hm, my test redirection had troubles with line break before HTTP/1.0 */
if((ttemp = strchr(request->p,'\r')) != NULL){ *ttemp = 0; request->fill = ttemp-request->p+1; } if((ttemp = strchr(request->p,'\r')) != NULL){ *ttemp = 0; request->fill = ttemp-request->p+1; }
@@ -405,26 +336,14 @@ int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *por
if(host->fill) if(host->fill)
{ /* Give virtual hosting a chance... adding the "Host: ... " line. */ { /* Give virtual hosting a chance... adding the "Host: ... " line. */
debug2("Host: %s:%s", host->p, port->p); debug2("Host: %s:%s", host->p, port->p);
if( mpg123_add_string(request, "Host: ") if(!( mpg123_add_string(request, "Host: ")
&& mpg123_add_string(request, host->p) && mpg123_add_string(request, host->p)
&& ( *try_without_port || ( && mpg123_add_string(request, ":")
mpg123_add_string(request, ":") && mpg123_add_string(request, port->p)
&& mpg123_add_string(request, port->p) )) && mpg123_add_string(request, "\r\n") ))
&& mpg123_add_string(request, "\r\n") ) return FALSE;
{
if(*try_without_port) *try_without_port = 0;
}
else return FALSE;
} }
/* Acceptance, stream setup. */
if( !append_accept(request)
|| !mpg123_add_string(request, "\r\n")
|| !mpg123_add_string(request, CONN_HEAD)
|| !mpg123_add_string(request, icy)
|| !mpg123_add_string(request, "\r\n") )
return FALSE;
/* Authorization. */ /* Authorization. */
if (httpauth1->fill || param.httpauth) { if (httpauth1->fill || param.httpauth) {
char *buf; char *buf;
@@ -456,72 +375,30 @@ int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *por
free(buf); /* Watch out for leaking if you introduce returns before this line. */ free(buf); /* Watch out for leaking if you introduce returns before this line. */
} }
while(ret && *client_head)
{
ret = mpg123_add_string(request, *client_head);
if(ret)
ret = mpg123_add_string(request, "\r\n");
++client_head;
}
if(ret) ret = mpg123_add_string(request, "\r\n"); if(ret) ret = mpg123_add_string(request, "\r\n");
return ret; return ret;
} }
#if !defined (WANT_WIN32_SOCKETS)
static int resolve_redirect(mpg123_string *response, mpg123_string *request_url, mpg123_string *purl)
{
debug1("request_url:%s", request_url->p);
/* initialized with full old url */
if(!mpg123_copy_string(request_url, purl)) return FALSE;
/* We may strip it down to a prefix ot totally. */ int http_open(const char* url, struct httpdata *hd, const char * const *client_head)
if(strncasecmp(response->p, "Location: http://", 17))
{ /* OK, only partial strip, need prefix for relative path. */
char* ptmp = NULL;
/* though it's not RFC (?), accept relative URIs as wget does */
fprintf(stderr, "NOTE: no complete URL in redirect, constructing one\n");
/* not absolute uri, could still be server-absolute */
/* I prepend a part of the request... out of the request */
if(response->p[10] == '/')
{
/* only prepend http://server/ */
/* I null the first / after http:// */
ptmp = strchr(purl->p+7,'/');
if(ptmp != NULL){ purl->fill = ptmp-purl->p+1; purl->p[purl->fill-1] = 0; }
}
else
{
/* prepend http://server/path/ */
/* now we want the last / */
ptmp = strrchr(purl->p+7, '/');
if(ptmp != NULL){ purl->fill = ptmp-purl->p+2; purl->p[purl->fill-1] = 0; }
}
}
else purl->fill = 0;
debug1("prefix=%s", purl->fill ? purl->p : "");
if(!mpg123_add_string(purl, response->p+10)) return FALSE;
debug1(" purl: %s", purl->p);
debug1("old request_url: %s", request_url->p);
return TRUE;
}
int http_open(const char* url, struct httpdata *hd)
{ {
mpg123_string purl, host, port, path; mpg123_string purl, host, port, path;
mpg123_string request, response, request_url; mpg123_string request, request_url;
mpg123_string httpauth1; mpg123_string httpauth1;
int sock = -1; int sock = -1;
int oom = 0; int oom = 0;
int relocate, numrelocs = 0;
int got_location = FALSE;
/*
workaround for http://www.global24music.com/rautemusik/files/extreme/isdn.pls
this site's apache gives me a relocation to the same place when I give the port in Host request field
for the record: Apache/2.0.51 (Fedora)
*/
int try_without_port = 0;
mpg123_init_string(&purl); mpg123_init_string(&purl);
mpg123_init_string(&host); mpg123_init_string(&host);
mpg123_init_string(&port); mpg123_init_string(&port);
mpg123_init_string(&path); mpg123_init_string(&path);
mpg123_init_string(&request); mpg123_init_string(&request);
mpg123_init_string(&response);
mpg123_init_string(&request_url); mpg123_init_string(&request_url);
mpg123_init_string(&httpauth1); mpg123_init_string(&httpauth1);
@@ -533,26 +410,6 @@ int http_open(const char* url, struct httpdata *hd)
/* Don't confuse the different auth strings... */ /* Don't confuse the different auth strings... */
if(!split_url(&purl, &httpauth1, NULL, NULL, NULL) ){ oom=1; goto exit; } if(!split_url(&purl, &httpauth1, NULL, NULL, NULL) ){ oom=1; goto exit; }
/* "GET http://" 11
* " HTTP/1.0\r\nUser-Agent: <PACKAGE_NAME>/<PACKAGE_VERSION>\r\n"
* 26 + PACKAGE_NAME + PACKAGE_VERSION
* accept header + accept_length()
* "Authorization: Basic \r\n" 23
* "\r\n" 2
* ... plus the other predefined header lines
*/
/* Just use this estimate as first guess to reduce malloc calls in string library. */
{
size_t length_estimate = 62 + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION)
+ accept_length() + strlen(CONN_HEAD) + strlen(icy_yes) + purl.fill;
if( !mpg123_grow_string(&request, length_estimate)
|| !mpg123_grow_string(&response,4096) )
{
oom=1; goto exit;
}
}
do
{ {
/* Storing the request url, with http:// prepended if needed. */ /* Storing the request url, with http:// prepended if needed. */
/* used to be url here... seemed wrong to me (when loop advanced...) */ /* used to be url here... seemed wrong to me (when loop advanced...) */
@@ -585,7 +442,7 @@ int http_open(const char* url, struct httpdata *hd)
} }
} }
if(!fill_request(&request, &host, &port, &httpauth1, &try_without_port)){ oom=1; goto exit; } if(!fill_request(&request, &host, &port, &httpauth1, client_head)){ oom=1; goto exit; }
httpauth1.fill = 0; /* We use the auth data from the URL only once. */ httpauth1.fill = 0; /* We use the auth data from the URL only once. */
if (hd->proxystate >= PROXY_HOST) if (hd->proxystate >= PROXY_HOST)
@@ -599,7 +456,11 @@ int http_open(const char* url, struct httpdata *hd)
} }
} }
debug2("attempting to open_connection to %s:%s", host.p, port.p); debug2("attempting to open_connection to %s:%s", host.p, port.p);
#ifdef WANT_WIN32_SOCKETS
sock = win32_net_open_connection(&host, &port);
#else
sock = open_connection(&host, &port); sock = open_connection(&host, &port);
#endif
if(sock < 0) if(sock < 0)
{ {
error1("Unable to establish connection to %s", host.fill ? host.p : ""); error1("Unable to establish connection to %s", host.fill ? host.p : "");
@@ -608,96 +469,14 @@ int http_open(const char* url, struct httpdata *hd)
#define http_failure close(sock); sock=-1; goto exit; #define http_failure close(sock); sock=-1; goto exit;
if(param.verbose > 2) fprintf(stderr, "HTTP request:\n%s\n",request.p); if(param.verbose > 2) fprintf(stderr, "HTTP request:\n%s\n",request.p);
if(!writestring(sock, &request)){ http_failure; } #ifdef WANT_WIN32_SOCKETS
relocate = FALSE; if(!win32_net_writestring (sock, &request))
/* Arbitrary length limit here... */ #else
#define safe_readstring \ if(unintr_write(sock, request.p, request.fill-1) != request.fill-1)
readstring(&response, SIZE_MAX/16, sock); \ #endif
if(response.fill > SIZE_MAX/16) /* > because of appended zero. */ \
{ \
error("HTTP response line exceeds max. length"); \
http_failure; \
} \
else if(response.fill == 0) \
{ \
error("readstring failed"); \
http_failure; \
} \
if(param.verbose > 2) fprintf(stderr, "HTTP in: %s", response.p);
safe_readstring;
{ {
char *sptr; http_failure;
if((sptr = strchr(response.p, ' ')))
{
if(response.fill > sptr-response.p+2)
switch (sptr[1])
{
case '3':
relocate = TRUE;
case '2':
break;
default:
fprintf (stderr, "HTTP request failed: %s", sptr+1); /* '\n' is included */
http_failure;
}
else{ error("Too short response,"); http_failure; }
}
} }
/* If we are relocated, we need to look out for a Location header. */
got_location = FALSE;
do
{
safe_readstring; /* Think about that: Should we really error out when we get nothing? Could be that the server forgot the trailing empty line... */
if (!strncasecmp(response.p, "Location: ", 10))
{ /* It is a redirection! */
if(!resolve_redirect(&response, &request_url, &purl)){ oom=1, http_failure; }
if(!strcmp(purl.p, request_url.p))
{
warning("relocated to very same place! trying request again without host port");
try_without_port = 1;
}
got_location = TRUE;
}
else
{ /* We got a header line (or the closing empty line). */
char *tmp;
debug1("searching for header values... %s", response.p);
/* Not sure if I want to bail out on error here. */
/* Also: What text encoding are these strings in? Doesn't need to be plain ASCII... */
get_header_string(&response, "content-type", &hd->content_type);
get_header_string(&response, "icy-name", &hd->icy_name);
get_header_string(&response, "icy-url", &hd->icy_url);
/* watch out for icy-metaint */
if((tmp = get_header_val("icy-metaint", &response)))
{
hd->icy_interval = (off_t) atol(tmp); /* atoll ? */
debug1("got icy-metaint %li", (long int)hd->icy_interval);
}
}
} while(response.p[0] != '\r' && response.p[0] != '\n');
if(relocate)
{
close(sock);
sock = -1;
/* Forget content type, might just relate to a displayed error page,
not the resource being redirected to. */
mpg123_free_string(&hd->content_type);
mpg123_init_string(&hd->content_type);
}
} while(relocate && got_location && purl.fill && numrelocs++ < HTTP_MAX_RELOCATIONS);
if(relocate)
{
if(!got_location)
error("Server meant to redirect but failed to provide a location!");
else
error1("Too many HTTP relocations (%i).", numrelocs);
http_failure;
} }
exit: /* The end as well as the exception handling point... */ exit: /* The end as well as the exception handling point... */
@@ -708,22 +487,10 @@ exit: /* The end as well as the exception handling point... */
mpg123_free_string(&port); mpg123_free_string(&port);
mpg123_free_string(&path); mpg123_free_string(&path);
mpg123_free_string(&request); mpg123_free_string(&request);
mpg123_free_string(&response);
mpg123_free_string(&request_url); mpg123_free_string(&request_url);
mpg123_free_string(&httpauth1); mpg123_free_string(&httpauth1);
return sock; return sock;
} }
#endif /*WANT_WIN32_SOCKETS*/
#else /* NETWORK */
/* stub */
int http_open (const char* url, struct httpdata *hd)
{
if(!param.quiet)
error("HTTP support not built in.");
return -1;
}
#endif #endif
/* EOF */ /* EOF */

View File

@@ -49,20 +49,17 @@ int debunk_mime(const char* mime);
int proxy_init(struct httpdata *hd); int proxy_init(struct httpdata *hd);
int translate_url(const char *url, mpg123_string *purl); int translate_url(const char *url, mpg123_string *purl);
size_t accept_length(void); size_t accept_length(void);
int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *port, mpg123_string *httpauth1, int *try_without_port); int fill_request(mpg123_string *request, mpg123_string *host, mpg123_string *port, mpg123_string *httpauth1, const char * const *client_head);
void get_header_string(mpg123_string *response, const char *fieldname, mpg123_string *store); void get_header_string(mpg123_string *response, const char *fieldname, mpg123_string *store);
char *get_header_val(const char *hname, mpg123_string *response); char *get_header_val(const char *hname, mpg123_string *response);
/* needed for HTTP/1.1 non-pipelining mode */
/* #define CONN_HEAD "Connection: close\r\n" */
#define CONN_HEAD ""
#define icy_yes "Icy-MetaData: 1" #define icy_yes "Icy-MetaData: 1"
#define icy_no "Icy-MetaData: 0" #define icy_no "Icy-MetaData: 0"
// Append an accept header line to the string, without line end. // Append an accept header line to the string, without line end.
int append_accept(mpg123_string *s); int append_accept(mpg123_string *s);
/* takes url and content type string address, opens resource, returns fd for data, allocates and sets content type */ // Open HTTP URL with internal network code.
extern int http_open (const char* url, struct httpdata *hd); int http_open(const char* url, struct httpdata *hd, const char * const *client_head);
#endif #endif

View File

@@ -16,6 +16,7 @@
#define compat_fdopen INT123_compat_fdopen #define compat_fdopen INT123_compat_fdopen
#define compat_close INT123_compat_close #define compat_close INT123_compat_close
#define compat_fclose INT123_compat_fclose #define compat_fclose INT123_compat_fclose
#define compat_binmode INT123_compat_binmode
#define win32_wide_utf8 INT123_win32_wide_utf8 #define win32_wide_utf8 INT123_win32_wide_utf8
#define win32_wide_utf7 INT123_win32_wide_utf7 #define win32_wide_utf7 INT123_win32_wide_utf7
#define win32_utf8_wide INT123_win32_utf8_wide #define win32_utf8_wide INT123_win32_utf8_wide
@@ -277,9 +278,6 @@
#define buffer_drop INT123_buffer_drop #define buffer_drop INT123_buffer_drop
#define buffer_write INT123_buffer_write #define buffer_write INT123_buffer_write
#define buffer_fill INT123_buffer_fill #define buffer_fill INT123_buffer_fill
#define read_buf INT123_read_buf
#define xfer_write_string INT123_xfer_write_string
#define xfer_read_string INT123_xfer_read_string
#define xfermem_init INT123_xfermem_init #define xfermem_init INT123_xfermem_init
#define xfermem_init_writer INT123_xfermem_init_writer #define xfermem_init_writer INT123_xfermem_init_writer
#define xfermem_init_reader INT123_xfermem_init_reader #define xfermem_init_reader INT123_xfermem_init_reader
@@ -304,8 +302,6 @@
#define raw_formats INT123_raw_formats #define raw_formats INT123_raw_formats
#define wav_formats INT123_wav_formats #define wav_formats INT123_wav_formats
#define wav_drain INT123_wav_drain #define wav_drain INT123_wav_drain
#define write_parameters INT123_write_parameters
#define read_parameters INT123_read_parameters
#define stringlists_add INT123_stringlists_add #define stringlists_add INT123_stringlists_add
#define check_neon INT123_check_neon #define check_neon INT123_check_neon
#define dct64_3dnow INT123_dct64_3dnow #define dct64_3dnow INT123_dct64_3dnow

View File

@@ -35,7 +35,9 @@
ASM_NAME(dct36_3dnow): ASM_NAME(dct36_3dnow):
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
#if defined(PIC) && defined(__APPLE__) // Not entirely sure about this PIC_GLOBAL_PTR here, but this is highly
// irrelevant, anyway. Anyone building 3DNow code for Android or Apple systems?
#ifdef PIC_GLOBAL_PTR
sub $4,%esp sub $4,%esp
#endif #endif
pushl %esi pushl %esi
@@ -45,7 +47,7 @@ ASM_NAME(dct36_3dnow):
#define _EBX_ %edi #define _EBX_ %edi
PREPARE_GOT PREPARE_GOT
GET_GOT GET_GOT
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
#define _COS9_ 0(%edi) #define _COS9_ 0(%edi)
#define _tfcos36_ 0(%eax) #define _tfcos36_ 0(%eax)
mov GLOBAL_VAR_PTR(tfcos36), %eax mov GLOBAL_VAR_PTR(tfcos36), %eax
@@ -187,7 +189,7 @@ ASM_NAME(dct36_3dnow):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 0+_tfcos36_,%mm5 punpckldq 0+_tfcos36_,%mm5
@@ -217,7 +219,7 @@ ASM_NAME(dct36_3dnow):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 32+_tfcos36_,%mm5 punpckldq 32+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -265,7 +267,7 @@ ASM_NAME(dct36_3dnow):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 4+_tfcos36_,%mm5 punpckldq 4+_tfcos36_,%mm5
@@ -295,7 +297,7 @@ ASM_NAME(dct36_3dnow):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 28+_tfcos36_,%mm5 punpckldq 28+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -356,7 +358,7 @@ ASM_NAME(dct36_3dnow):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 8+_tfcos36_,%mm5 punpckldq 8+_tfcos36_,%mm5
@@ -386,7 +388,7 @@ ASM_NAME(dct36_3dnow):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 24+_tfcos36_,%mm5 punpckldq 24+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -446,7 +448,7 @@ ASM_NAME(dct36_3dnow):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 12+_tfcos36_,%mm5 punpckldq 12+_tfcos36_,%mm5
@@ -476,7 +478,7 @@ ASM_NAME(dct36_3dnow):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 20+_tfcos36_,%mm5 punpckldq 20+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -512,7 +514,7 @@ ASM_NAME(dct36_3dnow):
movq 64(%eax),%mm3 movq 64(%eax),%mm3
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 16+_tfcos36_,%mm5 punpckldq 16+_tfcos36_,%mm5

View File

@@ -48,7 +48,9 @@
ASM_NAME(dct36_3dnowext): ASM_NAME(dct36_3dnowext):
pushl %ebp pushl %ebp
movl %esp, %ebp movl %esp, %ebp
#if defined(PIC) && defined(__APPLE__) // Not entirely sure about this PIC_GLOBAL_PTR here, but this is highly
// irrelevant, anyway. Anyone building 3DNow code for Android or Apple systems?
#ifdef PIC_GLOBAL_PTR
sub $4, %esp sub $4, %esp
#endif #endif
pushl %esi pushl %esi
@@ -58,7 +60,7 @@ ASM_NAME(dct36_3dnowext):
#define _EBX_ %edi #define _EBX_ %edi
PREPARE_GOT PREPARE_GOT
GET_GOT GET_GOT
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
#define _COS9_ 0(%edi) #define _COS9_ 0(%edi)
#define _tfcos36_ 0(%eax) #define _tfcos36_ 0(%eax)
mov GLOBAL_VAR_PTR(tfcos36), %eax mov GLOBAL_VAR_PTR(tfcos36), %eax
@@ -198,7 +200,7 @@ ASM_NAME(dct36_3dnowext):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 0+_tfcos36_,%mm5 punpckldq 0+_tfcos36_,%mm5
@@ -227,7 +229,7 @@ ASM_NAME(dct36_3dnowext):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 32+_tfcos36_,%mm5 punpckldq 32+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -275,7 +277,7 @@ ASM_NAME(dct36_3dnowext):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 4+_tfcos36_,%mm5 punpckldq 4+_tfcos36_,%mm5
@@ -305,7 +307,7 @@ ASM_NAME(dct36_3dnowext):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 28+_tfcos36_,%mm5 punpckldq 28+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -365,7 +367,7 @@ ASM_NAME(dct36_3dnowext):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 8+_tfcos36_,%mm5 punpckldq 8+_tfcos36_,%mm5
@@ -395,7 +397,7 @@ ASM_NAME(dct36_3dnowext):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 24+_tfcos36_,%mm5 punpckldq 24+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -455,7 +457,7 @@ ASM_NAME(dct36_3dnowext):
movq %mm2,%mm4 movq %mm2,%mm4
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 12+_tfcos36_,%mm5 punpckldq 12+_tfcos36_,%mm5
@@ -485,7 +487,7 @@ ASM_NAME(dct36_3dnowext):
pfsub %mm2,%mm4 pfsub %mm2,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
punpckldq 20+_tfcos36_,%mm5 punpckldq 20+_tfcos36_,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov 8(%ebp),%eax mov 8(%ebp),%eax
#endif #endif
pfmul %mm5,%mm4 pfmul %mm5,%mm4
@@ -520,7 +522,7 @@ ASM_NAME(dct36_3dnowext):
movq 64(%eax),%mm3 movq 64(%eax),%mm3
pfadd %mm3,%mm4 pfadd %mm3,%mm4
movq %mm7,%mm5 movq %mm7,%mm5
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov -4(%ebp),%eax mov -4(%ebp),%eax
#endif #endif
punpckldq 16+_tfcos36_,%mm5 punpckldq 16+_tfcos36_,%mm5

View File

@@ -36,7 +36,7 @@ ASM_NAME(dct64_3dnow):
/* femms */ /* femms */
/* 1 */ /* 1 */
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(pnts),%eax movl GLOBAL_VAR_PTR(pnts),%eax
movl (%eax),%eax movl (%eax),%eax
#else #else
@@ -140,7 +140,7 @@ ASM_NAME(dct64_3dnow):
movd %mm5,64(%ebx) movd %mm5,64(%ebx)
/* 2 */ /* 2 */
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(pnts),%eax movl GLOBAL_VAR_PTR(pnts),%eax
movl 4(%eax),%eax movl 4(%eax),%eax
#else #else
@@ -248,7 +248,7 @@ ASM_NAME(dct64_3dnow):
movd %mm5,96(%esi) movd %mm5,96(%esi)
/* 3 */ /* 3 */
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(pnts),%eax movl GLOBAL_VAR_PTR(pnts),%eax
movl 8(%eax),%eax movl 8(%eax),%eax
#else #else
@@ -354,7 +354,7 @@ ASM_NAME(dct64_3dnow):
movd %mm6,112(%ebx) movd %mm6,112(%ebx)
/* 4 */ /* 4 */
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(pnts),%eax movl GLOBAL_VAR_PTR(pnts),%eax
movl 12(%eax),%eax movl 12(%eax),%eax
#else #else
@@ -469,7 +469,7 @@ ASM_NAME(dct64_3dnow):
pi2fd %mm0,%mm0 pi2fd %mm0,%mm0
movd %eax,%mm1 movd %eax,%mm1
pi2fd %mm1,%mm1 pi2fd %mm1,%mm1
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(pnts),%eax movl GLOBAL_VAR_PTR(pnts),%eax
movl 16(%eax),%eax movl 16(%eax),%eax
#else #else

View File

@@ -32,7 +32,7 @@ ASM_NAME(dct64_MMX):
fstps (%edx) fstps (%edx)
movl 276(%esp),%edi movl 276(%esp),%edi
flds 4(%eax) flds 4(%eax)
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
movl GLOBAL_VAR_PTR(costab_mmxsse),%ebx movl GLOBAL_VAR_PTR(costab_mmxsse),%ebx
#else #else
leal GLOBAL_VAR(costab_mmxsse),%ebx leal GLOBAL_VAR(costab_mmxsse),%ebx

View File

@@ -77,7 +77,7 @@ ASM_NAME(dct64_sse):
subps %xmm0, %xmm5 subps %xmm0, %xmm5
subps %xmm1, %xmm4 subps %xmm1, %xmm4
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov GLOBAL_VAR_PTR(costab_mmxsse), %ecx mov GLOBAL_VAR_PTR(costab_mmxsse), %ecx
#else #else
lea GLOBAL_VAR(costab_mmxsse), %ecx lea GLOBAL_VAR(costab_mmxsse), %ecx

View File

@@ -77,7 +77,7 @@ ASM_NAME(dct64_real_sse):
subps %xmm0, %xmm5 subps %xmm0, %xmm5
subps %xmm1, %xmm4 subps %xmm1, %xmm4
#if defined(PIC) && defined(__APPLE__) #ifdef PIC_GLOBAL_PTR
mov GLOBAL_VAR_PTR(costab_mmxsse), %eax mov GLOBAL_VAR_PTR(costab_mmxsse), %eax
#else #else
lea GLOBAL_VAR(costab_mmxsse), %eax lea GLOBAL_VAR(costab_mmxsse), %eax

View File

@@ -139,6 +139,11 @@ Lpic_base: \
#endif /* PIC variants */ #endif /* PIC variants */
// Apple and Android NDK seem both not to like direct global access.
#if defined(PIC) && (defined(__APPLE__) || defined(ANDROID))
#define PIC_GLOBAL_PTR
#endif
#endif /* OPT_X86 */ #endif /* OPT_X86 */
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__) #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__)

View File

@@ -68,6 +68,9 @@ static void catch_interrupt (void)
intflag = TRUE; intflag = TRUE;
} }
static int xfer_write_string(out123_handle *ao, int who, const char *buf);
static int xfer_read_string(out123_handle *ao, int who, char **buf);
static int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize);
static int read_record(out123_handle *ao static int read_record(out123_handle *ao
, int who, void **buf, byte *prebuf, int *preoff, int presize, size_t *recsize); , int who, void **buf, byte *prebuf, int *preoff, int presize, size_t *recsize);
static int buffer_loop(out123_handle *ao); static int buffer_loop(out123_handle *ao);
@@ -198,6 +201,47 @@ static int buffer_cmd_finish(out123_handle *ao)
} }
} }
/* Serialization of tunable parameters to communicate them between
main process and buffer. Make sure these two stay in sync ... */
static int write_parameters(out123_handle *ao, int who)
{
int fd = ao->buffermem->fd[who];
if(
GOOD_WRITEVAL(fd, ao->flags)
&& GOOD_WRITEVAL(fd, ao->preload)
&& GOOD_WRITEVAL(fd, ao->gain)
&& GOOD_WRITEVAL(fd, ao->device_buffer)
&& GOOD_WRITEVAL(fd, ao->verbose)
&& !xfer_write_string(ao, who, ao->name)
&& !xfer_write_string(ao, who, ao->bindir)
)
return 0;
else
return -1;
}
static int read_parameters(out123_handle *ao
, int who, byte *prebuf, int *preoff, int presize)
{
int fd = ao->buffermem->fd[who];
#define GOOD_READVAL_BUF(fd, val) \
!read_buf(fd, &val, sizeof(val), prebuf, preoff, presize)
if(
GOOD_READVAL_BUF(fd, ao->flags)
&& GOOD_READVAL_BUF(fd, ao->preload)
&& GOOD_READVAL_BUF(fd, ao->gain)
&& GOOD_READVAL_BUF(fd, ao->device_buffer)
&& GOOD_READVAL_BUF(fd, ao->verbose)
&& !read_record(ao, who, (void**)&ao->name, prebuf, preoff, presize, NULL)
&& !read_record(ao, who, (void**)&ao->bindir, prebuf, preoff, presize, NULL)
)
return 0;
else
return -1;
#undef GOOD_READVAL_BUF
}
int buffer_sync_param(out123_handle *ao) int buffer_sync_param(out123_handle *ao)
{ {
int writerfd = ao->buffermem->fd[XF_WRITER]; int writerfd = ao->buffermem->fd[XF_WRITER];
@@ -524,7 +568,7 @@ int xfer_write_string(out123_handle *ao, int who, const char *buf)
} }
int xfer_read_string(out123_handle *ao, int who, char **buf) static int xfer_read_string(out123_handle *ao, int who, char **buf)
{ {
/* ao->errcode set in read_record() */ /* ao->errcode set in read_record() */
return read_record(ao, who, (void**)buf, NULL, NULL, 0, NULL) return read_record(ao, who, (void**)buf, NULL, NULL, 0, NULL)
@@ -536,7 +580,7 @@ int xfer_read_string(out123_handle *ao, int who, char **buf)
This assumes responsible use and avoids needless checking of input. This assumes responsible use and avoids needless checking of input.
And, yes, it modifies the preoff argument! And, yes, it modifies the preoff argument!
Returns 0 on success, modifies prebuffer fill. */ Returns 0 on success, modifies prebuffer fill. */
int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize) static int read_buf(int fd, void *addr, size_t size, byte *prebuf, int *preoff, int presize)
{ {
size_t need = size; size_t need = size;

View File

@@ -54,13 +54,4 @@ size_t buffer_write(out123_handle *ao, void *buffer, size_t bytes);
/* Thin wrapper over xfermem giving the current buffer fill. */ /* Thin wrapper over xfermem giving the current buffer fill. */
size_t buffer_fill(out123_handle *ao); size_t buffer_fill(out123_handle *ao);
/* Special handler to safely read values from command channel with
an additional buffer handed in. Exported for read_parameters(). */
int read_buf(int fd, void *addr, size_t size
, byte *prebuf, int *preoff, int presize);
/* Read/write strings from/to command channel. 0 on success. */
int xfer_write_string(out123_handle *ao, int who, const char *buf);
int xfer_read_string(out123_handle *ao, int who, char* *buf);
#endif #endif

View File

@@ -361,49 +361,6 @@ out123_param_from(out123_handle *ao, out123_handle* from_ao)
return 0; return 0;
} }
#ifndef NOXFERMEM
/* Serialization of tunable parameters to communicate them between
main process and buffer. Make sure these two stay in sync ... */
int write_parameters(out123_handle *ao, int who)
{
int fd = ao->buffermem->fd[who];
if(
GOOD_WRITEVAL(fd, ao->flags)
&& GOOD_WRITEVAL(fd, ao->preload)
&& GOOD_WRITEVAL(fd, ao->gain)
&& GOOD_WRITEVAL(fd, ao->device_buffer)
&& GOOD_WRITEVAL(fd, ao->verbose)
&& !xfer_write_string(ao, who, ao->name)
&& !xfer_write_string(ao, who, ao->bindir)
)
return 0;
else
return -1;
}
int read_parameters(out123_handle *ao
, int who, byte *prebuf, int *preoff, int presize)
{
int fd = ao->buffermem->fd[who];
#define GOOD_READVAL_BUF(fd, val) \
!read_buf(fd, &val, sizeof(val), prebuf, preoff, presize)
if(
GOOD_READVAL_BUF(fd, ao->flags)
&& GOOD_READVAL_BUF(fd, ao->preload)
&& GOOD_READVAL_BUF(fd, ao->gain)
&& GOOD_READVAL_BUF(fd, ao->device_buffer)
&& GOOD_READVAL_BUF(fd, ao->verbose)
&& !xfer_read_string(ao, who, &ao->name)
&& !xfer_read_string(ao, who, &ao->bindir)
)
return 0;
else
return -1;
#undef GOOD_READVAL_BUF
}
#endif
int attribute_align_arg int attribute_align_arg
out123_open(out123_handle *ao, const char* driver, const char* device) out123_open(out123_handle *ao, const char* driver, const char* device)
{ {
@@ -730,8 +687,14 @@ out123_play(out123_handle *ao, void *bytes, size_t count)
sum += written; sum += written;
count -= written; count -= written;
} }
if(written < block && errno != EINTR) if(written < block && errno != EINTR
{ && errno != EAGAIN
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
// Not all platforms define it (or only in more modern POSIX modes).
// Standard says it is supposed to be a macro, so simple check here.
&& errno != EWOULDBLOCK
#endif
){
ao->errcode = OUT123_DEV_PLAY; ao->errcode = OUT123_DEV_PLAY;
if(!AOQUIET) if(!AOQUIET)
merror( "Error in writing audio, wrote only %d of %d (%s?)!" merror( "Error in writing audio, wrote only %d of %d (%s?)!"

View File

@@ -18,9 +18,16 @@
NOTE: This particular num/size combination performs best under heavy NOTE: This particular num/size combination performs best under heavy
loads for my system, however this may not be true for any hardware/OS out there. loads for my system, however this may not be true for any hardware/OS out there.
Generally, BUFFER_SIZE < 8k || NUM_BUFFERS > 16 || NUM_BUFFERS < 4 are not recommended. Generally, BUFFER_SIZE < 8k || NUM_BUFFERS > 16 || NUM_BUFFERS < 4 are not recommended.
Introducing user-settable device buffer. We fix 8 buffers, scale the individual
buffer size, rounded/truncated a bit to not be too odd. The old default of 64K
buffers leads to 2.97 s with CD-DA. Quite excessive. We will probably reduce this
soon.
*/ */
#define BUFFER_SIZE 0x10000 #define DEFAULT_DEVICE_BUFFER 0.25
#define NUM_BUFFERS 8 /* total 512k roughly 2.5 sec of CD quality sound */ // Buffers are multiples of this.
#define BUFFER_GRANULARITY 256
#define NUM_BUFFERS 8
static void wait_for_buffer(WAVEHDR* hdr, HANDLE hEvent); static void wait_for_buffer(WAVEHDR* hdr, HANDLE hEvent);
static void drain_win32(out123_handle *ao); static void drain_win32(out123_handle *ao);
@@ -29,6 +36,7 @@ static void drain_win32(out123_handle *ao);
struct queue_state struct queue_state
{ {
WAVEHDR buffer_headers[NUM_BUFFERS]; WAVEHDR buffer_headers[NUM_BUFFERS];
size_t bufsize;
/* The next buffer to be filled and put in playback */ /* The next buffer to be filled and put in playback */
int next_buffer; int next_buffer;
/* Buffer playback completion event */ /* Buffer playback completion event */
@@ -100,11 +108,18 @@ static int open_win32(out123_handle *ao)
ereturn(-1, "Unable to open wave output device."); ereturn(-1, "Unable to open wave output device.");
} }
state->bufsize = (size_t)( (double)
(ao->device_buffer > 0. ? ao->device_buffer : DEFAULT_DEVICE_BUFFER)
* out_fmt.nAvgBytesPerSec / NUM_BUFFERS / BUFFER_GRANULARITY);
if(state->bufsize < 1)
state->bufsize = 1;
state->bufsize *= BUFFER_GRANULARITY;
/* Reset event from the "device open" message */ /* Reset event from the "device open" message */
ResetEvent(state->play_done_event); ResetEvent(state->play_done_event);
/* Allocate playback buffers */ /* Allocate playback buffers */
for(i = 0; i < NUM_BUFFERS; i++) for(i = 0; i < NUM_BUFFERS; i++)
if(!(state->buffer_headers[i].lpData = (LPSTR)malloc(BUFFER_SIZE))) if(!(state->buffer_headers[i].lpData = (LPSTR)malloc(state->bufsize)))
{ {
ereturn(-1, "Out of memory for playback buffers."); ereturn(-1, "Out of memory for playback buffers.");
} }
@@ -112,7 +127,7 @@ static int open_win32(out123_handle *ao)
{ {
/* Tell waveOutPrepareHeader the maximum value of dwBufferLength /* Tell waveOutPrepareHeader the maximum value of dwBufferLength
we will ever send */ we will ever send */
state->buffer_headers[i].dwBufferLength = BUFFER_SIZE; state->buffer_headers[i].dwBufferLength = state->bufsize;
state->buffer_headers[i].dwFlags = 0; state->buffer_headers[i].dwFlags = 0;
res = waveOutPrepareHeader(state->waveout, &state->buffer_headers[i], sizeof(WAVEHDR)); res = waveOutPrepareHeader(state->waveout, &state->buffer_headers[i], sizeof(WAVEHDR));
if(res != MMSYSERR_NOERROR) ereturn(-1, "Can't write to audio output device (prepare)."); if(res != MMSYSERR_NOERROR) ereturn(-1, "Can't write to audio output device (prepare).");
@@ -231,13 +246,13 @@ static int write_win32(out123_handle *ao, unsigned char *buf, int len)
wait_for_buffer(hdr, state->play_done_event); wait_for_buffer(hdr, state->play_done_event);
/* Now see how much we want to stuff in and then stuff it in. */ /* Now see how much we want to stuff in and then stuff it in. */
bufill = BUFFER_SIZE - hdr->dwBufferLength; bufill = state->bufsize - hdr->dwBufferLength;
if(len < bufill) bufill = len; if(len < bufill) bufill = len;
rest_len = len - bufill; rest_len = len - bufill;
memcpy(hdr->lpData + hdr->dwBufferLength, buf, bufill); memcpy(hdr->lpData + hdr->dwBufferLength, buf, bufill);
hdr->dwBufferLength += bufill; hdr->dwBufferLength += bufill;
if(hdr->dwBufferLength == BUFFER_SIZE) if(hdr->dwBufferLength == state->bufsize)
{ /* Send the buffer out when it's full. */ { /* Send the buffer out when it's full. */
hdr->dwFlags |= WHDR_PREPARED; hdr->dwFlags |= WHDR_PREPARED;

View File

@@ -117,9 +117,5 @@ struct audio_format_name {
char *sname; char *sname;
}; };
int write_parameters(out123_handle *ao, int fd);
int read_parameters(out123_handle *ao
, int fd, byte *prebuf, int *preoff, int presize);
#endif #endif

View File

@@ -45,7 +45,7 @@ int utf8force = 0; // enforce UTF-8 workings
int utf8env = 0; // produce UTF-8 text output int utf8env = 0; // produce UTF-8 text output
int utf8loc = 0; // have actual UTF-8 locale (so that mbstowcs() works) int utf8loc = 0; // have actual UTF-8 locale (so that mbstowcs() works)
static int term_is_fun = -1; //static int term_is_fun = -1;
static const char joker_symbol = '?'; static const char joker_symbol = '?';
static const char *uni_repl = "\xef\xbf\xbd"; static const char *uni_repl = "\xef\xbf\xbd";

View File

@@ -103,6 +103,7 @@ struct parameter param = {
,1024 /* resync_limit */ ,1024 /* resync_limit */
,0 /* smooth */ ,0 /* smooth */
,0.0 /* pitch */ ,0.0 /* pitch */
,0.5 // pauseloop
,0 /* appflags */ ,0 /* appflags */
,NULL /* proxyurl */ ,NULL /* proxyurl */
,0 /* keep_open */ ,0 /* keep_open */
@@ -483,7 +484,7 @@ static void set_appflag(char *arg, topt *opts)
#if defined(NETWORK) || defined(NET123) #if defined(NETWORK) || defined(NET123)
static void set_httpauth(char *arg, topt *opts) static void set_httpauth(char *arg, topt *opts)
{ {
param.httpauth = strdup(arg); param.httpauth = compat_strdup(arg);
// Do not advertise the password for all system users. // Do not advertise the password for all system users.
memset(arg, 'x', strlen(arg)); memset(arg, 'x', strlen(arg));
} }
@@ -717,6 +718,7 @@ topt opts[] = {
{'D', "delay", GLO_ARG | GLO_INT, 0, &param.delay, 0}, {'D', "delay", GLO_ARG | GLO_INT, 0, &param.delay, 0},
{0, "resync-limit", GLO_ARG | GLO_LONG, 0, &param.resync_limit, 0}, {0, "resync-limit", GLO_ARG | GLO_LONG, 0, &param.resync_limit, 0},
{0, "pitch", GLO_ARG|GLO_DOUBLE, 0, &param.pitch, 0}, {0, "pitch", GLO_ARG|GLO_DOUBLE, 0, &param.pitch, 0},
{0, "pauseloop", GLO_ARG|GLO_DOUBLE, 0, &param.pauseloop, 0},
#ifdef NETWORK #ifdef NETWORK
{0, "ignore-mime", GLO_LONG, set_appflag, &appflag, MPG123APP_IGNORE_MIME }, {0, "ignore-mime", GLO_LONG, set_appflag, &appflag, MPG123APP_IGNORE_MIME },
#endif #endif
@@ -1093,6 +1095,10 @@ int main(int sys_argc, char ** sys_argv)
print_outstr(stderr, prgName, 0, stderr_is_term); print_outstr(stderr, prgName, 0, stderr_is_term);
fprintf(stderr, ": Missing argument for option \"%s\".\n", loptarg); fprintf(stderr, ": Missing argument for option \"%s\".\n", loptarg);
usage(1); usage(1);
case GLO_BADARG:
print_outstr(stderr, prgName, 0, stderr_is_term);
fprintf(stderr, ": Bad option argument \"%s\".\n", loptarg);
usage(1);
} }
/* Do this _after_ parameter parsing. */ /* Do this _after_ parameter parsing. */
utf8force = param.force_utf8; utf8force = param.force_utf8;
@@ -1298,9 +1304,16 @@ int main(int sys_argc, char ** sys_argv)
ret = control_generic(mh); ret = control_generic(mh);
safe_exit(ret); safe_exit(ret);
} }
if(param.term_ctrl == MAYBE) {
param.term_ctrl = term_ctrl_default; int term_forced = param.term_ctrl == TRUE;
term_init(); if(param.term_ctrl == MAYBE)
param.term_ctrl = term_ctrl_default;
if(term_init() && term_forced)
{
error("Aborting since explicitly requested terminal control is not available.");
safe_exit(99);
}
}
if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number; if(APPFLAG(MPG123APP_CONTINUE)) frames_left = param.frame_number;
while ((fname = get_next_file())) while ((fname = get_next_file()))
@@ -1599,14 +1612,13 @@ static void long_usage(int err)
fprintf(o," -y --no-resync DISABLES resync on error (--resync is deprecated)\n"); fprintf(o," -y --no-resync DISABLES resync on error (--resync is deprecated)\n");
fprintf(o," -F --no-frankenstein disable support for Frankenstein streams\n"); fprintf(o," -F --no-frankenstein disable support for Frankenstein streams\n");
#if defined(NETWORK) || defined(NET123) #if defined(NETWORK) || defined(NET123)
#ifdef NETWORK fprintf(o," -p <f> --proxy <f> override proxy environemnt variable for plain HTTP\n");
fprintf(o," -p <f> --proxy <f> set WWW proxy\n");
#else
fprintf(o," --network <b> select network backend, available: auto"); fprintf(o," --network <b> select network backend, available: auto");
const char **nb = net123_backends; const char **nb = net123_backends;
while(*nb){ fprintf(o, " %s", *nb++); } while(*nb){ fprintf(o, " %s", *nb++); }
fprintf(o, "\n"); fprintf(o, "\n");
#endif fprintf(o," (auto meaning internal code for plain HTTP and the\n");
fprintf(o," first external option for HTTPS)\n");
fprintf(o," -u --auth set auth values for HTTP access\n"); fprintf(o," -u --auth set auth values for HTTP access\n");
fprintf(o," --auth-file set auth values for HTTP access from given file\n"); fprintf(o," --auth-file set auth values for HTTP access from given file\n");
fprintf(o," --ignore-mime ignore HTTP MIME types (content-type)\n"); fprintf(o," --ignore-mime ignore HTTP MIME types (content-type)\n");
@@ -1635,6 +1647,7 @@ static void long_usage(int err)
fprintf(o," --list-devices list the available output devices for given output module\n"); fprintf(o," --list-devices list the available output devices for given output module\n");
fprintf(o," -a <d> --audiodevice <d> select audio device (depending on chosen module)\n"); fprintf(o," -a <d> --audiodevice <d> select audio device (depending on chosen module)\n");
fprintf(o," -s --stdout write raw audio to stdout (host native format)\n"); fprintf(o," -s --stdout write raw audio to stdout (host native format)\n");
fprintf(o," -O <f> --outfile <f> write raw audio to given file (- is stdout)\n");
fprintf(o," -w <f> --wav <f> write samples as WAV file in <f> (- is stdout)\n"); fprintf(o," -w <f> --wav <f> write samples as WAV file in <f> (- is stdout)\n");
fprintf(o," --au <f> write samples as Sun AU file in <f> (- is stdout)\n"); fprintf(o," --au <f> write samples as Sun AU file in <f> (- is stdout)\n");
fprintf(o," --cdr <f> write samples as raw CD audio file in <f> (- is stdout)\n"); fprintf(o," --cdr <f> write samples as raw CD audio file in <f> (- is stdout)\n");
@@ -1703,6 +1716,7 @@ static void long_usage(int err)
#ifndef GENERIC #ifndef GENERIC
fprintf(o," --title set terminal title to filename\n"); fprintf(o," --title set terminal title to filename\n");
#endif #endif
fprintf(o," --pauseloop <s> loop interval in (fractional) seconds\n");
fprintf(o," --name <n> set instance name (used in various places)\n"); fprintf(o," --name <n> set instance name (used in various places)\n");
fprintf(o," --long-tag spacy id3 display with every item on a separate line\n"); fprintf(o," --long-tag spacy id3 display with every item on a separate line\n");
fprintf(o," --lyrics show lyrics (from ID3v2 USLT frame)\n"); fprintf(o," --lyrics show lyrics (from ID3v2 USLT frame)\n");

View File

@@ -97,6 +97,7 @@ struct parameter
long resync_limit; long resync_limit;
int smooth; int smooth;
double pitch; /* <0 or >0, 0.05 for 5% speedup. */ double pitch; /* <0 or >0, 0.05 for 5% speedup. */
double pauseloop; // terminal control 'pause' loop length
unsigned long appflags; /* various switches for mpg123 application */ unsigned long appflags; /* various switches for mpg123 application */
char *proxyurl; char *proxyurl;
int keep_open; /* Whether to keep files open after end reached, for remote control mode, perhaps terminal control, too. */ int keep_open; /* Whether to keep files open after end reached, for remote control mode, perhaps terminal control, too. */

View File

@@ -39,12 +39,17 @@
#ifndef _MPG123_NET123_H_ #ifndef _MPG123_NET123_H_
#define _MPG123_NET123_H_ #define _MPG123_NET123_H_
#include "config.h"
#include <sys/types.h> #include <sys/types.h>
// The network implementation defines the struct for private use. // stream handle for differing implementations, build-time plugins
// The purpose is just to keep enough context to be able to struct net123_handle_struct
// call net123_read() and net123_close() afterwards. {
struct net123_handle_struct; void *parts; // custom internal data
// callbacks
size_t (*read)(struct net123_handle_struct *nh, void *buf, size_t bufsize);
void (*close)(struct net123_handle_struct *nh);
};
typedef struct net123_handle_struct net123_handle; typedef struct net123_handle_struct net123_handle;
extern const char *net123_backends[]; extern const char *net123_backends[];
@@ -54,16 +59,16 @@ extern const char *net123_backends[];
// and then the raw data. // and then the raw data.
// client_head contains header lines to send with the request, without // client_head contains header lines to send with the request, without
// line ending // line ending
net123_handle *net123_open(const char *url, const char * const *client_head);
// Read data into buffer, return bytes read. // Variant for the external binding.
// This handles interrupts (EAGAIN, EINTR, ..) internally and only returns #ifdef NET123_EXEC
// a short byte count on EOF or error. End of file or error is not distinguished: net123_handle *net123_open_exec(const char *url, const char * const *client_head);
// For the user, it only matters if there will be more bytes or not. #endif
// Feel free to communicate errors via error() / merror() functions inside. #ifdef NET123_WININET
size_t net123_read(net123_handle *nh, void *buf, size_t bufsize); net123_handle *net123_open_wininet(const char *url, const char * const *client_head);
#endif
// Call that to free up resources, end processes. #ifdef NET123_WINHTTP
void net123_close(net123_handle *nh); net123_handle *net123_open_winhttp(const char *url, const char * const *client_head);
#endif
#endif #endif

View File

@@ -8,6 +8,9 @@
specifically if param.network_backend is set accordingly. specifically if param.network_backend is set accordingly.
*/ */
// kill
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
#include "config.h" #include "config.h"
#include "net123.h" #include "net123.h"
@@ -34,18 +37,11 @@
// wget --user=... --password=... // wget --user=... --password=...
// Alternatively: Have them in .netrc. // Alternatively: Have them in .netrc.
const char *net123_backends[] = typedef struct
{
"wget"
, "curl"
, NULL
};
struct net123_handle_struct
{ {
int fd; int fd;
pid_t worker; pid_t worker;
}; } exec_handle;
// Combine two given strings into one newly allocated one. // Combine two given strings into one newly allocated one.
// Use: (--parameter=, value) -> --parameter=value // Use: (--parameter=, value) -> --parameter=value
@@ -239,7 +235,36 @@ static char **curl_argv(const char *url, const char * const * client_head)
return argv; return argv;
} }
net123_handle *net123_open(const char *url, const char * const * client_head)
static size_t net123_read(net123_handle *nh, void *buf, size_t bufsize)
{
if(!nh || (bufsize && !buf))
return 0;
return unintr_read(((exec_handle*)nh->parts)->fd, buf, bufsize);
}
static void net123_close(net123_handle *nh)
{
if(!nh)
return;
exec_handle *eh = nh->parts;
if(eh->worker)
{
kill(eh->worker, SIGKILL);
errno = 0;
if(waitpid(eh->worker, NULL, 0) < 0)
merror("failed to wait for worker process: %s", strerror(errno));
else if(param.verbose > 1)
fprintf(stderr, "Note: network helper %"PRIiMAX" finished\n", (intmax_t)eh->worker);
}
if(eh->fd > -1)
close(eh->fd);
free(nh->parts);
free(nh);
}
net123_handle *net123_open_exec(const char *url, const char * const * client_head)
{ {
int use_curl = 0; int use_curl = 0;
char * const curl_check_argv[] = { "curl", "--help", "all", NULL }; char * const curl_check_argv[] = { "curl", "--help", "all", NULL };
@@ -276,12 +301,21 @@ net123_handle *net123_open(const char *url, const char * const * client_head)
} }
int fd[2]; int fd[2];
int hi = -1; // index of header value that might get a continuation line
net123_handle *nh = malloc(sizeof(net123_handle)); net123_handle *nh = malloc(sizeof(net123_handle));
if(!nh) exec_handle *eh = malloc(sizeof(exec_handle));
if(!nh || !eh)
{
if(nh)
free(nh);
if(eh)
free(eh);
return NULL; return NULL;
nh->fd = -1; }
nh->worker = 0; nh->parts = eh;
nh->read = net123_read;
nh->close = net123_close;
eh->fd = -1;
eh->worker = 0;
errno = 0; errno = 0;
if(pipe(fd)) if(pipe(fd))
{ {
@@ -293,15 +327,15 @@ net123_handle *net123_open(const char *url, const char * const * client_head)
compat_binmode(fd[0], TRUE); compat_binmode(fd[0], TRUE);
compat_binmode(fd[1], TRUE); compat_binmode(fd[1], TRUE);
nh->worker = fork(); eh->worker = fork();
if(nh->worker == -1) if(eh->worker == -1)
{ {
merror("fork failed: %s", strerror(errno)); merror("fork failed: %s", strerror(errno));
free(nh); free(nh);
return NULL; return NULL;
} }
if(nh->worker == 0) if(eh->worker == 0)
{ {
close(fd[0]); close(fd[0]);
dup2(fd[1], STDOUT_FILENO); dup2(fd[1], STDOUT_FILENO);
@@ -309,7 +343,6 @@ net123_handle *net123_open(const char *url, const char * const * client_head)
dup2(infd, STDIN_FILENO); dup2(infd, STDIN_FILENO);
// child // child
// Proxy environment variables can just be set in the user and inherited here, right? // Proxy environment variables can just be set in the user and inherited here, right?
int argc;
char **argv = use_curl ? curl_argv(url, client_head) : wget_argv(url, client_head); char **argv = use_curl ? curl_argv(url, client_head) : wget_argv(url, client_head);
if(!argv) if(!argv)
@@ -338,35 +371,9 @@ net123_handle *net123_open(const char *url, const char * const * client_head)
} }
// parent // parent
if(param.verbose > 1) if(param.verbose > 1)
fprintf(stderr, "Note: started network helper with PID %"PRIiMAX"\n", (intmax_t)nh->worker); fprintf(stderr, "Note: started network helper with PID %"PRIiMAX"\n", (intmax_t)eh->worker);
errno = 0; errno = 0;
close(fd[1]); close(fd[1]);
nh->fd = fd[0]; eh->fd = fd[0];
return nh; return nh;
} }
size_t net123_read(net123_handle *nh, void *buf, size_t bufsize)
{
if(!nh || (bufsize && !buf))
return 0;
return unintr_read(nh->fd, buf, bufsize);
}
void net123_close(net123_handle *nh)
{
if(!nh)
return;
if(nh->worker)
{
kill(nh->worker, SIGKILL);
errno = 0;
if(waitpid(nh->worker, NULL, 0) < 0)
merror("failed to wait for worker process: %s", strerror(errno));
else if(param.verbose > 1)
fprintf(stderr, "Note: network helper %"PRIiMAX" finished\n", (intmax_t)nh->worker);
}
if(nh->fd > -1)
close(nh->fd);
free(nh);
}

View File

@@ -5,13 +5,11 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <winhttp.h> #include <winhttp.h>
const char *net123_backends[] = { "(always winhttp)", NULL };
// The network implementation defines the struct for private use. // The network implementation defines the struct for private use.
// The purpose is just to keep enough context to be able to // The purpose is just to keep enough context to be able to
// call net123_read() and net123_close() afterwards. // call net123_read() and net123_close() afterwards.
#define URL_COMPONENTS_LENGTH 255 #define URL_COMPONENTS_LENGTH 255
struct net123_handle_struct { typedef struct {
HINTERNET session; HINTERNET session;
HINTERNET connect; HINTERNET connect;
HINTERNET request; HINTERNET request;
@@ -26,7 +24,7 @@ struct net123_handle_struct {
size_t headers_pos, headers_len; size_t headers_pos, headers_len;
DWORD internetStatus, internetStatusLength; DWORD internetStatus, internetStatusLength;
LPVOID additionalInfo; LPVOID additionalInfo;
}; } winhttp_handle;
#define MPG123CONCAT_(x,y) x ## y #define MPG123CONCAT_(x,y) x ## y
#define MPG123CONCAT(x,y) MPG123CONCAT_(x,y) #define MPG123CONCAT(x,y) MPG123CONCAT_(x,y)
@@ -34,7 +32,7 @@ struct net123_handle_struct {
#define MPG123STRINGIFY(x) MPG123STRINGIFY_(x) #define MPG123STRINGIFY(x) MPG123STRINGIFY_(x)
#define MPG123WSTR(x) MPG123CONCAT(L,MPG123STRINGIFY(x)) #define MPG123WSTR(x) MPG123CONCAT(L,MPG123STRINGIFY(x))
static DWORD wrap_auth(net123_handle *nh){ static DWORD wrap_auth(winhttp_handle *nh){
DWORD mode; DWORD mode;
DWORD ret; DWORD ret;
@@ -81,13 +79,16 @@ static void debug_crack(URL_COMPONENTS *comps){}
static static
void WINAPI net123_ssl_errors(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength){ void WINAPI net123_ssl_errors(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength){
net123_handle *nh = (net123_handle *)dwContext; winhttp_handle *nh = (winhttp_handle *)dwContext;
nh->internetStatus = dwInternetStatus; nh->internetStatus = dwInternetStatus;
nh->additionalInfo = lpvStatusInformation; nh->additionalInfo = lpvStatusInformation;
nh->internetStatusLength = dwStatusInformationLength; nh->internetStatusLength = dwStatusInformationLength;
} }
net123_handle *net123_open(const char *url, const char * const *client_head){ static size_t net123_read(net123_handle *nh, void *buf, size_t bufsize);
static void net123_close(net123_handle *nh);
net123_handle *net123_open_winhttp(const char *url, const char * const *client_head){
LPWSTR urlW = NULL, headers = NULL; LPWSTR urlW = NULL, headers = NULL;
size_t ii; size_t ii;
WINBOOL res; WINBOOL res;
@@ -101,8 +102,18 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
win32_utf8_wide(url, &urlW, NULL); win32_utf8_wide(url, &urlW, NULL);
if(urlW == NULL) goto cleanup; if(urlW == NULL) goto cleanup;
net123_handle *ret = calloc(1, sizeof(net123_handle)); winhttp_handle *ret = calloc(1, sizeof(winhttp_handle));
if (!ret) return ret; if (!ret) goto cleanup;
net123_handle *handle = calloc(1, sizeof(net123_handle));
if (!handle) {
free(ret);
goto cleanup;
}
handle->parts = ret;
handle->read = net123_read;
handle->close = net123_close;
ret->comps.dwStructSize = sizeof(ret->comps); ret->comps.dwStructSize = sizeof(ret->comps);
ret->comps.dwSchemeLength = 0; ret->comps.dwSchemeLength = 0;
@@ -206,13 +217,13 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
} }
debug("net123_open OK"); debug("net123_open OK");
return ret; return handle;
cleanup: cleanup:
debug("net123_open error"); debug("net123_open error");
if (urlW) free(urlW); if (urlW) free(urlW);
net123_close(ret); net123_close(handle);
ret = NULL; handle = NULL;
return ret; return handle;
} }
// Read data into buffer, return bytes read. // Read data into buffer, return bytes read.
@@ -221,20 +232,21 @@ cleanup:
// For the user, it only matters if there will be more bytes or not. // For the user, it only matters if there will be more bytes or not.
// Feel free to communicate errors via error() / merror() functions inside. // Feel free to communicate errors via error() / merror() functions inside.
size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){ size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){
winhttp_handle *h = nh->parts;
size_t ret; size_t ret;
size_t to_copy = nh->headers_len - nh->headers_pos; size_t to_copy = h->headers_len - h->headers_pos;
DWORD bytesread = 0; DWORD bytesread = 0;
if(to_copy){ if(to_copy){
ret = to_copy <= bufsize ? to_copy : bufsize; ret = to_copy <= bufsize ? to_copy : bufsize;
memcpy(buf, nh->headers + nh->headers_pos, ret); memcpy(buf, h->headers + h->headers_pos, ret);
nh->headers_pos += ret; h->headers_pos += ret;
return ret; return ret;
} }
/* is this needed? */ /* is this needed? */
to_copy = bufsize > ULONG_MAX ? ULONG_MAX : bufsize; to_copy = bufsize > ULONG_MAX ? ULONG_MAX : bufsize;
if(!WinHttpReadData(nh->request, buf, to_copy, &bytesread)){ if(!WinHttpReadData(h->request, buf, to_copy, &bytesread)){
return EOF; return EOF;
} }
return bytesread; return bytesread;
@@ -242,21 +254,26 @@ size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){
// Call that to free up resources, end processes. // Call that to free up resources, end processes.
void net123_close(net123_handle *nh){ void net123_close(net123_handle *nh){
if(nh->headers) { if (!nh) return;
free(nh->headers); winhttp_handle *h = nh->parts;
nh->headers = NULL; if(h) {
} if(h->headers) {
if(nh->request) { free(h->headers);
WinHttpCloseHandle(nh->request); h->headers = NULL;
nh->request = NULL; }
} if(h->request) {
if(nh->connect) { WinHttpCloseHandle(h->request);
WinHttpCloseHandle(nh->connect); h->request = NULL;
nh->connect = NULL; }
} if(h->connect) {
if(nh->session) { WinHttpCloseHandle(h->connect);
WinHttpCloseHandle(nh->session); h->connect = NULL;
nh->session = NULL; }
if(h->session) {
WinHttpCloseHandle(h->session);
h->session = NULL;
}
free(h);
} }
free(nh); free(nh);
} }

View File

@@ -5,13 +5,11 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <wininet.h> #include <wininet.h>
const char *net123_backends[] = { "(always wininet)", NULL };
// The network implementation defines the struct for private use. // The network implementation defines the struct for private use.
// The purpose is just to keep enough context to be able to // The purpose is just to keep enough context to be able to
// call net123_read() and net123_close() afterwards. // call net123_read() and net123_close() afterwards.
#define URL_COMPONENTS_LENGTH 255 #define URL_COMPONENTS_LENGTH 255
struct net123_handle_struct { typedef struct {
HINTERNET session; HINTERNET session;
HINTERNET connect; HINTERNET connect;
HINTERNET request; HINTERNET request;
@@ -28,7 +26,7 @@ struct net123_handle_struct {
DWORD HttpQueryInfoIndex; DWORD HttpQueryInfoIndex;
DWORD internetStatus, internetStatusLength; DWORD internetStatus, internetStatusLength;
LPVOID additionalInfo; LPVOID additionalInfo;
}; } wininet_handle;
#define MPG123CONCAT_(x,y) x ## y #define MPG123CONCAT_(x,y) x ## y
#define MPG123CONCAT(x,y) MPG123CONCAT_(x,y) #define MPG123CONCAT(x,y) MPG123CONCAT_(x,y)
@@ -60,13 +58,17 @@ static void debug_crack(URL_COMPONENTSW *comps){}
static static
void WINAPI net123_ssl_errors(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength){ void WINAPI net123_ssl_errors(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength){
net123_handle *nh = (net123_handle *)dwContext; debug("In net123_ssl_errors");
wininet_handle *nh = (wininet_handle *)(dwContext);
nh->internetStatus = dwInternetStatus; nh->internetStatus = dwInternetStatus;
nh->additionalInfo = lpvStatusInformation; nh->additionalInfo = lpvStatusInformation;
nh->internetStatusLength = dwStatusInformationLength; nh->internetStatusLength = dwStatusInformationLength;
} }
net123_handle *net123_open(const char *url, const char * const *client_head){ static size_t net123_read(net123_handle *nh, void *buf, size_t bufsize);
static void net123_close(net123_handle *nh);
net123_handle *net123_open_wininet(const char *url, const char * const *client_head){
LPWSTR urlW = NULL, headers = NULL; LPWSTR urlW = NULL, headers = NULL;
size_t ii; size_t ii;
WINBOOL res; WINBOOL res;
@@ -78,51 +80,63 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
if(urlW == NULL) goto cleanup; if(urlW == NULL) goto cleanup;
net123_handle *ret = calloc(1, sizeof(net123_handle)); net123_handle *ret = calloc(1, sizeof(net123_handle));
if (!ret) return ret; wininet_handle *wh = calloc(1, sizeof(wininet_handle));
if(!ret || !wh)
{
if(ret)
free(ret);
if(wh)
free(wh);
return NULL;
}
ret->comps.dwStructSize = sizeof(ret->comps); ret->parts = wh;
ret->comps.dwSchemeLength = URL_COMPONENTS_LENGTH - 1; ret->read = net123_read;
ret->comps.dwUserNameLength = URL_COMPONENTS_LENGTH - 1; ret->close = net123_close;
ret->comps.dwPasswordLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.dwHostNameLength = URL_COMPONENTS_LENGTH - 1; wh->comps.dwStructSize = sizeof(wh->comps);
ret->comps.dwUrlPathLength = URL_COMPONENTS_LENGTH - 1; wh->comps.dwSchemeLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.dwExtraInfoLength = URL_COMPONENTS_LENGTH - 1; wh->comps.dwUserNameLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.lpszHostName = ret->lpszHostName; wh->comps.dwPasswordLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.lpszUserName = ret->lpszUserName; wh->comps.dwHostNameLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.lpszPassword = ret->lpszPassword; wh->comps.dwUrlPathLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.lpszUrlPath = ret->lpszUrlPath; wh->comps.dwExtraInfoLength = URL_COMPONENTS_LENGTH - 1;
ret->comps.lpszExtraInfo = ret->lpszExtraInfo; wh->comps.lpszHostName = wh->lpszHostName;
ret->comps.lpszScheme = ret->lpszScheme; wh->comps.lpszUserName = wh->lpszUserName;
wh->comps.lpszPassword = wh->lpszPassword;
wh->comps.lpszUrlPath = wh->lpszUrlPath;
wh->comps.lpszExtraInfo = wh->lpszExtraInfo;
wh->comps.lpszScheme = wh->lpszScheme;
debug1("net123_open start crack %S", urlW); debug1("net123_open start crack %S", urlW);
if(!(res = InternetCrackUrlW(urlW, 0, 0, &ret->comps))) { if(!(res = InternetCrackUrlW(urlW, 0, 0, &wh->comps))) {
debug1("net123_open crack fail %lu", GetLastError()); debug1("net123_open crack fail %lu", GetLastError());
goto cleanup; goto cleanup;
} }
debug("net123_open crack OK"); debug("net123_open crack OK");
debug_crack(&ret->comps); debug_crack(&wh->comps);
ret->session = InternetOpenW(useragent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); wh->session = InternetOpenW(useragent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
free(urlW); free(urlW);
urlW = NULL; urlW = NULL;
debug("net123_open InternetOpenW OK"); debug("net123_open InternetOpenW OK");
if(!ret->session) goto cleanup; if(!wh->session) goto cleanup;
debug2("net123_open InternetConnectW %S %u", ret->comps.lpszHostName, ret->comps.nPort); debug2("net123_open InternetConnectW %S %u", wh->comps.lpszHostName, wh->comps.nPort);
ret->connect = InternetConnectW(ret->session, ret->comps.lpszHostName, ret->comps.nPort, wh->connect = InternetConnectW(wh->session, wh->comps.lpszHostName, wh->comps.nPort,
ret->comps.dwUserNameLength ? ret->comps.lpszUserName : NULL, ret->comps.dwPasswordLength ? ret->comps.lpszPassword : NULL, wh->comps.dwUserNameLength ? wh->comps.lpszUserName : NULL, wh->comps.dwPasswordLength ? wh->comps.lpszPassword : NULL,
INTERNET_SERVICE_HTTP, 0, 0); INTERNET_SERVICE_HTTP, 0, 0);
if(!ret->connect) goto cleanup; if(!wh->connect) goto cleanup;
debug("net123_open InternetConnectW OK"); debug("net123_open InternetConnectW OK");
debug1("HttpOpenRequestW GET %S", ret->comps.lpszUrlPath); debug1("HttpOpenRequestW GET %S", wh->comps.lpszUrlPath);
ret->request = HttpOpenRequestW(ret->connect, L"GET", ret->comps.lpszUrlPath, NULL, NULL, NULL, ret->comps.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)ret); wh->request = HttpOpenRequestW(wh->connect, L"GET", wh->comps.lpszUrlPath, NULL, NULL, NULL, wh->comps.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)wh);
if(!ret->request) goto cleanup; if(!wh->request) goto cleanup;
debug("HttpOpenRequestW GET OK"); debug("HttpOpenRequestW GET OK");
cb = InternetSetStatusCallback(ret->request, (INTERNET_STATUS_CALLBACK)net123_ssl_errors); cb = InternetSetStatusCallback(wh->request, (INTERNET_STATUS_CALLBACK)net123_ssl_errors);
if(cb != NULL){ if(cb != NULL){
error1("InternetSetStatusCallback failed to install callback, errors might not be reported properly! (%lu)", GetLastError()); error1("InternetSetStatusCallback failed to install callback, errors might not be reported properly! (%lu)", GetLastError());
} }
@@ -132,7 +146,7 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
if(!headers) if(!headers)
goto cleanup; goto cleanup;
debug1("HttpAddRequestHeadersW add %S", headers); debug1("HttpAddRequestHeadersW add %S", headers);
res = HttpAddRequestHeadersW(ret->request, headers, (DWORD) -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE); res = HttpAddRequestHeadersW(wh->request, headers, (DWORD) -1, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
debug2("HttpAddRequestHeadersW returns %u %lu", res, res ? 0 : GetLastError()); debug2("HttpAddRequestHeadersW returns %u %lu", res, res ? 0 : GetLastError());
free(headers); free(headers);
headers = NULL; headers = NULL;
@@ -140,13 +154,14 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
debug("net123_open ADD HEADERS OK"); debug("net123_open ADD HEADERS OK");
res = HttpSendRequestW(ret->request, NULL, 0, NULL, 0); res = HttpSendRequestW(wh->request, NULL, 0, NULL, 0);
if (!res) { if (!res) {
res = GetLastError(); res = GetLastError();
error1("HttpSendRequestW failed with %lu", res); error1("HttpSendRequestW failed with %lu", res);
goto cleanup; goto cleanup;
} }
debug("HttpSendRequestW OK");
// dummy, cannot be null // dummy, cannot be null
headers = calloc(1,1); headers = calloc(1,1);
@@ -155,18 +170,20 @@ net123_handle *net123_open(const char *url, const char * const *client_head){
error("Cannot allocate dummy buffer for HttpQueryInfoW"); error("Cannot allocate dummy buffer for HttpQueryInfoW");
goto cleanup; goto cleanup;
} }
res = HttpQueryInfoW(ret->request, HTTP_QUERY_RAW_HEADERS_CRLF, headers, &headerlen, &ret->HttpQueryInfoIndex); debug("Try HttpQueryInfoW pass 1");
res = HttpQueryInfoW(wh->request, HTTP_QUERY_RAW_HEADERS_CRLF, headers, &headerlen, &wh->HttpQueryInfoIndex);
free(headers); free(headers);
debug("HttpQueryInfoW pass 1 OK");
if(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER && headerlen > 0) { if(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER && headerlen > 0) {
/* buffer size is in bytes, not including terminator */ /* buffer size is in bytes, not including terminator */
headers = calloc(1, headerlen + sizeof(*headers)); headers = calloc(1, headerlen + sizeof(*headers));
if (!headers) goto cleanup; if (!headers) goto cleanup;
res = HttpQueryInfoW(ret->request, HTTP_QUERY_RAW_HEADERS_CRLF, headers, &headerlen, &ret->HttpQueryInfoIndex); res = HttpQueryInfoW(wh->request, HTTP_QUERY_RAW_HEADERS_CRLF, headers, &headerlen, &wh->HttpQueryInfoIndex);
debug3("HttpQueryInfoW returned %u, err %u : %S", res, GetLastError(), headers ? headers : L"null"); debug3("HttpQueryInfoW returned %u, err %u : %S", res, GetLastError(), headers ? headers : L"null");
win32_wide_utf7(headers, &ret->headers, &ret->headers_len); win32_wide_utf7(headers, &wh->headers, &wh->headers_len);
/* bytes written, skip the terminating null, we want to stop at the \r\n\r\n */ /* bytes written, skip the terminating null, we want to stop at the \r\n\r\n */
ret->headers_len --; wh->headers_len --;
free(headers); free(headers);
headers = NULL; headers = NULL;
} else { } else {
@@ -184,21 +201,24 @@ cleanup:
return ret; return ret;
} }
size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){ static size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){
if(!nh || !nh->parts)
return 0;
wininet_handle *wh = nh->parts;
size_t ret; size_t ret;
size_t to_copy = nh->headers_len - nh->headers_pos; size_t to_copy = wh->headers_len - wh->headers_pos;
DWORD bytesread = 0; DWORD bytesread = 0;
if(to_copy){ if(to_copy){
ret = to_copy <= bufsize ? to_copy : bufsize; ret = to_copy <= bufsize ? to_copy : bufsize;
memcpy(buf, nh->headers + nh->headers_pos, ret); memcpy(buf, wh->headers + wh->headers_pos, ret);
nh->headers_pos += ret; wh->headers_pos += ret;
return ret; return ret;
} }
/* is this needed? */ /* is this needed? */
to_copy = bufsize > ULONG_MAX ? ULONG_MAX : bufsize; to_copy = bufsize > ULONG_MAX ? ULONG_MAX : bufsize;
if(!InternetReadFile(nh->request, buf, to_copy, &bytesread)){ if(!InternetReadFile(wh->request, buf, to_copy, &bytesread)){
error1("InternetReadFile exited with %d", GetLastError()); error1("InternetReadFile exited with %d", GetLastError());
return EOF; return EOF;
} }
@@ -206,22 +226,28 @@ size_t net123_read(net123_handle *nh, void *buf, size_t bufsize){
} }
// Call that to free up resources, end processes. // Call that to free up resources, end processes.
void net123_close(net123_handle *nh){ static void net123_close(net123_handle *nh){
if(nh->headers) { if(!nh)
free(nh->headers); return;
nh->headers = NULL; wininet_handle *wh = nh->parts;
if(!wh) /*???*/
return;
if(wh->headers) {
free(wh->headers);
wh->headers = NULL;
} }
if(nh->request) { if(wh->request) {
InternetCloseHandle(nh->request); InternetCloseHandle(wh->request);
nh->request = NULL; wh->request = NULL;
} }
if(nh->connect) { if(wh->connect) {
InternetCloseHandle(nh->connect); InternetCloseHandle(wh->connect);
nh->connect = NULL; wh->connect = NULL;
} }
if(nh->session) { if(wh->session) {
InternetCloseHandle(nh->session); InternetCloseHandle(wh->session);
nh->session = NULL; wh->session = NULL;
} }
free(nh); free(nh);
free(wh);
} }

View File

@@ -1516,6 +1516,9 @@ int main(int sys_argc, char ** sys_argv)
case GLO_NOARG: case GLO_NOARG:
fprintf (stderr, ME": missing argument for parameter: %s\n", loptarg); fprintf (stderr, ME": missing argument for parameter: %s\n", loptarg);
usage(1); usage(1);
case GLO_BADARG:
fprintf(stderr, ME": bad option argument: %s\n", loptarg);
usage(1);
} }
finish_endian(); finish_endian();
mdebug("input byte flags: %ld, output byte flags: %ld", byte_in_flags, byte_out_flags); mdebug("input byte flags: %ld, output byte flags: %ld", byte_in_flags, byte_out_flags);

View File

@@ -357,7 +357,8 @@ static int add_next_file (int argc, char *argv[], int args_utf8)
} }
} }
pl.entry = 0; pl.entry = 0;
if(pl.file && pl.file->network) #ifdef NET123
if(pl.file && pl.file->nh)
{ {
debug1("htd.content_type.p: %p", (void*) pl.file->htd.content_type.p); debug1("htd.content_type.p: %p", (void*) pl.file->htd.content_type.p);
if(!APPFLAG(MPG123APP_IGNORE_MIME) && pl.file->htd.content_type.p != NULL) if(!APPFLAG(MPG123APP_IGNORE_MIME) && pl.file->htd.content_type.p != NULL)
@@ -402,6 +403,7 @@ static int add_next_file (int argc, char *argv[], int args_utf8)
} }
} }
} }
#endif
if(!pl.file) if(!pl.file)
{ {
param.listname = NULL; // why? param.listname = NULL; // why?

View File

@@ -4,11 +4,15 @@
This evolved into the generic I/O interposer for direct file or http stream This evolved into the generic I/O interposer for direct file or http stream
access, with explicit buffering for getline. access, with explicit buffering for getline.
copyright 2010-2019 by the mpg123 project - free software under the terms of the LGPL 2.1 copyright 2010-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 see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written by Michael Hipp initially written by Michael Hipp
*/ */
// setenv
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
#include "streamdump.h" #include "streamdump.h"
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@@ -18,6 +22,143 @@
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
#ifndef HTTP_MAX_RELOCATIONS
#define HTTP_MAX_RELOCATIONS 20
#endif
#if defined(NETWORK) && !defined(NET123)
#error "NETWORK only with NET123 from now on!"
#endif
#if !defined(NETWORK) && defined(NET123)
#error "NET123 only with NETWORK from now on!"
#endif
#ifdef NETWORK
const char *net123_backends[] =
{
"internal"
#ifdef NET123_EXEC
, "wget"
, "curl"
#endif
#ifdef NET123_WINHTTP
, "winhttp"
#endif
#ifdef NET123_WININET
, "wininet"
#endif
, NULL
};
// Net123 variant for our internal code that has safer legacy support for HTTP shoutcast.
static size_t net123_read_internal( struct net123_handle_struct *nh,
void *buf, size_t bufsize )
{
if(!nh)
return 0;
int *fdp = nh->parts;
#ifdef WANT_WIN32_SOCKETS
return win32_net_read(*fdp, buf, bufsize);
#else
return unintr_read(*fdp, buf, bufsize);
#endif
}
static void net123_close_internal(struct net123_handle_struct *nh)
{
if(nh)
return;
int *fdp = nh->parts;
#ifdef WANT_WIN32_SOCKETS
if(*fdp != SOCKET_ERROR)
win32_net_close(*fdp);
#else
close(*fdp);
#endif
free(fdp);
free(nh);
}
static net123_handle *net123_open_internal( const char *url
, const char * const *client_head, struct httpdata *hd )
{
net123_handle *nh = malloc(sizeof(net123_handle));
if(!nh)
return NULL;
int *fdp = malloc(sizeof(int));
if(!fdp)
{
free(nh);
return NULL;
}
nh->parts = fdp;
nh->read = net123_read_internal;
nh->close = net123_close_internal;
// Handles win32_net internally.
*fdp = http_open(url, hd, client_head);
if(*fdp >= 0)
return nh;
free(fdp);
free(nh);
return NULL;
}
// Decide which backend to load.
static net123_handle *net123_open( const char *url
, const char * const *client_head, struct httpdata *hd )
{
int autochoose = !strcmp("auto", param.network_backend);
int https = !strncasecmp("https://", url, 8);
if(param.proxyurl)
{
if(strcmp(param.proxyurl, "none"))
{
#ifdef HAVE_SETENV
setenv("http_proxy", param.proxyurl, 1);
setenv("HTTP_PROXY", param.proxyurl, 1);
setenv("https_proxy", param.proxyurl, 1);
setenv("HTTPS_PROXY", param.proxyurl, 1);
#endif
} else
{
#ifdef HAVE_UNSETENV
unsetenv("http_proxy");
unsetenv("HTTP_PROXY");
unsetenv("https_proxy");
unsetenv("HTTPS_PROXY");
#endif
}
}
if( (autochoose && !https)
|| !strcmp("internal", param.network_backend) )
{
if(https && !param.quiet)
fprintf(stderr, "Note: HTTPS will fail with internal network code.\n");
return net123_open_internal(url, client_head, hd);
}
#ifdef NET123_EXEC
if( autochoose
|| !strcmp("wget", param.network_backend)
|| !strcmp("curl", param.network_backend) )
return net123_open_exec(url, client_head);
#endif
#ifdef NET123_WININET
if(autochoose || !strcmp("wininet", param.network_backend))
return net123_open_wininet(url, client_head);
#endif
#ifdef NET123_WINHTTP
if(autochoose || !strcmp("winhttp", param.network_backend))
return net123_open_winhttp(url, client_head);
#endif
merror("no network backend for %s", https ? "HTTPS" : "HTTP");
return NULL;
}
#endif
/* Stream dump descriptor. */ /* Stream dump descriptor. */
static int dump_fd = -1; static int dump_fd = -1;
@@ -27,13 +168,9 @@ static int dump_fd = -1;
static ssize_t stream_read_raw(struct stream *sd, void *buf, size_t count) static ssize_t stream_read_raw(struct stream *sd, void *buf, size_t count)
{ {
ssize_t ret = -1; ssize_t ret = -1;
#ifdef NET123 #ifdef NETWORK
if(sd->nh) if(sd->nh)
ret = net123_read(sd->nh, buf, count); ret = (ssize_t) sd->nh->read(sd->nh, buf, count);
#endif
#ifdef WANT_WIN32_SOCKETS
if(sd->fd >= 0 && sd->network)
ret = win32_net_read(sd->fd, buf, count);
#endif #endif
if(sd->fd >= 0) // plain file or network socket if(sd->fd >= 0) // plain file or network socket
ret = (ssize_t) unintr_read(sd->fd, buf, count); ret = (ssize_t) unintr_read(sd->fd, buf, count);
@@ -75,8 +212,12 @@ static ssize_t stream_read(struct stream *sd, void *buf, size_t count)
static off_t stream_seek(struct stream *sd, off_t pos, int whence) static off_t stream_seek(struct stream *sd, off_t pos, int whence)
{ {
if(!sd || sd->network) if(!sd)
return -1; return -1;
#ifdef NET123
if(sd->nh)
return -1;
#endif
return lseek(sd->fd, pos, whence); return lseek(sd->fd, pos, whence);
} }
@@ -147,15 +288,22 @@ ssize_t stream_getline(struct stream *sd, mpg123_string *line)
} }
} }
int stream_parse_headers(struct stream *sd) #ifdef NETWORK
// Return 0 on success, non-zero when there is an error or more work to do.
// -1: error, 1: redirection to given location
static int stream_parse_headers(struct stream *sd, mpg123_string *location)
{ {
int ret = 0; int ret = 0;
mpg123_string line; mpg123_string line;
mpg123_init_string(&line); mpg123_init_string(&line);
mpg123_string icyint; mpg123_string icyint;
mpg123_init_string(&icyint); mpg123_init_string(&icyint);
const char *head[] = { "content-type", "icy-name", "icy-url", "icy-metaint" }; int redirect = 0;
mpg123_string *val[] = { &sd->htd.content_type, &sd->htd.icy_name, &sd->htd.icy_url, &icyint }; location->fill = 0;
const char *head[] = { "content-type", "icy-name"
, "icy-url", "icy-metaint", "location" };
mpg123_string *val[] = { &sd->htd.content_type, &sd->htd.icy_name
, &sd->htd.icy_url, &icyint, location };
int hn = sizeof(head)/sizeof(char*); int hn = sizeof(head)/sizeof(char*);
int hi = -1; int hi = -1;
int got_ok = 0; int got_ok = 0;
@@ -171,6 +319,8 @@ int stream_parse_headers(struct stream *sd)
} }
// React to HTTP error codes, but do not enforce an OK being sent as Shoutcast // React to HTTP error codes, but do not enforce an OK being sent as Shoutcast
// only produces very minimal headers, not even a HTTP response code. // only produces very minimal headers, not even a HTTP response code.
// Well, ICY 200 OK could be there, but then we got other headers to know
// things are fine.
if(!strncasecmp("http/", line.p, 5)) if(!strncasecmp("http/", line.p, 5))
{ {
// HTTP/1.1 200 OK // HTTP/1.1 200 OK
@@ -181,9 +331,17 @@ int stream_parse_headers(struct stream *sd)
++tok; ++tok;
if(tok && *tok != '2') if(tok && *tok != '2')
{ {
merror("HTTP error response: %s", line.p); if(*tok == '3')
ret = -1; {
break; redirect = ret = 1;
if(param.verbose > 2)
fprintf(stderr, "Note: HTTP redirect\n");
} else
{
merror("HTTP error response: %s", line.p);
ret = -1;
break;
}
} else if(tok && *tok == '2') } else if(tok && *tok == '2')
{ {
if(param.verbose > 2) if(param.verbose > 2)
@@ -235,7 +393,7 @@ int stream_parse_headers(struct stream *sd)
continue; continue;
} }
} }
if(icyint.fill) if(!redirect && icyint.fill)
{ {
sd->htd.icy_interval = atol(icyint.p); sd->htd.icy_interval = atol(icyint.p);
if(param.verbose > 1) if(param.verbose > 1)
@@ -245,6 +403,9 @@ int stream_parse_headers(struct stream *sd)
{ {
error("no data at all from network resource"); error("no data at all from network resource");
ret = -1; ret = -1;
} else if(redirect && !location->fill)
{
error("redirect but no location given");
} else if(!got_ok) } else if(!got_ok)
{ {
error("missing positive server response"); error("missing positive server response");
@@ -255,11 +416,84 @@ int stream_parse_headers(struct stream *sd)
return ret; return ret;
} }
// resolve relative locations given the initial full URL
// full URL ensured to either start with http:// or https://
// (case-insensitive), location non-empty
static void relocate_url(mpg123_string *location, const char *url)
{
if(!strncasecmp(location->p, "http://", 7) || !strncasecmp(location->p, "https://", 8))
return;
if(!url || (strncasecmp(url, "http://", 7) && strncasecmp(url, "https://", 8)))
{
mpg123_resize_string(location, 0);
return;
}
if(!param.quiet)
fprintf(stderr, "NOTE: no complete URL in redirect, constructing one\n");
mpg123_string purl;
mpg123_string workbuf;
mpg123_init_string(&purl);
mpg123_init_string(&workbuf);
if(mpg123_set_string(&purl, url) && mpg123_move_string(location, &workbuf))
{
debug1("relocate request_url: %s", purl.p);
// location somewhat relative, either /some/path or even just some/path
char* ptmp = NULL;
// Though it's not RFC (?), accept relative URIs as wget does.
if(workbuf.p[0] == '/')
{
// server-absolute only prepend http://server/
// I null the first / after http:// or https://
size_t off = (purl.p[4] == 's') ? 8 : 7;
ptmp = strchr(purl.p+off,'/');
if(ptmp != NULL)
{
purl.fill = ptmp-purl.p+1;
purl.p[purl.fill-1] = 0;
}
}
else
{
// relative to current directory
// prepend http://server/path/
// first cutting off parameter stuff from URL
for(size_t i=0; i<purl.fill; ++i)
{
if(purl.p[i] == '?' || purl.p[i] == '#')
{
purl.p[i] = 0;
purl.fill = i+1;
break;
}
}
// now the last slash, keeping it
ptmp = strrchr(purl.p, '/');
if(ptmp != NULL)
{
purl.fill = ptmp-purl.p+2;
purl.p[purl.fill-1] = 0;
}
}
// only the prefix left
debug1("prefix=%s", purl.p);
mpg123_add_string(location, purl.p);
}
mpg123_add_string(location, workbuf.p);
mpg123_free_string(&workbuf);
mpg123_free_string(&purl);
}
#endif
static void stream_init(struct stream *sd) static void stream_init(struct stream *sd)
{ {
sd->bufp = sd->buf; sd->bufp = sd->buf;
sd->fill = 0; sd->fill = 0;
sd->network = 0;
sd->fd = -1; sd->fd = -1;
#ifdef NET123 #ifdef NET123
sd->nh = NULL; sd->nh = NULL;
@@ -267,6 +501,24 @@ static void stream_init(struct stream *sd)
httpdata_init(&sd->htd); httpdata_init(&sd->htd);
} }
// Clean up things for another connection.
// Does not reset the network flag.
static void stream_reset(struct stream *sd)
{
#ifdef NET123
if(sd->nh)
sd->nh->close(sd->nh);
sd->nh = NULL;
#endif
if(sd->fd >= 0) // plain file or network socket
close(sd->fd);
sd->fd = -1;
httpdata_free(&sd->htd);
httpdata_init(&sd->htd);
sd->bufp = sd->buf;
sd->fill = 0;
}
struct stream *stream_open(const char *url) struct stream *stream_open(const char *url)
{ {
struct stream *sd = malloc(sizeof(struct stream)); struct stream *sd = malloc(sizeof(struct stream));
@@ -279,10 +531,9 @@ struct stream *stream_open(const char *url)
sd->fd = STDIN_FILENO; sd->fd = STDIN_FILENO;
compat_binmode(STDIN_FILENO, TRUE); compat_binmode(STDIN_FILENO, TRUE);
} }
#ifdef NET123 #ifdef NETWORK
else if(!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8)) else if(!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8))
{ {
sd->network = 1;
// Network stream with header parsing. // Network stream with header parsing.
const char *client_head[] = { NULL, NULL, NULL }; const char *client_head[] = { NULL, NULL, NULL };
client_head[0] = param.talk_icy ? icy_yes : icy_no; client_head[0] = param.talk_icy ? icy_yes : icy_no;
@@ -290,26 +541,51 @@ struct stream *stream_open(const char *url)
mpg123_init_string(&accept); mpg123_init_string(&accept);
append_accept(&accept); append_accept(&accept);
client_head[1] = accept.p; client_head[1] = accept.p;
sd->nh = net123_open(url, client_head); mpg123_string location;
if(!sd->nh || stream_parse_headers(sd)) mpg123_string urlcopy;
mpg123_init_string(&location);
mpg123_init_string(&urlcopy);
int numrelocs = 0;
while(sd)
{ {
stream_close(sd); sd->nh = net123_open(url, client_head, &sd->htd);
return NULL; if(!sd->nh)
} {
} stream_close(sd);
#elif defined(NETWORK) sd = NULL;
else if(!strncasecmp("http://", url, 7)) break;
{ }
#ifdef WANT_WIN32_SOCKETS location.fill = 0;
sd->fd = win32_net_http_open(url, &sd->htd); if(stream_parse_headers(sd, &location))
#else {
sd->fd = http_open(url, &sd->htd); stream_reset(sd);
#endif if(location.fill)
if(sd->fd < 0) {
{ if(++numrelocs > HTTP_MAX_RELOCATIONS)
stream_close(sd); {
return NULL; merror("too many HTTP redirections: %i", numrelocs);
url = NULL;
} else
{
relocate_url(&location, url); // resolve relative locations
mpg123_copy_string(&location, &urlcopy);
url = urlcopy.p;
}
} else
{
url = NULL;
}
if(!url)
{
stream_close(sd);
sd = NULL;
}
} else break; // Successful end.
} }
mpg123_free_string(&urlcopy);
mpg123_free_string(&location);
mpg123_free_string(&accept);
// Either sd is NULL or we got a stream ready.
} }
#endif #endif
else else
@@ -333,20 +609,7 @@ void stream_close(struct stream *sd)
{ {
if(!sd) if(!sd)
return; return;
#ifdef NET123 stream_reset(sd);
if(sd->nh)
net123_close(sd->nh);
#endif
#ifdef WANT_WIN32_SOCKETS
if(sd->fd >= 0 && sd->network)
{
if(sd->fd != SOCKET_ERROR)
win32_net_close(sd->fd);
}
#endif
if(sd->fd >= 0) // plain file or network socket
close(sd->fd);
httpdata_free(&sd->htd);
free(sd); free(sd);
} }
@@ -419,12 +682,7 @@ int dump_setup(struct stream *sd, mpg123_handle *mh)
ret = mpg123_open_handle(mh, sd); ret = mpg123_open_handle(mh, sd);
} else } else
{ {
#ifdef WANT_WIN32_SOCKETS mpg123_replace_reader(mh, NULL, NULL);
if(sd->network)
win32_net_replace(mh);
else // ensure libmpg123 is using its own reader otherwise
#endif
mpg123_replace_reader(mh, NULL, NULL);
ret = mpg123_open_fd(mh, sd->fd); ret = mpg123_open_fd(mh, sd->fd);
} }
if(ret != MPG123_OK) if(ret != MPG123_OK)

View File

@@ -18,6 +18,9 @@
#ifdef NET123 #ifdef NET123
#include "net123.h" #include "net123.h"
#endif #endif
#ifdef NETWORK
#include "httpget.h"
#endif
// The stream is either addressed via file descriptor or net123 handle. // The stream is either addressed via file descriptor or net123 handle.
struct stream struct stream
@@ -25,7 +28,6 @@ struct stream
char buf[256]; // buffer for getline char buf[256]; // buffer for getline
char *bufp; // read pointer in buffer char *bufp; // read pointer in buffer
int fill; // bytes in buffer int fill; // bytes in buffer
int network; // flag to mark network streams (with httpdata)
int fd; // if > 0: plain file descriptor or win32 net socket int fd; // if > 0: plain file descriptor or win32 net socket
struct httpdata htd; struct httpdata htd;
#ifdef NET123 #ifdef NET123

View File

@@ -17,22 +17,26 @@
#include "debug.h" #include "debug.h"
static int term_enable = 0; static int term_enable = 0;
static const char *extrabreak = "";
int seeking = FALSE; int seeking = FALSE;
extern out123_handle *ao; extern out123_handle *ao;
static const int helplen = 18;
#define HELPFMT "%-18s"
/* Hm, next step would be some system in this, plus configurability... /* Hm, next step would be some system in this, plus configurability...
Two keys for everything? It's just stop/pause for now... */ Two keys for everything? It's just stop/pause for now... */
struct keydef { const char key; const char key2; const char* desc; }; struct keydef { const char key; const char key2; const char* desc; };
struct keydef term_help[] = struct keydef term_help[] =
{ {
{ MPG123_STOP_KEY, ' ', "interrupt/restart playback (i.e. '(un)pause')" } { MPG123_STOP_KEY, ' ', "(un)pause playback" }
,{ MPG123_NEXT_KEY, 0, "next track" } ,{ MPG123_NEXT_KEY, 0, "next track" }
,{ MPG123_PREV_KEY, 0, "previous track" } ,{ MPG123_PREV_KEY, 0, "previous track" }
,{ MPG123_NEXT_DIR_KEY, 0, "next directory (next track until directory part changes)" } ,{ MPG123_NEXT_DIR_KEY, 0, "next directory" }
,{ MPG123_PREV_DIR_KEY, 0, "previous directory (previous track until directory part changes)" } ,{ MPG123_PREV_DIR_KEY, 0, "previous directory" }
,{ MPG123_BACK_KEY, 0, "back to beginning of track" } ,{ MPG123_BACK_KEY, 0, "back to beginning" }
,{ MPG123_PAUSE_KEY, 0, "loop around current position (don't combine with output buffer)" } ,{ MPG123_PAUSE_KEY, 0, "loop (--pauseloop)" }
,{ MPG123_FORWARD_KEY, 0, "forward" } ,{ MPG123_FORWARD_KEY, 0, "forward" }
,{ MPG123_REWIND_KEY, 0, "rewind" } ,{ MPG123_REWIND_KEY, 0, "rewind" }
,{ MPG123_FAST_FORWARD_KEY, 0, "fast forward" } ,{ MPG123_FAST_FORWARD_KEY, 0, "fast forward" }
@@ -42,19 +46,19 @@ struct keydef term_help[] =
,{ MPG123_VOL_UP_KEY, 0, "volume up" } ,{ MPG123_VOL_UP_KEY, 0, "volume up" }
,{ MPG123_VOL_DOWN_KEY, 0, "volume down" } ,{ MPG123_VOL_DOWN_KEY, 0, "volume down" }
,{ MPG123_VOL_MUTE_KEY, 0, "(un)mute volume" } ,{ MPG123_VOL_MUTE_KEY, 0, "(un)mute volume" }
,{ MPG123_RVA_KEY, 0, "RVA switch" } ,{ MPG123_RVA_KEY, 0, "cycle RVA modes" }
,{ MPG123_VERBOSE_KEY, 0, "verbose switch" } ,{ MPG123_VERBOSE_KEY, 0, "cycle verbosity" }
,{ MPG123_PLAYLIST_KEY, 0, "list current playlist, indicating current track there" } ,{ MPG123_PLAYLIST_KEY, 0, "show playlist" }
,{ MPG123_TAG_KEY, 0, "display tag info (again)" } ,{ MPG123_TAG_KEY, 0, "tag info" }
,{ MPG123_MPEG_KEY, 0, "print MPEG header info (again)" } ,{ MPG123_MPEG_KEY, 0, "MPEG header info" }
,{ MPG123_PITCH_UP_KEY, MPG123_PITCH_BUP_KEY, "pitch up (small step, big step)" } ,{ MPG123_PITCH_UP_KEY, MPG123_PITCH_BUP_KEY, "pitch up + ++" }
,{ MPG123_PITCH_DOWN_KEY, MPG123_PITCH_BDOWN_KEY, "pitch down (small step, big step)" } ,{ MPG123_PITCH_DOWN_KEY, MPG123_PITCH_BDOWN_KEY, "pitch down - --" }
,{ MPG123_PITCH_ZERO_KEY, 0, "reset pitch to zero" } ,{ MPG123_PITCH_ZERO_KEY, 0, "zero pitch" }
,{ MPG123_BOOKMARK_KEY, 0, "print out current position in playlist and track, for the benefit of some external tool to store bookmarks" } ,{ MPG123_BOOKMARK_KEY, 0, "print bookmark" }
,{ MPG123_HELP_KEY, 0, "this help" } ,{ MPG123_HELP_KEY, 0, "this help" }
,{ MPG123_QUIT_KEY, 0, "quit" } ,{ MPG123_QUIT_KEY, 0, "quit" }
,{ MPG123_EQ_RESET_KEY, 0, "reset to a flat equalizer" } ,{ MPG123_EQ_RESET_KEY, 0, "flat equalizer" }
,{ MPG123_EQ_SHOW_KEY, 0, "show our current rough equalizer settings" } ,{ MPG123_EQ_SHOW_KEY, 0, "show equalizer" }
,{ MPG123_BASS_UP_KEY, 0, "more bass" } ,{ MPG123_BASS_UP_KEY, 0, "more bass" }
,{ MPG123_BASS_DOWN_KEY, 0, "less bass" } ,{ MPG123_BASS_DOWN_KEY, 0, "less bass" }
,{ MPG123_MID_UP_KEY, 0, "more mids" } ,{ MPG123_MID_UP_KEY, 0, "more mids" }
@@ -64,7 +68,7 @@ struct keydef term_help[] =
}; };
/* initialze terminal */ /* initialze terminal */
void term_init(void) int term_init(void)
{ {
const char hide_cursor[] = "\x1b[?25l"; const char hide_cursor[] = "\x1b[?25l";
debug("term_init"); debug("term_init");
@@ -72,9 +76,11 @@ void term_init(void)
if(term_have_fun(STDERR_FILENO, param.term_visual)) if(term_have_fun(STDERR_FILENO, param.term_visual))
fprintf(stderr, "%s", hide_cursor); fprintf(stderr, "%s", hide_cursor);
if(param.verbose)
extrabreak = "\n";
debug1("param.term_ctrl: %i", param.term_ctrl); debug1("param.term_ctrl: %i", param.term_ctrl);
if(!param.term_ctrl) if(!param.term_ctrl)
return; return 0;
term_enable = 0; term_enable = 0;
errno = 0; errno = 0;
@@ -84,9 +90,10 @@ void term_init(void)
merror("failed to set up terminal: %s", strerror(errno)); merror("failed to set up terminal: %s", strerror(errno));
else else
error("failed to set up terminal"); error("failed to set up terminal");
return; return -1;
} }
term_enable = 1; term_enable = 1;
return 0;
} }
void term_hint(void) void term_hint(void)
@@ -127,7 +134,7 @@ void pause_recycle(mpg123_handle *fr)
{ {
/* Take care not to go backwards in time in steps of 1 frame /* Take care not to go backwards in time in steps of 1 frame
That is what the +1 is for. */ That is what the +1 is for. */
pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr)); pause_cycle=(int)(param.pauseloop/mpg123_tpf(fr));
offset-=pause_cycle; offset-=pause_cycle;
} }
@@ -153,7 +160,7 @@ off_t term_control(mpg123_handle *fr, out123_handle *ao)
do do
{ {
off_t old_offset = offset; off_t old_offset = offset;
term_handle_input(fr, ao, stopped|seeking); term_handle_input(fr, ao, seeking);
if((offset < 0) && (-offset > framenum)) offset = - framenum; if((offset < 0) && (-offset > framenum)) offset = - framenum;
if(param.verbose && offset != old_offset) if(param.verbose && offset != old_offset)
print_stat(fr,offset,ao,1,&param); print_stat(fr,offset,ao,1,&param);
@@ -204,6 +211,20 @@ static void seekmode(mpg123_handle *mh, out123_handle *ao)
} }
} }
static void print_term_help(struct keydef *def)
{
if(def->key2)
{
if(isspace(def->key2))
fprintf(stderr, "%c '%c'", def->key, def->key2);
else
fprintf(stderr, "%c %c ", def->key, def->key2);
}
else fprintf(stderr, "%c ", def->key);
fprintf(stderr, " " HELPFMT, def->desc);
}
static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val) static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
{ {
debug1("term_handle_key: %c", val); debug1("term_handle_key: %c", val);
@@ -212,7 +233,7 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
case MPG123_BACK_KEY: case MPG123_BACK_KEY:
out123_pause(ao); out123_pause(ao);
out123_drop(ao); out123_drop(ao);
if(paused) pause_cycle=(int)(LOOP_CYCLES/mpg123_tpf(fr)); if(paused) pause_cycle=(int)(param.pauseloop/mpg123_tpf(fr));
if(mpg123_seek_frame(fr, 0, SEEK_SET) < 0) if(mpg123_seek_frame(fr, 0, SEEK_SET) < 0)
error1("Seek to begin failed: %s", mpg123_strerror(fr)); error1("Seek to begin failed: %s", mpg123_strerror(fr));
@@ -232,8 +253,9 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
case MPG123_QUIT_KEY: case MPG123_QUIT_KEY:
debug("QUIT"); debug("QUIT");
if(stopped) if(stopped)
{ if(param.verbose) {
print_stat(fr,0,ao,0,&param); if(param.verbose)
print_stat(fr,0,ao,0,&param);
stopped = 0; stopped = 0;
out123_pause(ao); /* no chance for annoying underrun warnings */ out123_pause(ao); /* no chance for annoying underrun warnings */
@@ -244,13 +266,23 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
break; break;
case MPG123_PAUSE_KEY: case MPG123_PAUSE_KEY:
paused=1-paused; paused=1-paused;
size_t buffered = out123_buffered(ao);
out123_pause(ao); /* underrun awareness */ out123_pause(ao); /* underrun awareness */
out123_drop(ao); out123_drop(ao);
if(paused) if(paused)
{ {
/* Not really sure if that is what is wanted // Make output buffer react immediately, dropping decoded audio
This jumps in audio output, but has direct reaction to pausing loop. */ // and (at least trying to) seeking back in input.
out123_param_float(ao, OUT123_PRELOAD, 0.); out123_param_float(ao, OUT123_PRELOAD, 0.);
if(buffered)
{
int framesize = 1;
if(!out123_getformat(ao, NULL, NULL, NULL, &framesize))
{
buffered /= framesize;
mpg123_seek(fr, -buffered, SEEK_CUR);
}
}
pause_recycle(fr); pause_recycle(fr);
} }
else else
@@ -326,7 +358,8 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
print_stat(fr,0,ao,0,&param); print_stat(fr,0,ao,0,&param);
// Assuming only changes happen via terminal control, these 3 values // Assuming only changes happen via terminal control, these 3 values
// are what counts. // are what counts.
fprintf( stderr, "\n\nbass: %.3f\nmid: %.3f\ntreble: %.3f\n\n" fprintf( stderr, "%s\nbass: %.3f\nmid: %.3f\ntreble: %.3f\n\n"
, extrabreak
, mpg123_geteq(fr, MPG123_LEFT, 0) , mpg123_geteq(fr, MPG123_LEFT, 0)
, mpg123_geteq(fr, MPG123_LEFT, 1) , mpg123_geteq(fr, MPG123_LEFT, 1)
, mpg123_geteq(fr, MPG123_LEFT, 2) , mpg123_geteq(fr, MPG123_LEFT, 2)
@@ -381,7 +414,9 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
{ {
param.verbose = 0; param.verbose = 0;
clear_stat(); clear_stat();
} extrabreak = "";
} else
extrabreak = "\n";
mpg123_param(fr, MPG123_VERBOSE, param.verbose, 0); mpg123_param(fr, MPG123_VERBOSE, param.verbose, 0);
break; break;
case MPG123_RVA_KEY: case MPG123_RVA_KEY:
@@ -412,34 +447,38 @@ static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
case MPG123_TAG_KEY: case MPG123_TAG_KEY:
if(param.verbose) if(param.verbose)
print_stat(fr,0,ao,0,&param); print_stat(fr,0,ao,0,&param);
fprintf(stderr, "%s\n", param.verbose ? "\n" : ""); fprintf(stderr, "%s", extrabreak);
print_id3_tag(fr, param.long_id3, stderr, term_width(STDERR_FILENO)); print_id3_tag(fr, param.long_id3, stderr, term_width(STDERR_FILENO));
break; break;
case MPG123_MPEG_KEY: case MPG123_MPEG_KEY:
if(param.verbose) if(param.verbose)
print_stat(fr,0,ao,0,&param); print_stat(fr,0,ao,0,&param);
fprintf(stderr, "\n"); fprintf(stderr, "%s", extrabreak);
if(param.verbose > 1) if(param.verbose > 1)
print_header(fr); print_header(fr);
else else
print_header_compact(fr); print_header_compact(fr);
fprintf(stderr, "\n");
break; break;
case MPG123_HELP_KEY: case MPG123_HELP_KEY:
{ /* This is more than the one-liner before, but it's less spaghetti. */ { /* This is more than the one-liner before, but it's less spaghetti. */
int i; int i;
if(param.verbose) if(param.verbose)
print_stat(fr,0,ao,0,&param); print_stat(fr,0,ao,0,&param);
fprintf(stderr,"\n\n -= terminal control keys =-\n"); fprintf(stderr,"%s\n -= terminal control keys =-\n\n", extrabreak);
int linelen = term_width(STDERR_FILENO);
int colwidth = helplen+6;
int columns = linelen > colwidth ? ((linelen+2)/(colwidth+2)) : 1;
int j = 0;
for(i=0; i<(sizeof(term_help)/sizeof(struct keydef)); ++i) for(i=0; i<(sizeof(term_help)/sizeof(struct keydef)); ++i)
{ {
if(term_help[i].key2) fprintf(stderr, "[%c] or [%c]", term_help[i].key, term_help[i].key2); if(j)
else fprintf(stderr, "[%c]", term_help[i].key); fprintf(stderr, " ");
print_term_help(term_help+i);
fprintf(stderr, "\t%s\n", term_help[i].desc); j = (j+1)%columns;
if(!j)
fprintf(stderr, "\n");
} }
fprintf(stderr, "\nAlso, the number row (starting at 1, ending at 0) gives you jump points into the current track at 10%% intervals.\n"); fprintf(stderr, "\n\nNumber row jumps in 10%% steps.\n\n");
fprintf(stderr, "\n");
} }
break; break;
case MPG123_FRAME_INDEX_KEY: case MPG123_FRAME_INDEX_KEY:
@@ -508,7 +547,7 @@ static void term_handle_input(mpg123_handle *fr, out123_handle *ao, int do_delay
{ {
char val; char val;
/* Do we really want that while loop? This means possibly handling multiple inputs that come very rapidly in one go. */ /* Do we really want that while loop? This means possibly handling multiple inputs that come very rapidly in one go. */
while(term_get_key(do_delay, &val)) while(term_get_key(stopped, do_delay, &val))
{ {
term_handle_key(fr, ao, val); term_handle_key(fr, ao, val);
} }

View File

@@ -12,8 +12,6 @@
#include "mpg123app.h" #include "mpg123app.h"
#include "audio.h" #include "audio.h"
#define LOOP_CYCLES 0.500000 /* Loop time in sec */
/* /*
* Defines the keybindings in term.c - change to your * Defines the keybindings in term.c - change to your
* own preferences. * own preferences.
@@ -87,7 +85,7 @@
#define MPG123_TERM_USR2 "f" #define MPG123_TERM_USR2 "f"
void term_init(void); int term_init(void); // -1 on error, 0 success or no terminal desired
void term_exit(void); void term_exit(void);
off_t term_control(mpg123_handle *mh, out123_handle *ao); off_t term_control(mpg123_handle *mh, out123_handle *ao);
void term_hint(void); /* Print a message hinting at terminal usage. */ void term_hint(void); /* Print a message hinting at terminal usage. */

View File

@@ -25,7 +25,7 @@ void term_restore(void)
{ {
} }
int term_get_key(int do_delay, char *val) int term_get_key(int stopped, int do_delay, char *val)
{ {
return 0; return 0;
} }

View File

@@ -8,6 +8,10 @@
initially written by Thomas Orgis initially written by Thomas Orgis
*/ */
// ctermid
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
#include "config.h" #include "config.h"
#ifdef __OS2__ #ifdef __OS2__
@@ -176,7 +180,7 @@ int term_setup(void)
/* Get the next pressed key, if any. /* Get the next pressed key, if any.
Returns 1 when there is a key, 0 if not. */ Returns 1 when there is a key, 0 if not. */
int term_get_key(int do_delay, char *val) int term_get_key(int stopped, int do_delay, char *val)
{ {
#ifdef __OS2__ #ifdef __OS2__
KBDKEYINFO key; KBDKEYINFO key;
@@ -184,7 +188,7 @@ int term_get_key(int do_delay, char *val)
key.chScan = 0; key.chScan = 0;
if(do_delay) if(do_delay)
DosSleep(10); DosSleep(10);
if(!KbdCharIn(&key,IO_NOWAIT,0) && key.chChar) if(!KbdCharIn(&key,(stopped) ? IO_WAIT : IO_NOWAIT,0) && key.chChar)
{ {
*val = key.chChar; *val = key.chChar;
return 1; return 1;
@@ -207,7 +211,8 @@ int term_get_key(int do_delay, char *val)
FD_ZERO(&r); FD_ZERO(&r);
FD_SET(term_fd,&r); FD_SET(term_fd,&r);
if(select(term_fd+1,&r,NULL,NULL,&t) > 0 && FD_ISSET(term_fd,&r)) /* No timeout if stopped */
if(select(term_fd+1,&r,NULL,NULL,(stopped) ? NULL : &t) > 0 && FD_ISSET(term_fd,&r))
{ {
if(read(term_fd,val,1) <= 0) if(read(term_fd,val,1) <= 0)
return 0; /* Well, we couldn't read the key, so there is none. */ return 0; /* Well, we couldn't read the key, so there is none. */

View File

@@ -90,7 +90,7 @@ int term_present(void){
/* Get the next pressed key, if any. /* Get the next pressed key, if any.
Returns 1 when there is a key, 0 if not. */ Returns 1 when there is a key, 0 if not. */
int term_get_key(int do_delay, char *val){ int term_get_key(int stopped, int do_delay, char *val){
INPUT_RECORD record; INPUT_RECORD record;
HANDLE input; HANDLE input;
DWORD res; DWORD res;
@@ -99,7 +99,7 @@ int term_get_key(int do_delay, char *val){
if(input == NULL || input == INVALID_HANDLE_VALUE) if(input == NULL || input == INVALID_HANDLE_VALUE)
return 0; return 0;
while(WaitForSingleObject(input, do_delay ? 10 : 0) == WAIT_OBJECT_0){ while(WaitForSingleObject(input, stopped ? INFINITE : (do_delay ? 10 : 0)) == WAIT_OBJECT_0){
do_delay = 0; do_delay = 0;
if(!ReadConsoleInput(input, &record, 1, &res)) if(!ReadConsoleInput(input, &record, 1, &res))
return 0; return 0;

View File

@@ -47,6 +47,6 @@ void term_restore(void);
* \param val address to store character to * \param val address to store character to
* \return 1 if there is a key, 0 if not * \return 1 if there is a key, 0 if not
*/ */
int term_get_key(int do_delay, char *val); int term_get_key(int stopped, int do_delay, char *val);
#endif #endif

View File

@@ -86,7 +86,7 @@ int main(int argc, char **argv)
fprintf(stderr,"1to1 non-indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs[1],(size_p)samples); fprintf(stderr,"1to1 non-indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs[1],(size_p)samples);
fprintf(stderr,"NtoM indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs_ntom[0],(size_p)samples); fprintf(stderr,"NtoM indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs_ntom[0],(size_p)samples);
fprintf(stderr,"NtoM non-indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs_ntom[1],(size_p)samples); fprintf(stderr,"NtoM non-indexed seek errors: %"SIZE_P" / %"SIZE_P"\n", (size_p)errs_ntom[1],(size_p)samples);
fprintf(stderr,"Errors in getting first sample again: %"SIZE_P"\n", first_sample_errs); fprintf(stderr,"Errors in getting first sample again: %"SIZE_P"\n", (size_p)first_sample_errs);
fprintf(stderr,"\n"); fprintf(stderr,"\n");
if(ret == 0) if(ret == 0)

View File

@@ -1,14 +1,7 @@
#include "config.h" #include "win32_support.h"
#include "mpg123.h"
#include "mpg123app.h" #include "mpg123app.h"
#include "httpget.h"
#include "resolver.h"
#include "compat.h"
#include <errno.h>
#include "debug.h" #include "debug.h"
#if defined (WANT_WIN32_SOCKETS)
#ifdef DEBUG #ifdef DEBUG
#define msgme(x) win32_net_msg(x,__FILE__,__LINE__) #define msgme(x) win32_net_msg(x,__FILE__,__LINE__)
#define msgme1 win32_net_msg(1,__FILE__,__LINE__) #define msgme1 win32_net_msg(1,__FILE__,__LINE__)
@@ -115,28 +108,6 @@ static int get_sock_ch (int sock)
return (((int) c)&0xff); return (((int) c)&0xff);
return -1; return -1;
} }
/* Addapted from from newlib*/
char *win32_net_fgets(char *s, int n, int stream)
{
char c = 0;
char *buf;
buf = s;
debug1("Pseudo net fgets attempts to read %d bytes from network.", n - 1);
while (--n > 0 && (c = get_sock_ch (stream)) != -1)
{
*s++ = c;
if (c == '\n' || c == '\r')
break;
}
debug1("Pseudo net fgets got %"SIZE_P" bytes.", (size_p)(s - buf));
if (c == -1 && s == buf)
{
debug("Pseudo net fgets met a premature end.");
return NULL;
}
*s = 0;
return buf;
}
ssize_t win32_net_write (int fildes, const void *buf, size_t nbyte) ssize_t win32_net_write (int fildes, const void *buf, size_t nbyte)
{ {
@@ -148,18 +119,6 @@ ssize_t win32_net_write (int fildes, const void *buf, size_t nbyte)
return ret; return ret;
} }
off_t win32_net_lseek (int a, off_t b, int c)
{
debug("lseek on a socket called!");
return -1;
}
void win32_net_replace (mpg123_handle *fr)
{
debug("win32_net_replace ran");
mpg123_replace_reader(fr, win32_net_read, win32_net_lseek);
}
static int win32_net_timeout_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) static int win32_net_timeout_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
{ {
debug("win32_net_timeout_connect ran"); debug("win32_net_timeout_connect ran");
@@ -239,7 +198,7 @@ static int win32_net_timeout_connect(int sockfd, const struct sockaddr *serv_add
} }
} }
static int win32_net_open_connection(mpg123_string *host, mpg123_string *port) int win32_net_open_connection(mpg123_string *host, mpg123_string *port)
{ {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *addr, *addrlist; struct addrinfo *addr, *addrlist;
@@ -286,52 +245,10 @@ static int win32_net_open_connection(mpg123_string *host, mpg123_string *port)
} }
freeaddrinfo(addrlist); freeaddrinfo(addrlist);
return 1; return ws.local_socket == SOCKET_ERROR ? -1 : 1;
} }
static size_t win32_net_readstring (mpg123_string *string, size_t maxlen, int fd) int win32_net_writestring (int fd, mpg123_string *string)
{
debug2("Attempting readstring on %d for %"SIZE_P" bytes", fd, (size_p)maxlen);
int err;
string->fill = 0;
while(maxlen == 0 || string->fill < maxlen)
{
if(string->size-string->fill < 1)
if(!mpg123_grow_string(string, string->fill+4096))
{
error("Cannot allocate memory for reading.");
string->fill = 0;
return 0;
}
err = win32_net_read(0,string->p+string->fill,1); /*fd is ignored */
/* Whoa... reading one byte at a time... one could ensure the line break in another way, but more work. */
if( err == 1)
{
string->fill++;
if(string->p[string->fill-1] == '\n') break;
}
else if(errno != EINTR)
{
error("Error reading from socket or unexpected EOF.");
string->fill = 0;
/* bail out to prevent endless loop */
return 0;
}
}
if(!mpg123_grow_string(string, string->fill+1))
{
string->fill=0;
}
else
{
string->p[string->fill] = 0;
string->fill++;
}
return string->fill;
}
static int win32_net_writestring (int fd, mpg123_string *string)
{ {
size_t result, bytes; size_t result, bytes;
char *ptr = string->p; char *ptr = string->p;
@@ -355,253 +272,3 @@ static int win32_net_writestring (int fd, mpg123_string *string)
} }
return TRUE; return TRUE;
} }
static int win32_net_resolve_redirect(mpg123_string *response, mpg123_string *request_url, mpg123_string *purl)
{
debug1("request_url:%s", request_url->p);
/* initialized with full old url */
if(!mpg123_copy_string(request_url, purl)) return FALSE;
/* We may strip it down to a prefix ot totally. */
if(strncasecmp(response->p, "Location: http://", 17))
{ /* OK, only partial strip, need prefix for relative path. */
char* ptmp = NULL;
/* though it's not RFC (?), accept relative URIs as wget does */
fprintf(stderr, "NOTE: no complete URL in redirect, constructing one\n");
/* not absolute uri, could still be server-absolute */
/* I prepend a part of the request... out of the request */
if(response->p[10] == '/')
{
/* only prepend http://server/ */
/* I null the first / after http:// */
ptmp = strchr(purl->p+7,'/');
if(ptmp != NULL){ purl->fill = ptmp-purl->p+1; purl->p[purl->fill-1] = 0; }
}
else
{
/* prepend http://server/path/ */
/* now we want the last / */
ptmp = strrchr(purl->p+7, '/');
if(ptmp != NULL){ purl->fill = ptmp-purl->p+2; purl->p[purl->fill-1] = 0; }
}
}
else purl->fill = 0;
debug1("prefix=%s", purl->fill ? purl->p : "");
if(!mpg123_add_string(purl, response->p+10)) return FALSE;
debug1(" purl: %s", purl->p);
debug1("old request_url: %s", request_url->p);
return TRUE;
}
int win32_net_http_open(const char* url, struct httpdata *hd)
{
mpg123_string purl, host, port, path;
mpg123_string request, response, request_url;
mpg123_string httpauth1;
ws.local_socket = SOCKET_ERROR;
int oom = 0;
int relocate, numrelocs = 0;
int got_location = FALSE;
/*
workaround for http://www.global24music.com/rautemusik/files/extreme/isdn.pls
this site's apache gives me a relocation to the same place when I give the port in Host request field
for the record: Apache/2.0.51 (Fedora)
*/
int try_without_port = 0;
mpg123_init_string(&purl);
mpg123_init_string(&host);
mpg123_init_string(&port);
mpg123_init_string(&path);
mpg123_init_string(&request);
mpg123_init_string(&response);
mpg123_init_string(&request_url);
mpg123_init_string(&httpauth1);
/* Get initial info for proxy server. Once. */
if(hd->proxystate == PROXY_UNKNOWN && !proxy_init(hd)) goto exit;
if(!translate_url(url, &purl)){ oom=1; goto exit; }
/* Don't confuse the different auth strings... */
if(!split_url(&purl, &httpauth1, NULL, NULL, NULL) ){ oom=1; goto exit; }
/* "GET http://" 11
* " HTTP/1.0\r\nUser-Agent: <PACKAGE_NAME>/<PACKAGE_VERSION>\r\n"
* 26 + PACKAGE_NAME + PACKAGE_VERSION
* accept header + accept_length()
* "Authorization: Basic \r\n" 23
* "\r\n" 2
* ... plus the other predefined header lines
*/
/* Just use this estimate as first guess to reduce malloc calls in string library. */
{
size_t length_estimate = 62 + strlen(PACKAGE_NAME) + strlen(PACKAGE_VERSION)
+ accept_length() + strlen(CONN_HEAD) + strlen(icy_yes) + purl.fill;
if( !mpg123_grow_string(&request, length_estimate)
|| !mpg123_grow_string(&response,4096) )
{
oom=1; goto exit;
}
}
do
{
/* Storing the request url, with http:// prepended if needed. */
/* used to be url here... seemed wrong to me (when loop advanced...) */
if(strncasecmp(purl.p, "http://", 7) != 0) mpg123_set_string(&request_url, "http://");
else mpg123_set_string(&request_url, "");
mpg123_add_string(&request_url, purl.p);
if(!split_url(&purl, NULL, &host, &port, &path)){ oom=1; goto exit; }
if (hd->proxystate >= PROXY_HOST)
{
/* We will connect to proxy, full URL goes into the request. */
if( !mpg123_set_string(&request, "GET ")
|| !mpg123_add_string(&request, request_url.p) )
{
oom=1; goto exit;
}
}
else
{
/* We will connect to the host from the URL and only the path goes into the request. */
if( !mpg123_set_string(&request, "GET ")
|| !mpg123_add_string(&request, path.p) )
{
oom=1; goto exit;
}
}
if(!fill_request(&request, &host, &port, &httpauth1, &try_without_port)){ oom=1; goto exit; }
httpauth1.fill = 0; /* We use the auth data from the URL only once. */
if (hd->proxystate >= PROXY_HOST)
{
if( !mpg123_copy_string(&hd->proxyhost, &host)
|| !mpg123_copy_string(&hd->proxyport, &port) )
{
oom=1; goto exit;
}
}
debug2("attempting to open_connection to %s:%s", host.p, port.p);
win32_net_open_connection(&host, &port);
if(ws.local_socket == SOCKET_ERROR)
{
error1("Unable to establish connection to %s", host.fill ? host.p : "");
goto exit;
}
debug("win32_net_open_connection succeed");
#define http_failure win32_net_close(ws.local_socket); ws.local_socket=SOCKET_ERROR; goto exit;
if(param.verbose > 2) fprintf(stderr, "HTTP request:\n%s\n",request.p);
if(!win32_net_writestring(ws.local_socket, &request)){ http_failure; }
debug("Skipping fdopen for WSA sockets");
relocate = FALSE;
/* Arbitrary length limit here... */
#define safe_readstring \
win32_net_readstring(&response, SIZE_MAX/16, -1); \
if(response.fill > SIZE_MAX/16) /* > because of appended zero. */ \
{ \
error("HTTP response line exceeds max. length"); \
http_failure; \
} \
else if(response.fill == 0) \
{ \
error("readstring failed"); \
http_failure; \
} \
if(param.verbose > 2) fprintf(stderr, "HTTP in: %s", response.p);
safe_readstring;
{
char *sptr;
if((sptr = strchr(response.p, ' ')))
{
if(response.fill > sptr-response.p+2)
switch (sptr[1])
{
case '3':
relocate = TRUE;
case '2':
break;
default:
fprintf (stderr, "HTTP request failed: %s", sptr+1); /* '\n' is included */
http_failure;
}
else{ error("Too short response,"); http_failure; }
}
}
/* If we are relocated, we need to look out for a Location header. */
got_location = FALSE;
do
{
safe_readstring; /* Think about that: Should we really error out when we get nothing? Could be that the server forgot the trailing empty line... */
if (!strncasecmp(response.p, "Location: ", 10))
{ /* It is a redirection! */
if(!win32_net_resolve_redirect(&response, &request_url, &purl)){ oom=1, http_failure; }
if(!strcmp(purl.p, request_url.p))
{
warning("relocated to very same place! trying request again without host port");
try_without_port = 1;
}
got_location = TRUE;
}
else
{ /* We got a header line (or the closing empty line). */
char *tmp;
debug1("searching for header values... %s", response.p);
/* Not sure if I want to bail out on error here. */
/* Also: What text encoding are these strings in? Doesn't need to be plain ASCII... */
get_header_string(&response, "content-type", &hd->content_type);
get_header_string(&response, "icy-name", &hd->icy_name);
get_header_string(&response, "icy-url", &hd->icy_url);
/* watch out for icy-metaint */
if((tmp = get_header_val("icy-metaint", &response)))
{
hd->icy_interval = (off_t) atol(tmp); /* atoll ? */
debug1("got icy-metaint %li", (long int)hd->icy_interval);
}
}
} while(response.p[0] != '\r' && response.p[0] != '\n');
if (relocate) { win32_net_close(ws.local_socket); ws.local_socket=SOCKET_ERROR; }
} while(relocate && got_location && purl.fill && numrelocs++ < HTTP_MAX_RELOCATIONS);
if(relocate)
{
if(!got_location)
error("Server meant to redirect but failed to provide a location!");
else
error1("Too many HTTP relocations (%i).", numrelocs);
http_failure;
}
exit: /* The end as well as the exception handling point... */
if(oom) error("Apparently, I ran out of memory or had some bad input data...");
mpg123_free_string(&purl);
mpg123_free_string(&host);
mpg123_free_string(&port);
mpg123_free_string(&path);
mpg123_free_string(&request);
mpg123_free_string(&response);
mpg123_free_string(&request_url);
mpg123_free_string(&httpauth1);
if (ws.local_socket == SOCKET_ERROR || oom)
return -1;
else
return 1;
}
#else
int win32_net_http_open(const char* url, struct httpdata *hd)
{
return -1;
}
#endif /*WANT_WIN32_SOCKETS */

View File

@@ -9,7 +9,6 @@
#include "config.h" #include "config.h"
#include "mpg123.h" #include "mpg123.h"
#include "httpget.h"
#ifdef HAVE_WINDOWS_H #ifdef HAVE_WINDOWS_H
#define WIN32_LEAN_AND_MEAN 1 #define WIN32_LEAN_AND_MEAN 1
@@ -32,15 +31,18 @@
Note: Do not treat return values as valid file/socket handles, they only indicate success/failure. Note: Do not treat return values as valid file/socket handles, they only indicate success/failure.
file descriptors are ignored, only the local ws.local_socket is used for storing socket handle, file descriptors are ignored, only the local ws.local_socket is used for storing socket handle,
so the socket handle is always associated with the last call to win32_net_http_open so the socket handle is always associated with the last call to win32_net_http_open
TODO: Move the socket descriptor/state struct into streamdump.c, which wraps all network
connections. Stored in in nh->parts, it enables multiple sockets being opened.
*/ */
/** /**
* Opens an http URL * Opens an http URL
* @param[in] url URL to open * @param[in] host to connect to
* @param[out] hd http data info * @param[in] port to use
* @return -1 for failure, 1 for success * @return -1 for failure, 1 for success
*/ */
int win32_net_http_open(const char* url, struct httpdata *hd); int win32_net_open_connection(mpg123_string *host, mpg123_string *port);
/** /**
* Reads from network socket * Reads from network socket
@@ -61,13 +63,12 @@ ssize_t win32_net_read (int fildes, void *buf, size_t nbyte);
ssize_t win32_net_write (int fildes, const void *buf, size_t nbyte); ssize_t win32_net_write (int fildes, const void *buf, size_t nbyte);
/** /**
* Similar to fgets - get a string from a stream * Writes a whole mpg123_string to the network socket
* @param[out] s buffer to Write to * @param[in] filedes Value is ignored, last open connection is used.
* @param[in] n bytes of data to read. * @param[in] string the string to write
* @param[in] stream ignored for compatiblity, last open connection is used. * @return TRUE if successful, FALS on error
* @return pointer to s if successful, NULL if failture
*/ */
char *win32_net_fgets(char *s, int n, int stream); int win32_net_writestring (int filedes, mpg123_string *string);
/** /**
* Initialize Winsock 2.2. * Initialize Winsock 2.2.
@@ -84,12 +85,6 @@ void win32_net_deinit (void);
* @param[in] sock value is ignored. * @param[in] sock value is ignored.
*/ */
void win32_net_close (int sock); void win32_net_close (int sock);
/**
* Set reader callback for mpg123_open_fd
* @param[in] fr pointer to a mpg123_handle struct.
*/
void win32_net_replace (mpg123_handle *fr);
#endif #endif
#ifdef WANT_WIN32_UNICODE #ifdef WANT_WIN32_UNICODE