xref: /openbmc/qemu/audio/paaudio.c (revision 9d34e6d8a1a1db44d882cc307a0e6ebb7a406e28)
1 /* public domain */
2 
3 #include "qemu/osdep.h"
4 #include "qemu/module.h"
5 #include "audio.h"
6 #include "qapi/opts-visitor.h"
7 
8 #include <pulse/pulseaudio.h>
9 
10 #define AUDIO_CAP "pulseaudio"
11 #include "audio_int.h"
12 #include "audio_pt_int.h"
13 
14 typedef struct PAConnection {
15     char *server;
16     int refcount;
17     QTAILQ_ENTRY(PAConnection) list;
18 
19     pa_threaded_mainloop *mainloop;
20     pa_context *context;
21 } PAConnection;
22 
23 static QTAILQ_HEAD(PAConnectionHead, PAConnection) pa_conns =
24     QTAILQ_HEAD_INITIALIZER(pa_conns);
25 
26 typedef struct {
27     Audiodev *dev;
28     PAConnection *conn;
29 } paaudio;
30 
31 typedef struct {
32     HWVoiceOut hw;
33     int done;
34     int live;
35     int decr;
36     int rpos;
37     pa_stream *stream;
38     void *pcm_buf;
39     struct audio_pt pt;
40     paaudio *g;
41     int samples;
42 } PAVoiceOut;
43 
44 typedef struct {
45     HWVoiceIn hw;
46     int done;
47     int dead;
48     int incr;
49     int wpos;
50     pa_stream *stream;
51     void *pcm_buf;
52     struct audio_pt pt;
53     const void *read_data;
54     size_t read_index, read_length;
55     paaudio *g;
56     int samples;
57 } PAVoiceIn;
58 
59 static void qpa_conn_fini(PAConnection *c);
60 
61 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
62 {
63     va_list ap;
64 
65     va_start (ap, fmt);
66     AUD_vlog (AUDIO_CAP, fmt, ap);
67     va_end (ap);
68 
69     AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err));
70 }
71 
72 #ifndef PA_CONTEXT_IS_GOOD
73 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
74 {
75     return
76         x == PA_CONTEXT_CONNECTING ||
77         x == PA_CONTEXT_AUTHORIZING ||
78         x == PA_CONTEXT_SETTING_NAME ||
79         x == PA_CONTEXT_READY;
80 }
81 #endif
82 
83 #ifndef PA_STREAM_IS_GOOD
84 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
85 {
86     return
87         x == PA_STREAM_CREATING ||
88         x == PA_STREAM_READY;
89 }
90 #endif
91 
92 #define CHECK_SUCCESS_GOTO(c, rerror, expression, label)        \
93     do {                                                        \
94         if (!(expression)) {                                    \
95             if (rerror) {                                       \
96                 *(rerror) = pa_context_errno ((c)->context);    \
97             }                                                   \
98             goto label;                                         \
99         }                                                       \
100     } while (0)
101 
102 #define CHECK_DEAD_GOTO(c, stream, rerror, label)                       \
103     do {                                                                \
104         if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
105             !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
106             if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
107                 ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
108                 if (rerror) {                                           \
109                     *(rerror) = pa_context_errno ((c)->context);        \
110                 }                                                       \
111             } else {                                                    \
112                 if (rerror) {                                           \
113                     *(rerror) = PA_ERR_BADSTATE;                        \
114                 }                                                       \
115             }                                                           \
116             goto label;                                                 \
117         }                                                               \
118     } while (0)
119 
120 static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror)
121 {
122     PAConnection *c = p->g->conn;
123 
124     pa_threaded_mainloop_lock(c->mainloop);
125 
126     CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail);
127 
128     while (length > 0) {
129         size_t l;
130 
131         while (!p->read_data) {
132             int r;
133 
134             r = pa_stream_peek (p->stream, &p->read_data, &p->read_length);
135             CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail);
136 
137             if (!p->read_data) {
138                 pa_threaded_mainloop_wait(c->mainloop);
139                 CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail);
140             } else {
141                 p->read_index = 0;
142             }
143         }
144 
145         l = p->read_length < length ? p->read_length : length;
146         memcpy (data, (const uint8_t *) p->read_data+p->read_index, l);
147 
148         data = (uint8_t *) data + l;
149         length -= l;
150 
151         p->read_index += l;
152         p->read_length -= l;
153 
154         if (!p->read_length) {
155             int r;
156 
157             r = pa_stream_drop (p->stream);
158             p->read_data = NULL;
159             p->read_length = 0;
160             p->read_index = 0;
161 
162             CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail);
163         }
164     }
165 
166     pa_threaded_mainloop_unlock(c->mainloop);
167     return 0;
168 
169 unlock_and_fail:
170     pa_threaded_mainloop_unlock(c->mainloop);
171     return -1;
172 }
173 
174 static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror)
175 {
176     PAConnection *c = p->g->conn;
177 
178     pa_threaded_mainloop_lock(c->mainloop);
179 
180     CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail);
181 
182     while (length > 0) {
183         size_t l;
184         int r;
185 
186         while (!(l = pa_stream_writable_size (p->stream))) {
187             pa_threaded_mainloop_wait(c->mainloop);
188             CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail);
189         }
190 
191         CHECK_SUCCESS_GOTO(c, rerror, l != (size_t) -1, unlock_and_fail);
192 
193         if (l > length) {
194             l = length;
195         }
196 
197         r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
198         CHECK_SUCCESS_GOTO(c, rerror, r >= 0, unlock_and_fail);
199 
200         data = (const uint8_t *) data + l;
201         length -= l;
202     }
203 
204     pa_threaded_mainloop_unlock(c->mainloop);
205     return 0;
206 
207 unlock_and_fail:
208     pa_threaded_mainloop_unlock(c->mainloop);
209     return -1;
210 }
211 
212 static void *qpa_thread_out (void *arg)
213 {
214     PAVoiceOut *pa = arg;
215     HWVoiceOut *hw = &pa->hw;
216 
217     if (audio_pt_lock(&pa->pt, __func__)) {
218         return NULL;
219     }
220 
221     for (;;) {
222         int decr, to_mix, rpos;
223 
224         for (;;) {
225             if (pa->done) {
226                 goto exit;
227             }
228 
229             if (pa->live > 0) {
230                 break;
231             }
232 
233             if (audio_pt_wait(&pa->pt, __func__)) {
234                 goto exit;
235             }
236         }
237 
238         decr = to_mix = audio_MIN(pa->live, pa->samples >> 5);
239         rpos = pa->rpos;
240 
241         if (audio_pt_unlock(&pa->pt, __func__)) {
242             return NULL;
243         }
244 
245         while (to_mix) {
246             int error;
247             int chunk = audio_MIN (to_mix, hw->samples - rpos);
248             struct st_sample *src = hw->mix_buf + rpos;
249 
250             hw->clip (pa->pcm_buf, src, chunk);
251 
252             if (qpa_simple_write (pa, pa->pcm_buf,
253                                   chunk << hw->info.shift, &error) < 0) {
254                 qpa_logerr (error, "pa_simple_write failed\n");
255                 return NULL;
256             }
257 
258             rpos = (rpos + chunk) % hw->samples;
259             to_mix -= chunk;
260         }
261 
262         if (audio_pt_lock(&pa->pt, __func__)) {
263             return NULL;
264         }
265 
266         pa->rpos = rpos;
267         pa->live -= decr;
268         pa->decr += decr;
269     }
270 
271  exit:
272     audio_pt_unlock(&pa->pt, __func__);
273     return NULL;
274 }
275 
276 static int qpa_run_out (HWVoiceOut *hw, int live)
277 {
278     int decr;
279     PAVoiceOut *pa = (PAVoiceOut *) hw;
280 
281     if (audio_pt_lock(&pa->pt, __func__)) {
282         return 0;
283     }
284 
285     decr = audio_MIN (live, pa->decr);
286     pa->decr -= decr;
287     pa->live = live - decr;
288     hw->rpos = pa->rpos;
289     if (pa->live > 0) {
290         audio_pt_unlock_and_signal(&pa->pt, __func__);
291     }
292     else {
293         audio_pt_unlock(&pa->pt, __func__);
294     }
295     return decr;
296 }
297 
298 static int qpa_write (SWVoiceOut *sw, void *buf, int len)
299 {
300     return audio_pcm_sw_write (sw, buf, len);
301 }
302 
303 /* capture */
304 static void *qpa_thread_in (void *arg)
305 {
306     PAVoiceIn *pa = arg;
307     HWVoiceIn *hw = &pa->hw;
308 
309     if (audio_pt_lock(&pa->pt, __func__)) {
310         return NULL;
311     }
312 
313     for (;;) {
314         int incr, to_grab, wpos;
315 
316         for (;;) {
317             if (pa->done) {
318                 goto exit;
319             }
320 
321             if (pa->dead > 0) {
322                 break;
323             }
324 
325             if (audio_pt_wait(&pa->pt, __func__)) {
326                 goto exit;
327             }
328         }
329 
330         incr = to_grab = audio_MIN(pa->dead, pa->samples >> 5);
331         wpos = pa->wpos;
332 
333         if (audio_pt_unlock(&pa->pt, __func__)) {
334             return NULL;
335         }
336 
337         while (to_grab) {
338             int error;
339             int chunk = audio_MIN (to_grab, hw->samples - wpos);
340             void *buf = advance (pa->pcm_buf, wpos);
341 
342             if (qpa_simple_read (pa, buf,
343                                  chunk << hw->info.shift, &error) < 0) {
344                 qpa_logerr (error, "pa_simple_read failed\n");
345                 return NULL;
346             }
347 
348             hw->conv (hw->conv_buf + wpos, buf, chunk);
349             wpos = (wpos + chunk) % hw->samples;
350             to_grab -= chunk;
351         }
352 
353         if (audio_pt_lock(&pa->pt, __func__)) {
354             return NULL;
355         }
356 
357         pa->wpos = wpos;
358         pa->dead -= incr;
359         pa->incr += incr;
360     }
361 
362  exit:
363     audio_pt_unlock(&pa->pt, __func__);
364     return NULL;
365 }
366 
367 static int qpa_run_in (HWVoiceIn *hw)
368 {
369     int live, incr, dead;
370     PAVoiceIn *pa = (PAVoiceIn *) hw;
371 
372     if (audio_pt_lock(&pa->pt, __func__)) {
373         return 0;
374     }
375 
376     live = audio_pcm_hw_get_live_in (hw);
377     dead = hw->samples - live;
378     incr = audio_MIN (dead, pa->incr);
379     pa->incr -= incr;
380     pa->dead = dead - incr;
381     hw->wpos = pa->wpos;
382     if (pa->dead > 0) {
383         audio_pt_unlock_and_signal(&pa->pt, __func__);
384     }
385     else {
386         audio_pt_unlock(&pa->pt, __func__);
387     }
388     return incr;
389 }
390 
391 static int qpa_read (SWVoiceIn *sw, void *buf, int len)
392 {
393     return audio_pcm_sw_read (sw, buf, len);
394 }
395 
396 static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
397 {
398     int format;
399 
400     switch (afmt) {
401     case AUDIO_FORMAT_S8:
402     case AUDIO_FORMAT_U8:
403         format = PA_SAMPLE_U8;
404         break;
405     case AUDIO_FORMAT_S16:
406     case AUDIO_FORMAT_U16:
407         format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
408         break;
409     case AUDIO_FORMAT_S32:
410     case AUDIO_FORMAT_U32:
411         format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
412         break;
413     default:
414         dolog ("Internal logic error: Bad audio format %d\n", afmt);
415         format = PA_SAMPLE_U8;
416         break;
417     }
418     return format;
419 }
420 
421 static AudioFormat pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
422 {
423     switch (fmt) {
424     case PA_SAMPLE_U8:
425         return AUDIO_FORMAT_U8;
426     case PA_SAMPLE_S16BE:
427         *endianness = 1;
428         return AUDIO_FORMAT_S16;
429     case PA_SAMPLE_S16LE:
430         *endianness = 0;
431         return AUDIO_FORMAT_S16;
432     case PA_SAMPLE_S32BE:
433         *endianness = 1;
434         return AUDIO_FORMAT_S32;
435     case PA_SAMPLE_S32LE:
436         *endianness = 0;
437         return AUDIO_FORMAT_S32;
438     default:
439         dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
440         return AUDIO_FORMAT_U8;
441     }
442 }
443 
444 static void context_state_cb (pa_context *c, void *userdata)
445 {
446     PAConnection *conn = userdata;
447 
448     switch (pa_context_get_state(c)) {
449     case PA_CONTEXT_READY:
450     case PA_CONTEXT_TERMINATED:
451     case PA_CONTEXT_FAILED:
452         pa_threaded_mainloop_signal(conn->mainloop, 0);
453         break;
454 
455     case PA_CONTEXT_UNCONNECTED:
456     case PA_CONTEXT_CONNECTING:
457     case PA_CONTEXT_AUTHORIZING:
458     case PA_CONTEXT_SETTING_NAME:
459         break;
460     }
461 }
462 
463 static void stream_state_cb (pa_stream *s, void * userdata)
464 {
465     PAConnection *c = userdata;
466 
467     switch (pa_stream_get_state (s)) {
468 
469     case PA_STREAM_READY:
470     case PA_STREAM_FAILED:
471     case PA_STREAM_TERMINATED:
472         pa_threaded_mainloop_signal(c->mainloop, 0);
473         break;
474 
475     case PA_STREAM_UNCONNECTED:
476     case PA_STREAM_CREATING:
477         break;
478     }
479 }
480 
481 static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
482 {
483     PAConnection *c = userdata;
484 
485     pa_threaded_mainloop_signal(c->mainloop, 0);
486 }
487 
488 static pa_stream *qpa_simple_new (
489         PAConnection *c,
490         const char *name,
491         pa_stream_direction_t dir,
492         const char *dev,
493         const pa_sample_spec *ss,
494         const pa_channel_map *map,
495         const pa_buffer_attr *attr,
496         int *rerror)
497 {
498     int r;
499     pa_stream *stream;
500     pa_stream_flags_t flags;
501 
502     pa_threaded_mainloop_lock(c->mainloop);
503 
504     stream = pa_stream_new(c->context, name, ss, map);
505     if (!stream) {
506         goto fail;
507     }
508 
509     pa_stream_set_state_callback(stream, stream_state_cb, c);
510     pa_stream_set_read_callback(stream, stream_request_cb, c);
511     pa_stream_set_write_callback(stream, stream_request_cb, c);
512 
513     flags =
514         PA_STREAM_INTERPOLATE_TIMING
515 #ifdef PA_STREAM_ADJUST_LATENCY
516         | PA_STREAM_ADJUST_LATENCY
517 #endif
518         | PA_STREAM_AUTO_TIMING_UPDATE;
519 
520     if (dir == PA_STREAM_PLAYBACK) {
521         r = pa_stream_connect_playback(stream, dev, attr, flags, NULL, NULL);
522     } else {
523         r = pa_stream_connect_record(stream, dev, attr, flags);
524     }
525 
526     if (r < 0) {
527       goto fail;
528     }
529 
530     pa_threaded_mainloop_unlock(c->mainloop);
531 
532     return stream;
533 
534 fail:
535     pa_threaded_mainloop_unlock(c->mainloop);
536 
537     if (stream) {
538         pa_stream_unref (stream);
539     }
540 
541     *rerror = pa_context_errno(c->context);
542 
543     return NULL;
544 }
545 
546 static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
547                         void *drv_opaque)
548 {
549     int error;
550     pa_sample_spec ss;
551     pa_buffer_attr ba;
552     struct audsettings obt_as = *as;
553     PAVoiceOut *pa = (PAVoiceOut *) hw;
554     paaudio *g = pa->g = drv_opaque;
555     AudiodevPaOptions *popts = &g->dev->u.pa;
556     AudiodevPaPerDirectionOptions *ppdo = popts->out;
557     PAConnection *c = g->conn;
558 
559     ss.format = audfmt_to_pa (as->fmt, as->endianness);
560     ss.channels = as->nchannels;
561     ss.rate = as->freq;
562 
563     ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
564     ba.minreq = -1;
565     ba.maxlength = -1;
566     ba.prebuf = -1;
567 
568     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
569 
570     pa->stream = qpa_simple_new (
571         c,
572         "qemu",
573         PA_STREAM_PLAYBACK,
574         ppdo->has_name ? ppdo->name : NULL,
575         &ss,
576         NULL,                   /* channel map */
577         &ba,                    /* buffering attributes */
578         &error
579         );
580     if (!pa->stream) {
581         qpa_logerr (error, "pa_simple_new for playback failed\n");
582         goto fail1;
583     }
584 
585     audio_pcm_init_info (&hw->info, &obt_as);
586     hw->samples = pa->samples = audio_buffer_samples(
587         qapi_AudiodevPaPerDirectionOptions_base(ppdo),
588         &obt_as, ppdo->buffer_length);
589     pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
590     pa->rpos = hw->rpos;
591     if (!pa->pcm_buf) {
592         dolog ("Could not allocate buffer (%d bytes)\n",
593                hw->samples << hw->info.shift);
594         goto fail2;
595     }
596 
597     if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) {
598         goto fail3;
599     }
600 
601     return 0;
602 
603  fail3:
604     g_free (pa->pcm_buf);
605     pa->pcm_buf = NULL;
606  fail2:
607     if (pa->stream) {
608         pa_stream_unref (pa->stream);
609         pa->stream = NULL;
610     }
611  fail1:
612     return -1;
613 }
614 
615 static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
616 {
617     int error;
618     pa_sample_spec ss;
619     pa_buffer_attr ba;
620     struct audsettings obt_as = *as;
621     PAVoiceIn *pa = (PAVoiceIn *) hw;
622     paaudio *g = pa->g = drv_opaque;
623     AudiodevPaOptions *popts = &g->dev->u.pa;
624     AudiodevPaPerDirectionOptions *ppdo = popts->in;
625     PAConnection *c = g->conn;
626 
627     ss.format = audfmt_to_pa (as->fmt, as->endianness);
628     ss.channels = as->nchannels;
629     ss.rate = as->freq;
630 
631     ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
632     ba.maxlength = pa_usec_to_bytes(ppdo->latency * 2, &ss);
633     ba.minreq = -1;
634     ba.prebuf = -1;
635 
636     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
637 
638     pa->stream = qpa_simple_new (
639         c,
640         "qemu",
641         PA_STREAM_RECORD,
642         ppdo->has_name ? ppdo->name : NULL,
643         &ss,
644         NULL,                   /* channel map */
645         &ba,                    /* buffering attributes */
646         &error
647         );
648     if (!pa->stream) {
649         qpa_logerr (error, "pa_simple_new for capture failed\n");
650         goto fail1;
651     }
652 
653     audio_pcm_init_info (&hw->info, &obt_as);
654     hw->samples = pa->samples = audio_buffer_samples(
655         qapi_AudiodevPaPerDirectionOptions_base(ppdo),
656         &obt_as, ppdo->buffer_length);
657     pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
658     pa->wpos = hw->wpos;
659     if (!pa->pcm_buf) {
660         dolog ("Could not allocate buffer (%d bytes)\n",
661                hw->samples << hw->info.shift);
662         goto fail2;
663     }
664 
665     if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) {
666         goto fail3;
667     }
668 
669     return 0;
670 
671  fail3:
672     g_free (pa->pcm_buf);
673     pa->pcm_buf = NULL;
674  fail2:
675     if (pa->stream) {
676         pa_stream_unref (pa->stream);
677         pa->stream = NULL;
678     }
679  fail1:
680     return -1;
681 }
682 
683 static void qpa_fini_out (HWVoiceOut *hw)
684 {
685     void *ret;
686     PAVoiceOut *pa = (PAVoiceOut *) hw;
687 
688     audio_pt_lock(&pa->pt, __func__);
689     pa->done = 1;
690     audio_pt_unlock_and_signal(&pa->pt, __func__);
691     audio_pt_join(&pa->pt, &ret, __func__);
692 
693     if (pa->stream) {
694         pa_stream_unref (pa->stream);
695         pa->stream = NULL;
696     }
697 
698     audio_pt_fini(&pa->pt, __func__);
699     g_free (pa->pcm_buf);
700     pa->pcm_buf = NULL;
701 }
702 
703 static void qpa_fini_in (HWVoiceIn *hw)
704 {
705     void *ret;
706     PAVoiceIn *pa = (PAVoiceIn *) hw;
707 
708     audio_pt_lock(&pa->pt, __func__);
709     pa->done = 1;
710     audio_pt_unlock_and_signal(&pa->pt, __func__);
711     audio_pt_join(&pa->pt, &ret, __func__);
712 
713     if (pa->stream) {
714         pa_stream_unref (pa->stream);
715         pa->stream = NULL;
716     }
717 
718     audio_pt_fini(&pa->pt, __func__);
719     g_free (pa->pcm_buf);
720     pa->pcm_buf = NULL;
721 }
722 
723 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
724 {
725     PAVoiceOut *pa = (PAVoiceOut *) hw;
726     pa_operation *op;
727     pa_cvolume v;
728     PAConnection *c = pa->g->conn;
729 
730 #ifdef PA_CHECK_VERSION    /* macro is present in 0.9.16+ */
731     pa_cvolume_init (&v);  /* function is present in 0.9.13+ */
732 #endif
733 
734     switch (cmd) {
735     case VOICE_VOLUME:
736         {
737             SWVoiceOut *sw;
738             va_list ap;
739 
740             va_start (ap, cmd);
741             sw = va_arg (ap, SWVoiceOut *);
742             va_end (ap);
743 
744             v.channels = 2;
745             v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
746             v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
747 
748             pa_threaded_mainloop_lock(c->mainloop);
749 
750             op = pa_context_set_sink_input_volume(c->context,
751                 pa_stream_get_index (pa->stream),
752                 &v, NULL, NULL);
753             if (!op) {
754                 qpa_logerr(pa_context_errno(c->context),
755                            "set_sink_input_volume() failed\n");
756             } else {
757                 pa_operation_unref(op);
758             }
759 
760             op = pa_context_set_sink_input_mute(c->context,
761                 pa_stream_get_index (pa->stream),
762                sw->vol.mute, NULL, NULL);
763             if (!op) {
764                 qpa_logerr(pa_context_errno(c->context),
765                            "set_sink_input_mute() failed\n");
766             } else {
767                 pa_operation_unref(op);
768             }
769 
770             pa_threaded_mainloop_unlock(c->mainloop);
771         }
772     }
773     return 0;
774 }
775 
776 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
777 {
778     PAVoiceIn *pa = (PAVoiceIn *) hw;
779     pa_operation *op;
780     pa_cvolume v;
781     PAConnection *c = pa->g->conn;
782 
783 #ifdef PA_CHECK_VERSION
784     pa_cvolume_init (&v);
785 #endif
786 
787     switch (cmd) {
788     case VOICE_VOLUME:
789         {
790             SWVoiceIn *sw;
791             va_list ap;
792 
793             va_start (ap, cmd);
794             sw = va_arg (ap, SWVoiceIn *);
795             va_end (ap);
796 
797             v.channels = 2;
798             v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
799             v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
800 
801             pa_threaded_mainloop_lock(c->mainloop);
802 
803             op = pa_context_set_source_output_volume(c->context,
804                 pa_stream_get_index(pa->stream),
805                 &v, NULL, NULL);
806             if (!op) {
807                 qpa_logerr(pa_context_errno(c->context),
808                            "set_source_output_volume() failed\n");
809             } else {
810                 pa_operation_unref(op);
811             }
812 
813             op = pa_context_set_source_output_mute(c->context,
814                 pa_stream_get_index (pa->stream),
815                 sw->vol.mute, NULL, NULL);
816             if (!op) {
817                 qpa_logerr(pa_context_errno(c->context),
818                            "set_source_output_mute() failed\n");
819             } else {
820                 pa_operation_unref (op);
821             }
822 
823             pa_threaded_mainloop_unlock(c->mainloop);
824         }
825     }
826     return 0;
827 }
828 
829 static int qpa_validate_per_direction_opts(Audiodev *dev,
830                                            AudiodevPaPerDirectionOptions *pdo)
831 {
832     if (!pdo->has_buffer_length) {
833         pdo->has_buffer_length = true;
834         pdo->buffer_length = 46440;
835     }
836     if (!pdo->has_latency) {
837         pdo->has_latency = true;
838         pdo->latency = 15000;
839     }
840     return 1;
841 }
842 
843 /* common */
844 static void *qpa_conn_init(const char *server)
845 {
846     PAConnection *c = g_malloc0(sizeof(PAConnection));
847     QTAILQ_INSERT_TAIL(&pa_conns, c, list);
848 
849     c->mainloop = pa_threaded_mainloop_new();
850     if (!c->mainloop) {
851         goto fail;
852     }
853 
854     c->context = pa_context_new(pa_threaded_mainloop_get_api(c->mainloop),
855                                 server);
856     if (!c->context) {
857         goto fail;
858     }
859 
860     pa_context_set_state_callback(c->context, context_state_cb, c);
861 
862     if (pa_context_connect(c->context, server, 0, NULL) < 0) {
863         qpa_logerr(pa_context_errno(c->context),
864                    "pa_context_connect() failed\n");
865         goto fail;
866     }
867 
868     pa_threaded_mainloop_lock(c->mainloop);
869 
870     if (pa_threaded_mainloop_start(c->mainloop) < 0) {
871         goto unlock_and_fail;
872     }
873 
874     for (;;) {
875         pa_context_state_t state;
876 
877         state = pa_context_get_state(c->context);
878 
879         if (state == PA_CONTEXT_READY) {
880             break;
881         }
882 
883         if (!PA_CONTEXT_IS_GOOD(state)) {
884             qpa_logerr(pa_context_errno(c->context),
885                        "Wrong context state\n");
886             goto unlock_and_fail;
887         }
888 
889         /* Wait until the context is ready */
890         pa_threaded_mainloop_wait(c->mainloop);
891     }
892 
893     pa_threaded_mainloop_unlock(c->mainloop);
894     return c;
895 
896 unlock_and_fail:
897     pa_threaded_mainloop_unlock(c->mainloop);
898 fail:
899     AUD_log (AUDIO_CAP, "Failed to initialize PA context");
900     qpa_conn_fini(c);
901     return NULL;
902 }
903 
904 static void *qpa_audio_init(Audiodev *dev)
905 {
906     paaudio *g;
907     AudiodevPaOptions *popts = &dev->u.pa;
908     const char *server;
909     PAConnection *c;
910 
911     assert(dev->driver == AUDIODEV_DRIVER_PA);
912 
913     if (!popts->has_server) {
914         char pidfile[64];
915         char *runtime;
916         struct stat st;
917 
918         runtime = getenv("XDG_RUNTIME_DIR");
919         if (!runtime) {
920             return NULL;
921         }
922         snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
923         if (stat(pidfile, &st) != 0) {
924             return NULL;
925         }
926     }
927 
928     if (!qpa_validate_per_direction_opts(dev, popts->in)) {
929         return NULL;
930     }
931     if (!qpa_validate_per_direction_opts(dev, popts->out)) {
932         return NULL;
933     }
934 
935     g = g_malloc0(sizeof(paaudio));
936     server = popts->has_server ? popts->server : NULL;
937 
938     g->dev = dev;
939 
940     QTAILQ_FOREACH(c, &pa_conns, list) {
941         if (server == NULL || c->server == NULL ?
942             server == c->server :
943             strcmp(server, c->server) == 0) {
944             g->conn = c;
945             break;
946         }
947     }
948     if (!g->conn) {
949         g->conn = qpa_conn_init(server);
950     }
951     if (!g->conn) {
952         g_free(g);
953         return NULL;
954     }
955 
956     ++g->conn->refcount;
957     return g;
958 }
959 
960 static void qpa_conn_fini(PAConnection *c)
961 {
962     if (c->mainloop) {
963         pa_threaded_mainloop_stop(c->mainloop);
964     }
965 
966     if (c->context) {
967         pa_context_disconnect(c->context);
968         pa_context_unref(c->context);
969     }
970 
971     if (c->mainloop) {
972         pa_threaded_mainloop_free(c->mainloop);
973     }
974 
975     QTAILQ_REMOVE(&pa_conns, c, list);
976     g_free(c);
977 }
978 
979 static void qpa_audio_fini (void *opaque)
980 {
981     paaudio *g = opaque;
982     PAConnection *c = g->conn;
983 
984     if (--c->refcount == 0) {
985         qpa_conn_fini(c);
986     }
987 
988     g_free(g);
989 }
990 
991 static struct audio_pcm_ops qpa_pcm_ops = {
992     .init_out = qpa_init_out,
993     .fini_out = qpa_fini_out,
994     .run_out  = qpa_run_out,
995     .write    = qpa_write,
996     .ctl_out  = qpa_ctl_out,
997 
998     .init_in  = qpa_init_in,
999     .fini_in  = qpa_fini_in,
1000     .run_in   = qpa_run_in,
1001     .read     = qpa_read,
1002     .ctl_in   = qpa_ctl_in
1003 };
1004 
1005 static struct audio_driver pa_audio_driver = {
1006     .name           = "pa",
1007     .descr          = "http://www.pulseaudio.org/",
1008     .init           = qpa_audio_init,
1009     .fini           = qpa_audio_fini,
1010     .pcm_ops        = &qpa_pcm_ops,
1011     .can_be_default = 1,
1012     .max_voices_out = INT_MAX,
1013     .max_voices_in  = INT_MAX,
1014     .voice_size_out = sizeof (PAVoiceOut),
1015     .voice_size_in  = sizeof (PAVoiceIn),
1016     .ctl_caps       = VOICE_VOLUME_CAP
1017 };
1018 
1019 static void register_audio_pa(void)
1020 {
1021     audio_driver_register(&pa_audio_driver);
1022 }
1023 type_init(register_audio_pa);
1024