]> git.sesse.net Git - vlc/blob - modules/audio_output/pulse.c
cd15f84f57ed53b8540de5fe35013b1e8773d133
[vlc] / modules / audio_output / pulse.c
1 /*****************************************************************************
2  * pulse.c : Pulseaudio output plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2008 the VideoLAN team
5  * Copyright (C) 2009-2011 RĂ©mi Denis-Courmont
6  *
7  * Authors: Martin Hamrle <hamrle @ post . cz>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <math.h>
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_aout.h>
32 #include <vlc_cpu.h>
33
34 #include <pulse/pulseaudio.h>
35 #include <vlc_pulse.h>
36 #if !PA_CHECK_VERSION(0,9,22)
37 # include <vlc_xlib.h>
38 #endif
39
40 static int  Open        ( vlc_object_t * );
41 static void Close       ( vlc_object_t * );
42
43 vlc_module_begin ()
44     set_shortname( "PulseAudio" )
45     set_description( N_("Pulseaudio audio output") )
46     set_capability( "audio output", 160 )
47     set_category( CAT_AUDIO )
48     set_subcategory( SUBCAT_AUDIO_AOUT )
49     add_shortcut( "pulseaudio", "pa" )
50     set_callbacks( Open, Close )
51 vlc_module_end ()
52
53 /* TODO:
54  * - pause input on policy event
55  * - resample to compensate for long term drift
56  * - select music or video stream property correctly (?)
57  * - set further appropriate stream properties
58  * - update output devices list dynamically
59  */
60
61 /* NOTE:
62  * Be careful what you do when the PulseAudio mainloop is held, which is to say
63  * within PulseAudio callbacks, or after vlc_pa_lock().
64  * In particular, a VLC variable callback cannot be triggered nor deleted with
65  * the PulseAudio mainloop lock held, if the callback acquires the lock. */
66
67 struct aout_sys_t
68 {
69     pa_stream *stream; /**< PulseAudio playback stream object */
70     pa_context *context; /**< PulseAudio connection context */
71     pa_time_event *trigger; /**< Deferred stream trigger */
72     pa_volume_t base_volume; /**< 0dB reference volume */
73     pa_cvolume cvolume; /**< actual sink input volume */
74     mtime_t paused; /**< Time when (last) paused */
75     mtime_t pts; /**< Play time of buffer write offset */
76     mtime_t desync; /**< Measured desynchronization */
77     unsigned rate; /**< Current stream sample rate */
78 };
79
80 static void sink_list_cb(pa_context *, const pa_sink_info *, int, void *);
81 static void sink_input_info_cb(pa_context *, const pa_sink_input_info *,
82                                int, void *);
83
84 /*** Context ***/
85 static void context_cb(pa_context *ctx, pa_subscription_event_type_t type,
86                        uint32_t idx, void *userdata)
87 {
88     audio_output_t *aout = userdata;
89     aout_sys_t *sys = aout->sys;
90     pa_operation *op;
91
92     switch (type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
93     {
94       case PA_SUBSCRIPTION_EVENT_SINK:
95         switch (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK)
96         {
97           case PA_SUBSCRIPTION_EVENT_NEW:
98           case PA_SUBSCRIPTION_EVENT_CHANGE:
99             op = pa_context_get_sink_info_by_index(ctx, idx, sink_list_cb, aout);
100             if (likely(op != NULL))
101                 pa_operation_unref(op);
102             break;
103
104           case PA_SUBSCRIPTION_EVENT_REMOVE:
105             var_Change(aout, "audio-device", VLC_VAR_DELCHOICE,
106                        &(vlc_value_t){ .i_int = idx }, NULL);
107             break;
108         }
109         break;
110
111       case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
112         if (idx != pa_stream_get_index(sys->stream))
113             break; /* only interested in our sink input */
114
115         /* Gee... PA will not provide the infos directly in the event. */
116         switch (type & PA_SUBSCRIPTION_EVENT_TYPE_MASK)
117         {
118           case PA_SUBSCRIPTION_EVENT_REMOVE:
119             msg_Err(aout, "sink input killed!");
120             break;
121
122           default:
123             op = pa_context_get_sink_input_info(ctx, idx, sink_input_info_cb,
124                                                 aout);
125             if (likely(op != NULL))
126                 pa_operation_unref(op);
127             break;
128         }
129         break;
130
131       default: /* unsubscribed facility?! */
132         assert(0);
133     }
134 }
135
136
137 /*** Sink ***/
138 static void sink_list_cb(pa_context *c, const pa_sink_info *i, int eol,
139                          void *userdata)
140 {
141     audio_output_t *aout = userdata;
142     vlc_value_t val, text;
143
144     if (eol)
145         return;
146     (void) c;
147
148     msg_Dbg(aout, "listing sink %s (%"PRIu32"): %s", i->name, i->index,
149             i->description);
150     val.i_int = i->index;
151     text.psz_string = (char *)i->description;
152     var_Change(aout, "audio-device", VLC_VAR_DELCHOICE, &val, NULL);
153     var_Change(aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text);
154 }
155
156 static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
157                          void *userdata)
158 {
159     audio_output_t *aout = userdata;
160     aout_sys_t *sys = aout->sys;
161
162     if (eol)
163         return;
164     (void) c;
165
166     /* PulseAudio flat volume NORM / 100% / 0dB corresponds to no software
167      * amplification and maximum hardware amplification.
168      * VLC maps DEFAULT / 100% to no gain at all (software/hardware).
169      * Thus we need to use the sink base_volume as a multiplier,
170      * if and only if flat volume is active for our current sink. */
171     if (i->flags & PA_SINK_FLAT_VOLUME)
172         sys->base_volume = i->base_volume;
173     else
174         sys->base_volume = PA_VOLUME_NORM;
175     msg_Dbg(aout, "base volume: %"PRIu32, sys->base_volume);
176 }
177
178
179 /*** Latency management and lip synchronization ***/
180 static mtime_t vlc_pa_get_latency(audio_output_t *aout,
181                                   pa_context *ctx, pa_stream *s)
182 {
183     pa_usec_t latency;
184     int negative;
185
186     if (pa_stream_get_latency(s, &latency, &negative)) {
187         if (pa_context_errno (ctx) != PA_ERR_NODATA)
188             vlc_pa_error(aout, "unknown latency", ctx);
189         return VLC_TS_INVALID;
190     }
191     return negative ? -latency : +latency;
192 }
193
194 static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
195 {
196     aout_sys_t *sys = aout->sys;
197     const unsigned rate = aout->format.i_rate;
198
199     sys->pts = VLC_TS_INVALID;
200     sys->desync = 0;
201     pa_operation *op = pa_stream_update_sample_rate(s, rate, NULL, NULL);
202     if (unlikely(op == NULL))
203         return;
204     pa_operation_unref(op);
205     sys->rate = rate;
206 }
207
208 static void stream_start(pa_stream *s, audio_output_t *aout)
209 {
210     aout_sys_t *sys = aout->sys;
211     pa_operation *op;
212
213     if (sys->trigger != NULL) {
214         vlc_pa_rttime_free(sys->trigger);
215         sys->trigger = NULL;
216     }
217
218     op = pa_stream_cork(s, 0, NULL, NULL);
219     if (op != NULL)
220         pa_operation_unref(op);
221     op = pa_stream_trigger(s, NULL, NULL);
222     if (likely(op != NULL))
223         pa_operation_unref(op);
224 }
225
226 static void stream_stop(pa_stream *s, audio_output_t *aout)
227 {
228     aout_sys_t *sys = aout->sys;
229     pa_operation *op;
230
231     if (sys->trigger != NULL) {
232         vlc_pa_rttime_free(sys->trigger);
233         sys->trigger = NULL;
234     }
235
236     op = pa_stream_cork(s, 1, NULL, NULL);
237     if (op != NULL)
238         pa_operation_unref(op);
239 }
240
241 static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e,
242                               const struct timeval *tv, void *userdata)
243 {
244     audio_output_t *aout = userdata;
245     aout_sys_t *sys = aout->sys;
246
247     msg_Dbg(aout, "starting deferred");
248     assert (sys->trigger == e);
249     stream_start(sys->stream, aout);
250     (void) api; (void) e; (void) tv;
251 }
252
253 /**
254  * Starts or resumes the playback stream.
255  * Tries start playing back audio samples at the most accurate time
256  * in order to minimize desync and resampling during early playback.
257  * @note PulseAudio lock required.
258  */
259 static void stream_resync(audio_output_t *aout, pa_stream *s)
260 {
261     aout_sys_t *sys = aout->sys;
262     mtime_t delta;
263
264     assert (pa_stream_is_corked(s) > 0);
265     assert (sys->pts != VLC_TS_INVALID);
266
267     delta = vlc_pa_get_latency(aout, sys->context, s);
268     if (unlikely(delta == VLC_TS_INVALID))
269         delta = 0; /* screwed */
270
271     delta = (sys->pts - mdate()) - delta;
272     if (delta > 0) {
273         if (sys->trigger == NULL) {
274             msg_Dbg(aout, "deferring start (%"PRId64" us)", delta);
275             delta += pa_rtclock_now();
276             sys->trigger = pa_context_rttime_new(sys->context, delta,
277                                                  stream_trigger_cb, aout);
278         }
279     } else {
280         msg_Warn(aout, "starting late (%"PRId64" us)", delta);
281         stream_start(s, aout);
282     }
283 }
284
285 static void stream_latency_cb(pa_stream *s, void *userdata)
286 {
287     audio_output_t *aout = userdata;
288     aout_sys_t *sys = aout->sys;
289     mtime_t delta, change;
290
291     if (pa_stream_is_corked(s))
292         return;
293     if (sys->pts == VLC_TS_INVALID)
294     {
295         msg_Dbg(aout, "missing latency from input");
296         return;
297     }
298
299     /* Compute lip desynchronization */
300     delta = vlc_pa_get_latency(aout, sys->context, s);
301     if (delta == VLC_TS_INVALID)
302         return;
303
304     delta = (sys->pts - mdate()) - delta;
305     change = delta - sys->desync;
306     sys->desync = delta;
307     //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
308     //        delta, change);
309
310     const unsigned inrate = aout->format.i_rate;
311     unsigned outrate = sys->rate;
312     bool sync = false;
313
314     if (delta < -AOUT_MAX_PTS_DELAY)
315         msg_Warn(aout, "too late by %"PRId64" us", -delta);
316     else if (delta > +AOUT_MAX_PTS_ADVANCE)
317         msg_Warn(aout, "too early by %"PRId64" us", delta);
318     else if (outrate  == inrate)
319         return; /* In sync, do not add unnecessary disturbance! */
320     else
321         sync = true;
322
323     /* Compute playback sample rate */
324     /* This is empirical (especially the shift values).
325      * Feel free to define something smarter. */
326     int adj = sync ? (outrate - inrate)
327                    : outrate * ((delta >> 4) + change) / (CLOCK_FREQ << 2);
328     /* This avoids too quick rate variation. It sounds really bad and
329      * causes unstability (e.g. oscillation around the correct rate). */
330     int limit = inrate >> 10;
331     /* However, to improve stability and try to converge, closing to the
332      * nominal rate is favored over drifting from it. */
333     if ((adj > 0) == (sys->rate > inrate))
334         limit *= 2;
335     if (adj > +limit)
336         adj = +limit;
337     if (adj < -limit)
338         adj = -limit;
339     outrate -= adj;
340
341     /* This keeps the effective rate within specified range
342      * (+/-AOUT_MAX_RESAMPLING% - see <vlc_aout.h>) of the nominal rate. */
343     limit = inrate * AOUT_MAX_RESAMPLING / 100;
344     if (outrate > inrate + limit)
345         outrate = inrate + limit;
346     if (outrate < inrate - limit)
347         outrate = inrate - limit;
348
349     /* Apply adjusted sample rate */
350     if (outrate == sys->rate)
351         return;
352     pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
353     if (unlikely(op == NULL)) {
354         vlc_pa_error(aout, "cannot change sample rate", sys->context);
355         return;
356     }
357     pa_operation_unref(op);
358     msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
359     sys->rate = outrate;
360 }
361
362
363 /*** Stream helpers ***/
364 static void stream_state_cb(pa_stream *s, void *userdata)
365 {
366     switch (pa_stream_get_state(s)) {
367         case PA_STREAM_READY:
368         case PA_STREAM_FAILED:
369         case PA_STREAM_TERMINATED:
370             vlc_pa_signal(0);
371         default:
372             break;
373     }
374     (void) userdata;
375 }
376
377 static void stream_event_cb(pa_stream *s, const char *name, pa_proplist *pl,
378                             void *userdata)
379 {
380     audio_output_t *aout = userdata;
381
382 #if PA_CHECK_VERSION(1,0,0)
383     /* FIXME: expose aout_Restart() directly */
384     if (!strcmp(name, PA_STREAM_EVENT_FORMAT_LOST)) {
385         vlc_value_t dummy = { .i_int = 0 };
386
387         msg_Dbg (aout, "format lost");
388         aout_ChannelsRestart (VLC_OBJECT(aout), "audio-device",
389                               dummy, dummy, NULL);
390     } else
391 #endif
392         msg_Warn (aout, "unhandled event %s", name);
393     (void) s;
394     (void) pl;
395 }
396
397 static void stream_moved_cb(pa_stream *s, void *userdata)
398 {
399     audio_output_t *aout = userdata;
400     aout_sys_t *sys = aout->sys;
401     pa_operation *op;
402     uint32_t idx = pa_stream_get_device_index(s);
403
404     msg_Dbg(aout, "connected to sink %"PRIu32": %s", idx,
405                   pa_stream_get_device_name(s));
406     op = pa_context_get_sink_info_by_index(sys->context, idx,
407                                            sink_info_cb, aout);
408     if (likely(op != NULL))
409         pa_operation_unref(op);
410
411     /* Update the variable if someone else moved our stream */
412     var_Change(aout, "audio-device", VLC_VAR_SETVALUE,
413                &(vlc_value_t){ .i_int = idx }, NULL);
414
415     /* Sink unknown as yet, create stub choice for it */
416     if (var_GetInteger(aout, "audio-device") != idx)
417     {
418         var_Change(aout, "audio-device", VLC_VAR_ADDCHOICE,
419                    &(vlc_value_t){ .i_int = idx },
420                    &(vlc_value_t){ .psz_string = (char *)"?" });
421         var_Change(aout, "audio-device", VLC_VAR_SETVALUE,
422                    &(vlc_value_t){ .i_int = idx }, NULL);
423     }
424 }
425
426 static void stream_overflow_cb(pa_stream *s, void *userdata)
427 {
428     audio_output_t *aout = userdata;
429
430     msg_Err(aout, "overflow");
431     (void) s;
432 }
433
434 static void stream_started_cb(pa_stream *s, void *userdata)
435 {
436     audio_output_t *aout = userdata;
437
438     msg_Dbg(aout, "started");
439     (void) s;
440 }
441
442 static void stream_suspended_cb(pa_stream *s, void *userdata)
443 {
444     audio_output_t *aout = userdata;
445
446     msg_Dbg(aout, "suspended");
447     stream_reset_sync(s, aout);
448 }
449
450 static void stream_underflow_cb(pa_stream *s, void *userdata)
451 {
452     audio_output_t *aout = userdata;
453
454     msg_Warn(aout, "underflow");
455     stream_stop(s, aout);
456     stream_reset_sync(s, aout);
457 }
458
459 static int stream_wait(pa_stream *stream)
460 {
461     pa_stream_state_t state;
462
463     while ((state = pa_stream_get_state(stream)) != PA_STREAM_READY) {
464         if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
465             return -1;
466         vlc_pa_wait();
467     }
468     return 0;
469 }
470
471
472 /*** Sink input ***/
473 static void sink_input_info_cb(pa_context *ctx, const pa_sink_input_info *i,
474                                int eol, void *userdata)
475 {
476     audio_output_t *aout = userdata;
477     aout_sys_t *sys = aout->sys;
478     float volume;
479
480     if (eol)
481         return;
482     (void) ctx;
483
484     sys->cvolume = i->volume;
485     volume = pa_cvolume_max(&i->volume) / (float)PA_VOLUME_NORM;
486     aout_VolumeHardSet(aout, volume, i->mute);
487 }
488
489
490 /*** VLC audio output callbacks ***/
491
492 /* Memory free callback. The block_t address is in front of the data. */
493 static void data_free(void *data)
494 {
495     block_t **pp = data, *block;
496
497     memcpy(&block, pp - 1, sizeof (block));
498     block_Release(block);
499 }
500
501 static void *data_convert(block_t **pp)
502 {
503     block_t *block = *pp;
504     /* In most cases, there is enough head room, and this is really cheap: */
505     block = block_Realloc(block, sizeof (block), block->i_buffer);
506     *pp = block;
507     if (unlikely(block == NULL))
508         return NULL;
509
510     memcpy(block->p_buffer, &block, sizeof (block));
511     block->p_buffer += sizeof (block);
512     block->i_buffer -= sizeof (block);
513     return block->p_buffer;
514 }
515
516 /**
517  * Queue one audio frame to the playabck stream
518  */
519 static void Play(audio_output_t *aout, block_t *block)
520 {
521     aout_sys_t *sys = aout->sys;
522     pa_stream *s = sys->stream;
523
524     const void *ptr = data_convert(&block);
525     if (unlikely(ptr == NULL))
526         return;
527
528     size_t len = block->i_buffer;
529     mtime_t pts = block->i_pts + block->i_length;
530
531     /* Note: The core already holds the output FIFO lock at this point.
532      * Therefore we must not under any circumstances (try to) acquire the
533      * output FIFO lock while the PulseAudio threaded main loop lock is held
534      * (including from PulseAudio stream callbacks). Otherwise lock inversion
535      * will take place, and sooner or later a deadlock. */
536     vlc_pa_lock();
537
538     sys->pts = pts;
539     if (pa_stream_is_corked(s) > 0)
540         stream_resync(aout, s);
541
542 #if 0 /* Fault injector to test underrun recovery */
543     static volatile unsigned u = 0;
544     if ((++u % 1000) == 0) {
545         msg_Err(aout, "fault injection");
546         pa_operation_unref(pa_stream_flush(s, NULL, NULL));
547     }
548 #endif
549
550     if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0) {
551         vlc_pa_error(aout, "cannot write", sys->context);
552         block_Release(block);
553     }
554
555     vlc_pa_unlock();
556 }
557
558 /**
559  * Cork or uncork the playback stream
560  */
561 static void Pause(audio_output_t *aout, bool paused, mtime_t date)
562 {
563     aout_sys_t *sys = aout->sys;
564     pa_stream *s = sys->stream;
565
566     vlc_pa_lock();
567
568     if (paused) {
569         sys->paused = date;
570         stream_stop(s, aout);
571     } else {
572         assert (sys->paused != VLC_TS_INVALID);
573         date -= sys->paused;
574         msg_Dbg(aout, "resuming after %"PRId64" us", date);
575         sys->paused = VLC_TS_INVALID;
576         sys->pts += date;
577         stream_resync(aout, s);
578     }
579
580     vlc_pa_unlock();
581 }
582
583 /**
584  * Flush or drain the playback stream
585  */
586 static void Flush(audio_output_t *aout, bool wait)
587 {
588     aout_sys_t *sys = aout->sys;
589     pa_stream *s = sys->stream;
590     pa_operation *op;
591
592     vlc_pa_lock();
593
594     if (wait)
595         op = pa_stream_drain(s, NULL, NULL);
596         /* TODO: wait for drain completion*/
597     else
598         op = pa_stream_flush(s, NULL, NULL);
599     if (op != NULL)
600         pa_operation_unref(op);
601     vlc_pa_unlock();
602 }
603
604 static int VolumeSet(audio_output_t *aout, float vol, bool mute)
605 {
606     aout_sys_t *sys = aout->sys;
607     pa_operation *op;
608     uint32_t idx = pa_stream_get_index(sys->stream);
609
610     pa_cvolume cvolume = sys->cvolume;
611     pa_volume_t volume = sys->base_volume;
612
613     pa_cvolume_scale(&cvolume, PA_VOLUME_NORM); /* preserve balance */
614
615     /* VLC provides the software volume so convert directly to PulseAudio
616      * software volume, pa_volume_t. This is not a linear amplification factor
617      * so do not use PulseAudio linear amplification! */
618     vol *= PA_VOLUME_NORM;
619     if (unlikely(vol >= PA_VOLUME_MAX))
620         vol = PA_VOLUME_MAX;
621     volume = pa_sw_volume_multiply(volume, lround(vol));
622     pa_sw_cvolume_multiply_scalar(&cvolume, &cvolume, volume);
623
624     assert(pa_cvolume_valid(&cvolume));
625
626     vlc_pa_lock();
627     op = pa_context_set_sink_input_volume(sys->context, idx, &cvolume, NULL, NULL);
628     if (likely(op != NULL))
629         pa_operation_unref(op);
630     op = pa_context_set_sink_input_mute(sys->context, idx, mute, NULL, NULL);
631     if (likely(op != NULL))
632         pa_operation_unref(op);
633     vlc_pa_unlock();
634
635     return 0;
636 }
637
638 static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old,
639                       vlc_value_t val, void *userdata)
640 {
641     audio_output_t *aout = (audio_output_t *)obj;
642     aout_sys_t *sys = aout->sys;
643     pa_stream *s = userdata;
644     pa_operation *op;
645     uint32_t idx = pa_stream_get_index(s);
646     uint32_t sink_idx = val.i_int;
647
648     (void) varname; (void) old;
649
650     vlc_pa_lock();
651     op = pa_context_move_sink_input_by_index(sys->context, idx, sink_idx,
652                                              NULL, NULL);
653     if (likely(op != NULL)) {
654         pa_operation_unref(op);
655         msg_Dbg(aout, "moving to sink %"PRIu32, sink_idx);
656     } else
657         vlc_pa_error(obj, "cannot move sink", sys->context);
658     vlc_pa_unlock();
659
660     return (op != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
661 }
662
663
664 /**
665  * Create a PulseAudio playback stream, a.k.a. a sink input.
666  */
667 static int Open(vlc_object_t *obj)
668 {
669 #if !PA_CHECK_VERSION(0,9,22)
670     if (!vlc_xlib_init(obj))
671         return VLC_EGENERIC;
672 #endif
673
674     audio_output_t *aout = (audio_output_t *)obj;
675     pa_operation *op;
676
677     /* Sample format specification */
678     struct pa_sample_spec ss;
679     vlc_fourcc_t format = aout->format.i_format;
680 #if PA_CHECK_VERSION(1,0,0)
681     pa_encoding_t encoding = PA_ENCODING_INVALID;
682 #endif
683
684     switch(format)
685     {
686         case VLC_CODEC_F64B:
687             format = VLC_CODEC_F32B;
688         case VLC_CODEC_F32B:
689             ss.format = PA_SAMPLE_FLOAT32BE;
690             break;
691         case VLC_CODEC_F64L:
692             format = VLC_CODEC_F32L;
693         case VLC_CODEC_F32L:
694             ss.format = PA_SAMPLE_FLOAT32LE;
695             break;
696         case VLC_CODEC_FI32:
697             format = VLC_CODEC_FL32;
698             ss.format = PA_SAMPLE_FLOAT32NE;
699             break;
700         case VLC_CODEC_S32B:
701             ss.format = PA_SAMPLE_S32BE;
702             break;
703         case VLC_CODEC_S32L:
704             ss.format = PA_SAMPLE_S32LE;
705             break;
706         case VLC_CODEC_S24B:
707             ss.format = PA_SAMPLE_S24BE;
708             break;
709         case VLC_CODEC_S24L:
710             ss.format = PA_SAMPLE_S24LE;
711             break;
712         case VLC_CODEC_S16B:
713             ss.format = PA_SAMPLE_S16BE;
714             break;
715         case VLC_CODEC_S16L:
716             ss.format = PA_SAMPLE_S16LE;
717             break;
718         case VLC_CODEC_S8:
719             format = VLC_CODEC_U8;
720         case VLC_CODEC_U8:
721             ss.format = PA_SAMPLE_U8;
722             break;
723 #if PA_CHECK_VERSION(1,0,0)
724         case VLC_CODEC_A52:
725             format = VLC_CODEC_SPDIFL;
726             encoding = PA_ENCODING_AC3_IEC61937;
727             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
728             break;
729         /*case VLC_CODEC_EAC3:
730             format = VLC_CODEC_SPDIFL FIXME;
731             encoding = PA_ENCODING_EAC3_IEC61937;
732             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
733             break;
734         case VLC_CODEC_MPGA:
735             format = VLC_CODEC_SPDIFL FIXME;
736             encoding = PA_ENCODING_MPEG_IEC61937;
737             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
738             break;*/
739         case VLC_CODEC_DTS:
740             format = VLC_CODEC_SPDIFL;
741             encoding = PA_ENCODING_DTS_IEC61937;
742             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
743             break;
744 #endif
745         default:
746             if (HAVE_FPU)
747             {
748                 format = VLC_CODEC_FL32;
749                 ss.format = PA_SAMPLE_FLOAT32NE;
750             }
751             else
752             {
753                 format = VLC_CODEC_S16N;
754                 ss.format = PA_SAMPLE_S16NE;
755             }
756             break;
757     }
758
759     ss.rate = aout->format.i_rate;
760     ss.channels = aout_FormatNbChannels(&aout->format);
761     if (!pa_sample_spec_valid(&ss)) {
762         msg_Err(aout, "unsupported sample specification");
763         return VLC_EGENERIC;
764     }
765
766     /* Channel mapping (order defined in vlc_aout.h) */
767     struct pa_channel_map map;
768     map.channels = 0;
769
770     if (aout->format.i_physical_channels & AOUT_CHAN_LEFT)
771         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
772     if (aout->format.i_physical_channels & AOUT_CHAN_RIGHT)
773         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
774     if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLELEFT)
775         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
776     if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
777         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
778     if (aout->format.i_physical_channels & AOUT_CHAN_REARLEFT)
779         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
780     if (aout->format.i_physical_channels & AOUT_CHAN_REARRIGHT)
781         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
782     if (aout->format.i_physical_channels & AOUT_CHAN_REARCENTER)
783         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
784     if (aout->format.i_physical_channels & AOUT_CHAN_CENTER)
785     {
786         if (ss.channels == 1)
787             map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
788         else
789             map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
790     }
791     if (aout->format.i_physical_channels & AOUT_CHAN_LFE)
792         map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
793
794     for (unsigned i = 0; map.channels < ss.channels; i++) {
795         map.map[map.channels++] = PA_CHANNEL_POSITION_AUX0 + i;
796         msg_Warn(aout, "mapping channel %"PRIu8" to AUX%u", map.channels, i);
797     }
798
799     if (!pa_channel_map_valid(&map)) {
800         msg_Err(aout, "unsupported channel map");
801         return VLC_EGENERIC;
802     } else {
803         const char *name = pa_channel_map_to_name(&map);
804         msg_Dbg(aout, "using %s channel map", (name != NULL) ? name : "?");
805     }
806
807     /* Stream parameters */
808     const pa_stream_flags_t flags = PA_STREAM_START_CORKED
809                                   //| PA_STREAM_INTERPOLATE_TIMING
810                                   | PA_STREAM_AUTO_TIMING_UPDATE
811                                   | PA_STREAM_VARIABLE_RATE;
812
813     struct pa_buffer_attr attr;
814     attr.maxlength = -1;
815     /* PulseAudio assumes that tlength bytes are available in the buffer. Thus
816      * we need to be conservative and set the minimum value that the VLC
817      * audio decoder thread warrants. Otherwise, PulseAudio buffers will
818      * underrun on hardware with large buffers. VLC keeps at least
819      * AOUT_MIN_PREPARE and at most AOUT_MAX_PREPARE worth of audio buffers.
820      * TODO? tlength could be adaptively increased to reduce wakeups. */
821     attr.tlength = pa_usec_to_bytes(AOUT_MIN_PREPARE_TIME, &ss);
822     attr.prebuf = 0; /* trigger manually */
823     attr.minreq = -1;
824     attr.fragsize = 0; /* not used for output */
825
826     /* Allocate structures */
827     aout_sys_t *sys = malloc(sizeof(*sys));
828     if (unlikely(sys == NULL))
829         return VLC_ENOMEM;
830
831     pa_context *ctx = vlc_pa_connect (obj);
832     if (ctx == NULL)
833     {
834         free (sys);
835         return VLC_EGENERIC;
836     }
837
838     aout->sys = sys;
839     sys->stream = NULL;
840     sys->context = ctx;
841     sys->trigger = NULL;
842     sys->paused = VLC_TS_INVALID;
843     sys->pts = VLC_TS_INVALID;
844     sys->desync = 0;
845     sys->rate = ss.rate;
846
847     /* Context events */
848     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
849                                       | PA_SUBSCRIPTION_MASK_SINK_INPUT;
850
851     pa_context_set_subscribe_callback(ctx, context_cb, aout);
852     op = pa_context_subscribe(ctx, mask, NULL, NULL);
853     if (likely(op != NULL))
854        pa_operation_unref(op);
855
856     /* Channel volume */
857     sys->base_volume = PA_VOLUME_NORM;
858     pa_cvolume_set(&sys->cvolume, ss.channels, PA_VOLUME_NORM);
859
860 #if PA_CHECK_VERSION(1,0,0)
861     pa_format_info *formatv[2];
862     unsigned formatc = 0;
863
864     /* Favor digital pass-through if available*/
865     if (encoding != PA_ENCODING_INVALID) {
866         formatv[formatc] = pa_format_info_new();
867         formatv[formatc]->encoding = encoding;
868         pa_format_info_set_rate(formatv[formatc], ss.rate);
869         pa_format_info_set_channels(formatv[formatc], ss.channels);
870         formatc++;
871     }
872
873     /* Fallback to PCM */
874     formatv[formatc] = pa_format_info_new();
875     formatv[formatc]->encoding = PA_ENCODING_PCM;
876     pa_format_info_set_sample_format(formatv[formatc], ss.format);
877     pa_format_info_set_rate(formatv[formatc], ss.rate);
878     pa_format_info_set_channels(formatv[formatc], ss.channels);
879     formatc++;
880
881     /* Create a playback stream */
882     pa_stream *s;
883
884     vlc_pa_lock();
885     s = pa_stream_new_extended(ctx, "audio stream", formatv, formatc, NULL);
886
887     for (unsigned i = 0; i < formatc; i++)
888         pa_format_info_free(formatv[i]);
889 #else
890     vlc_pa_lock();
891     pa_stream *s = pa_stream_new(ctx, "audio stream", &ss, &map);
892 #endif
893     if (s == NULL) {
894         vlc_pa_error(obj, "stream creation failure", ctx);
895         goto fail;
896     }
897     sys->stream = s;
898     pa_stream_set_state_callback(s, stream_state_cb, NULL);
899     pa_stream_set_event_callback(s, stream_event_cb, aout);
900     pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
901     pa_stream_set_moved_callback(s, stream_moved_cb, aout);
902     pa_stream_set_overflow_callback(s, stream_overflow_cb, aout);
903     pa_stream_set_started_callback(s, stream_started_cb, aout);
904     pa_stream_set_suspended_callback(s, stream_suspended_cb, aout);
905     pa_stream_set_underflow_callback(s, stream_underflow_cb, aout);
906
907     if (pa_stream_connect_playback(s, NULL, &attr, flags, NULL, NULL) < 0
908      || stream_wait(s)) {
909         vlc_pa_error(obj, "stream connection failure", ctx);
910         goto fail;
911     }
912
913 #if PA_CHECK_VERSION(1,0,0)
914     if (encoding != PA_ENCODING_INVALID) {
915         const pa_format_info *info = pa_stream_get_format_info(s);
916
917         assert (info != NULL);
918         if (pa_format_info_is_pcm (info)) {
919             msg_Dbg(aout, "digital pass-through not available");
920             format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
921         } else {
922             msg_Dbg(aout, "digital pass-through enabled");
923             pa_stream_set_latency_update_callback(s, NULL, NULL);
924         }
925     }
926 #endif
927
928     const struct pa_buffer_attr *pba = pa_stream_get_buffer_attr(s);
929     msg_Dbg(aout, "using buffer metrics: maxlength=%u, tlength=%u, "
930             "prebuf=%u, minreq=%u",
931             pba->maxlength, pba->tlength, pba->prebuf, pba->minreq);
932
933     var_Create(aout, "audio-device", VLC_VAR_INTEGER|VLC_VAR_HASCHOICE);
934     var_Change(aout, "audio-device", VLC_VAR_SETTEXT,
935                &(vlc_value_t){ .psz_string = (char *)_("Audio device") },
936                NULL);
937     var_AddCallback (aout, "audio-device", StreamMove, s);
938     op = pa_context_get_sink_info_list(ctx, sink_list_cb, aout);
939     /* We may need to wait for completion... once LibVLC supports this */
940     if (op != NULL)
941         pa_operation_unref(op);
942     stream_moved_cb(s, aout);
943     vlc_pa_unlock();
944
945     aout->format.i_format = format;
946     aout->pf_play = Play;
947     aout->pf_pause = Pause;
948     aout->pf_flush = Flush;
949     aout_VolumeHardInit (aout, VolumeSet);
950     return VLC_SUCCESS;
951
952 fail:
953     vlc_pa_unlock();
954     Close(obj);
955     return VLC_EGENERIC;
956 }
957
958 /**
959  * Removes a PulseAudio playback stream
960  */
961 static void Close (vlc_object_t *obj)
962 {
963     audio_output_t *aout = (audio_output_t *)obj;
964     aout_sys_t *sys = aout->sys;
965     pa_context *ctx = sys->context;
966     pa_stream *s = sys->stream;
967
968     if (s != NULL) {
969         /* The callback takes mainloop lock, so it CANNOT be held here! */
970         var_DelCallback (aout, "audio-device", StreamMove, s);
971         var_Destroy (aout, "audio-device");
972
973         vlc_pa_lock ();
974         if (unlikely(sys->trigger != NULL))
975             vlc_pa_rttime_free(sys->trigger);
976         pa_stream_disconnect(s);
977
978         /* Clear all callbacks */
979         pa_stream_set_state_callback(s, NULL, NULL);
980         pa_stream_set_event_callback(s, NULL, NULL);
981         pa_stream_set_latency_update_callback(s, NULL, NULL);
982         pa_stream_set_moved_callback(s, NULL, NULL);
983         pa_stream_set_overflow_callback(s, NULL, NULL);
984         pa_stream_set_started_callback(s, NULL, NULL);
985         pa_stream_set_suspended_callback(s, NULL, NULL);
986         pa_stream_set_underflow_callback(s, NULL, NULL);
987
988         pa_stream_unref(s);
989         vlc_pa_unlock ();
990     }
991
992     vlc_pa_disconnect(obj, ctx);
993     free(sys);
994 }