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