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