From de0ef46ee9c9089a5a787fd1cd5f27ca475fc0be Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Thu, 7 Nov 2013 17:03:32 +0000 Subject: [PATCH] uaudio: pulseaudio support Organization: Straylight/Edgeware From: Richard Kettlewell Playback only, no volume setting. --- clients/Makefile.am | 3 +- clients/playrtp.c | 1 + configure.ac | 12 +++ disobedience/Makefile.am | 3 +- doc/disorder-playrtp.1.in | 3 + lib/Makefile.am | 1 + lib/uaudio-apis.c | 5 +- lib/uaudio-pulseaudio.c | 151 ++++++++++++++++++++++++++++++++++++++ lib/uaudio.h | 4 + server/Makefile.am | 6 +- server/speaker.c | 1 + 11 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 lib/uaudio-pulseaudio.c diff --git a/clients/Makefile.am b/clients/Makefile.am index 6ed9f4a..991554b 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -34,9 +34,10 @@ disorderfm_LDADD=$(LIBOBJS) ../lib/libdisorder.a $(LIBGC) $(LIBICONV) disorderfm_DEPENDENCIES=$(LIBOBJS) ../lib/libdisorder.a disorder_playrtp_SOURCES=playrtp.c playrtp.h playrtp-mem.c +disorder_playrtp_CFLAGS=$(PULSEAUDIO_CFLAGS) $(PULSEAUDIO_SIMPLE_CFLAGS) disorder_playrtp_LDADD=$(LIBOBJS) ../lib/libdisorder.a \ $(LIBASOUND) $(LIBPCRE) $(LIBICONV) $(LIBGCRYPT) $(COREAUDIO) \ - $(LIBPTHREAD) -lm + $(LIBPTHREAD) $(PULSEAUDIO_SIMPLE_LIBS) $(PULSEAUDIO_LIBS) -lm disorder_playrtp_DEPENDENCIES=$(LIBOBJS) ../lib/libdisorder.a rtpmon_SOURCES=rtpmon.c diff --git a/clients/playrtp.c b/clients/playrtp.c index 5956122..600aae1 100644 --- a/clients/playrtp.c +++ b/clients/playrtp.c @@ -855,6 +855,7 @@ int main(int argc, char **argv) { * the format before we know what it is! */ uaudio_set_format(44100/*Hz*/, 2/*channels*/, 16/*bits/channel*/, 1/*signed*/); + uaudio_set("application", "disorder-playrtp"); backend->start(playrtp_callback, NULL); /* We receive and convert audio data in a background thread */ if((err = pthread_create(<id, 0, listen_thread, 0))) diff --git a/configure.ac b/configure.ac index 37ef7cc..11085e0 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,7 @@ want_cgi=yes want_alsa=yes want_oss=yes want_coreaudio=yes +want_pulseaudio=yes # By default we don't want gtk-osx. But if you ask for --with-gtk-osx... # @@ -79,6 +80,10 @@ AC_ARG_WITH([alsa], [AS_HELP_STRING([--without-alsa], [do not build with ALSA support])], [want_alsa=$withval]) +AC_ARG_WITH([pulseaudio], + [AS_HELP_STRING([--without-pulseaudio], + [do not build with PulseAudio support])], + [want_pulseaudio=$withval]) AC_ARG_WITH([oss], [AS_HELP_STRING([--without-oss], [do not build with OSS support])], @@ -446,6 +451,13 @@ if test $want_alsa = yes; then AC_CHECK_LIB([asound], [snd_pcm_open], [AC_SUBST(LIBASOUND,[-lasound])]) fi +if test $want_pulseaudio = yes; then + PKG_CHECK_MODULES([PULSEAUDIO],[libpulse], + [AC_DEFINE([HAVE_PULSEAUDIO],[1],[define to 1 for PulseAudio support])], + [missing_libraries="$missing_libraries libpulse"]) + PKG_CHECK_MODULES([PULSEAUDIO_SIMPLE],[libpulse-simple],, + [missing_libraries="$missing_libraries libpulse-simple"]) +fi AC_CHECK_LIB([samplerate],[src_new], [AC_SUBST([LIBSAMPLERATE],[-lsamplerate])]) if test $want_server = yes; then diff --git a/disobedience/Makefile.am b/disobedience/Makefile.am index fa41a2c..4f79614 100644 --- a/disobedience/Makefile.am +++ b/disobedience/Makefile.am @@ -30,7 +30,8 @@ disobedience_SOURCES=disobedience.h disobedience.c client.c queue.c \ popup.h playlists.c multidrag.c multidrag.h autoscroll.c \ autoscroll.h globals.c disobedience_LDADD=../lib/libdisorder.a $(LIBPCRE) $(LIBGC) $(LIBGCRYPT) \ - $(LIBASOUND) $(COREAUDIO) $(LIBICONV) -lm + $(LIBASOUND) $(COREAUDIO) $(LIBICONV) -lm \ + $(PULSEAUDIO_SIMPLE_LIBS) $(PULSEAUDIO_LIBS) disobedience_LDFLAGS=$(GTK_LIBS) install-data-local: diff --git a/doc/disorder-playrtp.1.in b/doc/disorder-playrtp.1.in index abbeed5..228ae60 100644 --- a/doc/disorder-playrtp.1.in +++ b/doc/disorder-playrtp.1.in @@ -43,6 +43,9 @@ Select the playback API. The possibilities are, depending on platform and compilation options: .RS 8 .TP +.B pulseaudio +PulseAudio. +.TP .B alsa ALSA. Linux only. diff --git a/lib/Makefile.am b/lib/Makefile.am index 241c71e..4f7be92 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -85,6 +85,7 @@ libdisorder_a_SOURCES=charset.c charsetf.c charset.h \ tracksort.c \ uaudio.c uaudio-thread.c uaudio.h uaudio-apis.c \ uaudio-oss.c uaudio-alsa.c \ + uaudio-pulseaudio.c \ uaudio-coreaudio.c \ uaudio-rtp.c uaudio-command.c uaudio-schedule.c \ url.h url.c \ diff --git a/lib/uaudio-apis.c b/lib/uaudio-apis.c index 568ae36..867b1fd 100644 --- a/lib/uaudio-apis.c +++ b/lib/uaudio-apis.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2009 Richard Kettlewell + * Copyright (C) 2009, 2013 Richard Kettlewell * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,9 @@ const struct uaudio *const uaudio_apis[] = { #if HAVE_COREAUDIO_AUDIOHARDWARE_H &uaudio_coreaudio, #endif +#if HAVE_PULSEAUDIO + &uaudio_pulseaudio, +#endif #if HAVE_ALSA_ASOUNDLIB_H &uaudio_alsa, #endif diff --git a/lib/uaudio-pulseaudio.c b/lib/uaudio-pulseaudio.c new file mode 100644 index 0000000..f0124be --- /dev/null +++ b/lib/uaudio-pulseaudio.c @@ -0,0 +1,151 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2013 Richard Kettlewell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** @file lib/uaudio-pulseaudio.c + * @brief Support for PulseAudio backend */ +#include "common.h" + +#if HAVE_PULSEAUDIO + +#include +#include + +#include "mem.h" +#include "log.h" +#include "uaudio.h" +#include "configuration.h" + +static const char *const pulseaudio_options[] = { + "application", + NULL +}; + +static pa_simple *pulseaudio_simple_handle; + +/** @brief Open the PulseAudio sound device */ +static void pulseaudio_open() { + pa_sample_spec ss; + int error; + ss.format = -1; + switch(uaudio_bits) { + case 8: + if(!uaudio_signed) + ss.format = PA_SAMPLE_U8; + break; + case 16: + if(uaudio_signed) + ss.format = PA_SAMPLE_S16NE; + break; + case 32: + if(uaudio_signed) + ss.format = PA_SAMPLE_S32NE; + break; + } + if(ss.format == -1) + disorder_fatal(0, "unsupported uaudio format (%d, %d)", + uaudio_bits, uaudio_signed); + ss.channels = uaudio_channels; + ss.rate = uaudio_rate; + pulseaudio_simple_handle = pa_simple_new(NULL, + uaudio_get("application", "DisOrder"), + PA_STREAM_PLAYBACK, + NULL, + "DisOrder", + &ss, + NULL, + NULL, + &error); + if(!pulseaudio_simple_handle) + disorder_fatal(0, "pa_simple_new: %s", pa_strerror(error)); +} + +/** @brief Close the PulseAudio sound device */ +static void pulseaudio_close(void) { + pa_simple_free(pulseaudio_simple_handle); + pulseaudio_simple_handle = NULL; +} + +/** @brief Actually play sound via PulseAudio */ +static size_t pulseaudio_play(void *buffer, size_t samples, + unsigned attribute((unused)) flags) { + int error; + int ret = pa_simple_write(pulseaudio_simple_handle, + buffer, + samples * uaudio_sample_size, + &error); + if(ret < 0) + disorder_fatal(0, "pa_simple_write: %s", pa_strerror(error)); + return samples; +} + +static void pulseaudio_start(uaudio_callback *callback, + void *userdata) { + pulseaudio_open(); + uaudio_thread_start(callback, userdata, pulseaudio_play, + 32 / uaudio_sample_size, + 4096 / uaudio_sample_size, + 0); +} + +static void pulseaudio_stop(void) { + uaudio_thread_stop(); + pulseaudio_close(); +} + +static void pulseaudio_open_mixer(void) { + disorder_error(0, "no pulseaudio mixer support yet"); +} + +static void pulseaudio_close_mixer(void) { +} + +static void pulseaudio_get_volume(int *left, int *right) { + *left = *right = 0; +} + +static void pulseaudio_set_volume(int *left, int *right) { + *left = *right = 0; +} + +static void pulseaudio_configure(void) { +} + +const struct uaudio uaudio_pulseaudio = { + .name = "pulseaudio", + .options = pulseaudio_options, + .start = pulseaudio_start, + .stop = pulseaudio_stop, + .activate = uaudio_thread_activate, + .deactivate = uaudio_thread_deactivate, + .open_mixer = pulseaudio_open_mixer, + .close_mixer = pulseaudio_close_mixer, + .get_volume = pulseaudio_get_volume, + .set_volume = pulseaudio_set_volume, + .configure = pulseaudio_configure, + .flags = UAUDIO_API_CLIENT, +}; + +#endif + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/ diff --git a/lib/uaudio.h b/lib/uaudio.h index 2a32d40..631828f 100644 --- a/lib/uaudio.h +++ b/lib/uaudio.h @@ -195,6 +195,10 @@ extern const struct uaudio uaudio_alsa; extern const struct uaudio uaudio_oss; #endif +#if HAVE_PULSEAUDIO +extern const struct uaudio uaudio_pulseaudio; +#endif + extern const struct uaudio uaudio_rtp; extern const struct uaudio uaudio_command; diff --git a/server/Makefile.am b/server/Makefile.am index 8233cff..400b0ab 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -29,7 +29,8 @@ disorderd_SOURCES=disorderd.c api.c api-server.c daemonize.c play.c \ exports.c ../lib/memgc.c disorder-server.h disorderd_LDADD=$(LIBOBJS) ../lib/libdisorder.a \ $(LIBPCRE) $(LIBDB) $(LIBGC) $(LIBGCRYPT) $(LIBICONV) \ - $(LIBASOUND) $(COREAUDIO) $(LIBPTHREAD) $(LIBDL) + $(LIBASOUND) $(COREAUDIO) $(LIBPTHREAD) $(LIBDL) \ + $(PULSEAUDIO_SIMPLE_LIBS) $(PULSEAUDIO_LIBS) disorderd_LDFLAGS=-export-dynamic disorderd_DEPENDENCIES=../lib/libdisorder.a @@ -41,7 +42,8 @@ disorder_deadlock_DEPENDENCIES=../lib/libdisorder.a disorder_speaker_SOURCES=speaker.c disorder_speaker_LDADD=$(LIBOBJS) ../lib/libdisorder.a \ $(LIBASOUND) $(LIBPCRE) $(LIBICONV) $(LIBGCRYPT) $(COREAUDIO) \ - $(LIBPTHREAD) + $(LIBPTHREAD) \ + $(PULSEAUDIO_SIMPLE_LIBS) $(PULSEAUDIO_LIBS) disorder_speaker_DEPENDENCIES=../lib/libdisorder.a disorder_decode_SOURCES=decode.c decode.h disorder-server.h \ diff --git a/server/speaker.c b/server/speaker.c index a1b2d1d..fcfcf36 100644 --- a/server/speaker.c +++ b/server/speaker.c @@ -801,6 +801,7 @@ int main(int argc, char **argv) { /* backend-specific initialization */ if(backend->configure) backend->configure(); + uaudio_set("application", "disorder-speaker"); backend->start(speaker_callback, NULL); /* create the private socket directory */ byte_xasprintf(&dir, "%s/private", config->home); -- [mdw]