]> git.sesse.net Git - vlc/blob - modules/audio_output/pulse.c
mux: ogg: fix pointer arithmetic (cid #1048982)
[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
37 static int  Open        ( vlc_object_t * );
38 static void Close       ( vlc_object_t * );
39
40 vlc_module_begin ()
41     set_shortname( "PulseAudio" )
42     set_description( N_("Pulseaudio audio output") )
43     set_capability( "audio output", 160 )
44     set_category( CAT_AUDIO )
45     set_subcategory( SUBCAT_AUDIO_AOUT )
46     add_shortcut( "pulseaudio", "pa" )
47     set_callbacks( Open, Close )
48 vlc_module_end ()
49
50 /* NOTE:
51  * Be careful what you do when the PulseAudio mainloop is held, which is to say
52  * within PulseAudio callbacks, or after pa_threaded_mainloop_lock().
53  * In particular, a VLC variable callback cannot be triggered nor deleted with
54  * the PulseAudio mainloop lock held, if the callback acquires the lock. */
55
56 struct sink
57 {
58     struct sink *next;
59     uint32_t index;
60     pa_volume_t base_volume;
61     char name[1];
62 };
63
64 struct aout_sys_t
65 {
66     pa_stream *stream; /**< PulseAudio playback stream object */
67     pa_context *context; /**< PulseAudio connection context */
68     pa_threaded_mainloop *mainloop; /**< PulseAudio thread */
69     pa_time_event *trigger; /**< Deferred stream trigger */
70     pa_volume_t base_volume; /**< 0dB reference volume */
71     pa_cvolume cvolume; /**< actual sink input volume */
72     mtime_t first_pts; /**< Play time of buffer start */
73
74     pa_volume_t volume_force; /**< Forced volume (stream must be NULL) */
75     pa_stream_flags_t flags_force; /**< Forced flags (stream must be NULL) */
76     char *sink_force; /**< Forced sink name (stream must be NULL) */
77
78     struct sink *sinks; /**< Locally-cached list of sinks */
79 };
80
81 static void VolumeReport(audio_output_t *aout)
82 {
83     aout_sys_t *sys = aout->sys;
84     pa_volume_t volume = pa_cvolume_max(&sys->cvolume);
85
86     volume = pa_sw_volume_divide(volume, sys->base_volume);
87     aout_VolumeReport(aout, (float)volume / PA_VOLUME_NORM);
88 }
89
90 /*** Sink ***/
91 static struct sink *sink_find(aout_sys_t *sys, uint32_t index)
92 {
93     for (struct sink *sink = sys->sinks; sink != NULL; sink = sink->next)
94         if (sink->index == index)
95             return sink;
96     return NULL;
97 }
98
99 static struct sink *sink_find_by_name(aout_sys_t *sys, const char *name)
100 {
101     for (struct sink *sink = sys->sinks; sink != NULL; sink = sink->next)
102         if (!strcmp(sink->name, name))
103             return sink;
104     return NULL;
105 }
106
107 static void sink_add_cb(pa_context *ctx, const pa_sink_info *i, int eol,
108                         void *userdata)
109 {
110     audio_output_t *aout = userdata;
111     aout_sys_t *sys = aout->sys;
112
113     if (eol)
114     {
115         pa_threaded_mainloop_signal(sys->mainloop, 0);
116         return;
117     }
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     /* FIXME: expose aout_Restart() directly */
341     if (!strcmp(name, PA_STREAM_EVENT_FORMAT_LOST)) {
342         msg_Dbg (aout, "format lost");
343         aout_RestartRequest (aout, AOUT_RESTART_OUTPUT);
344     } else
345         msg_Warn (aout, "unhandled stream event \"%s\"", name);
346     (void) s;
347     (void) pl;
348 }
349
350 static void stream_moved_cb(pa_stream *s, void *userdata)
351 {
352     audio_output_t *aout = userdata;
353     aout_sys_t *sys = aout->sys;
354     const char *name = pa_stream_get_device_name(s);
355     struct sink *sink = sink_find(sys, pa_stream_get_device_index(s));
356
357     msg_Dbg(aout, "connected to sink %s", name);
358     aout_DeviceReport(aout, name);
359
360     sys->base_volume = likely(sink != NULL) ? sink->base_volume
361                                             : PA_VOLUME_INVALID;
362     msg_Dbg(aout, "base volume: %"PRIu32, sys->base_volume);
363     if (pa_cvolume_valid(&sys->cvolume))
364         VolumeReport(aout);
365 }
366
367 static void stream_overflow_cb(pa_stream *s, void *userdata)
368 {
369     audio_output_t *aout = userdata;
370     aout_sys_t *sys = aout->sys;
371     pa_operation *op;
372
373     msg_Err(aout, "overflow, flushing");
374     op = pa_stream_flush(s, NULL, NULL);
375     if (unlikely(op == NULL))
376         return;
377     pa_operation_unref(op);
378     sys->first_pts = VLC_TS_INVALID;
379 }
380
381 static void stream_started_cb(pa_stream *s, void *userdata)
382 {
383     audio_output_t *aout = userdata;
384
385     msg_Dbg(aout, "started");
386     (void) s;
387 }
388
389 static void stream_suspended_cb(pa_stream *s, void *userdata)
390 {
391     audio_output_t *aout = userdata;
392
393     msg_Dbg(aout, "suspended");
394     (void) s;
395 }
396
397 static void stream_underflow_cb(pa_stream *s, void *userdata)
398 {
399     audio_output_t *aout = userdata;
400
401     msg_Dbg(aout, "underflow");
402     (void) s;
403 }
404
405 static int stream_wait(pa_stream *stream, pa_threaded_mainloop *mainloop)
406 {
407     pa_stream_state_t state;
408
409     while ((state = pa_stream_get_state(stream)) != PA_STREAM_READY) {
410         if (state == PA_STREAM_FAILED || state == PA_STREAM_TERMINATED)
411             return -1;
412         pa_threaded_mainloop_wait(mainloop);
413     }
414     return 0;
415 }
416
417
418 /*** Sink input ***/
419 static void sink_input_info_cb(pa_context *ctx, const pa_sink_input_info *i,
420                                int eol, void *userdata)
421 {
422     audio_output_t *aout = userdata;
423     aout_sys_t *sys = aout->sys;
424
425     if (eol)
426         return;
427     (void) ctx;
428
429     sys->cvolume = i->volume; /* cache volume for balance preservation */
430     if (PA_VOLUME_IS_VALID(sys->base_volume))
431         VolumeReport(aout);
432     aout_MuteReport(aout, i->mute);
433 }
434
435 static void sink_input_event(pa_context *ctx,
436                              pa_subscription_event_type_t type,
437                              uint32_t idx, audio_output_t *aout)
438 {
439     pa_operation *op;
440
441     /* Gee... PA will not provide the infos directly in the event. */
442     switch (type)
443     {
444         case PA_SUBSCRIPTION_EVENT_REMOVE:
445             msg_Err(aout, "sink input killed!");
446             break;
447
448         default:
449             op = pa_context_get_sink_input_info(ctx, idx, sink_input_info_cb,
450                                                 aout);
451             if (likely(op != NULL))
452                 pa_operation_unref(op);
453             break;
454     }
455 }
456
457
458 /*** Context ***/
459 static void context_cb(pa_context *ctx, pa_subscription_event_type_t type,
460                        uint32_t idx, void *userdata)
461 {
462     audio_output_t *aout = userdata;
463     aout_sys_t *sys = aout->sys;
464     unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
465
466     type &= PA_SUBSCRIPTION_EVENT_TYPE_MASK;
467     switch (facility)
468     {
469         case PA_SUBSCRIPTION_EVENT_SINK:
470             sink_event(ctx, type, idx, userdata);
471             break;
472
473         case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
474             /* only interested in our sink input */
475             if (sys->stream != NULL && idx == pa_stream_get_index(sys->stream))
476                 sink_input_event(ctx, type, idx, userdata);
477             break;
478
479         default: /* unsubscribed facility?! */
480             assert(0);
481     }
482 }
483
484
485 /*** VLC audio output callbacks ***/
486
487 static int TimeGet(audio_output_t *aout, mtime_t *restrict delay)
488 {
489     aout_sys_t *sys = aout->sys;
490     pa_stream *s = sys->stream;
491
492     if (pa_stream_is_corked(s) > 0)
493         return -1; /* latency is irrelevant if corked */
494
495     mtime_t delta = vlc_pa_get_latency(aout, sys->context, s);
496     if (delta == VLC_TS_INVALID)
497         return -1;
498
499     *delay = delta;
500     return 0;
501 }
502
503 /* Memory free callback. The block_t address is in front of the data. */
504 static void data_free(void *data)
505 {
506     block_t **pp = data, *block;
507
508     memcpy(&block, pp - 1, sizeof (block));
509     block_Release(block);
510 }
511
512 static void *data_convert(block_t **pp)
513 {
514     block_t *block = *pp;
515     /* In most cases, there is enough head room, and this is really cheap: */
516     block = block_Realloc(block, sizeof (block), block->i_buffer);
517     *pp = block;
518     if (unlikely(block == NULL))
519         return NULL;
520
521     memcpy(block->p_buffer, &block, sizeof (block));
522     block->p_buffer += sizeof (block);
523     block->i_buffer -= sizeof (block);
524     return block->p_buffer;
525 }
526
527 /**
528  * Queue one audio frame to the playback stream
529  */
530 static void Play(audio_output_t *aout, block_t *block)
531 {
532     aout_sys_t *sys = aout->sys;
533     pa_stream *s = sys->stream;
534
535     const void *ptr = data_convert(&block);
536     if (unlikely(ptr == NULL))
537         return;
538
539     size_t len = block->i_buffer;
540
541     /* Note: The core already holds the output FIFO lock at this point.
542      * Therefore we must not under any circumstances (try to) acquire the
543      * output FIFO lock while the PulseAudio threaded main loop lock is held
544      * (including from PulseAudio stream callbacks). Otherwise lock inversion
545      * will take place, and sooner or later a deadlock. */
546     pa_threaded_mainloop_lock(sys->mainloop);
547
548     if (sys->first_pts == VLC_TS_INVALID)
549         sys->first_pts = block->i_pts;
550
551     if (pa_stream_is_corked(s) > 0)
552         stream_start(s, aout);
553
554 #if 0 /* Fault injector to test underrun recovery */
555     static volatile unsigned u = 0;
556     if ((++u % 1000) == 0) {
557         msg_Err(aout, "fault injection");
558         pa_operation_unref(pa_stream_flush(s, NULL, NULL));
559     }
560 #endif
561
562     if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0) {
563         vlc_pa_error(aout, "cannot write", sys->context);
564         block_Release(block);
565     }
566
567     pa_threaded_mainloop_unlock(sys->mainloop);
568 }
569
570 /**
571  * Cork or uncork the playback stream
572  */
573 static void Pause(audio_output_t *aout, bool paused, mtime_t date)
574 {
575     aout_sys_t *sys = aout->sys;
576     pa_stream *s = sys->stream;
577
578     pa_threaded_mainloop_lock(sys->mainloop);
579
580     if (paused) {
581         pa_stream_set_latency_update_callback(s, NULL, NULL);
582         stream_stop(s, aout);
583     } else {
584         pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
585         if (likely(sys->first_pts != VLC_TS_INVALID))
586             stream_start_now(s, aout);
587     }
588
589     pa_threaded_mainloop_unlock(sys->mainloop);
590     (void) date;
591 }
592
593 /**
594  * Flush or drain the playback stream
595  */
596 static void Flush(audio_output_t *aout, bool wait)
597 {
598     aout_sys_t *sys = aout->sys;
599     pa_stream *s = sys->stream;
600     pa_operation *op;
601
602     pa_threaded_mainloop_lock(sys->mainloop);
603
604     if (wait)
605         op = pa_stream_drain(s, NULL, NULL);
606         /* TODO: wait for drain completion*/
607     else
608         op = pa_stream_flush(s, NULL, NULL);
609     if (op != NULL)
610         pa_operation_unref(op);
611     pa_threaded_mainloop_unlock(sys->mainloop);
612 }
613
614 static int VolumeSet(audio_output_t *aout, float vol)
615 {
616     aout_sys_t *sys = aout->sys;
617     pa_stream *s = sys->stream;
618     pa_operation *op;
619     int ret = -1;
620     pa_volume_t base_volume;
621
622     /* VLC provides the software volume so convert directly to PulseAudio
623      * software volume, pa_volume_t. This is not a linear amplification factor
624      * so do not use PulseAudio linear amplification! */
625     vol *= PA_VOLUME_NORM;
626     if (unlikely(vol >= PA_VOLUME_MAX))
627         vol = PA_VOLUME_MAX;
628
629     pa_threaded_mainloop_lock(sys->mainloop);
630
631     base_volume = sys->base_volume;
632     if (!PA_VOLUME_IS_VALID(base_volume))
633     {   /* Base volume is unknown, typically because sink is unknown.
634          * Try to guess the base volume. */
635         const struct sink *sink = sys->sinks;
636         if (unlikely(sink == NULL))
637         {
638             msg_Err(aout, "cannot change volume without sink");
639             goto out;
640         }
641
642         base_volume = sink->base_volume;
643         while ((sink = sink->next) != NULL)
644             if (sink->base_volume != base_volume)
645             {
646                 msg_Err(aout, "cannot change volume without base");
647                 goto out;
648             }
649     }
650
651     pa_volume_t volume = pa_sw_volume_multiply(lroundf(vol), base_volume);
652
653     if (s == NULL)
654     {
655         sys->volume_force = volume;
656         aout_VolumeReport(aout, vol / (float)PA_VOLUME_NORM);
657         ret = 0;
658         goto out;
659     }
660
661     if (!pa_cvolume_valid(&sys->cvolume))
662     {
663         const pa_sample_spec *ss = pa_stream_get_sample_spec(s);
664
665         msg_Warn(aout, "balance clobbered by volume change");
666         pa_cvolume_set(&sys->cvolume, ss->channels, PA_VOLUME_NORM);
667     }
668
669     /* Preserve the balance (VLC does not support it). */
670     pa_cvolume cvolume = sys->cvolume;
671     pa_cvolume_scale(&cvolume, PA_VOLUME_NORM);
672     pa_sw_cvolume_multiply_scalar(&cvolume, &cvolume, volume);
673     assert(pa_cvolume_valid(&cvolume));
674
675     op = pa_context_set_sink_input_volume(sys->context, pa_stream_get_index(s),
676                                           &cvolume, NULL, NULL);
677     if (likely(op != NULL))
678     {
679         pa_operation_unref(op);
680         ret = 0;
681     }
682 out:
683     pa_threaded_mainloop_unlock(sys->mainloop);
684     return ret;
685 }
686
687 static int MuteSet(audio_output_t *aout, bool mute)
688 {
689     aout_sys_t *sys = aout->sys;
690
691     if (sys->stream == NULL)
692     {
693         sys->flags_force &= ~(PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED);
694         sys->flags_force |=
695             mute ? PA_STREAM_START_MUTED : PA_STREAM_START_UNMUTED;
696         aout_MuteReport(aout, mute);
697         return 0;
698     }
699
700     pa_operation *op;
701     uint32_t idx = pa_stream_get_index(sys->stream);
702     pa_threaded_mainloop_lock(sys->mainloop);
703     op = pa_context_set_sink_input_mute(sys->context, idx, mute, NULL, NULL);
704     if (likely(op != NULL))
705         pa_operation_unref(op);
706     pa_threaded_mainloop_unlock(sys->mainloop);
707
708     return 0;
709 }
710
711 static int StreamMove(audio_output_t *aout, const char *name)
712 {
713     aout_sys_t *sys = aout->sys;
714
715     if (sys->stream == NULL)
716     {
717         struct sink *sink = sink_find_by_name(sys, name);
718
719         sys->base_volume = likely(sink != NULL) ? sink->base_volume
720                                                 : PA_VOLUME_INVALID;
721         msg_Dbg(aout, "will connect to sink %s", name);
722         free(sys->sink_force);
723         sys->sink_force = strdup(name);
724         return 0;
725     }
726
727     pa_operation *op;
728     uint32_t idx = pa_stream_get_index(sys->stream);
729
730     pa_threaded_mainloop_lock(sys->mainloop);
731     op = pa_context_move_sink_input_by_name(sys->context, idx, name,
732                                             NULL, NULL);
733     if (likely(op != NULL)) {
734         pa_operation_unref(op);
735         msg_Dbg(aout, "moving to sink %s", name);
736     } else
737         vlc_pa_error(aout, "cannot move sink input", sys->context);
738     pa_threaded_mainloop_unlock(sys->mainloop);
739
740     return (op != NULL) ? 0 : -1;
741 }
742
743 static void Stop(audio_output_t *);
744
745 /**
746  * Create a PulseAudio playback stream, a.k.a. a sink input.
747  */
748 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
749 {
750     aout_sys_t *sys = aout->sys;
751
752     /* Sample format specification */
753     struct pa_sample_spec ss;
754     pa_encoding_t encoding = PA_ENCODING_INVALID;
755
756     switch (fmt->i_format)
757     {
758         case VLC_CODEC_FL64:
759             fmt->i_format = VLC_CODEC_FL32;
760         case VLC_CODEC_FL32:
761             ss.format = PA_SAMPLE_FLOAT32NE;
762             break;
763         case VLC_CODEC_S32N:
764             ss.format = PA_SAMPLE_S32NE;
765             break;
766         case VLC_CODEC_S16N:
767             ss.format = PA_SAMPLE_S16NE;
768             break;
769         case VLC_CODEC_U8:
770             ss.format = PA_SAMPLE_U8;
771             break;
772         case VLC_CODEC_A52:
773             fmt->i_format = VLC_CODEC_SPDIFL;
774             encoding = PA_ENCODING_AC3_IEC61937;
775             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
776             break;
777         /*case VLC_CODEC_EAC3:
778             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
779             encoding = PA_ENCODING_EAC3_IEC61937;
780             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
781             break;
782         case VLC_CODEC_MPGA:
783             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
784             encoding = PA_ENCODING_MPEG_IEC61937;
785             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
786             break;*/
787         case VLC_CODEC_DTS:
788             fmt->i_format = VLC_CODEC_SPDIFL;
789             encoding = PA_ENCODING_DTS_IEC61937;
790             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
791             break;
792         default:
793             if (HAVE_FPU)
794             {
795                 fmt->i_format = VLC_CODEC_FL32;
796                 ss.format = PA_SAMPLE_FLOAT32NE;
797             }
798             else
799             {
800                 fmt->i_format = VLC_CODEC_S16N;
801                 ss.format = PA_SAMPLE_S16NE;
802             }
803             break;
804     }
805
806     ss.rate = fmt->i_rate;
807     ss.channels = aout_FormatNbChannels(fmt);
808     if (!pa_sample_spec_valid(&ss)) {
809         msg_Err(aout, "unsupported sample specification");
810         return VLC_EGENERIC;
811     }
812
813     /* Channel mapping (order defined in vlc_aout.h) */
814     struct pa_channel_map map;
815     map.channels = 0;
816
817     if (fmt->i_physical_channels & AOUT_CHAN_LEFT)
818         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
819     if (fmt->i_physical_channels & AOUT_CHAN_RIGHT)
820         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
821     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLELEFT)
822         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
823     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
824         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
825     if (fmt->i_physical_channels & AOUT_CHAN_REARLEFT)
826         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
827     if (fmt->i_physical_channels & AOUT_CHAN_REARRIGHT)
828         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
829     if (fmt->i_physical_channels & AOUT_CHAN_REARCENTER)
830         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
831     if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
832     {
833         if (ss.channels == 1)
834             map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
835         else
836             map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
837     }
838     if (fmt->i_physical_channels & AOUT_CHAN_LFE)
839         map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
840
841     for (unsigned i = 0; map.channels < ss.channels; i++) {
842         map.map[map.channels++] = PA_CHANNEL_POSITION_AUX0 + i;
843         msg_Warn(aout, "mapping channel %"PRIu8" to AUX%u", map.channels, i);
844     }
845
846     if (!pa_channel_map_valid(&map)) {
847         msg_Err(aout, "unsupported channel map");
848         return VLC_EGENERIC;
849     } else {
850         const char *name = pa_channel_map_to_name(&map);
851         msg_Dbg(aout, "using %s channel map", (name != NULL) ? name : "?");
852     }
853
854     /* Stream parameters */
855     pa_stream_flags_t flags = sys->flags_force
856                             | PA_STREAM_START_CORKED
857                             | PA_STREAM_INTERPOLATE_TIMING
858                             | PA_STREAM_NOT_MONOTONIC
859                             | PA_STREAM_AUTO_TIMING_UPDATE
860                             | PA_STREAM_FIX_RATE;
861
862     struct pa_buffer_attr attr;
863     attr.maxlength = -1;
864     /* PulseAudio goes berserk if the target length (tlength) is not
865      * significantly longer than 2 periods (minreq), or when the period length
866      * is unspecified and the target length is short. */
867     attr.tlength = pa_usec_to_bytes(3 * AOUT_MIN_PREPARE_TIME, &ss);
868     attr.prebuf = 0; /* trigger manually */
869     attr.minreq = pa_usec_to_bytes(AOUT_MIN_PREPARE_TIME, &ss);
870     attr.fragsize = 0; /* not used for output */
871
872     pa_cvolume *cvolume = NULL, cvolumebuf;
873     if (PA_VOLUME_IS_VALID(sys->volume_force))
874     {
875         cvolume = &cvolumebuf;
876         pa_cvolume_set(cvolume, ss.channels, sys->volume_force);
877     }
878
879     sys->trigger = NULL;
880     pa_cvolume_init(&sys->cvolume);
881     sys->first_pts = VLC_TS_INVALID;
882
883     pa_format_info *formatv[2];
884     unsigned formatc = 0;
885
886     /* Favor digital pass-through if available*/
887     if (encoding != PA_ENCODING_INVALID) {
888         formatv[formatc] = pa_format_info_new();
889         formatv[formatc]->encoding = encoding;
890         pa_format_info_set_rate(formatv[formatc], ss.rate);
891         pa_format_info_set_channels(formatv[formatc], ss.channels);
892         pa_format_info_set_channel_map(formatv[formatc], &map);
893         formatc++;
894
895         /* FIX flags are only permitted for PCM, and there is no way to pass
896          * different flags for different formats... */
897         flags &= ~(PA_STREAM_FIX_FORMAT
898                  | PA_STREAM_FIX_RATE
899                  | PA_STREAM_FIX_CHANNELS);
900     }
901
902     /* Fallback to PCM */
903     formatv[formatc] = pa_format_info_new();
904     formatv[formatc]->encoding = PA_ENCODING_PCM;
905     pa_format_info_set_sample_format(formatv[formatc], ss.format);
906     pa_format_info_set_rate(formatv[formatc], ss.rate);
907     pa_format_info_set_channels(formatv[formatc], ss.channels);
908     pa_format_info_set_channel_map(formatv[formatc], &map);
909     formatc++;
910
911     /* Create a playback stream */
912     pa_proplist *props = pa_proplist_new();
913     if (likely(props != NULL))
914         /* TODO: set other stream properties */
915         pa_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
916
917     pa_threaded_mainloop_lock(sys->mainloop);
918     pa_stream *s = pa_stream_new_extended(sys->context, "audio stream",
919                                           formatv, formatc, props);
920
921     if (likely(props != NULL))
922         pa_proplist_free(props);
923     for (unsigned i = 0; i < formatc; i++)
924         pa_format_info_free(formatv[i]);
925
926     if (s == NULL) {
927         pa_threaded_mainloop_unlock(sys->mainloop);
928         vlc_pa_error(aout, "stream creation failure", sys->context);
929         return VLC_EGENERIC;
930     }
931     assert(sys->stream == NULL);
932     sys->stream = s;
933     pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop);
934     pa_stream_set_buffer_attr_callback(s, stream_buffer_attr_cb, aout);
935     pa_stream_set_event_callback(s, stream_event_cb, aout);
936     pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
937     pa_stream_set_moved_callback(s, stream_moved_cb, aout);
938     pa_stream_set_overflow_callback(s, stream_overflow_cb, aout);
939     pa_stream_set_started_callback(s, stream_started_cb, aout);
940     pa_stream_set_suspended_callback(s, stream_suspended_cb, aout);
941     pa_stream_set_underflow_callback(s, stream_underflow_cb, aout);
942
943     if (pa_stream_connect_playback(s, sys->sink_force, &attr, flags,
944                                    cvolume, NULL) < 0
945      || stream_wait(s, sys->mainloop)) {
946         vlc_pa_error(aout, "stream connection failure", sys->context);
947         goto fail;
948     }
949     sys->volume_force = PA_VOLUME_INVALID;
950     sys->flags_force = PA_STREAM_NOFLAGS;
951     free(sys->sink_force);
952     sys->sink_force = NULL;
953
954     const struct pa_sample_spec *spec = pa_stream_get_sample_spec(s);
955     if (encoding != PA_ENCODING_INVALID) {
956         const pa_format_info *info = pa_stream_get_format_info(s);
957
958         assert (info != NULL);
959         if (pa_format_info_is_pcm (info)) {
960             msg_Dbg(aout, "digital pass-through not available");
961             fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
962         } else {
963             msg_Dbg(aout, "digital pass-through enabled");
964             spec = NULL;
965         }
966     }
967     if (spec != NULL)
968         fmt->i_rate = spec->rate;
969
970     stream_buffer_attr_cb(s, aout);
971     stream_moved_cb(s, aout);
972     pa_threaded_mainloop_unlock(sys->mainloop);
973
974     return VLC_SUCCESS;
975
976 fail:
977     pa_threaded_mainloop_unlock(sys->mainloop);
978     Stop(aout);
979     return VLC_EGENERIC;
980 }
981
982 /**
983  * Removes a PulseAudio playback stream
984  */
985 static void Stop(audio_output_t *aout)
986 {
987     aout_sys_t *sys = aout->sys;
988     pa_stream *s = sys->stream;
989
990     pa_threaded_mainloop_lock(sys->mainloop);
991     if (unlikely(sys->trigger != NULL))
992         vlc_pa_rttime_free(sys->mainloop, sys->trigger);
993     pa_stream_disconnect(s);
994
995     /* Clear all callbacks */
996     pa_stream_set_state_callback(s, NULL, NULL);
997     pa_stream_set_buffer_attr_callback(s, NULL, NULL);
998     pa_stream_set_event_callback(s, NULL, NULL);
999     pa_stream_set_latency_update_callback(s, NULL, NULL);
1000     pa_stream_set_moved_callback(s, NULL, NULL);
1001     pa_stream_set_overflow_callback(s, NULL, NULL);
1002     pa_stream_set_started_callback(s, NULL, NULL);
1003     pa_stream_set_suspended_callback(s, NULL, NULL);
1004     pa_stream_set_underflow_callback(s, NULL, NULL);
1005
1006     pa_stream_unref(s);
1007     sys->stream = NULL;
1008     sys->base_volume = PA_VOLUME_INVALID;
1009     pa_threaded_mainloop_unlock(sys->mainloop);
1010 }
1011
1012 static int Open(vlc_object_t *obj)
1013 {
1014     audio_output_t *aout = (audio_output_t *)obj;
1015     aout_sys_t *sys = malloc(sizeof (*sys));
1016     pa_operation *op;
1017
1018     if (unlikely(sys == NULL))
1019         return VLC_ENOMEM;
1020
1021     /* Allocate structures */
1022     pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
1023     if (ctx == NULL)
1024     {
1025         free(sys);
1026         return VLC_EGENERIC;
1027     }
1028     sys->stream = NULL;
1029     sys->context = ctx;
1030     sys->base_volume = PA_VOLUME_INVALID;
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 (likely(op != NULL))
1051     {
1052         while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
1053             pa_threaded_mainloop_wait(sys->mainloop);
1054         pa_operation_unref(op);
1055     }
1056
1057     /* Context events */
1058     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
1059                                       | PA_SUBSCRIPTION_MASK_SINK_INPUT;
1060     pa_context_set_subscribe_callback(sys->context, context_cb, aout);
1061     op = pa_context_subscribe(sys->context, mask, NULL, NULL);
1062     if (likely(op != NULL))
1063        pa_operation_unref(op);
1064     pa_threaded_mainloop_unlock(sys->mainloop);
1065
1066     return VLC_SUCCESS;
1067 }
1068
1069 static void Close(vlc_object_t *obj)
1070 {
1071     audio_output_t *aout = (audio_output_t *)obj;
1072     aout_sys_t *sys = aout->sys;
1073     pa_context *ctx = sys->context;
1074
1075     pa_threaded_mainloop_lock(sys->mainloop);
1076     pa_context_set_subscribe_callback(sys->context, NULL, NULL);
1077     pa_threaded_mainloop_unlock(sys->mainloop);
1078     vlc_pa_disconnect(obj, ctx, sys->mainloop);
1079
1080     for (struct sink *sink = sys->sinks, *next; sink != NULL; sink = next)
1081     {
1082         next = sink->next;
1083         free(sink);
1084     }
1085     free(sys->sink_force);
1086     free(sys);
1087 }