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