]> git.proxmox.com Git - mirror_qemu.git/blame - audio/paaudio.c
paaudio: do not move stream when sink/source name is specified
[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;
33 int done;
34 int live;
35 int decr;
36 int rpos;
ea9ebc2c 37 pa_stream *stream;
b8e59f18 38 void *pcm_buf;
39 struct audio_pt pt;
9a644c4b 40 paaudio *g;
2c324b28 41 int samples;
b8e59f18 42} PAVoiceOut;
43
44typedef struct {
45 HWVoiceIn hw;
46 int done;
47 int dead;
48 int incr;
49 int 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;
2c324b28 56 int 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 (;;) {
222 int decr, to_mix, rpos;
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
2c324b28 238 decr = to_mix = audio_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;
247 int chunk = audio_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
bdff253c 276static int qpa_run_out (HWVoiceOut *hw, int live)
b8e59f18 277{
bdff253c 278 int decr;
b8e59f18 279 PAVoiceOut *pa = (PAVoiceOut *) hw;
280
470bcabd 281 if (audio_pt_lock(&pa->pt, __func__)) {
b8e59f18 282 return 0;
283 }
284
b8e59f18 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) {
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
298static int qpa_write (SWVoiceOut *sw, void *buf, int len)
299{
300 return audio_pcm_sw_write (sw, buf, len);
301}
302
303/* capture */
304static void *qpa_thread_in (void *arg)
305{
306 PAVoiceIn *pa = arg;
307 HWVoiceIn *hw = &pa->hw;
b8e59f18 308
470bcabd 309 if (audio_pt_lock(&pa->pt, __func__)) {
b8e59f18 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
6315633b 321 if (pa->dead > 0) {
b8e59f18 322 break;
323 }
324
470bcabd 325 if (audio_pt_wait(&pa->pt, __func__)) {
b8e59f18 326 goto exit;
327 }
328 }
329
2c324b28 330 incr = to_grab = audio_MIN(pa->dead, pa->samples >> 5);
6315633b 331 wpos = pa->wpos;
b8e59f18 332
470bcabd 333 if (audio_pt_unlock(&pa->pt, __func__)) {
b8e59f18 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
ea9ebc2c
MAL
342 if (qpa_simple_read (pa, buf,
343 chunk << hw->info.shift, &error) < 0) {
b8e59f18 344 qpa_logerr (error, "pa_simple_read failed\n");
345 return NULL;
346 }
347
00e07679 348 hw->conv (hw->conv_buf + wpos, buf, chunk);
b8e59f18 349 wpos = (wpos + chunk) % hw->samples;
350 to_grab -= chunk;
351 }
352
470bcabd 353 if (audio_pt_lock(&pa->pt, __func__)) {
b8e59f18 354 return NULL;
355 }
356
357 pa->wpos = wpos;
358 pa->dead -= incr;
359 pa->incr += incr;
360 }
361
362 exit:
470bcabd 363 audio_pt_unlock(&pa->pt, __func__);
b8e59f18 364 return NULL;
365}
366
367static int qpa_run_in (HWVoiceIn *hw)
368{
369 int live, incr, dead;
370 PAVoiceIn *pa = (PAVoiceIn *) hw;
371
470bcabd 372 if (audio_pt_lock(&pa->pt, __func__)) {
b8e59f18 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) {
470bcabd 383 audio_pt_unlock_and_signal(&pa->pt, __func__);
b8e59f18 384 }
385 else {
470bcabd 386 audio_pt_unlock(&pa->pt, __func__);
b8e59f18 387 }
388 return incr;
389}
390
391static int qpa_read (SWVoiceIn *sw, void *buf, int len)
392{
393 return audio_pcm_sw_read (sw, buf, len);
394}
395
85bc5852 396static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness)
b8e59f18 397{
398 int format;
399
400 switch (afmt) {
85bc5852
KZ
401 case AUDIO_FORMAT_S8:
402 case AUDIO_FORMAT_U8:
b8e59f18 403 format = PA_SAMPLE_U8;
404 break;
85bc5852
KZ
405 case AUDIO_FORMAT_S16:
406 case AUDIO_FORMAT_U16:
b8e59f18 407 format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
408 break;
85bc5852
KZ
409 case AUDIO_FORMAT_S32:
410 case AUDIO_FORMAT_U32:
b8e59f18 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
85bc5852 421static AudioFormat pa_to_audfmt (pa_sample_format_t fmt, int *endianness)
b8e59f18 422{
423 switch (fmt) {
424 case PA_SAMPLE_U8:
85bc5852 425 return AUDIO_FORMAT_U8;
b8e59f18 426 case PA_SAMPLE_S16BE:
427 *endianness = 1;
85bc5852 428 return AUDIO_FORMAT_S16;
b8e59f18 429 case PA_SAMPLE_S16LE:
430 *endianness = 0;
85bc5852 431 return AUDIO_FORMAT_S16;
b8e59f18 432 case PA_SAMPLE_S32BE:
433 *endianness = 1;
85bc5852 434 return AUDIO_FORMAT_S32;
b8e59f18 435 case PA_SAMPLE_S32LE:
436 *endianness = 0;
85bc5852 437 return AUDIO_FORMAT_S32;
b8e59f18 438 default:
439 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt);
85bc5852 440 return AUDIO_FORMAT_U8;
b8e59f18 441 }
442}
443
ea9ebc2c
MAL
444static void context_state_cb (pa_context *c, void *userdata)
445{
9d34e6d8 446 PAConnection *conn = userdata;
ea9ebc2c
MAL
447
448 switch (pa_context_get_state(c)) {
449 case PA_CONTEXT_READY:
450 case PA_CONTEXT_TERMINATED:
451 case PA_CONTEXT_FAILED:
9d34e6d8 452 pa_threaded_mainloop_signal(conn->mainloop, 0);
ea9ebc2c
MAL
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
463static void stream_state_cb (pa_stream *s, void * userdata)
464{
9d34e6d8 465 PAConnection *c = userdata;
ea9ebc2c
MAL
466
467 switch (pa_stream_get_state (s)) {
468
469 case PA_STREAM_READY:
470 case PA_STREAM_FAILED:
471 case PA_STREAM_TERMINATED:
9d34e6d8 472 pa_threaded_mainloop_signal(c->mainloop, 0);
ea9ebc2c
MAL
473 break;
474
475 case PA_STREAM_UNCONNECTED:
476 case PA_STREAM_CREATING:
477 break;
478 }
479}
480
481static void stream_request_cb (pa_stream *s, size_t length, void *userdata)
482{
9d34e6d8 483 PAConnection *c = userdata;
ea9ebc2c 484
9d34e6d8 485 pa_threaded_mainloop_signal(c->mainloop, 0);
ea9ebc2c
MAL
486}
487
488static pa_stream *qpa_simple_new (
9d34e6d8 489 PAConnection *c,
ea9ebc2c
MAL
490 const char *name,
491 pa_stream_direction_t dir,
492 const char *dev,
ea9ebc2c
MAL
493 const pa_sample_spec *ss,
494 const pa_channel_map *map,
495 const pa_buffer_attr *attr,
496 int *rerror)
497{
ea9ebc2c
MAL
498 int r;
499 pa_stream *stream;
9d34e6d8 500 pa_stream_flags_t flags;
ea9ebc2c 501
9d34e6d8 502 pa_threaded_mainloop_lock(c->mainloop);
ea9ebc2c 503
9d34e6d8 504 stream = pa_stream_new(c->context, name, ss, map);
ea9ebc2c
MAL
505 if (!stream) {
506 goto fail;
507 }
508
9d34e6d8
KZ
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);
ea9ebc2c 512
9d34e6d8
KZ
513 flags =
514 PA_STREAM_INTERPOLATE_TIMING
8f473dd1 515#ifdef PA_STREAM_ADJUST_LATENCY
9d34e6d8 516 | PA_STREAM_ADJUST_LATENCY
8f473dd1 517#endif
9d34e6d8
KZ
518 | PA_STREAM_AUTO_TIMING_UPDATE;
519
8a435f74
KZ
520 if (dev) {
521 /* don't move the stream if the user specified a sink/source */
522 flags |= PA_STREAM_DONT_MOVE;
523 }
524
9d34e6d8
KZ
525 if (dir == PA_STREAM_PLAYBACK) {
526 r = pa_stream_connect_playback(stream, dev, attr, flags, NULL, NULL);
ea9ebc2c 527 } else {
9d34e6d8 528 r = pa_stream_connect_record(stream, dev, attr, flags);
ea9ebc2c
MAL
529 }
530
531 if (r < 0) {
532 goto fail;
533 }
534
9d34e6d8 535 pa_threaded_mainloop_unlock(c->mainloop);
ea9ebc2c
MAL
536
537 return stream;
538
539fail:
9d34e6d8 540 pa_threaded_mainloop_unlock(c->mainloop);
ea9ebc2c
MAL
541
542 if (stream) {
543 pa_stream_unref (stream);
544 }
545
9d34e6d8 546 *rerror = pa_context_errno(c->context);
ea9ebc2c
MAL
547
548 return NULL;
549}
550
5706db1d
KZ
551static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
552 void *drv_opaque)
b8e59f18 553{
554 int error;
9a644c4b
KZ
555 pa_sample_spec ss;
556 pa_buffer_attr ba;
1ea879e5 557 struct audsettings obt_as = *as;
b8e59f18 558 PAVoiceOut *pa = (PAVoiceOut *) hw;
9a644c4b 559 paaudio *g = pa->g = drv_opaque;
2c324b28
KZ
560 AudiodevPaOptions *popts = &g->dev->u.pa;
561 AudiodevPaPerDirectionOptions *ppdo = popts->out;
9d34e6d8 562 PAConnection *c = g->conn;
b8e59f18 563
564 ss.format = audfmt_to_pa (as->fmt, as->endianness);
565 ss.channels = as->nchannels;
566 ss.rate = as->freq;
567
f6142777
MS
568 ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
569 ba.minreq = -1;
e6d16fa4
GH
570 ba.maxlength = -1;
571 ba.prebuf = -1;
572
b8e59f18 573 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
574
ea9ebc2c 575 pa->stream = qpa_simple_new (
9d34e6d8 576 c,
b8e59f18 577 "qemu",
578 PA_STREAM_PLAYBACK,
2c324b28 579 ppdo->has_name ? ppdo->name : NULL,
b8e59f18 580 &ss,
581 NULL, /* channel map */
e6d16fa4 582 &ba, /* buffering attributes */
b8e59f18 583 &error
584 );
ea9ebc2c 585 if (!pa->stream) {
b8e59f18 586 qpa_logerr (error, "pa_simple_new for playback failed\n");
587 goto fail1;
588 }
589
590 audio_pcm_init_info (&hw->info, &obt_as);
2c324b28 591 hw->samples = pa->samples = audio_buffer_samples(
baea032e
MS
592 qapi_AudiodevPaPerDirectionOptions_base(ppdo),
593 &obt_as, ppdo->buffer_length);
470bcabd 594 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
6315633b 595 pa->rpos = hw->rpos;
b8e59f18 596 if (!pa->pcm_buf) {
597 dolog ("Could not allocate buffer (%d bytes)\n",
598 hw->samples << hw->info.shift);
599 goto fail2;
600 }
601
470bcabd 602 if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) {
b8e59f18 603 goto fail3;
604 }
605
606 return 0;
607
608 fail3:
7267c094 609 g_free (pa->pcm_buf);
b8e59f18 610 pa->pcm_buf = NULL;
611 fail2:
ea9ebc2c
MAL
612 if (pa->stream) {
613 pa_stream_unref (pa->stream);
614 pa->stream = NULL;
615 }
b8e59f18 616 fail1:
617 return -1;
618}
619
5706db1d 620static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
b8e59f18 621{
622 int error;
9a644c4b 623 pa_sample_spec ss;
ade10301 624 pa_buffer_attr ba;
1ea879e5 625 struct audsettings obt_as = *as;
b8e59f18 626 PAVoiceIn *pa = (PAVoiceIn *) hw;
9a644c4b 627 paaudio *g = pa->g = drv_opaque;
2c324b28
KZ
628 AudiodevPaOptions *popts = &g->dev->u.pa;
629 AudiodevPaPerDirectionOptions *ppdo = popts->in;
9d34e6d8 630 PAConnection *c = g->conn;
b8e59f18 631
632 ss.format = audfmt_to_pa (as->fmt, as->endianness);
633 ss.channels = as->nchannels;
634 ss.rate = as->freq;
635
ade10301 636 ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
58c15e52 637 ba.maxlength = pa_usec_to_bytes(ppdo->latency * 2, &ss);
ade10301
MS
638 ba.minreq = -1;
639 ba.prebuf = -1;
640
b8e59f18 641 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
642
ea9ebc2c 643 pa->stream = qpa_simple_new (
9d34e6d8 644 c,
b8e59f18 645 "qemu",
646 PA_STREAM_RECORD,
2c324b28 647 ppdo->has_name ? ppdo->name : NULL,
b8e59f18 648 &ss,
649 NULL, /* channel map */
ade10301 650 &ba, /* buffering attributes */
b8e59f18 651 &error
652 );
ea9ebc2c 653 if (!pa->stream) {
b8e59f18 654 qpa_logerr (error, "pa_simple_new for capture failed\n");
655 goto fail1;
656 }
657
658 audio_pcm_init_info (&hw->info, &obt_as);
2c324b28 659 hw->samples = pa->samples = audio_buffer_samples(
baea032e
MS
660 qapi_AudiodevPaPerDirectionOptions_base(ppdo),
661 &obt_as, ppdo->buffer_length);
470bcabd 662 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
6315633b 663 pa->wpos = hw->wpos;
b8e59f18 664 if (!pa->pcm_buf) {
665 dolog ("Could not allocate buffer (%d bytes)\n",
666 hw->samples << hw->info.shift);
667 goto fail2;
668 }
669
470bcabd 670 if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) {
b8e59f18 671 goto fail3;
672 }
673
674 return 0;
675
676 fail3:
7267c094 677 g_free (pa->pcm_buf);
b8e59f18 678 pa->pcm_buf = NULL;
679 fail2:
ea9ebc2c
MAL
680 if (pa->stream) {
681 pa_stream_unref (pa->stream);
682 pa->stream = NULL;
683 }
b8e59f18 684 fail1:
685 return -1;
686}
687
688static void qpa_fini_out (HWVoiceOut *hw)
689{
690 void *ret;
691 PAVoiceOut *pa = (PAVoiceOut *) hw;
692
470bcabd 693 audio_pt_lock(&pa->pt, __func__);
b8e59f18 694 pa->done = 1;
470bcabd
AF
695 audio_pt_unlock_and_signal(&pa->pt, __func__);
696 audio_pt_join(&pa->pt, &ret, __func__);
b8e59f18 697
ea9ebc2c
MAL
698 if (pa->stream) {
699 pa_stream_unref (pa->stream);
700 pa->stream = NULL;
b8e59f18 701 }
702
470bcabd 703 audio_pt_fini(&pa->pt, __func__);
7267c094 704 g_free (pa->pcm_buf);
b8e59f18 705 pa->pcm_buf = NULL;
706}
707
708static void qpa_fini_in (HWVoiceIn *hw)
709{
710 void *ret;
711 PAVoiceIn *pa = (PAVoiceIn *) hw;
712
470bcabd 713 audio_pt_lock(&pa->pt, __func__);
b8e59f18 714 pa->done = 1;
470bcabd
AF
715 audio_pt_unlock_and_signal(&pa->pt, __func__);
716 audio_pt_join(&pa->pt, &ret, __func__);
b8e59f18 717
ea9ebc2c
MAL
718 if (pa->stream) {
719 pa_stream_unref (pa->stream);
720 pa->stream = NULL;
b8e59f18 721 }
722
470bcabd 723 audio_pt_fini(&pa->pt, __func__);
7267c094 724 g_free (pa->pcm_buf);
b8e59f18 725 pa->pcm_buf = NULL;
726}
727
728static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...)
729{
6e7a7f3d
MAL
730 PAVoiceOut *pa = (PAVoiceOut *) hw;
731 pa_operation *op;
732 pa_cvolume v;
9d34e6d8 733 PAConnection *c = pa->g->conn;
6e7a7f3d 734
8f473dd1
GH
735#ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */
736 pa_cvolume_init (&v); /* function is present in 0.9.13+ */
737#endif
6e7a7f3d
MAL
738
739 switch (cmd) {
740 case VOICE_VOLUME:
741 {
742 SWVoiceOut *sw;
743 va_list ap;
744
745 va_start (ap, cmd);
746 sw = va_arg (ap, SWVoiceOut *);
747 va_end (ap);
748
749 v.channels = 2;
750 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
751 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
752
9d34e6d8 753 pa_threaded_mainloop_lock(c->mainloop);
6e7a7f3d 754
9d34e6d8 755 op = pa_context_set_sink_input_volume(c->context,
6e7a7f3d
MAL
756 pa_stream_get_index (pa->stream),
757 &v, NULL, NULL);
9d34e6d8
KZ
758 if (!op) {
759 qpa_logerr(pa_context_errno(c->context),
760 "set_sink_input_volume() failed\n");
761 } else {
762 pa_operation_unref(op);
763 }
6e7a7f3d 764
9d34e6d8 765 op = pa_context_set_sink_input_mute(c->context,
6e7a7f3d
MAL
766 pa_stream_get_index (pa->stream),
767 sw->vol.mute, NULL, NULL);
768 if (!op) {
9d34e6d8
KZ
769 qpa_logerr(pa_context_errno(c->context),
770 "set_sink_input_mute() failed\n");
6e7a7f3d 771 } else {
9d34e6d8 772 pa_operation_unref(op);
6e7a7f3d
MAL
773 }
774
9d34e6d8 775 pa_threaded_mainloop_unlock(c->mainloop);
6e7a7f3d
MAL
776 }
777 }
b8e59f18 778 return 0;
779}
780
781static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
782{
6e7a7f3d
MAL
783 PAVoiceIn *pa = (PAVoiceIn *) hw;
784 pa_operation *op;
785 pa_cvolume v;
9d34e6d8 786 PAConnection *c = pa->g->conn;
6e7a7f3d 787
8f473dd1 788#ifdef PA_CHECK_VERSION
6e7a7f3d 789 pa_cvolume_init (&v);
8f473dd1 790#endif
6e7a7f3d
MAL
791
792 switch (cmd) {
793 case VOICE_VOLUME:
794 {
795 SWVoiceIn *sw;
796 va_list ap;
797
798 va_start (ap, cmd);
799 sw = va_arg (ap, SWVoiceIn *);
800 va_end (ap);
801
802 v.channels = 2;
803 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX;
804 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX;
805
9d34e6d8 806 pa_threaded_mainloop_lock(c->mainloop);
6e7a7f3d 807
9d34e6d8
KZ
808 op = pa_context_set_source_output_volume(c->context,
809 pa_stream_get_index(pa->stream),
6e7a7f3d
MAL
810 &v, NULL, NULL);
811 if (!op) {
9d34e6d8
KZ
812 qpa_logerr(pa_context_errno(c->context),
813 "set_source_output_volume() failed\n");
6e7a7f3d
MAL
814 } else {
815 pa_operation_unref(op);
816 }
817
9d34e6d8 818 op = pa_context_set_source_output_mute(c->context,
6e7a7f3d
MAL
819 pa_stream_get_index (pa->stream),
820 sw->vol.mute, NULL, NULL);
821 if (!op) {
9d34e6d8
KZ
822 qpa_logerr(pa_context_errno(c->context),
823 "set_source_output_mute() failed\n");
6e7a7f3d
MAL
824 } else {
825 pa_operation_unref (op);
826 }
827
9d34e6d8 828 pa_threaded_mainloop_unlock(c->mainloop);
6e7a7f3d
MAL
829 }
830 }
b8e59f18 831 return 0;
832}
833
baea032e
MS
834static int qpa_validate_per_direction_opts(Audiodev *dev,
835 AudiodevPaPerDirectionOptions *pdo)
836{
837 if (!pdo->has_buffer_length) {
838 pdo->has_buffer_length = true;
839 pdo->buffer_length = 46440;
840 }
f6142777
MS
841 if (!pdo->has_latency) {
842 pdo->has_latency = true;
843 pdo->latency = 15000;
844 }
baea032e
MS
845 return 1;
846}
847
9d34e6d8
KZ
848/* common */
849static void *qpa_conn_init(const char *server)
850{
851 PAConnection *c = g_malloc0(sizeof(PAConnection));
852 QTAILQ_INSERT_TAIL(&pa_conns, c, list);
853
854 c->mainloop = pa_threaded_mainloop_new();
855 if (!c->mainloop) {
856 goto fail;
857 }
858
859 c->context = pa_context_new(pa_threaded_mainloop_get_api(c->mainloop),
860 server);
861 if (!c->context) {
862 goto fail;
863 }
864
865 pa_context_set_state_callback(c->context, context_state_cb, c);
866
867 if (pa_context_connect(c->context, server, 0, NULL) < 0) {
868 qpa_logerr(pa_context_errno(c->context),
869 "pa_context_connect() failed\n");
870 goto fail;
871 }
872
873 pa_threaded_mainloop_lock(c->mainloop);
874
875 if (pa_threaded_mainloop_start(c->mainloop) < 0) {
876 goto unlock_and_fail;
877 }
878
879 for (;;) {
880 pa_context_state_t state;
881
882 state = pa_context_get_state(c->context);
883
884 if (state == PA_CONTEXT_READY) {
885 break;
886 }
887
888 if (!PA_CONTEXT_IS_GOOD(state)) {
889 qpa_logerr(pa_context_errno(c->context),
890 "Wrong context state\n");
891 goto unlock_and_fail;
892 }
893
894 /* Wait until the context is ready */
895 pa_threaded_mainloop_wait(c->mainloop);
896 }
897
898 pa_threaded_mainloop_unlock(c->mainloop);
899 return c;
900
901unlock_and_fail:
902 pa_threaded_mainloop_unlock(c->mainloop);
903fail:
904 AUD_log (AUDIO_CAP, "Failed to initialize PA context");
905 qpa_conn_fini(c);
906 return NULL;
907}
908
71830221 909static void *qpa_audio_init(Audiodev *dev)
b8e59f18 910{
2c324b28
KZ
911 paaudio *g;
912 AudiodevPaOptions *popts = &dev->u.pa;
913 const char *server;
9d34e6d8
KZ
914 PAConnection *c;
915
916 assert(dev->driver == AUDIODEV_DRIVER_PA);
2c324b28
KZ
917
918 if (!popts->has_server) {
d175505b
GH
919 char pidfile[64];
920 char *runtime;
921 struct stat st;
922
923 runtime = getenv("XDG_RUNTIME_DIR");
924 if (!runtime) {
925 return NULL;
926 }
927 snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime);
928 if (stat(pidfile, &st) != 0) {
929 return NULL;
930 }
931 }
932
baea032e 933 if (!qpa_validate_per_direction_opts(dev, popts->in)) {
9d34e6d8 934 return NULL;
baea032e
MS
935 }
936 if (!qpa_validate_per_direction_opts(dev, popts->out)) {
9d34e6d8 937 return NULL;
baea032e
MS
938 }
939
9d34e6d8
KZ
940 g = g_malloc0(sizeof(paaudio));
941 server = popts->has_server ? popts->server : NULL;
942
2c324b28 943 g->dev = dev;
ea9ebc2c 944
9d34e6d8
KZ
945 QTAILQ_FOREACH(c, &pa_conns, list) {
946 if (server == NULL || c->server == NULL ?
947 server == c->server :
948 strcmp(server, c->server) == 0) {
949 g->conn = c;
950 break;
951 }
ea9ebc2c 952 }
9d34e6d8
KZ
953 if (!g->conn) {
954 g->conn = qpa_conn_init(server);
ea9ebc2c 955 }
9d34e6d8
KZ
956 if (!g->conn) {
957 g_free(g);
958 return NULL;
ea9ebc2c
MAL
959 }
960
9d34e6d8
KZ
961 ++g->conn->refcount;
962 return g;
963}
ea9ebc2c 964
9d34e6d8
KZ
965static void qpa_conn_fini(PAConnection *c)
966{
967 if (c->mainloop) {
968 pa_threaded_mainloop_stop(c->mainloop);
ea9ebc2c
MAL
969 }
970
9d34e6d8
KZ
971 if (c->context) {
972 pa_context_disconnect(c->context);
973 pa_context_unref(c->context);
ea9ebc2c
MAL
974 }
975
9d34e6d8
KZ
976 if (c->mainloop) {
977 pa_threaded_mainloop_free(c->mainloop);
978 }
ea9ebc2c 979
9d34e6d8
KZ
980 QTAILQ_REMOVE(&pa_conns, c, list);
981 g_free(c);
b8e59f18 982}
983
984static void qpa_audio_fini (void *opaque)
985{
ea9ebc2c 986 paaudio *g = opaque;
9d34e6d8 987 PAConnection *c = g->conn;
ea9ebc2c 988
9d34e6d8
KZ
989 if (--c->refcount == 0) {
990 qpa_conn_fini(c);
ea9ebc2c
MAL
991 }
992
9a644c4b 993 g_free(g);
b8e59f18 994}
995
35f4b58c 996static struct audio_pcm_ops qpa_pcm_ops = {
1dd3e4d1
JQ
997 .init_out = qpa_init_out,
998 .fini_out = qpa_fini_out,
999 .run_out = qpa_run_out,
1000 .write = qpa_write,
1001 .ctl_out = qpa_ctl_out,
1002
1003 .init_in = qpa_init_in,
1004 .fini_in = qpa_fini_in,
1005 .run_in = qpa_run_in,
1006 .read = qpa_read,
1007 .ctl_in = qpa_ctl_in
b8e59f18 1008};
1009
d3893a39 1010static struct audio_driver pa_audio_driver = {
bee37f32
JQ
1011 .name = "pa",
1012 .descr = "http://www.pulseaudio.org/",
bee37f32
JQ
1013 .init = qpa_audio_init,
1014 .fini = qpa_audio_fini,
1015 .pcm_ops = &qpa_pcm_ops,
1a4ea1e3 1016 .can_be_default = 1,
bee37f32
JQ
1017 .max_voices_out = INT_MAX,
1018 .max_voices_in = INT_MAX,
1019 .voice_size_out = sizeof (PAVoiceOut),
6e7a7f3d
MAL
1020 .voice_size_in = sizeof (PAVoiceIn),
1021 .ctl_caps = VOICE_VOLUME_CAP
b8e59f18 1022};
d3893a39
GH
1023
1024static void register_audio_pa(void)
1025{
1026 audio_driver_register(&pa_audio_driver);
1027}
1028type_init(register_audio_pa);