Skip to content

Commit

Permalink
libao2: Add sndio audio output module.
Browse files Browse the repository at this point in the history
Patch by Alexandre Ratchov [alex caoua org].

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@36559 b3059339-0415-0410-9bf9-f77b7e298cf2
  • Loading branch information
reimar committed Dec 31, 2013
1 parent bce6ca0 commit 60d8680
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ SRCS_MPLAYER-$(SDL) += libao2/ao_sdl.c \
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
Expand Down
22 changes: 22 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ Audio output:
--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]
Expand Down Expand Up @@ -755,6 +756,7 @@ _vm=auto
_xf86keysym=auto
_mlib=no #broken, thus disabled
_sgiaudio=auto
_sndio=auto
_sunaudio=auto
_alsa=auto
_fastmemcpy=yes
Expand Down Expand Up @@ -1197,6 +1199,8 @@ for ac_option do
--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 ;;
Expand Down Expand Up @@ -5876,6 +5880,22 @@ echores "$_sgiaudio"
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
Expand Down Expand Up @@ -8458,6 +8478,7 @@ SDL_IMAGE = $sdl_image
SPEEX = $_speex
STREAM_CACHE = $_stream_cache
SGIAUDIO = $_sgiaudio
SNDIO = $_sndio
SUNAUDIO = $_sunaudio
SVGA = $_svga
TDFXFB = $_tdfxfb
Expand Down Expand Up @@ -8895,6 +8916,7 @@ $def_ossaudio_devdsp
$def_ossaudio_devmixer
$def_pulse
$def_sgiaudio
$def_sndio
$def_sunaudio
$def_win32waveout
Expand Down
256 changes: 256 additions & 0 deletions libao2/ao_sndio.c
Original file line number Diff line number Diff line change
@@ -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);
}
4 changes: 4 additions & 0 deletions libao2/audio_out.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern const ao_functions_t audio_out_jack;
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;
Expand Down Expand Up @@ -73,6 +74,9 @@ const ao_functions_t* const audio_out_drivers[] =
#ifdef CONFIG_COREAUDIO
&audio_out_coreaudio,
#endif
#ifdef CONFIG_SNDIO_AUDIO
&audio_out_sndio,
#endif
#ifdef CONFIG_OSS_AUDIO
&audio_out_oss,
#endif
Expand Down

0 comments on commit 60d8680

Please sign in to comment.