summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2013-09-28 18:01:12 +0200
committerwm4 <wm4@nowhere>2013-10-03 23:14:03 +0200
commit32894736780ea63e5fea456de27650fc27ec57c6 (patch)
treea72fe21baacc223136b313c66717069172400722
parentbdc56771eb8fa06f47599d90370017a6791e631b (diff)
downloadmpv-32894736780ea63e5fea456de27650fc27ec57c6.tar.bz2
mpv-32894736780ea63e5fea456de27650fc27ec57c6.tar.xz
audio/out: add sndio support
Based on an earlier patch for mplayer by Alexandre Ratchov <alex@caoua.org>
-rw-r--r--Makefile2
-rw-r--r--audio/out/ao.c4
-rw-r--r--audio/out/ao_sndio.c340
-rwxr-xr-xconfigure23
-rw-r--r--stream/ai_sndio.c49
-rw-r--r--stream/audio_in.c59
-rw-r--r--stream/audio_in.h19
7 files changed, 496 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 0c9eabc806..54d354ffc4 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ include config.mak
SOURCES_AUDIO_INPUT-$(ALSA) += stream/ai_alsa1x.c
SOURCES_AUDIO_INPUT-$(OSS) += stream/ai_oss.c
+SOURCES_AUDIO_INPUT-$(SNDIO) += stream/ai_sndio.c
SOURCES-$(AUDIO_INPUT) += $(SOURCES_AUDIO_INPUT-yes)
SOURCES-$(CDDA) += stream/stream_cdda.c \
stream/cdinfo.c
@@ -111,6 +112,7 @@ SOURCES-$(OSS) += audio/out/ao_oss.c
SOURCES-$(PULSE) += audio/out/ao_pulse.c
SOURCES-$(PORTAUDIO) += audio/out/ao_portaudio.c
SOURCES-$(RSOUND) += audio/out/ao_rsound.c
+SOURCES-$(SNDIO) += audio/out/ao_sndio.c
SOURCES-$(VDPAU) += video/vdpau.c video/out/vo_vdpau.c
SOURCES-$(VDA) += video/decode/vda.c
SOURCES-$(VDPAU_DEC) += video/decode/vdpau.c
diff --git a/audio/out/ao.c b/audio/out/ao.c
index 1c7cfcbcae..566ab0fea9 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -35,6 +35,7 @@
extern const struct ao_driver audio_out_oss;
extern const struct ao_driver audio_out_coreaudio;
extern const struct ao_driver audio_out_rsound;
+extern const struct ao_driver audio_out_sndio;
extern const struct ao_driver audio_out_pulse;
extern const struct ao_driver audio_out_jack;
extern const struct ao_driver audio_out_openal;
@@ -55,6 +56,9 @@ static const struct ao_driver * const audio_out_drivers[] = {
#ifdef CONFIG_PULSE
&audio_out_pulse,
#endif
+#ifdef CONFIG_SNDIO
+ &audio_out_sndio,
+#endif
#ifdef CONFIG_ALSA
&audio_out_alsa,
#endif
diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c
new file mode 100644
index 0000000000..0a1f9f3038
--- /dev/null
+++ b/audio/out/ao_sndio.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
+ * Copyright (c) 2013 Christian Neukirchen <chneukirchen@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <poll.h>
+#include <errno.h>
+#include <sndio.h>
+
+#include "mpvcore/m_option.h"
+#include "mpvcore/mp_msg.h"
+
+#include "audio/format.h"
+#include "ao.h"
+
+struct priv {
+ struct sio_hdl *hdl;
+ struct sio_par par;
+ int delay;
+ int vol;
+ int havevol;
+#define SILENCE_NMAX 0x1000
+ char silence[SILENCE_NMAX];
+ struct pollfd *pfd;
+ char *dev;
+};
+
+/*
+ * misc parameters (volume, etc...)
+ */
+static int control(struct ao *ao, enum aocontrol cmd, void *arg)
+{
+ struct priv *p = ao->priv;
+ ao_control_vol_t *vol = arg;
+
+ switch (cmd) {
+ case AOCONTROL_GET_VOLUME:
+ if (!p->havevol)
+ return CONTROL_FALSE;
+ vol->left = vol->right = p->vol * 100 / SIO_MAXVOL;
+ break;
+ case AOCONTROL_SET_VOLUME:
+ if (!p->havevol)
+ return CONTROL_FALSE;
+ sio_setvol(p->hdl, vol->left * SIO_MAXVOL / 100);
+ break;
+ default:
+ return CONTROL_UNKNOWN;
+ }
+ return CONTROL_OK;
+}
+
+/*
+ * call-back invoked to notify of the hardware position
+ */
+static void movecb(void *addr, int delta)
+{
+ struct priv *p = addr;
+ p->delay -= delta * (int)(p->par.bps * p->par.pchan);
+}
+
+/*
+ * call-back invoked to notify about volume changes
+ */
+static void volcb(void *addr, unsigned newvol)
+{
+ struct priv *p = addr;
+ p->vol = newvol;
+}
+
+static const struct mp_chmap sndio_layouts[MP_NUM_CHANNELS + 1] = {
+ {0}, // empty
+ {1, {MP_SPEAKER_ID_FL}}, // mono
+ MP_CHMAP2(FL, FR), // stereo
+ {0}, // 2.1
+ MP_CHMAP4(FL, FR, BL, BR), // 4.0
+ {0}, // 5.0
+ MP_CHMAP6(FL, FR, BL, BR, FC, LFE), // 5.1
+ {0}, // 6.1
+ MP_CHMAP8(FL, FR, BL, BR, FC, LFE, SL, SR), // 7.1
+ /* above is the fixed channel assignment for sndio, since we need to fill
+ all channels and cannot insert silence, not all layouts are supported. */
+};
+
+/*
+ * open device and setup parameters
+ * return: 0=success -1=fail
+ */
+static int init(struct ao *ao)
+{
+ struct priv *p = ao->priv;
+
+ struct af_to_par {
+ int format, bits, sig, le;
+ } static const af_to_par[] = {
+ {AF_FORMAT_U8, 8, 0, 0},
+ {AF_FORMAT_S8, 8, 1, 0},
+ {AF_FORMAT_U16_LE, 16, 0, 1},
+ {AF_FORMAT_U16_BE, 16, 0, 0},
+ {AF_FORMAT_S16_LE, 16, 1, 1},
+ {AF_FORMAT_S16_BE, 16, 1, 0},
+ {AF_FORMAT_U24_LE, 16, 0, 1},
+ {AF_FORMAT_U24_BE, 24, 0, 0},
+ {AF_FORMAT_S24_LE, 24, 1, 1},
+ {AF_FORMAT_S24_BE, 24, 1, 0},
+ {AF_FORMAT_U32_LE, 32, 0, 1},
+ {AF_FORMAT_U32_BE, 32, 0, 0},
+ {AF_FORMAT_S32_LE, 32, 1, 1},
+ {AF_FORMAT_S32_BE, 32, 1, 0}
+ }, *ap;
+ int i;
+
+ p->hdl = sio_open(p->dev, SIO_PLAY, 0);
+ if (p->hdl == NULL) {
+ MP_ERR(ao, "can't open sndio %s\n", p->dev);
+ goto error;
+ }
+ sio_initpar(&p->par);
+ for (i = 0, ap = af_to_par;; i++, ap++) {
+ if (i == sizeof(af_to_par) / sizeof(struct af_to_par)) {
+ MP_VERBOSE(ao, "unsupported format\n");
+ p->par.bits = 16;
+ p->par.sig = 1;
+ p->par.le = SIO_LE_NATIVE;
+ break;
+ }
+ if (ap->format == ao->format) {
+ p->par.bits = ap->bits;
+ p->par.sig = ap->sig;
+ if (ap->bits > 8)
+ p->par.le = ap->le;
+ if (ap->bits != SIO_BPS(ap->bits))
+ p->par.bps = ap->bits / 8;
+ break;
+ }
+ }
+ p->par.rate = ao->samplerate;
+
+ struct mp_chmap_sel sel = {0};
+ for (int n = 0; n < MP_NUM_CHANNELS+1; n++)
+ mp_chmap_sel_add_map(&sel, &sndio_layouts[n]);
+
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ goto error;
+
+ p->par.pchan = ao->channels.num;
+ p->par.appbufsz = p->par.rate * 250 / 1000; /* 250ms buffer */
+ p->par.round = p->par.rate * 10 / 1000; /* 10ms block size */
+ if (!sio_setpar(p->hdl, &p->par)) {
+ MP_ERR(ao, "couldn't set params\n");
+ goto error;
+ }
+ if (!sio_getpar(p->hdl, &p->par)) {
+ MP_ERR(ao, "couldn't get params\n");
+ goto error;
+ }
+ if (p->par.bits == 8 && p->par.bps == 1) {
+ ao->format = p->par.sig ? AF_FORMAT_S8 : AF_FORMAT_U8;
+ } else if (p->par.bits == 16 && p->par.bps == 2) {
+ ao->format = p->par.sig ?
+ (p->par.le ? AF_FORMAT_S16_LE : AF_FORMAT_S16_BE) :
+ (p->par.le ? AF_FORMAT_U16_LE : AF_FORMAT_U16_BE);
+ } else if ((p->par.bits == 24 || p->par.msb) && p->par.bps == 3) {
+ ao->format = p->par.sig ?
+ (p->par.le ? AF_FORMAT_S24_LE : AF_FORMAT_S24_BE) :
+ (p->par.le ? AF_FORMAT_U24_LE : AF_FORMAT_U24_BE);
+ } else if ((p->par.bits == 32 || p->par.msb) && p->par.bps == 4) {
+ ao->format = p->par.sig ?
+ (p->par.le ? AF_FORMAT_S32_LE : AF_FORMAT_S32_BE) :
+ (p->par.le ? AF_FORMAT_U32_LE : AF_FORMAT_U32_BE);
+ } else {
+ MP_ERR(ao, "couldn't set format\n");
+ goto error;
+ }
+
+ ao->bps = p->par.bps * p->par.pchan * p->par.rate;
+ ao->no_persistent_volume = true;
+ p->havevol = sio_onvol(p->hdl, volcb, p);
+ sio_onmove(p->hdl, movecb, p);
+ p->delay = 0;
+ if (!sio_start(p->hdl))
+ MP_ERR(ao, "init: couldn't start\n");
+
+ p->pfd = calloc (sio_nfds(p->hdl), sizeof (struct pollfd));
+ if (!p->pfd)
+ goto error;
+
+ return 0;
+
+error:
+ if (p->hdl)
+ sio_close(p->hdl);
+
+ return -1;
+}
+
+/*
+ * close device
+ */
+static void uninit(struct ao *ao, bool immed)
+{
+ struct priv *p = ao->priv;
+
+ if (p->hdl)
+ sio_close(p->hdl);
+
+ free(p->pfd);
+}
+
+/*
+ * stop playing and empty buffers (for seeking/pause)
+ */
+static void reset(struct ao *ao)
+{
+ struct priv *p = ao->priv;
+
+ if (!sio_stop(p->hdl))
+ MP_ERR(ao, "reset: couldn't stop\n");
+ p->delay = 0;
+ if (!sio_start(p->hdl))
+ MP_ERR(ao, "reset: couldn't start\n");
+}
+
+/*
+ * play given number of bytes until sio_write() blocks
+ */
+static int play(struct ao *ao, void *data, int len, int flags)
+{
+ struct priv *p = ao->priv;
+ int n;
+
+ n = sio_write(p->hdl, data, len);
+ p->delay += n;
+ if (flags & AOPLAY_FINAL_CHUNK)
+ reset(ao);
+ return n;
+}
+
+/*
+ * how many bytes can be played without blocking
+ */
+static int get_space(struct ao *ao)
+{
+ struct priv *p = ao->priv;
+ int n;
+
+ /*
+ * call poll() and sio_revents(), so the
+ * delay counter is updated
+ */
+ n = sio_pollfd(p->hdl, p->pfd, POLLOUT);
+ while (poll(p->pfd, n, 0) < 0 && errno == EINTR)
+ ; /* nothing */
+ sio_revents(p->hdl, p->pfd);
+
+ return p->par.bufsz * p->par.pchan * p->par.bps - p->delay;
+}
+
+/*
+ * return: delay in seconds between first and last sample in buffer
+ */
+static float get_delay(struct ao *ao)
+{
+ struct priv *p = ao->priv;
+ return (float)p->delay / (p->par.bps * p->par.pchan * p->par.rate);
+}
+
+/*
+ * stop playing, keep buffers (for pause)
+ */
+static void audio_pause(struct ao *ao)
+{
+ reset(ao);
+}
+
+/*
+ * resume playing, after audio_pause()
+ */
+static void audio_resume(struct ao *ao)
+{
+ struct priv *p = ao->priv;
+ int n, count, todo;
+
+ /*
+ * we want to start with buffers full, because mplayer uses
+ * get_space() pointer as clock, which would cause video to
+ * accelerate while buffers are filled.
+ */
+ todo = p->par.bufsz * p->par.pchan * p->par.bps;
+ while (todo > 0) {
+ count = todo;
+ if (count > SILENCE_NMAX)
+ count = SILENCE_NMAX;
+ n = sio_write(p->hdl, p->silence, count);
+ if (n == 0)
+ break;
+ todo -= n;
+ p->delay += n;
+ }
+}
+
+#define OPT_BASE_STRUCT struct priv
+
+const struct ao_driver audio_out_sndio = {
+ .info = &(const struct ao_info) {
+ "sndio audio output",
+ "sndio",
+ "Alexandre Ratchov <alex@caoua.org>, Christian Neukirchen <chneukirchen@gmail.com>",
+ "under development"
+ },
+ .init = init,
+ .uninit = uninit,
+ .control = control,
+ .get_space = get_space,
+ .play = play,
+ .get_delay = get_delay,
+ .pause = audio_pause,
+ .resume = audio_resume,
+ .reset = reset,
+ .priv_size = sizeof(struct priv),
+ .options = (const struct m_option[]) {
+ OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY)),
+ {0}
+ },
+};
diff --git a/configure b/configure
index 32525f9de9..2c41e05a34 100755
--- a/configure
+++ b/configure
@@ -364,6 +364,7 @@ Audio output:
--disable-alsa disable ALSA audio output [autodetect]
--disable-ossaudio disable OSS audio output [autodetect]
--disable-rsound disable RSound audio output [autodetect]
+ --disable-sndio disable sndio audio output [autodetect]
--disable-pulse disable Pulseaudio audio output [autodetect]
--disable-portaudio disable PortAudio audio output [autodetect]
--disable-jack disable JACK audio output [autodetect]
@@ -459,6 +460,7 @@ _lcms2=auto
_xinerama=auto
_vm=auto
_xf86keysym=auto
+_sndio=auto
_alsa=auto
_select=yes
_radio=no
@@ -625,6 +627,8 @@ for ac_option do
--disable-ossaudio) _ossaudio=no ;;
--enable-rsound) _rsound=yes ;;
--disable-rsound) _rsound=no ;;
+ --enable-sndio) _sndio=yes ;;
+ --disable-sndio) _sndio=no ;;
--enable-pulse) _pulse=yes ;;
--disable-pulse) _pulse=no ;;
--enable-portaudio) _portaudio=yes ;;
@@ -2323,6 +2327,23 @@ else
fi
+echocheck "sndio"
+if test "$_sndio" = auto ; then
+ _sndio=no
+ statement_check sndio.h 'struct sio_par par; sio_initpar(&par);' -lsndio && _sndio=yes
+fi
+echores "$_sndio"
+
+if test "$_sndio" = yes ; then
+ def_sndio='#define CONFIG_SNDIO 1'
+ aomodules="sndio $_aomodules"
+ libs_mplayer="$libs_mplayer -lsndio"
+else
+ def_sndio='#undef CONFIG_SNDIO'
+ noaomodules="sndio $_noaomodules"
+fi
+
+
echocheck "pulse"
if test "$_pulse" = auto ; then
_pulse=no
@@ -3290,6 +3311,7 @@ PVR = $_pvr
RADIO=$_radio
RADIO_CAPTURE=$_radio_capture
RSOUND = $_rsound
+SNDIO = $_sndio
STREAM_CACHE = $_stream_cache
TV = $_tv
TV_V4L2 = $_tv_v4l2
@@ -3426,6 +3448,7 @@ $def_ossaudio_devmixer
$def_pulse
$def_portaudio
$def_rsound
+$def_sndio
$def_ladspa
$def_libbs2b
diff --git a/stream/ai_sndio.c b/stream/ai_sndio.c
new file mode 100644
index 0000000000..b486bb9210
--- /dev/null
+++ b/stream/ai_sndio.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+#include <sndio.h>
+#include "audio_in.h"
+#include "mpvcore/mp_msg.h"
+
+int ai_sndio_setup(audio_in_t *ai)
+{
+ struct sio_par par;
+
+ sio_initpar(&par);
+
+ par.bits = 16;
+ par.sig = 1;
+ par.le = 1;
+ par.rchan = ai->req_channels;
+ par.rate = ai->req_samplerate;
+ par.appbufsz = ai->req_samplerate; /* 1 sec */
+
+ if (!sio_setpar(ai->sndio.hdl, &par) || !sio_getpar(ai->sndio.hdl, &par)) {
+ mp_msg(MSGT_TV, MSGL_ERR, "could not configure sndio audio");
+ return -1;
+ }
+
+ ai->channels = par.rchan;
+ ai->samplerate = par.rate;
+ ai->samplesize = par.bits;
+ ai->bytes_per_sample = par.bps;
+ ai->blocksize = par.round * par.bps;
+
+ return 0;
+}
+
+int ai_sndio_init(audio_in_t *ai)
+{
+ int err;
+
+ if ((ai->sndio.hdl = sio_open(ai->sndio.device, SIO_REC, 0)) == NULL) {
+ mp_msg(MSGT_TV, MSGL_ERR, "could not open sndio audio");
+ return -1;
+ }
+
+ err = ai_sndio_setup(ai);
+
+ return err;
+}
diff --git a/stream/audio_in.c b/stream/audio_in.c
index cc54e87800..420311e848 100644
--- a/stream/audio_in.c
+++ b/stream/audio_in.c
@@ -53,6 +53,12 @@ int audio_in_init(audio_in_t *ai, int type)
ai->oss.device = strdup("/dev/dsp");
return 0;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ ai->sndio.hdl = NULL;
+ ai->sndio.device = strdup("default");
+ return 0;
+#endif
default:
return -1;
}
@@ -74,6 +80,12 @@ int audio_in_setup(audio_in_t *ai)
ai->setup = 1;
return 0;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ if (ai_sndio_init(ai) < 0) return -1;
+ ai->setup = 1;
+ return 0;
+#endif
default:
return -1;
}
@@ -96,6 +108,13 @@ int audio_in_set_samplerate(audio_in_t *ai, int rate)
if (ai_oss_set_samplerate(ai) < 0) return -1;
return ai->samplerate;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ ai->req_samplerate = rate;
+ if (!ai->setup) return 0;
+ if (ai_sndio_setup(ai) < 0) return -1;
+ return ai->samplerate;
+#endif
default:
return -1;
}
@@ -118,6 +137,13 @@ int audio_in_set_channels(audio_in_t *ai, int channels)
if (ai_oss_set_channels(ai) < 0) return -1;
return ai->channels;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ ai->req_channels = channels;
+ if (!ai->setup) return 0;
+ if (ai_sndio_setup(ai) < 0) return -1;
+ return ai->channels;
+#endif
default:
return -1;
}
@@ -146,6 +172,12 @@ int audio_in_set_device(audio_in_t *ai, char *device)
ai->oss.device = strdup(device);
return 0;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ if (ai->sndio.device) free(ai->sndio.device);
+ ai->sndio.device = strdup(device);
+ return 0;
+#endif
default:
return -1;
}
@@ -171,6 +203,13 @@ int audio_in_uninit(audio_in_t *ai)
ai->setup = 0;
return 0;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ if (ai->sndio.hdl)
+ sio_close(ai->sndio.hdl);
+ ai->setup = 0;
+ return 0;
+#endif
}
}
return -1;
@@ -187,6 +226,12 @@ int audio_in_start_capture(audio_in_t *ai)
case AUDIO_IN_OSS:
return 0;
#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ if (!sio_start(ai->sndio.hdl))
+ return -1;
+ return 0;
+#endif
default:
return -1;
}
@@ -220,6 +265,20 @@ int audio_in_read_chunk(audio_in_t *ai, unsigned char *buffer)
#ifdef CONFIG_OSS_AUDIO
case AUDIO_IN_OSS:
ret = read(ai->oss.audio_fd, buffer, ai->blocksize);
+ if (ret != ai->blocksize) {
+ if (ret < 0) {
+ mp_msg(MSGT_TV, MSGL_ERR, "\nError reading audio: %s\n", strerror(errno));
+
+ } else {
+ mp_msg(MSGT_TV, MSGL_ERR, "\nNot enough audio samples!\n");
+ }
+ return -1;
+ }
+ return ret;
+#endif
+#ifdef CONFIG_SNDIO
+ case AUDIO_IN_SNDIO:
+ ret = sio_read(ai->sndio.hdl, buffer, ai->blocksize);
if (ret != ai->blocksize) {
if (ret < 0) {
mp_tmsg(MSGT_TV, MSGL_ERR, "\nError reading audio: %s\n", strerror(errno));
diff --git a/stream/audio_in.h b/stream/audio_in.h
index 31688e7192..2f42685c7c 100644
--- a/stream/audio_in.h
+++ b/stream/audio_in.h
@@ -21,6 +21,7 @@
#define AUDIO_IN_ALSA 1
#define AUDIO_IN_OSS 2
+#define AUDIO_IN_SNDIO 3
#include "config.h"
@@ -45,6 +46,16 @@ typedef struct {
} ai_oss_t;
#endif
+#ifdef CONFIG_SNDIO
+#include <sndio.h>
+
+typedef struct {
+ char *device;
+
+ struct sio_hdl *hdl;
+} ai_sndio_t;
+#endif
+
typedef struct
{
int type;
@@ -67,6 +78,9 @@ typedef struct
#ifdef CONFIG_OSS_AUDIO
ai_oss_t oss;
#endif
+#ifdef CONFIG_SNDIO
+ ai_sndio_t sndio;
+#endif
} audio_in_t;
int audio_in_init(audio_in_t *ai, int type);
@@ -90,4 +104,9 @@ int ai_oss_set_channels(audio_in_t *ai);
int ai_oss_init(audio_in_t *ai);
#endif
+#ifdef CONFIG_SNDIO
+int ai_sndio_setup(audio_in_t *ai);
+int ai_sndio_init(audio_in_t *ai);
+#endif
+
#endif /* MPLAYER_AUDIO_IN_H */