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