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