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 /* 553 * qemu audio tick runs at 100 Hz (by default), so processing 554 * data chunks worth 10 ms of sound should be a good fit. 555 */ 556 ba.tlength = pa_usec_to_bytes (10 * 1000, &ss); 557 ba.minreq = pa_usec_to_bytes (5 * 1000, &ss); 558 ba.maxlength = -1; 559 ba.prebuf = -1; 560 561 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 562 563 pa->stream = qpa_simple_new ( 564 g, 565 "qemu", 566 PA_STREAM_PLAYBACK, 567 ppdo->has_name ? ppdo->name : NULL, 568 &ss, 569 NULL, /* channel map */ 570 &ba, /* buffering attributes */ 571 &error 572 ); 573 if (!pa->stream) { 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); 579 hw->samples = pa->samples = audio_buffer_samples( 580 qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440); 581 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); 582 pa->rpos = hw->rpos; 583 if (!pa->pcm_buf) { 584 dolog ("Could not allocate buffer (%d bytes)\n", 585 hw->samples << hw->info.shift); 586 goto fail2; 587 } 588 589 if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) { 590 goto fail3; 591 } 592 593 return 0; 594 595 fail3: 596 g_free (pa->pcm_buf); 597 pa->pcm_buf = NULL; 598 fail2: 599 if (pa->stream) { 600 pa_stream_unref (pa->stream); 601 pa->stream = NULL; 602 } 603 fail1: 604 return -1; 605 } 606 607 static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 608 { 609 int error; 610 pa_sample_spec ss; 611 struct audsettings obt_as = *as; 612 PAVoiceIn *pa = (PAVoiceIn *) hw; 613 paaudio *g = pa->g = drv_opaque; 614 AudiodevPaOptions *popts = &g->dev->u.pa; 615 AudiodevPaPerDirectionOptions *ppdo = popts->in; 616 617 ss.format = audfmt_to_pa (as->fmt, as->endianness); 618 ss.channels = as->nchannels; 619 ss.rate = as->freq; 620 621 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 622 623 pa->stream = qpa_simple_new ( 624 g, 625 "qemu", 626 PA_STREAM_RECORD, 627 ppdo->has_name ? ppdo->name : NULL, 628 &ss, 629 NULL, /* channel map */ 630 NULL, /* buffering attributes */ 631 &error 632 ); 633 if (!pa->stream) { 634 qpa_logerr (error, "pa_simple_new for capture failed\n"); 635 goto fail1; 636 } 637 638 audio_pcm_init_info (&hw->info, &obt_as); 639 hw->samples = pa->samples = audio_buffer_samples( 640 qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440); 641 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); 642 pa->wpos = hw->wpos; 643 if (!pa->pcm_buf) { 644 dolog ("Could not allocate buffer (%d bytes)\n", 645 hw->samples << hw->info.shift); 646 goto fail2; 647 } 648 649 if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) { 650 goto fail3; 651 } 652 653 return 0; 654 655 fail3: 656 g_free (pa->pcm_buf); 657 pa->pcm_buf = NULL; 658 fail2: 659 if (pa->stream) { 660 pa_stream_unref (pa->stream); 661 pa->stream = NULL; 662 } 663 fail1: 664 return -1; 665 } 666 667 static void qpa_fini_out (HWVoiceOut *hw) 668 { 669 void *ret; 670 PAVoiceOut *pa = (PAVoiceOut *) hw; 671 672 audio_pt_lock(&pa->pt, __func__); 673 pa->done = 1; 674 audio_pt_unlock_and_signal(&pa->pt, __func__); 675 audio_pt_join(&pa->pt, &ret, __func__); 676 677 if (pa->stream) { 678 pa_stream_unref (pa->stream); 679 pa->stream = NULL; 680 } 681 682 audio_pt_fini(&pa->pt, __func__); 683 g_free (pa->pcm_buf); 684 pa->pcm_buf = NULL; 685 } 686 687 static void qpa_fini_in (HWVoiceIn *hw) 688 { 689 void *ret; 690 PAVoiceIn *pa = (PAVoiceIn *) hw; 691 692 audio_pt_lock(&pa->pt, __func__); 693 pa->done = 1; 694 audio_pt_unlock_and_signal(&pa->pt, __func__); 695 audio_pt_join(&pa->pt, &ret, __func__); 696 697 if (pa->stream) { 698 pa_stream_unref (pa->stream); 699 pa->stream = NULL; 700 } 701 702 audio_pt_fini(&pa->pt, __func__); 703 g_free (pa->pcm_buf); 704 pa->pcm_buf = NULL; 705 } 706 707 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) 708 { 709 PAVoiceOut *pa = (PAVoiceOut *) hw; 710 pa_operation *op; 711 pa_cvolume v; 712 paaudio *g = pa->g; 713 714 #ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */ 715 pa_cvolume_init (&v); /* function is present in 0.9.13+ */ 716 #endif 717 718 switch (cmd) { 719 case VOICE_VOLUME: 720 { 721 SWVoiceOut *sw; 722 va_list ap; 723 724 va_start (ap, cmd); 725 sw = va_arg (ap, SWVoiceOut *); 726 va_end (ap); 727 728 v.channels = 2; 729 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; 730 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; 731 732 pa_threaded_mainloop_lock (g->mainloop); 733 734 op = pa_context_set_sink_input_volume (g->context, 735 pa_stream_get_index (pa->stream), 736 &v, NULL, NULL); 737 if (!op) 738 qpa_logerr (pa_context_errno (g->context), 739 "set_sink_input_volume() failed\n"); 740 else 741 pa_operation_unref (op); 742 743 op = pa_context_set_sink_input_mute (g->context, 744 pa_stream_get_index (pa->stream), 745 sw->vol.mute, NULL, NULL); 746 if (!op) { 747 qpa_logerr (pa_context_errno (g->context), 748 "set_sink_input_mute() failed\n"); 749 } else { 750 pa_operation_unref (op); 751 } 752 753 pa_threaded_mainloop_unlock (g->mainloop); 754 } 755 } 756 return 0; 757 } 758 759 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) 760 { 761 PAVoiceIn *pa = (PAVoiceIn *) hw; 762 pa_operation *op; 763 pa_cvolume v; 764 paaudio *g = pa->g; 765 766 #ifdef PA_CHECK_VERSION 767 pa_cvolume_init (&v); 768 #endif 769 770 switch (cmd) { 771 case VOICE_VOLUME: 772 { 773 SWVoiceIn *sw; 774 va_list ap; 775 776 va_start (ap, cmd); 777 sw = va_arg (ap, SWVoiceIn *); 778 va_end (ap); 779 780 v.channels = 2; 781 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; 782 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; 783 784 pa_threaded_mainloop_lock (g->mainloop); 785 786 op = pa_context_set_source_output_volume (g->context, 787 pa_stream_get_index (pa->stream), 788 &v, NULL, NULL); 789 if (!op) { 790 qpa_logerr (pa_context_errno (g->context), 791 "set_source_output_volume() failed\n"); 792 } else { 793 pa_operation_unref(op); 794 } 795 796 op = pa_context_set_source_output_mute (g->context, 797 pa_stream_get_index (pa->stream), 798 sw->vol.mute, NULL, NULL); 799 if (!op) { 800 qpa_logerr (pa_context_errno (g->context), 801 "set_source_output_mute() failed\n"); 802 } else { 803 pa_operation_unref (op); 804 } 805 806 pa_threaded_mainloop_unlock (g->mainloop); 807 } 808 } 809 return 0; 810 } 811 812 /* common */ 813 static void *qpa_audio_init(Audiodev *dev) 814 { 815 paaudio *g; 816 AudiodevPaOptions *popts = &dev->u.pa; 817 const char *server; 818 819 if (!popts->has_server) { 820 char pidfile[64]; 821 char *runtime; 822 struct stat st; 823 824 runtime = getenv("XDG_RUNTIME_DIR"); 825 if (!runtime) { 826 return NULL; 827 } 828 snprintf(pidfile, sizeof(pidfile), "%s/pulse/pid", runtime); 829 if (stat(pidfile, &st) != 0) { 830 return NULL; 831 } 832 } 833 834 assert(dev->driver == AUDIODEV_DRIVER_PA); 835 836 g = g_malloc(sizeof(paaudio)); 837 server = popts->has_server ? popts->server : NULL; 838 839 g->dev = dev; 840 g->mainloop = NULL; 841 g->context = NULL; 842 843 g->mainloop = pa_threaded_mainloop_new (); 844 if (!g->mainloop) { 845 goto fail; 846 } 847 848 g->context = pa_context_new (pa_threaded_mainloop_get_api (g->mainloop), 849 server); 850 if (!g->context) { 851 goto fail; 852 } 853 854 pa_context_set_state_callback (g->context, context_state_cb, g); 855 856 if (pa_context_connect(g->context, server, 0, NULL) < 0) { 857 qpa_logerr (pa_context_errno (g->context), 858 "pa_context_connect() failed\n"); 859 goto fail; 860 } 861 862 pa_threaded_mainloop_lock (g->mainloop); 863 864 if (pa_threaded_mainloop_start (g->mainloop) < 0) { 865 goto unlock_and_fail; 866 } 867 868 for (;;) { 869 pa_context_state_t state; 870 871 state = pa_context_get_state (g->context); 872 873 if (state == PA_CONTEXT_READY) { 874 break; 875 } 876 877 if (!PA_CONTEXT_IS_GOOD (state)) { 878 qpa_logerr (pa_context_errno (g->context), 879 "Wrong context state\n"); 880 goto unlock_and_fail; 881 } 882 883 /* Wait until the context is ready */ 884 pa_threaded_mainloop_wait (g->mainloop); 885 } 886 887 pa_threaded_mainloop_unlock (g->mainloop); 888 889 return g; 890 891 unlock_and_fail: 892 pa_threaded_mainloop_unlock (g->mainloop); 893 fail: 894 AUD_log (AUDIO_CAP, "Failed to initialize PA context"); 895 qpa_audio_fini(g); 896 return NULL; 897 } 898 899 static void qpa_audio_fini (void *opaque) 900 { 901 paaudio *g = opaque; 902 903 if (g->mainloop) { 904 pa_threaded_mainloop_stop (g->mainloop); 905 } 906 907 if (g->context) { 908 pa_context_disconnect (g->context); 909 pa_context_unref (g->context); 910 } 911 912 if (g->mainloop) { 913 pa_threaded_mainloop_free (g->mainloop); 914 } 915 916 g_free(g); 917 } 918 919 static struct audio_pcm_ops qpa_pcm_ops = { 920 .init_out = qpa_init_out, 921 .fini_out = qpa_fini_out, 922 .run_out = qpa_run_out, 923 .write = qpa_write, 924 .ctl_out = qpa_ctl_out, 925 926 .init_in = qpa_init_in, 927 .fini_in = qpa_fini_in, 928 .run_in = qpa_run_in, 929 .read = qpa_read, 930 .ctl_in = qpa_ctl_in 931 }; 932 933 static struct audio_driver pa_audio_driver = { 934 .name = "pa", 935 .descr = "http://www.pulseaudio.org/", 936 .init = qpa_audio_init, 937 .fini = qpa_audio_fini, 938 .pcm_ops = &qpa_pcm_ops, 939 .can_be_default = 1, 940 .max_voices_out = INT_MAX, 941 .max_voices_in = INT_MAX, 942 .voice_size_out = sizeof (PAVoiceOut), 943 .voice_size_in = sizeof (PAVoiceIn), 944 .ctl_caps = VOICE_VOLUME_CAP 945 }; 946 947 static void register_audio_pa(void) 948 { 949 audio_driver_register(&pa_audio_driver); 950 } 951 type_init(register_audio_pa); 952