]> git.sesse.net Git - vlc/blob - modules/audio_output/pulse.c
audioqueue: clean-up
[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         return 0;
652     }
653
654     pa_operation *op;
655     uint32_t idx = pa_stream_get_index(sys->stream);
656     pa_threaded_mainloop_lock(sys->mainloop);
657     op = pa_context_set_sink_input_mute(sys->context, idx, mute, NULL, NULL);
658     if (likely(op != NULL))
659         pa_operation_unref(op);
660     pa_threaded_mainloop_unlock(sys->mainloop);
661
662     return 0;
663 }
664
665 static int SinksList(audio_output_t *aout, char ***namesp, char ***descsp)
666 {
667     aout_sys_t *sys = aout->sys;
668     char **names, **descs;
669     unsigned n = 0;
670
671     pa_threaded_mainloop_lock(sys->mainloop);
672     for (struct sink *sink = sys->sinks; sink != NULL; sink = sink->next)
673         n++;
674
675     *namesp = names = xmalloc(sizeof(*names) * n);
676     *descsp = descs = xmalloc(sizeof(*descs) * n);
677
678     for (struct sink *sink = sys->sinks; sink != NULL; sink = sink->next)
679     {
680         *(names++) = strdup(sink->name);
681         *(descs++) = strdup(sink->description);
682     }
683     pa_threaded_mainloop_unlock(sys->mainloop);
684     return n;
685 }
686
687 static int StreamMove(audio_output_t *aout, const char *name)
688 {
689     aout_sys_t *sys = aout->sys;
690
691     if (sys->stream == NULL)
692     {
693         msg_Dbg(aout, "will connect to sink %s", name);
694         free(sys->sink_force);
695         sys->sink_force = strdup(name);
696         return 0;
697     }
698
699     pa_operation *op;
700     uint32_t idx = pa_stream_get_index(sys->stream);
701
702     pa_threaded_mainloop_lock(sys->mainloop);
703     op = pa_context_move_sink_input_by_name(sys->context, idx, name,
704                                             NULL, NULL);
705     if (likely(op != NULL)) {
706         pa_operation_unref(op);
707         msg_Dbg(aout, "moving to sink %s", name);
708     } else
709         vlc_pa_error(aout, "cannot move sink input", sys->context);
710     pa_threaded_mainloop_unlock(sys->mainloop);
711
712     return (op != NULL) ? 0 : -1;
713 }
714
715 static void Stop(audio_output_t *);
716
717 /**
718  * Create a PulseAudio playback stream, a.k.a. a sink input.
719  */
720 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
721 {
722     aout_sys_t *sys = aout->sys;
723
724     /* Sample format specification */
725     struct pa_sample_spec ss;
726 #if PA_CHECK_VERSION(1,0,0)
727     pa_encoding_t encoding = PA_ENCODING_INVALID;
728 #endif
729
730     switch (fmt->i_format)
731     {
732         case VLC_CODEC_FL64:
733             fmt->i_format = VLC_CODEC_FL32;
734         case VLC_CODEC_FL32:
735             ss.format = PA_SAMPLE_FLOAT32NE;
736             break;
737         case VLC_CODEC_S32N:
738             ss.format = PA_SAMPLE_S32NE;
739             break;
740         case VLC_CODEC_S16N:
741             ss.format = PA_SAMPLE_S16NE;
742             break;
743         case VLC_CODEC_U8:
744             ss.format = PA_SAMPLE_U8;
745             break;
746 #if PA_CHECK_VERSION(1,0,0)
747         case VLC_CODEC_A52:
748             fmt->i_format = VLC_CODEC_SPDIFL;
749             encoding = PA_ENCODING_AC3_IEC61937;
750             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
751             break;
752         /*case VLC_CODEC_EAC3:
753             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
754             encoding = PA_ENCODING_EAC3_IEC61937;
755             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
756             break;
757         case VLC_CODEC_MPGA:
758             fmt->i_format = VLC_CODEC_SPDIFL FIXME;
759             encoding = PA_ENCODING_MPEG_IEC61937;
760             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
761             break;*/
762         case VLC_CODEC_DTS:
763             fmt->i_format = VLC_CODEC_SPDIFL;
764             encoding = PA_ENCODING_DTS_IEC61937;
765             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
766             break;
767 #endif
768         default:
769             if (HAVE_FPU)
770             {
771                 fmt->i_format = VLC_CODEC_FL32;
772                 ss.format = PA_SAMPLE_FLOAT32NE;
773             }
774             else
775             {
776                 fmt->i_format = VLC_CODEC_S16N;
777                 ss.format = PA_SAMPLE_S16NE;
778             }
779             break;
780     }
781
782     ss.rate = fmt->i_rate;
783     ss.channels = aout_FormatNbChannels(fmt);
784     if (!pa_sample_spec_valid(&ss)) {
785         msg_Err(aout, "unsupported sample specification");
786         return VLC_EGENERIC;
787     }
788
789     /* Channel mapping (order defined in vlc_aout.h) */
790     struct pa_channel_map map;
791     map.channels = 0;
792
793     if (fmt->i_physical_channels & AOUT_CHAN_LEFT)
794         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
795     if (fmt->i_physical_channels & AOUT_CHAN_RIGHT)
796         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
797     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLELEFT)
798         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
799     if (fmt->i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
800         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
801     if (fmt->i_physical_channels & AOUT_CHAN_REARLEFT)
802         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
803     if (fmt->i_physical_channels & AOUT_CHAN_REARRIGHT)
804         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
805     if (fmt->i_physical_channels & AOUT_CHAN_REARCENTER)
806         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
807     if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
808     {
809         if (ss.channels == 1)
810             map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
811         else
812             map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
813     }
814     if (fmt->i_physical_channels & AOUT_CHAN_LFE)
815         map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
816
817     for (unsigned i = 0; map.channels < ss.channels; i++) {
818         map.map[map.channels++] = PA_CHANNEL_POSITION_AUX0 + i;
819         msg_Warn(aout, "mapping channel %"PRIu8" to AUX%u", map.channels, i);
820     }
821
822     if (!pa_channel_map_valid(&map)) {
823         msg_Err(aout, "unsupported channel map");
824         return VLC_EGENERIC;
825     } else {
826         const char *name = pa_channel_map_to_name(&map);
827         msg_Dbg(aout, "using %s channel map", (name != NULL) ? name : "?");
828     }
829
830     /* Stream parameters */
831     const pa_stream_flags_t flags = sys->flags_force
832                                   | PA_STREAM_START_CORKED
833                                   | PA_STREAM_INTERPOLATE_TIMING
834                                   | PA_STREAM_NOT_MONOTONIC
835                                   | PA_STREAM_AUTO_TIMING_UPDATE
836                                   | PA_STREAM_FIX_RATE;
837
838     struct pa_buffer_attr attr;
839     attr.maxlength = -1;
840     /* PulseAudio goes berserk if the target length (tlength) is not
841      * significantly longer than 2 periods (minreq), or when the period length
842      * is unspecified and the target length is short. */
843     attr.tlength = pa_usec_to_bytes(3 * AOUT_MIN_PREPARE_TIME, &ss);
844     attr.prebuf = 0; /* trigger manually */
845     attr.minreq = pa_usec_to_bytes(AOUT_MIN_PREPARE_TIME, &ss);
846     attr.fragsize = 0; /* not used for output */
847
848     sys->stream = NULL;
849     sys->trigger = NULL;
850     sys->first_pts = VLC_TS_INVALID;
851     sys->paused = VLC_TS_INVALID;
852
853     /* Channel volume */
854     sys->base_volume = PA_VOLUME_NORM;
855     pa_cvolume_set(&sys->cvolume, ss.channels, PA_VOLUME_NORM);
856
857 #if PA_CHECK_VERSION(1,0,0)
858     pa_format_info *formatv[2];
859     unsigned formatc = 0;
860
861     /* Favor digital pass-through if available*/
862     if (encoding != PA_ENCODING_INVALID) {
863         formatv[formatc] = pa_format_info_new();
864         formatv[formatc]->encoding = encoding;
865         pa_format_info_set_rate(formatv[formatc], ss.rate);
866         pa_format_info_set_channels(formatv[formatc], ss.channels);
867         pa_format_info_set_channel_map(formatv[formatc], &map);
868         formatc++;
869     }
870
871     /* Fallback to PCM */
872     formatv[formatc] = pa_format_info_new();
873     formatv[formatc]->encoding = PA_ENCODING_PCM;
874     pa_format_info_set_sample_format(formatv[formatc], ss.format);
875     pa_format_info_set_rate(formatv[formatc], ss.rate);
876     pa_format_info_set_channels(formatv[formatc], ss.channels);
877     pa_format_info_set_channel_map(formatv[formatc], &map);
878     formatc++;
879
880     /* Create a playback stream */
881     pa_stream *s;
882     pa_proplist *props = pa_proplist_new();
883     if (likely(props != NULL))
884         /* TODO: set other stream properties */
885         pa_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
886
887     pa_threaded_mainloop_lock(sys->mainloop);
888     s = pa_stream_new_extended(sys->context, "audio stream", formatv, formatc,
889                                props);
890     if (likely(props != NULL))
891         pa_proplist_free(props);
892
893     for (unsigned i = 0; i < formatc; i++)
894         pa_format_info_free(formatv[i]);
895 #else
896     pa_threaded_mainloop_lock(sys->mainloop);
897     pa_stream *s = pa_stream_new(sys->context, "audio stream", &ss, &map);
898 #endif
899     if (s == NULL) {
900         pa_threaded_mainloop_unlock(sys->mainloop);
901         vlc_pa_error(aout, "stream creation failure", sys->context);
902         return VLC_EGENERIC;
903     }
904     sys->stream = s;
905     pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop);
906     pa_stream_set_buffer_attr_callback(s, stream_buffer_attr_cb, aout);
907     pa_stream_set_event_callback(s, stream_event_cb, aout);
908     pa_stream_set_latency_update_callback(s, stream_latency_cb, aout);
909     pa_stream_set_moved_callback(s, stream_moved_cb, aout);
910     pa_stream_set_overflow_callback(s, stream_overflow_cb, aout);
911     pa_stream_set_started_callback(s, stream_started_cb, aout);
912     pa_stream_set_suspended_callback(s, stream_suspended_cb, aout);
913     pa_stream_set_underflow_callback(s, stream_underflow_cb, aout);
914
915     if (pa_stream_connect_playback(s, sys->sink_force, &attr, flags, NULL,
916                                    NULL) < 0
917      || stream_wait(s, sys->mainloop)) {
918         vlc_pa_error(aout, "stream connection failure", sys->context);
919         goto fail;
920     }
921     sys->flags_force = PA_STREAM_NOFLAGS;
922     free(sys->sink_force);
923     sys->sink_force = NULL;
924
925     const struct pa_sample_spec *spec = pa_stream_get_sample_spec(s);
926 #if PA_CHECK_VERSION(1,0,0)
927     if (encoding != PA_ENCODING_INVALID) {
928         const pa_format_info *info = pa_stream_get_format_info(s);
929
930         assert (info != NULL);
931         if (pa_format_info_is_pcm (info)) {
932             msg_Dbg(aout, "digital pass-through not available");
933             fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
934         } else {
935             msg_Dbg(aout, "digital pass-through enabled");
936             spec = NULL;
937         }
938     }
939 #endif
940     if (spec != NULL)
941         fmt->i_rate = spec->rate;
942
943     stream_buffer_attr_cb(s, aout);
944     stream_moved_cb(s, aout);
945     pa_threaded_mainloop_unlock(sys->mainloop);
946
947     return VLC_SUCCESS;
948
949 fail:
950     pa_threaded_mainloop_unlock(sys->mainloop);
951     Stop(aout);
952     return VLC_EGENERIC;
953 }
954
955 /**
956  * Removes a PulseAudio playback stream
957  */
958 static void Stop(audio_output_t *aout)
959 {
960     aout_sys_t *sys = aout->sys;
961     pa_stream *s = sys->stream;
962
963     pa_threaded_mainloop_lock(sys->mainloop);
964     if (unlikely(sys->trigger != NULL))
965         vlc_pa_rttime_free(sys->mainloop, sys->trigger);
966     pa_stream_disconnect(s);
967
968     /* Clear all callbacks */
969     pa_stream_set_state_callback(s, NULL, NULL);
970     pa_stream_set_buffer_attr_callback(s, NULL, NULL);
971     pa_stream_set_event_callback(s, NULL, NULL);
972     pa_stream_set_latency_update_callback(s, NULL, NULL);
973     pa_stream_set_moved_callback(s, NULL, NULL);
974     pa_stream_set_overflow_callback(s, NULL, NULL);
975     pa_stream_set_started_callback(s, NULL, NULL);
976     pa_stream_set_suspended_callback(s, NULL, NULL);
977     pa_stream_set_underflow_callback(s, NULL, NULL);
978
979     pa_stream_unref(s);
980     sys->stream = NULL;
981     pa_threaded_mainloop_unlock(sys->mainloop);
982 }
983
984 static int Open(vlc_object_t *obj)
985 {
986     audio_output_t *aout = (audio_output_t *)obj;
987     aout_sys_t *sys = malloc(sizeof (*sys));
988     pa_operation *op;
989
990 #if !PA_CHECK_VERSION(0,9,22)
991     if (!vlc_xlib_init(obj))
992         return VLC_EGENERIC;
993 #endif
994     if (unlikely(sys == NULL))
995         return VLC_ENOMEM;
996
997     /* Allocate structures */
998     pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
999     if (ctx == NULL)
1000     {
1001         free(sys);
1002         return VLC_EGENERIC;
1003     }
1004     sys->stream = NULL;
1005     sys->context = ctx;
1006     sys->flags_force = PA_STREAM_NOFLAGS;
1007     sys->sink_force = NULL;
1008     sys->sinks = NULL;
1009
1010     aout->sys = sys;
1011     aout->start = Start;
1012     aout->stop = Stop;
1013     aout->time_get = TimeGet;
1014     aout->play = Play;
1015     aout->pause = Pause;
1016     aout->flush = Flush;
1017     aout->volume_set = VolumeSet;
1018     aout->mute_set = MuteSet;
1019     aout->device_enum = SinksList;
1020     aout->device_select = StreamMove;
1021
1022     pa_threaded_mainloop_lock(sys->mainloop);
1023     /* Sinks (output devices) list */
1024     op = pa_context_get_sink_info_list(sys->context, sink_add_cb, aout);
1025     if (op != NULL)
1026         pa_operation_unref(op);
1027
1028     /* Context events */
1029     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
1030                                       | PA_SUBSCRIPTION_MASK_SINK_INPUT;
1031     pa_context_set_subscribe_callback(sys->context, context_cb, aout);
1032     op = pa_context_subscribe(sys->context, mask, NULL, NULL);
1033     if (likely(op != NULL))
1034        pa_operation_unref(op);
1035     pa_threaded_mainloop_unlock(sys->mainloop);
1036
1037     return VLC_SUCCESS;
1038 }
1039
1040 static void Close(vlc_object_t *obj)
1041 {
1042     audio_output_t *aout = (audio_output_t *)obj;
1043     aout_sys_t *sys = aout->sys;
1044     pa_context *ctx = sys->context;
1045
1046     pa_threaded_mainloop_lock(sys->mainloop);
1047     pa_context_set_subscribe_callback(sys->context, NULL, NULL);
1048     pa_threaded_mainloop_unlock(sys->mainloop);
1049     vlc_pa_disconnect(obj, ctx, sys->mainloop);
1050
1051     for (struct sink *sink = sys->sinks, *next; sink != NULL; sink = next)
1052     {
1053         next = sink->next;
1054         free(sink->description);
1055         free(sink);
1056     }
1057     free(sys->sink_force);
1058     free(sys);
1059 }