Add PulseAudio support

git-svn-id: https://svn.musicpd.org/mpd/trunk@4316 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
J. Alexander Treuman 2006-07-13 19:03:49 +00:00
parent 93681d914e
commit 09698f917c
5 changed files with 226 additions and 8 deletions

View File

@ -39,6 +39,7 @@ AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support (default: enable)]
AC_ARG_ENABLE(sun,[ --disable-sun disable sun support (default: enable)],[enable_sun=$enableval],[enable_sun=yes])
AC_ARG_ENABLE(oss,[ --disable-oss disable OSS support (default: enable)],[enable_oss=$enableval],[enable_oss=yes])
AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA support (default: enable)],[enable_alsa=$enableval],[enable_alsa=yes])
AC_ARG_ENABLE(pulse,[ --disable-pulse disable support for the PulseAudio sound server (default: enable)],[enable_pulse=$enableval],[enable_pulse=yes])
AC_ARG_ENABLE(mvp,[ --enable-mvp enable support for Hauppauge Media MVP (default: disable)],[enable_mvp=$enableval],[enable_mvp=no])
AC_ARG_ENABLE(oggvorbis,[ --disable-oggvorbis disable Ogg Vorbis support (default: enable)],[enable_oggvorbis=$enableval],enable_oggvorbis=yes)
AC_ARG_ENABLE(oggflac,[ --disable-oggflac disable OggFLAC support (default: enable)],[enable_oggflac=$enableval],enable_oggflac=yes)
@ -147,6 +148,12 @@ if test x$enable_oss = xyes; then
AC_CHECK_HEADER(sys/soundcard.h,[enable_oss=yes;AC_DEFINE(HAVE_OSS,1,[Define to enable OSS])],[AC_MSG_WARN(Soundcard headers not found -- disabling OSS support);enable_oss=no])
fi
if test x$enable_pulse = xyes; then
PKG_CHECK_MODULES([PULSE], [libpulse-simple],
[enable_pulse=yes;AC_DEFINE([HAVE_PULSE], 1, [Define to enable PulseAudio])] MPD_LIBS="$MPD_LIBS $PULSE_LIBS" MPD_CFLAGS="$MPD_CFLAGS $PULSE_CFLAGS",
[enable_pulse=no;AC_MSG_WARN([PulseAudio not found -- disabling])])
fi
if test x$enable_mvp = xyes; then
AC_DEFINE(HAVE_MVP,1,[Define to enable Hauppauge Media MVP support])
fi
@ -636,9 +643,9 @@ else
fi
if test x$enable_sun = xyes; then
echo " Sun support ...... ............enabled"
echo " Sun support ...................enabled"
else
echo " Sun support ...... ............disabled"
echo " Sun support ...................disabled"
fi
if test x$enable_osx = xyes; then
@ -647,6 +654,12 @@ else
echo " OS X support ..................disabled"
fi
if test x$enable_pulse = xyes; then
echo " PulseAudio support ............enabled"
else
echo " PulseAudio support ............disabled"
fi
if test x$enable_mvp = xyes; then
echo " Media MVP support .............enabled"
else
@ -667,6 +680,7 @@ if test x$enable_ao = xno &&
test x$enable_sun = xno &&
test x$enable_alsa = xno &&
test x$enable_osx = xno &&
test x$enable_pulse = xno &&
test x$enable_mvp = xno; then
AC_MSG_ERROR("No Audio Output types configured!")
fi

View File

@ -186,14 +186,14 @@ This specifies whether relative or absolute paths for song filenames are used
when saving playlists. The default is "no".
.SH REQUIRED AUDIO OUTPUT PARAMETERS
.TP
.B name <name>
This specifies a unique name for the audio output.
.TP
.B type <type>
This specifies the audio output type. Depending on what audio output support
mpd was built with possible values could be "alsa", "oss", "osx", "mvp", "ao",
or "shout" (see \fBREQUIRED SHOUT OUTPUT PARAMETERS\fP and \fBOPTIONAL SHOUT
OUTPUT PARAMETERS\fP).
mpd was built with possible values could be "alsa", "oss", "osx", "pulse",
"mvp", "ao", or "shout" (see \fBREQUIRED SHOUT OUTPUT PARAMETERS\fP and
\fBOPTIONAL SHOUT OUTPUT PARAMETERS\fP).
.TP
.B name <name>
This specifies a unique name for the audio output.
.SH OPTIONAL AUDIO OUTPUT PARAMETERS
.TP
.B format <sample_rate:bits:channels>
@ -207,6 +207,14 @@ This specifies the device to use for audio output. Used by the alsa and oss
output types. The default for oss is "/dev/dsp"; the default for alsa is
"hw:0,0".
.TP
.B server <server list>
A space separated list of servers to try to connect to. Used only by the pulse
audio output. The default is to let PulseAudio choose a server.
.TP
.B sink <sink>
The sink to output to. Used only by the pulse audio output. The default is to
let PulseAudio choose a sink.
.TP
.B driver <driver>
This specifies the libao driver to use for audio output. Used only by the ao
output type. Possible values depend on what libao drivers are available. See

View File

@ -6,6 +6,7 @@ mpd_audioOutputs = \
audioOutputs/audioOutput_ao.c \
audioOutputs/audioOutput_oss.c \
audioOutputs/audioOutput_osx.c \
audioOutputs/audioOutput_pulse.c \
audioOutputs/audioOutput_mvp.c \
audioOutputs/audioOutput_shout.c

View File

