xref: /openbmc/qemu/audio/paaudio.c (revision 86044b24)
1 /* public domain */
2 
3 #include "qemu/osdep.h"
4 #include "qemu/module.h"
5 #include "qemu-common.h"
6 #include "audio.h"
7 #include "qapi/opts-visitor.h"
8 
9 #include <pulse/pulseaudio.h>
10 
11 #define AUDIO_CAP "pulseaudio"
12 #include "audio_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     pa_stream *stream;
34     paaudio *g;
35     size_t samples;
36 } PAVoiceOut;
37 
38 typedef struct {
39     HWVoiceIn hw;
40     pa_stream *stream;
41     const void *read_data;
42     size_t read_length;
43     paaudio *g;
44     size_t samples;
45 } PAVoiceIn;
46 
47 static void qpa_conn_fini(PAConnection *c);
48 
49 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
50 {
51     va_list ap;
52 
53     va_start (ap, fmt);
54     AUD_vlog (AUDIO_CAP, fmt, ap);
55     va_end (ap);
56 
57     AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err));
58 }
59 
60 #ifndef PA_CONTEXT_IS_GOOD
61 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
62 {
63     return
64         x == PA_CONTEXT_CONNECTING ||
65         x == PA_CONTEXT_AUTHORIZING ||
66         x == PA_CONTEXT_SETTING_NAME ||
67         x == PA_CONTEXT_READY;
68 }
69 #endif
70 
71 #ifndef PA_STREAM_IS_GOOD
72 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
73 {
74     return
75         x == PA_STREAM_CREATING ||
76         x == PA_STREAM_READY;
77 }
78 #endif
79 
80 #define CHECK_SUCCESS_GOTO(c, expression, label, msg)           \
81     do {                                                        \
82         if (!(expression)) {                                    \
83             qpa_logerr(pa_context_errno((c)->context), msg);    \
84             goto label;                                         \
85         }                                                       \
86     } while (0)
87 
88 #define CHECK_DEAD_GOTO(c, stream, label, msg)                          \
89     do {                                                                \
90         if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \
91             !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \
92             if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \
93                 ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \
94                 qpa_logerr(pa_context_errno((c)->context), msg);        \
95             } else {                                                    \
96                 qpa_logerr(PA_ERR_BADSTATE, msg);                       \
97             }                                                           \
98             goto label;                                                 \
99         }                                                               \
100     } while (0)
101 
102 static void *qpa_get_buffer_in(HWVoiceIn *hw, size_t *size)
103 {
104     PAVoiceIn *p = (PAVoiceIn *) hw;
105     PAConnection *c = p->g->conn;
106     int r;
107 
108     pa_threaded_mainloop_lock(c->mainloop);
109 
110     CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
111                     "pa_threaded_mainloop_lock failed\n");
112 
113     if (!p->read_length) {
114         r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
115         CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
116                            "pa_stream_peek failed\n");
117     }
118 
119     *size = MIN(p->read_length, *size);
120 
121     pa_threaded_mainloop_unlock(c->mainloop);
122     return (void *) p->read_data;
123 
124 unlock_and_fail:
125     pa_threaded_mainloop_unlock(c->mainloop);
126     *size = 0;
127     return NULL;
128 }
129 
130 static void qpa_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
131 {
132     PAVoiceIn *p = (PAVoiceIn *) hw;
133     PAConnection *c = p->g->conn;
134     int r;
135 
136     pa_threaded_mainloop_lock(c->mainloop);
137 
138     CHECK_DEAD_GOTO(c, p->stream, unlock,
139                     "pa_threaded_mainloop_lock failed\n");
140 
141     assert(buf == p->read_data && size <= p->read_length);
142 
143     p->read_data += size;
144     p->read_length -= size;
145 
146     if (size && !p->read_length) {
147         r = pa_stream_drop(p->stream);
148         CHECK_SUCCESS_GOTO(c, r == 0, unlock, "pa_stream_drop failed\n");
149     }
150 
151 unlock:
152     pa_threaded_mainloop_unlock(c->mainloop);
153 }
154 
155 static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length)
156 {
157     PAVoiceIn *p = (PAVoiceIn *) hw;
158     PAConnection *c = p->g->conn;
159     size_t l;
160     int r;
161 
162     pa_threaded_mainloop_lock(c->mainloop);
163 
164     CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
165                     "pa_threaded_mainloop_lock failed\n");
166 
167     if (!p->read_length) {
168         r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
169         CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
170                            "pa_stream_peek failed\n");
171     }
172 
173     l = MIN(p->read_length, length);
174     memcpy(data, p->read_data, l);
175 
176     p->read_data += l;
177     p->read_length -= l;
178 
179     if (!p->read_length) {
180         r = pa_stream_drop(p->stream);
181         CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail,
182                            "pa_stream_drop failed\n");
183     }
184 
185     pa_threaded_mainloop_unlock(c->mainloop);
186     return l;
187 
188 unlock_and_fail:
189     pa_threaded_mainloop_unlock(c->mainloop);
190     return 0;
191 }
192 
193 static void *qpa_get_buffer_out(HWVoiceOut *hw, size_t *size)
194 {
195     PAVoiceOut *p = (PAVoiceOut *) hw;
196     PAConnection *c = p->g->conn;
197     void *ret;
198     int r;
199 
200     pa_threaded_mainloop_lock(c->mainloop);
201 
202     CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
203                     "pa_threaded_mainloop_lock failed\n");
204 
205     *size = -1;
206     r = pa_stream_begin_write(p->stream, &ret, size);
207     CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail,
208                        "pa_stream_begin_write failed\n");
209 
210     pa_threaded_mainloop_unlock(c->mainloop);
211     return ret;
212 
213 unlock_and_fail:
214     pa_threaded_mainloop_unlock(c->mainloop);
215     *size = 0;
216     return NULL;
217 }
218 
219 static size_t qpa_write(HWVoiceOut *hw, void *data, size_t length)
220 {
221     PAVoiceOut *p = (PAVoiceOut *) hw;
222     PAConnection *c = p->g->conn;
223     size_t l;
224     int r;
225 
226     pa_threaded_mainloop_lock(c->mainloop);
227 
228     CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
229                     "pa_threaded_mainloop_lock failed\n");
230 
231     l = pa_stream_writable_size(p->stream);
232 
233     CHECK_SUCCESS_GOTO(c, l != (size_t) -1, unlock_and_fail,
234                        "pa_stream_writable_size failed\n");
235 
236     if (l > length) {
237         l = length;
238     }
239 
240     r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
241     CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail, "pa_stream_write failed\n");
242 
243     pa_threaded_mainloop_unlock(c->mainloop);
244     return l;
245 
246 unlock_and_fail:
247     pa_threaded_mainloop_unlock(c->mainloop);
248     return 0;
249 }
250 
251 static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
252 {
253     int format;
254 
255     switch (afmt) {
256     case AUDIO_FORMAT_S8:
257     case AUDIO_FORMAT_U8:
258         format = PA_SAMPLE_U8;
259         break;
260     case AUDIO_FORMAT_S16:
261     case AUDIO_FORMAT_U16:
262         format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
263         break;
264     case AUDIO_FORMAT_S32:
265     case AUDIO_FORMAT_U32:
266         format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
267         break;
268     default:
269         dolog ("Internal logic error: Bad audio format %d\n", afmt);
270         format = PA_SAMPLE_U8;
271         break;
272     }
273     return format;
274 }
275 
276 static AudioFormat pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
277 {
278     switch (fmt) {
279     case PA_SAMPLE_U8:
280         return AUDIO_FORMAT_U8;
281     case PA_SAMPLE_S16BE:
282         *endianness = 1;
283         return AUDIO_FORMAT_S16;
284     case PA_SAMPLE_S16LE:
285         *endianness = 0;
286         return AUDIO_FORMAT_S16;
287     case PA_SAMPLE_S32BE:
288         *endianness = 1;
289         return AUDIO_FORMAT_S32;
290     case PA_SAMPLE_S32LE:
291         *endianness = 0;
292         return AUDIO_FORMAT_S32;
293     default:
294         dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
295         return AUDIO_FORMAT_U8;
296     }
297 }
298 
299 static void context_state_cb (pa_context *c, void *userdata)
300 {
301     PAConnection *conn = userdata;
302 
303     switch (pa_context_get_state(c)) {
304     case PA_CONTEXT_READY:
305     case PA_CONTEXT_TERMINATED:
306     case PA_CONTEXT_FAILED:
307         pa_threaded_mainloop_signal(conn->mainloop, 0);
308         break;
309 
310     case PA_CONTEXT_UNCONNECTED:
311     case PA_CONTEXT_CONNECTING:
312     case PA_CONTEXT_AUTHORIZING:
313     case PA_CONTEXT_SETTING_NAME:
314         break;
315     }
316 }
317 
318 static void stream_state_cb (pa_stream *s, void * userdata)
319 {
320     PAConnection *c = userdata;
321 
322     switch (pa_stream_get_state (s)) {
323 
324     case PA_STREAM_READY:
325     case PA_STREAM_FAILED:
326     case PA_STREAM_TERMINATED:
327         pa_threaded_mainloop_signal(c->mainloop, 0);
328         break;
329 
330     case PA_STREAM_UNCONNECTED:
331     case PA_STREAM_CREATING:
332         break;
333     }
334 }
335 
336 static pa_stream *qpa_simple_new (
337         PAConnection *c,
338         const char *name,
339         pa_stream_direction_t dir,
340         const char *dev,
341         const pa_sample_spec *ss,
342         const pa_buffer_attr *attr,
343         int *rerror)
344 {
345     int r;
346     pa_stream *stream = NULL;
347     pa_stream_flags_t flags;
348     pa_channel_map map;
349 
350     pa_threaded_mainloop_lock(c->mainloop);
351 
352     pa_channel_map_init(&map);
353     map.channels = ss->channels;
354 
355     /*
356      * TODO: This currently expects the only frontend supporting more than 2
357      * channels is the usb-audio.  We will need some means to set channel
358      * order when a new frontend gains multi-channel support.
359      */
360     switch (ss->channels) {
361     case 1:
362         map.map[0] = PA_CHANNEL_POSITION_MONO;
363         break;
364 
365     case 2:
366         map.map[0] = PA_CHANNEL_POSITION_LEFT;
367         map.map[1] = PA_CHANNEL_POSITION_RIGHT;
368         break;
369 
370     case 6:
371         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
372         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
373         map.map[2] = PA_CHANNEL_POSITION_CENTER;
374         map.map[3] = PA_CHANNEL_POSITION_LFE;
375         map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
376         map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
377         break;
378 
379     case 8:
380         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
381         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
382         map.map[2] = PA_CHANNEL_POSITION_CENTER;
383         map.map[3] = PA_CHANNEL_POSITION_LFE;
384         map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
385         map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
386         map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
387         map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
388 
389     default:
390         dolog("Internal error: unsupported channel count %d\n", ss->channels);
391         goto fail;
392     }
393 
394     stream = pa_stream_new(c->context, name, ss, &map);
395     if (!stream) {
396         goto fail;
397     }
398 
399     pa_stream_set_state_callback(stream, stream_state_cb, c);
400 
401     flags =
402         PA_STREAM_INTERPOLATE_TIMING
403         | PA_STREAM_AUTO_TIMING_UPDATE
404         | PA_STREAM_EARLY_REQUESTS;
405 
406     if (dev) {
407         /* don't move the stream if the user specified a sink/source */
408         flags |= PA_STREAM_DONT_MOVE;
409     }
410 
411     if (dir == PA_STREAM_PLAYBACK) {
412         r = pa_stream_connect_playback(stream, dev, attr, flags, NULL, NULL);
413     } else {
414         r = pa_stream_connect_record(stream, dev, attr, flags);
415     }
416 
417     if (r < 0) {
418       goto fail;
419     }
420 
421     pa_threaded_mainloop_unlock(c->mainloop);
422 
423     return stream;
424 
425 fail:
426     pa_threaded_mainloop_unlock(c->mainloop);
427 
428     if (stream) {
429         pa_stream_unref (stream);
430     }
431 
432     *rerror = pa_context_errno(c->context);
433 
434     return NULL;
435 }
436 
437 static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
438                         void *drv_opaque)
439 {
440     int error;
441     pa_sample_spec ss;
442     pa_buffer_attr ba;
443     struct audsettings obt_as = *as;
444     PAVoiceOut *pa = (PAVoiceOut *) hw;
445     paaudio *g = pa->g = drv_opaque;
446     AudiodevPaOptions *popts = &g->dev->u.pa;
447     AudiodevPaPerDirectionOptions *ppdo = popts->out;
448     PAConnection *c = g->conn;
449 
450     ss.format = audfmt_to_pa (as->fmt, as->endianness);
451     ss.channels = as->nchannels;
452     ss.rate = as->freq;
453 
454     ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
455     ba.minreq = -1;
456     ba.maxlength = -1;
457     ba.prebuf = -1;
458 
459     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
460 
461     pa->stream = qpa_simple_new (
462         c,
463         ppdo->has_stream_name ? ppdo->stream_name : g->dev->id,
464         PA_STREAM_PLAYBACK,
465         ppdo->has_name ? ppdo->name : NULL,
466         &ss,
467         &ba,                    /* buffering attributes */
468         &error
469         );
470     if (!pa->stream) {
471         qpa_logerr (error, "pa_simple_new for playback failed\n");
472         goto fail1;
473     }
474 
475     audio_pcm_init_info (&hw->info, &obt_as);
476     hw->samples = pa->samples = audio_buffer_samples(
477         qapi_AudiodevPaPerDirectionOptions_base(ppdo),
478         &obt_as, ppdo->buffer_length);
479 
480     return 0;
481 
482  fail1:
483     return -1;
484 }
485 
486 static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
487 {
488     int error;
489     pa_sample_spec ss;
490     pa_buffer_attr ba;
491     struct audsettings obt_as = *as;
492     PAVoiceIn *pa = (PAVoiceIn *) hw;
493     paaudio *g = pa->g = drv_opaque;
494     AudiodevPaOptions *popts = &g->dev->u.pa;
495     AudiodevPaPerDirectionOptions *ppdo = popts->in;
496     PAConnection *c = g->conn;
497 
498     ss.format = audfmt_to_pa (as->fmt, as->endianness);
499     ss.channels = as->nchannels;
500     ss.rate = as->freq;
501 
502     ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
503     ba.maxlength = pa_usec_to_bytes(ppdo->latency * 2, &ss);
504     ba.minreq = -1;
505     ba.prebuf = -1;
506 
507     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
508 
509     pa->stream = qpa_simple_new (
510         c,
511         ppdo->has_stream_name ? ppdo->stream_name : g->dev->id,
512         PA_STREAM_RECORD,
513         ppdo->has_name ? ppdo->name : NULL,
514         &ss,
515         &ba,                    /* buffering attributes */
516         &error
517         );
518     if (!pa->stream) {
519         qpa_logerr (error, "pa_simple_new for capture failed\n");
520         goto fail1;
521     }
522 
523     audio_pcm_init_info (&hw->info, &obt_as);
524     hw->samples = pa->samples = audio_buffer_samples(
525         qapi_AudiodevPaPerDirectionOptions_base(ppdo),
526         &obt_as, ppdo->buffer_length);
527 
528     return 0;
529 
530  fail1:
531     return -1;
532 }
533 
534 static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream)
535 {
536     int err;
537 
538     pa_threaded_mainloop_lock(c->mainloop);
539     /*
540      * wait until actually connects. workaround pa bug #247
541      * https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/247
542      */
543     while (pa_stream_get_state(stream) == PA_STREAM_CREATING) {
544         pa_threaded_mainloop_wait(c->mainloop);
545     }
546 
547     err = pa_stream_disconnect(stream);
548     if (err != 0) {
549         dolog("Failed to disconnect! err=%d\n", err);
550     }
551     pa_stream_unref(stream);
552     pa_threaded_mainloop_unlock(c->mainloop);
553 }
554 
555 static void qpa_fini_out (HWVoiceOut *hw)
556 {
557     PAVoiceOut *pa = (PAVoiceOut *) hw;
558 
559     if (pa->stream) {
560         qpa_simple_disconnect(pa->g->conn, pa->stream);
561         pa->stream = NULL;
562     }
563 }
564 
565 static void qpa_fini_in (HWVoiceIn *hw)
566 {
567     PAVoiceIn *pa = (PAVoiceIn *) hw;
568 
569     if (pa->stream) {
570         qpa_simple_disconnect(pa->g->conn, pa->stream);
571         pa->stream = NULL;
572     }
573 }
574 
575 static void qpa_volume_out(HWVoiceOut *hw, Volume *vol)
576 {
577     PAVoiceOut *pa = (PAVoiceOut *) hw;
578     pa_operation *op;
579     pa_cvolume v;
580     PAConnection *c = pa->g->conn;
581     int i;
582 
583 #ifdef PA_CHECK_VERSION    /* macro is present in 0.9.16+ */
584     pa_cvolume_init (&v);  /* function is present in 0.9.13+ */
585 #endif
586 
587     v.channels = vol->channels;
588     for (i = 0; i < vol->channels; ++i) {
589         v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255;
590     }
591 
592     pa_threaded_mainloop_lock(c->mainloop);
593 
594     op = pa_context_set_sink_input_volume(c->context,
595                                           pa_stream_get_index(pa->stream),
596                                           &v, NULL, NULL);
597     if (!op) {
598         qpa_logerr(pa_context_errno(c->context),
599                    "set_sink_input_volume() failed\n");
600     } else {
601         pa_operation_unref(op);
602     }
603 
604     op = pa_context_set_sink_input_mute(c->context,
605                                         pa_stream_get_index(pa->stream),
606                                         vol->mute, NULL, NULL);
607     if (!op) {
608         qpa_logerr(pa_context_errno(c->context),
609                    "set_sink_input_mute() failed\n");
610     } else {
611         pa_operation_unref(op);
612     }
613 
614     pa_threaded_mainloop_unlock(c->mainloop);
615 }
616 
617 static void qpa_volume_in(HWVoiceIn *hw, Volume *vol)
618 {
619     PAVoiceIn *pa = (PAVoiceIn *) hw;
620     pa_operation *op;
621     pa_cvolume v;
622     PAConnection *c = pa->g->conn;
623     int i;
624 
625 #ifdef PA_CHECK_VERSION
626     pa_cvolume_init (&v);
627 #endif
628 
629     v.channels = vol->channels;
630     for (i = 0; i < vol->channels; ++i) {
631         v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255;
632     }
633 
634     pa_threaded_mainloop_lock(c->mainloop);
635 
636     op = pa_context_set_source_output_volume(c->context,
637         pa_stream_get_index(pa->stream),
638         &v, NULL, NULL);
639     if (!op) {
640         qpa_logerr(pa_context_errno(c->context),
641                    "set_source_output_volume() failed\n");
642     } else {
643         pa_operation_unref(op);
644     }
645 
646     op = pa_context_set_source_output_mute(c->context,
647         pa_stream_get_index(pa->stream),
648         vol->mute, NULL, NULL);
649     if (!op) {
650         qpa_logerr(pa_context_errno(c->context),
651                    "set_source_output_mute() failed\n");
652     } else {
653         pa_operation_unref(op);
654     }
655 
656     pa_threaded_mainloop_unlock(c->mainloop);
657 }
658 
659 static int qpa_validate_per_direction_opts(Audiodev *dev,
660                                            AudiodevPaPerDirectionOptions *pdo)
661 {
662     if (!pdo->has_buffer_length) {
663         pdo->has_buffer_length = true;
664         pdo->buffer_length = 46440;
665     }
666     if (!pdo->has_latency) {
667         pdo->has_latency = true;
668         pdo->latency = 15000;
669     }
670     return 1;
671 }
672 
673 /* common */
674 static void *qpa_conn_init(const char *server)
675 {
676     const char *vm_name;
677     PAConnection *c = g_malloc0(sizeof(PAConnection));
678     QTAILQ_INSERT_TAIL(&pa_conns, c, list);
679 
680     c->mainloop = pa_threaded_mainloop_new();
681     if (!c->mainloop) {
682         goto fail;
683     }
684 
685     vm_name = qemu_get_vm_name();
686     c->context = pa_context_new(pa_threaded_mainloop_get_api(c->mainloop),
687                                 vm_name ? vm_name : "qemu");
688     if (!c->context) {
689         goto fail;
690     }
691 
692     pa_context_set_state_callback(c->context, context_state_cb, c);
693 
694     if (pa_context_connect(c->context, server, 0, NULL) < 0) {
695         qpa_logerr(pa_context_errno(c->context),
696                    "pa_context_connect() failed\n");
697         goto fail;
698     }
699 
700     pa_threaded_mainloop_lock(c->mainloop);
701 
702     if (pa_threaded_mainloop_start(c->mainloop) < 0) {
703         goto unlock_and_fail;
704     }
705 
706     for (;;) {
707         pa_context_state_t state;
708 
709         state = pa_context_get_state(c->context);
710 
711         if (state == PA_CONTEXT_READY) {
712             break;
713         }
714 
715         if (!PA_CONTEXT_IS_GOOD(state)) {
716             qpa_logerr(pa_context_errno(c->context),
717                        "Wrong context state\n");
718             goto unlock_and_fail;
719         }
720 
721         /* Wait until the context is ready */
722         pa_threaded_mainloop_wait(c->mainloop);
723     }
724 
725     pa_threaded_mainloop_unlock(c->mainloop);
726     return c;
727 
728 unlock_and_fail:
729     pa_threaded_mainloop_unlock(c->mainloop);
730 fail:
731     AUD_log (AUDIO_CAP, "Failed to initialize PA context");
732     qpa_conn_fini(c);
733     return NULL;
734 }
735 
736 static void *qpa_audio_init(Audiodev *dev)
737 {
738     paaudio *g;
739     AudiodevPaOptions *popts = &dev->u.pa;
740     const char *server;
741     PAConnection *c;
742 
743     assert(dev->driver == AUDIODEV_DRIVER_PA);
744 
745     if (!popts->has_server) {
746         char pidfile[64];
747         char *runtime;
748         struct stat st;
749 
750         runtime = getenv("XDG_RUNTIME_DIR");
751         if (!runtime) {
752             return NULL;
753         }
754         snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
755         if (stat(pidfile, &st) != 0) {
756             return NULL;
757         }
758     }
759 
760     if (!qpa_validate_per_direction_opts(dev, popts->in)) {
761         return NULL;
762     }
763     if (!qpa_validate_per_direction_opts(dev, popts->out)) {
764         return NULL;
765     }
766 
767     g = g_malloc0(sizeof(paaudio));
768     server = popts->has_server ? popts->server : NULL;
769 
770     g->dev = dev;
771 
772     QTAILQ_FOREACH(c, &pa_conns, list) {
773         if (server == NULL || c->server == NULL ?
774             server == c->server :
775             strcmp(server, c->server) == 0) {
776             g->conn = c;
777             break;
778         }
779     }
780     if (!g->conn) {
781         g->conn = qpa_conn_init(server);
782     }
783     if (!g->conn) {
784         g_free(g);
785         return NULL;
786     }
787 
788     ++g->conn->refcount;
789     return g;
790 }
791 
792 static void qpa_conn_fini(PAConnection *c)
793 {
794     if (c->mainloop) {
795         pa_threaded_mainloop_stop(c->mainloop);
796     }
797 
798     if (c->context) {
799         pa_context_disconnect(c->context);
800         pa_context_unref(c->context);
801     }
802 
803     if (c->mainloop) {
804         pa_threaded_mainloop_free(c->mainloop);
805     }
806 
807     QTAILQ_REMOVE(&pa_conns, c, list);
808     g_free(c);
809 }
810 
811 static void qpa_audio_fini (void *opaque)
812 {
813     paaudio *g = opaque;
814     PAConnection *c = g->conn;
815 
816     if (--c->refcount == 0) {
817         qpa_conn_fini(c);
818     }
819 
820     g_free(g);
821 }
822 
823 static struct audio_pcm_ops qpa_pcm_ops = {
824     .init_out = qpa_init_out,
825     .fini_out = qpa_fini_out,
826     .write    = qpa_write,
827     .get_buffer_out = qpa_get_buffer_out,
828     .put_buffer_out = qpa_write, /* pa handles it */
829     .volume_out = qpa_volume_out,
830 
831     .init_in  = qpa_init_in,
832     .fini_in  = qpa_fini_in,
833     .read     = qpa_read,
834     .get_buffer_in = qpa_get_buffer_in,
835     .put_buffer_in = qpa_put_buffer_in,
836     .volume_in = qpa_volume_in
837 };
838 
839 static struct audio_driver pa_audio_driver = {
840     .name           = "pa",
841     .descr          = "http://www.pulseaudio.org/",
842     .init           = qpa_audio_init,
843     .fini           = qpa_audio_fini,
844     .pcm_ops        = &qpa_pcm_ops,
845     .can_be_default = 1,
846     .max_voices_out = INT_MAX,
847     .max_voices_in  = INT_MAX,
848     .voice_size_out = sizeof (PAVoiceOut),
849     .voice_size_in  = sizeof (PAVoiceIn),
850 };
851 
852 static void register_audio_pa(void)
853 {
854     audio_driver_register(&pa_audio_driver);
855 }
856 type_init(register_audio_pa);
857