diff --git a/configure.in b/configure.in index 4f10340..c532167 100644 --- a/configure.in +++ b/configure.in @@ -859,8 +859,9 @@ dnl speex(S): Ogg Speex dnl gogo(g): MP3 GOGO dnl jack(j): JACK dnl ao(O): Libao +dnl sndio(o): sndio -audio_targets='default oss alsa sun hpux irix mme sb_dsp w32 alib nas arts esd vorbis flac gogo portaudio npipe jack ao' +audio_targets='default oss alsa sun hpux irix mme sb_dsp w32 alib nas arts esd vorbis flac gogo portaudio npipe jack ao sndio' AC_ARG_WITH(nas-library, AS_HELP_STRING([--with-nas-library=library], [NAS absolute library path(Don't use -laudio)])) @@ -888,6 +889,7 @@ AC_ARG_ENABLE(audio, npipe: Named Pipe(windows) jack: JACK ao: Libao + sndio: sndio vorbis: Ogg Vorbis flac: FLAC / OggFLAC speex: Ogg Speex @@ -914,7 +916,7 @@ AC_ARG_WITH(default-output, [Specify default output mode (optional): (default|alsa|alib|arts|nas| esd|wav|au|aiff|list|vorbis|flac|speex| - gogo|portaudio|npipe|jack|ao)]), + gogo|portaudio|npipe|jack|ao|sndio)]), [ if test "$enable_audio" != no; then DEFAULT_PLAYMODE=$withval eval "au_enable_$DEFAULT_PLAYMODE=yes" @@ -1356,6 +1358,22 @@ else AC_MSG_RESULT(no) fi +dnl sndio +AC_MSG_CHECKING(enable_audio=sndio) +if test "x$au_enable_sndio" = xyes; then + AC_MSG_RESULT([yes, configuring sndio]) + AC_CHECK_HEADERS(sndio.h) + if test "x${ac_cv_header_sndio_h}" = xyes ; then + EXTRADEFS="$EXTRADEFS -DAU_SNDIO" + SYSEXTRAS="$SYSEXTRAS sndio_a.c" + EXTRALIBS="$EXTRALIBS -lsndio" + else + AC_MSG_WARN(Couldn't configure sndio.) + fi +else + AC_MSG_RESULT(no) +fi + dnl ogg's vorbis AC_MSG_CHECKING(enable_audio=vorbis) if test "x$au_enable_vorbis" = xyes; then @@ -1511,6 +1529,7 @@ case ".$DEFAULT_PLAYMODE" in .gogo) TIMIDITY_OUTPUT_ID=g ;; .jack) TIMIDITY_OUTPUT_ID=j ;; .ao) TIMIDITY_OUTPUT_ID=O ;; + .sndio) TIMIDITY_OUTPUT_ID=o ;; *) TIMIDITY_OUTPUT_ID= ;; esac AC_MSG_RESULT($DEFAULT_PLAYMODE/$TIMIDITY_OUTPUT_ID) diff --git a/timidity/Makefile.am b/timidity/Makefile.am index 4802b5f..d8e52b8 100644 --- a/timidity/Makefile.am +++ b/timidity/Makefile.am @@ -139,6 +139,7 @@ EXTRA_timidity_SOURCES = \ mfnode.h \ nas_a.c \ portaudio_a.c \ + sndio_a.c \ npipe_a.c \ sun_a.c \ vorbis_a.c \ diff --git a/timidity/output.c b/timidity/output.c index 2fec198..84dac8e 100644 --- a/timidity/output.c +++ b/timidity/output.c @@ -116,6 +116,10 @@ extern PlayMode nas_play_mode; extern PlayMode ao_play_mode; #endif /* AU_AO */ +#ifdef AU_SNDIO +extern PlayMode sndio_play_mode; +#endif /* AU_SNDIO */ + #ifndef __MACOS__ /* These are always compiled in. */ extern PlayMode raw_play_mode, wave_play_mode, au_play_mode, aiff_play_mode; @@ -142,6 +146,10 @@ PlayMode *play_mode_list[] = { &ao_play_mode, #endif /* AU_AO */ +#if defined(AU_SNDIO) + &sndio_play_mode, +#endif /* AU_SNDIO */ + #if defined(AU_ARTS) &arts_play_mode, #endif /* AU_ARTS */ diff --git b/timidity/sndio_a.c b/timidity/sndio_a.c new file mode 100644 index 0000000..22ad939 --- /dev/null +++ b/timidity/sndio_a.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2008 IWATA Ray + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ +#include + +#include "timidity.h" +#include "output.h" +#include "controls.h" +#include "timer.h" +#include "instrum.h" +#include "playmidi.h" +#include "miditrace.h" + +static int open_output(void); /* 0=success, 1=warning, -1=fatal error */ +static void close_output(void); +static int output_data(char *buf, int32 nbytes); +static int acntl(int request, void *arg); + +/* export the playback mode */ + +#define dpm sndio_play_mode + +PlayMode dpm = { + DEFAULT_RATE, PE_SIGNED|PE_16BIT, PF_PCM_STREAM, + -1, + {0}, /* default: get all the buffer fragments you can */ + "sndio mode", 'o', + NULL, + open_output, + close_output, + output_data, + acntl +}; + +static struct sio_hdl *sndio_ctx; + +static int open_output(void) +{ + static struct sio_par par, newpar; + + sndio_ctx = sio_open(NULL, SIO_PLAY, 0); + if (sndio_ctx == NULL) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_open() failed"); + return -1; + } + + sio_initpar(&par); + + par.sig = 1; + par.pchan = (dpm.encoding & PE_MONO) ? 1 : 2; + par.le = SIO_LE_NATIVE; + par.rate = dpm.rate; + if (dpm.encoding & PE_24BIT) { + par.bits = 24; + par.bps = 3; + } else if (dpm.encoding & PE_16BIT) { + par.bits = 16; + par.bps = 2; + } else { + par.bits = 8; + par.bps = 1; + } + + if (!sio_setpar(sndio_ctx, &par)) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_setpar() failed"); + return -1; + } + + if (sio_getpar(sndio_ctx, &newpar) == 0) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_getpar() failed"); + return -1; + } + if (newpar.sig != par.sig || + newpar.le != par.le || + newpar.pchan != par.pchan || + newpar.bits != par.bits || + newpar.bps != par.bps || + newpar.rate * 1000 > par.rate * 1005 || + newpar.rate * 1000 < par.rate * 995) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "couldn't set output play parameters"); + return -1; + } + + if (!sio_start(sndio_ctx)) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_start() failed"); + return -1; + } + return 0; +} + +static int output_data(char *buf, int32 nbytes) +{ + if (!sio_write(sndio_ctx, buf, nbytes)) { + ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "sio_write() failed"); + return -1; + } + return 0; +} + +static void close_output(void) +{ + if (sndio_ctx != NULL) { + sio_close(sndio_ctx); + sndio_ctx = NULL; + } +} + +static int acntl(int request, void *arg) +{ + switch(request) { + case PM_REQ_DISCARD: + case PM_REQ_PLAY_START: /* Called just before playing */ + case PM_REQ_PLAY_END: /* Called just after playing */ + return 0; + } + return -1; +} + diff --git a/timidity/timidity.c b/timidity/timidity.c index 4a4d601..894f55a 100644 --- a/timidity/timidity.c +++ b/timidity/timidity.c @@ -4049,7 +4049,8 @@ static int parse_opt_h(const char *arg) " `l' linear encoding" NLS " `U' U-Law encoding" NLS " `A' A-Law encoding" NLS -" `x' byte-swapped output" NLS, fp); +" `x' byte-swapped output" NLS +" `o' signed output" NLS, fp); fputs(NLS, fp); fputs("Alternative output format long options:" NLS " --output-stereo" NLS