1 /* 2 * QEMU ALSA audio driver 3 * 4 * Copyright (c) 2005 Vassili Karpov (malc) 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include <alsa/asoundlib.h> 27 #include "qemu/main-loop.h" 28 #include "qemu/module.h" 29 #include "audio.h" 30 #include "trace.h" 31 32 #pragma GCC diagnostic ignored "-Waddress" 33 34 #define AUDIO_CAP "alsa" 35 #include "audio_int.h" 36 37 #define DEBUG_ALSA 0 38 39 struct pollhlp { 40 snd_pcm_t *handle; 41 struct pollfd *pfds; 42 int count; 43 int mask; 44 AudioState *s; 45 }; 46 47 typedef struct ALSAVoiceOut { 48 HWVoiceOut hw; 49 snd_pcm_t *handle; 50 struct pollhlp pollhlp; 51 Audiodev *dev; 52 } ALSAVoiceOut; 53 54 typedef struct ALSAVoiceIn { 55 HWVoiceIn hw; 56 snd_pcm_t *handle; 57 struct pollhlp pollhlp; 58 Audiodev *dev; 59 } ALSAVoiceIn; 60 61 struct alsa_params_req { 62 int freq; 63 snd_pcm_format_t fmt; 64 int nchannels; 65 }; 66 67 struct alsa_params_obt { 68 int freq; 69 AudioFormat fmt; 70 int endianness; 71 int nchannels; 72 snd_pcm_uframes_t samples; 73 }; 74 75 static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...) 76 { 77 va_list ap; 78 79 va_start (ap, fmt); 80 AUD_vlog (AUDIO_CAP, fmt, ap); 81 va_end (ap); 82 83 AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err)); 84 } 85 86 static void G_GNUC_PRINTF (3, 4) alsa_logerr2 ( 87 int err, 88 const char *typ, 89 const char *fmt, 90 ... 91 ) 92 { 93 va_list ap; 94 95 AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ); 96 97 va_start (ap, fmt); 98 AUD_vlog (AUDIO_CAP, fmt, ap); 99 va_end (ap); 100 101 AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err)); 102 } 103 104 static void alsa_fini_poll (struct pollhlp *hlp) 105 { 106 int i; 107 struct pollfd *pfds = hlp->pfds; 108 109 if (pfds) { 110 for (i = 0; i < hlp->count; ++i) { 111 qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL); 112 } 113 g_free (pfds); 114 } 115 hlp->pfds = NULL; 116 hlp->count = 0; 117 hlp->handle = NULL; 118 } 119 120 static void alsa_anal_close1 (snd_pcm_t **handlep) 121 { 122 int err = snd_pcm_close (*handlep); 123 if (err) { 124 alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep); 125 } 126 *handlep = NULL; 127 } 128 129 static void alsa_anal_close (snd_pcm_t **handlep, struct pollhlp *hlp) 130 { 131 alsa_fini_poll (hlp); 132 alsa_anal_close1 (handlep); 133 } 134 135 static int alsa_recover (snd_pcm_t *handle) 136 { 137 int err = snd_pcm_prepare (handle); 138 if (err < 0) { 139 alsa_logerr (err, "Failed to prepare handle %p\n", handle); 140 return -1; 141 } 142 return 0; 143 } 144 145 static int alsa_resume (snd_pcm_t *handle) 146 { 147 int err = snd_pcm_resume (handle); 148 if (err < 0) { 149 alsa_logerr (err, "Failed to resume handle %p\n", handle); 150 return -1; 151 } 152 return 0; 153 } 154 155 static void alsa_poll_handler (void *opaque) 156 { 157 int err, count; 158 snd_pcm_state_t state; 159 struct pollhlp *hlp = opaque; 160 unsigned short revents; 161 162 count = poll (hlp->pfds, hlp->count, 0); 163 if (count < 0) { 164 dolog ("alsa_poll_handler: poll %s\n", strerror (errno)); 165 return; 166 } 167 168 if (!count) { 169 return; 170 } 171 172 /* XXX: ALSA example uses initial count, not the one returned by 173 poll, correct? */ 174 err = snd_pcm_poll_descriptors_revents (hlp->handle, hlp->pfds, 175 hlp->count, &revents); 176 if (err < 0) { 177 alsa_logerr (err, "snd_pcm_poll_descriptors_revents"); 178 return; 179 } 180 181 if (!(revents & hlp->mask)) { 182 trace_alsa_revents(revents); 183 return; 184 } 185 186 state = snd_pcm_state (hlp->handle); 187 switch (state) { 188 case SND_PCM_STATE_SETUP: 189 alsa_recover (hlp->handle); 190 break; 191 192 case SND_PCM_STATE_XRUN: 193 alsa_recover (hlp->handle); 194 break; 195 196 case SND_PCM_STATE_SUSPENDED: 197 alsa_resume (hlp->handle); 198 break; 199 200 case SND_PCM_STATE_PREPARED: 201 audio_run(hlp->s, "alsa run (prepared)"); 202 break; 203 204 case SND_PCM_STATE_RUNNING: 205 audio_run(hlp->s, "alsa run (running)"); 206 break; 207 208 default: 209 dolog ("Unexpected state %d\n", state); 210 } 211 } 212 213 static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask) 214 { 215 int i, count, err; 216 struct pollfd *pfds; 217 218 count = snd_pcm_poll_descriptors_count (handle); 219 if (count <= 0) { 220 dolog ("Could not initialize poll mode\n" 221 "Invalid number of poll descriptors %d\n", count); 222 return -1; 223 } 224 225 pfds = audio_calloc ("alsa_poll_helper", count, sizeof (*pfds)); 226 if (!pfds) { 227 dolog ("Could not initialize poll mode\n"); 228 return -1; 229 } 230 231 err = snd_pcm_poll_descriptors (handle, pfds, count); 232 if (err < 0) { 233 alsa_logerr (err, "Could not initialize poll mode\n" 234 "Could not obtain poll descriptors\n"); 235 g_free (pfds); 236 return -1; 237 } 238 239 for (i = 0; i < count; ++i) { 240 if (pfds[i].events & POLLIN) { 241 qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler, NULL, hlp); 242 } 243 if (pfds[i].events & POLLOUT) { 244 trace_alsa_pollout(i, pfds[i].fd); 245 qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp); 246 } 247 trace_alsa_set_handler(pfds[i].events, i, pfds[i].fd, err); 248 249 } 250 hlp->pfds = pfds; 251 hlp->count = count; 252 hlp->handle = handle; 253 hlp->mask = mask; 254 return 0; 255 } 256 257 static int alsa_poll_out (HWVoiceOut *hw) 258 { 259 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; 260 261 return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLOUT); 262 } 263 264 static int alsa_poll_in (HWVoiceIn *hw) 265 { 266 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; 267 268 return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN); 269 } 270 271 static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) 272 { 273 switch (fmt) { 274 case AUDIO_FORMAT_S8: 275 return SND_PCM_FORMAT_S8; 276 277 case AUDIO_FORMAT_U8: 278 return SND_PCM_FORMAT_U8; 279 280 case AUDIO_FORMAT_S16: 281 if (endianness) { 282 return SND_PCM_FORMAT_S16_BE; 283 } else { 284 return SND_PCM_FORMAT_S16_LE; 285 } 286 287 case AUDIO_FORMAT_U16: 288 if (endianness) { 289 return SND_PCM_FORMAT_U16_BE; 290 } else { 291 return SND_PCM_FORMAT_U16_LE; 292 } 293 294 case AUDIO_FORMAT_S32: 295 if (endianness) { 296 return SND_PCM_FORMAT_S32_BE; 297 } else { 298 return SND_PCM_FORMAT_S32_LE; 299 } 300 301 case AUDIO_FORMAT_U32: 302 if (endianness) { 303 return SND_PCM_FORMAT_U32_BE; 304 } else { 305 return SND_PCM_FORMAT_U32_LE; 306 } 307 308 case AUDIO_FORMAT_F32: 309 if (endianness) { 310 return SND_PCM_FORMAT_FLOAT_BE; 311 } else { 312 return SND_PCM_FORMAT_FLOAT_LE; 313 } 314 315 default: 316 dolog ("Internal logic error: Bad audio format %d\n", fmt); 317 #ifdef DEBUG_AUDIO 318 abort (); 319 #endif 320 return SND_PCM_FORMAT_U8; 321 } 322 } 323 324 static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt, 325 int *endianness) 326 { 327 switch (alsafmt) { 328 case SND_PCM_FORMAT_S8: 329 *endianness = 0; 330 *fmt = AUDIO_FORMAT_S8; 331 break; 332 333 case SND_PCM_FORMAT_U8: 334 *endianness = 0; 335 *fmt = AUDIO_FORMAT_U8; 336 break; 337 338 case SND_PCM_FORMAT_S16_LE: 339 *endianness = 0; 340 *fmt = AUDIO_FORMAT_S16; 341 break; 342 343 case SND_PCM_FORMAT_U16_LE: 344 *endianness = 0; 345 *fmt = AUDIO_FORMAT_U16; 346 break; 347 348 case SND_PCM_FORMAT_S16_BE: 349 *endianness = 1; 350 *fmt = AUDIO_FORMAT_S16; 351 break; 352 353 case SND_PCM_FORMAT_U16_BE: 354 *endianness = 1; 355 *fmt = AUDIO_FORMAT_U16; 356 break; 357 358 case SND_PCM_FORMAT_S32_LE: 359 *endianness = 0; 360 *fmt = AUDIO_FORMAT_S32; 361 break; 362 363 case SND_PCM_FORMAT_U32_LE: 364 *endianness = 0; 365 *fmt = AUDIO_FORMAT_U32; 366 break; 367 368 case SND_PCM_FORMAT_S32_BE: 369 *endianness = 1; 370 *fmt = AUDIO_FORMAT_S32; 371 break; 372 373 case SND_PCM_FORMAT_U32_BE: 374 *endianness = 1; 375 *fmt = AUDIO_FORMAT_U32; 376 break; 377 378 case SND_PCM_FORMAT_FLOAT_LE: 379 *endianness = 0; 380 *fmt = AUDIO_FORMAT_F32; 381 break; 382 383 case SND_PCM_FORMAT_FLOAT_BE: 384 *endianness = 1; 385 *fmt = AUDIO_FORMAT_F32; 386 break; 387 388 default: 389 dolog ("Unrecognized audio format %d\n", alsafmt); 390 return -1; 391 } 392 393 return 0; 394 } 395 396 static void alsa_dump_info (struct alsa_params_req *req, 397 struct alsa_params_obt *obt, 398 snd_pcm_format_t obtfmt, 399 AudiodevAlsaPerDirectionOptions *apdo) 400 { 401 dolog("parameter | requested value | obtained value\n"); 402 dolog("format | %10d | %10d\n", req->fmt, obtfmt); 403 dolog("channels | %10d | %10d\n", 404 req->nchannels, obt->nchannels); 405 dolog("frequency | %10d | %10d\n", req->freq, obt->freq); 406 dolog("============================================\n"); 407 dolog("requested: buffer len %" PRId32 " period len %" PRId32 "\n", 408 apdo->buffer_length, apdo->period_length); 409 dolog("obtained: samples %ld\n", obt->samples); 410 } 411 412 static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold) 413 { 414 int err; 415 snd_pcm_sw_params_t *sw_params; 416 417 snd_pcm_sw_params_alloca (&sw_params); 418 419 err = snd_pcm_sw_params_current (handle, sw_params); 420 if (err < 0) { 421 dolog ("Could not fully initialize DAC\n"); 422 alsa_logerr (err, "Failed to get current software parameters\n"); 423 return; 424 } 425 426 err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold); 427 if (err < 0) { 428 dolog ("Could not fully initialize DAC\n"); 429 alsa_logerr (err, "Failed to set software threshold to %ld\n", 430 threshold); 431 return; 432 } 433 434 err = snd_pcm_sw_params (handle, sw_params); 435 if (err < 0) { 436 dolog ("Could not fully initialize DAC\n"); 437 alsa_logerr (err, "Failed to set software parameters\n"); 438 return; 439 } 440 } 441 442 static int alsa_open(bool in, struct alsa_params_req *req, 443 struct alsa_params_obt *obt, snd_pcm_t **handlep, 444 Audiodev *dev) 445 { 446 AudiodevAlsaOptions *aopts = &dev->u.alsa; 447 AudiodevAlsaPerDirectionOptions *apdo = in ? aopts->in : aopts->out; 448 snd_pcm_t *handle; 449 snd_pcm_hw_params_t *hw_params; 450 int err; 451 unsigned int freq, nchannels; 452 const char *pcm_name = apdo->has_dev ? apdo->dev : "default"; 453 snd_pcm_uframes_t obt_buffer_size; 454 const char *typ = in ? "ADC" : "DAC"; 455 snd_pcm_format_t obtfmt; 456 457 freq = req->freq; 458 nchannels = req->nchannels; 459 460 snd_pcm_hw_params_alloca (&hw_params); 461 462 err = snd_pcm_open ( 463 &handle, 464 pcm_name, 465 in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 466 SND_PCM_NONBLOCK 467 ); 468 if (err < 0) { 469 alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name); 470 return -1; 471 } 472 473 err = snd_pcm_hw_params_any (handle, hw_params); 474 if (err < 0) { 475 alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n"); 476 goto err; 477 } 478 479 err = snd_pcm_hw_params_set_access ( 480 handle, 481 hw_params, 482 SND_PCM_ACCESS_RW_INTERLEAVED 483 ); 484 if (err < 0) { 485 alsa_logerr2 (err, typ, "Failed to set access type\n"); 486 goto err; 487 } 488 489 err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt); 490 if (err < 0) { 491 alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt); 492 } 493 494 err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0); 495 if (err < 0) { 496 alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq); 497 goto err; 498 } 499 500 err = snd_pcm_hw_params_set_channels_near ( 501 handle, 502 hw_params, 503 &nchannels 504 ); 505 if (err < 0) { 506 alsa_logerr2 (err, typ, "Failed to set number of channels %d\n", 507 req->nchannels); 508 goto err; 509 } 510 511 if (apdo->buffer_length) { 512 int dir = 0; 513 unsigned int btime = apdo->buffer_length; 514 515 err = snd_pcm_hw_params_set_buffer_time_near( 516 handle, hw_params, &btime, &dir); 517 518 if (err < 0) { 519 alsa_logerr2(err, typ, "Failed to set buffer time to %" PRId32 "\n", 520 apdo->buffer_length); 521 goto err; 522 } 523 524 if (apdo->has_buffer_length && btime != apdo->buffer_length) { 525 dolog("Requested buffer time %" PRId32 526 " was rejected, using %u\n", apdo->buffer_length, btime); 527 } 528 } 529 530 if (apdo->period_length) { 531 int dir = 0; 532 unsigned int ptime = apdo->period_length; 533 534 err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &ptime, 535 &dir); 536 537 if (err < 0) { 538 alsa_logerr2(err, typ, "Failed to set period time to %" PRId32 "\n", 539 apdo->period_length); 540 goto err; 541 } 542 543 if (apdo->has_period_length && ptime != apdo->period_length) { 544 dolog("Requested period time %" PRId32 " was rejected, using %d\n", 545 apdo->period_length, ptime); 546 } 547 } 548 549 err = snd_pcm_hw_params (handle, hw_params); 550 if (err < 0) { 551 alsa_logerr2 (err, typ, "Failed to apply audio parameters\n"); 552 goto err; 553 } 554 555 err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size); 556 if (err < 0) { 557 alsa_logerr2 (err, typ, "Failed to get buffer size\n"); 558 goto err; 559 } 560 561 err = snd_pcm_hw_params_get_format (hw_params, &obtfmt); 562 if (err < 0) { 563 alsa_logerr2 (err, typ, "Failed to get format\n"); 564 goto err; 565 } 566 567 if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) { 568 dolog ("Invalid format was returned %d\n", obtfmt); 569 goto err; 570 } 571 572 err = snd_pcm_prepare (handle); 573 if (err < 0) { 574 alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle); 575 goto err; 576 } 577 578 if (!in && aopts->has_threshold && aopts->threshold) { 579 struct audsettings as = { .freq = freq }; 580 alsa_set_threshold( 581 handle, 582 audio_buffer_frames(qapi_AudiodevAlsaPerDirectionOptions_base(apdo), 583 &as, aopts->threshold)); 584 } 585 586 obt->nchannels = nchannels; 587 obt->freq = freq; 588 obt->samples = obt_buffer_size; 589 590 *handlep = handle; 591 592 if (DEBUG_ALSA || obtfmt != req->fmt || 593 obt->nchannels != req->nchannels || obt->freq != req->freq) { 594 dolog ("Audio parameters for %s\n", typ); 595 alsa_dump_info(req, obt, obtfmt, apdo); 596 } 597 598 return 0; 599 600 err: 601 alsa_anal_close1 (&handle); 602 return -1; 603 } 604 605 static size_t alsa_buffer_get_free(HWVoiceOut *hw) 606 { 607 ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw; 608 snd_pcm_sframes_t avail; 609 size_t alsa_free, generic_free, generic_in_use; 610 611 avail = snd_pcm_avail_update(alsa->handle); 612 if (avail < 0) { 613 if (avail == -EPIPE) { 614 if (!alsa_recover(alsa->handle)) { 615 avail = snd_pcm_avail_update(alsa->handle); 616 } 617 } 618 if (avail < 0) { 619 alsa_logerr(avail, 620 "Could not obtain number of available frames\n"); 621 avail = 0; 622 } 623 } 624 625 alsa_free = avail * hw->info.bytes_per_frame; 626 generic_free = audio_generic_buffer_get_free(hw); 627 generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free; 628 if (generic_in_use) { 629 /* 630 * This code can only be reached in the unlikely case that 631 * snd_pcm_avail_update() returned a larger number of frames 632 * than snd_pcm_writei() could write. Make sure that all 633 * remaining bytes in the generic buffer can be written. 634 */ 635 alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0; 636 } 637 638 return alsa_free; 639 } 640 641 static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) 642 { 643 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; 644 size_t pos = 0; 645 size_t len_frames = len / hw->info.bytes_per_frame; 646 647 while (len_frames) { 648 char *src = advance(buf, pos); 649 snd_pcm_sframes_t written; 650 651 written = snd_pcm_writei(alsa->handle, src, len_frames); 652 653 if (written <= 0) { 654 switch (written) { 655 case 0: 656 trace_alsa_wrote_zero(len_frames); 657 return pos; 658 659 case -EPIPE: 660 if (alsa_recover(alsa->handle)) { 661 alsa_logerr(written, "Failed to write %zu frames\n", 662 len_frames); 663 return pos; 664 } 665 trace_alsa_xrun_out(); 666 continue; 667 668 case -ESTRPIPE: 669 /* 670 * stream is suspended and waiting for an application 671 * recovery 672 */ 673 if (alsa_resume(alsa->handle)) { 674 alsa_logerr(written, "Failed to write %zu frames\n", 675 len_frames); 676 return pos; 677 } 678 trace_alsa_resume_out(); 679 continue; 680 681 case -EAGAIN: 682 return pos; 683 684 default: 685 alsa_logerr(written, "Failed to write %zu frames from %p\n", 686 len, src); 687 return pos; 688 } 689 } 690 691 pos += written * hw->info.bytes_per_frame; 692 if (written < len_frames) { 693 break; 694 } 695 len_frames -= written; 696 } 697 698 return pos; 699 } 700 701 static void alsa_fini_out (HWVoiceOut *hw) 702 { 703 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; 704 705 ldebug ("alsa_fini\n"); 706 alsa_anal_close (&alsa->handle, &alsa->pollhlp); 707 } 708 709 static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, 710 void *drv_opaque) 711 { 712 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; 713 struct alsa_params_req req; 714 struct alsa_params_obt obt; 715 snd_pcm_t *handle; 716 struct audsettings obt_as; 717 Audiodev *dev = drv_opaque; 718 719 req.fmt = aud_to_alsafmt (as->fmt, as->endianness); 720 req.freq = as->freq; 721 req.nchannels = as->nchannels; 722 723 if (alsa_open(0, &req, &obt, &handle, dev)) { 724 return -1; 725 } 726 727 obt_as.freq = obt.freq; 728 obt_as.nchannels = obt.nchannels; 729 obt_as.fmt = obt.fmt; 730 obt_as.endianness = obt.endianness; 731 732 audio_pcm_init_info (&hw->info, &obt_as); 733 hw->samples = obt.samples; 734 735 alsa->pollhlp.s = hw->s; 736 alsa->handle = handle; 737 alsa->dev = dev; 738 return 0; 739 } 740 741 #define VOICE_CTL_PAUSE 0 742 #define VOICE_CTL_PREPARE 1 743 #define VOICE_CTL_START 2 744 745 static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl) 746 { 747 int err; 748 749 if (ctl == VOICE_CTL_PAUSE) { 750 err = snd_pcm_drop (handle); 751 if (err < 0) { 752 alsa_logerr (err, "Could not stop %s\n", typ); 753 return -1; 754 } 755 } else { 756 err = snd_pcm_prepare (handle); 757 if (err < 0) { 758 alsa_logerr (err, "Could not prepare handle for %s\n", typ); 759 return -1; 760 } 761 if (ctl == VOICE_CTL_START) { 762 err = snd_pcm_start(handle); 763 if (err < 0) { 764 alsa_logerr (err, "Could not start handle for %s\n", typ); 765 return -1; 766 } 767 } 768 } 769 770 return 0; 771 } 772 773 static void alsa_enable_out(HWVoiceOut *hw, bool enable) 774 { 775 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; 776 AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out; 777 778 if (enable) { 779 bool poll_mode = apdo->try_poll; 780 781 ldebug("enabling voice\n"); 782 if (poll_mode && alsa_poll_out(hw)) { 783 poll_mode = 0; 784 } 785 hw->poll_mode = poll_mode; 786 alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE); 787 } else { 788 ldebug("disabling voice\n"); 789 if (hw->poll_mode) { 790 hw->poll_mode = 0; 791 alsa_fini_poll(&alsa->pollhlp); 792 } 793 alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE); 794 } 795 } 796 797 static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) 798 { 799 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; 800 struct alsa_params_req req; 801 struct alsa_params_obt obt; 802 snd_pcm_t *handle; 803 struct audsettings obt_as; 804 Audiodev *dev = drv_opaque; 805 806 req.fmt = aud_to_alsafmt (as->fmt, as->endianness); 807 req.freq = as->freq; 808 req.nchannels = as->nchannels; 809 810 if (alsa_open(1, &req, &obt, &handle, dev)) { 811 return -1; 812 } 813 814 obt_as.freq = obt.freq; 815 obt_as.nchannels = obt.nchannels; 816 obt_as.fmt = obt.fmt; 817 obt_as.endianness = obt.endianness; 818 819 audio_pcm_init_info (&hw->info, &obt_as); 820 hw->samples = obt.samples; 821 822 alsa->pollhlp.s = hw->s; 823 alsa->handle = handle; 824 alsa->dev = dev; 825 return 0; 826 } 827 828 static void alsa_fini_in (HWVoiceIn *hw) 829 { 830 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; 831 832 alsa_anal_close (&alsa->handle, &alsa->pollhlp); 833 } 834 835 static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) 836 { 837 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; 838 size_t pos = 0; 839 840 while (len) { 841 void *dst = advance(buf, pos); 842 snd_pcm_sframes_t nread; 843 844 nread = snd_pcm_readi( 845 alsa->handle, dst, len / hw->info.bytes_per_frame); 846 847 if (nread <= 0) { 848 switch (nread) { 849 case 0: 850 trace_alsa_read_zero(len); 851 return pos; 852 853 case -EPIPE: 854 if (alsa_recover(alsa->handle)) { 855 alsa_logerr(nread, "Failed to read %zu frames\n", len); 856 return pos; 857 } 858 trace_alsa_xrun_in(); 859 continue; 860 861 case -EAGAIN: 862 return pos; 863 864 default: 865 alsa_logerr(nread, "Failed to read %zu frames to %p\n", 866 len, dst); 867 return pos; 868 } 869 } 870 871 pos += nread * hw->info.bytes_per_frame; 872 len -= nread * hw->info.bytes_per_frame; 873 } 874 875 return pos; 876 } 877 878 static void alsa_enable_in(HWVoiceIn *hw, bool enable) 879 { 880 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; 881 AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in; 882 883 if (enable) { 884 bool poll_mode = apdo->try_poll; 885 886 ldebug("enabling voice\n"); 887 if (poll_mode && alsa_poll_in(hw)) { 888 poll_mode = 0; 889 } 890 hw->poll_mode = poll_mode; 891 892 alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START); 893 } else { 894 ldebug ("disabling voice\n"); 895 if (hw->poll_mode) { 896 hw->poll_mode = 0; 897 alsa_fini_poll(&alsa->pollhlp); 898 } 899 alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE); 900 } 901 } 902 903 static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo) 904 { 905 if (!apdo->has_try_poll) { 906 apdo->try_poll = true; 907 apdo->has_try_poll = true; 908 } 909 } 910 911 static void *alsa_audio_init(Audiodev *dev) 912 { 913 AudiodevAlsaOptions *aopts; 914 assert(dev->driver == AUDIODEV_DRIVER_ALSA); 915 916 aopts = &dev->u.alsa; 917 alsa_init_per_direction(aopts->in); 918 alsa_init_per_direction(aopts->out); 919 920 /* 921 * need to define them, as otherwise alsa produces no sound 922 * doesn't set has_* so alsa_open can identify it wasn't set by the user 923 */ 924 if (!dev->u.alsa.out->has_period_length) { 925 /* 1024 frames assuming 44100Hz */ 926 dev->u.alsa.out->period_length = 1024 * 1000000 / 44100; 927 } 928 if (!dev->u.alsa.out->has_buffer_length) { 929 /* 4096 frames assuming 44100Hz */ 930 dev->u.alsa.out->buffer_length = 4096ll * 1000000 / 44100; 931 } 932 933 /* 934 * OptsVisitor sets unspecified optional fields to zero, but do not depend 935 * on it... 936 */ 937 if (!dev->u.alsa.in->has_period_length) { 938 dev->u.alsa.in->period_length = 0; 939 } 940 if (!dev->u.alsa.in->has_buffer_length) { 941 dev->u.alsa.in->buffer_length = 0; 942 } 943 944 return dev; 945 } 946 947 static void alsa_audio_fini (void *opaque) 948 { 949 } 950 951 static struct audio_pcm_ops alsa_pcm_ops = { 952 .init_out = alsa_init_out, 953 .fini_out = alsa_fini_out, 954 .write = alsa_write, 955 .buffer_get_free = alsa_buffer_get_free, 956 .run_buffer_out = audio_generic_run_buffer_out, 957 .enable_out = alsa_enable_out, 958 959 .init_in = alsa_init_in, 960 .fini_in = alsa_fini_in, 961 .read = alsa_read, 962 .run_buffer_in = audio_generic_run_buffer_in, 963 .enable_in = alsa_enable_in, 964 }; 965 966 static struct audio_driver alsa_audio_driver = { 967 .name = "alsa", 968 .descr = "ALSA http://www.alsa-project.org", 969 .init = alsa_audio_init, 970 .fini = alsa_audio_fini, 971 .pcm_ops = &alsa_pcm_ops, 972 .can_be_default = 1, 973 .max_voices_out = INT_MAX, 974 .max_voices_in = INT_MAX, 975 .voice_size_out = sizeof (ALSAVoiceOut), 976 .voice_size_in = sizeof (ALSAVoiceIn) 977 }; 978 979 static void register_audio_alsa(void) 980 { 981 audio_driver_register(&alsa_audio_driver); 982 } 983 type_init(register_audio_alsa); 984