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