1 diff --git a/audio.c b/audio.c
19 + if (!strcasecmp(name, "pulseaudio")) {
20 + pulse_funcs (funcs);
21 + printf ("Trying PulseAudio...\n");
22 + if (funcs->init(&hw_caps))
28 if (!strcasecmp(name, "oss")) {
30 diff --git a/configure.in b/configure.in
34 AC_MSG_ERROR([BerkeleyDB (libdb) not found.]))
37 +AC_ARG_WITH(pulse, AS_HELP_STRING(--without-pulse,
38 + Compile without PulseAudio support.))
40 +if test "x$with_pulse" != "xno"
42 + PKG_CHECK_MODULES(PULSE, [libpulse],
43 + [SOUND_DRIVERS="$SOUND_DRIVERS PULSE"
44 + EXTRA_OBJS="$EXTRA_OBJS pulse.o"
45 + AC_DEFINE([HAVE_PULSE], 1, [Define if you have PulseAudio.])
46 + EXTRA_LIBS="$EXTRA_LIBS $PULSE_LIBS"
47 + CFLAGS="$CFLAGS $PULSE_CFLAGS"],
52 AC_ARG_WITH(oss, AS_HELP_STRING([--without-oss],
53 [Compile without OSS support]))
55 diff --git a/options.c b/options.c
61 add_list ("SoundDriver", "SNDIO:JACK:OSS",
62 - CHECK_DISCRETE(5), "SNDIO", "Jack", "ALSA", "OSS", "null");
63 + CHECK_DISCRETE(5), "SNDIO", "PulseAudio", "Jack", "ALSA", "OSS", "null");
66 add_list ("SoundDriver", "Jack:ALSA:OSS",
67 - CHECK_DISCRETE(5), "SNDIO", "Jack", "ALSA", "OSS", "null");
68 + CHECK_DISCRETE(5), "SNDIO", "PulseAudio", "Jack", "ALSA", "OSS", "null");
71 add_str ("JackClientName", "moc", CHECK_NONE);
72 diff --git a/pulse.c b/pulse.c
78 + * MOC - music on console
79 + * Copyright (C) 2011 Marien Zwart <marienz@marienz.net>
81 + * This program is free software; you can redistribute it and/or modify
82 + * it under the terms of the GNU General Public License as published by
83 + * the Free Software Foundation; either version 2 of the License, or
84 + * (at your option) any later version.
88 +/* PulseAudio backend.
92 + * Does not autostart a PulseAudio server, but uses an already-started
93 + * one, which should be better than alsa-through-pulse.
95 + * Supports control of either our stream's or our entire sink's volume
96 + * while we are actually playing. Volume control while paused is
97 + * intentionally unsupported: the PulseAudio documentation strongly
98 + * suggests not passing in an initial volume when creating a stream
99 + * (allowing the server to track this instead), and we do not know
100 + * which sink to control if we do not have a stream open.
104 + * Most client-side (resource allocation) errors are fatal. Failure to
105 + * create a server context or stream is not fatal (and MOC should cope
106 + * with these failures too), but server communication failures later
107 + * on are currently not handled (MOC has no great way for us to tell
108 + * it we no longer work, and I am not sure if attempting to reconnect
109 + * is worth it or even a good idea).
111 + * The pulse "simple" API is too simple: it combines connecting to the
112 + * server and opening a stream into one operation, while I want to
113 + * connect to the server when MOC starts (and fall back to a different
114 + * backend if there is no server), and I cannot open a stream at that
115 + * time since I do not know the audio format yet.
117 + * PulseAudio strongly recommends we use a high-latency connection,
118 + * which the MOC frontend code might not expect from its audio
119 + * backend. We'll see.
121 + * We map MOC's percentage volumes linearly to pulse's PA_VOLUME_MUTED
122 + * (0) .. PA_VOLUME_NORM range. This is what the PulseAudio docs recommend
123 + * ( http://pulseaudio.org/wiki/WritingVolumeControlUIs ). It does mean
124 + * PulseAudio volumes above PA_VOLUME_NORM do not work well with MOC.
126 + * Comments in audio.h claim "All functions are executed only by one
127 + * thread" (referring to the function in the hw_funcs struct). This is
128 + * a blatant lie. Most of them are invoked off the "output buffer"
129 + * thread (out_buf.c) but at least the "playing" thread (audio.c)
130 + * calls audio_close which calls our close function. We can mostly
131 + * ignore this problem because we serialize on the pulseaudio threaded
132 + * mainloop lock. But it does mean that functions that are normally
133 + * only called between open and close (like reset) are sometimes
134 + * called without us having a stream. Bulletproof, therefore:
135 + * serialize setting/unsetting our global stream using the threaded
136 + * mainloop lock, and check for that stream being non-null before
139 + * I am not convinced there are no further dragons lurking here: can
140 + * the "playing" thread(s) close and reopen our output stream while
141 + * the "output buffer" thread is sending output there? We can bail if
142 + * our stream is simply closed, but we do not currently detect it
143 + * being reopened and no longer using the same sample format, which
144 + * might have interesting results...
146 + * Also, read_mixer is called from the main server thread (handling
147 + * commands). This crashed me once when it got at a stream that was in
148 + * the "creating" state and therefore did not have a valid stream
149 + * index yet. Fixed by only assigning to the stream global when the
153 +#ifdef HAVE_CONFIG_H
154 +# include "config.h"
159 +#include <pulse/pulseaudio.h>
165 +/* The pulse mainloop and context are initialized in pulse_init and
166 + * destroyed in pulse_shutdown.
168 +static pa_threaded_mainloop *mainloop = NULL;
169 +static pa_context *context = NULL;
171 +/* The stream is initialized in pulse_open and destroyed in pulse_close. */
172 +static pa_stream *stream = NULL;
174 +static int showing_sink_volume = 0;
176 +/* Callbacks that do nothing but wake up the mainloop. */
178 +static void context_state_callback (pa_context *context ATTR_UNUSED,
181 + pa_threaded_mainloop *m = userdata;
183 + pa_threaded_mainloop_signal (m, 0);
186 +static void stream_state_callback (pa_stream *stream ATTR_UNUSED,
189 + pa_threaded_mainloop *m = userdata;
191 + pa_threaded_mainloop_signal (m, 0);
194 +static void stream_write_callback (pa_stream *stream ATTR_UNUSED,
195 + size_t nbytes ATTR_UNUSED, void *userdata)
197 + pa_threaded_mainloop *m = userdata;
199 + pa_threaded_mainloop_signal (m, 0);
202 +/* Initialize pulse mainloop and context. Failure to connect to the
203 + * pulse daemon is nonfatal, everything else is fatal (as it
204 + * presumably means we ran out of resources).
206 +static int pulse_init (struct output_driver_caps *caps)
209 + pa_proplist *proplist;
211 + assert (!mainloop);
214 + mainloop = pa_threaded_mainloop_new ();
216 + fatal ("Cannot create PulseAudio mainloop");
218 + if (pa_threaded_mainloop_start (mainloop) < 0)
219 + fatal ("Cannot start PulseAudio mainloop");
221 + /* TODO: possibly add more props.
223 + * There are a few we could set in proplist.h but nothing I
224 + * expect to be very useful.
226 + * http://pulseaudio.org/wiki/ApplicationProperties recommends
227 + * setting at least application.name, icon.name and media.role.
229 + * No need to set application.name here, the name passed to
230 + * pa_context_new_with_proplist overrides it.
232 + proplist = pa_proplist_new ();
234 + fatal ("Cannot allocate PulseAudio proplist");
236 + pa_proplist_sets (proplist,
237 + PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
238 + pa_proplist_sets (proplist, PA_PROP_MEDIA_ROLE, "music");
239 + pa_proplist_sets (proplist, PA_PROP_APPLICATION_ID, "net.daper.moc");
241 + pa_threaded_mainloop_lock (mainloop);
243 + c = pa_context_new_with_proplist (
244 + pa_threaded_mainloop_get_api (mainloop),
245 + PACKAGE_NAME, proplist);
246 + pa_proplist_free (proplist);
249 + fatal ("Cannot allocate PulseAudio context");
251 + pa_context_set_state_callback (c, context_state_callback, mainloop);
253 + /* Ignore return value, rely on state being set properly */
254 + pa_context_connect (c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
257 + pa_context_state_t state = pa_context_get_state (c);
259 + if (state == PA_CONTEXT_READY)
262 + if (!PA_CONTEXT_IS_GOOD (state)) {
263 + error ("PulseAudio connection failed: %s",
264 + pa_strerror (pa_context_errno (c)));
266 + goto unlock_and_fail;
269 + debug ("waiting for context to become ready...");
270 + pa_threaded_mainloop_wait (mainloop);
273 + /* Only set the global now that the context is actually ready */
276 + pa_threaded_mainloop_unlock (mainloop);
278 + /* We just make up the hardware capabilities, since pulse is
279 + * supposed to be abstracting these out. Assume pulse will
280 + * deal with anything we want to throw at it, and that we will
281 + * only want mono or stereo audio.
283 + caps->min_channels = 1;
284 + caps->max_channels = 2;
285 + caps->formats = (SFMT_S8 | SFMT_S16 | SFMT_S32 |
286 + SFMT_FLOAT | SFMT_BE | SFMT_LE);
292 + pa_context_unref (c);
294 + pa_threaded_mainloop_unlock (mainloop);
296 + pa_threaded_mainloop_stop (mainloop);
297 + pa_threaded_mainloop_free (mainloop);
303 +static void pulse_shutdown (void)
305 + pa_threaded_mainloop_lock (mainloop);
307 + pa_context_disconnect (context);
308 + pa_context_unref (context);
311 + pa_threaded_mainloop_unlock (mainloop);
313 + pa_threaded_mainloop_stop (mainloop);
314 + pa_threaded_mainloop_free (mainloop);
318 +static int pulse_open (struct sound_params *sound_params)
325 + /* Initialize everything to -1, which in practice gets us
326 + * about 2 seconds of latency (which is fine). This is not the
327 + * same as passing NULL for this struct, which gets us an
328 + * unnecessarily short alsa-like latency.
330 + ba.fragsize = (uint32_t) -1;
331 + ba.tlength = (uint32_t) -1;
332 + ba.prebuf = (uint32_t) -1;
333 + ba.minreq = (uint32_t) -1;
334 + ba.maxlength = (uint32_t) -1;
336 + ss.channels = sound_params->channels;
337 + ss.rate = sound_params->rate;
338 + switch (sound_params->fmt) {
340 + ss.format = PA_SAMPLE_U8;
342 + case SFMT_S16 | SFMT_LE:
343 + ss.format = PA_SAMPLE_S16LE;
345 + case SFMT_S16 | SFMT_BE:
346 + ss.format = PA_SAMPLE_S16BE;
348 + case SFMT_FLOAT | SFMT_LE:
349 + ss.format = PA_SAMPLE_FLOAT32LE;
351 + case SFMT_FLOAT | SFMT_BE:
352 + ss.format = PA_SAMPLE_FLOAT32BE;
354 + case SFMT_S32 | SFMT_LE:
355 + ss.format = PA_SAMPLE_S32LE;
357 + case SFMT_S32 | SFMT_BE:
358 + ss.format = PA_SAMPLE_S32BE;
362 + fatal ("pulse: got unrequested format");
365 + debug ("opening stream");
367 + pa_threaded_mainloop_lock (mainloop);
369 + /* TODO: figure out if there are useful stream properties to set.
371 + * I do not really see any in proplist.h that we can set from
372 + * here (there are media title/artist/etc props but we do not
373 + * have that data available here).
375 + s = pa_stream_new (context, "music", &ss, NULL);
377 + fatal ("pulse: stream allocation failed");
379 + pa_stream_set_state_callback (s, stream_state_callback, mainloop);
380 + pa_stream_set_write_callback (s, stream_write_callback, mainloop);
382 + /* Ignore return value, rely on failed stream state instead. */
383 + pa_stream_connect_playback (
385 + PA_STREAM_INTERPOLATE_TIMING |
386 + PA_STREAM_AUTO_TIMING_UPDATE |
387 + PA_STREAM_ADJUST_LATENCY,
391 + pa_stream_state_t state = pa_stream_get_state (s);
393 + if (state == PA_STREAM_READY)
396 + if (!PA_STREAM_IS_GOOD (state)) {
397 + error ("PulseAudio stream connection failed");
402 + debug ("waiting for stream to become ready...");
403 + pa_threaded_mainloop_wait (mainloop);
406 + /* Only set the global stream now that it is actually ready */
409 + pa_threaded_mainloop_unlock (mainloop);
414 + pa_stream_unref (s);
416 + pa_threaded_mainloop_unlock (mainloop);
420 +static void pulse_close (void)
422 + debug ("closing stream");
424 + pa_threaded_mainloop_lock (mainloop);
426 + pa_stream_disconnect (stream);
427 + pa_stream_unref (stream);
430 + pa_threaded_mainloop_unlock (mainloop);
433 +static int pulse_play (const char *buff, const size_t size)
437 + debug ("Got %d bytes to play", (int)size);
439 + pa_threaded_mainloop_lock (mainloop);
441 + /* The buffer is usually writable when we get here, and there
442 + * are usually few (if any) writes after the first one. So
443 + * there is no point in doing further writes directly from the
444 + * callback: we can just do all writes from this thread.
447 + /* Break out of the loop if some other thread manages to close
448 + * our stream underneath us.
451 + size_t towrite = MIN(pa_stream_writable_size (stream),
453 + debug ("writing %d bytes", (int)towrite);
455 + /* We have no working way of dealing with errors
457 + if (pa_stream_write(stream, buff + offset, towrite,
458 + NULL, 0, PA_SEEK_RELATIVE))
459 + error ("pa_stream_write failed");
463 + if (offset >= size)
466 + pa_threaded_mainloop_wait (mainloop);
469 + pa_threaded_mainloop_unlock (mainloop);
471 + debug ("Done playing!");
473 + /* We should always return size, calling code does not deal
474 + * well with anything else. Only read the rest if you want to
477 + * The output buffer reader thread (out_buf.c:read_thread)
478 + * repeatedly loads some 64k/0.1s of audio into a buffer on
479 + * the stack, then calls audio_send_pcm repeatedly until this
480 + * entire buffer has been processed (similar to the loop in
481 + * this function). audio_send_pcm applies the softmixer and
482 + * equalizer, then feeds the result to this function, passing
483 + * through our return value.
485 + * So if we return less than size the equalizer/softmixer is
486 + * re-applied to the remaining data, which is silly. Also,
487 + * audio_send_pcm checks for our return value being zero and
488 + * calls fatal() if it is, so try to always process *some*
489 + * data. Also, out_buf.c uses the return value of this
490 + * function from the last run through its inner loop to update
491 + * its time attribute, which means it will be interestingly
492 + * off if that loop ran more than once.
494 + * Oh, and alsa.c seems to think it can return -1 to indicate
495 + * failure, which will cause out_buf.c to rewind its buffer
496 + * (to before its start, usually).
501 +static void volume_cb (const pa_cvolume *v, void *userdata)
503 + int *result = userdata;
506 + *result = 100 * pa_cvolume_avg (v) / PA_VOLUME_NORM;
508 + pa_threaded_mainloop_signal (mainloop, 0);
511 +static void sink_volume_cb (pa_context *c ATTR_UNUSED,
512 + const pa_sink_info *i, int eol ATTR_UNUSED,
515 + volume_cb (i ? &i->volume : NULL, userdata);
518 +static void sink_input_volume_cb (pa_context *c ATTR_UNUSED,
519 + const pa_sink_input_info *i,
520 + int eol ATTR_UNUSED,
521 + void *userdata ATTR_UNUSED)
523 + volume_cb (i ? &i->volume : NULL, userdata);
526 +static int pulse_read_mixer (void)
531 + debug ("read mixer");
533 + pa_threaded_mainloop_lock (mainloop);
536 + if (showing_sink_volume)
537 + op = pa_context_get_sink_info_by_index (
538 + context, pa_stream_get_device_index (stream),
539 + sink_volume_cb, &result);
541 + op = pa_context_get_sink_input_info (
542 + context, pa_stream_get_index (stream),
543 + sink_input_volume_cb, &result);
545 + while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
546 + pa_threaded_mainloop_wait (mainloop);
548 + pa_operation_unref (op);
551 + pa_threaded_mainloop_unlock (mainloop);
556 +static void pulse_set_mixer (int vol)
561 + /* Setting volume for one channel does the right thing. */
562 + pa_cvolume_set(&v, 1, vol * PA_VOLUME_NORM / 100);
564 + pa_threaded_mainloop_lock (mainloop);
567 + if (showing_sink_volume)
568 + op = pa_context_set_sink_volume_by_index (
569 + context, pa_stream_get_device_index (stream),
572 + op = pa_context_set_sink_input_volume (
573 + context, pa_stream_get_index (stream),
576 + pa_operation_unref (op);
579 + pa_threaded_mainloop_unlock (mainloop);
582 +static int pulse_get_buff_fill (void)
584 + /* This function is problematic. MOC uses it to for the "time
585 + * remaining" in the UI, but calls it more than once per
586 + * second (after each chunk of audio played, not for each
587 + * playback time update). We have to be fairly accurate here
588 + * for that time remaining to not jump weirdly. But PulseAudio
589 + * cannot give us a 100% accurate value here, as it involves a
590 + * server roundtrip. And if we call this a lot it suggests
591 + * switching to a mode where the value is interpolated, making
592 + * it presumably more inaccurate (see the flags we pass to
593 + * pa_stream_connect_playback).
595 + * MOC also contains what I believe to be a race: it calls
596 + * audio_get_buff_fill "soon" (after playing the first chunk)
597 + * after starting playback of the next song, at which point we
598 + * still have part of the previous song buffered. This means
599 + * our position into the new song is negative, which fails an
600 + * assert (in out_buf.c:out_buf_time_get). There is no sane
601 + * way for us to detect this condition. I believe no other
602 + * backend triggers this because the assert sits after an
603 + * implicit float -> int seconds conversion, which means we
604 + * have to be off by at least an entire second to get a
605 + * negative value, and none of the other backends have buffers
606 + * that large (alsa buffers are supposedly a few 100 ms).
608 + pa_usec_t buffered_usecs = 0;
609 + int buffered_bytes = 0;
611 + pa_threaded_mainloop_lock (mainloop);
613 + /* Using pa_stream_get_timing_info and returning the distance
614 + * between write_index and read_index would be more obvious,
615 + * but because of how the result is actually used I believe
616 + * using the latency value is slightly more correct, and it
617 + * makes the following crash-avoidance hack more obvious.
620 + /* This function will frequently fail the first time we call
621 + * it (pulse does not have the requested data yet). We ignore
622 + * that and just return 0.
624 + * Deal with stream being NULL too, just in case this is
625 + * called in a racy fashion similar to how reset() is.
628 + pa_stream_get_latency (stream, &buffered_usecs, NULL) >= 0) {
629 + /* Crash-avoidance HACK: floor our latency to at most
630 + * 1 second. It is usually more, but reporting that at
631 + * the start of playback crashes MOC, and we cannot
632 + * sanely detect when reporting it is safe.
634 + if (buffered_usecs > 1000000)
635 + buffered_usecs = 1000000;
637 + buffered_bytes = pa_usec_to_bytes (
639 + pa_stream_get_sample_spec (stream));
642 + pa_threaded_mainloop_unlock (mainloop);
644 + debug ("buffer fill: %d usec / %d bytes",
645 + (int) buffered_usecs, (int) buffered_bytes);
647 + return buffered_bytes;
650 +static void flush_callback (pa_stream *s ATTR_UNUSED, int success,
653 + int *result = userdata;
657 + pa_threaded_mainloop_signal (mainloop, 0);
660 +static int pulse_reset (void)
665 + debug ("reset requested");
667 + pa_threaded_mainloop_lock (mainloop);
669 + /* We *should* have a stream here, but MOC is racy, so bulletproof */
671 + op = pa_stream_flush (stream, flush_callback, &result);
673 + while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
674 + pa_threaded_mainloop_wait (mainloop);
676 + pa_operation_unref (op);
678 + logit ("pulse_reset() called without a stream");
680 + pa_threaded_mainloop_unlock (mainloop);
685 +static int pulse_get_rate (void)
687 + /* This is called once right after open. Do not bother making
692 + pa_threaded_mainloop_lock (mainloop);
695 + result = pa_stream_get_sample_spec (stream)->rate;
697 + error ("get_rate called without a stream");
701 + pa_threaded_mainloop_unlock (mainloop);
706 +static void pulse_toggle_mixer_channel (void)
708 + showing_sink_volume = !showing_sink_volume;
711 +static void sink_name_cb (pa_context *c ATTR_UNUSED,
712 + const pa_sink_info *i, int eol ATTR_UNUSED,
715 + char **result = userdata;
718 + *result = xstrdup (i->name);
720 + pa_threaded_mainloop_signal (mainloop, 0);
723 +static void sink_input_name_cb (pa_context *c ATTR_UNUSED,
724 + const pa_sink_input_info *i,
725 + int eol ATTR_UNUSED,
728 + char **result = userdata;
731 + *result = xstrdup (i->name);
733 + pa_threaded_mainloop_signal (mainloop, 0);
736 +static char *pulse_get_mixer_channel_name (void)
738 + char *result = NULL;
741 + pa_threaded_mainloop_lock (mainloop);
744 + if (showing_sink_volume)
745 + op = pa_context_get_sink_info_by_index (
746 + context, pa_stream_get_device_index (stream),
747 + sink_name_cb, &result);
749 + op = pa_context_get_sink_input_info (
750 + context, pa_stream_get_index (stream),
751 + sink_input_name_cb, &result);
753 + while (pa_operation_get_state (op) == PA_OPERATION_RUNNING)
754 + pa_threaded_mainloop_wait (mainloop);
756 + pa_operation_unref (op);
759 + pa_threaded_mainloop_unlock (mainloop);
762 + result = xstrdup ("disconnected");
767 +void pulse_funcs (struct hw_funcs *funcs)
769 + funcs->init = pulse_init;
770 + funcs->shutdown = pulse_shutdown;
771 + funcs->open = pulse_open;
772 + funcs->close = pulse_close;
773 + funcs->play = pulse_play;
774 + funcs->read_mixer = pulse_read_mixer;
775 + funcs->set_mixer = pulse_set_mixer;
776 + funcs->get_buff_fill = pulse_get_buff_fill;
777 + funcs->reset = pulse_reset;
778 + funcs->get_rate = pulse_get_rate;
779 + funcs->toggle_mixer_channel = pulse_toggle_mixer_channel;
780 + funcs->get_mixer_channel_name = pulse_get_mixer_channel_name;
782 diff --git a/pulse.h b/pulse.h
794 +void pulse_funcs (struct hw_funcs *funcs);