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