Mercurial > mplayer.hg
changeset 36463:c6843e5bf166
libao2: Add sndio audio output module.
Patch by Alexandre Ratchov [alex caoua org].
author | reimar |
---|---|
date | Tue, 31 Dec 2013 15:30:49 +0000 |
parents | b72daec4e223 |
children | cae4a4a36016 |
files | Makefile configure libao2/ao_sndio.c libao2/audio_out.c |
diffstat | 4 files changed, 283 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sun Dec 22 20:36:52 2013 +0000 +++ b/Makefile Tue Dec 31 15:30:49 2013 +0000 @@ -572,6 +572,7 @@ libvo/vo_sdl.c \ libvo/sdl_common.c SRCS_MPLAYER-$(SGIAUDIO) += libao2/ao_sgi.c +SRCS_MPLAYER-$(SNDIO) += libao2/ao_sndio.c SRCS_MPLAYER-$(SUNAUDIO) += libao2/ao_sun.c SRCS_MPLAYER-$(SVGA) += libvo/vo_svga.c SRCS_MPLAYER-$(TDFXFB) += libvo/vo_tdfxfb.c
--- a/configure Sun Dec 22 20:36:52 2013 +0000 +++ b/configure Tue Dec 31 15:30:49 2013 +0000 @@ -522,6 +522,7 @@ --disable-openal disable OpenAL audio output [autodetect] --disable-nas disable NAS audio output [autodetect] --disable-sgiaudio disable SGI audio output [autodetect] + --disable-sndio disable sndio audio output [autodetect] --disable-sunaudio disable Sun audio output [autodetect] --disable-kai disable KAI audio output [autodetect] --disable-dart disable DART audio output [autodetect] @@ -755,6 +756,7 @@ _xf86keysym=auto _mlib=no #broken, thus disabled _sgiaudio=auto +_sndio=auto _sunaudio=auto _alsa=auto _fastmemcpy=yes @@ -1197,6 +1199,8 @@ --disable-sunaudio) _sunaudio=no ;; --enable-sgiaudio) _sgiaudio=yes ;; --disable-sgiaudio) _sgiaudio=no ;; + --enable-sndio) _sndio=yes ;; + --disable-sndio) _sndio=no ;; --enable-alsa) _alsa=yes ;; --disable-alsa) _alsa=no ;; --enable-tv) _tv=yes ;; @@ -5876,6 +5880,22 @@ fi #if irix +echocheck "sndio audio" +if test "$_sndio" = auto ; then + _sndio=no + statement_check sndio.h 'sio_open(SIO_DEVANY, SIO_PLAY, 0)' -lsndio && _sndio=yes +fi +if test "$_sndio" = yes ; then + def_sndio='#define CONFIG_SNDIO_AUDIO 1' + aomodules="sndio $aomodules" + extra_ldflags="$extra_ldflags -lsndio" +else + def_sndio='#undef CONFIG_SNDIO_AUDIO' + noaomodules="sndio $noaomodules" +fi +echores "$_sndio" + + if os2 ; then echocheck "KAI (UNIAUD/DART)" if test "$_kai" = auto; then @@ -8458,6 +8478,7 @@ SPEEX = $_speex STREAM_CACHE = $_stream_cache SGIAUDIO = $_sgiaudio +SNDIO = $_sndio SUNAUDIO = $_sunaudio SVGA = $_svga TDFXFB = $_tdfxfb @@ -8895,6 +8916,7 @@ $def_ossaudio_devmixer $def_pulse $def_sgiaudio +$def_sndio $def_sunaudio $def_win32waveout
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libao2/ao_sndio.c Tue Dec 31 15:30:49 2013 +0000 @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> + * + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include <sys/types.h> +#include <poll.h> +#include <errno.h> +#include <sndio.h> +#include <stdlib.h> + +#include "config.h" +#include "mp_msg.h" +#include "mixer.h" +#include "help_mp.h" + +#include "libaf/af_format.h" + +#include "audio_out.h" +#include "audio_out_internal.h" + +static ao_info_t info = { + "sndio audio output", + "sndio", + "Alexandre Ratchov <alex@caoua.org>", + "" +}; + +LIBAO_EXTERN(sndio) + +static struct sio_hdl *hdl = NULL; +struct pollfd *pfds = NULL; +static struct sio_par par; +static int delay, vol, havevol; +static int prepause_delay; + +/* + * control misc parameters (only the volume for now) + */ +static int control(int cmd, void *arg) +{ + ao_control_vol_t *ctl = arg; + + switch (cmd) { + case AOCONTROL_GET_VOLUME: + if (!havevol) + return CONTROL_FALSE; + ctl->left = ctl->right = vol * 100 / SIO_MAXVOL; + break; + case AOCONTROL_SET_VOLUME: + if (!havevol) + return CONTROL_FALSE; + sio_setvol(hdl, ctl->left * SIO_MAXVOL / 100); + break; + default: + return CONTROL_UNKNOWN; + } + return CONTROL_OK; +} + +/* + * call-back invoked whenever the the hardware position changes + */ +static void movecb(void *addr, int delta) +{ + delay -= delta * (int)(par.bps * par.pchan); +} + +/* + * call-back invoked whenever the volume changes + */ +static void volcb(void *addr, unsigned newvol) +{ + vol = newvol; +} + +/* + * open device and setup parameters + * return: 1 = success, 0 = failure + */ +static int init(int rate, int channels, int format, int flags) +{ + int bpf; + + hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0); + if (hdl == NULL) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: can't open sndio\n"); + return 0; + } + sio_initpar(&par); + par.bits = af_fmt2bits(format); + par.sig = (format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_SI; + if (par.bits > 8) + par.le = (format & AF_FORMAT_END_MASK) == AF_FORMAT_LE; + par.rate = rate; + par.pchan = channels; + par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */ + par.round = par.rate * 10 / 1000; /* 10ms block size */ + if (!sio_setpar(hdl, &par)) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: couldn't set params\n"); + goto bad_close; + } + if (!sio_getpar(hdl, &par)) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: couldn't get params\n"); + goto bad_close; + } + if (par.bps != SIO_BPS(par.bits)) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: unsupported format\n"); + goto bad_close; + } + pfds = calloc(sio_nfds(hdl), sizeof(*pfds)); + if (pfds == NULL) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: couldn't allocate poll fds\n"); + goto bad_close; + } + bpf = par.bps * par.pchan; + ao_data.format = af_bits2fmt(8 * par.bps); + ao_data.format |= par.sig ? AF_FORMAT_SI : AF_FORMAT_US; + if (par.bits > 8) + ao_data.format |= par.le ? AF_FORMAT_LE : AF_FORMAT_BE; + ao_data.channels = par.pchan; + ao_data.bps = bpf * par.rate; + ao_data.buffersize = par.bufsz * bpf; + ao_data.outburst = par.round * bpf; + ao_data.samplerate = rate; + havevol = sio_onvol(hdl, volcb, NULL); + sio_onmove(hdl, movecb, NULL); + + /* + * prepare the device to start. It will start as soon there's enough + * data in the buffer to not underrun + */ + delay = 0; + if (!sio_start(hdl)) { + mp_msg(MSGT_AO, MSGL_ERR, "ao2: init: couldn't start\n"); + goto bad_free; + } + return 1; +bad_free: + free(pfds); + pfds = NULL; +bad_close: + sio_close(hdl); + hdl = NULL; + return 0; +} + +/* + * close device + */ +static void uninit(int immed) +{ + if (hdl) + sio_close(hdl); + if (pfds) + free(pfds); +} + +/* + * stop playing and prepare to restart + */ +static void reset(void) +{ + if (!sio_stop(hdl)) + mp_msg(MSGT_AO, MSGL_ERR, "ao2: reset: couldn't stop\n"); + delay = 0; + if (!sio_start(hdl)) + mp_msg(MSGT_AO, MSGL_ERR, "ao2: reset: couldn't start\n"); +} + +/* + * refresh the "delay" counter: call sio_revents() which keeps track of + * the hardware position + */ +static void refresh(void) +{ + int n; + + n = sio_pollfd(hdl, pfds, POLLOUT); + while (poll(pfds, n, 0) < 0 && errno == EINTR) + ; /* nothing */ + sio_revents(hdl, pfds); +} + +/* + * return the number of bytes available in the device buffer + */ +static int get_space(void) +{ + refresh(); + return par.bufsz * par.pchan * par.bps - delay; +} + +/* + * delay in seconds between first and last sample in the buffer + */ +static float get_delay(void) +{ + refresh(); + return (float)delay / (par.bps * par.pchan * par.rate); +} + +/* + * submit the given number of bytes to the device + */ +static int play(void *data, int len, int flags) +{ + int n; + + n = sio_write(hdl, data, len); + delay += n; + return n; +} + +/* + * pause playing + */ +static void audio_pause(void) +{ + /* + * sndio can't pause, so just stop + */ + prepause_delay = delay; + if (!sio_stop(hdl)) + mp_msg(MSGT_AO, MSGL_ERR, "ao2: pause: couldn't stop\n"); + delay = 0; +} + +/* + * resume playing after audio_pause() + */ +static void audio_resume(void) +{ + /* + * prepare to start; then refill the buffer with the number of bytes + * audio_pause() consumed (this will trigger start) + */ + if (!sio_start(hdl)) + mp_msg(MSGT_AO, MSGL_ERR, "ao2: resume: couldn't start\n"); + mp_ao_resume_refill(&audio_out_sndio, + par.bufsz * par.pchan * par.bps - prepause_delay); +}
--- a/libao2/audio_out.c Sun Dec 22 20:36:52 2013 +0000 +++ b/libao2/audio_out.c Tue Dec 31 15:30:49 2013 +0000 @@ -40,6 +40,7 @@ extern const ao_functions_t audio_out_openal; extern const ao_functions_t audio_out_null; extern const ao_functions_t audio_out_alsa; +extern const ao_functions_t audio_out_sndio; extern const ao_functions_t audio_out_nas; extern const ao_functions_t audio_out_sdl; extern const ao_functions_t audio_out_sun; @@ -73,6 +74,9 @@ #ifdef CONFIG_COREAUDIO &audio_out_coreaudio, #endif +#ifdef CONFIG_SNDIO_AUDIO + &audio_out_sndio, +#endif #ifdef CONFIG_OSS_AUDIO &audio_out_oss, #endif