Add PulseAudio support
git-svn-id: https://svn.musicpd.org/mpd/trunk@4316 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
93681d914e
commit
09698f917c
18
configure.ac
18
configure.ac
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
193
src/audioOutputs/audioOutput_pulse.c
Normal file
193
src/audioOutputs/audioOutput_pulse.c
Normal 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 */
|
Loading…
Reference in New Issue
Block a user