mirror of
https://github.com/mpv-player/mpv
synced 2025-02-16 12:17:12 +00:00
new EsounD audio driver (-ao esd)
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@8573 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
bb0678255c
commit
30c23e4946
@ -1,6 +1,8 @@
|
||||
|
||||
mplayer (0.90)
|
||||
|
||||
* -ao esd: new EsounD audio driver
|
||||
|
||||
rc2:
|
||||
General:
|
||||
* DOCS/tech/encoding-tips.txt and tech/directfb.txt
|
||||
|
2
Makefile
2
Makefile
@ -34,7 +34,7 @@ OBJS_MENCODER = $(SRCS_MENCODER:.c=.o)
|
||||
OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o)
|
||||
|
||||
VO_LIBS = $(AA_LIB) $(X_LIB) $(SDL_LIB) $(GGI_LIB) $(MP1E_LIB) $(MLIB_LIB) $(SVGA_LIB) $(DIRECTFB_LIB) $(GIF_LIB)
|
||||
AO_LIBS = $(ARTS_LIB) $(NAS_LIB) $(SGIAUDIO_LIB)
|
||||
AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(NAS_LIB) $(SGIAUDIO_LIB)
|
||||
CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(XVID_LIB) $(DECORE_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB)
|
||||
COMMON_LIBS = libmpcodecs/libmpcodecs.a mp3lib/libMP3.a liba52/liba52.a libmpeg2/libmpeg2.a $(W32_LIB) $(DS_LIB) libaf/libaf.a libmpdemux/libmpdemux.a input/libinput.a $(PP_LIB) postproc/libswscale.a linux/libosdep.a $(CSS_LIB) $(CODEC_LIBS) $(FREETYPE_LIB) $(TERMCAP_LIB) $(CDPARANOIA_LIB) $(STREAMING_LIB) $(WIN32_LIB)
|
||||
|
||||
|
33
configure
vendored
33
configure
vendored
@ -211,6 +211,7 @@ Video output:
|
||||
Audio output:
|
||||
--disable-ossaudio disable OSS sound support [autodetect]
|
||||
--disable-arts disable aRts sound support [autodetect]
|
||||
--disable-esd disable esd sound support [autodetect]
|
||||
--disable-alsa disable alsa sound support [autodetect]
|
||||
--disable-sunaudio disable Sun sound support [autodetect]
|
||||
--disable-win32waveout disable windows waveout sound support [autodetect]
|
||||
@ -975,6 +976,7 @@ _iconv=auto
|
||||
_rtc=auto
|
||||
_ossaudio=auto
|
||||
_arts=auto
|
||||
_esd=auto
|
||||
_liblzo=auto
|
||||
_mad=auto
|
||||
_vorbis=auto
|
||||
@ -1112,6 +1114,8 @@ for ac_option do
|
||||
--disable-ossaudio) _ossaudio=no ;;
|
||||
--enable-arts) _arts=yes ;;
|
||||
--disable-arts) _arts=no ;;
|
||||
--enable-esd) _esd=yes ;;
|
||||
--disable-esd) _esd=no ;;
|
||||
--enable-mad) _mad=yes ;;
|
||||
--disable-mad) _mad=no ;;
|
||||
--enable-liblzo) _liblzo=yes ;;
|
||||
@ -3181,6 +3185,32 @@ fi
|
||||
echores "$_arts"
|
||||
|
||||
|
||||
echocheck "EsounD"
|
||||
if test "$_esd" = auto ; then
|
||||
_esd=no
|
||||
if ( esd-config --version ) >> "$TMPLOG" 2>&1 ; then
|
||||
|
||||
cat > $TMPC << EOF
|
||||
#include <esd.h>
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
cc_check `esd-config --libs` `esd-config --cflags` && ( "$TMPO" >> "$TMPLOG" 2>&1 ) && _esd=yes
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$_esd" = yes ; then
|
||||
_def_esd='#define USE_ESD 1'
|
||||
_aosrc="$_aosrc ao_esd.c"
|
||||
_aomodules="esd $_aomodules"
|
||||
_ld_esd=`esd-config --libs`
|
||||
_inc_esd=`esd-config --cflags`
|
||||
else
|
||||
_noaomodules="esd $_noaomodules"
|
||||
fi
|
||||
echores "$_esd"
|
||||
|
||||
|
||||
echocheck "ALSA audio"
|
||||
if test "$_alsa" != no ; then
|
||||
_alsa=no
|
||||
@ -4711,6 +4741,8 @@ ALSA_LIB = $_ld_alsa
|
||||
NAS_LIB = $_ld_nas
|
||||
ARTS_LIB = $_ld_arts
|
||||
ARTS_INC = $_inc_arts
|
||||
ESD_LIB = $_ld_esd
|
||||
ESD_INC = $_inc_esd
|
||||
SGIAUDIO_LIB = $_ld_sgiaudio
|
||||
|
||||
# input/demuxer/codecs
|
||||
@ -5027,6 +5059,7 @@ $_def_ossaudio_devmixer
|
||||
$_def_alsa5
|
||||
$_def_alsa9
|
||||
$_def_arts
|
||||
$_def_esd
|
||||
$_def_sys_asoundlib_h
|
||||
$_def_alsa_asoundlib_h
|
||||
$_def_sunaudio
|
||||
|
468
libao2/ao_esd.c
Normal file
468
libao2/ao_esd.c
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* ao_esd - EsounD audio output driver for MPlayer
|
||||
*
|
||||
* Juergen Keil <jk@tools.de>
|
||||
*
|
||||
* This driver is distributed under the terms of the GPL
|
||||
*
|
||||
* TODO / known problems:
|
||||
* - does not work well when the esd daemon has autostandby disabled
|
||||
* (workaround: run esd with option "-as 2" - fortunatelly this is
|
||||
* the default)
|
||||
* - plays noise on a linux 2.4.4 kernel with a SB16PCI card, when using
|
||||
* a local tcp connection to the esd daemon; there is no noise when using
|
||||
* a unix domain socket connection.
|
||||
* (there are EIO errors reported by the sound card driver, so this is
|
||||
* most likely a linux sound card driver problem)
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef __svr4__
|
||||
#include <stropts.h>
|
||||
#endif
|
||||
#include <esd.h>
|
||||
|
||||
#include "audio_out.h"
|
||||
#include "audio_out_internal.h"
|
||||
#include "afmt.h"
|
||||
#include "../config.h"
|
||||
#include "../mp_msg.h"
|
||||
|
||||
|
||||
#undef ESD_DEBUG
|
||||
|
||||
#if ESD_DEBUG
|
||||
#define dprintf(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(...) /**/
|
||||
#endif
|
||||
|
||||
|
||||
#define ESD_CLIENT_NAME "MPlayer"
|
||||
#define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */
|
||||
|
||||
|
||||
static ao_info_t info =
|
||||
{
|
||||
"EsounD audio output",
|
||||
"esd",
|
||||
"Juergen Keil <jk@tools.de>",
|
||||
""
|
||||
};
|
||||
|
||||
LIBAO_EXTERN(esd)
|
||||
|
||||
static int esd_fd = -1;
|
||||
static int esd_play_fd = -1;
|
||||
static esd_server_info_t *esd_svinfo;
|
||||
static int esd_latency;
|
||||
static int esd_bytes_per_sample;
|
||||
static unsigned long esd_samples_written;
|
||||
static struct timeval esd_play_start;
|
||||
|
||||
|
||||
/*
|
||||
* to set/get/query special features/parameters
|
||||
*/
|
||||
static int control(int cmd, int arg)
|
||||
{
|
||||
esd_player_info_t *esd_pi;
|
||||
esd_info_t *esd_i;
|
||||
time_t now;
|
||||
static time_t vol_cache_time;
|
||||
static ao_control_vol_t vol_cache;
|
||||
|
||||
switch (cmd) {
|
||||
case AOCONTROL_GET_VOLUME:
|
||||
time(&now);
|
||||
if (now == vol_cache_time) {
|
||||
*(ao_control_vol_t *)arg = vol_cache;
|
||||
return CONTROL_OK;
|
||||
}
|
||||
|
||||
dprintf("esd: get vol\n");
|
||||
if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
|
||||
return CONTROL_ERROR;
|
||||
|
||||
for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
|
||||
if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
|
||||
break;
|
||||
|
||||
if (esd_pi != NULL) {
|
||||
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
||||
vol->left = esd_pi->left_vol_scale * 100 / ESD_VOLUME_BASE;
|
||||
vol->right = esd_pi->right_vol_scale * 100 / ESD_VOLUME_BASE;
|
||||
|
||||
vol_cache = *vol;
|
||||
vol_cache_time = now;
|
||||
}
|
||||
esd_free_all_info(esd_i);
|
||||
|
||||
return CONTROL_OK;
|
||||
|
||||
case AOCONTROL_SET_VOLUME:
|
||||
dprintf("esd: set vol\n");
|
||||
if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
|
||||
return CONTROL_ERROR;
|
||||
|
||||
for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
|
||||
if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
|
||||
break;
|
||||
|
||||
if (esd_pi != NULL) {
|
||||
ao_control_vol_t *vol = (ao_control_vol_t *)arg;
|
||||
esd_set_stream_pan(esd_fd, esd_pi->source_id,
|
||||
vol->left * ESD_VOLUME_BASE / 100,
|
||||
vol->right * ESD_VOLUME_BASE / 100);
|
||||
|
||||
vol_cache = *vol;
|
||||
time(&vol_cache_time);
|
||||
}
|
||||
esd_free_all_info(esd_i);
|
||||
return CONTROL_OK;
|
||||
|
||||
default:
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* open & setup audio device
|
||||
* return: 1=success 0=fail
|
||||
*/
|
||||
static int init(int rate_hz, int channels, int format, int flags)
|
||||
{
|
||||
esd_format_t esd_fmt;
|
||||
int bytes_per_sample;
|
||||
int fl;
|
||||
|
||||
if (esd_fd < 0) {
|
||||
esd_fd = esd_open_sound(NULL);
|
||||
if (esd_fd < 0) {
|
||||
mp_msg(MSGT_AO, MSGL_ERR, "AO: [esd] esd_open_sound failed: %s\n",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
esd_svinfo = esd_get_server_info(esd_fd);
|
||||
/*
|
||||
if (esd_svinfo) {
|
||||
mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
|
||||
esd_print_server_info(esd_svinfo);
|
||||
}
|
||||
*/
|
||||
|
||||
esd_latency = esd_get_latency(esd_fd);
|
||||
/* mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] latency: %d\n", esd_latency); */
|
||||
}
|
||||
|
||||
esd_fmt = ESD_STREAM | ESD_PLAY;
|
||||
|
||||
#if ESD_RESAMPLES
|
||||
/* let the esd daemon convert sample rate */
|
||||
#else
|
||||
/* let mplayer's audio filter convert the sample rate */
|
||||
if (esd_svinfo != NULL)
|
||||
rate_hz = esd_svinfo->rate;
|
||||
#endif
|
||||
ao_data.samplerate = rate_hz;
|
||||
|
||||
|
||||
/* EsounD can play mono or stereo */
|
||||
switch (channels) {
|
||||
case 1:
|
||||
esd_fmt |= ESD_MONO;
|
||||
ao_data.channels = bytes_per_sample = 1;
|
||||
break;
|
||||
default:
|
||||
esd_fmt |= ESD_STEREO;
|
||||
ao_data.channels = bytes_per_sample = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* EsounD can play 8bit unsigned and 16bit signed native */
|
||||
switch (format) {
|
||||
case AFMT_S8:
|
||||
case AFMT_U8:
|
||||
esd_fmt |= ESD_BITS8;
|
||||
ao_data.format = AFMT_U8;
|
||||
break;
|
||||
default:
|
||||
esd_fmt |= ESD_BITS16;
|
||||
ao_data.format = AFMT_S16_NE;
|
||||
bytes_per_sample *= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
esd_play_fd = esd_play_stream_fallback(esd_fmt, rate_hz,
|
||||
NULL, ESD_CLIENT_NAME);
|
||||
if (esd_play_fd < 0) {
|
||||
mp_msg(MSGT_AO, MSGL_ERR,
|
||||
"AO: [esd] failed to open esd playback stream: %s\n",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* enable non-blocking i/o on the socket connection to the esd server */
|
||||
if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0)
|
||||
fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl);
|
||||
|
||||
#if ESD_DEBUG
|
||||
{
|
||||
int sbuf, rbuf, len;
|
||||
len = sizeof(sbuf);
|
||||
getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len);
|
||||
len = sizeof(rbuf);
|
||||
getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len);
|
||||
dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
|
||||
sbuf, rbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
ao_data.bps = bytes_per_sample * rate_hz;
|
||||
ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE;
|
||||
|
||||
esd_play_start.tv_sec = 0;
|
||||
esd_samples_written = 0;
|
||||
esd_bytes_per_sample = bytes_per_sample;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* close audio device
|
||||
*/
|
||||
static void uninit()
|
||||
{
|
||||
if (esd_play_fd >= 0) {
|
||||
esd_close(esd_play_fd);
|
||||
esd_play_fd = -1;
|
||||
}
|
||||
|
||||
if (esd_svinfo) {
|
||||
esd_free_server_info(esd_svinfo);
|
||||
esd_svinfo = NULL;
|
||||
}
|
||||
|
||||
if (esd_fd >= 0) {
|
||||
esd_close(esd_fd);
|
||||
esd_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* plays 'len' bytes of 'data'
|
||||
* it should round it down to outburst*n
|
||||
* return: number of bytes played
|
||||
*/
|
||||
static int play(void* data, int len, int flags)
|
||||
{
|
||||
int offs;
|
||||
int nwritten;
|
||||
int nsamples;
|
||||
int remainder, n;
|
||||
int saved_fl;
|
||||
|
||||
/* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
|
||||
len = len / ESD_BUF_SIZE * ESD_BUF_SIZE;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
#define SINGLE_WRITE 0
|
||||
#if SINGLE_WRITE
|
||||
nwritten = write(esd_play_fd, data, len);
|
||||
#else
|
||||
for (offs = 0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) {
|
||||
/*
|
||||
* note: we're writing to a non-blocking socket here.
|
||||
* A partial write means, that the socket buffer is full.
|
||||
*/
|
||||
nwritten = write(esd_play_fd, (char*)data + offs, ESD_BUF_SIZE);
|
||||
if (nwritten != ESD_BUF_SIZE) {
|
||||
if (nwritten < 0 && errno != EAGAIN) {
|
||||
dprintf("esd play: write failed: %s\n", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
nwritten = offs;
|
||||
#endif
|
||||
|
||||
if (nwritten > 0 && nwritten % ESD_BUF_SIZE != 0) {
|
||||
|
||||
/*
|
||||
* partial write of an audio block of ESD_BUF_SIZE bytes.
|
||||
*
|
||||
* Send the remainder of that block as well; this avoids a busy
|
||||
* polling loop in the esd daemon, which waits for the rest of
|
||||
* the incomplete block using reads from a non-blocking
|
||||
* socket. This busy polling loop wastes CPU cycles on the
|
||||
* esd server machine, and we're trying to avoid that.
|
||||
* (esd 0.2.28+ has the busy polling read loop, 0.2.22 inserts
|
||||
* 0 samples which is bad as well)
|
||||
*
|
||||
* Let's hope the blocking write does not consume too much time.
|
||||
*
|
||||
* (fortunatelly, this piece of code is not used when playing
|
||||
* sound on the local machine - on solaris at least)
|
||||
*/
|
||||
remainder = ESD_BUF_SIZE - nwritten % ESD_BUF_SIZE;
|
||||
dprintf("esd play: partial audio block written, remainder %d \n",
|
||||
remainder);
|
||||
|
||||
/* blocking write of remaining bytes for the partial audio block */
|
||||
saved_fl = fcntl(esd_play_fd, F_GETFL);
|
||||
fcntl(esd_play_fd, F_SETFL, saved_fl & ~O_NDELAY);
|
||||
n = write(esd_play_fd, (char *)data + nwritten, remainder);
|
||||
fcntl(esd_play_fd, F_SETFL, saved_fl);
|
||||
|
||||
if (n != remainder) {
|
||||
mp_msg(MSGT_AO, MSGL_ERR,
|
||||
"AO: [esd] send remainer of audio block failed, %d/%d\n",
|
||||
n, remainder);
|
||||
} else
|
||||
nwritten += n;
|
||||
}
|
||||
|
||||
if (nwritten > 0) {
|
||||
if (!esd_play_start.tv_sec)
|
||||
gettimeofday(&esd_play_start, NULL);
|
||||
nsamples = nwritten / esd_bytes_per_sample;
|
||||
esd_samples_written += nsamples;
|
||||
|
||||
dprintf("esd play: %d %lu\n", nsamples, esd_samples_written);
|
||||
} else {
|
||||
dprintf("esd play: blocked / %lu\n", esd_samples_written);
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* stop playing, keep buffers (for pause)
|
||||
*/
|
||||
static void audio_pause()
|
||||
{
|
||||
/*
|
||||
* not possible with esd. the esd daemom will continue playing
|
||||
* buffered data (not more than ESD_MAX_DELAY seconds of samples)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* resume playing, after audio_pause()
|
||||
*/
|
||||
static void audio_resume()
|
||||
{
|
||||
/*
|
||||
* not possible with esd.
|
||||
*
|
||||
* Let's hope the pause was long enough that the esd ran out of
|
||||
* buffered data; we restart our time based delay computation
|
||||
* for an audio resume.
|
||||
*/
|
||||
esd_play_start.tv_sec = 0;
|
||||
esd_samples_written = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* stop playing and empty buffers (for seeking/pause)
|
||||
*/
|
||||
static void reset()
|
||||
{
|
||||
#ifdef __svr4__
|
||||
/* throw away data buffered in the esd connection */
|
||||
if (ioctl(esd_play_fd, I_FLUSH, FLUSHW))
|
||||
perror("I_FLUSH");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return: how many bytes can be played without blocking
|
||||
*/
|
||||
static int get_space()
|
||||
{
|
||||
struct timeval tmout;
|
||||
fd_set wfds;
|
||||
float current_delay;
|
||||
int space;
|
||||
|
||||
/*
|
||||
* Don't buffer too much data in the esd daemon.
|
||||
*
|
||||
* If we send too much, esd will block in write()s to the sound
|
||||
* device, and the consequence is a huge slow down for things like
|
||||
* esd_get_all_info().
|
||||
*/
|
||||
if ((current_delay = get_delay()) >= ESD_MAX_DELAY) {
|
||||
dprintf("esd get_space: too much data buffered\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(esd_play_fd, &wfds);
|
||||
tmout.tv_sec = 0;
|
||||
tmout.tv_usec = 0;
|
||||
|
||||
if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1)
|
||||
return 0;
|
||||
|
||||
if (!FD_ISSET(esd_play_fd, &wfds))
|
||||
return 0;
|
||||
|
||||
/* try to fill 50% of the remaining "free" buffer space */
|
||||
space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f;
|
||||
|
||||
/* round up to next multiple of ESD_BUF_SIZE */
|
||||
space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE;
|
||||
|
||||
dprintf("esd get_space: %d\n", space);
|
||||
return space;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* return: delay in seconds between first and last sample in buffer
|
||||
*/
|
||||
static float get_delay()
|
||||
{
|
||||
struct timeval now;
|
||||
double buffered_samples_time;
|
||||
double play_time;
|
||||
|
||||
if (!esd_play_start.tv_sec)
|
||||
return 0;
|
||||
|
||||
buffered_samples_time = (float)esd_samples_written / ao_data.samplerate;
|
||||
gettimeofday(&now, NULL);
|
||||
play_time = now.tv_sec - esd_play_start.tv_sec;
|
||||
play_time += (now.tv_usec - esd_play_start.tv_usec) / 1000000.;
|
||||
|
||||
/* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
|
||||
|
||||
if (play_time > buffered_samples_time) {
|
||||
dprintf("esd: underflow\n");
|
||||
esd_play_start.tv_sec = 0;
|
||||
esd_samples_written = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dprintf("esd: get_delay %f\n", buffered_samples_time - play_time);
|
||||
return buffered_samples_time - play_time;
|
||||
}
|
@ -19,6 +19,9 @@ extern ao_functions_t audio_out_oss;
|
||||
#ifdef USE_ARTS
|
||||
extern ao_functions_t audio_out_arts;
|
||||
#endif
|
||||
#ifdef USE_ESD
|
||||
extern ao_functions_t audio_out_esd;
|
||||
#endif
|
||||
extern ao_functions_t audio_out_null;
|
||||
#ifdef HAVE_ALSA5
|
||||
extern ao_functions_t audio_out_alsa5;
|
||||
@ -79,6 +82,9 @@ ao_functions_t* audio_out_drivers[] =
|
||||
#ifdef USE_ARTS
|
||||
&audio_out_arts,
|
||||
#endif
|
||||
#ifdef USE_ESD
|
||||
&audio_out_esd,
|
||||
#endif
|
||||
#ifdef HAVE_NAS
|
||||
&audio_out_nas,
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user