1 /* public domain */ 2 #include "qemu/osdep.h" 3 #include "qemu-common.h" 4 #include "audio.h" 5 6 #include <pulse/pulseaudio.h> 7 8 #define AUDIO_CAP "pulseaudio" 9 #include "audio_int.h" 10 #include "audio_pt_int.h" 11 12 typedef struct { 13 int samples; 14 char *server; 15 char *sink; 16 char *source; 17 } PAConf; 18 19 typedef struct { 20 PAConf conf; 21 pa_threaded_mainloop *mainloop; 22 pa_context *context; 23 } paaudio; 24 25 typedef struct { 26 HWVoiceOut hw; 27 int done; 28 int live; 29 int decr; 30 int rpos; 31 pa_stream *stream; 32 void *pcm_buf; 33 struct audio_pt pt; 34 paaudio *g; 35 } PAVoiceOut; 36 37 typedef struct { 38 HWVoiceIn hw; 39 int done; 40 int dead; 41 int incr; 42 int wpos; 43 pa_stream *stream; 44 void *pcm_buf; 45 struct audio_pt pt; 46 const void *read_data; 47 size_t read_index, read_length; 48 paaudio *g; 49 } PAVoiceIn; 50 51 static void qpa_audio_fini(void *opaque); 52 53 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...) 54 { 55 va_list ap; 56 57 va_start (ap, fmt); 58 AUD_vlog (AUDIO_CAP, fmt, ap); 59 va_end (ap); 60 61 AUD_log (AUDIO_CAP, "Reason: %s\n", pa_strerror (err)); 62 } 63 64 #ifndef PA_CONTEXT_IS_GOOD 65 static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) 66 { 67 return 68 x == PA_CONTEXT_CONNECTING || 69 x == PA_CONTEXT_AUTHORIZING || 70 x == PA_CONTEXT_SETTING_NAME || 71 x == PA_CONTEXT_READY; 72 } 73 #endif 74 75 #ifndef PA_STREAM_IS_GOOD 76 static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) 77 { 78 return 79 x == PA_STREAM_CREATING || 80 x == PA_STREAM_READY; 81 } 82 #endif 83 84 #define CHECK_SUCCESS_GOTO(c, rerror, expression, label) \ 85 do { \ 86 if (!(expression)) { \ 87 if (rerror) { \ 88 *(rerror) = pa_context_errno ((c)->context); \ 89 } \ 90 goto label; \ 91 } \ 92 } while (0) 93 94 #define CHECK_DEAD_GOTO(c, stream, rerror, label) \ 95 do { \ 96 if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \ 97 !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \ 98 if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \ 99 ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \ 100 if (rerror) { \ 101 *(rerror) = pa_context_errno ((c)->context); \ 102 } \ 103 } else { \ 104 if (rerror) { \ 105 *(rerror) = PA_ERR_BADSTATE; \ 106 } \ 107 } \ 108 goto label; \ 109 } \ 110 } while (0) 111 112 static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) 113 { 114 paaudio *g = p->g; 115 116 pa_threaded_mainloop_lock (g->mainloop); 117 118 CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); 119 120 while (length > 0) { 121 size_t l; 122 123 while (!p->read_data) { 124 int r; 125 126 r = pa_stream_peek (p->stream, &p->read_data, &p->read_length); 127 CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail); 128 129 if (!p->read_data) { 130 pa_threaded_mainloop_wait (g->mainloop); 131 CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); 132 } else { 133 p->read_index = 0; 134 } 135 } 136 137 l = p->read_length < length ? p->read_length : length; 138 memcpy (data, (const uint8_t *) p->read_data+p->read_index, l); 139 140 data = (uint8_t *) data + l; 141 length -= l; 142 143 p->read_index += l; 144 p->read_length -= l; 145 146 if (!p->read_length) { 147 int r; 148 149 r = pa_stream_drop (p->stream); 150 p->read_data = NULL; 151 p->read_length = 0; 152 p->read_index = 0; 153 154 CHECK_SUCCESS_GOTO (g, rerror, r == 0, unlock_and_fail); 155 } 156 } 157 158 pa_threaded_mainloop_unlock (g->mainloop); 159 return 0; 160 161 unlock_and_fail: 162 pa_threaded_mainloop_unlock (g->mainloop); 163 return -1; 164 } 165 166 static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror) 167 { 168 paaudio *g = p->g; 169 170 pa_threaded_mainloop_lock (g->mainloop); 171 172 CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); 173 174 while (length > 0) { 175 size_t l; 176 int r; 177 178 while (!(l = pa_stream_writable_size (p->stream))) { 179 pa_threaded_mainloop_wait (g->mainloop); 180 CHECK_DEAD_GOTO (g, p->stream, rerror, unlock_and_fail); 181 } 182 183 CHECK_SUCCESS_GOTO (g, rerror, l != (size_t) -1, unlock_and_fail); 184 185 if (l > length) { 186 l = length; 187 } 188 189 r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); 190 CHECK_SUCCESS_GOTO (g, rerror, r >= 0, unlock_and_fail); 191 192 data = (const uint8_t *) data + l; 193 length -= l; 194 } 195 196 pa_threaded_mainloop_unlock (g->mainloop); 197 return 0; 198 199 unlock_and_fail: 200 pa_threaded_mainloop_unlock (g->mainloop); 201 return -1; 202 } 203 204 static void *qpa_thread_out (void *arg) 205 { 206 PAVoiceOut *pa = arg; 207 HWVoiceOut *hw = &pa->hw; 208 209 if (audio_pt_lock(&pa->pt, __func__)) { 210 return NULL; 211 } 212 213 for (;;) { 214 int decr, to_mix, rpos; 215 216 for (;;) { 217 if (pa->done) { 218 goto exit; 219 } 220 221 if (pa->live > 0) { 222 break; 223 } 224 225 if (audio_pt_wait(&pa->pt, __func__)) { 226 goto exit; 227 } 228 } 229 230 decr = to_mix = audio_MIN(pa->live, pa->g->conf.samples >> 5); 231 rpos = pa->rpos; 232 233 if (audio_pt_unlock(&pa->pt, __func__)) { 234 return NULL; 235 } 236 237 while (to_mix) { 238 int error; 239 int chunk = audio_MIN (to_mix, hw->samples - rpos); 240 struct st_sample *src = hw->mix_buf + rpos; 241 242 hw->clip (pa->pcm_buf, src, chunk); 243 244 if (qpa_simple_write (pa, pa->pcm_buf, 245 chunk << hw->info.shift, &error) < 0) { 246 qpa_logerr (error, "pa_simple_write failed\n"); 247 return NULL; 248 } 249 250 rpos = (rpos + chunk) % hw->samples; 251 to_mix -= chunk; 252 } 253 254 if (audio_pt_lock(&pa->pt, __func__)) { 255 return NULL; 256 } 257 258 pa->rpos = rpos; 259 pa->live -= decr; 260 pa->decr += decr; 261 } 262 263 exit: 264 audio_pt_unlock(&pa->pt, __func__); 265 return NULL; 266 } 267 268 static int qpa_run_out (HWVoiceOut *hw, int live) 269 { 270 int decr; 271 PAVoiceOut *pa = (PAVoiceOut *) hw; 272 273 if (audio_pt_lock(&pa->pt, __func__)) { 274 return 0; 275 } 276 277 decr = audio_MIN (live, pa->decr); 278 pa->decr -= decr; 279 pa->live = live - decr; 280 hw->rpos = pa->rpos; 281 if (pa->live > 0) { 282 audio_pt_unlock_and_signal(&pa->pt, __func__); 283 } 284 else { 285 audio_pt_unlock(&pa->pt, __func__); 286 } 287 return decr; 288 } 289 290 static int qpa_write (SWVoiceOut *sw, void *buf, int len) 291 { 292 return audio_pcm_sw_write (sw, buf, len); 293 } 294 295 /* capture */ 296 static void *qpa_thread_in (void *arg) 297 { 298 PAVoiceIn *pa = arg; 299 HWVoiceIn *hw = &pa->hw; 300 301 if (audio_pt_lock(&pa->pt, __func__)) { 302 return NULL; 303 } 304 305 for (;;) { 306 int incr, to_grab, wpos; 307 308 for (;;) { 309 if (pa->done) { 310 goto exit; 311 } 312 313 if (pa->dead > 0) { 314 break; 315 } 316 317 if (audio_pt_wait(&pa->pt, __func__)) { 318 goto exit; 319 } 320 } 321 322 incr = to_grab = audio_MIN(pa->dead, pa->g->conf.samples >> 5); 323 wpos = pa->wpos; 324 325 if (audio_pt_unlock(&pa->pt, __func__)) { 326 return NULL; 327 } 328 329 while (to_grab) { 330 int error; 331 int chunk = audio_MIN (to_grab, hw->samples - wpos); 332 void *buf = advance (pa->pcm_buf, wpos); 333 334 if (qpa_simple_read (pa, buf, 335 chunk << hw->info.shift, &error) < 0) { 336 qpa_logerr (error, "pa_simple_read failed\n"); 337 return NULL; 338 } 339 340 hw->conv (hw->conv_buf + wpos, buf, chunk); 341 wpos = (wpos + chunk) % hw->samples; 342 to_grab -= chunk; 343 } 344 345 if (audio_pt_lock(&pa->pt, __func__)) { 346 return NULL; 347 } 348 349 pa->wpos = wpos; 350 pa->dead -= incr; 351 pa->incr += incr; 352 } 353 354 exit: 355 audio_pt_unlock(&pa->pt, __func__); 356 return NULL; 357 } 358 359 static int qpa_run_in (HWVoiceIn *hw) 360 { 361 int live, incr, dead; 362 PAVoiceIn *pa = (PAVoiceIn *) hw; 363 364 if (audio_pt_lock(&pa->pt, __func__)) { 365 return 0; 366 } 367 368 live = audio_pcm_hw_get_live_in (hw); 369 dead = hw->samples - live; 370 incr = audio_MIN (dead, pa->incr); 371 pa->incr -= incr; 372 pa->dead = dead - incr; 373 hw->wpos = pa->wpos; 374 if (pa->dead > 0) { 375 audio_pt_unlock_and_signal(&pa->pt, __func__); 376 } 377 else { 378 audio_pt_unlock(&pa->pt, __func__); 379 } 380 return incr; 381 } 382 383 static int qpa_read (SWVoiceIn *sw, void *buf, int len) 384 { 385 return audio_pcm_sw_read (sw, buf, len); 386 } 387 388 static pa_sample_format_t audfmt_to_pa (audfmt_e afmt, int endianness) 389 { 390 int format; 391 392 switch (afmt) { 393 case AUD_FMT_S8: 394 case AUD_FMT_U8: 395 format = PA_SAMPLE_U8; 396 break; 397 case AUD_FMT_S16: 398 case AUD_FMT_U16: 399 format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; 400 break; 401 case AUD_FMT_S32: 402 case AUD_FMT_U32: 403 format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; 404 break; 405 default: 406 dolog ("Internal logic error: Bad audio format %d\n", afmt); 407 format = PA_SAMPLE_U8; 408 break; 409 } 410 return format; 411 } 412 413 static audfmt_e pa_to_audfmt (pa_sample_format_t fmt, int *endianness) 414 { 415 switch (fmt) { 416 case PA_SAMPLE_U8: 417 return AUD_FMT_U8; 418 case PA_SAMPLE_S16BE: 419 *endianness = 1; 420 return AUD_FMT_S16; 421 case PA_SAMPLE_S16LE: 422 *endianness = 0; 423 return AUD_FMT_S16; 424 case PA_SAMPLE_S32BE: 425 *endianness = 1; 426 return AUD_FMT_S32; 427 case PA_SAMPLE_S32LE: 428 *endianness = 0; 429 return AUD_FMT_S32; 430 default: 431 dolog ("Internal logic error: Bad pa_sample_format %d\n", fmt); 432 return AUD_FMT_U8; 433 } 434 } 435 436 static void context_state_cb (pa_context *c, void *userdata) 437 { 438 paaudio *g = userdata; 439 440 switch (pa_context_get_state(c)) { 441 case PA_CONTEXT_READY: 442 case PA_CONTEXT_TERMINATED: 443 case PA_CONTEXT_FAILED: 444 pa_threaded_mainloop_signal (g->mainloop, 0); 445 break; 446 447 case PA_CONTEXT_UNCONNECTED: 448 case PA_CONTEXT_CONNECTING: 449 case PA_CONTEXT_AUTHORIZING: 450 case PA_CONTEXT_SETTING_NAME: 451 break; 452 } 453 } 454 455 static void stream_state_cb (pa_stream *s, void * userdata) 456 { 457 paaudio *g = userdata; 458 459 switch (pa_stream_get_state (s)) { 460 461 case PA_STREAM_READY: 462 case PA_STREAM_FAILED: 463 case PA_STREAM_TERMINATED: 464 pa_threaded_mainloop_signal (g->mainloop, 0); 465 break; 466 467 case PA_STREAM_UNCONNECTED: 468 case PA_STREAM_CREATING: 469 break; 470 } 471 } 472 473 static void stream_request_cb (pa_stream *s, size_t length, void *userdata) 474 { 475 paaudio *g = userdata; 476 477 pa_threaded_mainloop_signal (g->mainloop, 0); 478 } 479 480 static pa_stream *qpa_simple_new ( 481 paaudio *g, 482 const char *name, 483 pa_stream_direction_t dir, 484 const char *dev, 485 const pa_sample_spec *ss, 486 const pa_channel_map *map, 487 const pa_buffer_attr *attr, 488 int *rerror) 489 { 490 int r; 491 pa_stream *stream; 492 493 pa_threaded_mainloop_lock (g->mainloop); 494 495 stream = pa_stream_new (g->context, name, ss, map); 496 if (!stream) { 497 goto fail; 498 } 499 500 pa_stream_set_state_callback (stream, stream_state_cb, g); 501 pa_stream_set_read_callback (stream, stream_request_cb, g); 502 pa_stream_set_write_callback (stream, stream_request_cb, g); 503 504 if (dir == PA_STREAM_PLAYBACK) { 505 r = pa_stream_connect_playback (stream, dev, attr, 506 PA_STREAM_INTERPOLATE_TIMING 507 #ifdef PA_STREAM_ADJUST_LATENCY 508 |PA_STREAM_ADJUST_LATENCY 509 #endif 510 |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); 511 } else { 512 r = pa_stream_connect_record (stream, dev, attr, 513 PA_STREAM_INTERPOLATE_TIMING 514 #ifdef PA_STREAM_ADJUST_LATENCY 515 |PA_STREAM_ADJUST_LATENCY 516 #endif 517 |PA_STREAM_AUTO_TIMING_UPDATE); 518 } 519 520 if (r < 0) { 521 goto fail; 522 } 523 524 pa_threaded_mainloop_unlock (g->mainloop); 525 526 return stream; 527 528 fail: 529 pa_threaded_mainloop_unlock (g->mainloop); 530 531 if (stream) { 532 pa_stream_unref (stream); 533 } 534 535 *rerror = pa_context_errno (g->context); 536 537 return NULL; 538 } 539 540 static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, 541 void *drv_opaque) 542 { 543 int error; 544 pa_sample_spec ss; 545 pa_buffer_attr ba; 546 struct audsettings obt_as = *as; 547 PAVoiceOut *pa = (PAVoiceOut *) hw; 548 paaudio *g = pa->g = drv_opaque; 549 550 ss.format = audfmt_to_pa (as->fmt, as->endianness); 551 ss.channels = as->nchannels; 552 ss.rate = as->freq; 553 554 /* 555 * qemu audio tick runs at 100 Hz (by default), so processing 556 * data chunks worth 10 ms of sound should be a good fit. 557 */ 558 ba.tlength = pa_usec_to_bytes (10 * 1000, &ss); 559 ba.minreq = pa_usec_to_bytes (5 * 1000, &ss); 560 ba.maxlength = -1; 561 ba.prebuf = -1; 562 563 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 564 565 pa->stream = qpa_simple_new ( 566 g, 567 "qemu", 568 PA_STREAM_PLAYBACK, 569 g->conf.sink, 570 &ss, 571 NULL, /* channel map */ 572 &ba, /* buffering attributes */ 573 &error 574 ); 575 if (!pa->stream) { 576 qpa_logerr (error, "pa_simple_new for playback failed\n"); 577 goto fail1; 578 } 579 580 audio_pcm_init_info (&hw->info, &obt_as); 581 hw->samples = g->conf.samples; 582 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); 583 pa->rpos = hw->rpos; 584 if (!pa->pcm_buf) { 585 dolog ("Could not allocate buffer (%d bytes)\n", 586 hw->samples << hw->info.shift); 587 goto fail2; 588 } 589 590 if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) { 591 goto fail3; 592 } 593 594 return 0; 595 596 fail3: 597 g_free (pa->pcm_buf); 598 pa->pcm_buf = NULL; 599 fail2: 600 if (pa->stream) { 601 pa_stream_unref (pa->stream); 602 pa->stream = NULL; 603 } 604 fail1: 605 return -1; 606 } 607 608 static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 609 { 610 int error; 611 pa_sample_spec ss; 612 struct audsettings obt_as = *as; 613 PAVoiceIn *pa = (PAVoiceIn *) hw; 614 paaudio *g = pa->g = drv_opaque; 615 616 ss.format = audfmt_to_pa (as->fmt, as->endianness); 617 ss.channels = as->nchannels; 618 ss.rate = as->freq; 619 620 obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness); 621 622 pa->stream = qpa_simple_new ( 623 g, 624 "qemu", 625 PA_STREAM_RECORD, 626 g->conf.source, 627 &ss, 628 NULL, /* channel map */ 629 NULL, /* buffering attributes */ 630 &error 631 ); 632 if (!pa->stream) { 633 qpa_logerr (error, "pa_simple_new for capture failed\n"); 634 goto fail1; 635 } 636 637 audio_pcm_init_info (&hw->info, &obt_as); 638 hw->samples = g->conf.samples; 639 pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); 640 pa->wpos = hw->wpos; 641 if (!pa->pcm_buf) { 642 dolog ("Could not allocate buffer (%d bytes)\n", 643 hw->samples << hw->info.shift); 644 goto fail2; 645 } 646 647 if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) { 648 goto fail3; 649 } 650 651 return 0; 652 653 fail3: 654 g_free (pa->pcm_buf); 655 pa->pcm_buf = NULL; 656 fail2: 657 if (pa->stream) { 658 pa_stream_unref (pa->stream); 659 pa->stream = NULL; 660 } 661 fail1: 662 return -1; 663 } 664 665 static void qpa_fini_out (HWVoiceOut *hw) 666 { 667 void *ret; 668 PAVoiceOut *pa = (PAVoiceOut *) hw; 669 670 audio_pt_lock(&pa->pt, __func__); 671 pa->done = 1; 672 audio_pt_unlock_and_signal(&pa->pt, __func__); 673 audio_pt_join(&pa->pt, &ret, __func__); 674 675 if (pa->stream) { 676 pa_stream_unref (pa->stream); 677 pa->stream = NULL; 678 } 679 680 audio_pt_fini(&pa->pt, __func__); 681 g_free (pa->pcm_buf); 682 pa->pcm_buf = NULL; 683 } 684 685 static void qpa_fini_in (HWVoiceIn *hw) 686 { 687 void *ret; 688 PAVoiceIn *pa = (PAVoiceIn *) hw; 689 690 audio_pt_lock(&pa->pt, __func__); 691 pa->done = 1; 692 audio_pt_unlock_and_signal(&pa->pt, __func__); 693 audio_pt_join(&pa->pt, &ret, __func__); 694 695 if (pa->stream) { 696 pa_stream_unref (pa->stream); 697 pa->stream = NULL; 698 } 699 700 audio_pt_fini(&pa->pt, __func__); 701 g_free (pa->pcm_buf); 702 pa->pcm_buf = NULL; 703 } 704 705 static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) 706 { 707 PAVoiceOut *pa = (PAVoiceOut *) hw; 708 pa_operation *op; 709 pa_cvolume v; 710 paaudio *g = pa->g; 711 712 #ifdef PA_CHECK_VERSION /* macro is present in 0.9.16+ */ 713 pa_cvolume_init (&v); /* function is present in 0.9.13+ */ 714 #endif 715 716 switch (cmd) { 717 case VOICE_VOLUME: 718 { 719 SWVoiceOut *sw; 720 va_list ap; 721 722 va_start (ap, cmd); 723 sw = va_arg (ap, SWVoiceOut *); 724 va_end (ap); 725 726 v.channels = 2; 727 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; 728 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; 729 730 pa_threaded_mainloop_lock (g->mainloop); 731 732 op = pa_context_set_sink_input_volume (g->context, 733 pa_stream_get_index (pa->stream), 734 &v, NULL, NULL); 735 if (!op) 736 qpa_logerr (pa_context_errno (g->context), 737 "set_sink_input_volume() failed\n"); 738 else 739 pa_operation_unref (op); 740 741 op = pa_context_set_sink_input_mute (g->context, 742 pa_stream_get_index (pa->stream), 743 sw->vol.mute, NULL, NULL); 744 if (!op) { 745 qpa_logerr (pa_context_errno (g->context), 746 "set_sink_input_mute() failed\n"); 747 } else { 748 pa_operation_unref (op); 749 } 750 751 pa_threaded_mainloop_unlock (g->mainloop); 752 } 753 } 754 return 0; 755 } 756 757 static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) 758 { 759 PAVoiceIn *pa = (PAVoiceIn *) hw; 760 pa_operation *op; 761 pa_cvolume v; 762 paaudio *g = pa->g; 763 764 #ifdef PA_CHECK_VERSION 765 pa_cvolume_init (&v); 766 #endif 767 768 switch (cmd) { 769 case VOICE_VOLUME: 770 { 771 SWVoiceIn *sw; 772 va_list ap; 773 774 va_start (ap, cmd); 775 sw = va_arg (ap, SWVoiceIn *); 776 va_end (ap); 777 778 v.channels = 2; 779 v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; 780 v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; 781 782 pa_threaded_mainloop_lock (g->mainloop); 783 784 op = pa_context_set_source_output_volume (g->context, 785 pa_stream_get_index (pa->stream), 786 &v, NULL, NULL); 787 if (!op) { 788 qpa_logerr (pa_context_errno (g->context), 789 "set_source_output_volume() failed\n"); 790 } else { 791 pa_operation_unref(op); 792 } 793 794 op = pa_context_set_source_output_mute (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_output_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 static 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 955 static void register_audio_pa(void) 956 { 957 audio_driver_register(&pa_audio_driver); 958 } 959 type_init(register_audio_pa); 960