@ -75,6 +75,7 @@ extern AudioOutputPlugin alsaPlugin;
extern AudioOutputPlugin aoPlugin;
extern AudioOutputPlugin ossPlugin;
extern AudioOutputPlugin osxPlugin;
extern AudioOutputPlugin pulsePlugin;
extern AudioOutputPlugin mvpPlugin;
extern AudioOutputPlugin shoutPlugin;
@ -88,6 +89,7 @@ void initAudioDriver() {
loadAudioOutputPlugin(&aoPlugin);
loadAudioOutputPlugin(&ossPlugin);
loadAudioOutputPlugin(&osxPlugin);
loadAudioOutputPlugin(&pulsePlugin);
loadAudioOutputPlugin(&mvpPlugin);
loadAudioOutputPlugin(&shoutPlugin);

View File

@ -0,0 +1,193 @@
#include "../audioOutput.h"
#include <stdlib.h>
#ifdef HAVE_PULSE
#define MPD_PULSE_NAME "mpd"
#define MPD_PULSE_STREAM_NAME "mpd"
#include "../conf.h"
#include "../log.h"
#include <pulse/simple.h>
#include <pulse/error.h>
typedef struct _PulseData {
char * server;
char * sink;
pa_simple * s;
} PulseData;
static PulseData * newPulseData()
{
PulseData * ret;
ret = malloc(sizeof(PulseData));
ret->server = NULL;
ret->sink = NULL;
ret->s = NULL;
return ret;
}
static void freePulseData(PulseData * ad)
{
if (ad->server) free(ad->server);
if (ad->sink) free(ad->sink);
free(ad);
}
static int pulse_initDriver(AudioOutput * audioOutput, ConfigParam * param)
{
BlockParam * server = NULL;
BlockParam * sink = NULL;
PulseData * ad;
if (param) {
server = getBlockParam(param, "server");
sink = getBlockParam(param, "sink");
}
ad = newPulseData();
ad->server = server ? strdup(server->value) : NULL;
ad->sink = sink ? strdup(sink->value) : NULL;
audioOutput->data = ad;
return 0;
}
static void pulse_finishDriver(AudioOutput * audioOutput)
{
freePulseData((PulseData *) audioOutput->data);
}
static int pulse_testDefault()
{
pa_simple * s;
pa_sample_spec ss;
int error;
ss.format = PA_SAMPLE_S16NE;
ss.rate = 44100;
ss.channels = 2;
s = pa_simple_new(NULL, MPD_PULSE_NAME, PA_STREAM_PLAYBACK, NULL,
MPD_PULSE_STREAM_NAME, &ss, NULL, NULL, &error);
if (!s) {
WARNING("Cannot connect to default PulseAudio server: %s\n",
pa_strerror(error));
return -1;
}
pa_simple_free(s);
return 0;
}
static int pulse_openDevice(AudioOutput * audioOutput)
{
PulseData * ad;
AudioFormat * audioFormat;
pa_sample_spec ss;
int error;
ad = audioOutput->data;
audioFormat = &audioOutput->outAudioFormat;
if (audioFormat->bits != 16) {
ERROR("PulseAudio doesn't support %i bit audio\n",
audioFormat->bits);
return -1;
}
ss.format = PA_SAMPLE_S16NE;
ss.rate = audioFormat->sampleRate;
ss.channels = audioFormat->channels;
ad->s = pa_simple_new(ad->server, MPD_PULSE_NAME, PA_STREAM_PLAYBACK,
ad->sink, MPD_PULSE_STREAM_NAME, &ss,
NULL, NULL, &error);
if (!ad->s) {
ERROR("Cannot connect to server in PulseAudio output " \
"\"%s\": %s\n", audioOutput->name, pa_strerror(error));
return -1;
}
audioOutput->open = 1;
DEBUG("PulseAudio output \"%s\" connected and playing %i bit, %i " \
"channel audio at %i Hz\n", audioOutput->name, audioFormat->bits,
audioFormat->channels, audioFormat->sampleRate);
return 0;
}
static void pulse_dropBufferedAudio(AudioOutput * audioOutput)
{
PulseData * ad;
int error;
ad = audioOutput->data;
if (pa_simple_flush(ad->s, &error) < 0)
WARNING("Flush failed in PulseAudio output \"%s\": %s\n",
audioOutput->name, pa_strerror(error));
}
static void pulse_closeDevice(AudioOutput * audioOutput)
{
PulseData * ad;
ad = audioOutput->data;
if (ad->s) {
pa_simple_drain(ad->s, NULL);
pa_simple_free(ad->s);
}
audioOutput->open = 0;
}
static int pulse_playAudio(AudioOutput * audioOutput, char * playChunk,
int size)
{
PulseData * ad;
int error;
ad = audioOutput->data;
if (pa_simple_write(ad->s, playChunk, size, &error) < 0) {
ERROR("PulseAudio output \"%s\" disconnecting due to write " \
"error: %s\n", audioOutput->name, pa_strerror(error));
pulse_closeDevice(audioOutput);
return -1;
}
return 0;
}
AudioOutputPlugin pulsePlugin = {
"pulse",
pulse_testDefault,
pulse_initDriver,
pulse_finishDriver,
pulse_openDevice,
pulse_playAudio,
pulse_dropBufferedAudio,
pulse_closeDevice,
NULL, /* sendMetadataFunc */
};
#else /* HAVE_PULSE */
AudioOutputPlugin pulsePlugin =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
#endif /* HAVE_PULSE */