]> git.sesse.net Git - vlc/blob - modules/audio_output/pulse.c
pulse: fix NDEBUG-only warning
[vlc] / modules / audio_output / pulse.c
1 /*****************************************************************************
2  * pulse.c : Pulseaudio output plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2008 VLC authors and VideoLAN
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 it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * 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 "vlcpulse.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 /* NOTE:
54  * Be careful what you do when the PulseAudio mainloop is held, which is to say
55  * within PulseAudio callbacks, or after pa_threaded_mainloop_lock().
56  * In particular, a VLC variable callback cannot be triggered nor deleted with
57  * the PulseAudio mainloop lock held, if the callback acquires the lock. */
58
59 struct sink
60 {
61     struct sink *next;
62     uint32_t index;
63     char name[1];
64 };
65
66 struct aout_sys_t
67 {
68     pa_stream *stream; /**< PulseAudio playback stream object */
69     pa_context *context; /**< PulseAudio connection context */
70     pa_threaded_mainloop *mainloop; /**< PulseAudio thread */
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 first_pts; /**< Play time of buffer start */
75     mtime_t paused; /**< Time when (last) paused */
76
77     pa_stream_flags_t flags_force; /**< Forced flags (stream must be NULL) */
78     char *sink_force; /**< Forced sink name (stream must be NULL) */
79
80     struct sink *sinks; /**< Locally-cached list of sinks */
81 };
82
83
84 /*** Sink ***/
85 static void sink_add_cb(pa_context *ctx, const pa_sink_info *i, int eol,
86                         void *userdata)
87 {
88     audio_output_t *aout = userdata;
89     aout_sys_t *sys = aout->sys;
90
91     if (eol)
92         return;
93     (void) ctx;
94
95     msg_Dbg(aout, "adding sink %"PRIu32": %s (%s)", i->index, i->name,
96             i->description);
97     aout_HotplugReport(aout, i->name, i->description);
98
99     size_t namelen = strlen(i->name);
100     struct sink *sink = malloc(sizeof (*sink) + namelen);
101     if (unlikely(sink == NULL))
102         return;
103
104     sink->next = sys->sinks;
105     sink->index = i->index;
106     memcpy(sink->name, i->name, namelen + 1);
107     sys->sinks = sink;
108 }
109
110 static void sink_mod_cb(pa_context *ctx, const pa_sink_info *i, int eol,
111                         void *userdata)
112 {
113     audio_output_t *aout = userdata;
114
115     if (eol)
116         return;
117     (void) ctx;
118
119     msg_Dbg(aout, "changing sink %"PRIu32": %s (%s)", i->index, i->name,
120             i->description);
121     aout_HotplugReport(aout, i->name, i->description);
122 }
123
124 static void sink_del(uint32_t index, audio_output_t *aout)
125 {
126     aout_sys_t *sys = aout->sys;
127     struct sink **pp = &sys->sinks, *sink;
128
129     msg_Dbg(aout, "removing sink %"PRIu32, index);
130
131     while ((sink = *pp) != NULL)
132         if (sink->index == index)
133         {
134             *pp = sink->next;
135             aout_HotplugReport(aout, sink->name, NULL);
136             free(sink);
137         }
138         else
139             pp = &sink->next;
140 }
141
142 static void sink_event(pa_context *ctx, unsigned type, uint32_t idx,
143                        audio_output_t *aout)
144 {
145     pa_operation *op = NULL;
146
147     switch (type)
148     {
149         case PA_SUBSCRIPTION_EVENT_NEW:
150             op = pa_context_get_sink_info_by_index(ctx, idx, sink_add_cb,
151                                                    aout);
152             break;
153         case PA_SUBSCRIPTION_EVENT_CHANGE:
154             op = pa_context_get_sink_info_by_index(ctx, idx, sink_mod_cb,
155                                                    aout);
156             break;
157         case PA_SUBSCRIPTION_EVENT_REMOVE:
158             sink_del(idx, aout);
159             break;
160     }
161     if (op != NULL)
162         pa_operation_unref(op);
163 }
164
165 static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
166                          void *userdata)
167 {
168     audio_output_t *aout = userdata;
169     aout_sys_t *sys = aout->sys;
170
171     if (eol)
172         return;
173     (void) c;
174
175     /* PulseAudio flat volume NORM / 100% / 0dB corresponds to no software
176      * amplification and maximum hardware amplification.
177      * VLC maps DEFAULT / 100% to no gain at all (software/hardware).
178      * Thus we need to use the sink base_volume as a multiplier,
179      * if and only if flat volume is active for our current sink. */
180     if (i->flags & PA_SINK_FLAT_VOLUME)
181         sys->base_volume = i->base_volume;
182     else
183         sys->base_volume = PA_VOLUME_NORM;
184     msg_Dbg(aout, "base volume: %"PRIu32, sys->base_volume);
185 }
186
187
188 /*** Latency management and lip synchronization ***/
189 static void stream_start_now(pa_stream *s, audio_output_t *aout)
190 {
191     pa_operation *op;
192
193     assert (aout->sys->trigger == NULL);
194
195     op = pa_stream_cork(s, 0, NULL, NULL);
196     if (op != NULL)
197         pa_operation_unref(op);
198     op = pa_stream_trigger(s, NULL, NULL);
199     if (likely(op != NULL))
200         pa_operation_unref(op);
201 }
202
203 static void stream_stop(pa_stream *s, audio_output_t *aout)
204 {
205     aout_sys_t *sys = aout->sys;
206     pa_operation *op;
207
208     if (sys->trigger != NULL) {
209         vlc_pa_rttime_free(sys->mainloop, sys->trigger);
210         sys->trigger = NULL;
211     }
212
213     op = pa_stream_cork(s, 1, NULL, NULL);
214     if (op != NULL)
215         pa_operation_unref(op);
216 }
217
218 static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e,
219                               const struct timeval *tv, void *userdata)
220 {
221     audio_output_t *aout = userdata;
222     aout_sys_t *sys = aout->sys;
223
224     assert (sys->trigger == e);
225
226     msg_Dbg(aout, "starting deferred");
227     vlc_pa_rttime_free(sys->mainloop, sys->trigger);
228     sys->trigger = NULL;
229     stream_start_now(sys->stream, aout);
230     (void) api; (void) e; (void) tv;
231 }
232
233 /**
234  * Starts or resumes the playback stream.
235  * Tries start playing back audio samples at the most accurate time
236  * in order to minimize desync and resampling during early playback.
237  * @note PulseAudio lock required.
238  */
239 static void stream_start(pa_stream *s, audio_output_t *aout)
240 {
241     aout_sys_t *sys = aout->sys;
242     mtime_t delta;
243
244     assert (sys->first_pts != VLC_TS_INVALID);
245
246     if (sys->trigger != NULL) {
247         vlc_pa_rttime_free(sys->mainloop, sys->trigger);
248         sys->trigger = NULL;
249     }
250
251     delta = vlc_pa_get_latency(aout, sys->context, s);
252     if (unlikely(delta == VLC_TS_INVALID)) {
253         msg_Dbg(aout, "cannot synchronize start");
254         delta = 0; /* screwed */
255     }
256
257     delta = (sys->first_pts - mdate()) - delta;
258     if (delta > 0) {
259         msg_Dbg(aout, "deferring start (%"PRId64" us)", delta);
260         delta += pa_rtclock_now();
261         sys->trigger = pa_context_rttime_new(sys->context, delta,
262                                              stream_trigger_cb, aout);
263     } else {
264         msg_Warn(aout, "starting late (%"PRId64" us)", delta);
265         stream_start_now(s, aout);
266     }
267 }
268
269 static void stream_latency_cb(pa_stream *s, void *userdata)
270 {
271     audio_output_t *aout = userdata;
272     aout_sys_t *sys = aout->sys;
273
274     if (sys->paused != VLC_TS_INVALID)
275         return; /* nothing to do while paused */
276     if (sys->first_pts == VLC_TS_INVALID)
277         return; /* nothing to do if buffers are (still) empty */
278     if (pa_stream_is_corked(s) > 0)
279         stream_start(s, aout);
280 }
281
282
283 /*** Stream helpers ***/
284 static void stream_state_cb(pa_stream *s, void *userdata)
285 {
286     pa_threaded_mainloop *mainloop = userdata;
287
288     switch (pa_stream_get_state(s)) {
289         case PA_STREAM_READY:
290         case PA_STREAM_FAILED:
291         case PA_STREAM_TERMINATED:
292             pa_threaded_mainloop_signal(mainloop, 0);
293         default:
294             break;
295     }
296 }
297
298 static void stream_buffer_attr_cb(pa_stream *s, void *userdata)
299 {
300     audio_output_t *aout = userdata;
301     const pa_buffer_attr *pba = pa_stream_get_buffer_attr(s);
302
303     msg_Dbg(aout, "changed buffer metrics: maxlength=%u, tlength=%u, "
304             "prebuf=%u, minreq=%u",
305             pba->maxlength, pba->tlength, pba->prebuf, pba->minreq);
306 }
307
308 static void stream_event_cb(pa_stream *s, const char *name, pa_proplist *pl,
309                             void *userdata)
310 {
311     audio_output_t *aout = userdata;
312
313     if (!strcmp(name, PA_STREAM_EVENT_REQUEST_CORK))
314         aout_PolicyReport(aout, true);
315     else
316     if (!strcmp(name, PA_STREAM_EVENT_REQUEST_UNCORK))
317         aout_PolicyReport(aout, false);
318     else
319 #if PA_CHECK_VERSION(1,0,0)
320     /* FIXME: expose aout_Restart() directly */
321     if (!strcmp(name, PA_STREAM_EVENT_FORMAT_LOST)) {
322         msg_Dbg (aout, "format lost");
323         aout_RestartRequest (aout, AOUT_RESTART_OUTPUT);
324     } else
325 #endif
326         msg_Warn (aout, "unhandled stream event \"%s\"", name);
327     (void) s;
328     (void) pl;
329 }
330
331 static void stream_moved_cb(pa_stream *s, void *userdata)
332 {
333     audio_output_t *aout = userdata;
334     aout_sys_t *sys = aout->sys;
335     const char *name = pa_stream_get_device_name(s);
336     pa_operation *op;
337
338     msg_Dbg(aout, "connected to sink %s", name);
339     aout_DeviceReport(aout, name);
340
341     op = pa_context_get_sink_info_by_name(sys->context, name, sink_info_cb,
342                                           aout);
343     if (likely(op != NULL))
344         pa_operation_unref(op);
345 }
346
347 static void stream_overflow_cb(pa_stream *s, void *userdata)
348 {
349     audio_output_t *aout = userdata;
350     aout_sys_t *sys = aout->sys;
351     pa_operation *op;
352
353     msg_Err(aout, "overflow, flushing");
354     op = pa_stream_flush(s, NULL, NULL);
355     if (unlikely(op == NULL))
356         return;
357     pa_operation_unref(op);
358     sys->first_pts = VLC_TS_INVALID;
359 }
360
361 static void stream_started_cb(pa_stream *s, void *userdata)
362 {
363     audio_output_t *aout = userdata;
364
365     msg_Dbg(aout, "started");
366     (void) s;
367 }
368
369 static void stream_suspended_cb(pa_stream *s, void *userdata)
370 {
371     audio_output_t *aout = userdata;
372
373     msg_Dbg(aout, "suspended");
374     (void) s;
375 }
376
377 static void stream_underflow_cb(pa_stream *s, void *userdata)
378 {
379     audio_output_t *aout = userdata;
380
381     msg_Dbg(aout, "underflow");
382     (void) s;
383 }
384
385 static int stream_wait(pa_stream *stream, pa_threaded_mainloop *mainloop)
386 {
387     pa_stream_state_t state;
388
389     while ((state = pa_stream_get_state(stream)) != PA_STREAM_READY) {
390         if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
391             return -1;
392         pa_threaded_mainloop_wait(mainloop);
393     }
394     return 0;
395 }
396
397
398 /*** Sink input ***/
399 static void sink_input_info_cb(pa_context *ctx, const pa_sink_input_info *i,
400                                int eol, void *userdata)
401 {
402     audio_output_t *aout = userdata;
403     aout_sys_t *sys = aout->sys;
404
405     if (eol)
406         return;
407     (void) ctx;
408
409     sys->cvolume = i->volume; /* cache volume for balance preservation */
410
411     pa_volume_t volume = pa_cvolume_max(&i->volume);
412     volume = pa_sw_volume_divide(volume, sys->base_volume);
413     aout_VolumeReport(aout, (float)volume / PA_VOLUME_NORM);
414     aout_MuteReport(aout, i->mute);
415 }
416
417 static void sink_input_event(pa_context *ctx,
418                              pa_subscription_event_type_t type,
419                              uint32_t idx, audio_output_t *aout)
420 {
421     pa_operation *op;
422
423     /* Gee... PA will not provide the infos directly in the event. */
424     switch (type)
425     {
426         case PA_SUBSCRIPTION_EVENT_REMOVE:
427             msg_Err(aout, "sink input killed!");
428             break;
429
430         default:
431             op = pa_context_get_sink_input_info(ctx, idx, sink_input_info_cb,
432                                                 aout);
433             if (likely(op != NULL))
434                 pa_operation_unref(op);
435             break;
436     }
437 }
438
439
440 /*** Context ***/
441 static void context_cb(pa_context *ctx, pa_subscription_event_type_t type,
442                        uint32_t idx, void *userdata)
443 {
444     audio_output_t *aout = userdata;
445     aout_sys_t *sys = aout->sys;
446     unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
447
448     type &= PA_SUBSCRIPTION_EVENT_TYPE_MASK;
449     switch (facility)
450     {
451         case PA_SUBSCRIPTION_EVENT_SINK:
452             sink_event(ctx, type, idx, userdata);
453             break;
454
455         case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
456             /* only interested in our sink input */
457             if (sys->stream != NULL && idx == pa_stream_get_index(sys->stream))
458                 sink_input_event(ctx, type, idx, userdata);
459             break;
460
461         default: /* unsubscribed facility?! */
462             assert(0);
463     }
464 }
465
466
467 /*** VLC audio output callbacks ***/
468
469 static int TimeGet(audio_output_t *aout, mtime_t *restrict delay)
470 {
471     aout_sys_t *sys = aout->sys;
472     pa_stream *s = sys->stream;
473
474     if (pa_stream_is_corked(s) > 0)
475         return -1; /* latency is irrelevant if corked */
476
477     mtime_t delta = vlc_pa_get_latency(aout, sys->context, s);
478     if (delta == VLC_TS_INVALID)
479         return -1;
480
481     *delay = delta;
482     return 0;
483 }
484
485 /* Memory free callback. The block_t address is in front of the data. */
486 static void data_free(void *data)
487 {
488     block_t **pp = data, *block;
489
490     memcpy(&block, pp - 1, sizeof (block));
491     block_Release(block);
492 }
493
494 static void *data_convert(block_t **pp)
495 {
496     block_t *block = *pp;
497     /* In most cases, there is enough head room, and this is really cheap: */
498     block = block_Realloc(block, sizeof (block), block->i_buffer);
499     *pp = block;
500     if (unlikely(block == NULL))
501         return NULL;
502
503     memcpy(block->p_buffer, &block, sizeof (block));
504     block->p_buffer += sizeof (block);
505     block->i_buffer -= sizeof (block);
506     return block->p_buffer;
507 }
508
509 /**
510  * Queue one audio frame to the playback stream
511  */
512 static void Play(audio_output_t *aout, block_t *block)
513 {
514     aout_sys_t *sys = aout->sys;
515     pa_stream *s = sys->stream;
516
517     assert (sys->paused == VLC_TS_INVALID);
518
519     const void *ptr = data_convert(&block);
520     if (unlikely(ptr == NULL))
521         return;
522
523     size_t len = block->i_buffer;
524
525     /* Note: The core already holds the output FIFO lock at this point.
526      * Therefore we must not under any circumstances (try to) acquire the
527      * output FIFO lock while the PulseAudio threaded main loop lock is held
528      * (including from PulseAudio stream callbacks). Otherwise lock inversion
529      * will take place, and sooner or later a deadlock. */
530     pa_threaded_mainloop_lock(sys->mainloop);
531
532     if (sys->first_pts == VLC_TS_INVALID)
533         sys->first_pts = block->i_pts;
534
535     if (pa_stream_is_corked(s) > 0)
536         stream_start(s, aout);
537
538 #if 0 /* Fault injector to test underrun recovery */
539     static volatile unsigned u = 0;
540     if ((++u % 1000) == 0) {
541         msg_Err(aout, "fault injection");
542         pa_operation_unref(pa_stream_flush(s, NULL, NULL));
543     }
544 #endif
545
546     if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0) {
547         vlc_pa_error(aout, "cannot write", sys->context);
548         block_Release(block);
549     }
550
551     pa_threaded_mainloop_unlock(sys->mainloop);
552 }
553
554 /**
555  * Cork or uncork the playback stream
556  */
557 static void Pause(audio_output_t *aout, bool paused, mtime_t date)
558 {
559     aout_sys_t *sys = aout->sys;
560     pa_stream *s = sys->stream;
561
562     pa_threaded_mainloop_lock(sys->mainloop);
563
564     if (paused) {
565         sys->paused = date;
566         stream_stop(s, aout);
567     } else {
568         assert (sys->paused != VLC_TS_INVALID);
569         date -= sys->paused;
570         msg_Dbg(aout, "resuming after %"PRId64" us", date);
571         sys->paused = VLC_TS_INVALID;
572
573         if (sys->first_pts != VLC_TS_INVALID) {
574             sys->first_pts += date;
575             stream_start(s, aout);
576         }
577     }
578
579     pa_threaded_mainloop_unlock(sys->mainloop);
580 }
581
582 /**
583  * Flush or drain the playback stream
584  */
585 static void Flush(audio_output_t *aout, bool wait)
586 {
587     aout_sys_t *sys = aout->sys;
588     pa_stream *s = sys->stream;
589     pa_operation *op;
590
591     pa_threaded_mainloop_lock(sys->mainloop);
592
593     if (wait)
594         op = pa_stream_drain(s, NULL, NULL);
595         /* TODO: wait for drain completion*/
596     else
597         op = pa_stream_flush(s, NULL, NULL);
598     if (op != NULL)
599         pa_operation_unref(op);
600     pa_threaded_mainloop_unlock(sys->mainloop);
601 }
602
603 static int VolumeSet(audio_output_t *aout, float vol)
604 {
605     aout_sys_t *sys = aout->sys;
606     if (sys->stream == NULL)
607     {
608         msg_Err (aout, "cannot change volume while not playing");
609         return -1;
610     }
611
612     /* VLC provides the software volume so convert directly to PulseAudio
613      * software volume, pa_volume_t. This is not a linear amplification factor
614      * so do not use PulseAudio linear amplification! */
615     vol *= PA_VOLUME_NORM;
616     if (unlikely(vol >= PA_VOLUME_MAX))
617         vol = PA_VOLUME_MAX;
618     pa_volume_t volume = pa_sw_volume_multiply(lround(vol), sys->base_volume);
619
620     /* Preserve the balance (VLC does not support it). */
621     pa_cvolume cvolume = sys->cvolume;
622     pa_cvolume_scale(&cvolume, PA_VOLUME_NORM);
623     pa_sw_cvolume_multiply_scalar(&cvolume, &cvolume, volume);
624     assert(pa_cvolume_valid(&cvolume));
625
626     pa_operation *op;
627     uint32_t idx = pa_stream_get_index(sys->stream);
628     pa_threaded_mainloop_lock(sys->mainloop);
629     op = pa_context_set_sink_input_volume(sys->context, idx, &cvolume,
630                                           NULL, NULL);
631     if (likely(op != NULL))
632         pa_operation_unref(op);
633     pa_threaded_mainloop_unlock(sys->mainloop);
634
635     return 0;
636 }
637
638 static int MuteSet(audio_output_t *aout, bool mute)
639 {
640     aout_sys_t *sys = aout->sys;
641
642     if (sys->stream == NULL)
643     {
644         sys->flags_force &= ~(PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED);
645         sys->flags_force |=
646             mute ? PA_STREAM_START_MUTED : PA_STREAM_START_UNMUTED;
647         aout_MuteReport(aout, mute);
648         return 0;
649     }
650
651     pa_operation *op;
652     uint32_t idx = pa_stream_get_index(sys->stream);
653     pa_threaded_mainloop_lock(sys->mainloop);
654     op = pa_context_set_sink_input_mute(sys->context, idx, mute, NULL, NULL);
655     if (likely(op != NULL))
656         pa_operation_unref(op);
657     pa_threaded_mainloop_unlock(sys->mainloop);
658
659     return 0;
660 }
661
662 static int StreamMove(audio_output_t *aout, const char *name)
663 {
664     aout_sys_t *sys = aout->sys;
665
666     if (sys->stream == NULL)
667     {
668         msg_Dbg(aout, "will connect to sink %s", name);
669         free(sys->sink_force);
670         sys->sink_force = strdup(name);
671         return 0;
672     }
673
674     pa_operation *op;
675     uint32_t idx = pa_stream_get_index(sys->stream);
676
677     pa_threaded_mainloop_lock(sys->mainloop);
678     op = pa_context_move_sink_input_by_name(sys->context, idx, name,
679                                             NULL, NULL);
680     if (likely(op != NULL)) {
681         pa_operation_unref(op);
682         msg_Dbg(aout, "moving to sink %s", name);
683     } else
684         vlc_pa_error(aout, "cannot move sink input", sys->context);
685     pa_threaded_mainloop_unlock(sys->mainloop);
686
687     return (op != NULL) ? 0 : -1;
688 }
689
690 static void Stop(audio_output_t *);
691
692 /**
693  * Create a PulseAudio playback stream, a.k.a. a sink input.
694  */
695 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
696 {
697     aout_sys_t *sys = aout->sys;
698
699     /* Sample format specification */
700     struct pa_sample_spec ss;
701 #if PA_CHECK_VERSION(1,0,0)
702     pa_encoding_t encoding = PA_ENCODING_INVALID;
703 #endif
704
705     switch (fmt->i_format)
706     {
707         case VLC_CODEC_FL64:
708             fmt->i_format = VLC_CODEC_FL32;
709         case VLC_CODEC_FL32:
710             ss.format = PA_SAMPLE_FLOAT32NE;
711             break;
712         case VLC_CODEC_S32N:
713             ss.format = PA_SAMPLE_S32NE;
714             break;
715         case VLC_CODEC_S16N:
716             ss.format = PA_SAMPLE_S16NE;
717             break;
718         case VLC_CODEC_U8:
719             ss.format = PA_SAMPLE_U8;
720             break;
721 #if PA_CHECK_VERSION(1,0,0)
722         case VLC_CODEC_A52:
723             fmt->i_format = VLC_CODEC_SPDIFL;
724             encoding = PA_ENCODING_AC3_IEC61937;
725             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
726             break;
727         /*case VLC_CODEC_EAC3:
728             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
729             encoding = PA_ENCODING_EAC3_IEC61937;
730             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
731             break;
732         case VLC_CODEC_MPGA:
733             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
734             encoding = PA_ENCODING_MPEG_IEC61937;
735             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
736             break;*/
737         case VLC_CODEC_DTS:
738             fmt->i_format = VLC_CODEC_SPDIFL;
739             encoding = PA_ENCODING_DTS_IEC61937;
740             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
741             break;
742 #endif
743         default:
744             if (HAVE_FPU)
745             {
746                 fmt->i_format = VLC_CODEC_FL32;
747                 ss.format = PA_SAMPLE_FLOAT32NE;
748             }
749             else
750             {
751                 fmt->i_format = VLC_CODEC_S16N;
752                 ss.format = PA_SAMPLE_S16NE;
753             }
754             break;
755     }
756
757     ss.rate = fmt->i_rate;
758     ss.channels = aout_FormatNbChannels(fmt);
759     if (!pa_sample_spec_valid(&ss)) {
760         msg_Err(aout, "unsupported sample specification");
761         return VLC_EGENERIC;
762     }
763
764     /* Channel mapping (order defined in vlc_aout.h) */
765     struct pa_channel_map map;
766     map.channels = 0;
767
768     if (fmt->i_physical_channels & AOUT_CHAN_LEFT)
769         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
770     if (fmt->i_physical_channels & AOUT_CHAN_RIGHT)
771         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
772     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLELEFT)
773         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
774     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
775         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
776     if (fmt->i_physical_channels & AOUT_CHAN_REARLEFT)
777         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
778     if (fmt->i_physical_channels & AOUT_CHAN_REARRIGHT)
779         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
780     if (fmt->i_physical_channels & AOUT_CHAN_REARCENTER)
781         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
782     if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
783     {
784         if (ss.channels == 1)
785             map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
786         else
787             map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
788     }
789     if (fmt->i_physical_channels & AOUT_CHAN_LFE)
790         map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
791
792     for (unsigned i = 0; map.channels < ss.channels; i++) {
793         map.map[map.channels++] = PA_CHANNEL_POSITION_AUX0 + i;
794         msg_Warn(aout, "mapping channel %"PRIu8" to AUX%u", map.channels, i);
795     }
796
797     if (!pa_channel_map_valid(&map)) {
798         msg_Err(aout, "unsupported channel map");
799         return VLC_EGENERIC;
800     } else {
801         const char *name = pa_channel_map_to_name(&map);
802         msg_Dbg(aout, "using %s channel map", (name != NULL) ? name : "?");
803     }
804
805     /* Stream parameters */
806     const pa_stream_flags_t flags = sys->flags_force
807                                   | PA_STREAM_START_CORKED
808                                   | PA_STREAM_INTERPOLATE_TIMING
809                                   | PA_STREAM_NOT_MONOTONIC
810                                   | PA_STREAM_AUTO_TIMING_UPDATE
811                                   | PA_STREAM_FIX_RATE;
812
813     struct pa_buffer_attr attr;
814     attr.maxlength = -1;
815     /* PulseAudio goes berserk if the target length (tlength) is not
816      * significantly longer than 2 periods (minreq), or when the period length
817      * is unspecified and the target length is short. */
818     attr.tlength = pa_usec_to_bytes(3 * AOUT_MIN_PREPARE_TIME, &ss);
819     attr.prebuf = 0; /* trigger manually */
820     attr.minreq = pa_usec_to_bytes(AOUT_MIN_PREPARE_TIME, &ss);
821     attr.fragsize = 0; /* not used for output */
822
823     sys->stream = NULL;
824     sys->trigger = NULL;
825     sys->first_pts = VLC_TS_INVALID;
826     sys->paused = VLC_TS_INVALID;
827
828     /* Channel volume */
829     sys->base_volume = PA_VOLUME_NORM;
830     pa_cvolume_set(&sys->cvolume, ss.channels, PA_VOLUME_NORM);
831
832 #if PA_CHECK_VERSION(1,0,0)
833     pa_format_info *formatv[2];
834     unsigned formatc = 0;
835
836     /* Favor digital pass-through if available*/
837     if (encoding != PA_ENCODING_INVALID) {
838         formatv[formatc] = pa_format_info_new();
839         formatv[formatc]->encoding = encoding;
840         pa_format_info_set_rate(formatv[formatc], ss.rate);
841         pa_format_info_set_channels(formatv[formatc], ss.channels);
842         pa_format_info_set_channel_map(formatv[formatc], &map);
843         formatc++;
844     }
845
846     /* Fallback to PCM */
847     formatv[formatc] = pa_format_info_new();
848     formatv[formatc]->encoding = PA_ENCODING_PCM;
849     pa_format_info_set_sample_format(formatv[formatc], ss.format);
850     pa_format_info_set_rate(formatv[formatc], ss.rate);
851     pa_format_info_set_channels(formatv[formatc], ss.channels);
852     pa_format_info_set_channel_map(formatv[formatc], &map);
853     formatc++;
854
855     /* Create a playback stream */
856     pa_stream *s;
857     pa_proplist *props = pa_proplist_new();
858     if (likely(props != NULL))
859         /* TODO: set other stream properties */
860         pa_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
861
862     pa_threaded_mainloop_lock(sys->mainloop);
863     s = pa_stream_new_extended(sys->context, "audio stream", formatv, formatc,
864                                props);
865     if (likely(props != NULL))
866         pa_proplist_free(props);
867
868     for (unsigned i = 0; i < formatc; i++)
869         pa_format_info_free(formatv[i]);
870 #else
871     pa_threaded_mainloop_lock(sys->mainloop);
872     pa_stream *s = pa_stream_new(sys->context, "audio stream", &ss, &map);
873 #endif
874     if (s == NULL) {
875         pa_threaded_mainloop_unlock(sys->mainloop);
876         vlc_pa_error(aout, "stream creation failure", sys->context);
877         return VLC_EGENERIC;
878     }
879     sys->stream = s;
880     pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop);
881     pa_stream_set_buffer_attr_callback(s, stream_buffer_attr_cb, aout);
882     pa_stream_set_event_callback(s, stream_event_cb, aout);
883     pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
884     pa_stream_set_moved_callback(s, stream_moved_cb, aout);
885     pa_stream_set_overflow_callback(s, stream_overflow_cb, aout);
886     pa_stream_set_started_callback(s, stream_started_cb, aout);
887     pa_stream_set_suspended_callback(s, stream_suspended_cb, aout);
888     pa_stream_set_underflow_callback(s, stream_underflow_cb, aout);
889
890     if (pa_stream_connect_playback(s, sys->sink_force, &attr, flags, NULL,
891                                    NULL) < 0
892      || stream_wait(s, sys->mainloop)) {
893         vlc_pa_error(aout, "stream connection failure", sys->context);
894         goto fail;
895     }
896     sys->flags_force = PA_STREAM_NOFLAGS;
897     free(sys->sink_force);
898     sys->sink_force = NULL;
899
900     const struct pa_sample_spec *spec = pa_stream_get_sample_spec(s);
901 #if PA_CHECK_VERSION(1,0,0)
902     if (encoding != PA_ENCODING_INVALID) {
903         const pa_format_info *info = pa_stream_get_format_info(s);
904
905         assert (info != NULL);
906         if (pa_format_info_is_pcm (info)) {
907             msg_Dbg(aout, "digital pass-through not available");
908             fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
909         } else {
910             msg_Dbg(aout, "digital pass-through enabled");
911             spec = NULL;
912         }
913     }
914 #endif
915     if (spec != NULL)
916         fmt->i_rate = spec->rate;
917
918     stream_buffer_attr_cb(s, aout);
919     stream_moved_cb(s, aout);
920     pa_threaded_mainloop_unlock(sys->mainloop);
921
922     return VLC_SUCCESS;
923
924 fail:
925     pa_threaded_mainloop_unlock(sys->mainloop);
926     Stop(aout);
927     return VLC_EGENERIC;
928 }
929
930 /**
931  * Removes a PulseAudio playback stream
932  */
933 static void Stop(audio_output_t *aout)
934 {
935     aout_sys_t *sys = aout->sys;
936     pa_stream *s = sys->stream;
937
938     pa_threaded_mainloop_lock(sys->mainloop);
939     if (unlikely(sys->trigger != NULL))
940         vlc_pa_rttime_free(sys->mainloop, sys->trigger);
941     pa_stream_disconnect(s);
942
943     /* Clear all callbacks */
944     pa_stream_set_state_callback(s, NULL, NULL);
945     pa_stream_set_buffer_attr_callback(s, NULL, NULL);
946     pa_stream_set_event_callback(s, NULL, NULL);
947     pa_stream_set_latency_update_callback(s, NULL, NULL);
948     pa_stream_set_moved_callback(s, NULL, NULL);
949     pa_stream_set_overflow_callback(s, NULL, NULL);
950     pa_stream_set_started_callback(s, NULL, NULL);
951     pa_stream_set_suspended_callback(s, NULL, NULL);
952     pa_stream_set_underflow_callback(s, NULL, NULL);
953
954     pa_stream_unref(s);
955     sys->stream = NULL;
956     pa_threaded_mainloop_unlock(sys->mainloop);
957 }
958
959 static int Open(vlc_object_t *obj)
960 {
961     audio_output_t *aout = (audio_output_t *)obj;
962     aout_sys_t *sys = malloc(sizeof (*sys));
963     pa_operation *op;
964
965 #if !PA_CHECK_VERSION(0,9,22)
966     if (!vlc_xlib_init(obj))
967         return VLC_EGENERIC;
968 #endif
969     if (unlikely(sys == NULL))
970         return VLC_ENOMEM;
971
972     /* Allocate structures */
973     pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
974     if (ctx == NULL)
975     {
976         free(sys);
977         return VLC_EGENERIC;
978     }
979     sys->stream = NULL;
980     sys->context = ctx;
981     sys->flags_force = PA_STREAM_NOFLAGS;
982     sys->sink_force = NULL;
983     sys->sinks = NULL;
984
985     aout->sys = sys;
986     aout->start = Start;
987     aout->stop = Stop;
988     aout->time_get = TimeGet;
989     aout->play = Play;
990     aout->pause = Pause;
991     aout->flush = Flush;
992     aout->volume_set = VolumeSet;
993     aout->mute_set = MuteSet;
994     aout->device_select = StreamMove;
995
996     pa_threaded_mainloop_lock(sys->mainloop);
997     /* Sinks (output devices) list */
998     op = pa_context_get_sink_info_list(sys->context, sink_add_cb, aout);
999     if (op != NULL)
1000         pa_operation_unref(op);
1001
1002     /* Context events */
1003     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
1004                                       | PA_SUBSCRIPTION_MASK_SINK_INPUT;
1005     pa_context_set_subscribe_callback(sys->context, context_cb, aout);
1006     op = pa_context_subscribe(sys->context, mask, NULL, NULL);
1007     if (likely(op != NULL))
1008        pa_operation_unref(op);
1009     pa_threaded_mainloop_unlock(sys->mainloop);
1010
1011     return VLC_SUCCESS;
1012 }
1013
1014 static void Close(vlc_object_t *obj)
1015 {
1016     audio_output_t *aout = (audio_output_t *)obj;
1017     aout_sys_t *sys = aout->sys;
1018     pa_context *ctx = sys->context;
1019
1020     pa_threaded_mainloop_lock(sys->mainloop);
1021     pa_context_set_subscribe_callback(sys->context, NULL, NULL);
1022     pa_threaded_mainloop_unlock(sys->mainloop);
1023     vlc_pa_disconnect(obj, ctx, sys->mainloop);
1024
1025     for (struct sink *sink = sys->sinks, *next; sink != NULL; sink = next)
1026     {
1027         next = sink->next;
1028         free(sink);
1029     }
1030     free(sys->sink_force);
1031     free(sys);
1032 }