mirror of
https://github.com/mpv-player/mpv
synced 2025-02-16 12:17:12 +00:00
audio/out: add sndio support
Based on an earlier patch for mplayer by Alexandre Ratchov <alex@caoua.org>
This commit is contained in:
parent
bdc56771eb
commit
3289473678
2
Makefile
2
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
|
||||
|
@ -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
|
||||
|
340
audio/out/ao_sndio.c
Normal file
340
audio/out/ao_sndio.c
Normal file
@ -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}
|
||||
},
|
||||
};
|
23
configure
vendored
23
configure
vendored
@ -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
|
||||
|
49
stream/ai_sndio.c
Normal file
49
stream/ai_sndio.c
Normal file
@ -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;
|
||||
}
|
@ -52,6 +52,12 @@ int audio_in_init(audio_in_t *ai, int type)
|
||||
ai->oss.audio_fd = -1;
|
||||
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;
|
||||
@ -73,6 +79,12 @@ int audio_in_setup(audio_in_t *ai)
|
||||
if (ai_oss_init(ai) < 0) return -1;
|
||||
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;
|
||||
@ -95,6 +107,13 @@ int audio_in_set_samplerate(audio_in_t *ai, int rate)
|
||||
if (!ai->setup) return 0;
|
||||
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;
|
||||
@ -117,6 +136,13 @@ int audio_in_set_channels(audio_in_t *ai, int channels)
|
||||
if (!ai->setup) return 0;
|
||||
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;
|
||||
@ -145,6 +171,12 @@ int audio_in_set_device(audio_in_t *ai, char *device)
|
||||
free(ai->oss.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;
|
||||
@ -170,6 +202,13 @@ int audio_in_uninit(audio_in_t *ai)
|
||||
close(ai->oss.audio_fd);
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -186,6 +225,12 @@ int audio_in_start_capture(audio_in_t *ai)
|
||||
#ifdef CONFIG_OSS_AUDIO
|
||||
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));
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user