mirror of
http://mpg123.de/trunk/.git
synced 2025-10-28 02:55:29 +03:00
Finished hacking in loadable output module support from branch "njh-outputplugin".
Legacy support allows statically compiling in a single module. Still needs some work, but a quick test on my MacBook worked :) git-svn-id: svn://scm.orgis.org/mpg123/trunk@932 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
257
configure.ac
257
configure.ac
@@ -10,7 +10,7 @@ AC_PREREQ(2.57)
|
|||||||
|
|
||||||
dnl ############# Initialisation
|
dnl ############# Initialisation
|
||||||
|
|
||||||
AC_INIT([mpg123], [0.67], [mpg123-devel@lists.sourceforge.net])
|
AC_INIT([mpg123], [1.0pre1], [mpg123-devel@lists.sourceforge.net])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR(src/mpg123.c)
|
AC_CONFIG_SRCDIR(src/mpg123.c)
|
||||||
AC_CONFIG_AUX_DIR(build)
|
AC_CONFIG_AUX_DIR(build)
|
||||||
@@ -32,12 +32,27 @@ AC_PROG_RANLIB
|
|||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
AC_INLINE
|
AC_INLINE
|
||||||
|
|
||||||
# Check if system supports termios
|
|
||||||
AC_SYS_POSIX_TERMIOS
|
dnl ############# Use Libtool for dynamic module loading
|
||||||
if test "x$ac_cv_sys_posix_termios" = "xyes"; then
|
|
||||||
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
|
dnl Enable building of the libltdl library
|
||||||
[Define this if you have the POSIX termios library])
|
AC_LIBLTDL_INSTALLABLE
|
||||||
fi
|
AC_SUBST(LTDLINCL)
|
||||||
|
AC_SUBST(LIBLTDL)
|
||||||
|
AC_DEFINE(HAVE_LTDL, 1, [ Define if LTDL library is available. ])
|
||||||
|
|
||||||
|
dnl Check for dlopen support
|
||||||
|
AC_LIBTOOL_DLOPEN
|
||||||
|
|
||||||
|
dnl We only want shared libraries by default
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
AC_ENABLE_SHARED
|
||||||
|
|
||||||
|
dnl Configure libtool
|
||||||
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
|
dnl Configure libltdl
|
||||||
|
AC_CONFIG_SUBDIRS(libltdl)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -112,23 +127,23 @@ AC_ARG_WITH([cpu], [
|
|||||||
])
|
])
|
||||||
|
|
||||||
AC_ARG_WITH([audio], [
|
AC_ARG_WITH([audio], [
|
||||||
--with-audio=aix Use AIX audio output sub-system
|
--with-default-audio=aix Use AIX as default audio output sub-system
|
||||||
--with-audio=alib Use Alib audio output sub-system (for HPUX)
|
--with-default-audio=alib Use Alib as default audio output sub-system (for HPUX)
|
||||||
--with-audio=alsa Use ALSA audio output sub-system
|
--with-default-audio=alsa Use ALSA as default audio output sub-system
|
||||||
--with-audio=dummy Use dummy audio (when no sound card is available)
|
--with-default-audio=dummy Use dummy as default audio (when no sound card is available)
|
||||||
--with-audio=esd Use ESoundD audio output sub-system
|
--with-default-audio=esd Use ESoundD as default audio output sub-system
|
||||||
--with-audio=hp Use HP audio output sub-system
|
--with-default-audio=hp Use HP as default audio output sub-system
|
||||||
--with-audio=jack Use JACK low-latency audio server
|
--with-default-audio=jack Use JACK as default low-latency audio server
|
||||||
--with-audio=macosx Use Mac OS X audio output sub-system (CoreAudio)
|
--with-default-audio=macosx Use Mac OS X as default audio output sub-system (CoreAudio)
|
||||||
--with-audio=mint Use MinT audio output sub-system (Atari)
|
--with-default-audio=mint Use MinT as default audio output sub-system (Atari)
|
||||||
--with-audio=nas Use NAS audio output (Network Audio System)
|
--with-default-audio=nas Use NAS as default audio output (Network Audio System)
|
||||||
--with-audio=os2 Use OS2 audio output sub-system
|
--with-default-audio=os2 Use OS2 as default audio output sub-system
|
||||||
--with-audio=oss Use OSS audio output sub-system (/dev/dsp)
|
--with-default-audio=oss Use OSS as default audio output sub-system (/dev/dsp)
|
||||||
--with-audio=portaudio Use PortAudio audio output sub-system
|
--with-default-audio=portaudio Use PortAudio as default audio output sub-system
|
||||||
--with-audio=sdl Use SDL audio output sub-system (Simple DirectMedia Layer)
|
--with-default-audio=pulse Use Pulse audio server as default audio output sub-system
|
||||||
--with-audio=sgi Use SGI audio output sub-system (IRIX)
|
--with-default-audio=sdl Use SDL as default audio output sub-system (Simple DirectMedia Layer)
|
||||||
--with-audio=sun Use Sun audio output sub-system (/dev/audio)
|
--with-default-audio=sgi Use SGI as default audio output sub-system (IRIX)
|
||||||
--with-audio=win32 Use Windows audio output (WinMM)
|
--with-default-audio=sun Use Sun as default audio output sub-system (/dev/audio)
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_ARG_WITH([optimization], [
|
AC_ARG_WITH([optimization], [
|
||||||
@@ -143,6 +158,27 @@ AC_ARG_WITH([seektable], [
|
|||||||
--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
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl ############## Modules
|
||||||
|
|
||||||
|
# Dummy audio output module is alway supported
|
||||||
|
output_modules="dummy"
|
||||||
|
|
||||||
|
# Location that modules are installed to
|
||||||
|
if test x$libdir = 'x${exec_prefix}/lib'; then
|
||||||
|
if test x$prefix = xNONE; then
|
||||||
|
pkglibdir="$ac_default_prefix/lib/$PACKAGE_NAME"
|
||||||
|
else
|
||||||
|
pkglibdir="$prefix/lib/$PACKAGE_NAME"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
pkglibdir="$libdir/$PACKAGE_NAME"
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED([PKGLIBDIR], "$pkglibdir", [Path to installed modules] )
|
||||||
|
AC_SUBST([pkglibdir])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl ############## Assembler, compiler properties
|
dnl ############## Assembler, compiler properties
|
||||||
|
|
||||||
# based on posting from John Dalgliesh <johnd@defyne.org> on ffmpeg (LGPL) mailing list
|
# based on posting from John Dalgliesh <johnd@defyne.org> on ffmpeg (LGPL) mailing list
|
||||||
@@ -191,6 +227,14 @@ dnl ############## Function Checks
|
|||||||
|
|
||||||
AC_FUNC_MMAP
|
AC_FUNC_MMAP
|
||||||
|
|
||||||
|
# Check if system supports termios
|
||||||
|
AC_SYS_POSIX_TERMIOS
|
||||||
|
if test "x$ac_cv_sys_posix_termios" = "xyes"; then
|
||||||
|
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
|
||||||
|
[Define this if you have the POSIX termios library])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Check for sched_setscheduler
|
# Check for sched_setscheduler
|
||||||
AC_CHECK_FUNCS( sched_setscheduler setuid getuid)
|
AC_CHECK_FUNCS( sched_setscheduler setuid getuid)
|
||||||
|
|
||||||
@@ -213,28 +257,41 @@ if test $fifo = "yes" && test $have_mkfifo = "no"; then
|
|||||||
AC_MSG_WARN( [ You forced FIFO code while I think there is no mkfifo() available! ] )
|
AC_MSG_WARN( [ You forced FIFO code while I think there is no mkfifo() available! ] )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl ############## Library Checks
|
|
||||||
|
|
||||||
# Checks for libraries.
|
|
||||||
|
dnl ############## Header and Library Checks
|
||||||
|
|
||||||
|
AC_HEADER_STDC
|
||||||
|
dnl Is it too paranoid to specifically check for stdint.h and limits.h?
|
||||||
|
AC_CHECK_HEADERS([stdlib.h string.h unistd.h sched.h sys/ioctl.h stdint.h limits.h inttypes.h sys/time.h sys/wait.h sys/resource.h signal.h])
|
||||||
|
|
||||||
|
|
||||||
|
# Checks for maths libraries.
|
||||||
AC_CHECK_LIB([m], [sqrt])
|
AC_CHECK_LIB([m], [sqrt])
|
||||||
AC_CHECK_LIB([mx], [powf])
|
AC_CHECK_LIB([mx], [powf])
|
||||||
|
|
||||||
|
|
||||||
# Check for JACK
|
# Check for JACK
|
||||||
PKG_CHECK_MODULES(JACK, jack, HAVE_JACK=yes, HAVE_JACK=no)
|
PKG_CHECK_MODULES(JACK, jack, output_modules="jack $output_modules" HAVE_JACK="yes", HAVE_JACK="no")
|
||||||
|
AC_SUBST( JACK_CFLAGS )
|
||||||
|
AC_SUBST( JACK_LDFLAGS )
|
||||||
|
AC_SUBST( JACK_LIBS )
|
||||||
|
AM_CONDITIONAL( [HAVE_JACK], [test "x$HAVE_JACK" = xyes] )
|
||||||
|
|
||||||
|
# Check for Simple Pulse Audio API
|
||||||
|
PKG_CHECK_MODULES(PULSE, libpulse-simple, output_modules="pulse $output_modules" HAVE_PULSE="yes", HAVE_PULSE="no")
|
||||||
|
AC_SUBST( PULSE_CFLAGS )
|
||||||
|
AC_SUBST( PULSE_LDFLAGS )
|
||||||
|
AC_SUBST( PULSE_LIBS )
|
||||||
|
AM_CONDITIONAL( [HAVE_PULSE], [test "x$HAVE_PULSE" = xyes] )
|
||||||
|
|
||||||
# Check for EsounD
|
# Check for EsounD
|
||||||
PKG_CHECK_MODULES(ESOUND, esound, HAVE_ESOUND=yes, HAVE_ESOUND=no)
|
PKG_CHECK_MODULES(ESOUND, esound, output_modules="esound $output_modules" HAVE_ESOUND="yes", HAVE_ESOUND="no")
|
||||||
|
AC_SUBST( ESOUND_CFLAGS )
|
||||||
|
AC_SUBST( ESOUND_LDFLAGS )
|
||||||
|
AC_SUBST( ESOUND_LIBS )
|
||||||
|
AM_CONDITIONAL( [HAVE_ESOUND], [test "x$HAVE_ESOUND" = xyes] )
|
||||||
|
|
||||||
# Check for SDL
|
|
||||||
PKG_CHECK_MODULES(SDL, sdl, HAVE_SDL=yes, HAVE_SDL=no)
|
|
||||||
|
|
||||||
# Check for NAS
|
|
||||||
AC_CHECK_LIB( [audio], [AuOpenServer],
|
|
||||||
[ AC_CHECK_HEADER( [audio/audiolib.h],
|
|
||||||
[ HAVE_NAS="yes" ],
|
|
||||||
[ AC_MSG_WARN([Found NAS library but NOT header files on your system]) ] )
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for PortAudio
|
# Check for PortAudio
|
||||||
case $target in
|
case $target in
|
||||||
@@ -243,7 +300,7 @@ case $target in
|
|||||||
if test "x$HAVE_PORTAUDIO" != "xyes"; then
|
if test "x$HAVE_PORTAUDIO" != "xyes"; then
|
||||||
AC_CHECK_LIB( [portaudio], [Pa_Initialize],
|
AC_CHECK_LIB( [portaudio], [Pa_Initialize],
|
||||||
[ AC_CHECK_HEADER( [portaudio.h],
|
[ AC_CHECK_HEADER( [portaudio.h],
|
||||||
[ HAVE_PORTAUDIO_WINMM="yes" && HAVE_PORTAUDIO="yes" ],
|
[ output_modules="portaudio $output_modules" HAVE_PORTAUDIO_WINMM="yes" HAVE_PORTAUDIO="yes" ],
|
||||||
[ AC_MSG_WARN([Found PortAudio library but NOT header files on your system]) ] )
|
[ AC_MSG_WARN([Found PortAudio library but NOT header files on your system]) ] )
|
||||||
],
|
],
|
||||||
[ HAVE_PORTAUDIO="no" ],
|
[ HAVE_PORTAUDIO="no" ],
|
||||||
@@ -254,31 +311,78 @@ case $target in
|
|||||||
*)
|
*)
|
||||||
AC_CHECK_LIB( [portaudio], [Pa_Initialize],
|
AC_CHECK_LIB( [portaudio], [Pa_Initialize],
|
||||||
[ AC_CHECK_HEADER( [portaudio.h],
|
[ AC_CHECK_HEADER( [portaudio.h],
|
||||||
[ HAVE_PORTAUDIO="yes" ],
|
[ output_modules="portaudio $output_modules" HAVE_PORTAUDIO="yes" ],
|
||||||
[ AC_MSG_WARN([Found PortAudio library but NOT header files on your system]) ] )
|
[ AC_MSG_WARN([Found PortAudio library but NOT header files on your system]) ] )
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
AM_CONDITIONAL( [HAVE_PORTAUDIO], [test "x$HAVE_PORTAUDIO" = xyes] )
|
||||||
|
|
||||||
|
# Check for SDL
|
||||||
|
PKG_CHECK_MODULES(SDL, sdl, output_modules="sdl $output_modules" HAVE_SDL="yes", HAVE_SDL="no")
|
||||||
|
AC_SUBST( SDL_CFLAGS )
|
||||||
|
AC_SUBST( SDL_LDFLAGS )
|
||||||
|
AC_SUBST( SDL_LIBS )
|
||||||
|
AM_CONDITIONAL( [HAVE_SDL], [test "x$HAVE_SDL" = xyes] )
|
||||||
|
|
||||||
|
# Check for NAS
|
||||||
|
AC_CHECK_LIB( [audio], [AuOpenServer],
|
||||||
|
[ AC_CHECK_HEADER( [audio/audiolib.h],
|
||||||
|
[ output_modules="nas $output_modules" HAVE_NAS="yes"],
|
||||||
|
[ AC_MSG_WARN([Found NAS library but NOT header files on your system]) ] )
|
||||||
|
]
|
||||||
|
)
|
||||||
|
AM_CONDITIONAL( [HAVE_NAS], [test "x$HAVE_NAS" = xyes] )
|
||||||
|
|
||||||
# Check for windows ... and win32 audio
|
# Check for windows ... and win32 audio
|
||||||
# Does not work... instead just check for header
|
# Does not work... instead just check for header
|
||||||
# AC_CHECK_LIB( [winmm], [waveOutOpen] )
|
# AC_CHECK_LIB( [winmm], [waveOutOpen] )
|
||||||
AC_CHECK_HEADERS([windows.h], HAVE_WINMM=yes, HAVE_WINMM=no)
|
AC_CHECK_HEADERS([windows.h], HAVE_WINMM=yes, HAVE_WINMM=no)
|
||||||
|
|
||||||
|
# Sun Audio headers
|
||||||
|
AC_CHECK_HEADERS([sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h])
|
||||||
|
if test "x${ac_cv_header_sun_audioio_h}" = "xyes" \
|
||||||
|
-o "x${ac_cv_header_sys_audioio_h}" = "xyes" \
|
||||||
|
-o "x${ac_cv_header_asm_audioio_h}" = "xyes";
|
||||||
|
then
|
||||||
|
output_modules="sun $output_modules"
|
||||||
|
HAVE_SUN="yes"
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL( [HAVE_SUN], [test "x$HAVE_SUN" = xyes] )
|
||||||
|
|
||||||
|
# OSS Header files
|
||||||
|
AC_CHECK_HEADERS([sys/soundcard.h linux/soundcard.h machine/soundcard.h])
|
||||||
|
if test "x${ac_cv_header_sys_soundcard_h}" = "xyes" \
|
||||||
|
-o "x${ac_cv_header_linux_soundcard_h}" = "xyes" \
|
||||||
|
-o "x${ac_cv_header_machine_soundcard_h}" = "xyes";
|
||||||
|
then
|
||||||
|
output_modules="oss $output_modules"
|
||||||
|
HAVE_OSS="yes"
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL( [HAVE_OSS], [test "x$HAVE_OSS" = xyes] )
|
||||||
|
|
||||||
# Check for ALSA
|
# Check for ALSA
|
||||||
AC_CHECK_LIB( [asound], [snd_pcm_open],
|
AC_CHECK_LIB( [asound], [snd_pcm_open],
|
||||||
[ AC_CHECK_HEADER( [alsa/asoundlib.h],
|
[ AC_CHECK_HEADER( [alsa/asoundlib.h],
|
||||||
[ HAVE_ALSA="yes" ],
|
[ output_modules="alsa $output_modules" HAVE_ALSA="yes"],
|
||||||
[ AC_MSG_WARN([Found ALSA library but NOT header files on your system]) ] )
|
[ AC_MSG_WARN([Found ALSA library but NOT header files on your system]) ] )
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
AM_CONDITIONAL( [HAVE_ALSA], [test "x$HAVE_ALSA" = xyes] )
|
||||||
|
|
||||||
dnl ############## Header Checks
|
|
||||||
|
|
||||||
AC_HEADER_STDC
|
# Mac OS X CoreAudio
|
||||||
dnl Is it too paranoid to specifically check for stdint.h and limits.h?
|
AC_CHECK_HEADERS([AudioUnit/AudioUnit.h CoreServices/CoreServices.h AudioToolbox/AudioToolbox.h])
|
||||||
AC_CHECK_HEADERS([stdlib.h string.h unistd.h sched.h sys/ioctl.h stdint.h limits.h inttypes.h sys/time.h sys/wait.h sys/resource.h signal.h])
|
if test "x${ac_cv_header_AudioUnit_AudioUnit_h}" = "xyes" \
|
||||||
|
-a "x${ac_cv_header_CoreServices_CoreServices_h}" = "xyes" \
|
||||||
|
-a "x${ac_cv_header_AudioToolbox_AudioToolbox_h}" = "xyes";
|
||||||
|
then
|
||||||
|
output_modules="coreaudio $output_modules"
|
||||||
|
HAVE_COREAUDIO="yes"
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL( [HAVE_COREAUDIO], [test "x$HAVE_COREAUDIO" = xyes] )
|
||||||
|
|
||||||
|
|
||||||
# attempt to make the signal stuff work... also with GENERIC - later
|
# attempt to make the signal stuff work... also with GENERIC - later
|
||||||
#if test $ac_cv_header_sys_signal_h = yes; then
|
#if test $ac_cv_header_sys_signal_h = yes; then
|
||||||
@@ -290,26 +394,6 @@ AC_CHECK_HEADERS([stdlib.h string.h unistd.h sched.h sys/ioctl.h stdint.h limits
|
|||||||
# AC_DEFINE(
|
# AC_DEFINE(
|
||||||
#fi
|
#fi
|
||||||
|
|
||||||
# OSS Header files: One of them is enough.
|
|
||||||
AC_CHECK_HEADERS(sys/soundcard.h)
|
|
||||||
AC_CHECK_HEADERS(linux/soundcard.h)
|
|
||||||
AC_CHECK_HEADERS(machine/soundcard.h)
|
|
||||||
if test "x${ac_cv_header_sys_soundcard_h}" = "xyes" ||
|
|
||||||
test "x${ac_cv_header_linux_soundcard_h}" = "xyes" ||
|
|
||||||
test "x${ac_cv_header_machine_soundcard_h}" = "xyes"; then
|
|
||||||
HAVE_OSS=yes
|
|
||||||
else
|
|
||||||
HAVE_OSS=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Sun Audio headers
|
|
||||||
AC_CHECK_HEADERS([sun/audioio.h sys/audioio.h asm/audioio.h sys/audio.h], HAVE_SUNAUDIO=yes, HAVE_SUNAUDIO=no)
|
|
||||||
|
|
||||||
# Mac OS X
|
|
||||||
AC_CHECK_HEADERS([AudioUnit/AudioUnit.h CoreServices/CoreServices.h AudioToolbox/AudioToolbox.h],
|
|
||||||
HAVE_MACOSXAUDIO=yes, HAVE_MACOSXAUDIO=no)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl ############## Choose compiler flags and CPU
|
dnl ############## Choose compiler flags and CPU
|
||||||
@@ -509,6 +593,19 @@ fi
|
|||||||
AC_SUBST( CPU_TYPE_LIB )
|
AC_SUBST( CPU_TYPE_LIB )
|
||||||
|
|
||||||
|
|
||||||
|
dnl ############## Create list of modules to build
|
||||||
|
|
||||||
|
# Enable module support in source code
|
||||||
|
AC_DEFINE( USE_MODULES, 1, [Define if modules are enabled] )
|
||||||
|
|
||||||
|
# Did user choose default audio subsystem ?
|
||||||
|
if test "x$with_default_audio" != "x"; then
|
||||||
|
default_output_module=$with_default_audio
|
||||||
|
else
|
||||||
|
default_output_module=`echo "$output_modules" | $AWK '{ print $1 }'`
|
||||||
|
fi
|
||||||
|
AC_DEFINE_UNQUOTED( DEFAULT_OUTPUT_MODULE, "$default_output_module", [The default audio output module to use] )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl ############## Compiler Optimizations
|
dnl ############## Compiler Optimizations
|
||||||
@@ -721,34 +818,32 @@ AC_SUBST(AUDIO_LIBS)
|
|||||||
|
|
||||||
dnl ############## Final Output
|
dnl ############## Final Output
|
||||||
|
|
||||||
AC_OUTPUT([Makefile src/Makefile])
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
src/Makefile
|
||||||
|
src/output/Makefile
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dnl ############## Display Message
|
dnl ############## Display Message
|
||||||
|
|
||||||
echo -n "
|
echo "
|
||||||
$PACKAGE $VERSION
|
$PACKAGE_NAME $PACKAGE_VERSION
|
||||||
|
|
||||||
Install path ............ $prefix
|
Install path ............ $prefix
|
||||||
CPU Optimisation......... $cpu_type
|
CPU Optimisation......... $cpu_type
|
||||||
Compiler Optimization ... $with_optimization
|
Compiler Optimization ... $with_optimization
|
||||||
Audio output ............ $audio_system (detected:"
|
|
||||||
test "x$HAVE_ALSA" = "xyes" && echo -n " alsa"
|
|
||||||
test "x$HAVE_OSS" = "xyes" && echo -n " oss"
|
|
||||||
test "x$HAVE_MACOSXAUDIO" = "xyes" && echo -n " coreaudio"
|
|
||||||
test "x$HAVE_SUNAUDIO" = "xyes" && echo -n " sun"
|
|
||||||
test "x$HAVE_JACK" = "xyes" && echo -n " jack"
|
|
||||||
test "x$HAVE_PORTAUDIO" = "xyes" && echo -n " portaudio"
|
|
||||||
test "x$HAVE_NAS" = "xyes" && echo -n " nas"
|
|
||||||
test "x$HAVE_SDL" = "xyes" && echo -n " sdl"
|
|
||||||
test "x$HAVE_ESOUND" = "xyes" && echo -n " esd"
|
|
||||||
test "x$HAVE_WINMM" = "xyes" && echo -n " win32"
|
|
||||||
echo ")
|
|
||||||
Gapless Support ......... $gapless
|
Gapless Support ......... $gapless
|
||||||
Debugging ............... $debugging
|
Debugging ............... $debugging
|
||||||
Seek table size ......... $seektable
|
Seek table size ......... $seektable
|
||||||
FIFO support ............ $fifo
|
FIFO support ............ $fifo
|
||||||
|
|
||||||
|
Modules Directory ....... $pkglibdir
|
||||||
|
Audio output modules .... $output_modules
|
||||||
|
Default output module ... $default_output_module
|
||||||
"
|
"
|
||||||
if test $cpu_type = "generic_float"; then
|
if test $cpu_type = "generic_float"; then
|
||||||
echo "You chose the generic build with 32bit float output.
|
echo "You chose the generic build with 32bit float output.
|
||||||
@@ -762,8 +857,6 @@ fi
|
|||||||
if test "$debugging" = "enabled"; then
|
if test "$debugging" = "enabled"; then
|
||||||
echo "CFLAGS='$CFLAGS'"
|
echo "CFLAGS='$CFLAGS'"
|
||||||
echo "LIBS='$LIBS'"
|
echo "LIBS='$LIBS'"
|
||||||
echo "AUDIO_CFLAGS='$AUDIO_CFLAGS'"
|
|
||||||
echo "AUDIO_LIBS='$AUDIO_LIBS'"
|
|
||||||
else
|
else
|
||||||
echo "Next type 'make' and then 'make install'."
|
echo "Next type 'make' and then 'make install'."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,11 +4,12 @@
|
|||||||
## 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 Nicholas J. Humfrey
|
## initially written by Nicholas J. Humfrey
|
||||||
|
|
||||||
AM_CFLAGS = @AUDIO_CFLAGS@
|
mpg123_LDADD = @LIBLTDL@ @CPU_TYPE_LIB@
|
||||||
#AM_LDFLAGS =
|
mpg123_LDFLAGS = -export-dynamic
|
||||||
mpg123_LDADD = @AUDIO_OBJ@ @CPU_TYPE_LIB@ @AUDIO_LIBS@
|
mpg123_INCLUDES = @LTDLINCL@
|
||||||
mpg123_DEPENDENCIES = @AUDIO_OBJ@ @CPU_TYPE_LIB@
|
mpg123_DEPENDENCIES = @LIBLTDL@ @CPU_TYPE_LIB@
|
||||||
|
|
||||||
|
SUBDIRS = output
|
||||||
EXTRA_DIST = Makefile.legacy config.h.legacy
|
EXTRA_DIST = Makefile.legacy config.h.legacy
|
||||||
|
|
||||||
CLEANFILES = *.a
|
CLEANFILES = *.a
|
||||||
@@ -19,7 +20,7 @@ EXTRA_PROGRAMS = testcpu
|
|||||||
testcpu_SOURCES = \
|
testcpu_SOURCES = \
|
||||||
testcpu.c \
|
testcpu.c \
|
||||||
getcpuflags.S
|
getcpuflags.S
|
||||||
|
|
||||||
mpg123_SOURCES = \
|
mpg123_SOURCES = \
|
||||||
audio.c \
|
audio.c \
|
||||||
audio.h \
|
audio.h \
|
||||||
@@ -52,6 +53,8 @@ mpg123_SOURCES = \
|
|||||||
layer3.c \
|
layer3.c \
|
||||||
layer3.h \
|
layer3.h \
|
||||||
mangle.h \
|
mangle.h \
|
||||||
|
module.c \
|
||||||
|
module.h \
|
||||||
mpg123.c \
|
mpg123.c \
|
||||||
mpg123.h \
|
mpg123.h \
|
||||||
optimize.h \
|
optimize.h \
|
||||||
@@ -70,25 +73,8 @@ mpg123_SOURCES = \
|
|||||||
xfermem.c \
|
xfermem.c \
|
||||||
xfermem.h
|
xfermem.h
|
||||||
|
|
||||||
EXTRA_mpg123_SOURCES = \
|
|
||||||
audio_aix.c \
|
EXTRA_mpg123_SOURCES = getcpuflags.h
|
||||||
audio_alib.c \
|
|
||||||
audio_alsa.c \
|
|
||||||
audio_dummy.c \
|
|
||||||
audio_esd.c \
|
|
||||||
audio_hp.c \
|
|
||||||
audio_jack.c \
|
|
||||||
audio_coreaudio.c \
|
|
||||||
audio_mint.c \
|
|
||||||
audio_nas.c \
|
|
||||||
audio_os2.c \
|
|
||||||
audio_oss.c \
|
|
||||||
audio_portaudio.c \
|
|
||||||
audio_sdl.c \
|
|
||||||
audio_sgi.c \
|
|
||||||
audio_sun.c \
|
|
||||||
audio_win32.c \
|
|
||||||
getcpuflags.h
|
|
||||||
|
|
||||||
|
|
||||||
# Processor dependent decoder code
|
# Processor dependent decoder code
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ nothing-specified:
|
|||||||
@echo "make bsdos4 BSDI BSD/OS 4.0"
|
@echo "make bsdos4 BSDI BSD/OS 4.0"
|
||||||
@echo "make bsdos-nas BSDI BSD/OS with NAS support"
|
@echo "make bsdos-nas BSDI BSD/OS with NAS support"
|
||||||
@echo "make mint MiNT on Atari"
|
@echo "make mint MiNT on Atari"
|
||||||
|
@echo "make macosx CoreAudio on Mac OS X"
|
||||||
@echo "make generic try this one if your system isn't listed above"
|
@echo "make generic try this one if your system isn't listed above"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Please read the file INSTALL for additional information."
|
@echo "Please read the file INSTALL for additional information."
|
||||||
@@ -104,15 +105,17 @@ freebsd-help:
|
|||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
linux-devel:
|
linux-devel:
|
||||||
$(MAKE) OBJECTS="decode_i386.o dct64_i386.o audio_oss.o" \
|
$(MAKE) CC=gcc
|
||||||
CC=gcc \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -IOPT_I386 -DREAL_IS_FLOAT -DLINUX -Wall -g \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -IOPT_I386 -DREAL_IS_FLOAT -DLINUX -Wall -g \
|
||||||
-DREAD_MMAP -DOSS -funroll-all-loops \
|
-DREAD_MMAP -DOSS -funroll-all-loops \
|
||||||
-finline-functions -ffast-math" \
|
-finline-functions -ffast-math" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
linux-profile:
|
linux-profile:
|
||||||
$(MAKE) OBJECTS="decode_i386.o dct64_i386.o audio_oss.o" \
|
$(MAKE) OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CC=gcc LDFLAGS="$(LDFLAGS) -pg" \
|
CC=gcc LDFLAGS="$(LDFLAGS) -pg" \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -DREAL_IS_FLOAT -DLINUX -Wall -pg \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -DREAL_IS_FLOAT -DLINUX -Wall -pg \
|
||||||
-DREAD_MMAP -DOSS -funroll-all-loops \
|
-DREAD_MMAP -DOSS -funroll-all-loops \
|
||||||
@@ -121,7 +124,8 @@ linux-profile:
|
|||||||
|
|
||||||
linux:
|
linux:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -O2 -funroll-all-loops \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -O2 -funroll-all-loops \
|
||||||
-DOSS -DHAVE_TERMIOS \
|
-DOSS -DHAVE_TERMIOS \
|
||||||
-Wall" \
|
-Wall" \
|
||||||
@@ -129,8 +133,8 @@ linux:
|
|||||||
|
|
||||||
linux-x86:
|
linux-x86:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o term.o" \
|
||||||
audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
@@ -141,8 +145,8 @@ linux-x86:
|
|||||||
#just for development... gapless will be on for normal builds when stable
|
#just for development... gapless will be on for normal builds when stable
|
||||||
linux-x86-gapless:
|
linux-x86-gapless:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o term.o" \
|
||||||
audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DGAPLESS $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DGAPLESS $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
@@ -152,8 +156,8 @@ linux-x86-gapless:
|
|||||||
|
|
||||||
linux-mmx:
|
linux-mmx:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_mmx.o tabinit_mmx.o decode_mmx.o \
|
OBJECTS="decode_i386.o dct64_mmx.o tabinit_mmx.o decode_mmx.o term.o" \
|
||||||
audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS=" $(CFLAGS) -DOPT_MMX -DREAL_IS_FLOAT \
|
CFLAGS=" $(CFLAGS) -DOPT_MMX -DREAL_IS_FLOAT \
|
||||||
-DLINUX -DOSS -DHAVE_TERMIOS\
|
-DLINUX -DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
@@ -163,8 +167,8 @@ linux-mmx:
|
|||||||
|
|
||||||
linux-mmap:
|
linux-mmap:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o term.o" \
|
||||||
audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DREAD_MMAP -DOSS -DHAVE_TERMIOS\
|
-DREAD_MMAP -DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
@@ -176,9 +180,10 @@ linux-3dnow:
|
|||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o decode_3dnow.o dct64_3dnow.o \
|
OBJECTS="decode_i386.o decode_3dnow.o dct64_3dnow.o \
|
||||||
dct64_i386.o dct36_3dnow.o getcpuflags.o \
|
dct64_i386.o dct36_3dnow.o getcpuflags.o \
|
||||||
equalizer_3dnow.o decode_i586.o audio_oss.o term.o optimize.o" \
|
equalizer_3dnow.o decode_i586.o term.o optimize.o" \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_MULTI -DOPT_I586 -DOPT_3DNOW -DREAL_IS_FLOAT -DLINUX \
|
OUTPUT_MODULE=oss \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_MULTI -DOPT_I586 -DOPT_3DNOW \
|
||||||
|
-DREAL_IS_FLOAT -DLINUX -DOSS -DHAVE_TERMIOS \
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math" \
|
-finline-functions -ffast-math" \
|
||||||
@@ -186,8 +191,8 @@ linux-3dnow:
|
|||||||
|
|
||||||
linux-i486:
|
linux-i486:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o \
|
OBJECTS="decode_i386.o dct64_i386.o decode_i486.o dct64_i486.o term.o" \
|
||||||
decode_i486.o dct64_i486.o audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I486 -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I486 -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 -march=i486 \
|
-Wall -O2 -march=i486 \
|
||||||
@@ -197,8 +202,8 @@ linux-i486:
|
|||||||
|
|
||||||
linux-i386:
|
linux-i386:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o \
|
OBJECTS="decode_i386.o dct64_i386.o term.o" \
|
||||||
audio_oss.o term.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-Wall -O2 \
|
-Wall -O2 \
|
||||||
@@ -209,8 +214,8 @@ linux-i386:
|
|||||||
linux-esd:
|
linux-esd:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
AUDIO_LIB="-lesd -laudiofile" \
|
AUDIO_LIB="-lesd -laudiofile" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o term.o" \
|
||||||
audio_esd.o term.o" \
|
OUTPUT_MODULE=esd \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DOSS -DUSE_ESD -DHAVE_TERMIOS\
|
-DOSS -DUSE_ESD -DHAVE_TERMIOS\
|
||||||
-Wall -O2 -mcpu=i486 \
|
-Wall -O2 -mcpu=i486 \
|
||||||
@@ -221,8 +226,8 @@ linux-esd:
|
|||||||
linux-alsa:
|
linux-alsa:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
AUDIO_LIB="-lasound" \
|
AUDIO_LIB="-lasound" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o term.o" \
|
||||||
audio_alsa.o term.o" \
|
OUTPUT_MODULE=alsa \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PENTIUM_OPT) -DREAL_IS_FLOAT -DLINUX \
|
||||||
-DALSA -DHAVE_TERMIOS\
|
-DALSA -DHAVE_TERMIOS\
|
||||||
-Wall -O2 -mcpu=i486 \
|
-Wall -O2 -mcpu=i486 \
|
||||||
@@ -233,7 +238,8 @@ linux-alsa:
|
|||||||
linux-mips-alsa:
|
linux-mips-alsa:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
AUDIO_LIB="-lasound" \
|
AUDIO_LIB="-lasound" \
|
||||||
OBJECTS="decode.o dct64.o audio_alsa.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=alsa \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DALSA \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DALSA \
|
||||||
-DHAVE_TERMIOS -Wall -O2 \
|
-DHAVE_TERMIOS -Wall -O2 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -241,7 +247,8 @@ linux-mips-alsa:
|
|||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
linux-alpha:
|
linux-alpha:
|
||||||
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DLINUX -DOSS -DHAVE_TERMIOS -Wall -O2 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DLINUX -DOSS -DHAVE_TERMIOS -Wall -O2 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math \
|
-finline-functions -ffast-math \
|
||||||
@@ -251,7 +258,8 @@ linux-alpha:
|
|||||||
linux-alpha-esd:
|
linux-alpha-esd:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
AUDIO_LIB="-lesd -laudiofile" \
|
AUDIO_LIB="-lesd -laudiofile" \
|
||||||
OBJECTS="decode.o dct64.o audio_esd.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=esd \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DLINUX -DOSS -DHAVE_TERMIOS -Wall -O2 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DLINUX -DOSS -DHAVE_TERMIOS -Wall -O2 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math \
|
-finline-functions -ffast-math \
|
||||||
@@ -260,7 +268,8 @@ linux-alpha-esd:
|
|||||||
|
|
||||||
#linux-ppc:
|
#linux-ppc:
|
||||||
# $(MAKE) CC=gcc LDFLAGS= \
|
# $(MAKE) CC=gcc LDFLAGS= \
|
||||||
# OBJECTS="decode.o dct64.o audio_oss.o" \
|
# OBJECTS="decode.o dct64.o" \
|
||||||
|
# OUTPUT_MODULE=oss \
|
||||||
# CFLAGS="-DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=ppc \
|
# CFLAGS="-DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=ppc \
|
||||||
# -DOSS -DPPC_ENDIAN \
|
# -DOSS -DPPC_ENDIAN \
|
||||||
# -fomit-frame-pointer -funroll-all-loops \
|
# -fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -270,7 +279,8 @@ linux-alpha-esd:
|
|||||||
#linux-ppc-esd:
|
#linux-ppc-esd:
|
||||||
# $(MAKE) CC=gcc LDFLAGS= \
|
# $(MAKE) CC=gcc LDFLAGS= \
|
||||||
# AUDIO_LIB="-lesd -laudiofile" \
|
# AUDIO_LIB="-lesd -laudiofile" \
|
||||||
# OBJECTS="decode.o dct64.o audio_esd.o" \
|
# OBJECTS="decode.o dct64.o" \
|
||||||
|
# OUTPUT_MODULE=esd \
|
||||||
# CFLAGS="-DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=ppc \
|
# CFLAGS="-DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=ppc \
|
||||||
# -DOSS -DPPC_ENDIAN \
|
# -DOSS -DPPC_ENDIAN \
|
||||||
# -fomit-frame-pointer -funroll-all-loops \
|
# -fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -279,7 +289,8 @@ linux-alpha-esd:
|
|||||||
|
|
||||||
linux-ppc:
|
linux-ppc:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=powerpc \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=powerpc \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -289,7 +300,8 @@ linux-ppc:
|
|||||||
linux-ppc-esd:
|
linux-ppc-esd:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
AUDIO_LIB="-lesd -laudiofile" \
|
AUDIO_LIB="-lesd -laudiofile" \
|
||||||
OBJECTS="decode.o dct64.o audio_esd.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=esd \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=powerpc \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 -mcpu=powerpc \
|
||||||
-DOSS -DHAVE_TERMIOS\
|
-DOSS -DHAVE_TERMIOS\
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -299,7 +311,8 @@ linux-ppc-esd:
|
|||||||
linux-ppc-nas:
|
linux-ppc-nas:
|
||||||
$(MAKE) CC=gcc LDFLAGS='-L/usr/X11R6/lib' \
|
$(MAKE) CC=gcc LDFLAGS='-L/usr/X11R6/lib' \
|
||||||
AUDIO_LIB='-laudio -lXau -lXt' \
|
AUDIO_LIB='-laudio -lXau -lXt' \
|
||||||
OBJECTS='decode.o dct64.o audio_nas.o term.o' \
|
OBJECTS='decode.o dct64.o term.o' \
|
||||||
|
OUTPUT_MODULE=nas \
|
||||||
CFLAGS="-I/usr/X11R6/include -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DNAS -DTERM_CONTROL \
|
CFLAGS="-I/usr/X11R6/include -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DNAS -DTERM_CONTROL \
|
||||||
-Wall -O2 -mcpu=powerpc \
|
-Wall -O2 -mcpu=powerpc \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -308,7 +321,8 @@ linux-ppc-nas:
|
|||||||
|
|
||||||
linux-sparc:
|
linux-sparc:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DHAVE_MMAP -DSPARCLINUX -Wall -O2 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DHAVE_MMAP -DSPARCLINUX -Wall -O2 \
|
||||||
-DHAVE_TERMIOS \
|
-DHAVE_TERMIOS \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -317,7 +331,8 @@ linux-sparc:
|
|||||||
|
|
||||||
linux-hppa:
|
linux-hppa:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -Wall -O2 \
|
||||||
-DHAVE_TERMIOS \
|
-DHAVE_TERMIOS \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -325,7 +340,8 @@ linux-hppa:
|
|||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
linux-m68k:
|
linux-m68k:
|
||||||
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DHAVE_TERMIOS \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -DLINUX -DHAVE_TERMIOS \
|
||||||
-DOSS -DOSS_BIG_ENDIAN -Wall -O2 -m68040 \
|
-DOSS -DOSS_BIG_ENDIAN -Wall -O2 -m68040 \
|
||||||
-fomit-frame-pointer -funroll-loops \
|
-fomit-frame-pointer -funroll-loops \
|
||||||
@@ -333,7 +349,8 @@ linux-m68k:
|
|||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
linux-arm:
|
linux-arm:
|
||||||
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o audio_oss.o term.o" \
|
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FIXED -DLINUX -DHAVE_TERMIOS \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FIXED -DLINUX -DHAVE_TERMIOS \
|
||||||
-DOSS -Wall -O6 -mtune=xscale \
|
-DOSS -Wall -O6 -mtune=xscale \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
@@ -343,7 +360,8 @@ linux-arm:
|
|||||||
linux-nas:
|
linux-nas:
|
||||||
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \
|
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \
|
||||||
AUDIO_LIB="-laudio -lXau -lXt" \
|
AUDIO_LIB="-laudio -lXau -lXt" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_nas.o term.o" \
|
OBJECTS="decode_i386.o dct64_i386.o term.o" \
|
||||||
|
OUTPUT_MODULE=nas \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -I/usr/X11R6/include \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -I/usr/X11R6/include \
|
||||||
-DOPT_I386 -DREAL_IS_FLOAT -DLINUX -DNAS \
|
-DOPT_I386 -DREAL_IS_FLOAT -DLINUX -DNAS \
|
||||||
-DHAVE_TERMIOS \
|
-DHAVE_TERMIOS \
|
||||||
@@ -360,7 +378,8 @@ linux-nas:
|
|||||||
|
|
||||||
freebsd:
|
freebsd:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_oss.o" \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DREAD_MMAP \
|
-DREAD_MMAP \
|
||||||
@@ -370,7 +389,8 @@ freebsd:
|
|||||||
freebsd-esd:
|
freebsd-esd:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
AUDIO_LIB="-lesd -laudiofile" \
|
AUDIO_LIB="-lesd -laudiofile" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(GETBITS) audio_esd.o" \
|
OBJECTS="decode_i386.o dct64_i386.o $(GETBITS)" \
|
||||||
|
OUTPUT_MODULE=esd \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DREAD_MMAP \
|
-DREAD_MMAP \
|
||||||
@@ -385,14 +405,16 @@ freebsd-esd:
|
|||||||
solaris-pure:
|
solaris-pure:
|
||||||
$(MAKE) CC="purify -cache-dir=/tmp cc" \
|
$(MAKE) CC="purify -cache-dir=/tmp cc" \
|
||||||
LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -fast -native -xO4 -DSOLARIS -DHAVE_TERMIOS \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -fast -native -xO4 -DSOLARIS -DHAVE_TERMIOS \
|
||||||
-DHAVE_MMAP" \
|
-DHAVE_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
solaris-ccscc:
|
solaris-ccscc:
|
||||||
$(MAKE) CC=/usr/ccs/bin/ucbcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
$(MAKE) CC=/usr/ccs/bin/ucbcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -fast -native -xO4 -DSOLARIS \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -fast -native -xO4 -DSOLARIS \
|
||||||
-DHAVE_MMAP" \
|
-DHAVE_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
@@ -400,7 +422,8 @@ solaris-ccscc:
|
|||||||
# common solaris compile entries
|
# common solaris compile entries
|
||||||
solaris:
|
solaris:
|
||||||
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS)-fast -DOPT_GENERIC -native -xO4 -DSOLARIS \
|
CFLAGS="$(CFLAGS)-fast -DOPT_GENERIC -native -xO4 -DSOLARIS \
|
||||||
-DHAVE_MMAP -DHAVE_TERMIOS" \
|
-DHAVE_MMAP -DHAVE_TERMIOS" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
@@ -408,7 +431,8 @@ solaris:
|
|||||||
solaris-gcc-profile:
|
solaris-gcc-profile:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
LDFLAGS="$(LDFLAGS) -lsocket -lnsl -pg" \
|
LDFLAGS="$(LDFLAGS) -lsocket -lnsl -pg" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -g -pg -O2 -Wall -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -g -pg -O2 -Wall -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-DREAD_MMAP \
|
-DREAD_MMAP \
|
||||||
-funroll-all-loops -finline-functions" \
|
-funroll-all-loops -finline-functions" \
|
||||||
@@ -417,7 +441,8 @@ solaris-gcc-profile:
|
|||||||
solaris-gcc:
|
solaris-gcc:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o term.o" \
|
OBJECTS="decode.o dct64.o term.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -Wall -pedantic -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -Wall -pedantic -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-DREAD_MMAP -DHAVE_TERMIOS \
|
-DREAD_MMAP -DHAVE_TERMIOS \
|
||||||
-funroll-all-loops -finline-functions" \
|
-funroll-all-loops -finline-functions" \
|
||||||
@@ -426,7 +451,8 @@ solaris-gcc:
|
|||||||
solaris-gcc-esd:
|
solaris-gcc-esd:
|
||||||
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
AUDIO_LIB="-lesd -lresolv" \
|
AUDIO_LIB="-lesd -lresolv" \
|
||||||
OBJECTS="decode.o dct64.o audio_esd.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=esd \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -Wall -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -Wall -DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-DREAD_MMAP \
|
-DREAD_MMAP \
|
||||||
-funroll-all-loops -finline-functions" \
|
-funroll-all-loops -finline-functions" \
|
||||||
@@ -434,8 +460,8 @@ solaris-gcc-esd:
|
|||||||
|
|
||||||
solaris-x86-gcc-oss:
|
solaris-x86-gcc-oss:
|
||||||
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o \
|
OBJECTS="decode_i386.o dct64_i386.o $(PENTIUM_DECODE).o" \
|
||||||
audio_oss.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I586 -DREAL_IS_FLOAT -DHAVE_MMAP \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I586 -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-DREAD_MMAP -DOSS \
|
-DREAD_MMAP -DOSS \
|
||||||
-Wall -O2 -mcpu=i486 \
|
-Wall -O2 -mcpu=i486 \
|
||||||
@@ -445,7 +471,8 @@ solaris-x86-gcc-oss:
|
|||||||
solaris-gcc-nas:
|
solaris-gcc-nas:
|
||||||
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
$(MAKE) CC=gcc LDFLAGS="$(LDFLAGS) -lsocket -lnsl" \
|
||||||
AUDIO_LIB="-L/usr/openwin/lib -laudio -lXau"\
|
AUDIO_LIB="-L/usr/openwin/lib -laudio -lXau"\
|
||||||
OBJECTS="decode.o dct64.o audio_nas.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=nas \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -I/usr/openwin/include -Wall \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -I/usr/openwin/include -Wall \
|
||||||
-DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
-DSOLARIS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-DREAD_MMAP -DNAS \
|
-DREAD_MMAP -DNAS \
|
||||||
@@ -454,50 +481,60 @@ solaris-gcc-nas:
|
|||||||
|
|
||||||
sunos:
|
sunos:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -O2 -DOPT_GENERIC -DSUNOS -DREAL_IS_FLOAT -DHAVE_MMAP -DHAVE_SYS_IOCTL_H -DHAVE_SUN_AUDIOIO_H -DNO_RT -DHAVE_NO_STRERROR \
|
OUTPUT_MODULE=sun \
|
||||||
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -O2 -DOPT_GENERIC -DSUNOS -DREAL_IS_FLOAT -DHAVE_MMAP \
|
||||||
-funroll-loops" \
|
-funroll-loops" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
# CFLAGS='-DREAL_IS_FLOAT -Aa +O3 -D_HPUX_SOURCE -DHPUX'
|
# CFLAGS='-DREAL_IS_FLOAT -Aa +O3 -D_HPUX_SOURCE -DHPUX'
|
||||||
hpux:
|
hpux:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
OBJECTS="decode.o dct64.o audio_hp.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=hp \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -Ae +O3 -D_HPUX_SOURCE -DHPUX" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -Ae +O3 -D_HPUX_SOURCE -DHPUX" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
hpux-alib:
|
hpux-alib:
|
||||||
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -L/opt/audio/lib" \
|
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -L/opt/audio/lib" \
|
||||||
OBJECTS="decode.o dct64.o audio_alib.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=alib \
|
||||||
AUDIO_LIB=-lAlib \
|
AUDIO_LIB=-lAlib \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DREAL_IS_FLOAT -Ae +O3 -D_HPUX_SOURCE -DHPUX \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DREAL_IS_FLOAT -Ae +O3 -D_HPUX_SOURCE -DHPUX \
|
||||||
-I/opt/audio/include" \
|
-I/opt/audio/include" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
hpux-gcc:
|
hpux-gcc:
|
||||||
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o audio_hp.o" \
|
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=hp \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -O3 -D_HPUX_SOURCE -DHPUX" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DREAL_IS_FLOAT -O3 -D_HPUX_SOURCE -DHPUX" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
sgi:
|
sgi:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
OBJECTS="decode.o dct64.o audio_sgi.o" AUDIO_LIB=-laudio \
|
OBJECTS="decode.o dct64.o"
|
||||||
|
OUTPUT_MODULE=sgi \
|
||||||
|
AUDIO_LIB=-laudio \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -DSGI -DREAL_IS_FLOAT -DHAVE_MMAP" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -DSGI -DREAL_IS_FLOAT -DHAVE_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
sgi-gcc:
|
sgi-gcc:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_sgi.o" AUDIO_LIB=-laudio \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=sgi \
|
||||||
|
AUDIO_LIB=-laudio \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -DSGI -DREAL_IS_FLOAT -DHAVE_MMAP" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O2 -DSGI -DREAL_IS_FLOAT -DHAVE_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
dec:
|
dec:
|
||||||
$(MAKE) CC=cc OBJECTS="decode.o dct64.o audio_dummy.o" \
|
$(MAKE) CC=cc OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=dummy \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
||||||
LDFLAGS="$(LDFLAGS) -lrt" \
|
LDFLAGS="$(LDFLAGS) -lrt" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
dec-debug:
|
dec-debug:
|
||||||
$(MAKE) CC=cc OBJECTS="decode.o dct64.o audio_dummy.o" \
|
$(MAKE) CC=cc OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=dummy \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -g3 -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -g3 -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
||||||
LDFLAGS="$(LDFLAGS) -lrt" \
|
LDFLAGS="$(LDFLAGS) -lrt" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
@@ -505,31 +542,36 @@ dec-debug:
|
|||||||
dec-nas:
|
dec-nas:
|
||||||
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \
|
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \
|
||||||
AUDIO_LIB="-laudio -lXau -ldnet_stub"\
|
AUDIO_LIB="-laudio -lXau -ldnet_stub"\
|
||||||
OBJECTS="decode.o dct64.o audio_nas.o" \
|
OUTPUT_MODULE=nas \
|
||||||
|
OBJECTS="decode.o dct64.o" \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -I/usr/X11R6/include -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -I/usr/X11R6/include -std1 -warnprotos -O4 -DHAVE_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
ultrix:
|
ultrix:
|
||||||
$(MAKE) CC=cc OBJECTS="decode.o dct64.o audio_dummy.o" \
|
$(MAKE) CC=cc OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=dummy \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -std1 -O2 -DULTRIX" \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -std1 -O2 -DULTRIX" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
aix-gcc:
|
aix-gcc:
|
||||||
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o audio_aix.o" \
|
$(MAKE) CC=gcc OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=aix \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DAIX -Wall -O6 -DHAVE_MMAP -DREAD_MMAP -DREAL_IS_FLOAT \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DAIX -Wall -O6 -DHAVE_MMAP -DREAD_MMAP -DREAL_IS_FLOAT \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math" \
|
-finline-functions -ffast-math" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
aix-xlc:
|
aix-xlc:
|
||||||
$(MAKE) OBJECTS="decode.o dct64.o audio_aix.o" \
|
$(MAKE) OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=aix \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O3 -qstrict -qcpluscmt -DAIX -DHAVE_MMAP \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -O3 -qstrict -qcpluscmt -DAIX -DHAVE_MMAP \
|
||||||
-DREAD_MMAP" \
|
-DREAD_MMAP" \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
os2:
|
os2:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_os2.o" \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=os2 \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 DREAL_IS_FLOAT -DNOXFERMEM -DOS2 -Wall -O2 -mcpu=i486 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 DREAL_IS_FLOAT -DNOXFERMEM -DOS2 -Wall -O2 -mcpu=i486 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math" \
|
-finline-functions -ffast-math" \
|
||||||
@@ -538,7 +580,8 @@ os2:
|
|||||||
|
|
||||||
netbsd:
|
netbsd:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -ansi -pedantic -O3 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -ansi -pedantic -O3 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math \
|
-funroll-all-loops -ffast-math \
|
||||||
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD -DNO_RT" \
|
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD -DNO_RT" \
|
||||||
@@ -546,7 +589,8 @@ netbsd:
|
|||||||
|
|
||||||
netbsd-x86:
|
netbsd-x86:
|
||||||
$(MAKE) CC=cc \
|
$(MAKE) CC=cc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_sun.o" \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -mcpu=i486 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -mcpu=i486 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DI386_ASSEM -DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD -DNO_RT" \
|
-DI386_ASSEM -DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD -DNO_RT" \
|
||||||
@@ -554,7 +598,8 @@ netbsd-x86:
|
|||||||
|
|
||||||
netbsd-rt:
|
netbsd-rt:
|
||||||
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lpthread" \
|
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lpthread" \
|
||||||
OBJECTS="decode.o dct64.o audio_sun.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -ansi -pedantic -O3 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -ansi -pedantic -O3 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math \
|
-funroll-all-loops -ffast-math \
|
||||||
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD" \
|
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD" \
|
||||||
@@ -562,7 +607,8 @@ netbsd-rt:
|
|||||||
|
|
||||||
netbsd-x86-rt:
|
netbsd-x86-rt:
|
||||||
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lpthread" \
|
$(MAKE) CC=cc LDFLAGS="$(LDFLAGS) -lpthread" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_sun.o" \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=sun \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -mcpu=i486 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_I386 -Wall -ansi -pedantic -O4 -mcpu=i486 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD" \
|
-DREAL_IS_FLOAT -DHAVE_MMAP -DNETBSD" \
|
||||||
@@ -570,8 +616,8 @@ netbsd-x86-rt:
|
|||||||
|
|
||||||
bsdos:
|
bsdos:
|
||||||
$(MAKE) CC=shlicc2 \
|
$(MAKE) CC=shlicc2 \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
audio_oss.o" \
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DI386_ASSEM -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
-DI386_ASSEM -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
||||||
@@ -580,7 +626,8 @@ bsdos:
|
|||||||
|
|
||||||
bsdos4:
|
bsdos4:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o audio_oss.o" \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
|
OUTPUT_MODULE=oss \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DOPT_I386 -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
-DOPT_I386 -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
||||||
@@ -590,8 +637,8 @@ bsdos4:
|
|||||||
bsdos-nas:
|
bsdos-nas:
|
||||||
$(MAKE) CC=shlicc2 \
|
$(MAKE) CC=shlicc2 \
|
||||||
AUDIO_LIB="-laudio -lXau -L/usr/X11R6/lib" \
|
AUDIO_LIB="-laudio -lXau -L/usr/X11R6/lib" \
|
||||||
OBJECTS="decode_i386.o dct64_i386.o \
|
OBJECTS="decode_i386.o dct64_i386.o" \
|
||||||
audio_nas.o" \
|
OUTPUT_MODULE=nas \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -Wall -O4 -mcpu=i486 -fomit-frame-pointer \
|
||||||
-funroll-all-loops -ffast-math -DROT_I386 \
|
-funroll-all-loops -ffast-math -DROT_I386 \
|
||||||
-DOPT_I386 -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
-DOPT_I386 -DREAL_IS_FLOAT -DHAVE_MMAP -DOSS \
|
||||||
@@ -600,7 +647,8 @@ bsdos-nas:
|
|||||||
|
|
||||||
mint:
|
mint:
|
||||||
$(MAKE) CC=gcc \
|
$(MAKE) CC=gcc \
|
||||||
OBJECTS="decode.o dct64.o audio_mint.o" \
|
OBJECTS="decode.o dct64.o" \
|
||||||
|
OUTPUT_MODULE=mint \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -O2 -m68020-40 -m68881 \
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -Wall -O2 -m68020-40 -m68881 \
|
||||||
-fomit-frame-pointer -funroll-all-loops \
|
-fomit-frame-pointer -funroll-all-loops \
|
||||||
-finline-functions -ffast-math \
|
-finline-functions -ffast-math \
|
||||||
@@ -608,11 +656,23 @@ mint:
|
|||||||
AUDIO_LIB='-lsocket' \
|
AUDIO_LIB='-lsocket' \
|
||||||
mpg123-make
|
mpg123-make
|
||||||
|
|
||||||
|
macosx:
|
||||||
|
$(MAKE) CC=gcc \
|
||||||
|
OBJECTS="decode.o dct64.o sfifo.o term.o" \
|
||||||
|
OUTPUT_MODULE=coreaudio \
|
||||||
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) \
|
||||||
|
-DREAL_IS_FLOAT -DHAVE_TERMIOS -DNO_RT -DOPT_GENERIC \
|
||||||
|
-Wall -O2 -fomit-frame-pointer -funroll-all-loops \
|
||||||
|
-finline-functions -ffast-math" \
|
||||||
|
AUDIO_LIB="-framework AudioToolbox -framework AudioUnit -framework CoreServices" \
|
||||||
|
mpg123-make
|
||||||
|
|
||||||
# maybe you need the additonal options LDFLAGS='-lnsl -lsocket' when linking (see solaris:)
|
# maybe you need the additonal options LDFLAGS='-lnsl -lsocket' when linking (see solaris:)
|
||||||
generic:
|
generic:
|
||||||
$(MAKE) LDFLAGS= OBJECTS="decode.o dct64.o audio_dummy.o" \
|
$(MAKE) LDFLAGS= OBJECTS="decode.o dct64.o" \
|
||||||
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DGENERIC -DNOXFERMEM" \
|
OUTPUT_MODULE=dummy \
|
||||||
mpg123-make
|
CFLAGS="$(CFLAGS) $(CPPFLAGS) -DOPT_GENERIC -DGENERIC -DNOXFERMEM" \
|
||||||
|
mpg123-make
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
###########################################################################
|
###########################################################################
|
||||||
@@ -625,11 +685,13 @@ mpg123: mpg123.o playlist.o stringbuf.o common.o id3.o icy.o $(OBJECTS) decode_2
|
|||||||
tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \
|
tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \
|
||||||
getlopt.o httpget.o xfermem.o equalizer.o \
|
getlopt.o httpget.o xfermem.o equalizer.o \
|
||||||
decode_ntom.o $(MAKEFILE) wav.o readers.o getbits.o \
|
decode_ntom.o $(MAKEFILE) wav.o readers.o getbits.o \
|
||||||
control_generic.o
|
control_generic.o legacy_module.o output/$(OUTPUT_MODULE).o
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) mpg123.o playlist.o stringbuf.o tabinit.o common.o id3.o icy.o layer1.o \
|
$(CC) $(CFLAGS) $(LDFLAGS) \
|
||||||
|
mpg123.o playlist.o stringbuf.o tabinit.o common.o id3.o icy.o layer1.o \
|
||||||
layer2.o layer3.o audio.o buffer.o decode_2to1.o equalizer.o \
|
layer2.o layer3.o audio.o buffer.o decode_2to1.o equalizer.o \
|
||||||
decode_4to1.o getlopt.o httpget.o xfermem.o decode_ntom.o \
|
decode_4to1.o getlopt.o httpget.o xfermem.o decode_ntom.o \
|
||||||
wav.o readers.o getbits.o control_generic.o \
|
wav.o readers.o getbits.o control_generic.o \
|
||||||
|
output/$(OUTPUT_MODULE).o legacy_module.o \
|
||||||
$(OBJECTS) -o $(BINNAME) -lm $(AUDIO_LIB)
|
$(OBJECTS) -o $(BINNAME) -lm $(AUDIO_LIB)
|
||||||
|
|
||||||
mpg123.exe: mpg123.o playlist.o stringbuf.o common.o id3.o $(OBJECTS) decode_2to1.o decode_4to1.o \
|
mpg123.exe: mpg123.o playlist.o stringbuf.o common.o id3.o $(OBJECTS) decode_2to1.o decode_4to1.o \
|
||||||
@@ -637,6 +699,9 @@ mpg123.exe: mpg123.o playlist.o stringbuf.o common.o id3.o $(OBJECTS) decode_2to
|
|||||||
getlopt.o httpget.o $(MAKEFILE) wav.o readers.o getbits.o
|
getlopt.o httpget.o $(MAKEFILE) wav.o readers.o getbits.o
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o mpg123.exe -lm $(LIBS)
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o mpg123.exe -lm $(LIBS)
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) -I. -I.. -DDEFAULT_OUTPUT_MODULE="\"$(OUTPUT_MODULE)\"" -c -o $@ $<
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
###########################################################################
|
###########################################################################
|
||||||
###########################################################################
|
###########################################################################
|
||||||
@@ -653,13 +718,6 @@ common.o: mpg123.h common.h layer3.h debug.h config.h id3.h icy.h
|
|||||||
mpg123.o: mpg123.c mpg123.h getlopt.h xfermem.h buffer.h term.h debug.h id3.h config.h
|
mpg123.o: mpg123.c mpg123.h getlopt.h xfermem.h buffer.h term.h debug.h id3.h config.h
|
||||||
mpg123.h: audio.h debug.h config.h
|
mpg123.h: audio.h debug.h config.h
|
||||||
audio.o: mpg123.h debug.h config.h
|
audio.o: mpg123.h debug.h config.h
|
||||||
audio_oss.o: mpg123.h debug.h config.h
|
|
||||||
audio_sun.o: mpg123.h debug.h config.h
|
|
||||||
audio_sgi.o: mpg123.h debug.h config.h
|
|
||||||
audio_hp.o: mpg123.h debug.h config.h
|
|
||||||
audio_nas.o: mpg123.h debug.h config.h
|
|
||||||
audio_os2.o: mpg123.h debug.h config.h
|
|
||||||
audio_dummy.o: mpg123.h debug.h config.h
|
|
||||||
buffer.o: mpg123.h xfermem.h buffer.h debug.h config.h
|
buffer.o: mpg123.h xfermem.h buffer.h debug.h config.h
|
||||||
getbits.o: common.h mpg123.h debug.h config.h
|
getbits.o: common.h mpg123.h debug.h config.h
|
||||||
tabinit.o: mpg123.h audio.h debug.h config.h
|
tabinit.o: mpg123.h audio.h debug.h config.h
|
||||||
@@ -678,13 +736,27 @@ id3.o: config.h mpg123.h stringbuf.h genre.h id3.h debug.h common.h
|
|||||||
icy.o: icy.h stringbuf.h
|
icy.o: icy.h stringbuf.h
|
||||||
control_generic.o: config.h mpg123.h common.h debug.h layer3.h id3.h icy.h
|
control_generic.o: config.h mpg123.h common.h debug.h layer3.h id3.h icy.h
|
||||||
|
|
||||||
|
output/aix.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/alib.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/alsa.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/coreaudio.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/dummy.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/esd.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/hp.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/mint.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/nas.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/os2.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/oss.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/sgi.o: audio.h mpg123.h debug.h config.h
|
||||||
|
output/sun.o: audio.h mpg123.h debug.h config.h
|
||||||
|
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
###########################################################################
|
###########################################################################
|
||||||
###########################################################################
|
###########################################################################
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *core *~ mpg123 gmon.out system
|
rm -f *.o *core *~ output/*.o mpg123 gmon.out system
|
||||||
|
|
||||||
prepared-for-install:
|
prepared-for-install:
|
||||||
@if [ ! -x mpg123 ]; then \
|
@if [ ! -x mpg123 ]; then \
|
||||||
|
|||||||
344
src/audio.c
344
src/audio.c
@@ -8,29 +8,105 @@
|
|||||||
|
|
||||||
#include "mpg123.h"
|
#include "mpg123.h"
|
||||||
|
|
||||||
void audio_info_struct_init(struct audio_info_struct *ai)
|
/* Open an audio output module */
|
||||||
|
audio_output_t* open_output_module( const char* name )
|
||||||
{
|
{
|
||||||
ai->fn = -1;
|
mpg123_module_t *module = NULL;
|
||||||
ai->rate = -1;
|
audio_output_t *ao = NULL;
|
||||||
ai->gain = -1;
|
int result = 0;
|
||||||
ai->output = -1;
|
|
||||||
ai->handle = NULL;
|
/* Open the module */
|
||||||
ai->device = NULL;
|
module = open_module( "output", name );
|
||||||
ai->channels = -1;
|
if (module == NULL) return NULL;
|
||||||
ai->format = -1;
|
|
||||||
|
/* Check module supports output */
|
||||||
|
if (module->init_output == NULL) {
|
||||||
|
error1("Module '%s' does not support audio output.", name);
|
||||||
|
close_module( module );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocation memory for audio output type */
|
||||||
|
ao = alloc_audio_output();
|
||||||
|
if (ao==NULL) {
|
||||||
|
error( "Failed to allocate audio output structure." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the init function */
|
||||||
|
result = module->init_output(ao);
|
||||||
|
if (result) {
|
||||||
|
error1( "Module's init function failed: %d", result );
|
||||||
|
close_module( module );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the pointer to the module (so we can close it later) */
|
||||||
|
ao->module = module;
|
||||||
|
|
||||||
|
return ao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void audio_info_struct_dump(struct audio_info_struct *ai)
|
|
||||||
|
/* FIXME: this is called anywhere */
|
||||||
|
void close_output_module( audio_output_t* ao )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ai->fn=%d\n", ai->fn);
|
if (!ao) return;
|
||||||
fprintf(stderr, "ai->handle=%p\n", ai->handle);
|
|
||||||
fprintf(stderr, "ai->rate=%ld\n", ai->rate);
|
/* Close the audio output */
|
||||||
fprintf(stderr, "ai->gain=%ld\n", ai->gain);
|
if (ao->close) ao->close( ao );
|
||||||
fprintf(stderr, "ai->output=%d\n", ai->output);
|
|
||||||
fprintf(stderr, "ai->device='%s'\n", ai->device);
|
/* Deinitialise the audio output */
|
||||||
fprintf(stderr, "ai->channels=%d\n", ai->channels);
|
if (ao->deinit) ao->deinit( ao );
|
||||||
fprintf(stderr, "ai->format=%d\n", ai->format);
|
|
||||||
|
/* Unload the module */
|
||||||
|
if (ao->module) close_module( ao->module );
|
||||||
|
|
||||||
|
/* Free up memory */
|
||||||
|
free( ao );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* allocate and initialise memory */
|
||||||
|
audio_output_t* alloc_audio_output()
|
||||||
|
{
|
||||||
|
audio_output_t* ao = malloc( sizeof( audio_output_t ) );
|
||||||
|
if (ao==NULL) error( "Failed to allocate memory for audio_output_t." );
|
||||||
|
|
||||||
|
/* Initialise variables */
|
||||||
|
ao->fn = -1;
|
||||||
|
ao->rate = -1;
|
||||||
|
ao->gain = -1;
|
||||||
|
ao->userptr = NULL;
|
||||||
|
ao->device = NULL;
|
||||||
|
ao->channels = -1;
|
||||||
|
ao->format = -1;
|
||||||
|
|
||||||
|
/*ao->module = NULL;*/
|
||||||
|
|
||||||
|
/* Set the callbacks to NULL */
|
||||||
|
ao->open = NULL;
|
||||||
|
ao->get_formats = NULL;
|
||||||
|
ao->write = NULL;
|
||||||
|
ao->flush = NULL;
|
||||||
|
ao->close = NULL;
|
||||||
|
ao->deinit = NULL;
|
||||||
|
|
||||||
|
return ao;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void audio_output_dump(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ao->fn=%d\n", ao->fn);
|
||||||
|
fprintf(stderr, "ao->userptr=%p\n", ao->userptr);
|
||||||
|
fprintf(stderr, "ao->rate=%ld\n", ao->rate);
|
||||||
|
fprintf(stderr, "ao->gain=%ld\n", ao->gain);
|
||||||
|
fprintf(stderr, "ao->device='%s'\n", ao->device);
|
||||||
|
fprintf(stderr, "ao->channels=%d\n", ao->channels);
|
||||||
|
fprintf(stderr, "ao->format=%d\n", ao->format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -38,48 +114,45 @@ void audio_info_struct_dump(struct audio_info_struct *ai)
|
|||||||
#define NUM_ENCODINGS 6
|
#define NUM_ENCODINGS 6
|
||||||
#define NUM_RATES 10
|
#define NUM_RATES 10
|
||||||
|
|
||||||
struct audio_name audio_val2name[NUM_ENCODINGS+1] = {
|
struct audio_format_name audio_val2name[NUM_ENCODINGS+1] = {
|
||||||
{ AUDIO_FORMAT_SIGNED_16 , "signed 16 bit" , "s16 " } ,
|
{ AUDIO_FORMAT_SIGNED_16 , "signed 16 bit" , "s16 " } ,
|
||||||
{ AUDIO_FORMAT_UNSIGNED_16, "unsigned 16 bit" , "u16 " } ,
|
{ AUDIO_FORMAT_UNSIGNED_16, "unsigned 16 bit" , "u16 " } ,
|
||||||
{ AUDIO_FORMAT_UNSIGNED_8 , "unsigned 8 bit" , "u8 " } ,
|
{ AUDIO_FORMAT_UNSIGNED_8 , "unsigned 8 bit" , "u8 " } ,
|
||||||
{ AUDIO_FORMAT_SIGNED_8 , "signed 8 bit" , "s8 " } ,
|
{ AUDIO_FORMAT_SIGNED_8 , "signed 8 bit" , "s8 " } ,
|
||||||
{ AUDIO_FORMAT_ULAW_8 , "mu-law (8 bit)" , "ulaw " } ,
|
{ AUDIO_FORMAT_ULAW_8 , "mu-law (8 bit)" , "ulaw " } ,
|
||||||
{ AUDIO_FORMAT_ALAW_8 , "a-law (8 bit)" , "alaw " } ,
|
{ AUDIO_FORMAT_ALAW_8 , "a-law (8 bit)" , "alaw " } ,
|
||||||
{ -1 , NULL }
|
{ -1 , NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
|
||||||
static char *channel_name[NUM_CHANNELS] =
|
|
||||||
{ "mono" , "stereo" };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int channels[NUM_CHANNELS] = { 1 , 2 };
|
static int channels[NUM_CHANNELS] = { 1 , 2 };
|
||||||
static int rates[NUM_RATES] = {
|
static int rates[NUM_RATES] = {
|
||||||
8000, 11025, 12000,
|
8000, 11025, 12000,
|
||||||
16000, 22050, 24000,
|
16000, 22050, 24000,
|
||||||
32000, 44100, 48000,
|
32000, 44100, 48000,
|
||||||
8000 /* 8000 = dummy for user forced */
|
8000 /* 8000 = dummy for user forced */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int encodings[NUM_ENCODINGS] = {
|
static int encodings[NUM_ENCODINGS] = {
|
||||||
AUDIO_FORMAT_SIGNED_16,
|
AUDIO_FORMAT_SIGNED_16,
|
||||||
AUDIO_FORMAT_UNSIGNED_16,
|
AUDIO_FORMAT_UNSIGNED_16,
|
||||||
AUDIO_FORMAT_UNSIGNED_8,
|
AUDIO_FORMAT_UNSIGNED_8,
|
||||||
AUDIO_FORMAT_SIGNED_8,
|
AUDIO_FORMAT_SIGNED_8,
|
||||||
AUDIO_FORMAT_ULAW_8,
|
AUDIO_FORMAT_ULAW_8,
|
||||||
AUDIO_FORMAT_ALAW_8
|
AUDIO_FORMAT_ALAW_8
|
||||||
};
|
};
|
||||||
|
|
||||||
static char capabilities[NUM_CHANNELS][NUM_ENCODINGS][NUM_RATES];
|
static char capabilities[NUM_CHANNELS][NUM_ENCODINGS][NUM_RATES];
|
||||||
|
|
||||||
void print_capabilities(struct audio_info_struct *ai)
|
static void print_capabilities(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int j,k,k1=NUM_RATES-1;
|
int j,k,k1=NUM_RATES-1;
|
||||||
if(param.force_rate) {
|
if(param.force_rate) {
|
||||||
rates[NUM_RATES-1] = param.force_rate;
|
rates[NUM_RATES-1] = param.force_rate;
|
||||||
k1 = NUM_RATES;
|
k1 = NUM_RATES;
|
||||||
}
|
}
|
||||||
fprintf(stderr,"\nAudio device: %s\nAudio capabilities:\n(matrix of [S]tereo or [M]ono support for sample format and rate in Hz)\n |", ai->device != NULL ? ai->device : "<none>");
|
fprintf(stderr,"\nAudio device: %s\nAudio capabilities:\n(matrix of [S]tereo or [M]ono support for sample format and rate in Hz)\n |",
|
||||||
|
ao->device != NULL ? ao->device : "<none>");
|
||||||
for(j=0;j<NUM_ENCODINGS;j++) {
|
for(j=0;j<NUM_ENCODINGS;j++) {
|
||||||
fprintf(stderr," %5s |",audio_val2name[j].sname);
|
fprintf(stderr," %5s |",audio_val2name[j].sname);
|
||||||
}
|
}
|
||||||
@@ -104,13 +177,13 @@ void print_capabilities(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void audio_capabilities(struct audio_info_struct *ai)
|
void audio_capabilities(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int fmts;
|
int fmts;
|
||||||
int i,j,k,k1=NUM_RATES-1;
|
int i,j,k,k1=NUM_RATES-1;
|
||||||
struct audio_info_struct ai1 = *ai;
|
audio_output_t ao1 = *ao;
|
||||||
|
|
||||||
if (param.outmode != DECODE_AUDIO) {
|
if (param.outmode != DECODE_AUDIO) {
|
||||||
memset(capabilities,1,sizeof(capabilities));
|
memset(capabilities,1,sizeof(capabilities));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -122,16 +195,16 @@ void audio_capabilities(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* if audio_open fails, the device is just not capable of anything... */
|
/* if audio_open fails, the device is just not capable of anything... */
|
||||||
if(audio_open(&ai1) < 0) {
|
if(ao1.open(&ao1) < 0) {
|
||||||
perror("audio");
|
error("failed to open audio device");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(i=0;i<NUM_CHANNELS;i++) {
|
for(i=0;i<NUM_CHANNELS;i++) {
|
||||||
for(j=0;j<NUM_RATES;j++) {
|
for(j=0;j<NUM_RATES;j++) {
|
||||||
ai1.channels = channels[i];
|
ao1.channels = channels[i];
|
||||||
ai1.rate = rates[j];
|
ao1.rate = rates[j];
|
||||||
fmts = audio_get_formats(&ai1);
|
fmts = ao1.get_formats(&ao1);
|
||||||
if(fmts < 0)
|
if(fmts < 0)
|
||||||
continue;
|
continue;
|
||||||
for(k=0;k<NUM_ENCODINGS;k++) {
|
for(k=0;k<NUM_ENCODINGS;k++) {
|
||||||
@@ -140,10 +213,10 @@ void audio_capabilities(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio_close(&ai1);
|
ao1.close(&ao1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(param.verbose > 1) print_capabilities(ai);
|
if(param.verbose > 1) print_capabilities(ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rate2num(int r)
|
static int rate2num(int r)
|
||||||
@@ -156,22 +229,22 @@ static int rate2num(int r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int audio_fit_cap_helper(struct audio_info_struct *ai,int rn,int f0,int f2,int c)
|
static int audio_fit_cap_helper(audio_output_t *ao,int rn,int f0,int f2,int c)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(rn >= 0) {
|
if(rn >= 0) {
|
||||||
for(i=f0;i<f2;i++) {
|
for(i=f0;i<f2;i++) {
|
||||||
if(capabilities[c][i][rn]) {
|
if(capabilities[c][i][rn]) {
|
||||||
ai->rate = rates[rn];
|
ao->rate = rates[rn];
|
||||||
ai->format = encodings[i];
|
ao->format = encodings[i];
|
||||||
ai->channels = channels[c];
|
ao->channels = channels[c];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -179,12 +252,15 @@ static int audio_fit_cap_helper(struct audio_info_struct *ai,int rn,int f0,int f
|
|||||||
* r=rate of stream
|
* r=rate of stream
|
||||||
* return 0 on error
|
* return 0 on error
|
||||||
*/
|
*/
|
||||||
int audio_fit_capabilities(struct audio_info_struct *ai,int c,int r)
|
int audio_fit_capabilities(audio_output_t *ao,int c,int r)
|
||||||
{
|
{
|
||||||
int rn;
|
int rn;
|
||||||
int f0=0;
|
int f0=0;
|
||||||
|
|
||||||
if(param.force_8bit) f0 = 2; /* skip the 16bit encodings */
|
/* skip the 16bit encodings */
|
||||||
|
if(param.force_8bit) {
|
||||||
|
f0 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
c--; /* stereo=1 ,mono=0 */
|
c--; /* stereo=1 ,mono=0 */
|
||||||
|
|
||||||
@@ -196,76 +272,76 @@ int audio_fit_capabilities(struct audio_info_struct *ai,int c,int r)
|
|||||||
rates[NUM_RATES-1] = param.force_rate; /* To make STDOUT decoding work. */
|
rates[NUM_RATES-1] = param.force_rate; /* To make STDOUT decoding work. */
|
||||||
rn = rate2num(param.force_rate);
|
rn = rate2num(param.force_rate);
|
||||||
/* 16bit encodings */
|
/* 16bit encodings */
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,f0,2,c)) return 1;
|
||||||
/* 8bit encodings */
|
/* 8bit encodings */
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c)) return 1;
|
||||||
|
|
||||||
/* try again with different stereoness */
|
/* try again with different stereoness */
|
||||||
if(c == 1 && !param.force_stereo) c = 0;
|
if(c == 1 && !param.force_stereo) c = 0;
|
||||||
else if(c == 0 && !param.force_mono) c = 1;
|
else if(c == 0 && !param.force_mono) c = 1;
|
||||||
|
|
||||||
/* 16bit encodings */
|
/* 16bit encodings */
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,f0,2,c)) return 1;
|
||||||
/* 8bit encodings */
|
/* 8bit encodings */
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c)) return 1;
|
||||||
|
|
||||||
error3("Unable to set up output device! Constraints: %s%s%liHz.",
|
error3("Unable to set up output device! Constraints: %s%s%liHz.",
|
||||||
(param.force_stereo ? "stereo, " :
|
(param.force_stereo ? "stereo, " :
|
||||||
(param.force_mono ? "mono, " : "")),
|
(param.force_mono ? "mono, " : "")),
|
||||||
(param.force_8bit ? "8bit, " : ""),
|
(param.force_8bit ? "8bit, " : ""),
|
||||||
param.force_rate);
|
param.force_rate);
|
||||||
if(param.verbose <= 1) print_capabilities(ai);
|
if(param.verbose <= 1) print_capabilities(ao);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try different rates with 16bit */
|
/* try different rates with 16bit */
|
||||||
rn = rate2num(r>>0);
|
rn = rate2num(r>>0);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c))
|
if(audio_fit_cap_helper(ao,rn,f0,2,c))
|
||||||
return 1;
|
return 1;
|
||||||
rn = rate2num(r>>1);
|
rn = rate2num(r>>1);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c))
|
if(audio_fit_cap_helper(ao,rn,f0,2,c))
|
||||||
return 1;
|
return 1;
|
||||||
rn = rate2num(r>>2);
|
rn = rate2num(r>>2);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c))
|
if(audio_fit_cap_helper(ao,rn,f0,2,c))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* try different rates with 8bit */
|
/* try different rates with 8bit */
|
||||||
rn = rate2num(r>>0);
|
rn = rate2num(r>>0);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c))
|
||||||
return 1;
|
return 1;
|
||||||
rn = rate2num(r>>1);
|
rn = rate2num(r>>1);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c))
|
||||||
return 1;
|
return 1;
|
||||||
rn = rate2num(r>>2);
|
rn = rate2num(r>>2);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c))
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* try again with different stereoness */
|
/* try agaon with different stereoness */
|
||||||
if(c == 1 && !param.force_stereo) c = 0;
|
if(c == 1 && !param.force_stereo) c = 0;
|
||||||
else if(c == 0 && !param.force_mono) c = 1;
|
else if(c == 0 && !param.force_mono) c = 1;
|
||||||
|
|
||||||
/* 16bit */
|
/* 16bit */
|
||||||
rn = rate2num(r>>0);
|
rn = rate2num(r>>0);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,f0,2,c)) return 1;
|
||||||
rn = rate2num(r>>1);
|
rn = rate2num(r>>1);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,f0,2,c)) return 1;
|
||||||
rn = rate2num(r>>2);
|
rn = rate2num(r>>2);
|
||||||
if(audio_fit_cap_helper(ai,rn,f0,2,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,f0,2,c)) return 1;
|
||||||
|
|
||||||
/* 8bit */
|
/* 8bit */
|
||||||
rn = rate2num(r>>0);
|
rn = rate2num(r>>0);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c)) return 1;
|
||||||
rn = rate2num(r>>1);
|
rn = rate2num(r>>1);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c)) return 1;
|
||||||
rn = rate2num(r>>2);
|
rn = rate2num(r>>2);
|
||||||
if(audio_fit_cap_helper(ai,rn,2,NUM_ENCODINGS,c)) return 1;
|
if(audio_fit_cap_helper(ao,rn,2,NUM_ENCODINGS,c)) return 1;
|
||||||
|
|
||||||
error5("Unable to set up output device! Constraints: %s%s%i, %i or %iHz.",
|
error5("Unable to set up output device! Constraints: %s%s%i, %i or %iHz.",
|
||||||
(param.force_stereo ? "stereo, " :
|
(param.force_stereo ? "stereo, " :
|
||||||
(param.force_mono ? "mono, " : "")),
|
(param.force_mono ? "mono, " : "")),
|
||||||
(param.force_8bit ? "8bit, " : ""),
|
(param.force_8bit ? "8bit, " : ""),
|
||||||
r, r>>1, r>>2);
|
r, r>>1, r>>2);
|
||||||
if(param.verbose <= 1) print_capabilities(ai);
|
if(param.verbose <= 1) print_capabilities(ao);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,3 +355,105 @@ char *audio_encoding_name(int format)
|
|||||||
}
|
}
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
|
#ifndef NOXFERMEM
|
||||||
|
static void catch_child(void)
|
||||||
|
{
|
||||||
|
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: Old output initialization code that needs updating */
|
||||||
|
|
||||||
|
int init_output( audio_output_t *ao )
|
||||||
|
{
|
||||||
|
static int init_done = FALSE;
|
||||||
|
|
||||||
|
if (init_done) return 0;
|
||||||
|
init_done = TRUE;
|
||||||
|
|
||||||
|
#ifndef NOXFERMEM
|
||||||
|
/*
|
||||||
|
* Only DECODE_AUDIO and DECODE_FILE are sanely handled by the
|
||||||
|
* buffer process. For now, we just ignore the request
|
||||||
|
* to buffer the output. [dk]
|
||||||
|
*/
|
||||||
|
if (param.usebuffer && (param.outmode != DECODE_AUDIO) &&
|
||||||
|
(param.outmode != DECODE_FILE)) {
|
||||||
|
fprintf(stderr, "Sorry, won't buffer output unless writing plain audio.\n");
|
||||||
|
param.usebuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.usebuffer) {
|
||||||
|
unsigned int bufferbytes;
|
||||||
|
sigset_t newsigset, oldsigset;
|
||||||
|
if (param.usebuffer < 32)
|
||||||
|
param.usebuffer = 32; /* minimum is 32 Kbytes! */
|
||||||
|
bufferbytes = (param.usebuffer * 1024);
|
||||||
|
bufferbytes -= bufferbytes % FRAMEBUFUNIT;
|
||||||
|
/* +1024 for NtoM rounding problems */
|
||||||
|
xfermem_init (&buffermem, bufferbytes ,0,1024);
|
||||||
|
pcm_sample = (unsigned char *) buffermem->data;
|
||||||
|
pcm_point = 0;
|
||||||
|
sigemptyset (&newsigset);
|
||||||
|
sigaddset (&newsigset, SIGUSR1);
|
||||||
|
sigprocmask (SIG_BLOCK, &newsigset, &oldsigset);
|
||||||
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
|
catchsignal (SIGCHLD, catch_child);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch ((buffer_pid = fork())) {
|
||||||
|
case -1: /* error */
|
||||||
|
perror("fork()");
|
||||||
|
return 1;
|
||||||
|
case 0: /* child */
|
||||||
|
if(rd) rd->close(rd); /* child doesn't need the input stream */
|
||||||
|
xfermem_init_reader (buffermem);
|
||||||
|
buffer_loop(ao, &oldsigset);
|
||||||
|
xfermem_done_reader (buffermem);
|
||||||
|
xfermem_done (buffermem);
|
||||||
|
exit(0);
|
||||||
|
default: /* parent */
|
||||||
|
xfermem_init_writer (buffermem);
|
||||||
|
param.outmode = DECODE_BUFFER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* + 1024 for NtoM rate converter */
|
||||||
|
if (!(pcm_sample = (unsigned char *) malloc(audiobufsize * 2 + 1024))) {
|
||||||
|
perror ("malloc()");
|
||||||
|
return 1;
|
||||||
|
#ifndef NOXFERMEM
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(param.outmode) {
|
||||||
|
case DECODE_AUDIO:
|
||||||
|
if(ao->open(ao) < 0) {
|
||||||
|
error("failed to open audio device");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DECODE_WAV:
|
||||||
|
wav_open(ao,param.filename);
|
||||||
|
break;
|
||||||
|
case DECODE_AU:
|
||||||
|
au_open(ao,param.filename);
|
||||||
|
break;
|
||||||
|
case DECODE_CDR:
|
||||||
|
cdr_open(ao,param.filename);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
83
src/audio.h
83
src/audio.h
@@ -14,6 +14,8 @@
|
|||||||
#ifndef _MPG123_AUDIO_H_
|
#ifndef _MPG123_AUDIO_H_
|
||||||
#define _MPG123_AUDIO_H_
|
#define _MPG123_AUDIO_H_
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
#define AUDIO_OUT_HEADPHONES 0x01
|
#define AUDIO_OUT_HEADPHONES 0x01
|
||||||
#define AUDIO_OUT_INTERNAL_SPEAKER 0x02
|
#define AUDIO_OUT_INTERNAL_SPEAKER 0x02
|
||||||
#define AUDIO_OUT_LINE_OUT 0x04
|
#define AUDIO_OUT_LINE_OUT 0x04
|
||||||
@@ -29,60 +31,67 @@ enum {
|
|||||||
DECODE_AUDIOFILE
|
DECODE_AUDIOFILE
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AUDIO_FORMAT_MASK 0x100
|
|
||||||
#define AUDIO_FORMAT_16 0x100
|
|
||||||
#define AUDIO_FORMAT_8 0x000
|
|
||||||
|
|
||||||
#define AUDIO_FORMAT_SIGNED_16 0x110
|
#define AUDIO_FORMAT_MASK 0x100
|
||||||
#define AUDIO_FORMAT_UNSIGNED_16 0x120
|
#define AUDIO_FORMAT_16 0x100
|
||||||
#define AUDIO_FORMAT_UNSIGNED_8 0x1
|
#define AUDIO_FORMAT_8 0x000
|
||||||
#define AUDIO_FORMAT_SIGNED_8 0x2
|
|
||||||
#define AUDIO_FORMAT_ULAW_8 0x4
|
#define AUDIO_FORMAT_SIGNED_16 0x110
|
||||||
#define AUDIO_FORMAT_ALAW_8 0x8
|
#define AUDIO_FORMAT_UNSIGNED_16 0x120
|
||||||
|
#define AUDIO_FORMAT_UNSIGNED_8 0x1
|
||||||
|
#define AUDIO_FORMAT_SIGNED_8 0x2
|
||||||
|
#define AUDIO_FORMAT_ULAW_8 0x4
|
||||||
|
#define AUDIO_FORMAT_ALAW_8 0x8
|
||||||
|
|
||||||
/* 3% rate tolerance */
|
/* 3% rate tolerance */
|
||||||
#define AUDIO_RATE_TOLERANCE 3
|
#define AUDIO_RATE_TOLERANCE 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct audio_info_struct
|
typedef struct audio_output_struct
|
||||||
{
|
{
|
||||||
int fn; /* filenumber */
|
int fn; /* filenumber */
|
||||||
void *handle; /* driver specific pointer */
|
void *userptr; /* driver specific pointer */
|
||||||
|
|
||||||
|
/* Callbacks */
|
||||||
|
int (*open)(struct audio_output_struct *);
|
||||||
|
int (*get_formats)(struct audio_output_struct *);
|
||||||
|
int (*write)(struct audio_output_struct *, unsigned char *,int);
|
||||||
|
void (*flush)(struct audio_output_struct *);
|
||||||
|
int (*close)(struct audio_output_struct *);
|
||||||
|
int (*deinit)(struct audio_output_struct *);
|
||||||
|
|
||||||
|
/* the module this belongs to */
|
||||||
|
mpg123_module_t *module;
|
||||||
|
|
||||||
|
char *device; /* device name */
|
||||||
|
long rate; /* sample rate */
|
||||||
|
long gain; /* output gain */
|
||||||
|
int channels; /* number of channels */
|
||||||
|
int format; /* format flags */
|
||||||
|
int output; /* headphone/speaker/lineout */
|
||||||
|
|
||||||
|
} audio_output_t;
|
||||||
|
|
||||||
long rate;
|
struct audio_format_name {
|
||||||
long gain;
|
int val;
|
||||||
int output;
|
char *name;
|
||||||
|
char *sname;
|
||||||
char *device;
|
|
||||||
int channels;
|
|
||||||
int format;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct audio_name {
|
|
||||||
int val;
|
|
||||||
char *name;
|
|
||||||
char *sname;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ------ Declarations from "audio.c" ------ */
|
/* ------ Declarations from "audio.c" ------ */
|
||||||
|
|
||||||
extern void audio_info_struct_init(struct audio_info_struct *);
|
extern audio_output_t* open_output_module( const char* name );
|
||||||
extern void audio_info_struct_dump(struct audio_info_struct *ai);
|
extern audio_output_t* alloc_audio_output();
|
||||||
extern void audio_capabilities(struct audio_info_struct *);
|
extern void deinit_audio_output( audio_output_t* ao );
|
||||||
extern int audio_fit_capabilities(struct audio_info_struct *ai,int c,int r);
|
extern void audio_output_dump(audio_output_t *ao);
|
||||||
|
extern void audio_capabilities(audio_output_t *ao);
|
||||||
|
extern int audio_fit_capabilities(audio_output_t *ao,int c,int r);
|
||||||
extern char *audio_encoding_name(int format);
|
extern char *audio_encoding_name(int format);
|
||||||
|
|
||||||
|
extern int init_output( audio_output_t *ao );
|
||||||
|
|
||||||
/* ------ Declarations from "audio_*.c" ------ */
|
|
||||||
|
|
||||||
extern int audio_open(struct audio_info_struct *);
|
|
||||||
extern int audio_get_formats(struct audio_info_struct *);
|
|
||||||
extern int audio_play_samples(struct audio_info_struct *, unsigned char *,int);
|
|
||||||
extern void audio_queueflush(struct audio_info_struct *ai);
|
|
||||||
extern int audio_close(struct audio_info_struct *);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
216
src/audio_alsa.c
216
src/audio_alsa.c
@@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
audio_alsa: sound output with Advanced Linux Sound Architecture 1.x API
|
|
||||||
|
|
||||||
copyright 2006 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
|
|
||||||
|
|
||||||
written by Clemens Ladisch <clemens@ladisch.de>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mpg123.h"
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/* make ALSA 0.9.x compatible to the 1.0.x API */
|
|
||||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
|
||||||
#define ALSA_PCM_NEW_SW_PARAMS_API
|
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
|
||||||
|
|
||||||
/* My laptop has probs playing low-sampled files with only 0.5s buffer... this should be a user setting -- ThOr */
|
|
||||||
#define BUFFER_LENGTH 0.5 /* in seconds */
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
snd_pcm_format_t alsa;
|
|
||||||
int mpg123;
|
|
||||||
} format_map[] = {
|
|
||||||
{ SND_PCM_FORMAT_S16, AUDIO_FORMAT_SIGNED_16 },
|
|
||||||
{ SND_PCM_FORMAT_U16, AUDIO_FORMAT_UNSIGNED_16 },
|
|
||||||
{ SND_PCM_FORMAT_U8, AUDIO_FORMAT_UNSIGNED_8 },
|
|
||||||
{ SND_PCM_FORMAT_S8, AUDIO_FORMAT_SIGNED_8 },
|
|
||||||
{ SND_PCM_FORMAT_A_LAW, AUDIO_FORMAT_ALAW_8 },
|
|
||||||
{ SND_PCM_FORMAT_MU_LAW, AUDIO_FORMAT_ULAW_8 },
|
|
||||||
};
|
|
||||||
#define NUM_FORMATS (sizeof format_map / sizeof format_map[0])
|
|
||||||
|
|
||||||
static int initialize_device(struct audio_info_struct *ai);
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
const char *pcm_name;
|
|
||||||
snd_pcm_t *pcm;
|
|
||||||
|
|
||||||
pcm_name = ai->device ? ai->device : "default";
|
|
||||||
if (snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
|
||||||
fprintf(stderr, "audio_open(): cannot open device %s\n", pcm_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ai->handle = pcm;
|
|
||||||
if (ai->format != -1) {
|
|
||||||
/* we're going to play: initalize sample format */
|
|
||||||
return initialize_device(ai);
|
|
||||||
} else {
|
|
||||||
/* query mode; sample format will be set for each query */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rates_match(long int desired, unsigned int actual)
|
|
||||||
{
|
|
||||||
return actual * 100 > desired * (100 - AUDIO_RATE_TOLERANCE) &&
|
|
||||||
actual * 100 < desired * (100 + AUDIO_RATE_TOLERANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int initialize_device(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_params_t *hw;
|
|
||||||
int i;
|
|
||||||
snd_pcm_format_t format;
|
|
||||||
unsigned int rate;
|
|
||||||
snd_pcm_uframes_t buffer_size;
|
|
||||||
snd_pcm_uframes_t period_size;
|
|
||||||
snd_pcm_sw_params_t *sw;
|
|
||||||
|
|
||||||
snd_pcm_hw_params_alloca(&hw);
|
|
||||||
if (snd_pcm_hw_params_any(ai->handle, hw) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): no configuration available\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_hw_params_set_access(ai->handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): device does not support interleaved access\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
format = SND_PCM_FORMAT_UNKNOWN;
|
|
||||||
for (i = 0; i < NUM_FORMATS; ++i) {
|
|
||||||
if (ai->format == format_map[i].mpg123) {
|
|
||||||
format = format_map[i].alsa;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (format == SND_PCM_FORMAT_UNKNOWN) {
|
|
||||||
fprintf(stderr, "initialize_device(): invalid sample format %d\n", ai->format);
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_hw_params_set_format(ai->handle, hw, format) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set format %s\n", snd_pcm_format_name(format));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_hw_params_set_channels(ai->handle, hw, ai->channels) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set %d channels\n", ai->channels);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rate = ai->rate;
|
|
||||||
if (snd_pcm_hw_params_set_rate_near(ai->handle, hw, &rate, NULL) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set rate %u\n", rate);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!rates_match(ai->rate, rate)) {
|
|
||||||
fprintf(stderr, "initialize_device(): rate %ld not available, using %u\n", ai->rate, rate);
|
|
||||||
/* return -1; */
|
|
||||||
}
|
|
||||||
buffer_size = rate * BUFFER_LENGTH;
|
|
||||||
if (snd_pcm_hw_params_set_buffer_size_near(ai->handle, hw, &buffer_size) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set buffer size\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
period_size = buffer_size / 4;
|
|
||||||
if (snd_pcm_hw_params_set_period_size_near(ai->handle, hw, &period_size, NULL) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set period size\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_hw_params(ai->handle, hw) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set hw params\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_pcm_sw_params_alloca(&sw);
|
|
||||||
if (snd_pcm_sw_params_current(ai->handle, sw) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot get sw params\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* start playing after the first write */
|
|
||||||
if (snd_pcm_sw_params_set_start_threshold(ai->handle, sw, 1) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set start threshold\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* wake up on every interrupt */
|
|
||||||
if (snd_pcm_sw_params_set_avail_min(ai->handle, sw, 1) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set min avail\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* always write as many frames as possible */
|
|
||||||
if (snd_pcm_sw_params_set_xfer_align(ai->handle, sw, 1) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set transfer alignment\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_sw_params(ai->handle, sw) < 0) {
|
|
||||||
fprintf(stderr, "initialize_device(): cannot set sw params\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_params_t *hw;
|
|
||||||
unsigned int rate;
|
|
||||||
int supported_formats, i;
|
|
||||||
|
|
||||||
snd_pcm_hw_params_alloca(&hw);
|
|
||||||
if (snd_pcm_hw_params_any(ai->handle, hw) < 0) {
|
|
||||||
fprintf(stderr, "audio_get_formats(): no configuration available\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snd_pcm_hw_params_set_access(ai->handle, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
|
|
||||||
return -1;
|
|
||||||
if (snd_pcm_hw_params_set_channels(ai->handle, hw, ai->channels) < 0)
|
|
||||||
return 0;
|
|
||||||
rate = ai->rate;
|
|
||||||
if (snd_pcm_hw_params_set_rate_near(ai->handle, hw, &rate, NULL) < 0)
|
|
||||||
return -1;
|
|
||||||
if (!rates_match(ai->rate, rate))
|
|
||||||
return 0;
|
|
||||||
supported_formats = 0;
|
|
||||||
for (i = 0; i < NUM_FORMATS; ++i) {
|
|
||||||
if (snd_pcm_hw_params_test_format(ai->handle, hw, format_map[i].alsa) == 0)
|
|
||||||
supported_formats |= format_map[i].mpg123;
|
|
||||||
}
|
|
||||||
return supported_formats;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int bytes)
|
|
||||||
{
|
|
||||||
snd_pcm_uframes_t frames;
|
|
||||||
snd_pcm_sframes_t written;
|
|
||||||
|
|
||||||
frames = snd_pcm_bytes_to_frames(ai->handle, bytes);
|
|
||||||
written = snd_pcm_writei(ai->handle, buf, frames);
|
|
||||||
if (written == -EINTR) /* interrupted system call */
|
|
||||||
written = 0;
|
|
||||||
else if (written == -EPIPE) { /* underrun */
|
|
||||||
if (snd_pcm_prepare(ai->handle) >= 0)
|
|
||||||
written = snd_pcm_writei(ai->handle, buf, frames);
|
|
||||||
}
|
|
||||||
if (written >= 0)
|
|
||||||
return snd_pcm_frames_to_bytes(ai->handle, written);
|
|
||||||
else
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
/* is this the optimal solution? - we should figure out what we really whant from this function */
|
|
||||||
snd_pcm_drop(ai->handle);
|
|
||||||
snd_pcm_prepare(ai->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
if(ai->handle != NULL) /* be really generous for being called without any device opening */
|
|
||||||
{
|
|
||||||
if (snd_pcm_state(ai->handle) == SND_PCM_STATE_RUNNING)
|
|
||||||
snd_pcm_drain(ai->handle);
|
|
||||||
return snd_pcm_close(ai->handle);
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
audio_dummy.c: dummy audio output
|
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
||||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
|
||||||
initially written by Michael Hipp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mpg123.h"
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"No audio device support compiled into this binary (use -s).\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|
||||||
{
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
128
src/audio_esd.c
128
src/audio_esd.c
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
audio_esd.c: audio output for ESounD (highly untested nowadays (?))
|
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
||||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
|
||||||
initially written by Eric B. Mitchell ("esd port" should be this file...)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <esd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "mpg123.h"
|
|
||||||
|
|
||||||
#ifdef SOLARIS
|
|
||||||
#include <stropts.h>
|
|
||||||
#include <sys/conf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static unsigned esd_rate = 0, esd_format = 0, esd_channels = 0;
|
|
||||||
static char *esdserver = NULL;
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
esd_format_t format = ESD_STREAM | ESD_PLAY;
|
|
||||||
|
|
||||||
if (!esd_rate)
|
|
||||||
{
|
|
||||||
int esd;
|
|
||||||
esd_server_info_t *info;
|
|
||||||
esd_format_t fmt;
|
|
||||||
|
|
||||||
if ((esd = esd_open_sound(NULL)) >= 0)
|
|
||||||
{
|
|
||||||
info = esd_get_server_info(esd);
|
|
||||||
esd_rate = info->rate;
|
|
||||||
fmt = info->format;
|
|
||||||
esd_free_server_info(info);
|
|
||||||
esd_close(esd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
esd_rate = esd_audio_rate;
|
|
||||||
fmt = esd_audio_format;
|
|
||||||
}
|
|
||||||
esd_format = AUDIO_FORMAT_UNSIGNED_8;
|
|
||||||
if ((fmt & ESD_MASK_BITS) == ESD_BITS16)
|
|
||||||
esd_format |= AUDIO_FORMAT_SIGNED_16;
|
|
||||||
esd_channels = fmt & ESD_MASK_CHAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ai->format == -1)
|
|
||||||
ai->format = esd_format;
|
|
||||||
else if (!(ai->format & esd_format))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "audio: Unsupported audio format: %d\n", ai->format);
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ai->format & AUDIO_FORMAT_SIGNED_16)
|
|
||||||
format |= ESD_BITS16;
|
|
||||||
else if (ai->format & AUDIO_FORMAT_UNSIGNED_8)
|
|
||||||
format |= ESD_BITS8;
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
if (ai->channels == -1)
|
|
||||||
ai->channels = 2;
|
|
||||||
else if (ai->channels <= 0 || ai->channels > esd_channels)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "audio: Unsupported no of channels: %d\n", ai->channels);
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ai->channels == 1)
|
|
||||||
format |= ESD_MONO;
|
|
||||||
else if (ai->channels == 2)
|
|
||||||
format |= ESD_STEREO;
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
if (ai->rate == -1)
|
|
||||||
ai->rate = esd_rate;
|
|
||||||
else if (ai->rate > esd_rate)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ai->fn = esd_play_stream_fallback(format, ai->rate, ai->device, "mpg123");
|
|
||||||
return (ai->fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
if (0 < ai->channels && ai->channels <= esd_channels
|
|
||||||
&& 0 < ai->rate && ai->rate <= esd_rate)
|
|
||||||
return esd_format;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|
||||||
{
|
|
||||||
return write(ai->fn,buf,len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
close (ai->fn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SOLARIS
|
|
||||||
void audio_queueflush (struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
ioctl (ai->fn, I_FLUSH, FLUSHRW);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#ifdef NETBSD
|
|
||||||
void audio_queueflush (struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
ioctl (ai->fn, AUDIO_FLUSH, 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Dunno what to do on Linux and Cygwin, but the func must be at least defined! */
|
|
||||||
void audio_queueflush (struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
150
src/audio_hp.c
150
src/audio_hp.c
@@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
audio_hp.c: audio output for HP-UX
|
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
||||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
|
||||||
initially written by Michael Hipp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mpg123.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/audio.h>
|
|
||||||
|
|
||||||
static int audio_set_rate(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
if(ai->rate >= 0)
|
|
||||||
return ioctl(ai->fn,AUDIO_SET_SAMPLE_RATE,ai->rate);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_set_channels(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
if(ai->channels<0)
|
|
||||||
return 0;
|
|
||||||
return ioctl(ai->fn,AUDIO_SET_CHANNELS,ai->channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_set_format(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int fmt;
|
|
||||||
|
|
||||||
switch(ai->format) {
|
|
||||||
case -1:
|
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
|
||||||
default:
|
|
||||||
fmt = AUDIO_FORMAT_LINEAR16BIT;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_UNSIGNED_8:
|
|
||||||
fprintf(stderr,"unsigned 8 bit linear not supported\n");
|
|
||||||
return -1;
|
|
||||||
case AUDIO_FORMAT_SIGNED_8:
|
|
||||||
fprintf(stderr,"signed 8 bit linear not supported\n");
|
|
||||||
return -1;
|
|
||||||
case AUDIO_FORMAT_ALAW_8:
|
|
||||||
fmt = AUDIO_FORMAT_ALAW;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_ULAW_8:
|
|
||||||
fmt = AUDIO_FORMAT_ULAW;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ioctl(ai->fn,AUDIO_SET_DATA_FORMAT,fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_reset_parameters(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ret = audio_set_format(ai);
|
|
||||||
if(ret >= 0)
|
|
||||||
ret = audio_set_channels(ai);
|
|
||||||
if(ret >= 0)
|
|
||||||
ret = audio_set_rate(ai);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
struct audio_describe ades;
|
|
||||||
struct audio_gain again;
|
|
||||||
int i,audio;
|
|
||||||
|
|
||||||
ai->fn = open("/dev/audio",O_RDWR);
|
|
||||||
|
|
||||||
if(ai->fn < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
|
||||||
ioctl(ai->fn,AUDIO_DESCRIBE,&ades);
|
|
||||||
|
|
||||||
if(ai->gain != -1)
|
|
||||||
{
|
|
||||||
if(ai->gain > ades.max_transmit_gain)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"your gainvalue was to high -> set to maximum.\n");
|
|
||||||
ai->gain = ades.max_transmit_gain;
|
|
||||||
}
|
|
||||||
if(ai->gain < ades.min_transmit_gain)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"your gainvalue was to low -> set to minimum.\n");
|
|
||||||
ai->gain = ades.min_transmit_gain;
|
|
||||||
}
|
|
||||||
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
|
||||||
ioctl(ai->fn,AUDIO_GET_GAINS,&again);
|
|
||||||
again.cgain[0].transmit_gain = ai->gain;
|
|
||||||
again.cgain[1].transmit_gain = ai->gain;
|
|
||||||
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
|
||||||
ioctl(ai->fn,AUDIO_SET_GAINS,&again);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ai->output != -1)
|
|
||||||
{
|
|
||||||
if(ai->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
|
||||||
ioctl(ai->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_SPEAKER);
|
|
||||||
else if(ai->output & AUDIO_OUT_HEADPHONES)
|
|
||||||
ioctl(ai->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_HEADPHONE);
|
|
||||||
else if(ai->output & AUDIO_OUT_LINE_OUT)
|
|
||||||
ioctl(ai->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ai->rate == -1)
|
|
||||||
ai->rate = 44100;
|
|
||||||
|
|
||||||
for(i=0;i<ades.nrates;i++)
|
|
||||||
{
|
|
||||||
if(ai->rate == ades.sample_rate[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(i == ades.nrates)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Can't set sample-rate to %ld.\n",ai->rate);
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(audio_reset_parameters(ai) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return ai->fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|
||||||
{
|
|
||||||
return write(ai->fn,buf,len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
close (ai->fn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
293
src/audio_oss.c
293
src/audio_oss.c
@@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
audio_oss.c: audio output via Open Sound System
|
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
||||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
|
||||||
initially written by Michael Hipp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "mpg123.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_SOUNDCARD_H
|
|
||||||
#include <linux/soundcard.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SOUNDCARD_H
|
|
||||||
#include <sys/soundcard.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_MACHINE_SOUNDCARD_H
|
|
||||||
#include <machine/soundcard.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AFMT_S16_NE
|
|
||||||
# ifdef OSS_BIG_ENDIAN
|
|
||||||
# define AFMT_S16_NE AFMT_S16_BE
|
|
||||||
# else
|
|
||||||
# define AFMT_S16_NE AFMT_S16_LE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef AFMT_U16_NE
|
|
||||||
# ifdef OSS_BIG_ENDIAN
|
|
||||||
# define AFMT_U16_NE AFMT_U16_BE
|
|
||||||
# else
|
|
||||||
# define AFMT_U16_NE AFMT_U16_LE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int outburst;
|
|
||||||
|
|
||||||
|
|
||||||
static int audio_rate_best_match(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int ret,dsp_rate;
|
|
||||||
|
|
||||||
if(!ai || ai->fn < 0 || ai->rate < 0)
|
|
||||||
return -1;
|
|
||||||
dsp_rate = ai->rate;
|
|
||||||
ret = ioctl(ai->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
|
||||||
if(ret < 0)
|
|
||||||
return ret;
|
|
||||||
ai->rate = dsp_rate;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_set_rate(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int dsp_rate;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if(ai->rate >= 0) {
|
|
||||||
dsp_rate = ai->rate;
|
|
||||||
ret = ioctl(ai->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_set_channels(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int chan = ai->channels - 1;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if(ai->channels < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = ioctl(ai->fn, SNDCTL_DSP_STEREO, &chan);
|
|
||||||
if(chan != (ai->channels-1)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int audio_set_format(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int sample_size,fmts;
|
|
||||||
int sf,ret;
|
|
||||||
|
|
||||||
if(ai->format == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch(ai->format) {
|
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
|
||||||
default:
|
|
||||||
fmts = AFMT_S16_NE;
|
|
||||||
sample_size = 16;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_UNSIGNED_8:
|
|
||||||
fmts = AFMT_U8;
|
|
||||||
sample_size = 8;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_SIGNED_8:
|
|
||||||
fmts = AFMT_S8;
|
|
||||||
sample_size = 8;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_ULAW_8:
|
|
||||||
fmts = AFMT_MU_LAW;
|
|
||||||
sample_size = 8;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_ALAW_8:
|
|
||||||
fmts = AFMT_A_LAW;
|
|
||||||
sample_size = 8;
|
|
||||||
break;
|
|
||||||
case AUDIO_FORMAT_UNSIGNED_16:
|
|
||||||
fmts = AFMT_U16_NE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
if(ioctl(ai->fn, SNDCTL_DSP_SAMPLESIZE,&sample_size) < 0)
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
sf = fmts;
|
|
||||||
ret = ioctl(ai->fn, SNDCTL_DSP_SETFMT, &fmts);
|
|
||||||
if(sf != fmts) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int audio_reset_parameters(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ret = ioctl(ai->fn, SNDCTL_DSP_RESET, NULL);
|
|
||||||
if(ret < 0)
|
|
||||||
error("Can't reset audio!");
|
|
||||||
ret = audio_set_format(ai);
|
|
||||||
if (ret == -1)
|
|
||||||
goto err;
|
|
||||||
ret = audio_set_channels(ai);
|
|
||||||
if (ret == -1)
|
|
||||||
goto err;
|
|
||||||
ret = audio_set_rate(ai);
|
|
||||||
if (ret == -1)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
/* Careful here. As per OSS v1.1, the next ioctl() commits the format
|
|
||||||
* set above, so we must issue SNDCTL_DSP_RESET before we're allowed to
|
|
||||||
* change it again. [dk]
|
|
||||||
*/
|
|
||||||
if (ioctl(ai->fn, SNDCTL_DSP_GETBLKSIZE, &outburst) == -1 ||
|
|
||||||
outburst > MAXOUTBURST)
|
|
||||||
outburst = MAXOUTBURST;
|
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
char usingdefdev = 0;
|
|
||||||
|
|
||||||
if(!ai)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if(!ai->device) {
|
|
||||||
ai->device = "/dev/dsp";
|
|
||||||
usingdefdev = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
|
||||||
|
|
||||||
if(ai->fn < 0)
|
|
||||||
{
|
|
||||||
if(usingdefdev) {
|
|
||||||
ai->device = "/dev/sound/dsp";
|
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
|
||||||
if(ai->fn < 0) {
|
|
||||||
error("Can't open default sound device!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error1("Can't open %s!",ai->device);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(audio_reset_parameters(ai) < 0) {
|
|
||||||
close(ai->fn);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ai->gain >= 0) {
|
|
||||||
int e,mask;
|
|
||||||
e = ioctl(ai->fn , SOUND_MIXER_READ_DEVMASK ,&mask);
|
|
||||||
if(e < 0) {
|
|
||||||
error("audio/gain: Can't get audio device features list.");
|
|
||||||
}
|
|
||||||
else if(mask & SOUND_MASK_PCM) {
|
|
||||||
int gain = (ai->gain<<8)|(ai->gain);
|
|
||||||
e = ioctl(ai->fn, SOUND_MIXER_WRITE_PCM , &gain);
|
|
||||||
}
|
|
||||||
else if(!(mask & SOUND_MASK_VOLUME)) {
|
|
||||||
error1("audio/gain: setable Volume/PCM-Level not supported by your audio device: %#04x",mask);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int gain = (ai->gain<<8)|(ai->gain);
|
|
||||||
e = ioctl(ai->fn, SOUND_MIXER_WRITE_VOLUME , &gain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ai->fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get formats for specific channel/rate parameters
|
|
||||||
*/
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
int fmt = 0;
|
|
||||||
int r = ai->rate;
|
|
||||||
int c = ai->channels;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
static int fmts[] = {
|
|
||||||
AUDIO_FORMAT_ULAW_8 , AUDIO_FORMAT_SIGNED_16 ,
|
|
||||||
AUDIO_FORMAT_UNSIGNED_8 , AUDIO_FORMAT_SIGNED_8 ,
|
|
||||||
AUDIO_FORMAT_UNSIGNED_16 , AUDIO_FORMAT_ALAW_8 };
|
|
||||||
|
|
||||||
/* Reset is required before we're allowed to set the new formats. [dk] */
|
|
||||||
ioctl(ai->fn, SNDCTL_DSP_RESET, NULL);
|
|
||||||
|
|
||||||
for(i=0;i<6;i++) {
|
|
||||||
ai->format = fmts[i];
|
|
||||||
if(audio_set_format(ai) < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ai->channels = c;
|
|
||||||
if(audio_set_channels(ai) < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ai->rate = r;
|
|
||||||
if(audio_rate_best_match(ai) < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( (ai->rate*100 > r*(100-AUDIO_RATE_TOLERANCE)) && (ai->rate*100 < r*(100+AUDIO_RATE_TOLERANCE)) ) {
|
|
||||||
fmt |= fmts[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(ioctl(ai->fn,SNDCTL_DSP_GETFMTS,&fmts) < 0) {
|
|
||||||
fprintf(stderr,"No");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fmts & AFMT_MU_LAW)
|
|
||||||
ret |= AUDIO_FORMAT_ULAW_8;
|
|
||||||
if(fmts & AFMT_S16_NE)
|
|
||||||
ret |= AUDIO_FORMAT_SIGNED_16;
|
|
||||||
if(fmts & AFMT_U8)
|
|
||||||
ret |= AUDIO_FORMAT_UNSIGNED_8;
|
|
||||||
if(fmts & AFMT_S8)
|
|
||||||
ret |= AUDIO_FORMAT_SIGNED_8;
|
|
||||||
if(fmts & AFMT_U16_NE)
|
|
||||||
ret |= AUDIO_FORMAT_UNSIGNED_16;
|
|
||||||
if(fmts & AFMT_A_LAW)
|
|
||||||
ret |= AUDIO_FORMAT_ALAW_8;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return fmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|
||||||
{
|
|
||||||
return write(ai->fn,buf,len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
close (ai->fn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
20
src/buffer.c
20
src/buffer.c
@@ -92,7 +92,7 @@ void buffer_sig(int signal, int block)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
int my_fd = buffermem->fd[XF_READER];
|
int my_fd = buffermem->fd[XF_READER];
|
||||||
@@ -104,7 +104,7 @@ void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
|||||||
catchsignal (SIGUSR1, catch_usr1);
|
catchsignal (SIGUSR1, catch_usr1);
|
||||||
sigprocmask (SIG_SETMASK, oldsigset, NULL);
|
sigprocmask (SIG_SETMASK, oldsigset, NULL);
|
||||||
if (param.outmode == DECODE_AUDIO) {
|
if (param.outmode == DECODE_AUDIO) {
|
||||||
if (audio_open(ai) < 0) {
|
if (ao->open(ao) < 0) {
|
||||||
perror("audio");
|
perror("audio");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
|||||||
if (intflag) {
|
if (intflag) {
|
||||||
intflag = FALSE;
|
intflag = FALSE;
|
||||||
if (param.outmode == DECODE_AUDIO)
|
if (param.outmode == DECODE_AUDIO)
|
||||||
audio_queueflush (ai);
|
ao->flush(ao);
|
||||||
xf->readindex = xf->freeindex;
|
xf->readindex = xf->freeindex;
|
||||||
if (xf->wakeme[XF_WRITER])
|
if (xf->wakeme[XF_WRITER])
|
||||||
xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
||||||
@@ -141,11 +141,11 @@ void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
|||||||
if (xf->wakeme[XF_WRITER])
|
if (xf->wakeme[XF_WRITER])
|
||||||
xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
|
||||||
if (param.outmode == DECODE_AUDIO) {
|
if (param.outmode == DECODE_AUDIO) {
|
||||||
audio_close (ai);
|
ao->close(ao);
|
||||||
ai->rate = xf->buf[0];
|
ao->rate = xf->buf[0];
|
||||||
ai->channels = xf->buf[1];
|
ao->channels = xf->buf[1];
|
||||||
ai->format = xf->buf[2];
|
ao->format = xf->buf[2];
|
||||||
if (audio_open(ai) < 0) {
|
if (ao->open(ao) < 0) {
|
||||||
perror("audio");
|
perror("audio");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
|||||||
if (param.outmode == DECODE_FILE)
|
if (param.outmode == DECODE_FILE)
|
||||||
bytes = write(OutputDescriptor, xf->data + xf->readindex, bytes);
|
bytes = write(OutputDescriptor, xf->data + xf->readindex, bytes);
|
||||||
else if (param.outmode == DECODE_AUDIO)
|
else if (param.outmode == DECODE_AUDIO)
|
||||||
bytes = audio_play_samples(ai,
|
bytes = ao->write(ao,
|
||||||
(unsigned char *) (xf->data + xf->readindex), bytes);
|
(unsigned char *) (xf->data + xf->readindex), bytes);
|
||||||
|
|
||||||
if(bytes < 0) {
|
if(bytes < 0) {
|
||||||
@@ -246,7 +246,7 @@ void buffer_loop(struct audio_info_struct *ai, sigset_t *oldsigset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (param.outmode == DECODE_AUDIO)
|
if (param.outmode == DECODE_AUDIO)
|
||||||
audio_close (ai);
|
ao->close(ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
29
src/common.c
29
src/common.c
@@ -104,24 +104,24 @@ static int decode_header(struct frame *fr,unsigned long newhead);
|
|||||||
|
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
/* take into account: channels, bytes per sample, resampling (integer samples!) */
|
/* take into account: channels, bytes per sample, resampling (integer samples!) */
|
||||||
unsigned long samples_to_bytes(unsigned long s, struct frame *fr , struct audio_info_struct* ai)
|
unsigned long samples_to_bytes(unsigned long s, struct frame *fr , audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/* rounding positive number... */
|
/* rounding positive number... */
|
||||||
double sammy, samf;
|
double sammy, samf;
|
||||||
sammy = (1.0*s) * (1.0*ai->rate)/freqs[fr->sampling_frequency];
|
sammy = (1.0*s) * (1.0*ao->rate)/freqs[fr->sampling_frequency];
|
||||||
debug4("%lu samples to bytes with freq %li (ai.rate %li); sammy %f", s, freqs[fr->sampling_frequency], ai->rate, sammy);
|
debug4("%lu samples to bytes with freq %li (ai.rate %li); sammy %f", s, freqs[fr->sampling_frequency], ao->rate, sammy);
|
||||||
samf = floor(sammy);
|
samf = floor(sammy);
|
||||||
return (unsigned long)
|
return (unsigned long)
|
||||||
(((ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) ? 2 : 1)
|
(((ao->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) ? 2 : 1)
|
||||||
#ifdef FLOATOUT
|
#ifdef FLOATOUT
|
||||||
* 2
|
* 2
|
||||||
#endif
|
#endif
|
||||||
* ai->channels
|
* ao->channels
|
||||||
* (int) (((sammy - samf) < 0.5) ? samf : ( sammy-samf > 0.5 ? samf+1 : ((unsigned long) samf % 2 == 0 ? samf : samf + 1)));
|
* (int) (((sammy - samf) < 0.5) ? samf : ( sammy-samf > 0.5 ? samf+1 : ((unsigned long) samf % 2 == 0 ? samf : samf + 1)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void audio_flush(int outmode, struct audio_info_struct *ai)
|
void audio_flush(int outmode, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/* the gapless code is not in effect for buffered mode... as then condition for audio_flush is never met */
|
/* the gapless code is not in effect for buffered mode... as then condition for audio_flush is never met */
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
@@ -135,7 +135,7 @@ void audio_flush(int outmode, struct audio_info_struct *ai)
|
|||||||
write (OutputDescriptor, pcm_sample, pcm_point);
|
write (OutputDescriptor, pcm_sample, pcm_point);
|
||||||
break;
|
break;
|
||||||
case DECODE_AUDIO:
|
case DECODE_AUDIO:
|
||||||
audio_play_samples (ai, pcm_sample, pcm_point);
|
ao->write(ao, pcm_sample, pcm_point);
|
||||||
break;
|
break;
|
||||||
case DECODE_BUFFER:
|
case DECODE_BUFFER:
|
||||||
error("The buffer doesn't work like that... I shouldn't ever be getting here.");
|
error("The buffer doesn't work like that... I shouldn't ever be getting here.");
|
||||||
@@ -452,7 +452,8 @@ init_resync:
|
|||||||
}
|
}
|
||||||
else if (give_note)
|
else if (give_note)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Note: Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n", newhead,rd->tell(rd)-4);
|
fprintf(stderr,"Note: Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n",
|
||||||
|
newhead, (long unsigned int)rd->tell(rd)-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(give_note && (newhead & 0xffffff00) == ('b'<<24)+('m'<<16)+('p'<<8)) fprintf(stderr,"Note: Could be a BMP album art.\n");
|
if(give_note && (newhead & 0xffffff00) == ('b'<<24)+('m'<<16)+('p'<<8)) fprintf(stderr,"Note: Could be a BMP album art.\n");
|
||||||
@@ -1183,7 +1184,7 @@ long compute_buffer_offset(struct frame *fr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Way too many parameters - heck, this fr and ai is always the same! */
|
/* Way too many parameters - heck, this fr and ai is always the same! */
|
||||||
int position_info(struct frame* fr, unsigned long no, long buffsize, struct audio_info_struct* ai,
|
int position_info(struct frame* fr, unsigned long no, long buffsize, audio_output_t *ao,
|
||||||
unsigned long* frames_left, double* current_seconds, double* seconds_left)
|
unsigned long* frames_left, double* current_seconds, double* seconds_left)
|
||||||
{
|
{
|
||||||
double tpf;
|
double tpf;
|
||||||
@@ -1212,9 +1213,9 @@ int position_info(struct frame* fr, unsigned long no, long buffsize, struct audi
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
tpf = compute_tpf(fr);
|
tpf = compute_tpf(fr);
|
||||||
if(buffsize > 0 && ai && ai->rate > 0 && ai->channels > 0) {
|
if(buffsize > 0 && ao && ao->rate > 0 && ao->channels > 0) {
|
||||||
dt = (double) buffsize / ai->rate / ai->channels;
|
dt = (double) buffsize / ao->rate / ao->channels;
|
||||||
if( (ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
|
if( (ao->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
|
||||||
dt *= 0.5;
|
dt *= 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1267,11 +1268,11 @@ unsigned int roundui(double val)
|
|||||||
return (unsigned int) ((val-base) < 0.5 ? base : base + 1 );
|
return (unsigned int) ((val-base) < 0.5 ? base : base + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_stat(struct frame *fr,unsigned long no,long buffsize,struct audio_info_struct *ai)
|
void print_stat(struct frame *fr, unsigned long no, long buffsize, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
double tim1,tim2;
|
double tim1,tim2;
|
||||||
unsigned long rno;
|
unsigned long rno;
|
||||||
if(!position_info(fr, no, buffsize, ai, &rno, &tim1, &tim2))
|
if(!position_info(fr, no, buffsize, ao, &rno, &tim1, &tim2))
|
||||||
{
|
{
|
||||||
/* All these sprintf... only to avoid two writes to stderr in case of using buffer?
|
/* All these sprintf... only to avoid two writes to stderr in case of using buffer?
|
||||||
I guess we can drop that. */
|
I guess we can drop that. */
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ extern struct bitstream_info bsi;
|
|||||||
#define DECODER_DELAY 529
|
#define DECODER_DELAY 529
|
||||||
|
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
unsigned long samples_to_bytes(unsigned long s, struct frame *fr , struct audio_info_struct* ai);
|
unsigned long samples_to_bytes(unsigned long s, struct frame *fr, audio_output_t* ao);
|
||||||
/* samples per frame ...
|
/* samples per frame ...
|
||||||
Layer I
|
Layer I
|
||||||
Layer II
|
Layer II
|
||||||
@@ -89,7 +89,7 @@ extern const char* remote_header_help;
|
|||||||
void print_remote_header(struct frame* fr);
|
void print_remote_header(struct frame* fr);
|
||||||
void generic_sendmsg (const char *fmt, ...);
|
void generic_sendmsg (const char *fmt, ...);
|
||||||
|
|
||||||
int position_info(struct frame* fr, unsigned long no, long buffsize, struct audio_info_struct* ai,
|
int position_info(struct frame* fr, unsigned long no, long buffsize, audio_output_t *ao,
|
||||||
unsigned long* frames_left, double* current_seconds, double* seconds_left);
|
unsigned long* frames_left, double* current_seconds, double* seconds_left);
|
||||||
|
|
||||||
int read_frame_recover(struct frame* fr);
|
int read_frame_recover(struct frame* fr);
|
||||||
@@ -99,7 +99,7 @@ void print_frame_index(FILE* out);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void print_stat(struct frame *fr,unsigned long no,long buffsize,struct audio_info_struct *ai);
|
void print_stat(struct frame *fr,unsigned long no,long buffsize,audio_output_t *ao);
|
||||||
void clear_stat();
|
void clear_stat();
|
||||||
|
|
||||||
/* rva data, used in common.c, set in id3.c */
|
/* rva data, used in common.c, set in id3.c */
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
#include "icy.h"
|
#include "icy.h"
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
#include "layer3.h"
|
#include "layer3.h"
|
||||||
extern struct audio_info_struct pre_ai;
|
extern audio_output_t pre_ao;
|
||||||
#endif
|
#endif
|
||||||
#define MODE_STOPPED 0
|
#define MODE_STOPPED 0
|
||||||
#define MODE_PLAYING 1
|
#define MODE_PLAYING 1
|
||||||
#define MODE_PAUSED 2
|
#define MODE_PAUSED 2
|
||||||
|
|
||||||
extern struct audio_info_struct ai;
|
extern audio_output_t ao;
|
||||||
extern int buffer_pid;
|
extern int buffer_pid;
|
||||||
#ifdef FIFO
|
#ifdef FIFO
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -55,7 +55,7 @@ void generic_sendstat (struct frame *fr)
|
|||||||
{
|
{
|
||||||
unsigned long frames_left;
|
unsigned long frames_left;
|
||||||
double current_seconds, seconds_left;
|
double current_seconds, seconds_left;
|
||||||
if(!position_info(fr, fr->num, xfermem_get_usedspace(buffermem), &ai, &frames_left, ¤t_seconds, &seconds_left))
|
if(!position_info(fr, fr->num, xfermem_get_usedspace(buffermem), &ao, &frames_left, ¤t_seconds, &seconds_left))
|
||||||
generic_sendmsg("F %li %lu %3.2f %3.2f", fr->num, frames_left, current_seconds, seconds_left);
|
generic_sendmsg("F %li %lu %3.2f %3.2f", fr->num, frames_left, current_seconds, seconds_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ int control_generic (struct frame *fr)
|
|||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
if (!read_frame(fr)) {
|
if (!read_frame(fr)) {
|
||||||
mode = MODE_STOPPED;
|
mode = MODE_STOPPED;
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
rd->close(rd);
|
rd->close(rd);
|
||||||
generic_sendmsg("P 0");
|
generic_sendmsg("P 0");
|
||||||
continue;
|
continue;
|
||||||
@@ -156,7 +156,7 @@ int control_generic (struct frame *fr)
|
|||||||
if(!play_frame(init,fr))
|
if(!play_frame(init,fr))
|
||||||
{
|
{
|
||||||
generic_sendmsg("E play_frame failed");
|
generic_sendmsg("E play_frame failed");
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
rd->close(rd);
|
rd->close(rd);
|
||||||
mode = MODE_STOPPED;
|
mode = MODE_STOPPED;
|
||||||
generic_sendmsg("P 0");
|
generic_sendmsg("P 0");
|
||||||
@@ -247,7 +247,7 @@ int control_generic (struct frame *fr)
|
|||||||
{
|
{
|
||||||
if (mode == MODE_PLAYING) {
|
if (mode == MODE_PLAYING) {
|
||||||
mode = MODE_PAUSED;
|
mode = MODE_PAUSED;
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
buffer_stop();
|
buffer_stop();
|
||||||
generic_sendmsg("P 1");
|
generic_sendmsg("P 1");
|
||||||
} else {
|
} else {
|
||||||
@@ -262,7 +262,7 @@ int control_generic (struct frame *fr)
|
|||||||
/* STOP */
|
/* STOP */
|
||||||
if (!strcasecmp(comstr, "S") || !strcasecmp(comstr, "STOP")) {
|
if (!strcasecmp(comstr, "S") || !strcasecmp(comstr, "STOP")) {
|
||||||
if (mode != MODE_STOPPED) {
|
if (mode != MODE_STOPPED) {
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
rd->close(rd);
|
rd->close(rd);
|
||||||
mode = MODE_STOPPED;
|
mode = MODE_STOPPED;
|
||||||
generic_sendmsg("P 0");
|
generic_sendmsg("P 0");
|
||||||
@@ -360,7 +360,7 @@ int control_generic (struct frame *fr)
|
|||||||
char *spos;
|
char *spos;
|
||||||
long offset;
|
long offset;
|
||||||
double secs;
|
double secs;
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
|
|
||||||
spos = arg;
|
spos = arg;
|
||||||
if (!spos)
|
if (!spos)
|
||||||
@@ -404,9 +404,9 @@ int control_generic (struct frame *fr)
|
|||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
if(param.gapless && (fr->lay == 3))
|
if(param.gapless && (fr->lay == 3))
|
||||||
{
|
{
|
||||||
prepare_audioinfo(fr, &pre_ai);
|
prepare_audioinfo(fr, &pre_ao);
|
||||||
layer3_gapless_set_position(fr->num, fr, &pre_ai);
|
layer3_gapless_set_position(fr->num, fr, &pre_ao);
|
||||||
layer3_gapless_set_ignore(frame_before, fr, &pre_ai);
|
layer3_gapless_set_ignore(frame_before, fr, &pre_ao);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -521,13 +521,13 @@ int control_generic (struct frame *fr)
|
|||||||
xfermem_done(buffermem);
|
xfermem_done(buffermem);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, &ao);
|
||||||
free(pcm_sample);
|
free(pcm_sample);
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (param.outmode == DECODE_AUDIO)
|
if (param.outmode == DECODE_AUDIO)
|
||||||
audio_close(&ai);
|
ao.close(&ao);
|
||||||
if (param.outmode == DECODE_WAV)
|
if (param.outmode == DECODE_WAV)
|
||||||
wav_close();
|
wav_close();
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ void I_step_two(real fraction[2][SBLIMIT],unsigned int balloc[2*SBLIMIT],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_layer1(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
int do_layer1(struct frame *fr,int outmode,audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int clip=0;
|
int clip=0;
|
||||||
int i,stereo = fr->stereo;
|
int i,stereo = fr->stereo;
|
||||||
@@ -146,7 +146,7 @@ int do_layer1(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(pcm_point >= audiobufsize)
|
if(pcm_point >= audiobufsize)
|
||||||
audio_flush(outmode,ai);
|
audio_flush(outmode,ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clip;
|
return clip;
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ static void II_select_table(struct frame *fr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int do_layer2(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
int do_layer2(struct frame *fr,int outmode,audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int clip=0;
|
int clip=0;
|
||||||
int i,j;
|
int i,j;
|
||||||
@@ -315,7 +315,7 @@ int do_layer2(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(pcm_point >= audiobufsize)
|
if(pcm_point >= audiobufsize)
|
||||||
audio_flush(outmode,ai);
|
audio_flush(outmode,ao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
src/layer3.c
20
src/layer3.c
@@ -123,27 +123,27 @@ void layer3_gapless_init(unsigned long b, unsigned long e)
|
|||||||
debug2("layer3_gapless_init: from %lu to %lu samples", begin, end);
|
debug2("layer3_gapless_init: from %lu to %lu samples", begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer3_gapless_set_position(unsigned long frames, struct frame* fr, struct audio_info_struct *ai)
|
void layer3_gapless_set_position(unsigned long frames, struct frame* fr, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
position = samples_to_bytes(frames*spf(fr), fr, ai);
|
position = samples_to_bytes(frames*spf(fr), fr, ao);
|
||||||
debug1("set; position now %lu", position);
|
debug1("set; position now %lu", position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void layer3_gapless_bytify(struct frame *fr, struct audio_info_struct *ai)
|
void layer3_gapless_bytify(struct frame *fr, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
if(!bytified)
|
if(!bytified)
|
||||||
{
|
{
|
||||||
begin = samples_to_bytes(begin, fr, ai);
|
begin = samples_to_bytes(begin, fr, ao);
|
||||||
end = samples_to_bytes(end, fr, ai);
|
end = samples_to_bytes(end, fr, ao);
|
||||||
bytified = 1;
|
bytified = 1;
|
||||||
debug2("bytified: begin=%lu; end=%5lu", begin, end);
|
debug2("bytified: begin=%lu; end=%5lu", begin, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I need initialized fr here! */
|
/* I need initialized fr here! */
|
||||||
void layer3_gapless_set_ignore(unsigned long frames, struct frame *fr, struct audio_info_struct *ai)
|
void layer3_gapless_set_ignore(unsigned long frames, struct frame *fr, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
ignore = samples_to_bytes(frames*spf(fr), fr, ai);
|
ignore = samples_to_bytes(frames*spf(fr), fr, ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1773,7 +1773,7 @@ static void III_hybrid(real fsIn[SBLIMIT][SSLIMIT], real tsOut[SSLIMIT][SBLIMIT]
|
|||||||
/*
|
/*
|
||||||
* main layer3 handler
|
* main layer3 handler
|
||||||
*/
|
*/
|
||||||
int do_layer3(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
int do_layer3(struct frame *fr,int outmode,audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int gr, ch, ss,clip=0;
|
int gr, ch, ss,clip=0;
|
||||||
int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */
|
int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */
|
||||||
@@ -1916,7 +1916,7 @@ int do_layer3(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
|||||||
else
|
else
|
||||||
playlimit -= 128;
|
playlimit -= 128;
|
||||||
#endif
|
#endif
|
||||||
if(pcm_point >= audiobufsize) audio_flush(outmode,ai);
|
if(pcm_point >= audiobufsize) audio_flush(outmode,ao);
|
||||||
}
|
}
|
||||||
#ifdef OPT_I486
|
#ifdef OPT_I486
|
||||||
} else {
|
} else {
|
||||||
@@ -1932,7 +1932,7 @@ int do_layer3(struct frame *fr,int outmode,struct audio_info_struct *ai)
|
|||||||
ss+=n;
|
ss+=n;
|
||||||
pcm_point+=(2*2*32)*n;
|
pcm_point+=(2*2*32)*n;
|
||||||
|
|
||||||
if(pcm_point >= audiobufsize) audio_flush(outmode,ai);
|
if(pcm_point >= audiobufsize) audio_flush(outmode,ao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
/* init part 1; set start/end in samples_*/
|
/* init part 1; set start/end in samples_*/
|
||||||
void layer3_gapless_init(unsigned long b, unsigned long e);
|
void layer3_gapless_init(unsigned long b, unsigned long e);
|
||||||
/* init part 2; transform to byte addresses with new info */
|
/* init part 2; transform to byte addresses with new info */
|
||||||
void layer3_gapless_bytify(struct frame *fr, struct audio_info_struct *ai);
|
void layer3_gapless_bytify(struct frame *fr, audio_output_t *ao);
|
||||||
/* after some seeking action to a new frame, the decoder needs to know which one is coming next */
|
/* after some seeking action to a new frame, the decoder needs to know which one is coming next */
|
||||||
void layer3_gapless_set_position(unsigned long frames, struct frame* fr, struct audio_info_struct *ai);
|
void layer3_gapless_set_position(unsigned long frames, struct frame* fr, audio_output_t *ao);
|
||||||
void layer3_gapless_set_ignore(unsigned long frames, struct frame* fr, struct audio_info_struct *ai);
|
void layer3_gapless_set_ignore(unsigned long frames, struct frame* fr, audio_output_t *ao);
|
||||||
/* removing the gaps from buffer */
|
/* removing the gaps from buffer */
|
||||||
void layer3_gapless_buffercheck();
|
void layer3_gapless_buffercheck();
|
||||||
|
|||||||
74
src/legacy_module.c
Normal file
74
src/legacy_module.c
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
legacy_module.c: dummy interface to modular code loader for legacy build system
|
||||||
|
|
||||||
|
copyright 2007 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://www.mpg123.org
|
||||||
|
initially written by Nicholas J Humfrey
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* A single module is staticly compiled in for each type */
|
||||||
|
extern mpg123_module_t mpg123_output_module_info;
|
||||||
|
/* extern mpg123_module_t mpg123_input_module_info; */
|
||||||
|
|
||||||
|
|
||||||
|
/* Open a module */
|
||||||
|
mpg123_module_t*
|
||||||
|
open_module( const char* type, const char* name )
|
||||||
|
{
|
||||||
|
mpg123_module_t *mod = NULL;
|
||||||
|
|
||||||
|
/* Select the module info structure, based on the desired type */
|
||||||
|
if (strcmp(type, "output")==0) {
|
||||||
|
mod = &mpg123_output_module_info;
|
||||||
|
/*
|
||||||
|
} else if (strcmp(type, "input")==0) {
|
||||||
|
mod = &mpg123_input_module_info;
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
error1("Unable to open module type '%s'.", type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the module compiled in is the module requested */
|
||||||
|
if (strcmp(name, mod->name)!=0) {
|
||||||
|
error1("Unable to open requesed module '%s'.", name);
|
||||||
|
error1("The only available staticly compiled module is '%s'.", mod->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugging info
|
||||||
|
debug1("Details of static module type '%s':", type);
|
||||||
|
debug1(" api_version=%d", mod->api_version);
|
||||||
|
debug1(" name=%s", mod->name);
|
||||||
|
debug1(" description=%s", mod->description);
|
||||||
|
debug1(" revision=%s", mod->revision);
|
||||||
|
debug1(" handle=%x", (unsigned int)mod->handle);
|
||||||
|
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void close_module( mpg123_module_t* module )
|
||||||
|
{
|
||||||
|
debug("close_module()");
|
||||||
|
|
||||||
|
/* Module was never really 'loaded', so nothing to do here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void list_modules()
|
||||||
|
{
|
||||||
|
debug("list_modules()" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
170
src/module.c
Normal file
170
src/module.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
module.c: modular code loader
|
||||||
|
|
||||||
|
copyright 1995-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.de
|
||||||
|
initially written by Nicholas J Humfrey
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_LTDL
|
||||||
|
#error Cannot build without LTDL library support
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MODULE_FILE_SUFFIX ".la"
|
||||||
|
#define MODULE_SYMBOL_PREFIX "mpg123_"
|
||||||
|
#define MODULE_SYMBOL_SUFFIX "_module_info"
|
||||||
|
|
||||||
|
|
||||||
|
/* Open a module */
|
||||||
|
mpg123_module_t*
|
||||||
|
open_module( const char* type, const char* name )
|
||||||
|
{
|
||||||
|
lt_dlhandle handle = NULL;
|
||||||
|
mpg123_module_t *module = NULL;
|
||||||
|
char* module_name = strdup( name );
|
||||||
|
char* module_path = NULL;
|
||||||
|
int module_path_len = 0;
|
||||||
|
char* module_symbol = NULL;
|
||||||
|
int module_symbol_len = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Initialize libltdl */
|
||||||
|
if (lt_dlinit()) error( "Failed to initialise libltdl" );
|
||||||
|
|
||||||
|
/* Clean up the module name to prevent loading random files */
|
||||||
|
for(i=0; i<strlen(module_name); i++) {
|
||||||
|
if (!isalnum(module_name[i])) module_name[i] = '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work out the path of the module to open */
|
||||||
|
module_path_len = strlen( PKGLIBDIR ) + 1 +
|
||||||
|
strlen( type ) + 1 + strlen( module_name ) +
|
||||||
|
strlen( MODULE_FILE_SUFFIX ) + 1;
|
||||||
|
module_path = malloc( module_path_len );
|
||||||
|
if (module_path == NULL) {
|
||||||
|
error1( "Failed to allocate memory for module name: %s", strerror(errno) );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
snprintf( module_path, module_path_len, "%s/%s_%s%s", PKGLIBDIR, type, module_name, MODULE_FILE_SUFFIX );
|
||||||
|
|
||||||
|
|
||||||
|
/* Display the path of the module created */
|
||||||
|
debug1( "Module path: %s", module_path );
|
||||||
|
|
||||||
|
|
||||||
|
/* Open the module */
|
||||||
|
handle = lt_dlopen( module_path );
|
||||||
|
free( module_path );
|
||||||
|
free( module_name );
|
||||||
|
if (handle==NULL) {
|
||||||
|
error1( "Failed to open module: %s", lt_dlerror() );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work out the symbol name */
|
||||||
|
module_symbol_len = strlen( MODULE_SYMBOL_PREFIX ) +
|
||||||
|
strlen( type ) +
|
||||||
|
strlen( MODULE_SYMBOL_SUFFIX ) + 1;
|
||||||
|
module_symbol = malloc( module_path_len );
|
||||||
|
snprintf( module_symbol, module_symbol_len, "%s%s%s", MODULE_SYMBOL_PREFIX, type, MODULE_SYMBOL_SUFFIX );
|
||||||
|
debug1( "Module symbol: %s", module_symbol );
|
||||||
|
|
||||||
|
/* Get the information structure from the module */
|
||||||
|
module = (mpg123_module_t*)lt_dlsym(handle, module_symbol );
|
||||||
|
if (module==NULL) {
|
||||||
|
error1( "Failed to get module symbol: %s", lt_dlerror() );
|
||||||
|
lt_dlclose( handle );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
free( module_symbol );
|
||||||
|
|
||||||
|
/* Store handle in the data structure */
|
||||||
|
module->handle = handle;
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void close_module( mpg123_module_t* module )
|
||||||
|
{
|
||||||
|
lt_dlhandle handle = module->handle;
|
||||||
|
int err = lt_dlclose( handle );
|
||||||
|
|
||||||
|
if (err) error1("Failed to close module: %s", lt_dlerror() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void list_modules()
|
||||||
|
{
|
||||||
|
DIR* dir = NULL;
|
||||||
|
struct dirent *dp = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Open the module directory */
|
||||||
|
dir = opendir( PKGLIBDIR );
|
||||||
|
if (dir==NULL) {
|
||||||
|
error2("Failed to open the module directory (%s): %s\n", PKGLIBDIR, strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display the program title */
|
||||||
|
/* print_title(stderr); */
|
||||||
|
|
||||||
|
/* List the output modules */
|
||||||
|
printf("\n");
|
||||||
|
printf("Available modules\n");
|
||||||
|
printf("-----------------\n");
|
||||||
|
|
||||||
|
while( (dp = readdir(dir)) != NULL ) {
|
||||||
|
if (dp->d_type == DT_REG) {
|
||||||
|
char* ext = dp->d_name + strlen( dp->d_name ) - strlen( MODULE_FILE_SUFFIX );
|
||||||
|
if (strcmp(ext, MODULE_FILE_SUFFIX) == 0)
|
||||||
|
{
|
||||||
|
char *module_name = NULL;
|
||||||
|
char *module_type = NULL;
|
||||||
|
char *uscore_pos = NULL;
|
||||||
|
mpg123_module_t *module = NULL;
|
||||||
|
|
||||||
|
/* Extract the module type */
|
||||||
|
module_type = strdup( dp->d_name );
|
||||||
|
uscore_pos = strchr( module_type, '_' );
|
||||||
|
if (uscore_pos==NULL) continue;
|
||||||
|
if (uscore_pos>=module_type+strlen(module_type)+1) continue;
|
||||||
|
*uscore_pos = '\0';
|
||||||
|
|
||||||
|
/* Extract the short name of the module */
|
||||||
|
module_name = strdup( dp->d_name + strlen( module_type ) + 1 );
|
||||||
|
module_name[ strlen( module_name ) - strlen( MODULE_FILE_SUFFIX ) ] = '\0';
|
||||||
|
|
||||||
|
/* Open the module */
|
||||||
|
module = open_module( module_type, module_name );
|
||||||
|
if (module) {
|
||||||
|
printf("%-15s%s %s\n", module->name, module_type, module->description );
|
||||||
|
|
||||||
|
/* Close the module again */
|
||||||
|
close_module( module );
|
||||||
|
}
|
||||||
|
|
||||||
|
free( module_name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir( dir );
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
48
src/module.h
Normal file
48
src/module.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
module: module loading and listing interface
|
||||||
|
|
||||||
|
copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.de
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifndef _MPG123_MODULE_H_
|
||||||
|
#define _MPG123_MODULE_H_
|
||||||
|
|
||||||
|
#ifdef HAVE_LTDL
|
||||||
|
#include <ltdl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MPG123_MODULE_API_VERSION (1)
|
||||||
|
|
||||||
|
/* The full structure is delared in audio.h */
|
||||||
|
struct audio_output_struct;
|
||||||
|
|
||||||
|
typedef struct mpg123_module_struct {
|
||||||
|
const int api_version; /* module API version number */
|
||||||
|
|
||||||
|
const char* name; /* short name of the module */
|
||||||
|
const char* description; /* description of what the module does */
|
||||||
|
const char* revision; /* source code revision */
|
||||||
|
|
||||||
|
#ifdef HAVE_LTDL
|
||||||
|
lt_dlhandle handle; /* ltdl handle - set by open_module */
|
||||||
|
#else
|
||||||
|
void* handle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialisers - set to NULL if unsupported by module */
|
||||||
|
int (*init_output)(struct audio_output_struct* ao); /* audio output - returns 0 on success */
|
||||||
|
|
||||||
|
} mpg123_module_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------ Declarations from "module.c" ------ */
|
||||||
|
|
||||||
|
mpg123_module_t* open_module( const char* type, const char* name );
|
||||||
|
void close_module( mpg123_module_t* module );
|
||||||
|
void list_modules();
|
||||||
|
|
||||||
|
#endif
|
||||||
312
src/mpg123.c
312
src/mpg123.c
@@ -68,6 +68,8 @@ struct parameter param = {
|
|||||||
0 , /* second level buffer size */
|
0 , /* second level buffer size */
|
||||||
TRUE , /* resync after stream error */
|
TRUE , /* resync after stream error */
|
||||||
0 , /* verbose level */
|
0 , /* verbose level */
|
||||||
|
DEFAULT_OUTPUT_MODULE, /* output module */
|
||||||
|
NULL, /* output device */
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
FALSE , /* term control */
|
FALSE , /* term control */
|
||||||
#endif
|
#endif
|
||||||
@@ -124,7 +126,6 @@ int buffer_fd[2];
|
|||||||
int buffer_pid;
|
int buffer_pid;
|
||||||
|
|
||||||
static int intflag = FALSE;
|
static int intflag = FALSE;
|
||||||
|
|
||||||
int OutputDescriptor;
|
int OutputDescriptor;
|
||||||
|
|
||||||
/* A safe realloc also for very old systems where realloc(NULL, size) returns NULL. */
|
/* A safe realloc also for very old systems where realloc(NULL, size) returns NULL. */
|
||||||
@@ -145,16 +146,9 @@ const char *strerror(int errnum)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(WIN32) && !defined(GENERIC)
|
#if !defined(WIN32) && !defined(GENERIC)
|
||||||
#ifndef NOXFERMEM
|
|
||||||
static void catch_child(void)
|
|
||||||
{
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void catch_interrupt(void)
|
static void catch_interrupt(void)
|
||||||
{
|
{
|
||||||
intflag = TRUE;
|
intflag = TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -173,116 +167,37 @@ void safe_exit(int code)
|
|||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
audio_output_t *ao = NULL;
|
||||||
|
audio_output_t pre_ao;
|
||||||
static struct frame fr;
|
static struct frame fr;
|
||||||
struct audio_info_struct ai,pre_ai;
|
|
||||||
txfermem *buffermem = NULL;
|
txfermem *buffermem = NULL;
|
||||||
#define FRAMEBUFUNIT (18 * 64 * 4)
|
|
||||||
|
|
||||||
void set_synth_functions(struct frame *fr);
|
void set_synth_functions(struct frame *fr);
|
||||||
|
|
||||||
void init_output(void)
|
|
||||||
{
|
|
||||||
static int init_done = FALSE;
|
|
||||||
|
|
||||||
if (init_done)
|
|
||||||
return;
|
|
||||||
init_done = TRUE;
|
|
||||||
#ifndef NOXFERMEM
|
|
||||||
/*
|
|
||||||
* Only DECODE_AUDIO and DECODE_FILE are sanely handled by the
|
|
||||||
* buffer process. For now, we just ignore the request
|
|
||||||
* to buffer the output. [dk]
|
|
||||||
*/
|
|
||||||
if (param.usebuffer && (param.outmode != DECODE_AUDIO) &&
|
|
||||||
(param.outmode != DECODE_FILE)) {
|
|
||||||
fprintf(stderr, "Sorry, won't buffer output unless writing plain audio.\n");
|
|
||||||
param.usebuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param.usebuffer) {
|
|
||||||
unsigned int bufferbytes;
|
|
||||||
sigset_t newsigset, oldsigset;
|
|
||||||
if (param.usebuffer < 32)
|
|
||||||
param.usebuffer = 32; /* minimum is 32 Kbytes! */
|
|
||||||
bufferbytes = (param.usebuffer * 1024);
|
|
||||||
bufferbytes -= bufferbytes % FRAMEBUFUNIT;
|
|
||||||
/* +1024 for NtoM rounding problems */
|
|
||||||
xfermem_init (&buffermem, bufferbytes ,0,1024);
|
|
||||||
pcm_sample = (unsigned char *) buffermem->data;
|
|
||||||
pcm_point = 0;
|
|
||||||
sigemptyset (&newsigset);
|
|
||||||
sigaddset (&newsigset, SIGUSR1);
|
|
||||||
sigprocmask (SIG_BLOCK, &newsigset, &oldsigset);
|
|
||||||
#if !defined(WIN32) && !defined(GENERIC)
|
|
||||||
catchsignal (SIGCHLD, catch_child);
|
|
||||||
#endif
|
|
||||||
switch ((buffer_pid = fork())) {
|
|
||||||
case -1: /* error */
|
|
||||||
perror("fork()");
|
|
||||||
safe_exit(1);
|
|
||||||
case 0: /* child */
|
|
||||||
if(rd)
|
|
||||||
rd->close(rd); /* child doesn't need the input stream */
|
|
||||||
xfermem_init_reader (buffermem);
|
|
||||||
buffer_loop (&ai, &oldsigset);
|
|
||||||
xfermem_done_reader (buffermem);
|
|
||||||
xfermem_done (buffermem);
|
|
||||||
exit(0);
|
|
||||||
default: /* parent */
|
|
||||||
xfermem_init_writer (buffermem);
|
|
||||||
param.outmode = DECODE_BUFFER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#endif
|
|
||||||
/* + 1024 for NtoM rate converter */
|
|
||||||
if (!(pcm_sample = (unsigned char *) malloc(audiobufsize * 2 + 1024))) {
|
|
||||||
perror ("malloc()");
|
|
||||||
safe_exit (1);
|
|
||||||
#ifndef NOXFERMEM
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(param.outmode) {
|
|
||||||
case DECODE_AUDIO:
|
|
||||||
if(audio_open(&ai) < 0) {
|
|
||||||
perror("audio");
|
|
||||||
safe_exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DECODE_WAV:
|
|
||||||
wav_open(&ai,param.filename);
|
|
||||||
break;
|
|
||||||
case DECODE_AU:
|
|
||||||
au_open(&ai,param.filename);
|
|
||||||
break;
|
|
||||||
case DECODE_CDR:
|
|
||||||
cdr_open(&ai,param.filename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_output_h(char *a)
|
static void set_output_h(char *a)
|
||||||
{
|
{
|
||||||
if(ai.output <= 0)
|
if(ao->output <= 0)
|
||||||
ai.output = AUDIO_OUT_HEADPHONES;
|
ao->output = AUDIO_OUT_HEADPHONES;
|
||||||
else
|
else
|
||||||
ai.output |= AUDIO_OUT_HEADPHONES;
|
ao->output |= AUDIO_OUT_HEADPHONES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_output_s(char *a)
|
static void set_output_s(char *a)
|
||||||
{
|
{
|
||||||
if(ai.output <= 0)
|
if(ao->output <= 0)
|
||||||
ai.output = AUDIO_OUT_INTERNAL_SPEAKER;
|
ao->output = AUDIO_OUT_INTERNAL_SPEAKER;
|
||||||
else
|
else
|
||||||
ai.output |= AUDIO_OUT_INTERNAL_SPEAKER;
|
ao->output |= AUDIO_OUT_INTERNAL_SPEAKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_output_l(char *a)
|
static void set_output_l(char *a)
|
||||||
{
|
{
|
||||||
if(ai.output <= 0)
|
if(ao->output <= 0)
|
||||||
ai.output = AUDIO_OUT_LINE_OUT;
|
ao->output = AUDIO_OUT_LINE_OUT;
|
||||||
else
|
else
|
||||||
ai.output |= AUDIO_OUT_LINE_OUT;
|
ao->output |= AUDIO_OUT_LINE_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_output (char *arg)
|
static void set_output (char *arg)
|
||||||
@@ -302,39 +217,44 @@ void set_verbose (char *arg)
|
|||||||
{
|
{
|
||||||
param.verbose++;
|
param.verbose++;
|
||||||
}
|
}
|
||||||
void set_wav(char *arg)
|
|
||||||
|
static void set_out_wav(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode = DECODE_WAV;
|
param.outmode = DECODE_WAV;
|
||||||
strncpy(param.filename,arg,255);
|
strncpy(param.filename,arg,255);
|
||||||
param.filename[255] = 0;
|
param.filename[255] = 0;
|
||||||
}
|
}
|
||||||
void set_cdr(char *arg)
|
|
||||||
|
static void set_out_cdr(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode = DECODE_CDR;
|
param.outmode = DECODE_CDR;
|
||||||
strncpy(param.filename,arg,255);
|
strncpy(param.filename,arg,255);
|
||||||
param.filename[255] = 0;
|
param.filename[255] = 0;
|
||||||
}
|
}
|
||||||
void set_au(char *arg)
|
|
||||||
|
static void set_out_au(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode = DECODE_AU;
|
param.outmode = DECODE_AU;
|
||||||
strncpy(param.filename,arg,255);
|
strncpy(param.filename,arg,255);
|
||||||
param.filename[255] = 0;
|
param.filename[255] = 0;
|
||||||
}
|
}
|
||||||
static void SetOutFile(char *Arg)
|
|
||||||
|
static void set_out_file(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode=DECODE_FILE;
|
param.outmode=DECODE_FILE;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
OutputDescriptor=_open(Arg,_O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC,0666);
|
OutputDescriptor=_open(arg,_O_CREAT|_O_WRONLY|_O_BINARY|_O_TRUNC,0666);
|
||||||
#else
|
#else
|
||||||
OutputDescriptor=open(Arg,O_CREAT|O_WRONLY|O_TRUNC,0666);
|
OutputDescriptor=open(arg,O_CREAT|O_WRONLY|O_TRUNC,0666);
|
||||||
#endif
|
#endif
|
||||||
if(OutputDescriptor==-1)
|
if(OutputDescriptor==-1)
|
||||||
{
|
{
|
||||||
error2("Can't open %s for writing (%s).\n",Arg,strerror(errno));
|
error2("Can't open %s for writing (%s).\n",arg,strerror(errno));
|
||||||
safe_exit(1);
|
safe_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void SetOutStdout(char *Arg)
|
|
||||||
|
static void set_out_stdout(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode=DECODE_FILE;
|
param.outmode=DECODE_FILE;
|
||||||
param.remote_err=TRUE;
|
param.remote_err=TRUE;
|
||||||
@@ -343,11 +263,12 @@ static void SetOutStdout(char *Arg)
|
|||||||
_setmode(STDOUT_FILENO, _O_BINARY);
|
_setmode(STDOUT_FILENO, _O_BINARY);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static void SetOutStdout1(char *Arg)
|
|
||||||
|
static void set_out_stdout1(char *arg)
|
||||||
{
|
{
|
||||||
param.outmode=DECODE_AUDIOFILE;
|
param.outmode=DECODE_AUDIOFILE;
|
||||||
param.remote_err=TRUE;
|
param.remote_err=TRUE;
|
||||||
OutputDescriptor=STDOUT_FILENO;
|
OutputDescriptor=STDOUT_FILENO;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
_setmode(STDOUT_FILENO, _O_BINARY);
|
_setmode(STDOUT_FILENO, _O_BINARY);
|
||||||
#endif
|
#endif
|
||||||
@@ -355,40 +276,43 @@ static void SetOutStdout1(char *Arg)
|
|||||||
|
|
||||||
void realtime_not_compiled(char *arg)
|
void realtime_not_compiled(char *arg)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Option '-T / --realtime' not compiled into this binary.\n");
|
fprintf(stderr,"Option '-T / --realtime' not compiled into this binary.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Please note: GLO_NUM expects point to LONG! */
|
/* Please note: GLO_NUM expects point to LONG! */
|
||||||
/* ThOr:
|
/* ThOr:
|
||||||
* Yeah, and despite that numerous addresses to int variables were
|
* Yeah, and despite that numerous addresses to int variables were passed.
|
||||||
passed.
|
|
||||||
* That's not good on my Alpha machine with int=32bit and long=64bit!
|
* That's not good on my Alpha machine with int=32bit and long=64bit!
|
||||||
* Introduced GLO_INT and GLO_LONG as different bits to make that clear.
|
* Introduced GLO_INT and GLO_LONG as different bits to make that clear.
|
||||||
* GLO_NUM no longer exists.
|
* GLO_NUM no longer exists.
|
||||||
*/
|
*/
|
||||||
topt opts[] = {
|
topt opts[] = {
|
||||||
{'k', "skip", GLO_ARG | GLO_LONG, 0, &startFrame, 0},
|
{'k', "skip", GLO_ARG | GLO_LONG, 0, &startFrame, 0},
|
||||||
{'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &ai.device, 0},
|
{'o', "output", GLO_ARG | GLO_CHAR, set_output, NULL, 0},
|
||||||
|
{0, "list-modules",0, list_modules, NULL, 0},
|
||||||
|
{'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, ¶m.output_device, 0},
|
||||||
{'2', "2to1", GLO_INT, 0, ¶m.down_sample, 1},
|
{'2', "2to1", GLO_INT, 0, ¶m.down_sample, 1},
|
||||||
{'4', "4to1", GLO_INT, 0, ¶m.down_sample, 2},
|
{'4', "4to1", GLO_INT, 0, ¶m.down_sample, 2},
|
||||||
{'t', "test", GLO_INT, 0, ¶m.outmode, DECODE_TEST},
|
{'t', "test", GLO_INT, 0, ¶m.outmode, DECODE_TEST},
|
||||||
{'s', "stdout", GLO_INT, SetOutStdout, ¶m.outmode, DECODE_FILE},
|
{'s', "stdout", GLO_INT, set_out_stdout, ¶m.outmode, DECODE_FILE},
|
||||||
{'S', "STDOUT", GLO_INT, SetOutStdout1, ¶m.outmode,DECODE_AUDIOFILE},
|
{'S', "STDOUT", GLO_INT, set_out_stdout1, ¶m.outmode,DECODE_AUDIOFILE},
|
||||||
{'O', "outfile", GLO_ARG | GLO_CHAR, SetOutFile, NULL, 0},
|
{'O', "outfile", GLO_ARG | GLO_CHAR, set_out_file, NULL, 0},
|
||||||
{'c', "check", GLO_INT, 0, ¶m.checkrange, TRUE},
|
{'c', "check", GLO_INT, 0, ¶m.checkrange, TRUE},
|
||||||
{'v', "verbose", 0, set_verbose, 0, 0},
|
{'v', "verbose", 0, set_verbose, 0, 0},
|
||||||
{'q', "quiet", GLO_INT, 0, ¶m.quiet, TRUE},
|
{'q', "quiet", GLO_INT, 0, ¶m.quiet, TRUE},
|
||||||
{'y', "resync", GLO_INT, 0, ¶m.tryresync, FALSE},
|
{'y', "resync", GLO_INT, 0, ¶m.tryresync, FALSE},
|
||||||
{'0', "single0", GLO_INT, 0, ¶m.force_mono, MONO_LEFT},
|
{'0', "single0", GLO_INT, 0, ¶m.force_mono, 0},
|
||||||
{0, "left", GLO_INT, 0, ¶m.force_mono, MONO_LEFT},
|
{0, "left", GLO_INT, 0, ¶m.force_mono, 0},
|
||||||
{'1', "single1", GLO_INT, 0, ¶m.force_mono, MONO_RIGHT},
|
{'1', "single1", GLO_INT, 0, ¶m.force_mono, 1},
|
||||||
{0, "right", GLO_INT, 0, ¶m.force_mono, MONO_RIGHT},
|
{0, "right", GLO_INT, 0, ¶m.force_mono, 1},
|
||||||
{'m', "singlemix", GLO_INT, 0, ¶m.force_mono, MONO_MIX},
|
{'m', "singlemix", GLO_INT, 0, ¶m.force_mono, 3},
|
||||||
{0, "mix", GLO_INT, 0, ¶m.force_mono, MONO_MIX},
|
{0, "mix", GLO_INT, 0, ¶m.force_mono, 3},
|
||||||
{0, "mono", GLO_INT, 0, ¶m.force_mono, MONO_MIX},
|
{0, "mono", GLO_INT, 0, ¶m.force_mono, 3},
|
||||||
{0, "stereo", GLO_INT, 0, ¶m.force_stereo, 1},
|
{0, "stereo", GLO_INT, 0, ¶m.force_stereo, 1},
|
||||||
{0, "reopen", GLO_INT, 0, ¶m.force_reopen, 1},
|
{0, "reopen", GLO_INT, 0, ¶m.force_reopen, 1},
|
||||||
{'g', "gain", GLO_ARG | GLO_LONG, 0, &ai.gain, 0},
|
/* {'g', "gain", GLO_ARG | GLO_LONG, 0, &ao.gain, 0}, FIXME */
|
||||||
{'r', "rate", GLO_ARG | GLO_LONG, 0, ¶m.force_rate, 0},
|
{'r', "rate", GLO_ARG | GLO_LONG, 0, ¶m.force_rate, 0},
|
||||||
{0, "8bit", GLO_INT, 0, ¶m.force_8bit, 1},
|
{0, "8bit", GLO_INT, 0, ¶m.force_8bit, 1},
|
||||||
{0, "headphones", 0, set_output_h, 0,0},
|
{0, "headphones", 0, set_output_h, 0,0},
|
||||||
@@ -438,9 +362,9 @@ topt opts[] = {
|
|||||||
{'T', "realtime", 0, realtime_not_compiled, 0, 0 },
|
{'T', "realtime", 0, realtime_not_compiled, 0, 0 },
|
||||||
#endif
|
#endif
|
||||||
{0, "title", GLO_INT, 0, ¶m.xterm_title, TRUE },
|
{0, "title", GLO_INT, 0, ¶m.xterm_title, TRUE },
|
||||||
{'w', "wav", GLO_ARG | GLO_CHAR, set_wav, 0 , 0 },
|
{'w', "wav", GLO_ARG | GLO_CHAR, set_out_wav, 0, 0 },
|
||||||
{0, "cdr", GLO_ARG | GLO_CHAR, set_cdr, 0 , 0 },
|
{0, "cdr", GLO_ARG | GLO_CHAR, set_out_cdr, 0, 0 },
|
||||||
{0, "au", GLO_ARG | GLO_CHAR, set_au, 0 , 0 },
|
{0, "au", GLO_ARG | GLO_CHAR, set_out_au, 0, 0 },
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
{0, "gapless", GLO_INT, 0, ¶m.gapless, 1},
|
{0, "gapless", GLO_INT, 0, ¶m.gapless, 1},
|
||||||
#endif
|
#endif
|
||||||
@@ -485,22 +409,22 @@ static void reset_audio(void)
|
|||||||
buffermem->freeindex = 0;
|
buffermem->freeindex = 0;
|
||||||
if (intflag)
|
if (intflag)
|
||||||
return;
|
return;
|
||||||
buffermem->buf[0] = ai.rate;
|
buffermem->buf[0] = ao->rate;
|
||||||
buffermem->buf[1] = ai.channels;
|
buffermem->buf[1] = ao->channels;
|
||||||
buffermem->buf[2] = ai.format;
|
buffermem->buf[2] = ao->format;
|
||||||
buffer_reset();
|
buffer_reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (param.outmode == DECODE_AUDIO) {
|
if (param.outmode == DECODE_AUDIO) {
|
||||||
/* audio_reset_parameters(&ai); */
|
/* audio_reset_parameters(ao); */
|
||||||
/* close and re-open in order to flush
|
/* close and re-open in order to flush
|
||||||
* the device's internal buffer before
|
* the device's internal buffer before
|
||||||
* changing the sample rate. [OF]
|
* changing the sample rate. [OF]
|
||||||
*/
|
*/
|
||||||
audio_close (&ai);
|
ao->close(ao);
|
||||||
if (audio_open(&ai) < 0) {
|
if (ao->open(ao) < 0) {
|
||||||
perror("audio");
|
error("failed to open audio device");
|
||||||
safe_exit(1);
|
safe_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -511,11 +435,11 @@ static void reset_audio(void)
|
|||||||
precog the audio rate that will be set before output begins
|
precog the audio rate that will be set before output begins
|
||||||
this is needed to give gapless code a chance to keep track for firstframe != 0
|
this is needed to give gapless code a chance to keep track for firstframe != 0
|
||||||
*/
|
*/
|
||||||
void prepare_audioinfo(struct frame *fr, struct audio_info_struct *nai)
|
void prepare_audioinfo(struct frame *fr, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
long newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
|
long newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
|
||||||
fr->down_sample = param.down_sample;
|
fr->down_sample = param.down_sample;
|
||||||
if(!audio_fit_capabilities(nai,fr->stereo,newrate)) safe_exit(1);
|
if(!audio_fit_capabilities(ao,fr->stereo,newrate)) safe_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -540,22 +464,22 @@ int play_frame(int init,struct frame *fr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(fr->header_change > 1 || init) {
|
if(fr->header_change > 1 || init) {
|
||||||
old_rate = ai.rate;
|
old_rate = ao->rate;
|
||||||
old_format = ai.format;
|
old_format = ao->format;
|
||||||
old_channels = ai.channels;
|
old_channels = ao->channels;
|
||||||
|
|
||||||
newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
|
newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
|
||||||
prepare_audioinfo(fr, &ai);
|
prepare_audioinfo(fr, ao);
|
||||||
if(param.verbose > 1) fprintf(stderr, "Note: audio output rate = %li\n", ai.rate);
|
if(param.verbose > 1) fprintf(stderr, "Note: audio output rate = %li\n", ao->rate);
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
if(param.gapless && (fr->lay == 3)) layer3_gapless_bytify(fr, &ai);
|
if(param.gapless && (fr->lay == 3)) layer3_gapless_bytify(fr, ao);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check, whether the fitter set our proposed rate */
|
/* check, whether the fitter set our proposed rate */
|
||||||
if(ai.rate != newrate) {
|
if(ao->rate != newrate) {
|
||||||
if(ai.rate == (newrate>>1) )
|
if(ao->rate == (newrate>>1) )
|
||||||
fr->down_sample++;
|
fr->down_sample++;
|
||||||
else if(ai.rate == (newrate>>2) )
|
else if(ao->rate == (newrate>>2) )
|
||||||
fr->down_sample+=2;
|
fr->down_sample+=2;
|
||||||
else {
|
else {
|
||||||
fr->down_sample = 3;
|
fr->down_sample = 3;
|
||||||
@@ -574,7 +498,7 @@ int play_frame(int init,struct frame *fr)
|
|||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
long n = freqs[fr->sampling_frequency];
|
long n = freqs[fr->sampling_frequency];
|
||||||
long m = ai.rate;
|
long m = ao->rate;
|
||||||
|
|
||||||
if(!synth_ntom_set_step(n,m)) return 0;
|
if(!synth_ntom_set_step(n,m)) return 0;
|
||||||
|
|
||||||
@@ -589,11 +513,14 @@ int play_frame(int init,struct frame *fr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_output();
|
if (init_output( ao )) {
|
||||||
if(ai.rate != old_rate || ai.channels != old_channels ||
|
safe_exit(-1);
|
||||||
ai.format != old_format || param.force_reopen) {
|
}
|
||||||
if(!param.force_mono) {
|
|
||||||
if(ai.channels == 1)
|
if(ao->rate != old_rate || ao->channels != old_channels ||
|
||||||
|
ao->format != old_format || param.force_reopen) {
|
||||||
|
if(param.force_mono < 0) {
|
||||||
|
if(ao->channels == 1)
|
||||||
fr->single = 3;
|
fr->single = 3;
|
||||||
else
|
else
|
||||||
fr->single = -1;
|
fr->single = -1;
|
||||||
@@ -602,7 +529,7 @@ int play_frame(int init,struct frame *fr)
|
|||||||
fr->single = param.force_mono-1;
|
fr->single = param.force_mono-1;
|
||||||
|
|
||||||
param.force_stereo &= ~0x2;
|
param.force_stereo &= ~0x2;
|
||||||
if(fr->single >= 0 && ai.channels == 2) {
|
if(fr->single >= 0 && ao->channels == 2) {
|
||||||
param.force_stereo |= 0x2;
|
param.force_stereo |= 0x2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,7 +539,7 @@ int play_frame(int init,struct frame *fr)
|
|||||||
if(param.verbose) {
|
if(param.verbose) {
|
||||||
if(fr->down_sample == 3) {
|
if(fr->down_sample == 3) {
|
||||||
long n = freqs[fr->sampling_frequency];
|
long n = freqs[fr->sampling_frequency];
|
||||||
long m = ai.rate;
|
long m = ao->rate;
|
||||||
if(n > m) {
|
if(n > m) {
|
||||||
fprintf(stderr,"Audio: %2.4f:1 conversion,",(float)n/(float)m);
|
fprintf(stderr,"Audio: %2.4f:1 conversion,",(float)n/(float)m);
|
||||||
}
|
}
|
||||||
@@ -623,7 +550,7 @@ int play_frame(int init,struct frame *fr)
|
|||||||
else {
|
else {
|
||||||
fprintf(stderr,"Audio: %ld:1 conversion,",(long)pow(2.0,fr->down_sample));
|
fprintf(stderr,"Audio: %ld:1 conversion,",(long)pow(2.0,fr->down_sample));
|
||||||
}
|
}
|
||||||
fprintf(stderr," rate: %ld, encoding: %s, channels: %d\n",ai.rate,audio_encoding_name(ai.format),ai.channels);
|
fprintf(stderr," rate: %ld, encoding: %s, channels: %d\n",ao->rate,audio_encoding_name(ao->format),ao->channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (intflag)
|
if (intflag)
|
||||||
@@ -636,7 +563,7 @@ int play_frame(int init,struct frame *fr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* do the decoding */
|
/* do the decoding */
|
||||||
clip = (fr->do_layer)(fr,param.outmode,&ai);
|
clip = (fr->do_layer)(fr,param.outmode,ao);
|
||||||
|
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
if (param.usebuffer) {
|
if (param.usebuffer) {
|
||||||
@@ -705,13 +632,13 @@ void set_synth_functions(struct frame *fr)
|
|||||||
funcs_mono[1][0][0] = opt_synth_1to1_mono;
|
funcs_mono[1][0][0] = opt_synth_1to1_mono;
|
||||||
funcs_mono[1][1][0] = opt_synth_1to1_8bit_mono;
|
funcs_mono[1][1][0] = opt_synth_1to1_8bit_mono;
|
||||||
|
|
||||||
if((ai.format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_8)
|
if((ao->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_8)
|
||||||
p8 = 1;
|
p8 = 1;
|
||||||
fr->synth = funcs[p8][ds];
|
fr->synth = funcs[p8][ds];
|
||||||
fr->synth_mono = funcs_mono[ai.channels==2 ? 0 : 1][p8][ds];
|
fr->synth_mono = funcs_mono[param.force_stereo?0:1][p8][ds];
|
||||||
|
|
||||||
if(p8) {
|
if(p8) {
|
||||||
if(make_conv16to8_table(ai.format) != 0)
|
if(make_conv16to8_table(ao->format) != 0)
|
||||||
{
|
{
|
||||||
/* it's a bit more work to get proper error propagation up */
|
/* it's a bit more work to get proper error propagation up */
|
||||||
safe_exit(1);
|
safe_exit(1);
|
||||||
@@ -747,7 +674,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
(prgName = strrchr(argv[0], '/')) ? prgName++ : (prgName = argv[0]);
|
(prgName = strrchr(argv[0], '/')) ? prgName++ : (prgName = argv[0]);
|
||||||
|
|
||||||
audio_info_struct_init(&ai);
|
|
||||||
|
|
||||||
while ((result = getlopt(argc, argv, opts)))
|
while ((result = getlopt(argc, argv, opts)))
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@@ -811,11 +737,21 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(param.force_rate && param.down_sample) {
|
if(param.force_rate && param.down_sample) {
|
||||||
fprintf(stderr,"Down sampling and fixed rate options not allowed together!\n");
|
error("Down sampling and fixed rate options not allowed together!");
|
||||||
safe_exit(1);
|
safe_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_capabilities(&ai);
|
/* Open audio output module */
|
||||||
|
ao = open_output_module( param.output_module );
|
||||||
|
if (!ao) {
|
||||||
|
error("Failed to open audio output module.");
|
||||||
|
safe_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_capabilities(ao);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* equalizer initialization regardless of equalfile */
|
/* equalizer initialization regardless of equalfile */
|
||||||
for(j=0; j<32; j++) {
|
for(j=0; j<32; j++) {
|
||||||
equalizer[0][j] = equalizer[1][j] = 1.0;
|
equalizer[0][j] = equalizer[1][j] = 1.0;
|
||||||
@@ -960,11 +896,11 @@ tc_hack:
|
|||||||
{
|
{
|
||||||
if(pre_init)
|
if(pre_init)
|
||||||
{
|
{
|
||||||
prepare_audioinfo(&fr, &pre_ai);
|
prepare_audioinfo(&fr, &pre_ao);
|
||||||
pre_init = 0;
|
pre_init = 0;
|
||||||
}
|
}
|
||||||
/* keep track... */
|
/* keep track... */
|
||||||
layer3_gapless_set_position(fr.num, &fr, &pre_ai);
|
layer3_gapless_set_position(fr.num, &fr, &pre_ao);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -982,12 +918,12 @@ tc_hack:
|
|||||||
if(param.verbose) {
|
if(param.verbose) {
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
if (param.verbose > 1 || !(fr.num & 0x7))
|
if (param.verbose > 1 || !(fr.num & 0x7))
|
||||||
print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),&ai);
|
print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),ao);
|
||||||
if(param.verbose > 2 && param.usebuffer)
|
if(param.verbose > 2 && param.usebuffer)
|
||||||
fprintf(stderr,"[%08x %08x]",buffermem->readindex,buffermem->freeindex);
|
fprintf(stderr,"[%08x %08x]",buffermem->readindex,buffermem->freeindex);
|
||||||
#else
|
#else
|
||||||
if (param.verbose > 1 || !(fr.num & 0x7))
|
if (param.verbose > 1 || !(fr.num & 0x7))
|
||||||
print_stat(&fr,fr.num,0,&ai);
|
print_stat(&fr,fr.num,0,ao);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
@@ -995,12 +931,12 @@ tc_hack:
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
long offset;
|
long offset;
|
||||||
if((offset=term_control(&fr,&ai))) {
|
if((offset=term_control(&fr,ao))) {
|
||||||
if(!rd->back_frame(rd, &fr, -offset)) {
|
if(!rd->back_frame(rd, &fr, -offset)) {
|
||||||
debug1("seeked to %lu", fr.num);
|
debug1("seeked to %lu", fr.num);
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
if(param.gapless && (fr.lay == 3))
|
if(param.gapless && (fr.lay == 3))
|
||||||
layer3_gapless_set_position(fr.num, &fr, &ai);
|
layer3_gapless_set_position(fr.num, &fr, ao);
|
||||||
#endif
|
#endif
|
||||||
} else { error("seek failed!"); }
|
} else { error("seek failed!"); }
|
||||||
}
|
}
|
||||||
@@ -1010,7 +946,7 @@ tc_hack:
|
|||||||
}
|
}
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
/* make sure that the correct padding is skipped after track ended */
|
/* make sure that the correct padding is skipped after track ended */
|
||||||
if(param.gapless) audio_flush(param.outmode, &ai);
|
if(param.gapless) audio_flush(param.outmode, ao);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
@@ -1022,18 +958,18 @@ tc_hack:
|
|||||||
buffer_ignore_lowmem();
|
buffer_ignore_lowmem();
|
||||||
|
|
||||||
if(param.verbose)
|
if(param.verbose)
|
||||||
print_stat(&fr,fr.num,s,&ai);
|
print_stat(&fr,fr.num,s,ao);
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
if(param.term_ctrl) {
|
if(param.term_ctrl) {
|
||||||
long offset;
|
long offset;
|
||||||
if((offset=term_control(&fr,&ai))) {
|
if((offset=term_control(&fr,ao))) {
|
||||||
if((!rd->back_frame(rd, &fr, -offset))
|
if((!rd->back_frame(rd, &fr, -offset))
|
||||||
&& read_frame(&fr))
|
&& read_frame(&fr))
|
||||||
{
|
{
|
||||||
debug1("seeked to %lu", fr.num);
|
debug1("seeked to %lu", fr.num);
|
||||||
#ifdef GAPLESS
|
#ifdef GAPLESS
|
||||||
if(param.gapless && (fr.lay == 3))
|
if(param.gapless && (fr.lay == 3))
|
||||||
layer3_gapless_set_position(fr.num, &fr, &ai);
|
layer3_gapless_set_position(fr.num, &fr, ao);
|
||||||
#endif
|
#endif
|
||||||
goto tc_hack; /* Doh! Gag me with a spoon! */
|
goto tc_hack; /* Doh! Gag me with a spoon! */
|
||||||
} else { error("seek failed!"); }
|
} else { error("seek failed!"); }
|
||||||
@@ -1045,7 +981,7 @@ tc_hack:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if(param.verbose)
|
if(param.verbose)
|
||||||
print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),&ai);
|
print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),ao);
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
if(param.term_ctrl)
|
if(param.term_ctrl)
|
||||||
term_restore();
|
term_restore();
|
||||||
@@ -1112,7 +1048,7 @@ tc_hack:
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#endif
|
#endif
|
||||||
audio_flush(param.outmode, &ai);
|
audio_flush(param.outmode, ao);
|
||||||
free (pcm_sample);
|
free (pcm_sample);
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
}
|
}
|
||||||
@@ -1120,7 +1056,7 @@ tc_hack:
|
|||||||
|
|
||||||
switch(param.outmode) {
|
switch(param.outmode) {
|
||||||
case DECODE_AUDIO:
|
case DECODE_AUDIO:
|
||||||
audio_close(&ai);
|
ao->close(ao);
|
||||||
break;
|
break;
|
||||||
case DECODE_WAV:
|
case DECODE_WAV:
|
||||||
wav_close();
|
wav_close();
|
||||||
@@ -1222,6 +1158,8 @@ static void long_usage(int err)
|
|||||||
fprintf(o," -Z --random full random play\n");
|
fprintf(o," -Z --random full random play\n");
|
||||||
|
|
||||||
fprintf(o,"\noutput/processing options\n\n");
|
fprintf(o,"\noutput/processing options\n\n");
|
||||||
|
fprintf(o," -o <o> --output <o> select audio output module\n");
|
||||||
|
fprintf(o," --list-modules list the available modules\n");
|
||||||
fprintf(o," -a <d> --audiodevice <d> select audio device\n");
|
fprintf(o," -a <d> --audiodevice <d> select audio device\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," -S --STDOUT play AND output stream (not implemented yet)\n");
|
fprintf(o," -S --STDOUT play AND output stream (not implemented yet)\n");
|
||||||
|
|||||||
33
src/mpg123.h
33
src/mpg123.h
@@ -118,6 +118,7 @@ typedef unsigned char byte;
|
|||||||
# define REAL_MUL(x, y) ((x) * (y))
|
# define REAL_MUL(x, y) ((x) * (y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */
|
/* AUDIOBUFSIZE = n*64 with n=1,2,3 ... */
|
||||||
@@ -171,7 +172,7 @@ struct frame {
|
|||||||
int down_sample;
|
int down_sample;
|
||||||
int header_change;
|
int header_change;
|
||||||
int lay;
|
int lay;
|
||||||
int (*do_layer)(struct frame *fr,int,struct audio_info_struct *);
|
int (*do_layer)(struct frame *fr,int,audio_output_t *);
|
||||||
int error_protection;
|
int error_protection;
|
||||||
int bitrate_index;
|
int bitrate_index;
|
||||||
int sampling_frequency;
|
int sampling_frequency;
|
||||||
@@ -187,6 +188,9 @@ struct frame {
|
|||||||
unsigned long num; /* the nth frame in some stream... */
|
unsigned long num; /* the nth frame in some stream... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define FRAMEBUFUNIT (18 * 64 * 4)
|
||||||
|
|
||||||
#define VERBOSE_MAX 3
|
#define VERBOSE_MAX 3
|
||||||
|
|
||||||
#define MONO_LEFT 1
|
#define MONO_LEFT 1
|
||||||
@@ -204,6 +208,8 @@ struct parameter {
|
|||||||
long usebuffer; /* second level buffer size */
|
long usebuffer; /* second level buffer size */
|
||||||
int tryresync; /* resync stream after error */
|
int tryresync; /* resync stream after error */
|
||||||
int verbose; /* verbose level */
|
int verbose; /* verbose level */
|
||||||
|
char* output_module; /* audio output module to use */
|
||||||
|
char* output_device; /* audio output device to use */
|
||||||
#ifdef HAVE_TERMIOS
|
#ifdef HAVE_TERMIOS
|
||||||
int term_ctrl;
|
int term_ctrl;
|
||||||
#endif
|
#endif
|
||||||
@@ -279,12 +285,12 @@ extern int buffer_fd[2];
|
|||||||
extern txfermem *buffermem;
|
extern txfermem *buffermem;
|
||||||
|
|
||||||
#ifndef NOXFERMEM
|
#ifndef NOXFERMEM
|
||||||
extern void buffer_loop(struct audio_info_struct *ai,sigset_t *oldsigset);
|
extern void buffer_loop(audio_output_t *ao,sigset_t *oldsigset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------ Declarations from "common.c" ------ */
|
/* ------ Declarations from "common.c" ------ */
|
||||||
|
|
||||||
extern void audio_flush(int, struct audio_info_struct *);
|
extern void audio_flush(int, audio_output_t *);
|
||||||
extern void (*catchsignal(int signum, void(*handler)()))();
|
extern void (*catchsignal(int signum, void(*handler)()))();
|
||||||
|
|
||||||
extern void print_header(struct frame *);
|
extern void print_header(struct frame *);
|
||||||
@@ -305,6 +311,7 @@ extern void set_pointer(long);
|
|||||||
extern unsigned char *pcm_sample;
|
extern unsigned char *pcm_sample;
|
||||||
extern int pcm_point;
|
extern int pcm_point;
|
||||||
extern int audiobufsize;
|
extern int audiobufsize;
|
||||||
|
extern int buffer_pid;
|
||||||
|
|
||||||
extern int OutputDescriptor;
|
extern int OutputDescriptor;
|
||||||
|
|
||||||
@@ -347,11 +354,11 @@ extern int open_stream(char *,int fd);
|
|||||||
extern void read_frame_init (struct frame* fr);
|
extern void read_frame_init (struct frame* fr);
|
||||||
extern int read_frame(struct frame *fr);
|
extern int read_frame(struct frame *fr);
|
||||||
/* why extern? */
|
/* why extern? */
|
||||||
void prepare_audioinfo(struct frame *fr, struct audio_info_struct *nai);
|
extern void prepare_audioinfo(struct frame *fr, audio_output_t *ao);
|
||||||
extern int play_frame(int init,struct frame *fr);
|
extern int play_frame(int init,struct frame *fr);
|
||||||
extern int do_layer3(struct frame *fr,int,struct audio_info_struct *);
|
extern int do_layer3(struct frame *fr,int,audio_output_t *);
|
||||||
extern int do_layer2(struct frame *fr,int,struct audio_info_struct *);
|
extern int do_layer2(struct frame *fr,int,audio_output_t *);
|
||||||
extern int do_layer1(struct frame *fr,int,struct audio_info_struct *);
|
extern int do_layer1(struct frame *fr,int,audio_output_t *);
|
||||||
extern void do_equalizer(real *bandPtr,int channel);
|
extern void do_equalizer(real *bandPtr,int channel);
|
||||||
|
|
||||||
/* synth_1to1 in optimize.h, one should also use opts for these here... */
|
/* synth_1to1 in optimize.h, one should also use opts for these here... */
|
||||||
@@ -392,18 +399,18 @@ extern int synth_ntom_set_step(long,long);
|
|||||||
|
|
||||||
extern int control_generic(struct frame *fr);
|
extern int control_generic(struct frame *fr);
|
||||||
|
|
||||||
extern int cdr_open(struct audio_info_struct *ai, char *ame);
|
extern int cdr_open(audio_output_t *, char *ame);
|
||||||
extern int au_open(struct audio_info_struct *ai, char *name);
|
extern int au_open(audio_output_t *, char *name);
|
||||||
extern int wav_open(struct audio_info_struct *ai, char *wavfilename);
|
extern int wav_open(audio_output_t *, char *wavfilename);
|
||||||
extern int wav_write(unsigned char *buf,int len);
|
extern int wav_write(unsigned char *buf,int len);
|
||||||
extern int cdr_close(void);
|
extern int cdr_close(void);
|
||||||
extern int au_close(void);
|
extern int au_close(void);
|
||||||
extern int wav_close(void);
|
extern int wav_close(void);
|
||||||
|
|
||||||
extern int au_open(struct audio_info_struct *ai, char *aufilename);
|
extern int au_open(audio_output_t *, char *aufilename);
|
||||||
extern int au_close(void);
|
extern int au_close(void);
|
||||||
|
|
||||||
extern int cdr_open(struct audio_info_struct *ai, char *cdrfilename);
|
extern int cdr_open(audio_output_t *, char *cdrfilename);
|
||||||
extern int cdr_close(void);
|
extern int cdr_close(void);
|
||||||
|
|
||||||
extern unsigned char *conv16to8;
|
extern unsigned char *conv16to8;
|
||||||
@@ -414,7 +421,7 @@ extern real equalizer[2][32];
|
|||||||
extern real equalizer_sum[2][32];
|
extern real equalizer_sum[2][32];
|
||||||
extern int equalizer_cnt;
|
extern int equalizer_cnt;
|
||||||
|
|
||||||
extern struct audio_name audio_val2name[];
|
extern struct audio_format_name audio_val2name[];
|
||||||
|
|
||||||
extern struct parameter param;
|
extern struct parameter param;
|
||||||
|
|
||||||
|
|||||||
126
src/output/Makefile.am
Normal file
126
src/output/Makefile.am
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
## Makefile.am: produce Makefile.in from this
|
||||||
|
|
||||||
|
## copyright by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
## see COPYING and AUTHORS files in distribution or http://www.mpg123.org
|
||||||
|
## initially written by Nicholas J. Humfrey
|
||||||
|
|
||||||
|
|
||||||
|
pkglib_LTLIBRARIES = output_dummy.la
|
||||||
|
output_dummy_la_SOURCES = dummy.c
|
||||||
|
output_dummy_la_LDFLAGS = -module -avoid-version
|
||||||
|
|
||||||
|
#if HAVE_AIX
|
||||||
|
#pkglib_LTLIBRARIES += output_aix.la
|
||||||
|
#output_aix_la_SOURCES = aix.c
|
||||||
|
#output_aix_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_ALIB
|
||||||
|
#pkglib_LTLIBRARIES += output_alib.la
|
||||||
|
#output_alib_la_SOURCES = alib.c
|
||||||
|
#output_alib_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if HAVE_ALSA
|
||||||
|
pkglib_LTLIBRARIES += output_alsa.la
|
||||||
|
output_alsa_la_SOURCES = alsa.c
|
||||||
|
output_alsa_la_LDFLAGS = -module -avoid-version
|
||||||
|
output_alsa_la_LIBADD = -lasound
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_COREAUDIO
|
||||||
|
pkglib_LTLIBRARIES += output_coreaudio.la
|
||||||
|
output_coreaudio_la_SOURCES = coreaudio.c
|
||||||
|
output_coreaudio_la_LDFLAGS = -module -avoid-version \
|
||||||
|
-framework AudioToolbox \
|
||||||
|
-framework AudioUnit \
|
||||||
|
-framework CoreServices
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_ESOUND
|
||||||
|
pkglib_LTLIBRARIES += output_esound.la
|
||||||
|
output_esound_la_SOURCES = esd.c
|
||||||
|
output_esound_la_CFLAGS = @ESOUND_CFLAGS@
|
||||||
|
output_esound_la_LDFLAGS = -module -avoid-version @ESOUND_LDFLAGS@
|
||||||
|
output_esound_la_LIBADD = @ESOUND_LIBS@
|
||||||
|
endif
|
||||||
|
|
||||||
|
#if HAVE_HP
|
||||||
|
#pkglib_LTLIBRARIES += output_hp.la
|
||||||
|
#output_hp_la_SOURCES = hp.c
|
||||||
|
#output_hp_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if HAVE_JACK
|
||||||
|
pkglib_LTLIBRARIES += output_jack.la
|
||||||
|
output_jack_la_SOURCES = jack.c
|
||||||
|
output_jack_la_CFLAGS = @JACK_CFLAGS@
|
||||||
|
output_jack_la_LDFLAGS = -module -avoid-version @JACK_LDFLAGS@
|
||||||
|
output_jack_la_LIBADD = @JACK_LIBS@
|
||||||
|
endif
|
||||||
|
|
||||||
|
#if HAVE_MINT
|
||||||
|
#pkglib_LTLIBRARIES += output_mint.la
|
||||||
|
#output_mint_la_SOURCES = mint.c
|
||||||
|
#output_mint_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if HAVE_NAS
|
||||||
|
pkglib_LTLIBRARIES += output_nas.la
|
||||||
|
output_nas_la_SOURCES = nas.c
|
||||||
|
output_nas_la_LDFLAGS = -module -avoid-version
|
||||||
|
output_nas_la_LIBADD = -laudio
|
||||||
|
endif
|
||||||
|
|
||||||
|
#if HAVE_OS2
|
||||||
|
#pkglib_LTLIBRARIES += output_os2.la
|
||||||
|
#output_os2_la_SOURCES = os2.c
|
||||||
|
#output_os2_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if HAVE_OSS
|
||||||
|
pkglib_LTLIBRARIES += output_oss.la
|
||||||
|
output_oss_la_SOURCES = oss.c
|
||||||
|
output_oss_la_LDFLAGS = -module -avoid-version
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_PORTAUDIO
|
||||||
|
pkglib_LTLIBRARIES += output_portaudio.la
|
||||||
|
output_portaudio_la_SOURCES = portaudio.c
|
||||||
|
output_portaudio_la_LDFLAGS = -module -avoid-version
|
||||||
|
output_portaudio_la_LIBADD = -lportaudio
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_PULSE
|
||||||
|
pkglib_LTLIBRARIES += output_pulse.la
|
||||||
|
output_pulse_la_SOURCES = pulse.c
|
||||||
|
output_pulse_la_CFLAGS = @PULSE_CFLAGS@
|
||||||
|
output_pulse_la_LDFLAGS = -module -avoid-version @PULSE_LDFLAGS@
|
||||||
|
output_pulse_la_LIBADD = @PULSE_LIBS@
|
||||||
|
endif
|
||||||
|
|
||||||
|
if HAVE_SDL
|
||||||
|
pkglib_LTLIBRARIES += output_sdl.la
|
||||||
|
output_sdl_la_SOURCES = sdl.c
|
||||||
|
output_sdl_la_CFLAGS = @SDL_CFLAGS@
|
||||||
|
output_sdl_la_LDFLAGS = -module -avoid-version @SDL_LDFLAGS@
|
||||||
|
output_sdl_la_LIBADD = @SDL_LIBS@
|
||||||
|
endif
|
||||||
|
|
||||||
|
#if HAVE_SGI
|
||||||
|
#pkglib_LTLIBRARIES += output_sgi.la
|
||||||
|
#output_sgi_la_SOURCES = sgi.c
|
||||||
|
#output_sgi_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if HAVE_SUN
|
||||||
|
pkglib_LTLIBRARIES += output_sun.la
|
||||||
|
output_sun_la_SOURCES = sun.c
|
||||||
|
output_sun_la_LDFLAGS = -module -avoid-version
|
||||||
|
endif
|
||||||
|
|
||||||
|
#if HAVE_WIN32
|
||||||
|
#pkglib_LTLIBRARIES += output_win32.la
|
||||||
|
#output_win32_la_SOURCES = win32.c
|
||||||
|
#output_win32_la_LDFLAGS = -module -avoid-version
|
||||||
|
#endif
|
||||||
@@ -1,15 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
audio_aix.c: Driver for IBM RS/6000 with AIX Ultimedia Services
|
aix: Driver for IBM RS/6000 with AIX Ultimedia Services
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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 Juergen Schoew and Tomas Oegren
|
initially written by Juergen Schoew and Tomas Oegren
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/audio.h>
|
#include <sys/audio.h>
|
||||||
#include <stropts.h>
|
#include <stropts.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@@ -21,56 +26,56 @@
|
|||||||
/* #define AUDIO_BSIZE AUDIO_IGNORE */
|
/* #define AUDIO_BSIZE AUDIO_IGNORE */
|
||||||
#define AUDIO_BSIZE 200
|
#define AUDIO_BSIZE 200
|
||||||
|
|
||||||
int audio_rate_best_match(struct audio_info_struct *ai)
|
int audio_rate_best_match(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
static long valid [ ] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900,
|
static long valid [ ] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900,
|
||||||
22050, 27420, 32000, 33075, 37800, 44100, 48000, 0 };
|
22050, 27420, 32000, 33075, 37800, 44100, 48000, 0 };
|
||||||
int i = 0;
|
int i = 0;
|
||||||
long best = 8000;
|
long best = 8000;
|
||||||
|
|
||||||
if(!ai || ai->fn < 0 || ai->rate < 0) {
|
if(!ai || ao->fn < 0 || ao->rate < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (valid [i])
|
while (valid [i])
|
||||||
{
|
{
|
||||||
if (abs(valid[i] - ai->rate) < abs(best - ai->rate))
|
if (abs(valid[i] - ao->rate) < abs(best - ao->rate))
|
||||||
{
|
{
|
||||||
best = valid [i];
|
best = valid [i];
|
||||||
}
|
}
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ai->rate = best;
|
ao->rate = best;
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_init ainit;
|
audio_init ainit;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(!ai->device) {
|
if(!ao->device) {
|
||||||
if(getenv("AUDIODEV")) {
|
if(getenv("AUDIODEV")) {
|
||||||
if(param.verbose > 1)
|
if(param.verbose > 1)
|
||||||
fprintf(stderr,"Using audio-device value from AUDIODEV environmentvariable!\n");
|
fprintf(stderr,"Using audio-device value from AUDIODEV environmentvariable!\n");
|
||||||
ai->device = getenv("AUDIODEV");
|
ao->device = getenv("AUDIODEV");
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ai->device = "/dev/paud0/1"; /* paud0 for PCI */
|
ao->device = "/dev/paud0/1"; /* paud0 for PCI */
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
if ((ai->fn == -1) & (errno == ENOENT)) {
|
if ((ao->fn == -1) & (errno == ENOENT)) {
|
||||||
ai->device = "/dev/baud0/1"; /* baud0 for MCA */
|
ao->device = "/dev/baud0/1"; /* baud0 for MCA */
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else ai->fn = open(ai->device,O_WRONLY);
|
} else ao->fn = open(ao->device,O_WRONLY);
|
||||||
|
|
||||||
if(ai->fn < 0){
|
if(ao->fn < 0){
|
||||||
fprintf(stderr,"Can't open audio device!\n");
|
fprintf(stderr,"Can't open audio device!\n");
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init to default values */
|
/* Init to default values */
|
||||||
@@ -83,14 +88,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
ainit.operation = PLAY;
|
ainit.operation = PLAY;
|
||||||
ainit.bsize = AUDIO_BSIZE;
|
ainit.bsize = AUDIO_BSIZE;
|
||||||
|
|
||||||
ret = ioctl (ai->fn, AUDIO_INIT, & ainit);
|
ret = ioctl (ao->fn, AUDIO_INIT, & ainit);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
audio_reset_parameters(ai);
|
audio_reset_parameters(ai);
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_reset_parameters(struct audio_info_struct *ai)
|
int audio_reset_parameters(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_control acontrol;
|
audio_control acontrol;
|
||||||
audio_change achange;
|
audio_change achange;
|
||||||
@@ -105,16 +110,16 @@ int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
achange.volume = (long) (0x7fff << 16);
|
achange.volume = (long) (0x7fff << 16);
|
||||||
achange.volume_delay = 0;
|
achange.volume_delay = 0;
|
||||||
achange.input = AUDIO_IGNORE;
|
achange.input = AUDIO_IGNORE;
|
||||||
if (ai->output == -1) achange.output = INTERNAL_SPEAKER;
|
if (ao->output == -1) achange.output = INTERNAL_SPEAKER;
|
||||||
else
|
else
|
||||||
achange.output = 0;
|
achange.output = 0;
|
||||||
if(ai->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
if(ao->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||||
achange.output |= INTERNAL_SPEAKER;
|
achange.output |= INTERNAL_SPEAKER;
|
||||||
if(ai->output & AUDIO_OUT_HEADPHONES)
|
if(ao->output & AUDIO_OUT_HEADPHONES)
|
||||||
achange.output |= EXTERNAL_SPEAKER;
|
achange.output |= EXTERNAL_SPEAKER;
|
||||||
if(ai->output & AUDIO_OUT_LINE_OUT)
|
if(ao->output & AUDIO_OUT_LINE_OUT)
|
||||||
achange.output |= OUTPUT_1;
|
achange.output |= OUTPUT_1;
|
||||||
if(ai->output == 0)
|
if(ao->output == 0)
|
||||||
achange.output = AUDIO_IGNORE;
|
achange.output = AUDIO_IGNORE;
|
||||||
achange.treble = AUDIO_IGNORE;
|
achange.treble = AUDIO_IGNORE;
|
||||||
achange.bass = AUDIO_IGNORE;
|
achange.bass = AUDIO_IGNORE;
|
||||||
@@ -126,19 +131,19 @@ int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
acontrol.position = 0;
|
acontrol.position = 0;
|
||||||
acontrol.request_info = (char *) & achange;
|
acontrol.request_info = (char *) & achange;
|
||||||
|
|
||||||
ret = ioctl (ai->fn, AUDIO_CONTROL, & acontrol);
|
ret = ioctl (ao->fn, AUDIO_CONTROL, & acontrol);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Init Device for new values */
|
/* Init Device for new values */
|
||||||
if (ai->rate >0) {
|
if (ao->rate >0) {
|
||||||
memset ( & ainit, '\0', sizeof (ainit));
|
memset ( & ainit, '\0', sizeof (ainit));
|
||||||
ainit.srate = audio_rate_best_match(ai);
|
ainit.srate = audio_rate_best_match(ai);
|
||||||
if (ai->channels > 0)
|
if (ao->channels > 0)
|
||||||
ainit.channels = ai->channels;
|
ainit.channels = ao->channels;
|
||||||
else
|
else
|
||||||
ainit.channels = 1;
|
ainit.channels = 1;
|
||||||
switch (ai->format) {
|
switch (ao->format) {
|
||||||
default :
|
default :
|
||||||
ainit.mode = PCM;
|
ainit.mode = PCM;
|
||||||
ainit.bits_per_sample = 8;
|
ainit.bits_per_sample = 8;
|
||||||
@@ -178,7 +183,7 @@ int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
ainit.operation = PLAY;
|
ainit.operation = PLAY;
|
||||||
ainit.bsize = AUDIO_BSIZE;
|
ainit.bsize = AUDIO_BSIZE;
|
||||||
|
|
||||||
ret = ioctl (ai->fn, AUDIO_INIT, & ainit);
|
ret = ioctl (ao->fn, AUDIO_INIT, & ainit);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr,"Can't set new audio parameters!\n");
|
fprintf(stderr,"Can't set new audio parameters!\n");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -189,7 +194,7 @@ int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
acontrol.request_info = NULL;
|
acontrol.request_info = NULL;
|
||||||
acontrol.position = 0;
|
acontrol.position = 0;
|
||||||
|
|
||||||
ret = ioctl (ai->fn, AUDIO_CONTROL, & acontrol);
|
ret = ioctl (ao->fn, AUDIO_CONTROL, & acontrol);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr,"Can't reset audio!\n");
|
fprintf(stderr,"Can't reset audio!\n");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -197,7 +202,7 @@ int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/* ULTIMEDIA DOCUMENTATION SAYS:
|
/* ULTIMEDIA DOCUMENTATION SAYS:
|
||||||
The Ultimedia Audio Adapter supports fourteen sample rates you can use to
|
The Ultimedia Audio Adapter supports fourteen sample rates you can use to
|
||||||
@@ -209,9 +214,9 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
long rate;
|
long rate;
|
||||||
|
|
||||||
rate = ai->rate;
|
rate = ao->rate;
|
||||||
audio_rate_best_match(ai);
|
audio_rate_best_match(ai);
|
||||||
if (ai->rate == rate)
|
if (ao->rate == rate)
|
||||||
return (AUDIO_FORMAT_SIGNED_16|AUDIO_FORMAT_UNSIGNED_16|
|
return (AUDIO_FORMAT_SIGNED_16|AUDIO_FORMAT_UNSIGNED_16|
|
||||||
AUDIO_FORMAT_UNSIGNED_8|AUDIO_FORMAT_SIGNED_8|
|
AUDIO_FORMAT_UNSIGNED_8|AUDIO_FORMAT_SIGNED_8|
|
||||||
AUDIO_FORMAT_ULAW_8|AUDIO_FORMAT_ALAW_8);
|
AUDIO_FORMAT_ULAW_8|AUDIO_FORMAT_ALAW_8);
|
||||||
@@ -219,12 +224,12 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
return write(ai->fn,buf,len);
|
return write(ao->fn,buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_control acontrol;
|
audio_control acontrol;
|
||||||
audio_buffer abuffer;
|
audio_buffer abuffer;
|
||||||
@@ -236,7 +241,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
acontrol.position = 0;
|
acontrol.position = 0;
|
||||||
i=50; /* Don't do this forever on a bad day :-) */
|
i=50; /* Don't do this forever on a bad day :-) */
|
||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
if ((ioctl(ai->fn, AUDIO_BUFFER, &acontrol))< 0) {
|
if ((ioctl(ao->fn, AUDIO_BUFFER, &acontrol))< 0) {
|
||||||
fprintf(stderr, "buffer read failed: %d\n", errno);
|
fprintf(stderr, "buffer read failed: %d\n", errno);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -251,18 +256,18 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
acontrol.request_info = NULL;
|
acontrol.request_info = NULL;
|
||||||
acontrol.position = 0;
|
acontrol.position = 0;
|
||||||
|
|
||||||
ret = ioctl ( ai->fn, AUDIO_CONTROL, & acontrol );
|
ret = ioctl ( ao->fn, AUDIO_CONTROL, & acontrol );
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr,"Can't close audio!\n");
|
fprintf(stderr,"Can't close audio!\n");
|
||||||
|
|
||||||
ret = close (ai->fn);
|
ret = close (ao->fn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr,"Can't close audio!\n");
|
fprintf(stderr,"Can't close audio!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_alib.c: audio output for HP-UX using alib
|
alib: audio output for HP-UX using alib
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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
|
||||||
@@ -54,14 +54,14 @@
|
|||||||
*
|
*
|
||||||
* used :
|
* used :
|
||||||
*
|
*
|
||||||
* int audio_open(struct audio_info_struct *ai);
|
* int audio_open(audio_output_t *ao);
|
||||||
* int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len);
|
* int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len);
|
||||||
* int audio_close(struct audio_info_struct *ai);
|
* int audio_close(audio_output_t *ao);
|
||||||
*
|
*
|
||||||
* unused :
|
* unused :
|
||||||
*
|
*
|
||||||
* int audio_set_rate(struct audio_info_struct *ai);
|
* int audio_set_rate(audio_output_t *ao);
|
||||||
* int audio_set_channels(struct audio_info_struct *ai);
|
* int audio_set_channels(audio_output_t *ao);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -91,12 +91,12 @@ static long myHandler(Audio *audio,AErrorEvent *err_event) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the fn element of ai
|
* Set the fn element of ai
|
||||||
* Use ai->rate and ai->channels
|
* Use ao->rate and ao->channels
|
||||||
* Doesn't set any volume
|
* Doesn't set any volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* return on error leaves stuff dirty here... */
|
/* return on error leaves stuff dirty here... */
|
||||||
int audio_open(struct audio_info_struct *ai) {
|
int audio_open(audio_output_t *ao) {
|
||||||
AudioAttributes Attribs;
|
AudioAttributes Attribs;
|
||||||
AudioAttrMask AttribsMask;
|
AudioAttrMask AttribsMask;
|
||||||
AGainEntry gainEntry[4];
|
AGainEntry gainEntry[4];
|
||||||
@@ -117,13 +117,13 @@ int audio_open(struct audio_info_struct *ai) {
|
|||||||
if(audioServer==NULL)
|
if(audioServer==NULL)
|
||||||
{error("Error: could not open audio\n"); return -1; }
|
{error("Error: could not open audio\n"); return -1; }
|
||||||
|
|
||||||
ai->fn = socket( AF_INET, SOCK_STREAM, 0 );
|
ao->fn = socket( AF_INET, SOCK_STREAM, 0 );
|
||||||
if(ai->fn<0)
|
if(ao->fn<0)
|
||||||
{error("Socket creation failed"); return -1; }
|
{error("Socket creation failed"); return -1; }
|
||||||
|
|
||||||
Attribs.type = ATSampled;
|
Attribs.type = ATSampled;
|
||||||
Attribs.attr.sampled_attr.sampling_rate = ai->rate;
|
Attribs.attr.sampled_attr.sampling_rate = ao->rate;
|
||||||
Attribs.attr.sampled_attr.channels = ai->channels;
|
Attribs.attr.sampled_attr.channels = ao->channels;
|
||||||
Attribs.attr.sampled_attr.data_format = ADFLin16;
|
Attribs.attr.sampled_attr.data_format = ADFLin16;
|
||||||
AttribsMask = ASSamplingRateMask | ASChannelsMask | ASDataFormatMask;
|
AttribsMask = ASSamplingRateMask | ASChannelsMask | ASDataFormatMask;
|
||||||
|
|
||||||
@@ -141,23 +141,23 @@ int audio_open(struct audio_info_struct *ai) {
|
|||||||
xid=APlaySStream(audioServer,AttribsMask,&Attribs,
|
xid=APlaySStream(audioServer,AttribsMask,&Attribs,
|
||||||
&playParams,&audioStream,NULL);
|
&playParams,&audioStream,NULL);
|
||||||
|
|
||||||
status=connect(ai->fn,
|
status=connect(ao->fn,
|
||||||
(struct sockaddr *) &audioStream.tcp_sockaddr,
|
(struct sockaddr *) &audioStream.tcp_sockaddr,
|
||||||
sizeof(struct sockaddr_in) );
|
sizeof(struct sockaddr_in) );
|
||||||
if(status<0){error("Connect failed"); return -1;}
|
if(status<0){error("Connect failed"); return -1;}
|
||||||
|
|
||||||
i=-1;
|
i=-1;
|
||||||
tcpProtocolEntry=getprotobyname("tcp");
|
tcpProtocolEntry=getprotobyname("tcp");
|
||||||
setsockopt(ai->fn,tcpProtocolEntry->p_proto,TCP_NODELAY,&i,sizeof(i));
|
setsockopt(ao->fn,tcpProtocolEntry->p_proto,TCP_NODELAY,&i,sizeof(i));
|
||||||
|
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
close(ai->fn);
|
close(ao->fn);
|
||||||
ASetCloseDownMode( audioServer, AKeepTransactions, NULL );
|
ASetCloseDownMode( audioServer, AKeepTransactions, NULL );
|
||||||
ACloseAudio( audioServer, NULL );
|
ACloseAudio( audioServer, NULL );
|
||||||
audioServer = (Audio *) NULL;
|
audioServer = (Audio *) NULL;
|
||||||
@@ -171,19 +171,19 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
* deserv to be inline
|
* deserv to be inline
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
inline int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
return write(ai->fn,buf,len*2);
|
return write(ao->fn,buf,len*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
251
src/output/alsa.c
Normal file
251
src/output/alsa.c
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
alsa: sound output with Advanced Linux Sound Architecture 1.x API
|
||||||
|
|
||||||
|
copyright 2006 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
|
||||||
|
|
||||||
|
written by Clemens Ladisch <clemens@ladisch.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
#include "audio.h"
|
||||||
|
#include "module.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* make ALSA 0.9.x compatible to the 1.0.x API */
|
||||||
|
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||||
|
#define ALSA_PCM_NEW_SW_PARAMS_API
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
/* My laptop has probs playing low-sampled files with only 0.5s buffer... this should be a user setting -- ThOr */
|
||||||
|
#define BUFFER_LENGTH 0.5 /* in seconds */
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
snd_pcm_format_t alsa;
|
||||||
|
int mpg123;
|
||||||
|
} format_map[] = {
|
||||||
|
{ SND_PCM_FORMAT_S16, AUDIO_FORMAT_SIGNED_16 },
|
||||||
|
{ SND_PCM_FORMAT_U16, AUDIO_FORMAT_UNSIGNED_16 },
|
||||||
|
{ SND_PCM_FORMAT_U8, AUDIO_FORMAT_UNSIGNED_8 },
|
||||||
|
{ SND_PCM_FORMAT_S8, AUDIO_FORMAT_SIGNED_8 },
|
||||||
|
{ SND_PCM_FORMAT_A_LAW, AUDIO_FORMAT_ALAW_8 },
|
||||||
|
{ SND_PCM_FORMAT_MU_LAW, AUDIO_FORMAT_ULAW_8 },
|
||||||
|
};
|
||||||
|
#define NUM_FORMATS (sizeof format_map / sizeof format_map[0])
|
||||||
|
|
||||||
|
|
||||||
|
static int rates_match(long int desired, unsigned int actual)
|
||||||
|
{
|
||||||
|
return actual * 100 > desired * (100 - AUDIO_RATE_TOLERANCE) &&
|
||||||
|
actual * 100 < desired * (100 + AUDIO_RATE_TOLERANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int initialize_device(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
snd_pcm_hw_params_t *hw;
|
||||||
|
int i;
|
||||||
|
snd_pcm_format_t format;
|
||||||
|
unsigned int rate;
|
||||||
|
snd_pcm_uframes_t buffer_size;
|
||||||
|
snd_pcm_uframes_t period_size;
|
||||||
|
snd_pcm_sw_params_t *sw;
|
||||||
|
|
||||||
|
snd_pcm_hw_params_alloca(&hw);
|
||||||
|
if (snd_pcm_hw_params_any(ao->userptr, hw) < 0) {
|
||||||
|
error("initialize_device(): no configuration available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_hw_params_set_access(ao->userptr, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
|
||||||
|
error("initialize_device(): device does not support interleaved access");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
format = SND_PCM_FORMAT_UNKNOWN;
|
||||||
|
for (i = 0; i < NUM_FORMATS; ++i) {
|
||||||
|
if (ao->format == format_map[i].mpg123) {
|
||||||
|
format = format_map[i].alsa;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (format == SND_PCM_FORMAT_UNKNOWN) {
|
||||||
|
error1("initialize_device(): invalid sample format %d", ao->format);
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_hw_params_set_format(ao->userptr, hw, format) < 0) {
|
||||||
|
error1("initialize_device(): cannot set format %s", snd_pcm_format_name(format));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_hw_params_set_channels(ao->userptr, hw, ao->channels) < 0) {
|
||||||
|
error1("initialize_device(): cannot set %d channels", ao->channels);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rate = ao->rate;
|
||||||
|
if (snd_pcm_hw_params_set_rate_near(ao->userptr, hw, &rate, NULL) < 0) {
|
||||||
|
error1("initialize_device(): cannot set rate %u", rate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!rates_match(ao->rate, rate)) {
|
||||||
|
error2("initialize_device(): rate %ld not available, using %u", ao->rate, rate);
|
||||||
|
/* return -1; */
|
||||||
|
}
|
||||||
|
buffer_size = rate * BUFFER_LENGTH;
|
||||||
|
if (snd_pcm_hw_params_set_buffer_size_near(ao->userptr, hw, &buffer_size) < 0) {
|
||||||
|
error("initialize_device(): cannot set buffer size");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
period_size = buffer_size / 4;
|
||||||
|
if (snd_pcm_hw_params_set_period_size_near(ao->userptr, hw, &period_size, NULL) < 0) {
|
||||||
|
error("initialize_device(): cannot set period size");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_hw_params(ao->userptr, hw) < 0) {
|
||||||
|
error("initialize_device(): cannot set hw params");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_pcm_sw_params_alloca(&sw);
|
||||||
|
if (snd_pcm_sw_params_current(ao->userptr, sw) < 0) {
|
||||||
|
error("initialize_device(): cannot get sw params");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* start playing after the first write */
|
||||||
|
if (snd_pcm_sw_params_set_start_threshold(ao->userptr, sw, 1) < 0) {
|
||||||
|
error("initialize_device(): cannot set start threshold");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* wake up on every interrupt */
|
||||||
|
if (snd_pcm_sw_params_set_avail_min(ao->userptr, sw, 1) < 0) {
|
||||||
|
error("initialize_device(): cannot set min available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* always write as many frames as possible */
|
||||||
|
if (snd_pcm_sw_params_set_xfer_align(ao->userptr, sw, 1) < 0) {
|
||||||
|
error("initialize_device(): cannot set transfer alignment");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_sw_params(ao->userptr, sw) < 0) {
|
||||||
|
error("initialize_device(): cannot set sw params");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int open_alsa(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
const char *pcm_name;
|
||||||
|
snd_pcm_t *pcm;
|
||||||
|
|
||||||
|
pcm_name = ao->device ? ao->device : "default";
|
||||||
|
if (snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||||
|
error1("cannot open device %s", pcm_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ao->userptr = pcm;
|
||||||
|
if (ao->format != -1) {
|
||||||
|
/* we're going to play: initalize sample format */
|
||||||
|
return initialize_device(ao);
|
||||||
|
} else {
|
||||||
|
/* query mode; sample format will be set for each query */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_formats_alsa(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
snd_pcm_hw_params_t *hw;
|
||||||
|
unsigned int rate;
|
||||||
|
int supported_formats, i;
|
||||||
|
|
||||||
|
snd_pcm_hw_params_alloca(&hw);
|
||||||
|
if (snd_pcm_hw_params_any(ao->userptr, hw) < 0) {
|
||||||
|
error("get_formats_alsa(): no configuration available");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (snd_pcm_hw_params_set_access(ao->userptr, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
|
||||||
|
return -1;
|
||||||
|
if (snd_pcm_hw_params_set_channels(ao->userptr, hw, ao->channels) < 0)
|
||||||
|
return 0;
|
||||||
|
rate = ao->rate;
|
||||||
|
if (snd_pcm_hw_params_set_rate_near(ao->userptr, hw, &rate, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
if (!rates_match(ao->rate, rate))
|
||||||
|
return 0;
|
||||||
|
supported_formats = 0;
|
||||||
|
for (i = 0; i < NUM_FORMATS; ++i) {
|
||||||
|
if (snd_pcm_hw_params_test_format(ao->userptr, hw, format_map[i].alsa) == 0)
|
||||||
|
supported_formats |= format_map[i].mpg123;
|
||||||
|
}
|
||||||
|
return supported_formats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_alsa(audio_output_t *ao, unsigned char *buf, int bytes)
|
||||||
|
{
|
||||||
|
snd_pcm_uframes_t frames;
|
||||||
|
snd_pcm_sframes_t written;
|
||||||
|
|
||||||
|
frames = snd_pcm_bytes_to_frames(ai->handle, bytes);
|
||||||
|
written = snd_pcm_writei(ai->handle, buf, frames);
|
||||||
|
if (written == -EINTR) /* interrupted system call */
|
||||||
|
written = 0;
|
||||||
|
else if (written == -EPIPE) { /* underrun */
|
||||||
|
if (snd_pcm_prepare(ai->handle) >= 0)
|
||||||
|
written = snd_pcm_writei(ai->handle, buf, frames);
|
||||||
|
}
|
||||||
|
if (written >= 0)
|
||||||
|
return snd_pcm_frames_to_bytes(ao->userptr, written);
|
||||||
|
else
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_alsa(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
/* is this the optimal solution? - we should figure out what we really whant from this function */
|
||||||
|
snd_pcm_drop(ao->userptr);
|
||||||
|
snd_pcm_prepare(ao->userptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_alsa(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
if(ao->userptr != NULL) /* be really generous for being called without any device opening */
|
||||||
|
{
|
||||||
|
if (snd_pcm_state(ao->userptr) == SND_PCM_STATE_RUNNING)
|
||||||
|
snd_pcm_drain(ao->userptr);
|
||||||
|
return snd_pcm_close(ao->userptr);
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_alsa(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_alsa;
|
||||||
|
ao->flush = flush_alsa;
|
||||||
|
ao->write = write_alsa;
|
||||||
|
ao->get_formats = get_formats_alsa;
|
||||||
|
ao->close = close_alsa;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "alsa",
|
||||||
|
/* description */ "Output audio using Advanced Linux Sound Architecture (ALSA).",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_alsa,
|
||||||
|
};
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int card=0,device=0;
|
int card=0,device=0;
|
||||||
@@ -42,9 +42,9 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
if(!ai)
|
if(!ai)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(ai->device) { /* parse ALSA device name */
|
if(ao->device) { /* parse ALSA device name */
|
||||||
if(strchr(ai->device,':')) { /* card with device */
|
if(strchr(ao->device,':')) { /* card with device */
|
||||||
strncpy(scard, ai->device, sizeof(scard)-1);
|
strncpy(scard, ao->device, sizeof(scard)-1);
|
||||||
scard[sizeof(scard)-1] = '\0';
|
scard[sizeof(scard)-1] = '\0';
|
||||||
if (strchr(scard,':')) *strchr(scard,':') = '\0';
|
if (strchr(scard,':')) *strchr(scard,':') = '\0';
|
||||||
card = snd_card_name(scard);
|
card = snd_card_name(scard);
|
||||||
@@ -52,9 +52,9 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
fprintf(stderr, "wrong soundcard number: %s\n", scard);
|
fprintf(stderr, "wrong soundcard number: %s\n", scard);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
strncpy(sdevice, strchr(ai->device, ':') + 1, sizeof(sdevice)-1);
|
strncpy(sdevice, strchr(ao->device, ':') + 1, sizeof(sdevice)-1);
|
||||||
} else {
|
} else {
|
||||||
strncpy(sdevice, ai->device, sizeof(sdevice)-1);
|
strncpy(sdevice, ao->device, sizeof(sdevice)-1);
|
||||||
}
|
}
|
||||||
sdevice[sizeof(sdevice)-1] = '\0';
|
sdevice[sizeof(sdevice)-1] = '\0';
|
||||||
device = atoi(sdevice);
|
device = atoi(sdevice);
|
||||||
@@ -65,7 +65,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open the ALSA device
|
// Open the ALSA device
|
||||||
if((err=snd_pcm_open(&ai->handle, card, device, SND_PCM_OPEN_PLAYBACK)) < 0 )
|
if((err=snd_pcm_open(&ao->handle, card, device, SND_PCM_OPEN_PLAYBACK)) < 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "open failed: %s\n", snd_strerror(err));
|
fprintf(stderr, "open failed: %s\n", snd_strerror(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -81,38 +81,38 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void audio_set_playback_format(struct audio_info_struct *ai)
|
static void audio_set_playback_format(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
snd_pcm_format_t alsa_format;
|
snd_pcm_format_t alsa_format;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
alsa_format.rat = ai->rate;
|
alsa_format.rat = ao->rate;
|
||||||
alsa_format.channels = ai->channels;
|
alsa_format.channels = ao->channels;
|
||||||
|
|
||||||
switch(ai->format)
|
switch(ao->format)
|
||||||
{
|
{
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
default:
|
default:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_S16_NE;
|
ao->alsa_format.format=SND_PCM_SFMT_S16_NE;
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_UNSIGNED_8:
|
case AUDIO_FORMAT_UNSIGNED_8:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_U8;
|
ao->alsa_format.format=SND_PCM_SFMT_U8;
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_SIGNED_8:
|
case AUDIO_FORMAT_SIGNED_8:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_S8;
|
ao->alsa_format.format=SND_PCM_SFMT_S8;
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_ULAW_8:
|
case AUDIO_FORMAT_ULAW_8:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_MU_LAW;
|
ao->alsa_format.format=SND_PCM_SFMT_MU_LAW;
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_ALAW_8:
|
case AUDIO_FORMAT_ALAW_8:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_A_LAW;
|
ao->alsa_format.format=SND_PCM_SFMT_A_LAW;
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_UNSIGNED_16:
|
case AUDIO_FORMAT_UNSIGNED_16:
|
||||||
ai->alsa_format.format=SND_PCM_SFMT_U16_NE;
|
ao->alsa_format.format=SND_PCM_SFMT_U16_NE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((err=snd_pcm_playback_format(ai->handle, &alsa_format)) < 0 )
|
if((err=snd_pcm_playback_format(ao->handle, &alsa_format)) < 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "snd_pcm_playback_format failed: %s\n", snd_strerror(err));
|
fprintf(stderr, "snd_pcm_playback_format failed: %s\n", snd_strerror(err));
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -120,13 +120,13 @@ static void audio_set_playback_format(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void audio_set_playback_params(struct audio_info_struct *ai)
|
static void audio_set_playback_params(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
snd_pcm_playback_info_t pi;
|
snd_pcm_playback_info_t pi;
|
||||||
snd_pcm_playback_params_t pp;
|
snd_pcm_playback_params_t pp;
|
||||||
|
|
||||||
if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
|
if((err=snd_pcm_playback_info(ao->handle, &pi)) < 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
|
fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
|
||||||
return; /* not fatal error */
|
return; /* not fatal error */
|
||||||
@@ -139,7 +139,7 @@ static void audio_set_playback_params(struct audio_info_struct *ai)
|
|||||||
pp.fragments_max = -1;
|
pp.fragments_max = -1;
|
||||||
pp.fragments_room = 1;
|
pp.fragments_room = 1;
|
||||||
|
|
||||||
if((err=snd_pcm_playback_params(ai->handle, &pp)) < 0 )
|
if((err=snd_pcm_playback_params(ao->handle, &pp)) < 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "playback params failed: %s\n", snd_strerror(err));
|
fprintf(stderr, "playback params failed: %s\n", snd_strerror(err));
|
||||||
return; /* not fatal error */
|
return; /* not fatal error */
|
||||||
@@ -149,7 +149,7 @@ static void audio_set_playback_params(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int i, err;
|
int i, err;
|
||||||
int fmt = -1;
|
int fmt = -1;
|
||||||
@@ -166,7 +166,7 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
SND_PCM_FMT_MU_LAW, SND_PCM_FMT_A_LAW
|
SND_PCM_FMT_MU_LAW, SND_PCM_FMT_A_LAW
|
||||||
};
|
};
|
||||||
|
|
||||||
if((err=snd_pcm_playback_info(ai->handle, &pi)) < 0 )
|
if((err=snd_pcm_playback_info(ao->handle, &pi)) < 0 )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
|
fprintf(stderr, "playback info failed: %s\n", snd_strerror(err));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -183,23 +183,23 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret=snd_pcm_write(ai->handle, buf, len);
|
ret=snd_pcm_write(ao->handle, buf, len);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ret = snd_pcm_close(ai->handle);
|
ret = snd_pcm_close(ao->handle);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_macosx: audio output on MacOS X
|
coreaudio: audio output on MacOS X
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the GPL 2
|
copyright ?-2006 by the mpg123 project - free software under the terms of the GPL 2
|
||||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#include <AudioToolbox/AudioToolbox.h>
|
#include <AudioToolbox/AudioToolbox.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define FIFO_DURATION (0.5f)
|
#define FIFO_DURATION (0.5f) /* Duration of the ring buffer in seconds */
|
||||||
|
|
||||||
|
|
||||||
struct anEnv
|
struct anEnv
|
||||||
@@ -38,8 +38,6 @@ struct anEnv
|
|||||||
sfifo_t fifo;
|
sfifo_t fifo;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct anEnv *env=NULL;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static OSStatus playProc(AudioConverterRef inAudioConverter,
|
static OSStatus playProc(AudioConverterRef inAudioConverter,
|
||||||
@@ -48,8 +46,10 @@ static OSStatus playProc(AudioConverterRef inAudioConverter,
|
|||||||
AudioStreamPacketDescription **outDataPacketDescription,
|
AudioStreamPacketDescription **outDataPacketDescription,
|
||||||
void* inClientData)
|
void* inClientData)
|
||||||
{
|
{
|
||||||
|
struct anEnv *env = (struct anEnv *)inClientData;
|
||||||
long n;
|
long n;
|
||||||
|
|
||||||
|
|
||||||
if(env->last_buffer) {
|
if(env->last_buffer) {
|
||||||
env->play_done = 1;
|
env->play_done = 1;
|
||||||
return noErr;
|
return noErr;
|
||||||
@@ -94,18 +94,18 @@ static OSStatus convertProc(void *inRefCon, AudioUnitRenderActionFlags *inAction
|
|||||||
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
|
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
|
||||||
UInt32 inNumFrames, AudioBufferList *ioData)
|
UInt32 inNumFrames, AudioBufferList *ioData)
|
||||||
{
|
{
|
||||||
|
AudioStreamPacketDescription* outPacketDescription = NULL;
|
||||||
|
struct anEnv *env = (struct anEnv *)inRefCon;
|
||||||
OSStatus err= noErr;
|
OSStatus err= noErr;
|
||||||
void *inInputDataProcUserData=NULL;
|
|
||||||
AudioStreamPacketDescription* outPacketDescription =NULL;
|
|
||||||
|
|
||||||
err = AudioConverterFillComplexBuffer(env->converter, playProc, inInputDataProcUserData, &inNumFrames, ioData, outPacketDescription);
|
err = AudioConverterFillComplexBuffer(env->converter, playProc, inRefCon, &inNumFrames, ioData, outPacketDescription);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open_coreaudio(audio_output_t *ao)
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
{
|
||||||
|
struct anEnv *env = NULL;
|
||||||
UInt32 size;
|
UInt32 size;
|
||||||
ComponentDescription desc;
|
ComponentDescription desc;
|
||||||
Component comp;
|
Component comp;
|
||||||
@@ -115,15 +115,16 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
Boolean outWritable;
|
Boolean outWritable;
|
||||||
|
|
||||||
/* Allocate memory for data structure */
|
/* Allocate memory for data structure */
|
||||||
if (!env) {
|
if (!ao->userptr) {
|
||||||
env = (struct anEnv*)malloc( sizeof( struct anEnv ) );
|
ao->userptr = malloc( sizeof( struct anEnv ) );
|
||||||
if (!env) {
|
if (!ao->userptr) {
|
||||||
error("failed to malloc memory for 'struct anEnv'");
|
error("failed to malloc memory for 'struct anEnv'");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize our environment */
|
/* Initialize our environment */
|
||||||
|
env = (struct anEnv *)ao->userptr;
|
||||||
env->play = 0;
|
env->play = 0;
|
||||||
env->buffer = NULL;
|
env->buffer = NULL;
|
||||||
env->buffer_size = 0;
|
env->buffer_size = 0;
|
||||||
@@ -167,9 +168,9 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Specify the input PCM format */
|
/* Specify the input PCM format */
|
||||||
env->channels = ai->channels;
|
env->channels = ao->channels;
|
||||||
inFormat.mSampleRate = ai->rate;
|
inFormat.mSampleRate = ao->rate;
|
||||||
inFormat.mChannelsPerFrame = ai->channels;
|
inFormat.mChannelsPerFrame = ao->channels;
|
||||||
inFormat.mBitsPerChannel = 16;
|
inFormat.mBitsPerChannel = 16;
|
||||||
inFormat.mBytesPerPacket = 2*inFormat.mChannelsPerFrame;
|
inFormat.mBytesPerPacket = 2*inFormat.mChannelsPerFrame;
|
||||||
inFormat.mFramesPerPacket = 1;
|
inFormat.mFramesPerPacket = 1;
|
||||||
@@ -185,7 +186,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
/* Add our callback - but don't start it yet */
|
/* Add our callback - but don't start it yet */
|
||||||
memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));
|
memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));
|
||||||
renderCallback.inputProc = convertProc;
|
renderCallback.inputProc = convertProc;
|
||||||
renderCallback.inputProcRefCon = 0;
|
renderCallback.inputProcRefCon = ao->userptr;
|
||||||
if(AudioUnitSetProperty(env->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct))) {
|
if(AudioUnitSetProperty(env->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct))) {
|
||||||
error("AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed");
|
error("AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed");
|
||||||
return(-1);
|
return(-1);
|
||||||
@@ -193,14 +194,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
|
|
||||||
/* Open an audio I/O stream and create converter */
|
/* Open an audio I/O stream and create converter */
|
||||||
if (ai->rate > 0 && ai->channels >0 ) {
|
if (ao->rate > 0 && ao->channels >0 ) {
|
||||||
int ringbuffer_len;
|
int ringbuffer_len;
|
||||||
|
|
||||||
if(AudioConverterNew(&inFormat, &outFormat, &(env->converter))) {
|
if(AudioConverterNew(&inFormat, &outFormat, &(env->converter))) {
|
||||||
error("AudioConverterNew failed");
|
error("AudioConverterNew failed");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
if(ai->channels == 1) {
|
if(ao->channels == 1) {
|
||||||
SInt32 channelMap[2] = { 0, 0 };
|
SInt32 channelMap[2] = { 0, 0 };
|
||||||
if(AudioConverterSetProperty(env->converter, kAudioConverterChannelMap, sizeof(channelMap), channelMap)) {
|
if(AudioConverterSetProperty(env->converter, kAudioConverterChannelMap, sizeof(channelMap), channelMap)) {
|
||||||
error("AudioConverterSetProperty(kAudioConverterChannelMap) failed");
|
error("AudioConverterSetProperty(kAudioConverterChannelMap) failed");
|
||||||
@@ -209,7 +210,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise FIFO */
|
/* Initialise FIFO */
|
||||||
ringbuffer_len = ai->rate * FIFO_DURATION * sizeof(short) *ai->channels;
|
ringbuffer_len = ao->rate * FIFO_DURATION * sizeof(short) *ao->channels;
|
||||||
debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);
|
debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);
|
||||||
sfifo_init( &env->fifo, ringbuffer_len );
|
sfifo_init( &env->fifo, ringbuffer_len );
|
||||||
|
|
||||||
@@ -218,16 +219,15 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_formats_coreaudio(audio_output_t *ao)
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
|
||||||
{
|
{
|
||||||
/* Only support Signed 16-bit output */
|
/* Only support Signed 16-bit output */
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_coreaudio(audio_output_t *ao, unsigned char *buf, int len)
|
||||||
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len)
|
|
||||||
{
|
{
|
||||||
|
struct anEnv *env = (struct anEnv *)ao->userptr;
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
/* If there is no room, then sleep for half the length of the FIFO */
|
/* If there is no room, then sleep for half the length of the FIFO */
|
||||||
@@ -255,8 +255,10 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
static int close_coreaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
|
struct anEnv *env = (struct anEnv *)ao->userptr;
|
||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
env->decode_done = 1;
|
env->decode_done = 1;
|
||||||
while(!env->play_done && env->play) usleep(10000);
|
while(!env->play_done && env->play) usleep(10000);
|
||||||
@@ -275,14 +277,15 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
/* Free environment data structure */
|
/* Free environment data structure */
|
||||||
free(env);
|
free(env);
|
||||||
env=NULL;
|
ao->userptr=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
static void flush_coreaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
|
struct anEnv *env = (struct anEnv *)ao->userptr;
|
||||||
|
|
||||||
/* Stop playback */
|
/* Stop playback */
|
||||||
if(AudioOutputUnitStop(env->outputUnit)) {
|
if(AudioOutputUnitStop(env->outputUnit)) {
|
||||||
@@ -293,3 +296,36 @@ void audio_queueflush(struct audio_info_struct *ai)
|
|||||||
/* Empty out the ring buffer */
|
/* Empty out the ring buffer */
|
||||||
sfifo_flush( &env->fifo );
|
sfifo_flush( &env->fifo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_coreaudio(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_coreaudio;
|
||||||
|
ao->flush = flush_coreaudio;
|
||||||
|
ao->write = write_coreaudio;
|
||||||
|
ao->get_formats = get_formats_coreaudio;
|
||||||
|
ao->close = close_coreaudio;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "coreaudio",
|
||||||
|
/* description */ "Output audio using Mac OS X's CoreAudio.",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_coreaudio,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
70
src/output/dummy.c
Normal file
70
src/output/dummy.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
dummy: dummy audio output
|
||||||
|
|
||||||
|
copyright ?-2006 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
|
||||||
|
static int open_dummy(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
debug("open_dummy()");
|
||||||
|
warning("Using the dummy audio output module.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_formats_dummy(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
debug("get_formats_dummy()");
|
||||||
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_dummy(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
|
{
|
||||||
|
debug("write_dummy()");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_dummy(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
debug("flush_dummy()");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_dummy(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
debug("close_dummy()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_dummy(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_dummy;
|
||||||
|
ao->flush = flush_dummy;
|
||||||
|
ao->write = write_dummy;
|
||||||
|
ao->get_formats = get_formats_dummy;
|
||||||
|
ao->close = close_dummy;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "dummy",
|
||||||
|
/* description */ "Dummy audio output - does not output audio.",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_dummy,
|
||||||
|
};
|
||||||
|
|
||||||
160
src/output/esd.c
Normal file
160
src/output/esd.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
esd: audio output for ESounD (highly untested nowadays (?))
|
||||||
|
|
||||||
|
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
initially written by Eric B. Mitchell ("esd port" should be this file...)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
|
||||||
|
#ifdef SOLARIS
|
||||||
|
#include <stropts.h>
|
||||||
|
#include <sys/conf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static unsigned esd_rate = 0, esd_format = 0, esd_channels = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static int open_esound(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
esd_format_t format = ESD_STREAM | ESD_PLAY;
|
||||||
|
|
||||||
|
if (!esd_rate)
|
||||||
|
{
|
||||||
|
int esd;
|
||||||
|
esd_server_info_t *info;
|
||||||
|
esd_format_t fmt;
|
||||||
|
|
||||||
|
if ((esd = esd_open_sound(NULL)) >= 0)
|
||||||
|
{
|
||||||
|
info = esd_get_server_info(esd);
|
||||||
|
esd_rate = info->rate;
|
||||||
|
fmt = info->format;
|
||||||
|
esd_free_server_info(info);
|
||||||
|
esd_close(esd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esd_rate = esd_audio_rate;
|
||||||
|
fmt = esd_audio_format;
|
||||||
|
}
|
||||||
|
esd_format = AUDIO_FORMAT_UNSIGNED_8;
|
||||||
|
|
||||||
|
if ((fmt & ESD_MASK_BITS) == ESD_BITS16)
|
||||||
|
esd_format |= AUDIO_FORMAT_SIGNED_16;
|
||||||
|
esd_channels = fmt & ESD_MASK_CHAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ao->format == -1)
|
||||||
|
ao->format = esd_format;
|
||||||
|
else if (!(ao->format & esd_format))
|
||||||
|
{
|
||||||
|
error1("Unsupported audio format: %d\n", ao->format);
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ao->format & AUDIO_FORMAT_SIGNED_16)
|
||||||
|
format |= ESD_BITS16;
|
||||||
|
else if (ao->format & AUDIO_FORMAT_UNSIGNED_8)
|
||||||
|
format |= ESD_BITS8;
|
||||||
|
else assert(0);
|
||||||
|
|
||||||
|
if (ao->channels == -1) ao->channels = 2;
|
||||||
|
else if (ao->channels <= 0 || ao->channels > esd_channels)
|
||||||
|
{
|
||||||
|
error1("Unsupported no of channels: %d\n", ao->channels);
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ao->channels == 1)
|
||||||
|
format |= ESD_MONO;
|
||||||
|
else if (ao->channels == 2)
|
||||||
|
format |= ESD_STEREO;
|
||||||
|
else assert(0);
|
||||||
|
|
||||||
|
if (ao->rate == -1) ao->rate = esd_rate;
|
||||||
|
else if (ao->rate > esd_rate)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ao->fn = esd_play_stream_fallback(format, ao->rate, ao->device, "mpg123");
|
||||||
|
return (ao->fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_formats_esound (audio_output_t *ao)
|
||||||
|
{
|
||||||
|
if (0 < ao->channels && ao->channels <= esd_channels
|
||||||
|
&& 0 < ao->rate && ao->rate <= esd_rate)
|
||||||
|
{
|
||||||
|
return esd_format;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_esound(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
|
{
|
||||||
|
return write(ao->fn,buf,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_esound(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
close (ao->fn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SOLARIS
|
||||||
|
static void flush_esound (audio_output_t *ao)
|
||||||
|
{
|
||||||
|
ioctl (ao->fn, I_FLUSH, FLUSHRW);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef NETBSD
|
||||||
|
static void flush_esound (audio_output_t *ao)
|
||||||
|
{
|
||||||
|
ioctl (ao->fn, AUDIO_FLUSH, 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Dunno what to do on Linux and Cygwin, but the func must be at least defined! */
|
||||||
|
static void flush_esound (audio_output_t *ao)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int init_esound(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_esound;
|
||||||
|
ao->flush = flush_esound;
|
||||||
|
ao->write = write_esound;
|
||||||
|
ao->get_formats = get_formats_esound;
|
||||||
|
ao->close = close_esound;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "esound",
|
||||||
|
/* description */ "Output audio using ESounD (The Enlightened Sound Daemon).",
|
||||||
|
/* revision */ "$Rev$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_esound,
|
||||||
|
};
|
||||||
153
src/output/hp.c
Normal file
153
src/output/hp.c
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
hp: audio output for HP-UX
|
||||||
|
|
||||||
|
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
initially written by Michael Hipp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/audio.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int audio_set_rate(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
if(ao->rate >= 0) {
|
||||||
|
return ioctl(ao->fn,AUDIO_SET_SAMPLE_RATE,ao->rate);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_set_channels(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
if(ao->channels<0) return 0;
|
||||||
|
return ioctl(ao->fn,AUDIO_SET_CHANNELS,ao->channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_set_format(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int fmt;
|
||||||
|
|
||||||
|
switch(ao->format) {
|
||||||
|
case -1:
|
||||||
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
|
default:
|
||||||
|
fmt = AUDIO_FORMAT_LINEAR16BIT;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_UNSIGNED_8:
|
||||||
|
fprintf(stderr,"unsigned 8 bit linear not supported\n");
|
||||||
|
return -1;
|
||||||
|
case AUDIO_FORMAT_SIGNED_8:
|
||||||
|
fprintf(stderr,"signed 8 bit linear not supported\n");
|
||||||
|
return -1;
|
||||||
|
case AUDIO_FORMAT_ALAW_8:
|
||||||
|
fmt = AUDIO_FORMAT_ALAW;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_ULAW_8:
|
||||||
|
fmt = AUDIO_FORMAT_ULAW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ioctl(ao->fn,AUDIO_SET_DATA_FORMAT,fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_get_formats(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_reset_parameters(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = audio_set_format(ai);
|
||||||
|
if(ret >= 0)
|
||||||
|
ret = audio_set_channels(ai);
|
||||||
|
if(ret >= 0)
|
||||||
|
ret = audio_set_rate(ai);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int audio_open(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
struct audio_describe ades;
|
||||||
|
struct audio_gain again;
|
||||||
|
int i,audio;
|
||||||
|
|
||||||
|
ao->fn = open("/dev/audio",O_RDWR);
|
||||||
|
|
||||||
|
if(ao->fn < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
ioctl(ao->fn,AUDIO_DESCRIBE,&ades);
|
||||||
|
|
||||||
|
if(ao->gain != -1)
|
||||||
|
{
|
||||||
|
if(ao->gain > ades.max_transmit_gain)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"your gainvalue was to high -> set to maximum.\n");
|
||||||
|
ao->gain = ades.max_transmit_gain;
|
||||||
|
}
|
||||||
|
if(ao->gain < ades.min_transmit_gain)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"your gainvalue was to low -> set to minimum.\n");
|
||||||
|
ao->gain = ades.min_transmit_gain;
|
||||||
|
}
|
||||||
|
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
||||||
|
ioctl(ao->fn,AUDIO_GET_GAINS,&again);
|
||||||
|
again.cgain[0].transmit_gain = ao->gain;
|
||||||
|
again.cgain[1].transmit_gain = ao->gain;
|
||||||
|
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
||||||
|
ioctl(ao->fn,AUDIO_SET_GAINS,&again);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ao->output != -1)
|
||||||
|
{
|
||||||
|
if(ao->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||||
|
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_SPEAKER);
|
||||||
|
else if(ao->output & AUDIO_OUT_HEADPHONES)
|
||||||
|
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_HEADPHONE);
|
||||||
|
else if(ao->output & AUDIO_OUT_LINE_OUT)
|
||||||
|
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ao->rate == -1)
|
||||||
|
ao->rate = 44100;
|
||||||
|
|
||||||
|
for(i=0;i<ades.nrates;i++)
|
||||||
|
{
|
||||||
|
if(ao->rate == ades.sample_rate[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i == ades.nrates)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Can't set sample-rate to %ld.\n",ao->rate);
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(audio_reset_parameters(ai) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ao->fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
|
{
|
||||||
|
return write(ao->fn,buf,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int audio_close(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
close (ao->fn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_queueflush(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_jack.c: audio output via JACK
|
jack: audio output via JACK Audio Connection Kit
|
||||||
|
|
||||||
copyright 2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright 2006 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
|
||||||
@@ -31,7 +31,7 @@ static jack_handle_t* alloc_jack_handle()
|
|||||||
|
|
||||||
handle = malloc(sizeof(jack_handle_t));
|
handle = malloc(sizeof(jack_handle_t));
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
error("audio_open(): Failed to allocate memory for our handle.");
|
error("Failed to allocate memory for our handle.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +72,7 @@ static void free_jack_handle( jack_handle_t* handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int process_callback( jack_nframes_t nframes, void *arg )
|
||||||
process_callback( jack_nframes_t nframes, void *arg )
|
|
||||||
{
|
{
|
||||||
jack_handle_t* handle = (jack_handle_t*)arg;
|
jack_handle_t* handle = (jack_handle_t*)arg;
|
||||||
size_t to_read = sizeof (jack_default_audio_sample_t) * nframes;
|
size_t to_read = sizeof (jack_default_audio_sample_t) * nframes;
|
||||||
@@ -92,25 +91,24 @@ process_callback( jack_nframes_t nframes, void *arg )
|
|||||||
bzero( buf+len, to_read - len );
|
bzero( buf+len, to_read - len );
|
||||||
|
|
||||||
/*if (len < to_read)*/
|
/*if (len < to_read)*/
|
||||||
/* fprintf(stderr, "failed to read from ring buffer %d\n",c);*/
|
/* error1("failed to read from ring buffer %d",c);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Success*/
|
/* Success*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void shutdown_callback( void *arg )
|
||||||
shutdown_callback( void *arg )
|
|
||||||
{
|
{
|
||||||
/* jack_handle_t* handle = (jack_handle_t*)arg; */
|
/* jack_handle_t* handle = (jack_handle_t*)arg; */
|
||||||
|
|
||||||
fprintf(stderr, "shutdown_callback()\n");
|
debug("shutdown_callback()");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* crude way of automatically connecting up jack ports */
|
/* crude way of automatically connecting up jack ports */
|
||||||
/* 0 on error */
|
/* 0 on error */
|
||||||
int autoconnect_jack_ports( jack_handle_t* handle )
|
static int autoconnect_jack_ports( jack_handle_t* handle )
|
||||||
{
|
{
|
||||||
const char **all_ports;
|
const char **all_ports;
|
||||||
unsigned int ch=0;
|
unsigned int ch=0;
|
||||||
@@ -129,7 +127,7 @@ int autoconnect_jack_ports( jack_handle_t* handle )
|
|||||||
const char* in = jack_port_name( handle->ports[ch] );
|
const char* in = jack_port_name( handle->ports[ch] );
|
||||||
const char* out = all_ports[i];
|
const char* out = all_ports[i];
|
||||||
|
|
||||||
fprintf(stderr, "Connecting %s to %s\n", in, out);
|
debug2("Connecting %s to %sesound", in, out);
|
||||||
|
|
||||||
if ((err = jack_connect(handle->client, in, out)) != 0) {
|
if ((err = jack_connect(handle->client, in, out)) != 0) {
|
||||||
error1("connect_jack_ports(): failed to jack_connect() ports: %d",err);
|
error1("connect_jack_ports(): failed to jack_connect() ports: %d",err);
|
||||||
@@ -145,36 +143,54 @@ int autoconnect_jack_ports( jack_handle_t* handle )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int connect_jack_ports( jack_handle_t* handle, const char *dev )
|
static int connect_jack_ports( jack_handle_t* handle, const char *dev )
|
||||||
{
|
{
|
||||||
if (dev==NULL || strcmp(dev, "auto")==0) {
|
if (dev==NULL || strcmp(dev, "auto")==0) {
|
||||||
return autoconnect_jack_ports( handle );
|
return autoconnect_jack_ports( handle );
|
||||||
} else if (strcmp(dev, "none")==0) {
|
} else if (strcmp(dev, "none")==0) {
|
||||||
fprintf(stderr, "Not connecting up jack ports as requested.\n");
|
warning("Not connecting up jack ports as requested.");
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Sorry I don't know how to connect up ports yet.\n");
|
warning("Sorry I don't know how to connect up ports yet.");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
static int close_jack(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||||
|
|
||||||
|
debug("close_jack().");
|
||||||
|
|
||||||
|
/* Close and shutdown*/
|
||||||
|
if (handle) {
|
||||||
|
free_jack_handle( handle );
|
||||||
|
ao->userptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int open_jack(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
char client_name[255];
|
char client_name[255];
|
||||||
jack_handle_t *handle=NULL;
|
jack_handle_t *handle=NULL;
|
||||||
|
jack_options_t jopt = JackNullOption;
|
||||||
|
jack_status_t jstat = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if(!ai) return -1;
|
if(!ao) return -1;
|
||||||
|
|
||||||
/* Return if already open*/
|
/* Return if already open*/
|
||||||
if (ai->handle) {
|
if (ao->userptr) {
|
||||||
fprintf(stderr, "audio_open(): error, already open\n");
|
error("audio device is already open.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For some reason we get called with format=-1 initially*/
|
/* For some reason we get called with format=-1 initially*/
|
||||||
/* Just prentend that it didn't happen*/
|
/* Just prentend that it didn't happen*/
|
||||||
if (ai->format==-1) {
|
if (ao->format==-1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,51 +199,54 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
/* Create some storage for ourselves*/
|
/* Create some storage for ourselves*/
|
||||||
if((handle = alloc_jack_handle()) == NULL) return -1;
|
if((handle = alloc_jack_handle()) == NULL) return -1;
|
||||||
|
|
||||||
ai->handle = (void*)handle;
|
ao->userptr = (void*)handle;
|
||||||
|
|
||||||
/* Register with Jack*/
|
/* Register with Jack*/
|
||||||
snprintf(client_name, 255, "mpg123-%d", getpid());
|
snprintf(client_name, 255, "mpg123-%d", getpid());
|
||||||
if ((handle->client = jack_client_new(client_name)) == 0) {
|
if ((handle->client = jack_client_open(client_name, jopt, &jstat)) == 0) {
|
||||||
error("JACK server not running?");
|
error1("Failed to open jack client: 0x%x", jstat);
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
printf("Registering as JACK client %s.\n", client_name);
|
|
||||||
|
/* Display the unique client name allocated to us */
|
||||||
|
printf("Registered as JACK client %s.\n",
|
||||||
|
jack_get_client_name( handle->client ) );
|
||||||
|
|
||||||
|
|
||||||
/* Check the sample rate is correct*/
|
/* Check the sample rate is correct*/
|
||||||
if (jack_get_sample_rate( handle->client ) != (jack_nframes_t)ai->rate) {
|
if (jack_get_sample_rate( handle->client ) != (jack_nframes_t)ao->rate) {
|
||||||
error("JACK Sample Rate is different to sample rate of file.");
|
error("JACK Sample Rate is different to sample rate of file.");
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Register ports with Jack*/
|
/* Register ports with Jack*/
|
||||||
handle->channels = ai->channels;
|
handle->channels = ao->channels;
|
||||||
if (handle->channels == 1) {
|
if (handle->channels == 1) {
|
||||||
if (!(handle->ports[0] = jack_port_register(handle->client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
if (!(handle->ports[0] = jack_port_register(handle->client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||||
{
|
{
|
||||||
error("Cannot register JACK output port 'mono'.");
|
error("Cannot register JACK output port 'mono'.");
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if (handle->channels == 2) {
|
} else if (handle->channels == 2) {
|
||||||
if (!(handle->ports[0] = jack_port_register(handle->client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
if (!(handle->ports[0] = jack_port_register(handle->client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||||
{
|
{
|
||||||
error("Cannot register JACK output port 'left'.");
|
error("Cannot register JACK output port 'left'.");
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!(handle->ports[1] = jack_port_register(handle->client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
if (!(handle->ports[1] = jack_port_register(handle->client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||||
{
|
{
|
||||||
error("Cannot register JACK output port 'right'.");
|
error("Cannot register JACK output port 'right'.");
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error1("audio_open(): invalid number of channels (%d).", handle->channels);
|
error1("invalid number of output channels (%d).", handle->channels);
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,14 +262,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
/* Activate client*/
|
/* Activate client*/
|
||||||
if (jack_activate(handle->client)) {
|
if (jack_activate(handle->client)) {
|
||||||
fprintf(stderr, "audio_open(): Can't activate client\n");
|
error("Can't activate client.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect up the portsm, return */
|
/* Connect up the portsm, return */
|
||||||
if(!connect_jack_ports( handle, ai->device ))
|
if(!connect_jack_ports( handle, ao->device ))
|
||||||
{
|
{
|
||||||
/* deregistering of ports will not work but should just fail, then, and let the rest clean up */
|
/* deregistering of ports will not work but should just fail, then, and let the rest clean up */
|
||||||
audio_close(ai);
|
close_jack(ao);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,24 +278,24 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
|
|
||||||
/* Jack is in fact 32-bit floats only */
|
/* Jack is in fact 32-bit floats only */
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
static int get_formats_jack(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len)
|
static int write_jack(audio_output_t *ao, unsigned char *buf, int len)
|
||||||
{
|
{
|
||||||
int c,n = 0;
|
int c,n = 0;
|
||||||
short* src = (short*)buf;
|
short* src = (short*)buf;
|
||||||
jack_handle_t *handle = (jack_handle_t*)ai->handle;
|
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||||
jack_nframes_t samples = len / 2 / handle->channels;
|
jack_nframes_t samples = len / 2 / handle->channels;
|
||||||
size_t tmp_size = samples * sizeof( jack_default_audio_sample_t );
|
size_t tmp_size = samples * sizeof( jack_default_audio_sample_t );
|
||||||
|
|
||||||
|
|
||||||
/* Sanity check that ring buffer is at least twice the size of the audio we just got*/
|
/* Sanity check that ring buffer is at least twice the size of the audio we just got*/
|
||||||
if (handle->rb_size/2 < len) {
|
if (handle->rb_size/2 < len) {
|
||||||
error("audio_play_samples(): ring buffer is less than twice the size of audio given.");
|
error("ring buffer is less than twice the size of audio given.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +310,7 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
/* Ensure the temporary buffer is big enough*/
|
/* Ensure the temporary buffer is big enough*/
|
||||||
handle->tmp_buffer = (jack_default_audio_sample_t*)realloc( handle->tmp_buffer, tmp_size);
|
handle->tmp_buffer = (jack_default_audio_sample_t*)realloc( handle->tmp_buffer, tmp_size);
|
||||||
if (!handle->tmp_buffer) {
|
if (!handle->tmp_buffer) {
|
||||||
error("audio_play_samples(): failed to realloc temporary buffer.");
|
error("failed to realloc temporary buffer.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +327,7 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
len = jack_ringbuffer_write(handle->rb[c], (char*)handle->tmp_buffer, tmp_size);
|
len = jack_ringbuffer_write(handle->rb[c], (char*)handle->tmp_buffer, tmp_size);
|
||||||
if (len < tmp_size)
|
if (len < tmp_size)
|
||||||
{
|
{
|
||||||
error("audio_play_samples(): failed to write to ring ruffer.");
|
error("failed to write to ring ruffer.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,31 +336,42 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
static void flush_jack(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
jack_handle_t *handle = (jack_handle_t*)ai->handle;
|
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||||
|
|
||||||
/*fprintf(stderr, "audio_close().\n");*/
|
|
||||||
|
|
||||||
/* Close and shutdown*/
|
|
||||||
if (handle) {
|
|
||||||
free_jack_handle( handle );
|
|
||||||
ai->handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
{
|
|
||||||
jack_handle_t *handle = (jack_handle_t*)ai->handle;
|
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
fprintf(stderr, "audio_queueflush().\n");
|
|
||||||
|
|
||||||
/* Reset the ring buffers*/
|
/* Reset the ring buffers*/
|
||||||
for(c=0; c<handle->channels; c++) {
|
for(c=0; c<handle->channels; c++) {
|
||||||
jack_ringbuffer_reset(handle->rb[c]);
|
jack_ringbuffer_reset(handle->rb[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int init_jack(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_jack;
|
||||||
|
ao->flush = flush_jack;
|
||||||
|
ao->write = write_jack;
|
||||||
|
ao->get_formats = get_formats_jack;
|
||||||
|
ao->close = close_jack;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "jack",
|
||||||
|
/* description */ "Output audio using JACK (JACK Audio Connection Kit).",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_jack,
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_libao.c: audio output via libao (now doing something like mpg321;-)
|
libao: audio output via libao
|
||||||
|
|
||||||
copyright 2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright 2006 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
|
||||||
@@ -13,25 +13,6 @@
|
|||||||
#include "mpg123.h"
|
#include "mpg123.h"
|
||||||
|
|
||||||
|
|
||||||
static int initialized=0;
|
|
||||||
|
|
||||||
static void audio_initialize()
|
|
||||||
{
|
|
||||||
if (!initialized) {
|
|
||||||
ao_initialize();
|
|
||||||
initialized=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void audio_shutdown()
|
|
||||||
{
|
|
||||||
if (initialized) {
|
|
||||||
ao_shutdown();
|
|
||||||
initialized=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(struct audio_info_struct *ai)
|
||||||
{
|
{
|
||||||
ao_device *device = NULL;
|
ao_device *device = NULL;
|
||||||
@@ -43,13 +24,13 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
if(!ai) return -1;
|
if(!ai) return -1;
|
||||||
|
|
||||||
/* Return if already open */
|
/* Return if already open */
|
||||||
if (ai->handle) {
|
if (ao->handle) {
|
||||||
fprintf(stderr, "audio_open(): error, already open\n");
|
fprintf(stderr, "audio_open(): error, already open\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Work out the sample size */
|
/* Work out the sample size */
|
||||||
switch (ai->format) {
|
switch (ao->format) {
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
format.bits = 16;
|
format.bits = 16;
|
||||||
break;
|
break;
|
||||||
@@ -65,29 +46,29 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "audio_open(): Unsupported Audio Format: %d\n", ai->format);
|
fprintf(stderr, "audio_open(): Unsupported Audio Format: %d\n", ao->format);
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set the reset of the format */
|
/* Set the reset of the format */
|
||||||
format.channels = ai->channels;
|
format.channels = ao->channels;
|
||||||
format.rate = ai->rate;
|
format.rate = ao->rate;
|
||||||
format.byte_format = AO_FMT_NATIVE;
|
format.byte_format = AO_FMT_NATIVE;
|
||||||
|
|
||||||
/* Initialize libao */
|
/* Initialize libao */
|
||||||
audio_initialize();
|
audio_initialize();
|
||||||
|
|
||||||
/* Choose the driver to use */
|
/* Choose the driver to use */
|
||||||
if (ai->device) {
|
if (ao->device) {
|
||||||
/* parse device:filename; remember to free stuff before bailing out */
|
/* parse device:filename; remember to free stuff before bailing out */
|
||||||
char* search_ptr;
|
char* search_ptr;
|
||||||
if( (search_ptr = strchr(ai->device, ':')) != NULL )
|
if( (search_ptr = strchr(ao->device, ':')) != NULL )
|
||||||
{
|
{
|
||||||
/* going to split up the info in new memory to preserve the original string */
|
/* going to split up the info in new memory to preserve the original string */
|
||||||
size_t devlen = search_ptr-ai->device+1;
|
size_t devlen = search_ptr-ao->device+1;
|
||||||
size_t filelen = strlen(ai->device)-devlen+1;
|
size_t filelen = strlen(ao->device)-devlen+1;
|
||||||
debug("going to allocate %lu:%lu bytes", (unsigned long)devlen, (unsigned long)filelen);
|
debug("going to allocate %lu:%lu bytes", (unsigned long)devlen, (unsigned long)filelen);
|
||||||
char* devicename = malloc(devlen*sizeof(char));
|
char* devicename = malloc(devlen*sizeof(char));
|
||||||
devicename[devlen-1] = 0;
|
devicename[devlen-1] = 0;
|
||||||
@@ -95,7 +76,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
filename[filelen-1] = 0;
|
filename[filelen-1] = 0;
|
||||||
if((devicename != NULL) && (filename != NULL))
|
if((devicename != NULL) && (filename != NULL))
|
||||||
{
|
{
|
||||||
strncpy(devicename, ai->device, devlen-1);
|
strncpy(devicename, ao->device, devlen-1);
|
||||||
strncpy(filename, search_ptr+1, filelen-1);
|
strncpy(filename, search_ptr+1, filelen-1);
|
||||||
if(filename[0] == 0){ free(filename); filename = NULL; }
|
if(filename[0] == 0){ free(filename); filename = NULL; }
|
||||||
}
|
}
|
||||||
@@ -109,7 +90,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
driver = ao_driver_id( devicename );
|
driver = ao_driver_id( devicename );
|
||||||
if(devicename != NULL) free(devicename);
|
if(devicename != NULL) free(devicename);
|
||||||
}
|
}
|
||||||
else driver = ao_driver_id( ai->device );
|
else driver = ao_driver_id( ao->device );
|
||||||
} else {
|
} else {
|
||||||
driver = ao_default_driver_id();
|
driver = ao_default_driver_id();
|
||||||
}
|
}
|
||||||
@@ -160,7 +141,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
/* Store it for later */
|
/* Store it for later */
|
||||||
ai->handle = (void*)device;
|
ao->handle = (void*)device;
|
||||||
}
|
}
|
||||||
/* always do this here! */
|
/* always do this here! */
|
||||||
if(filename != NULL) free(filename);
|
if(filename != NULL) free(filename);
|
||||||
@@ -170,15 +151,15 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
|
|
||||||
/* The two formats we support */
|
/* The two formats we support */
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
return AUDIO_FORMAT_SIGNED_16 | AUDIO_FORMAT_SIGNED_8;
|
return AUDIO_FORMAT_SIGNED_16 | AUDIO_FORMAT_SIGNED_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
ao_device *device = (ao_device*)ai->handle;
|
ao_device *device = (ao_device*)ao->handle;
|
||||||
|
|
||||||
res = ao_play(device, (char*)buf, len);
|
res = ao_play(device, (char*)buf, len);
|
||||||
if (res==0) {
|
if (res==0) {
|
||||||
@@ -189,14 +170,14 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
ao_device *device = (ao_device*)ai->handle;
|
ao_device *device = (ao_device*)ao->handle;
|
||||||
|
|
||||||
/* Close and shutdown */
|
/* Close and shutdown */
|
||||||
if (device) {
|
if (device) {
|
||||||
ao_close(device);
|
ao_close(device);
|
||||||
ai->handle = NULL;
|
ao->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_shutdown();
|
audio_shutdown();
|
||||||
@@ -204,7 +185,49 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int deinit_libao(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
ao_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_libao(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Initialise LibAO */
|
||||||
|
ao_initialize();
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_libao;
|
||||||
|
ao->flush = flush_libao;
|
||||||
|
ao->write = write_libao;
|
||||||
|
ao->get_formats = get_formats_libao;
|
||||||
|
ao->close = close_libao;
|
||||||
|
ao->deinit = deinit_libao;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "libao",
|
||||||
|
/* description */ "Output audio using LibAO.",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_libao,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_mint: audio output for MINT
|
mint: audio output for MINT
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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
|
||||||
@@ -18,30 +18,30 @@ int real_rate_printed = 0;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int audio_rate_best_match(struct audio_info_struct *ai)
|
static int audio_rate_best_match(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int ret,dsp_rate;
|
int ret,dsp_rate;
|
||||||
|
|
||||||
if(!ai || ai->fn < 0 || ai->rate < 0)
|
if(!ai || ao->fn < 0 || ao->rate < 0)
|
||||||
return -1;
|
return -1;
|
||||||
dsp_rate = ai->rate;
|
dsp_rate = ao->rate;
|
||||||
ret = ioctl(ai->fn,AIOCSSPEED, (void *)dsp_rate);
|
ret = ioctl(ao->fn,AIOCSSPEED, (void *)dsp_rate);
|
||||||
ret = ioctl(ai->fn,AIOCGSPEED,&dsp_rate);
|
ret = ioctl(ao->fn,AIOCGSPEED,&dsp_rate);
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ai->rate = dsp_rate;
|
ao->rate = dsp_rate;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_rate(struct audio_info_struct *ai)
|
static int audio_set_rate(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int dsp_rate = ai->rate;
|
int dsp_rate = ao->rate;
|
||||||
|
|
||||||
if(ai->rate >= 0) {
|
if(ao->rate >= 0) {
|
||||||
int ret, real_rate;
|
int ret, real_rate;
|
||||||
ret = ioctl(ai->fn, AIOCSSPEED, (void *)dsp_rate);
|
ret = ioctl(ao->fn, AIOCSSPEED, (void *)dsp_rate);
|
||||||
if (ret >= 0 && !real_rate_printed) {
|
if (ret >= 0 && !real_rate_printed) {
|
||||||
ioctl(ai->fn,AIOCGSPEED,&real_rate);
|
ioctl(ao->fn,AIOCGSPEED,&real_rate);
|
||||||
if (real_rate != dsp_rate) {
|
if (real_rate != dsp_rate) {
|
||||||
fprintf(stderr, "Replay rate: %d Hz\n", real_rate);
|
fprintf(stderr, "Replay rate: %d Hz\n", real_rate);
|
||||||
real_rate_printed = 1;
|
real_rate_printed = 1;
|
||||||
@@ -53,24 +53,24 @@ static int audio_set_rate(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_channels(struct audio_info_struct *ai)
|
static int audio_set_channels(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int chan = ai->channels;
|
int chan = ao->channels;
|
||||||
|
|
||||||
if(ai->channels < 1)
|
if(ao->channels < 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return ioctl(ai->fn, AIOCSCHAN, (void *)chan);
|
return ioctl(ao->fn, AIOCSCHAN, (void *)chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_format(struct audio_info_struct *ai)
|
static int audio_set_format(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int fmts;
|
int fmts;
|
||||||
|
|
||||||
if(ai->format == -1)
|
if(ao->format == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(ai->format) {
|
switch(ao->format) {
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
default:
|
default:
|
||||||
fmts = AFMT_S16;
|
fmts = AFMT_S16;
|
||||||
@@ -85,13 +85,13 @@ static int audio_set_format(struct audio_info_struct *ai)
|
|||||||
fmts = AFMT_ULAW;
|
fmts = AFMT_ULAW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ioctl(ai->fn, AIOCSFMT, (void *)fmts);
|
return ioctl(ao->fn, AIOCSFMT, (void *)fmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_reset_parameters(struct audio_info_struct *ai)
|
static int audio_reset_parameters(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ret = ioctl(ai->fn,AIOCRESET,NULL);
|
ret = ioctl(ao->fn,AIOCRESET,NULL);
|
||||||
if(ret >= 0)
|
if(ret >= 0)
|
||||||
ret = audio_set_format(ai);
|
ret = audio_set_format(ai);
|
||||||
if(ret >= 0)
|
if(ret >= 0)
|
||||||
@@ -103,36 +103,36 @@ static int audio_reset_parameters(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
if(!ai)
|
if(!ai)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(!ai->device)
|
if(!ao->device)
|
||||||
ai->device = "/dev/audio";
|
ao->device = "/dev/audio";
|
||||||
|
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
|
|
||||||
if(ai->fn < 0)
|
if(ao->fn < 0)
|
||||||
{
|
{
|
||||||
error1("Can't open %s!",ai->device);
|
error1("Can't open %s!",ao->device);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ioctl(ai->fn, AIOCGBLKSIZE, &outburst);
|
ioctl(ao->fn, AIOCGBLKSIZE, &outburst);
|
||||||
if(outburst > MAXOUTBURST)
|
if(outburst > MAXOUTBURST)
|
||||||
outburst = MAXOUTBURST;
|
outburst = MAXOUTBURST;
|
||||||
if(audio_reset_parameters(ai) < 0) {
|
if(audio_reset_parameters(ai) < 0) {
|
||||||
close(ai->fn);
|
close(ao->fn);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
}
|
}
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int fmts;
|
int fmts;
|
||||||
|
|
||||||
if(ioctl(ai->fn,AIOCGFMTS,&fmts) < 0)
|
if(ioctl(ao->fn,AIOCGFMTS,&fmts) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(fmts & AFMT_ULAW)
|
if(fmts & AFMT_ULAW)
|
||||||
@@ -147,18 +147,18 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
return write(ai->fn,buf,len);
|
return write(ao->fn,buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
close (ai->fn);
|
close (ao->fn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_nas: audio output via NAS
|
nas: audio output via NAS
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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
|
||||||
@@ -28,12 +28,13 @@ typedef struct
|
|||||||
#define NAS_SOUND_LOW_WATER_MARK 25 /* percent */
|
#define NAS_SOUND_LOW_WATER_MARK 25 /* percent */
|
||||||
#define NAS_MAX_FORMAT 10 /* currently, there are 7 supported formats */
|
#define NAS_MAX_FORMAT 10 /* currently, there are 7 supported formats */
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: stick this inside userptr inside audio_output_t instead */
|
||||||
static InfoRec info;
|
static InfoRec info;
|
||||||
|
|
||||||
/* NAS specific routines */
|
/* NAS specific routines */
|
||||||
|
|
||||||
static void
|
static void nas_sendData(AuServer *aud, InfoPtr i, AuUint32 numBytes)
|
||||||
nas_sendData(AuServer *aud, InfoPtr i, AuUint32 numBytes)
|
|
||||||
{
|
{
|
||||||
if (numBytes < i->buf_cnt) {
|
if (numBytes < i->buf_cnt) {
|
||||||
AuWriteElement(aud, i->flow, 0, numBytes, i->buf, AuFalse, NULL);
|
AuWriteElement(aud, i->flow, 0, numBytes, i->buf, AuFalse, NULL);
|
||||||
@@ -48,8 +49,7 @@ nas_sendData(AuServer *aud, InfoPtr i, AuUint32 numBytes)
|
|||||||
i->data_sent = AuTrue;
|
i->data_sent = AuTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AuBool
|
static AuBool nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
|
||||||
nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
|
|
||||||
{
|
{
|
||||||
InfoPtr i = (InfoPtr) handler->data;
|
InfoPtr i = (InfoPtr) handler->data;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 0 on error */
|
/* 0 on error */
|
||||||
int nas_createFlow(struct audio_info_struct *ai)
|
static int nas_createFlow(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
AuDeviceID device = AuNone;
|
AuDeviceID device = AuNone;
|
||||||
AuElement elements[2];
|
AuElement elements[2];
|
||||||
@@ -94,7 +94,7 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
switch(ai->format) {
|
switch(ao->format) {
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
default:
|
default:
|
||||||
if (((char) *(short *)"x")=='x') /* ugly, but painless */
|
if (((char) *(short *)"x")=='x') /* ugly, but painless */
|
||||||
@@ -117,20 +117,20 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
if (((AuDeviceKind(AuServerDevice(info.aud, i)) ==
|
if (((AuDeviceKind(AuServerDevice(info.aud, i)) ==
|
||||||
AuComponentKindPhysicalOutput) &&
|
AuComponentKindPhysicalOutput) &&
|
||||||
AuDeviceNumTracks(AuServerDevice(info.aud, i))
|
AuDeviceNumTracks(AuServerDevice(info.aud, i))
|
||||||
== ai->channels )) {
|
== ao->channels )) {
|
||||||
device = AuDeviceIdentifier(AuServerDevice(info.aud, i));
|
device = AuDeviceIdentifier(AuServerDevice(info.aud, i));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (device == AuNone) {
|
if (device == AuNone) {
|
||||||
error1("Couldn't find an output device providing %d channels.", ai->channels);
|
error1("Couldn't find an output device providing %d channels.", ao->channels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set gain */
|
/* set gain */
|
||||||
if(ai->gain >= 0) {
|
if(ao->gain >= 0) {
|
||||||
info.da = AuGetDeviceAttributes(info.aud, device, NULL);
|
info.da = AuGetDeviceAttributes(info.aud, device, NULL);
|
||||||
if ((info.da)!=NULL) {
|
if ((info.da)!=NULL) {
|
||||||
AuDeviceGain(info.da) = AuFixedPointFromSum(ai->gain, 0);
|
AuDeviceGain(info.da) = AuFixedPointFromSum(ao->gain, 0);
|
||||||
AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da),
|
AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da),
|
||||||
AuCompDeviceGainMask, info.da, NULL);
|
AuCompDeviceGainMask, info.da, NULL);
|
||||||
}
|
}
|
||||||
@@ -143,13 +143,13 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_samples = ai->rate * NAS_SOUND_PORT_DURATION;
|
buf_samples = ao->rate * NAS_SOUND_PORT_DURATION;
|
||||||
|
|
||||||
AuMakeElementImportClient(&elements[0], /* element */
|
AuMakeElementImportClient(&elements[0], /* element */
|
||||||
(unsigned short) ai->rate,
|
(unsigned short) ao->rate,
|
||||||
/* rate */
|
/* rate */
|
||||||
format, /* format */
|
format, /* format */
|
||||||
ai->channels, /* channels */
|
ao->channels, /* channels */
|
||||||
AuTrue, /* ??? */
|
AuTrue, /* ??? */
|
||||||
buf_samples, /* max samples */
|
buf_samples, /* max samples */
|
||||||
(AuUint32) (buf_samples / 100
|
(AuUint32) (buf_samples / 100
|
||||||
@@ -160,7 +160,7 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
AuMakeElementExportDevice(&elements[1], /* element */
|
AuMakeElementExportDevice(&elements[1], /* element */
|
||||||
0, /* input */
|
0, /* input */
|
||||||
device, /* device */
|
device, /* device */
|
||||||
(unsigned short) ai->rate,
|
(unsigned short) ao->rate,
|
||||||
/* rate */
|
/* rate */
|
||||||
AuUnlimitedSamples, /* num samples */
|
AuUnlimitedSamples, /* num samples */
|
||||||
0, /* num actions */
|
0, /* num actions */
|
||||||
@@ -179,7 +179,7 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
nas_eventHandler, /* callback */
|
nas_eventHandler, /* callback */
|
||||||
(AuPointer) &info); /* data */
|
(AuPointer) &info); /* data */
|
||||||
|
|
||||||
info.buf_size = buf_samples * ai->channels * AuSizeofFormat(format);
|
info.buf_size = buf_samples * ao->channels * AuSizeofFormat(format);
|
||||||
info.buf = (char *) malloc(info.buf_size);
|
info.buf = (char *) malloc(info.buf_size);
|
||||||
if (info.buf == NULL) {
|
if (info.buf == NULL) {
|
||||||
error1("Unable to allocate input/output buffer of size %ld",
|
error1("Unable to allocate input/output buffer of size %ld",
|
||||||
@@ -197,7 +197,7 @@ int nas_createFlow(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void nas_flush()
|
static void flush_nas(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
AuEvent ev;
|
AuEvent ev;
|
||||||
|
|
||||||
@@ -208,19 +208,18 @@ void nas_flush()
|
|||||||
info.data_sent = AuFalse;
|
info.data_sent = AuFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* required functions */
|
|
||||||
|
|
||||||
/* returning -1 on error, 0 on success... */
|
/* returning -1 on error, 0 on success... */
|
||||||
int audio_open(struct audio_info_struct *ai)
|
static int open_nas(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
if(!ai)
|
if(!ao) return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!(info.aud = AuOpenServer(ai->device, 0, NULL, 0, NULL, NULL))) {
|
if (!(info.aud = AuOpenServer(ao->device, 0, NULL, 0, NULL, NULL))) {
|
||||||
if (ai->device==NULL)
|
if (ao->device==NULL) {
|
||||||
error("could not open default NAS server");
|
error("could not open default NAS server");
|
||||||
else
|
} else {
|
||||||
error1("could not open NAS server %s\n", ai->device);
|
error1("could not open NAS server %s\n", ao->device);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
info.buf_size = 0;
|
info.buf_size = 0;
|
||||||
@@ -229,7 +228,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
static int get_formats_nas(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int i, j, k, ret;
|
int i, j, k, ret;
|
||||||
|
|
||||||
@@ -256,12 +255,12 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
static int write_nas(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
int buf_cnt = 0;
|
int buf_cnt = 0;
|
||||||
|
|
||||||
if (info.buf_size == 0)
|
if (info.buf_size == 0)
|
||||||
if(!nas_createFlow(ai)) return -1;
|
if(!nas_createFlow(ao)) return -1;
|
||||||
|
|
||||||
while ((info.buf_cnt + (len - buf_cnt)) > info.buf_size) {
|
while ((info.buf_cnt + (len - buf_cnt)) > info.buf_size) {
|
||||||
memcpy(info.buf + info.buf_cnt,
|
memcpy(info.buf + info.buf_cnt,
|
||||||
@@ -269,7 +268,7 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|||||||
(info.buf_size - info.buf_cnt));
|
(info.buf_size - info.buf_cnt));
|
||||||
buf_cnt += (info.buf_size - info.buf_cnt);
|
buf_cnt += (info.buf_size - info.buf_cnt);
|
||||||
info.buf_cnt += (info.buf_size - info.buf_cnt);
|
info.buf_cnt += (info.buf_size - info.buf_cnt);
|
||||||
nas_flush();
|
flush_nas(ao);
|
||||||
}
|
}
|
||||||
memcpy(info.buf + info.buf_cnt,
|
memcpy(info.buf + info.buf_cnt,
|
||||||
buf + buf_cnt,
|
buf + buf_cnt,
|
||||||
@@ -279,7 +278,7 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
static int close_nas(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
if (info.aud == NULL) {
|
if (info.aud == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -292,7 +291,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!info.finished) {
|
while (!info.finished) {
|
||||||
nas_flush();
|
flush_nas(ao);
|
||||||
}
|
}
|
||||||
AuCloseServer(info.aud);
|
AuCloseServer(info.aud);
|
||||||
free(info.buf);
|
free(info.buf);
|
||||||
@@ -300,6 +299,38 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int init_nas(audio_output_t* ao)
|
||||||
{
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_nas;
|
||||||
|
ao->flush = flush_nas;
|
||||||
|
ao->write = write_nas;
|
||||||
|
ao->get_formats = get_formats_nas;
|
||||||
|
ao->close = close_nas;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "nas",
|
||||||
|
/* description */ "Output audio using NAS (Network Audio System)",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_nas,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_os2: OS/2 RealTime DART Engine
|
os2: OS/2 RealTime DART Engine
|
||||||
|
|
||||||
copyright 1998-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright 1998-2006 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
|
||||||
@@ -137,7 +137,7 @@ static void MciError(ULONG ulError)
|
|||||||
fprintf(stderr,"%s",mmerror);
|
fprintf(stderr,"%s",mmerror);
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_set_volume(struct audio_info_struct *ai, USHORT setvolume)
|
int audio_set_volume(audio_output_t *ao, USHORT setvolume)
|
||||||
{
|
{
|
||||||
if(setvolume > 100) setvolume = 100;
|
if(setvolume > 100) setvolume = 100;
|
||||||
volume = setvolume; /* useful when device is closed and reopened */
|
volume = setvolume; /* useful when device is closed and reopened */
|
||||||
@@ -154,7 +154,7 @@ int audio_set_volume(struct audio_info_struct *ai, USHORT setvolume)
|
|||||||
return setvolume;
|
return setvolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_pause(struct audio_info_struct *ai, int pause)
|
int audio_pause(audio_output_t *ao, int pause)
|
||||||
{
|
{
|
||||||
if(maop.usDeviceID)
|
if(maop.usDeviceID)
|
||||||
{
|
{
|
||||||
@@ -170,7 +170,7 @@ int audio_pause(struct audio_info_struct *ai, int pause)
|
|||||||
return pause;
|
return pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
ULONG rc,i;
|
ULONG rc,i;
|
||||||
char *temp;
|
char *temp;
|
||||||
@@ -182,22 +182,22 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
if(!ai) return -1;
|
if(!ai) return -1;
|
||||||
|
|
||||||
if(!ai->device) ai->device = "0";
|
if(!ao->device) ao->device = "0";
|
||||||
|
|
||||||
if(ai->rate < 0) ai->rate = 44100;
|
if(ao->rate < 0) ao->rate = 44100;
|
||||||
if(ai->channels < 0) ai->channels = 2;
|
if(ao->channels < 0) ao->channels = 2;
|
||||||
if(ai->format < 0) ai->format = AUDIO_FORMAT_SIGNED_16;
|
if(ao->format < 0) ao->format = AUDIO_FORMAT_SIGNED_16;
|
||||||
|
|
||||||
if(ai->format == AUDIO_FORMAT_SIGNED_16)
|
if(ao->format == AUDIO_FORMAT_SIGNED_16)
|
||||||
bits = 16;
|
bits = 16;
|
||||||
else if(ai->format == AUDIO_FORMAT_UNSIGNED_8)
|
else if(ao->format == AUDIO_FORMAT_UNSIGNED_8)
|
||||||
bits = 8;
|
bits = 8;
|
||||||
else return -1;
|
else return -1;
|
||||||
|
|
||||||
/* open the mixer device */
|
/* open the mixer device */
|
||||||
memset (&maop, 0, sizeof(maop));
|
memset (&maop, 0, sizeof(maop));
|
||||||
maop.usDeviceID = 0;
|
maop.usDeviceID = 0;
|
||||||
maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, atoi(ai->device));
|
maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, atoi(ao->device));
|
||||||
|
|
||||||
openflags = MCI_WAIT | MCI_OPEN_TYPE_ID;
|
openflags = MCI_WAIT | MCI_OPEN_TYPE_ID;
|
||||||
if(!lockdevice) openflags |= MCI_OPEN_SHAREABLE;
|
if(!lockdevice) openflags |= MCI_OPEN_SHAREABLE;
|
||||||
@@ -215,7 +215,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* volume in ai->gain ?? */
|
/* volume in ao->gain ?? */
|
||||||
|
|
||||||
/* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */
|
/* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */
|
||||||
|
|
||||||
@@ -223,8 +223,8 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
mmp.ulBitsPerSample = bits;
|
mmp.ulBitsPerSample = bits;
|
||||||
mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||||
mmp.ulSamplesPerSec = ai->rate;
|
mmp.ulSamplesPerSec = ao->rate;
|
||||||
mmp.ulChannels = ai->channels;
|
mmp.ulChannels = ao->channels;
|
||||||
|
|
||||||
/* Setup the mixer for playback of wave data */
|
/* Setup the mixer for playback of wave data */
|
||||||
mmp.ulFormatMode = MCI_PLAY;
|
mmp.ulFormatMode = MCI_PLAY;
|
||||||
@@ -345,7 +345,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
return maop.usDeviceID;
|
return maop.usDeviceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
/* if we're too quick, let's wait */
|
/* if we're too quick, let's wait */
|
||||||
if(nobuffermode)
|
if(nobuffermode)
|
||||||
@@ -390,18 +390,18 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_playing_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_playing_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
if(len > audiobufsize || !playingbuffer) return -1;
|
if(len > audiobufsize || !playingbuffer) return -1;
|
||||||
|
|
||||||
if(mmp.ulBitsPerSample == 16)
|
if(mmp.ulBitsPerSample == 16)
|
||||||
ai->format = AUDIO_FORMAT_SIGNED_16;
|
ao->format = AUDIO_FORMAT_SIGNED_16;
|
||||||
else if(mmp.ulBitsPerSample == 8)
|
else if(mmp.ulBitsPerSample == 8)
|
||||||
ai->format = AUDIO_FORMAT_UNSIGNED_8;
|
ao->format = AUDIO_FORMAT_UNSIGNED_8;
|
||||||
else return -1;
|
else return -1;
|
||||||
|
|
||||||
ai->rate = mmp.ulSamplesPerSec;
|
ao->rate = mmp.ulSamplesPerSec;
|
||||||
ai->channels = mmp.ulChannels;
|
ao->channels = mmp.ulChannels;
|
||||||
|
|
||||||
if(buf && len)
|
if(buf && len)
|
||||||
{
|
{
|
||||||
@@ -445,13 +445,13 @@ int audio_playing_samples(struct audio_info_struct *ai,unsigned char *buf,int le
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_nobuffermode(struct audio_info_struct *ai, int setnobuffermode)
|
int audio_nobuffermode(audio_output_t *ao, int setnobuffermode)
|
||||||
{
|
{
|
||||||
nobuffermode = setnobuffermode;
|
nobuffermode = setnobuffermode;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_trash_buffers(struct audio_info_struct *ai)
|
int audio_trash_buffers(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -467,7 +467,7 @@ int audio_trash_buffers(struct audio_info_struct *ai)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
ULONG rc;
|
ULONG rc;
|
||||||
|
|
||||||
@@ -526,7 +526,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
/*
|
/*
|
||||||
* get formats for specific channel/rate parameters
|
* get formats for specific channel/rate parameters
|
||||||
*/
|
*/
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int fmts = 0;
|
int fmts = 0;
|
||||||
ULONG rc;
|
ULONG rc;
|
||||||
@@ -536,8 +536,8 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
mmp.pmixEvent = DARTEvent;
|
mmp.pmixEvent = DARTEvent;
|
||||||
|
|
||||||
mmptemp.ulFormatMode = MCI_PLAY;
|
mmptemp.ulFormatMode = MCI_PLAY;
|
||||||
mmptemp.ulSamplesPerSec = ai->rate;
|
mmptemp.ulSamplesPerSec = ao->rate;
|
||||||
mmptemp.ulChannels = ai->channels;
|
mmptemp.ulChannels = ao->channels;
|
||||||
|
|
||||||
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||||
mmptemp.ulBitsPerSample = 16;
|
mmptemp.ulBitsPerSample = 16;
|
||||||
@@ -634,6 +634,6 @@ int audio_get_devices(char *info, int deviceid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
322
src/output/oss.c
Normal file
322
src/output/oss.c
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
oss: audio output via Open Sound System
|
||||||
|
|
||||||
|
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
initially written by Michael Hipp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "mpg123.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_SOUNDCARD_H
|
||||||
|
#include <linux/soundcard.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOUNDCARD_H
|
||||||
|
#include <sys/soundcard.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MACHINE_SOUNDCARD_H
|
||||||
|
#include <machine/soundcard.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AFMT_S16_NE
|
||||||
|
# ifdef OSS_BIG_ENDIAN
|
||||||
|
# define AFMT_S16_NE AFMT_S16_BE
|
||||||
|
# else
|
||||||
|
# define AFMT_S16_NE AFMT_S16_LE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef AFMT_U16_NE
|
||||||
|
# ifdef OSS_BIG_ENDIAN
|
||||||
|
# define AFMT_U16_NE AFMT_U16_BE
|
||||||
|
# else
|
||||||
|
# define AFMT_U16_NE AFMT_U16_LE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static int rate_best_match_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int ret,dsp_rate;
|
||||||
|
|
||||||
|
if(!ao || ao->fn < 0 || ao->rate < 0) return -1;
|
||||||
|
dsp_rate = ao->rate;
|
||||||
|
|
||||||
|
ret = ioctl(ao->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
||||||
|
if(ret < 0) return ret;
|
||||||
|
ao->rate = dsp_rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_rate_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int dsp_rate;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if(ao->rate >= 0) {
|
||||||
|
dsp_rate = ao->rate;
|
||||||
|
ret = ioctl(ao->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_channels_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int chan = ao->channels - 1;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(ao->channels < 0) return 0;
|
||||||
|
|
||||||
|
ret = ioctl(ao->fn, SNDCTL_DSP_STEREO, &chan);
|
||||||
|
if(chan != (ao->channels-1)) return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_format_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int sample_size,fmts;
|
||||||
|
int sf,ret;
|
||||||
|
|
||||||
|
if(ao->format == -1) return 0;
|
||||||
|
|
||||||
|
switch(ao->format) {
|
||||||
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
|
default:
|
||||||
|
fmts = AFMT_S16_NE;
|
||||||
|
sample_size = 16;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_UNSIGNED_8:
|
||||||
|
fmts = AFMT_U8;
|
||||||
|
sample_size = 8;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_SIGNED_8:
|
||||||
|
fmts = AFMT_S8;
|
||||||
|
sample_size = 8;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_ULAW_8:
|
||||||
|
fmts = AFMT_MU_LAW;
|
||||||
|
sample_size = 8;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_ALAW_8:
|
||||||
|
fmts = AFMT_A_LAW;
|
||||||
|
sample_size = 8;
|
||||||
|
break;
|
||||||
|
case AUDIO_FORMAT_UNSIGNED_16:
|
||||||
|
fmts = AFMT_U16_NE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(ioctl(ao->fn, SNDCTL_DSP_SAMPLESIZE, &sample_size) < 0)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sf = fmts;
|
||||||
|
ret = ioctl(ao->fn, SNDCTL_DSP_SETFMT, &fmts);
|
||||||
|
if(sf != fmts) return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int reset_parameters_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = ioctl(ao->fn, SNDCTL_DSP_RESET, NULL);
|
||||||
|
if(ret < 0) error("Can't reset audio!");
|
||||||
|
ret = set_format_oss(ao);
|
||||||
|
if (ret == -1) goto err;
|
||||||
|
ret = set_channels_oss(ao);
|
||||||
|
if (ret == -1) goto err;
|
||||||
|
ret = set_rate_oss(ao);
|
||||||
|
if (ret == -1) goto err;
|
||||||
|
|
||||||
|
/* Careful here. As per OSS v1.1, the next ioctl() commits the format
|
||||||
|
* set above, so we must issue SNDCTL_DSP_RESET before we're allowed to
|
||||||
|
* change it again. [dk]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FIXME: this needs re-enabled (but not using global variables this time):
|
||||||
|
if (ioctl(ao->fn, SNDCTL_DSP_GETBLKSIZE, &outburst) == -1 ||
|
||||||
|
outburst > MAXOUTBURST)
|
||||||
|
outburst = MAXOUTBURST;
|
||||||
|
*/
|
||||||
|
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int open_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
char usingdefdev = 0;
|
||||||
|
|
||||||
|
if(!ao) return -1;
|
||||||
|
|
||||||
|
if(!ao->device) {
|
||||||
|
ao->device = "/dev/dsp";
|
||||||
|
usingdefdev = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
|
|
||||||
|
if(ao->fn < 0)
|
||||||
|
{
|
||||||
|
if(usingdefdev) {
|
||||||
|
ao->device = "/dev/sound/dsp";
|
||||||
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
|
if(ao->fn < 0) {
|
||||||
|
error("Can't open default sound device!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error1("Can't open %s!",ao->device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reset_parameters_oss(ao) < 0) {
|
||||||
|
close(ao->fn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ao->gain >= 0) {
|
||||||
|
int e,mask;
|
||||||
|
e = ioctl(ao->fn , SOUND_MIXER_READ_DEVMASK ,&mask);
|
||||||
|
if(e < 0) {
|
||||||
|
error("audio/gain: Can't get audio device features list.");
|
||||||
|
}
|
||||||
|
else if(mask & SOUND_MASK_PCM) {
|
||||||
|
int gain = (ao->gain<<8)|(ao->gain);
|
||||||
|
e = ioctl(ao->fn, SOUND_MIXER_WRITE_PCM , &gain);
|
||||||
|
}
|
||||||
|
else if(!(mask & SOUND_MASK_VOLUME)) {
|
||||||
|
error1("audio/gain: setable Volume/PCM-Level not supported by your audio device: %#04x",mask);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int gain = (ao->gain<<8)|(ao->gain);
|
||||||
|
e = ioctl(ao->fn, SOUND_MIXER_WRITE_VOLUME , &gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ao->fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get formats for specific channel/rate parameters
|
||||||
|
*/
|
||||||
|
static int get_formats_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
int fmt = 0;
|
||||||
|
int r = ao->rate;
|
||||||
|
int c = ao->channels;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
static int fmts[] = {
|
||||||
|
AUDIO_FORMAT_ULAW_8 , AUDIO_FORMAT_SIGNED_16 ,
|
||||||
|
AUDIO_FORMAT_UNSIGNED_8 , AUDIO_FORMAT_SIGNED_8 ,
|
||||||
|
AUDIO_FORMAT_UNSIGNED_16 , AUDIO_FORMAT_ALAW_8
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Reset is required before we're allowed to set the new formats. [dk] */
|
||||||
|
ioctl(ao->fn, SNDCTL_DSP_RESET, NULL);
|
||||||
|
|
||||||
|
for(i=0;i<6;i++) {
|
||||||
|
ao->format = fmts[i];
|
||||||
|
if(set_format_oss(ao) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ao->channels = c;
|
||||||
|
if(set_channels_oss(ao) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ao->rate = r;
|
||||||
|
if(rate_best_match_oss(ao) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( (ao->rate*100 > r*(100-AUDIO_RATE_TOLERANCE)) && (ao->rate*100 < r*(100+AUDIO_RATE_TOLERANCE)) ) {
|
||||||
|
fmt |= fmts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(ioctl(ao->fn,SNDCTL_DSP_GETFMTS,&fmts) < 0) {
|
||||||
|
fprintf(stderr,"No");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fmts & AFMT_MU_LAW)
|
||||||
|
ret |= AUDIO_FORMAT_ULAW_8;
|
||||||
|
if(fmts & AFMT_S16_NE)
|
||||||
|
ret |= AUDIO_FORMAT_SIGNED_16;
|
||||||
|
if(fmts & AFMT_U8)
|
||||||
|
ret |= AUDIO_FORMAT_UNSIGNED_8;
|
||||||
|
if(fmts & AFMT_S8)
|
||||||
|
ret |= AUDIO_FORMAT_SIGNED_8;
|
||||||
|
if(fmts & AFMT_U16_NE)
|
||||||
|
ret |= AUDIO_FORMAT_UNSIGNED_16;
|
||||||
|
if(fmts & AFMT_A_LAW)
|
||||||
|
ret |= AUDIO_FORMAT_ALAW_8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_oss(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
|
{
|
||||||
|
return write(ao->fn,buf,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
close (ao->fn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_oss(audio_output_t *ao)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int init_oss(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_oss;
|
||||||
|
ao->flush = flush_oss;
|
||||||
|
ao->write = write_oss;
|
||||||
|
ao->get_formats = get_formats_oss;
|
||||||
|
ao->close = close_oss;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "oss",
|
||||||
|
/* description */ "Output audio using OSS",
|
||||||
|
/* revision */ "$Rev$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_oss,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_portaudio: audio output via PortAudio cross-platform audio API
|
portaudio: audio output via PortAudio cross-platform audio API
|
||||||
|
|
||||||
copyright 2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright 2006 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
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
#define FIFO_DURATION (0.5f)
|
#define FIFO_DURATION (0.5f)
|
||||||
|
|
||||||
|
|
||||||
static int pa_initialised=0;
|
|
||||||
static PaStream *pa_stream=NULL;
|
static PaStream *pa_stream=NULL;
|
||||||
static sfifo_t fifo;
|
static sfifo_t fifo;
|
||||||
|
|
||||||
@@ -34,8 +33,8 @@ static int paCallback( void *inputBuffer, void *outputBuffer,
|
|||||||
unsigned long framesPerBuffer,
|
unsigned long framesPerBuffer,
|
||||||
PaTimestamp outTime, void *userData )
|
PaTimestamp outTime, void *userData )
|
||||||
{
|
{
|
||||||
struct audio_info_struct *ai = userData;
|
audio_output_t *ao = userData;
|
||||||
unsigned long bytes = framesPerBuffer * SAMPLE_SIZE * ai->channels;
|
unsigned long bytes = framesPerBuffer * SAMPLE_SIZE * ao->channels;
|
||||||
|
|
||||||
if (sfifo_used(&fifo)<bytes) {
|
if (sfifo_used(&fifo)<bytes) {
|
||||||
error("ringbuffer for PortAudio is empty");
|
error("ringbuffer for PortAudio is empty");
|
||||||
@@ -47,36 +46,23 @@ static int paCallback( void *inputBuffer, void *outputBuffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
static int open_portaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
PaError err;
|
PaError err;
|
||||||
|
|
||||||
/* Initialise PortAudio */
|
|
||||||
if (!pa_initialised) {
|
|
||||||
err = Pa_Initialize();
|
|
||||||
if( err != paNoError ) {
|
|
||||||
error1("Failed to initialise PortAudio: %s", Pa_GetErrorText( err ));
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
pa_initialised=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Open an audio I/O stream. */
|
/* Open an audio I/O stream. */
|
||||||
if (ai->rate > 0 && ai->channels >0 ) {
|
if (ao->rate > 0 && ao->channels >0 ) {
|
||||||
|
|
||||||
err = Pa_OpenDefaultStream(
|
err = Pa_OpenDefaultStream(
|
||||||
&pa_stream,
|
&pa_stream,
|
||||||
0, /* no input channels */
|
0, /* no input channels */
|
||||||
ai->channels, /* number of output channels */
|
ao->channels, /* number of output channels */
|
||||||
paInt16, /* signed 16-bit samples */
|
paInt16, /* signed 16-bit samples */
|
||||||
ai->rate, /* sample rate */
|
ao->rate, /* sample rate */
|
||||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||||
0, /* number of buffers, if zero then use default minimum */
|
0, /* number of buffers, if zero then use default minimum */
|
||||||
paCallback, /* no callback - use blocking IO */
|
paCallback, /* no callback - use blocking IO */
|
||||||
ai );
|
ao );
|
||||||
|
|
||||||
if( err != paNoError ) {
|
if( err != paNoError ) {
|
||||||
error1("Failed to open PortAudio default stream: %s", Pa_GetErrorText( err ));
|
error1("Failed to open PortAudio default stream: %s", Pa_GetErrorText( err ));
|
||||||
@@ -84,7 +70,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise FIFO */
|
/* Initialise FIFO */
|
||||||
sfifo_init( &fifo, ai->rate * FIFO_DURATION * SAMPLE_SIZE *ai->channels );
|
sfifo_init( &fifo, ao->rate * FIFO_DURATION * SAMPLE_SIZE *ao->channels );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,14 +78,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
static int get_formats_portaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/* Only implemented Signed 16-bit audio for now */
|
/* Only implemented Signed 16-bit audio for now */
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len)
|
static int write_portaudio(audio_output_t *ao, unsigned char *buf, int len)
|
||||||
{
|
{
|
||||||
PaError err;
|
PaError err;
|
||||||
int written;
|
int written;
|
||||||
@@ -132,7 +118,7 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
static int close_portaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
PaError err;
|
PaError err;
|
||||||
|
|
||||||
@@ -141,7 +127,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
if (Pa_StreamActive( pa_stream ) == 1) {
|
if (Pa_StreamActive( pa_stream ) == 1) {
|
||||||
err = Pa_StopStream( pa_stream );
|
err = Pa_StopStream( pa_stream );
|
||||||
if( err != paNoError ) {
|
if( err != paNoError ) {
|
||||||
fprintf(stderr, "Failed to stop PortAudio stream: %s", Pa_GetErrorText( err ));
|
error1("Failed to stop PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +135,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
/* and then close the stream */
|
/* and then close the stream */
|
||||||
err = Pa_CloseStream( pa_stream );
|
err = Pa_CloseStream( pa_stream );
|
||||||
if( err != paNoError ) {
|
if( err != paNoError ) {
|
||||||
fprintf(stderr, "Failed to close PortAudio stream: %s", Pa_GetErrorText( err ));
|
error1("Failed to close PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +148,7 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
static void flush_portaudio(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
PaError err;
|
PaError err;
|
||||||
|
|
||||||
@@ -174,3 +160,43 @@ void audio_queueflush(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_portaudio(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
int err = paNoError;
|
||||||
|
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Initialise PortAudio */
|
||||||
|
err = Pa_Initialize();
|
||||||
|
if( err != paNoError ) {
|
||||||
|
error1("Failed to initialise PortAudio: %s", Pa_GetErrorText( err ));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_portaudio;
|
||||||
|
ao->flush = flush_portaudio;
|
||||||
|
ao->write = write_portaudio;
|
||||||
|
ao->get_formats = get_formats_portaudio;
|
||||||
|
ao->close = close_portaudio;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "portaudio",
|
||||||
|
/* description */ "Output audio using PortAudio",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_portaudio,
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_portaudio.c: audio output via PortAudio cross-platform audio API
|
sdl: audio output via SDL cross-platform API
|
||||||
|
|
||||||
copyright 2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright 2006 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
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
#define FRAMES_PER_BUFFER (256)
|
#define FRAMES_PER_BUFFER (256)
|
||||||
#define FIFO_DURATION (0.5f)
|
#define FIFO_DURATION (0.5f)
|
||||||
|
|
||||||
static int sdl_initialised=0;
|
|
||||||
static sfifo_t fifo;
|
static sfifo_t fifo;
|
||||||
|
|
||||||
|
|
||||||
@@ -28,10 +27,9 @@ static sfifo_t fifo;
|
|||||||
stream: A pointer to the audio buffer to be filled
|
stream: A pointer to the audio buffer to be filled
|
||||||
len: The length (in bytes) of the audio buffer
|
len: The length (in bytes) of the audio buffer
|
||||||
*/
|
*/
|
||||||
static void
|
static void audio_callback_sdl(void *udata, Uint8 *stream, int len)
|
||||||
audio_callback_sdl(void *udata, Uint8 *stream, int len)
|
|
||||||
{
|
{
|
||||||
/* struct audio_info_struct *ai = udata; */
|
/* audio_output_t *ao = udata; */
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
/* Only play if we have data left */
|
/* Only play if we have data left */
|
||||||
@@ -49,23 +47,11 @@ audio_callback_sdl(void *udata, Uint8 *stream, int len)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open_sdl(audio_output_t *ao)
|
||||||
int audio_open(struct audio_info_struct *ai)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Initalise SDL */
|
|
||||||
if (!sdl_initialised) {
|
|
||||||
if (SDL_Init( SDL_INIT_AUDIO ) ) {
|
|
||||||
error1("Failed to initialise SDL: %s\n", SDL_GetError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sdl_initialised=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Open an audio I/O stream. */
|
/* Open an audio I/O stream. */
|
||||||
if (ai->rate > 0 && ai->channels >0 ) {
|
if (ao->rate > 0 && ao->channels >0 ) {
|
||||||
SDL_AudioSpec wanted;
|
SDL_AudioSpec wanted;
|
||||||
size_t ringbuffer_len;
|
size_t ringbuffer_len;
|
||||||
|
|
||||||
@@ -74,9 +60,9 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
wanted.format = AUDIO_S16SYS;
|
wanted.format = AUDIO_S16SYS;
|
||||||
wanted.samples = 1024; /* Good low-latency value for callback */
|
wanted.samples = 1024; /* Good low-latency value for callback */
|
||||||
wanted.callback = audio_callback_sdl;
|
wanted.callback = audio_callback_sdl;
|
||||||
wanted.userdata = ai;
|
wanted.userdata = ao;
|
||||||
wanted.channels = ai->channels;
|
wanted.channels = ao->channels;
|
||||||
wanted.freq = ai->rate;
|
wanted.freq = ao->rate;
|
||||||
|
|
||||||
/* Open the audio device, forcing the desired format */
|
/* Open the audio device, forcing the desired format */
|
||||||
if ( SDL_OpenAudio(&wanted, NULL) ) {
|
if ( SDL_OpenAudio(&wanted, NULL) ) {
|
||||||
@@ -85,8 +71,8 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise FIFO */
|
/* Initialise FIFO */
|
||||||
ringbuffer_len = ai->rate * FIFO_DURATION * SAMPLE_SIZE *ai->channels;
|
ringbuffer_len = ao->rate * FIFO_DURATION * SAMPLE_SIZE *ao->channels;
|
||||||
debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);
|
debug2( "Allocating %d byte ring-buffer (%f seconds)", (int)ringbuffer_len, (float)FIFO_DURATION);
|
||||||
sfifo_init( &fifo, ringbuffer_len );
|
sfifo_init( &fifo, ringbuffer_len );
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -95,14 +81,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
static int get_formats_sdl(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/* Only implemented Signed 16-bit audio for now */
|
/* Only implemented Signed 16-bit audio for now */
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len)
|
static int write_sdl(audio_output_t *ao, unsigned char *buf, int len)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Sleep for half the length of the FIFO */
|
/* Sleep for half the length of the FIFO */
|
||||||
@@ -128,7 +114,7 @@ int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
static int close_sdl(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
SDL_CloseAudio();
|
SDL_CloseAudio();
|
||||||
|
|
||||||
@@ -137,10 +123,46 @@ int audio_close(struct audio_info_struct *ai)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
static void flush_sdl(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
SDL_PauseAudio(1);
|
SDL_PauseAudio(1);
|
||||||
|
|
||||||
sfifo_flush( &fifo );
|
sfifo_flush( &fifo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int init_sdl(audio_output_t* ao)
|
||||||
|
{
|
||||||
|
if (ao==NULL) return -1;
|
||||||
|
|
||||||
|
/* Initialise SDL */
|
||||||
|
if (SDL_Init( SDL_INIT_AUDIO ) ) {
|
||||||
|
error1("Failed to initialise SDL: %s\n", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set callbacks */
|
||||||
|
ao->open = open_sdl;
|
||||||
|
ao->flush = flush_sdl;
|
||||||
|
ao->write = write_sdl;
|
||||||
|
ao->get_formats = get_formats_sdl;
|
||||||
|
ao->close = close_sdl;
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Module information data structure
|
||||||
|
*/
|
||||||
|
mpg123_module_t mpg123_output_module_info = {
|
||||||
|
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||||
|
/* name */ "sdl",
|
||||||
|
/* description */ "Output audio using SDL (Simple DirectMedia Layer).",
|
||||||
|
/* revision */ "$Rev:$",
|
||||||
|
/* handle */ NULL,
|
||||||
|
|
||||||
|
/* init_output */ init_sdl,
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_sgi.c: audio output on sgi boxen
|
sgi: audio output on SGI boxen
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
static const char analog_output_res_name[] = ".AnalogOut";
|
static const char analog_output_res_name[] = ".AnalogOut";
|
||||||
|
|
||||||
|
|
||||||
static int audio_set_rate(struct audio_info_struct *ai, ALconfig config)
|
static int audio_set_rate(audio_output_t *ao, ALconfig config)
|
||||||
{
|
{
|
||||||
int dev = alGetDevice(config);
|
int dev = alGetDevice(config);
|
||||||
ALpv params[1];
|
ALpv params[1];
|
||||||
@@ -31,7 +31,7 @@ static int audio_set_rate(struct audio_info_struct *ai, ALconfig config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
params[0].param = AL_OUTPUT_RATE;
|
params[0].param = AL_OUTPUT_RATE;
|
||||||
params[0].value.ll = alDoubleToFixed(ai->rate);
|
params[0].value.ll = alDoubleToFixed(ao->rate);
|
||||||
|
|
||||||
if (alSetParams(dev, params,1) < 0)
|
if (alSetParams(dev, params,1) < 0)
|
||||||
fprintf(stderr,"audio_set_rate : %s\n",alGetErrorString(oserror()));
|
fprintf(stderr,"audio_set_rate : %s\n",alGetErrorString(oserror()));
|
||||||
@@ -39,11 +39,11 @@ static int audio_set_rate(struct audio_info_struct *ai, ALconfig config)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_channels(struct audio_info_struct *ai, ALconfig config)
|
static int audio_set_channels(audio_output_t *ao, ALconfig config)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(ai->channels == 2)
|
if(ao->channels == 2)
|
||||||
ret = alSetChannels(config, AL_STEREO);
|
ret = alSetChannels(config, AL_STEREO);
|
||||||
else
|
else
|
||||||
ret = alSetChannels(config, AL_MONO);
|
ret = alSetChannels(config, AL_MONO);
|
||||||
@@ -54,7 +54,7 @@ static int audio_set_channels(struct audio_info_struct *ai, ALconfig config)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_format(struct audio_info_struct *ai, ALconfig config)
|
static int audio_set_format(audio_output_t *ao, ALconfig config)
|
||||||
{
|
{
|
||||||
if (alSetSampFmt(config,AL_SAMPFMT_TWOSCOMP) < 0)
|
if (alSetSampFmt(config,AL_SAMPFMT_TWOSCOMP) < 0)
|
||||||
fprintf(stderr,"audio_set_format : %s\n",alGetErrorString(oserror()));
|
fprintf(stderr,"audio_set_format : %s\n",alGetErrorString(oserror()));
|
||||||
@@ -66,7 +66,7 @@ static int audio_set_format(struct audio_info_struct *ai, ALconfig config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
int dev = AL_DEFAULT_OUTPUT;
|
int dev = AL_DEFAULT_OUTPUT;
|
||||||
ALconfig config = alNewConfig();
|
ALconfig config = alNewConfig();
|
||||||
@@ -79,7 +79,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set port parameters */
|
/* Set port parameters */
|
||||||
if(ai->channels == 2)
|
if(ao->channels == 2)
|
||||||
alSetChannels(config, AL_STEREO);
|
alSetChannels(config, AL_STEREO);
|
||||||
else
|
else
|
||||||
alSetChannels(config, AL_MONO);
|
alSetChannels(config, AL_MONO);
|
||||||
@@ -90,14 +90,14 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
|
|
||||||
/* Setup output device to specified module. If there is no module
|
/* Setup output device to specified module. If there is no module
|
||||||
specified in ai structure, use the default four output */
|
specified in ai structure, use the default four output */
|
||||||
if ((ai->device) != NULL) {
|
if ((ao->device) != NULL) {
|
||||||
|
|
||||||
char *dev_name;
|
char *dev_name;
|
||||||
|
|
||||||
dev_name=malloc((strlen(ai->device) + strlen(analog_output_res_name) + 1) *
|
dev_name=malloc((strlen(ao->device) + strlen(analog_output_res_name) + 1) *
|
||||||
sizeof(char));
|
sizeof(char));
|
||||||
|
|
||||||
strcpy(dev_name,ai->device);
|
strcpy(dev_name,ao->device);
|
||||||
strcat(dev_name,analog_output_res_name);
|
strcat(dev_name,analog_output_res_name);
|
||||||
|
|
||||||
/* Find the asked device resource */
|
/* Find the asked device resource */
|
||||||
@@ -128,7 +128,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ai->handle = (void*)port;
|
ao->handle = (void*)port;
|
||||||
|
|
||||||
|
|
||||||
audio_set_format(ai, config);
|
audio_set_format(ai, config);
|
||||||
@@ -142,17 +142,17 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
return AUDIO_FORMAT_SIGNED_16;
|
return AUDIO_FORMAT_SIGNED_16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
ALport port = (ALport)ai->handle;
|
ALport port = (ALport)ao->handle;
|
||||||
|
|
||||||
if(ai->format == AUDIO_FORMAT_SIGNED_8)
|
if(ao->format == AUDIO_FORMAT_SIGNED_8)
|
||||||
alWriteFrames(port, buf, len>>1);
|
alWriteFrames(port, buf, len>>1);
|
||||||
else
|
else
|
||||||
alWriteFrames(port, buf, len>>2);
|
alWriteFrames(port, buf, len>>2);
|
||||||
@@ -160,20 +160,20 @@ int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
ALport port = (ALport)ai->handle;
|
ALport port = (ALport)ao->handle;
|
||||||
|
|
||||||
if (port) {
|
if (port) {
|
||||||
while(alGetFilled(port) > 0)
|
while(alGetFilled(port) > 0)
|
||||||
sginap(1);
|
sginap(1);
|
||||||
alClosePort(port);
|
alClosePort(port);
|
||||||
ai->handle=NULL;
|
ao->handle=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush(struct audio_info_struct *ai)
|
void audio_queueflush(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
audio_sun.c: audio output for Sun systems
|
sun: audio output for Sun systems
|
||||||
|
|
||||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2006 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "mpg123.h"
|
#include "mpg123.h"
|
||||||
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
@@ -34,10 +39,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void audio_set_format_helper(struct audio_info_struct *ai, audio_info_t *ainfo)
|
static void audio_set_format_helper(audio_output_t *ao, audio_info_t *ainfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(ai->format) {
|
switch(ao->format) {
|
||||||
case -1:
|
case -1:
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
default:
|
default:
|
||||||
@@ -69,99 +74,99 @@ static void audio_set_format_helper(struct audio_info_struct *ai, audio_info_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int audio_reset_parameters(struct audio_info_struct *ai)
|
static int audio_reset_parameters(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
|
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
|
|
||||||
if(ai->rate != -1)
|
if(ao->rate != -1)
|
||||||
ainfo.play.sample_rate = ai->rate;
|
ainfo.play.sample_rate = ao->rate;
|
||||||
if(ai->channels >= 0)
|
if(ao->channels >= 0)
|
||||||
ainfo.play.channels = ai->channels;
|
ainfo.play.channels = ao->channels;
|
||||||
audio_set_format_helper(ai,&ainfo);
|
audio_set_format_helper(ai,&ainfo);
|
||||||
|
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) == -1)
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_rate_best_match(struct audio_info_struct *ai)
|
static int audio_rate_best_match(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
|
|
||||||
ainfo.play.sample_rate = ai->rate;
|
ainfo.play.sample_rate = ao->rate;
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) < 0) {
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) < 0) {
|
||||||
ai->rate = 0;
|
ao->rate = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(ioctl(ai->fn, AUDIO_GETINFO, &ainfo) < 0) {
|
if(ioctl(ao->fn, AUDIO_GETINFO, &ainfo) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ai->rate = ainfo.play.sample_rate;
|
ao->rate = ainfo.play.sample_rate;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_rate(struct audio_info_struct *ai)
|
static int audio_set_rate(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
|
|
||||||
if(ai->rate != -1) {
|
if(ao->rate != -1) {
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
ainfo.play.sample_rate = ai->rate;
|
ainfo.play.sample_rate = ao->rate;
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) == -1)
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_channels(struct audio_info_struct *ai)
|
static int audio_set_channels(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
|
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
ainfo.play.channels = ai->channels;
|
ainfo.play.channels = ao->channels;
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) == -1)
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_set_format(struct audio_info_struct *ai)
|
static int audio_set_format(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
|
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
audio_set_format_helper(ai,&ainfo);
|
audio_set_format_helper(ai,&ainfo);
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) == -1)
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_open(struct audio_info_struct *ai)
|
int audio_open(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
|
|
||||||
if(!ai->device) {
|
if(!ao->device) {
|
||||||
if(getenv("AUDIODEV")) {
|
if(getenv("AUDIODEV")) {
|
||||||
if(param.verbose > 1)
|
if(param.verbose > 1)
|
||||||
fprintf(stderr,"Using audio-device value from AUDIODEV environment variable!\n");
|
fprintf(stderr,"Using audio-device value from AUDIODEV environment variable!\n");
|
||||||
ai->device = getenv("AUDIODEV");
|
ao->device = getenv("AUDIODEV");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ai->device = "/dev/audio";
|
ao->device = "/dev/audio";
|
||||||
}
|
}
|
||||||
|
|
||||||
ai->fn = open(ai->device,O_WRONLY);
|
ao->fn = open(ao->device,O_WRONLY);
|
||||||
if(ai->fn < 0)
|
if(ao->fn < 0)
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
|
|
||||||
#if defined(SUNOS) && defined(AUDIO_GETDEV)
|
#if defined(SUNOS) && defined(AUDIO_GETDEV)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
if(ioctl(ai->fn, AUDIO_GETDEV, &type) == -1)
|
if(ioctl(ao->fn, AUDIO_GETDEV, &type) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if(type == AUDIO_DEV_UNKNOWN || type == AUDIO_DEV_AMD)
|
if(type == AUDIO_DEV_UNKNOWN || type == AUDIO_DEV_AMD)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -170,7 +175,7 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
#if defined(SOLARIS) || defined(SPARCLINUX)
|
#if defined(SOLARIS) || defined(SPARCLINUX)
|
||||||
{
|
{
|
||||||
struct audio_device ad;
|
struct audio_device ad;
|
||||||
if(ioctl(ai->fn, AUDIO_GETDEV, &ad) == -1)
|
if(ioctl(ao->fn, AUDIO_GETDEV, &ad) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
if(param.verbose > 1)
|
if(param.verbose > 1)
|
||||||
fprintf(stderr,"Audio device type: %s\n",ad.name);
|
fprintf(stderr,"Audio device type: %s\n",ad.name);
|
||||||
@@ -180,36 +185,36 @@ int audio_open(struct audio_info_struct *ai)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(audio_reset_parameters(ai) < 0) {
|
if(audio_reset_parameters(ao) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
|
|
||||||
if(ai->output > 0)
|
if(ao->output > 0)
|
||||||
ainfo.play.port = 0;
|
ainfo.play.port = 0;
|
||||||
if(ai->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
if(ao->output & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||||
ainfo.play.port |= AUDIO_SPEAKER;
|
ainfo.play.port |= AUDIO_SPEAKER;
|
||||||
if(ai->output & AUDIO_OUT_HEADPHONES)
|
if(ao->output & AUDIO_OUT_HEADPHONES)
|
||||||
ainfo.play.port |= AUDIO_HEADPHONE;
|
ainfo.play.port |= AUDIO_HEADPHONE;
|
||||||
#ifdef AUDIO_LINE_OUT
|
#ifdef AUDIO_LINE_OUT
|
||||||
if(ai->output & AUDIO_OUT_LINE_OUT)
|
if(ao->output & AUDIO_OUT_LINE_OUT)
|
||||||
ainfo.play.port |= AUDIO_LINE_OUT;
|
ainfo.play.port |= AUDIO_LINE_OUT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(ai->gain != -1)
|
if(ao->gain != -1)
|
||||||
ainfo.play.gain = ai->gain;
|
ainfo.play.gain = ao->gain;
|
||||||
|
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) == -1)
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return ai->fn;
|
return ao->fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int audio_get_formats(struct audio_info_struct *ai)
|
int audio_get_formats(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
static int tab[][3] = {
|
static int tab[][3] = {
|
||||||
{ AUDIO_ENCODING_ULAW , 8, AUDIO_FORMAT_ULAW_8 } ,
|
{ AUDIO_ENCODING_ULAW , 8, AUDIO_FORMAT_ULAW_8 } ,
|
||||||
@@ -223,33 +228,33 @@ int audio_get_formats(struct audio_info_struct *ai)
|
|||||||
audio_info_t ainfo;
|
audio_info_t ainfo;
|
||||||
int i,fmts=0;
|
int i,fmts=0;
|
||||||
|
|
||||||
for(i=0;i<sizeof(tab)/sizeof(tab[0]);i++) {
|
for(i=0;i<4;i++) {
|
||||||
AUDIO_INITINFO(&ainfo);
|
AUDIO_INITINFO(&ainfo);
|
||||||
ainfo.play.encoding = tab[i][0];
|
ainfo.play.encoding = tab[i][0];
|
||||||
ainfo.play.precision = tab[i][1];
|
ainfo.play.precision = tab[i][1];
|
||||||
#if 1
|
#if 1
|
||||||
ainfo.play.sample_rate = ai->rate;
|
ainfo.play.sample_rate = ao->rate;
|
||||||
ainfo.play.channels = ai->channels;
|
ainfo.play.channels = ao->channels;
|
||||||
#endif
|
#endif
|
||||||
if(ioctl(ai->fn, AUDIO_SETINFO, &ainfo) >= 0) {
|
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) >= 0) {
|
||||||
fmts |= tab[i][2];
|
fmts |= tab[i][2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmts;
|
return fmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
|
int audio_play_samples(audio_output_t *ao,unsigned char *buf,int len)
|
||||||
{
|
{
|
||||||
return write(ai->fn,buf,len);
|
return write(ao->fn,buf,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int audio_close(struct audio_info_struct *ai)
|
int audio_close(audio_output_t *ao)
|
||||||
{
|
{
|
||||||
close (ai->fn);
|
close (ao->fn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_queueflush (struct audio_info_struct *ai)
|
void audio_queueflush (audio_output_t *ao)
|
||||||
{
|
{
|
||||||
/*ioctl (ai->fn, I_FLUSH, FLUSHRW);*/
|
/*ioctl (ao->fn, I_FLUSH, FLUSHRW);*/
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
audio_win32.c: audio output for Windows 32bit
|
win32: audio output for Windows 32bit
|
||||||
|
|
||||||
copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
|
copyright ?-2007 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
|
||||||
12
src/term.c
12
src/term.c
@@ -19,6 +19,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
extern int buffer_pid;
|
extern int buffer_pid;
|
||||||
|
extern audio_output_t ao;
|
||||||
|
|
||||||
static int term_enable = 0;
|
static int term_enable = 0;
|
||||||
static struct termios old_tio;
|
static struct termios old_tio;
|
||||||
@@ -75,7 +76,7 @@ static int stopped = 0;
|
|||||||
static int paused = 0;
|
static int paused = 0;
|
||||||
static int pause_cycle;
|
static int pause_cycle;
|
||||||
|
|
||||||
long term_control(struct frame *fr, struct audio_info_struct *ai)
|
long term_control(struct frame *fr, audio_output_t *ao)
|
||||||
{
|
{
|
||||||
long offset = 0;
|
long offset = 0;
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ long term_control(struct frame *fr, struct audio_info_struct *ai)
|
|||||||
offset += term_handle_input(fr, stopped);
|
offset += term_handle_input(fr, stopped);
|
||||||
if((offset < 0) && (-offset > fr->num)) offset = - fr->num;
|
if((offset < 0) && (-offset > fr->num)) offset = - fr->num;
|
||||||
if(param.verbose && offset != 0)
|
if(param.verbose && offset != 0)
|
||||||
print_stat(fr,fr->num+offset,0,ai);
|
print_stat(fr,fr->num+offset,0,ao);
|
||||||
} while (stopped);
|
} while (stopped);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
@@ -114,7 +115,6 @@ static long term_handle_input(struct frame *fr, int do_delay)
|
|||||||
{
|
{
|
||||||
int n = 1;
|
int n = 1;
|
||||||
long offset = 0;
|
long offset = 0;
|
||||||
extern struct audio_info_struct ai;
|
|
||||||
|
|
||||||
while(n > 0) {
|
while(n > 0) {
|
||||||
fd_set r;
|
fd_set r;
|
||||||
@@ -133,7 +133,7 @@ static long term_handle_input(struct frame *fr, int do_delay)
|
|||||||
|
|
||||||
switch(tolower(val)) {
|
switch(tolower(val)) {
|
||||||
case BACK_KEY:
|
case BACK_KEY:
|
||||||
if(!param.usebuffer) audio_queueflush(&ai);
|
if(!param.usebuffer) ao.flush(&ao);
|
||||||
/*
|
/*
|
||||||
* NOTE: rd->rewind() calls buffer_resync() that blocks until
|
* NOTE: rd->rewind() calls buffer_resync() that blocks until
|
||||||
* buffer process returns ACK. If buffer process is stopped, we
|
* buffer process returns ACK. If buffer process is stopped, we
|
||||||
@@ -154,7 +154,7 @@ static long term_handle_input(struct frame *fr, int do_delay)
|
|||||||
fr->num=0;
|
fr->num=0;
|
||||||
break;
|
break;
|
||||||
case NEXT_KEY:
|
case NEXT_KEY:
|
||||||
if(!param.usebuffer) audio_queueflush(&ai);
|
if(!param.usebuffer) ao.flush(&ao);
|
||||||
plain_buffer_resync();
|
plain_buffer_resync();
|
||||||
next_track();
|
next_track();
|
||||||
break;
|
break;
|
||||||
@@ -178,7 +178,7 @@ static long term_handle_input(struct frame *fr, int do_delay)
|
|||||||
case STOP_KEY:
|
case STOP_KEY:
|
||||||
case ' ':
|
case ' ':
|
||||||
/* when seeking while stopped and then resuming, I want to prevent the chirp from the past */
|
/* when seeking while stopped and then resuming, I want to prevent the chirp from the past */
|
||||||
if(!param.usebuffer) audio_queueflush(&ai);
|
if(!param.usebuffer) ao.flush(&ao);
|
||||||
stopped=1-stopped;
|
stopped=1-stopped;
|
||||||
if(paused) {
|
if(paused) {
|
||||||
paused=0;
|
paused=0;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
#define EMPTY_STRING " \b\b\b\b\b\b\b\b"
|
#define EMPTY_STRING " \b\b\b\b\b\b\b\b"
|
||||||
|
|
||||||
void term_init(void);
|
void term_init(void);
|
||||||
long term_control(struct frame *fr, struct audio_info_struct *ai);
|
long term_control(struct frame *fr, audio_output_t *ao);
|
||||||
void term_restore(void);
|
void term_restore(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
36
src/wav.c
36
src/wav.c
@@ -169,7 +169,7 @@ static int open_file(char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int au_open(struct audio_info_struct *ai, char *aufilename)
|
int au_open(audio_output_t *ao, char *aufilename)
|
||||||
{
|
{
|
||||||
#ifdef FLOATOUT
|
#ifdef FLOATOUT
|
||||||
error("AU file support for float values not there yet");
|
error("AU file support for float values not there yet");
|
||||||
@@ -177,7 +177,7 @@ int au_open(struct audio_info_struct *ai, char *aufilename)
|
|||||||
#else
|
#else
|
||||||
flipendian = 0;
|
flipendian = 0;
|
||||||
|
|
||||||
switch(ai->format) {
|
switch(ao->format) {
|
||||||
case AUDIO_FORMAT_SIGNED_16:
|
case AUDIO_FORMAT_SIGNED_16:
|
||||||
{
|
{
|
||||||
int endiantest = testEndian();
|
int endiantest = testEndian();
|
||||||
@@ -187,7 +187,7 @@ int au_open(struct audio_info_struct *ai, char *aufilename)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AUDIO_FORMAT_UNSIGNED_8:
|
case AUDIO_FORMAT_UNSIGNED_8:
|
||||||
ai->format = AUDIO_FORMAT_ULAW_8;
|
ao->format = AUDIO_FORMAT_ULAW_8;
|
||||||
case AUDIO_FORMAT_ULAW_8:
|
case AUDIO_FORMAT_ULAW_8:
|
||||||
long2bigendian(1,auhead.encoding,sizeof(auhead.encoding));
|
long2bigendian(1,auhead.encoding,sizeof(auhead.encoding));
|
||||||
break;
|
break;
|
||||||
@@ -197,8 +197,8 @@ int au_open(struct audio_info_struct *ai, char *aufilename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
long2bigendian(0xffffffff,auhead.datalen,sizeof(auhead.datalen));
|
long2bigendian(0xffffffff,auhead.datalen,sizeof(auhead.datalen));
|
||||||
long2bigendian(ai->rate,auhead.rate,sizeof(auhead.rate));
|
long2bigendian(ao->rate,auhead.rate,sizeof(auhead.rate));
|
||||||
long2bigendian(ai->channels,auhead.channels,sizeof(auhead.channels));
|
long2bigendian(ao->channels,auhead.channels,sizeof(auhead.channels));
|
||||||
|
|
||||||
if(open_file(aufilename) < 0)
|
if(open_file(aufilename) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -210,18 +210,18 @@ int au_open(struct audio_info_struct *ai, char *aufilename)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int cdr_open(struct audio_info_struct *ai, char *cdrfilename)
|
int cdr_open(audio_output_t *ao, char *cdrfilename)
|
||||||
{
|
{
|
||||||
#ifdef FLOATOUT
|
#ifdef FLOATOUT
|
||||||
error("refusing to produce cdr file with float values");
|
error("refusing to produce cdr file with float values");
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
param.force_stereo = 0;
|
param.force_stereo = 0;
|
||||||
ai->format = AUDIO_FORMAT_SIGNED_16;
|
ao->format = AUDIO_FORMAT_SIGNED_16;
|
||||||
ai->rate = 44100;
|
ao->rate = 44100;
|
||||||
ai->channels = 2;
|
ao->channels = 2;
|
||||||
/*
|
/*
|
||||||
if(ai->format != AUDIO_FORMAT_SIGNED_16 || ai->rate != 44100 || ai->channels != 2) {
|
if(ao->format != AUDIO_FORMAT_SIGNED_16 || ao->rate != 44100 || ao->channels != 2) {
|
||||||
fprintf(stderr,"Oops .. not forced to 16 bit, 44kHz?, stereo\n");
|
fprintf(stderr,"Oops .. not forced to 16 bit, 44kHz?, stereo\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ int cdr_open(struct audio_info_struct *ai, char *cdrfilename)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int wav_open(struct audio_info_struct *ai, char *wavfilename)
|
int wav_open(audio_output_t *ao, char *wavfilename)
|
||||||
{
|
{
|
||||||
int bps;
|
int bps;
|
||||||
|
|
||||||
@@ -248,11 +248,11 @@ int wav_open(struct audio_info_struct *ai, char *wavfilename)
|
|||||||
long2littleendian(bps=32,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
long2littleendian(bps=32,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
||||||
flipendian = testEndian();
|
flipendian = testEndian();
|
||||||
#else
|
#else
|
||||||
if(ai->format == AUDIO_FORMAT_SIGNED_16) {
|
if(ao->format == AUDIO_FORMAT_SIGNED_16) {
|
||||||
long2littleendian(bps=16,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
long2littleendian(bps=16,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
||||||
flipendian = testEndian();
|
flipendian = testEndian();
|
||||||
}
|
}
|
||||||
else if(ai->format == AUDIO_FORMAT_UNSIGNED_8)
|
else if(ao->format == AUDIO_FORMAT_UNSIGNED_8)
|
||||||
long2littleendian(bps=8,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
long2littleendian(bps=8,RIFF.WAVE.fmt.BitsPerSample,sizeof(RIFF.WAVE.fmt.BitsPerSample));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -261,13 +261,13 @@ int wav_open(struct audio_info_struct *ai, char *wavfilename)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(ai->rate < 0) ai->rate = 44100;
|
if(ao->rate < 0) ao->rate = 44100;
|
||||||
|
|
||||||
long2littleendian(ai->channels,RIFF.WAVE.fmt.Channels,sizeof(RIFF.WAVE.fmt.Channels));
|
long2littleendian(ao->channels,RIFF.WAVE.fmt.Channels,sizeof(RIFF.WAVE.fmt.Channels));
|
||||||
long2littleendian(ai->rate,RIFF.WAVE.fmt.SamplesPerSec,sizeof(RIFF.WAVE.fmt.SamplesPerSec));
|
long2littleendian(ao->rate,RIFF.WAVE.fmt.SamplesPerSec,sizeof(RIFF.WAVE.fmt.SamplesPerSec));
|
||||||
long2littleendian((int)(ai->channels * ai->rate * bps)>>3,
|
long2littleendian((int)(ao->channels * ao->rate * bps)>>3,
|
||||||
RIFF.WAVE.fmt.AvgBytesPerSec,sizeof(RIFF.WAVE.fmt.AvgBytesPerSec));
|
RIFF.WAVE.fmt.AvgBytesPerSec,sizeof(RIFF.WAVE.fmt.AvgBytesPerSec));
|
||||||
long2littleendian((int)(ai->channels * bps)>>3,
|
long2littleendian((int)(ao->channels * bps)>>3,
|
||||||
RIFF.WAVE.fmt.BlockAlign,sizeof(RIFF.WAVE.fmt.BlockAlign));
|
RIFF.WAVE.fmt.BlockAlign,sizeof(RIFF.WAVE.fmt.BlockAlign));
|
||||||
|
|
||||||
if(open_file(wavfilename) < 0)
|
if(open_file(wavfilename) < 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user