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