diff --git a/configure.ac b/configure.ac index 71108fc..53b6e3d 100644 --- a/configure.ac +++ b/configure.ac @@ -147,6 +147,15 @@ if test x"$enable_oss" != x"no"; then esac fi +dnl check for sndio +AC_ARG_ENABLE([sndio], + [ --disable-sndio make a version not using sndio]) +if test x"$enable_sndio" != x"no"; then + AC_DEFINE([LIBAO_SNDIO],,[libao sndio support]) + AC_CHECK_LIB([sndio],[sio_initpar], + [LIBAO_LIBS="$LIBAO_LIBS -lsndio"]) +fi + dnl check for solaris AC_ARG_ENABLE([solaris-audio], [ --disable-solaris-audio make a version not using solaris audio]) diff --git a/libao/Makefile.am b/libao/Makefile.am index 39c8a80..77ed9a0 100644 --- a/libao/Makefile.am +++ b/libao/Makefile.am @@ -3,7 +3,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LTLIBRARIES = libao.la libao_la_SOURCES = audio_out.c audio_out_null.c audio_out_float.c \ - audio_out_oss.c audio_out_solaris.c audio_out_al.c \ + audio_out_oss.c audio_out_sndio.c audio_out_solaris.c audio_out_al.c \ audio_out_win.c audio_out_wav.c audio_out_aif.c \ audio_out_peak.c convert2s16.c \ audio_out_internal.h diff --git a/libao/audio_out.c b/libao/audio_out.c index 8de05b1..5240992 100644 --- a/libao/audio_out.c +++ b/libao/audio_out.c @@ -34,6 +34,10 @@ extern ao_open_t ao_oss_open; extern ao_open_t ao_ossdolby_open; extern ao_open_t ao_oss4_open; extern ao_open_t ao_oss6_open; +extern ao_open_t ao_sndio_open; +extern ao_open_t ao_sndiodolby_open; +extern ao_open_t ao_sndio4_open; +extern ao_open_t ao_sndio6_open; extern ao_open_t ao_solaris_open; extern ao_open_t ao_solarisdolby_open; extern ao_open_t ao_al_open; @@ -62,6 +66,12 @@ static ao_driver_t audio_out_drivers[] = { {"oss4", ao_oss4_open}, {"oss6", ao_oss6_open}, #endif +#ifdef LIBAO_SNDIO + {"sndio", ao_sndio_open}, + {"sndiodolby", ao_sndiodolby_open}, + {"sndio4", ao_sndio4_open}, + {"sndio6", ao_sndio6_open}, +#endif #ifdef LIBAO_SOLARIS {"solaris", ao_solaris_open}, {"solarisdolby", ao_solarisdolby_open}, diff --git b/libao/audio_out_sndio.c b/libao/audio_out_sndio.c new file mode 100644 index 0000000..e3908d3 --- /dev/null +++ b/libao/audio_out_sndio.c @@ -0,0 +1,170 @@ +/* + * audio_out_sndio.c + * Copyright (C) 2000-2003 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of a52dec, a free ATSC A-52 stream decoder. + * See http://liba52.sourceforge.net/ for updates. + * + * a52dec is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * a52dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#ifdef LIBAO_SNDIO + +#include +#include +#include +#include + +#include "dca.h" +#include "audio_out.h" +#include "audio_out_internal.h" + +typedef struct sndio_instance_s { + ao_instance_t ao; + struct sio_hdl *hdl; + int sample_rate; + int set_params; + int flags; +} sndio_instance_t; + +static int sndio_setup (ao_instance_t * _instance, int sample_rate, int * flags, + level_t * level, sample_t * bias) +{ + sndio_instance_t * instance = (sndio_instance_t *) _instance; + + if ((instance->set_params == 0) && (instance->sample_rate != sample_rate)) + return 1; + instance->sample_rate = sample_rate; + + *flags = instance->flags; + *level = CONVERT_LEVEL; + *bias = CONVERT_BIAS; + + return 0; +} + +static int sndio_play (ao_instance_t * _instance, int flags, sample_t * _samples) +{ + sndio_instance_t * instance = (sndio_instance_t *) _instance; + int16_t int16_samples[256*6]; + int chans = -1; + +#ifdef LIBDCA_DOUBLE + convert_t samples[256 * 6]; + int i; + + for (i = 0; i < 256 * 6; i++) + samples[i] = _samples[i]; +#else + convert_t * samples = _samples; +#endif + + chans = channels_multi (flags); + flags &= DCA_CHANNEL_MASK | DCA_LFE; + + if (instance->set_params) { + struct sio_par par; + + sio_initpar(&par); + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + par.pchan = chans; + par.rate = instance->sample_rate; + if (!sio_setpar(instance->hdl, &par) || !sio_setpar(instance->hdl, &par)) { + fprintf (stderr, "Can not set audio parameters\n"); + return 1; + } + if (par.bits != 16 || par.sig != 1 || par.le != SIO_LE_NATIVE || + par.pchan != chans || par.rate != instance->sample_rate) { + fprintf (stderr, "Unsupported audio parameters\n"); + return 1; + } + instance->flags = flags; + instance->set_params = 0; + sio_start(instance->hdl); + } else if ((flags == DCA_DOLBY) && (instance->flags == DCA_STEREO)) { + fprintf (stderr, "Switching from stereo to dolby surround\n"); + instance->flags = DCA_DOLBY; + } else if ((flags == DCA_STEREO) && (instance->flags == DCA_DOLBY)) { + fprintf (stderr, "Switching from dolby surround to stereo\n"); + instance->flags = DCA_STEREO; + } else if (flags != instance->flags) + return 1; + + convert2s16_multi (samples, int16_samples, flags); + sio_write (instance->hdl, int16_samples, 256 * sizeof (int16_t) * chans); + + return 0; +} + +static void sndio_close (ao_instance_t * _instance) +{ + sndio_instance_t * instance = (sndio_instance_t *) _instance; + + sio_close (instance->hdl); +} + +static ao_instance_t * sndio_open (int flags) +{ + sndio_instance_t * instance; + + instance = (sndio_instance_t *) malloc (sizeof (sndio_instance_t)); + if (instance == NULL) + return NULL; + + instance->ao.setup = sndio_setup; + instance->ao.play = sndio_play; + instance->ao.close = sndio_close; + + instance->sample_rate = 0; + instance->set_params = 1; + instance->flags = flags; + + instance->hdl = sio_open (SIO_DEVANY, SIO_PLAY, 0); + if (instance->hdl == NULL) { + fprintf (stderr, "Can not open " SIO_DEVANY " device\n"); + free (instance); + return NULL; + } + + return (ao_instance_t *) instance; +} + +ao_instance_t * ao_sndio_open (void) +{ + return sndio_open (DCA_STEREO); +} + +ao_instance_t * ao_sndiodolby_open (void) +{ + return sndio_open (DCA_DOLBY); +} + +ao_instance_t * ao_sndio4_open (void) +{ + return sndio_open (DCA_2F2R); +} + +ao_instance_t * ao_sndio6_open (void) +{ + return sndio_open (DCA_3F2R | DCA_LFE); +} + +#endif