qemu/audio/alsaaudio.c
<<
>>
Prefs
   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#include "qemu/osdep.h"
  25#include <alsa/asoundlib.h>
  26#include "qemu-common.h"
  27#include "qemu/main-loop.h"
  28#include "audio.h"
  29#include "trace.h"
  30
  31#pragma GCC diagnostic ignored "-Waddress"
  32
  33#define AUDIO_CAP "alsa"
  34#include "audio_int.h"
  35
  36struct pollhlp {
  37    snd_pcm_t *handle;
  38    struct pollfd *pfds;
  39    int count;
  40    int mask;
  41};
  42
  43typedef struct ALSAVoiceOut {
  44    HWVoiceOut hw;
  45    int wpos;
  46    int pending;
  47    void *pcm_buf;
  48    snd_pcm_t *handle;
  49    struct pollhlp pollhlp;
  50    Audiodev *dev;
  51} ALSAVoiceOut;
  52
  53typedef struct ALSAVoiceIn {
  54    HWVoiceIn hw;
  55    snd_pcm_t *handle;
  56    void *pcm_buf;
  57    struct pollhlp pollhlp;
  58    Audiodev *dev;
  59} ALSAVoiceIn;
  60
  61struct alsa_params_req {
  62    int freq;
  63    snd_pcm_format_t fmt;
  64    int nchannels;
  65};
  66
  67struct alsa_params_obt {
  68    int freq;
  69    AudioFormat fmt;
  70    int endianness;
  71    int nchannels;
  72    snd_pcm_uframes_t samples;
  73};
  74
  75static void GCC_FMT_ATTR (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
  86static void GCC_FMT_ATTR (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
 104static 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
 120static 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
 129static void alsa_anal_close (snd_pcm_t **handlep, struct pollhlp *hlp)
 130{
 131    alsa_fini_poll (hlp);
 132    alsa_anal_close1 (handlep);
 133}
 134
 135static 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
 145static 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
 155static 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 ("alsa run (prepared)");
 202        break;
 203
 204    case SND_PCM_STATE_RUNNING:
 205        audio_run ("alsa run (running)");
 206        break;
 207
 208    default:
 209        dolog ("Unexpected state %d\n", state);
 210    }
 211}
 212
 213static 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
 257static 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
 264static 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
 271static int alsa_write (SWVoiceOut *sw, void *buf, int len)
 272{
 273    return audio_pcm_sw_write (sw, buf, len);
 274}
 275
 276static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
 277{
 278    switch (fmt) {
 279    case AUDIO_FORMAT_S8:
 280        return SND_PCM_FORMAT_S8;
 281
 282    case AUDIO_FORMAT_U8:
 283        return SND_PCM_FORMAT_U8;
 284
 285    case AUDIO_FORMAT_S16:
 286        if (endianness) {
 287            return SND_PCM_FORMAT_S16_BE;
 288        }
 289        else {
 290            return SND_PCM_FORMAT_S16_LE;
 291        }
 292
 293    case AUDIO_FORMAT_U16:
 294        if (endianness) {
 295            return SND_PCM_FORMAT_U16_BE;
 296        }
 297        else {
 298            return SND_PCM_FORMAT_U16_LE;
 299        }
 300
 301    case AUDIO_FORMAT_S32:
 302        if (endianness) {
 303            return SND_PCM_FORMAT_S32_BE;
 304        }
 305        else {
 306            return SND_PCM_FORMAT_S32_LE;
 307        }
 308
 309    case AUDIO_FORMAT_U32:
 310        if (endianness) {
 311            return SND_PCM_FORMAT_U32_BE;
 312        }
 313        else {
 314            return SND_PCM_FORMAT_U32_LE;
 315        }
 316
 317    default:
 318        dolog ("Internal logic error: Bad audio format %d\n", fmt);
 319#ifdef DEBUG_AUDIO
 320        abort ();
 321#endif
 322        return SND_PCM_FORMAT_U8;
 323    }
 324}
 325
 326static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt,
 327                           int *endianness)
 328{
 329    switch (alsafmt) {
 330    case SND_PCM_FORMAT_S8:
 331        *endianness = 0;
 332        *fmt = AUDIO_FORMAT_S8;
 333        break;
 334
 335    case SND_PCM_FORMAT_U8:
 336        *endianness = 0;
 337        *fmt = AUDIO_FORMAT_U8;
 338        break;
 339
 340    case SND_PCM_FORMAT_S16_LE:
 341        *endianness = 0;
 342        *fmt = AUDIO_FORMAT_S16;
 343        break;
 344
 345    case SND_PCM_FORMAT_U16_LE:
 346        *endianness = 0;
 347        *fmt = AUDIO_FORMAT_U16;
 348        break;
 349
 350    case SND_PCM_FORMAT_S16_BE:
 351        *endianness = 1;
 352        *fmt = AUDIO_FORMAT_S16;
 353        break;
 354
 355    case SND_PCM_FORMAT_U16_BE:
 356        *endianness = 1;
 357        *fmt = AUDIO_FORMAT_U16;
 358        break;
 359
 360    case SND_PCM_FORMAT_S32_LE:
 361        *endianness = 0;
 362        *fmt = AUDIO_FORMAT_S32;
 363        break;
 364
 365    case SND_PCM_FORMAT_U32_LE:
 366        *endianness = 0;
 367        *fmt = AUDIO_FORMAT_U32;
 368        break;
 369
 370    case SND_PCM_FORMAT_S32_BE:
 371        *endianness = 1;
 372        *fmt = AUDIO_FORMAT_S32;
 373        break;
 374
 375    case SND_PCM_FORMAT_U32_BE:
 376        *endianness = 1;
 377        *fmt = AUDIO_FORMAT_U32;
 378        break;
 379
 380    default:
 381        dolog ("Unrecognized audio format %d\n", alsafmt);
 382        return -1;
 383    }
 384
 385    return 0;
 386}
 387
 388static void alsa_dump_info (struct alsa_params_req *req,
 389                            struct alsa_params_obt *obt,
 390                            snd_pcm_format_t obtfmt,
 391                            AudiodevAlsaPerDirectionOptions *apdo)
 392{
 393    dolog("parameter | requested value | obtained value\n");
 394    dolog("format    |      %10d |     %10d\n", req->fmt, obtfmt);
 395    dolog("channels  |      %10d |     %10d\n",
 396          req->nchannels, obt->nchannels);
 397    dolog("frequency |      %10d |     %10d\n", req->freq, obt->freq);
 398    dolog("============================================\n");
 399    dolog("requested: buffer len %" PRId32 " period len %" PRId32 "\n",
 400          apdo->buffer_length, apdo->period_length);
 401    dolog("obtained: samples %ld\n", obt->samples);
 402}
 403
 404static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
 405{
 406    int err;
 407    snd_pcm_sw_params_t *sw_params;
 408
 409    snd_pcm_sw_params_alloca (&sw_params);
 410
 411    err = snd_pcm_sw_params_current (handle, sw_params);
 412    if (err < 0) {
 413        dolog ("Could not fully initialize DAC\n");
 414        alsa_logerr (err, "Failed to get current software parameters\n");
 415        return;
 416    }
 417
 418    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
 419    if (err < 0) {
 420        dolog ("Could not fully initialize DAC\n");
 421        alsa_logerr (err, "Failed to set software threshold to %ld\n",
 422                     threshold);
 423        return;
 424    }
 425
 426    err = snd_pcm_sw_params (handle, sw_params);
 427    if (err < 0) {
 428        dolog ("Could not fully initialize DAC\n");
 429        alsa_logerr (err, "Failed to set software parameters\n");
 430        return;
 431    }
 432}
 433
 434static int alsa_open(bool in, struct alsa_params_req *req,
 435                     struct alsa_params_obt *obt, snd_pcm_t **handlep,
 436                     Audiodev *dev)
 437{
 438    AudiodevAlsaOptions *aopts = &dev->u.alsa;
 439    AudiodevAlsaPerDirectionOptions *apdo = in ? aopts->in : aopts->out;
 440    snd_pcm_t *handle;
 441    snd_pcm_hw_params_t *hw_params;
 442    int err;
 443    unsigned int freq, nchannels;
 444    const char *pcm_name = apdo->has_dev ? apdo->dev : "default";
 445    snd_pcm_uframes_t obt_buffer_size;
 446    const char *typ = in ? "ADC" : "DAC";
 447    snd_pcm_format_t obtfmt;
 448
 449    freq = req->freq;
 450    nchannels = req->nchannels;
 451
 452    snd_pcm_hw_params_alloca (&hw_params);
 453
 454    err = snd_pcm_open (
 455        &handle,
 456        pcm_name,
 457        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
 458        SND_PCM_NONBLOCK
 459        );
 460    if (err < 0) {
 461        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
 462        return -1;
 463    }
 464
 465    err = snd_pcm_hw_params_any (handle, hw_params);
 466    if (err < 0) {
 467        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
 468        goto err;
 469    }
 470
 471    err = snd_pcm_hw_params_set_access (
 472        handle,
 473        hw_params,
 474        SND_PCM_ACCESS_RW_INTERLEAVED
 475        );
 476    if (err < 0) {
 477        alsa_logerr2 (err, typ, "Failed to set access type\n");
 478        goto err;
 479    }
 480
 481    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
 482    if (err < 0) {
 483        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
 484    }
 485
 486    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
 487    if (err < 0) {
 488        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
 489        goto err;
 490    }
 491
 492    err = snd_pcm_hw_params_set_channels_near (
 493        handle,
 494        hw_params,
 495        &nchannels
 496        );
 497    if (err < 0) {
 498        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
 499                      req->nchannels);
 500        goto err;
 501    }
 502
 503    if (nchannels != 1 && nchannels != 2) {
 504        alsa_logerr2 (err, typ,
 505                      "Can not handle obtained number of channels %d\n",
 506                      nchannels);
 507        goto err;
 508    }
 509
 510    if (apdo->buffer_length) {
 511        int dir = 0;
 512        unsigned int btime = apdo->buffer_length;
 513
 514        err = snd_pcm_hw_params_set_buffer_time_near(
 515            handle, hw_params, &btime, &dir);
 516
 517        if (err < 0) {
 518            alsa_logerr2(err, typ, "Failed to set buffer time to %" PRId32 "\n",
 519                         apdo->buffer_length);
 520            goto err;
 521        }
 522
 523        if (apdo->has_buffer_length && btime != apdo->buffer_length) {
 524            dolog("Requested buffer time %" PRId32
 525                  " was rejected, using %u\n", apdo->buffer_length, btime);
 526        }
 527    }
 528
 529    if (apdo->period_length) {
 530        int dir = 0;
 531        unsigned int ptime = apdo->period_length;
 532
 533        err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &ptime,
 534                                                     &dir);
 535
 536        if (err < 0) {
 537            alsa_logerr2(err, typ, "Failed to set period time to %" PRId32 "\n",
 538                         apdo->period_length);
 539            goto err;
 540        }
 541
 542        if (apdo->has_period_length && ptime != apdo->period_length) {
 543            dolog("Requested period time %" PRId32 " was rejected, using %d\n",
 544                  apdo->period_length, ptime);
 545        }
 546    }
 547
 548    err = snd_pcm_hw_params (handle, hw_params);
 549    if (err < 0) {
 550        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
 551        goto err;
 552    }
 553
 554    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
 555    if (err < 0) {
 556        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
 557        goto err;
 558    }
 559
 560    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
 561    if (err < 0) {
 562        alsa_logerr2 (err, typ, "Failed to get format\n");
 563        goto err;
 564    }
 565
 566    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
 567        dolog ("Invalid format was returned %d\n", obtfmt);
 568        goto err;
 569    }
 570
 571    err = snd_pcm_prepare (handle);
 572    if (err < 0) {
 573        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
 574        goto err;
 575    }
 576
 577    if (!in && aopts->has_threshold && aopts->threshold) {
 578        struct audsettings as = { .freq = freq };
 579        alsa_set_threshold(
 580            handle,
 581            audio_buffer_frames(qapi_AudiodevAlsaPerDirectionOptions_base(apdo),
 582                                &as, aopts->threshold));
 583    }
 584
 585    obt->nchannels = nchannels;
 586    obt->freq = freq;
 587    obt->samples = obt_buffer_size;
 588
 589    *handlep = handle;
 590
 591    if (obtfmt != req->fmt ||
 592         obt->nchannels != req->nchannels ||
 593         obt->freq != req->freq) {
 594        dolog ("Audio parameters for %s\n", typ);
 595        alsa_dump_info(req, obt, obtfmt, apdo);
 596    }
 597
 598#ifdef DEBUG
 599    alsa_dump_info(req, obt, obtfmt, pdo);
 600#endif
 601    return 0;
 602
 603 err:
 604    alsa_anal_close1 (&handle);
 605    return -1;
 606}
 607
 608static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
 609{
 610    snd_pcm_sframes_t avail;
 611
 612    avail = snd_pcm_avail_update (handle);
 613    if (avail < 0) {
 614        if (avail == -EPIPE) {
 615            if (!alsa_recover (handle)) {
 616                avail = snd_pcm_avail_update (handle);
 617            }
 618        }
 619
 620        if (avail < 0) {
 621            alsa_logerr (avail,
 622                         "Could not obtain number of available frames\n");
 623            return -1;
 624        }
 625    }
 626
 627    return avail;
 628}
 629
 630static void alsa_write_pending (ALSAVoiceOut *alsa)
 631{
 632    HWVoiceOut *hw = &alsa->hw;
 633
 634    while (alsa->pending) {
 635        int left_till_end_samples = hw->samples - alsa->wpos;
 636        int len = audio_MIN (alsa->pending, left_till_end_samples);
 637        char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift);
 638
 639        while (len) {
 640            snd_pcm_sframes_t written;
 641
 642            written = snd_pcm_writei (alsa->handle, src, len);
 643
 644            if (written <= 0) {
 645                switch (written) {
 646                case 0:
 647                    trace_alsa_wrote_zero(len);
 648                    return;
 649
 650                case -EPIPE:
 651                    if (alsa_recover (alsa->handle)) {
 652                        alsa_logerr (written, "Failed to write %d frames\n",
 653                                     len);
 654                        return;
 655                    }
 656                    trace_alsa_xrun_out();
 657                    continue;
 658
 659                case -ESTRPIPE:
 660                    /* stream is suspended and waiting for an
 661                       application recovery */
 662                    if (alsa_resume (alsa->handle)) {
 663                        alsa_logerr (written, "Failed to write %d frames\n",
 664                                     len);
 665                        return;
 666                    }
 667                    trace_alsa_resume_out();
 668                    continue;
 669
 670                case -EAGAIN:
 671                    return;
 672
 673                default:
 674                    alsa_logerr (written, "Failed to write %d frames from %p\n",
 675                                 len, src);
 676                    return;
 677                }
 678            }
 679
 680            alsa->wpos = (alsa->wpos + written) % hw->samples;
 681            alsa->pending -= written;
 682            len -= written;
 683        }
 684    }
 685}
 686
 687static int alsa_run_out (HWVoiceOut *hw, int live)
 688{
 689    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 690    int decr;
 691    snd_pcm_sframes_t avail;
 692
 693    avail = alsa_get_avail (alsa->handle);
 694    if (avail < 0) {
 695        dolog ("Could not get number of available playback frames\n");
 696        return 0;
 697    }
 698
 699    decr = audio_MIN (live, avail);
 700    decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending);
 701    alsa->pending += decr;
 702    alsa_write_pending (alsa);
 703    return decr;
 704}
 705
 706static void alsa_fini_out (HWVoiceOut *hw)
 707{
 708    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 709
 710    ldebug ("alsa_fini\n");
 711    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
 712
 713    g_free(alsa->pcm_buf);
 714    alsa->pcm_buf = NULL;
 715}
 716
 717static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as,
 718                         void *drv_opaque)
 719{
 720    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 721    struct alsa_params_req req;
 722    struct alsa_params_obt obt;
 723    snd_pcm_t *handle;
 724    struct audsettings obt_as;
 725    Audiodev *dev = drv_opaque;
 726
 727    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
 728    req.freq = as->freq;
 729    req.nchannels = as->nchannels;
 730
 731    if (alsa_open(0, &req, &obt, &handle, dev)) {
 732        return -1;
 733    }
 734
 735    obt_as.freq = obt.freq;
 736    obt_as.nchannels = obt.nchannels;
 737    obt_as.fmt = obt.fmt;
 738    obt_as.endianness = obt.endianness;
 739
 740    audio_pcm_init_info (&hw->info, &obt_as);
 741    hw->samples = obt.samples;
 742
 743    alsa->pcm_buf = audio_calloc(__func__, obt.samples, 1 << hw->info.shift);
 744    if (!alsa->pcm_buf) {
 745        dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
 746               hw->samples, 1 << hw->info.shift);
 747        alsa_anal_close1 (&handle);
 748        return -1;
 749    }
 750
 751    alsa->handle = handle;
 752    alsa->dev = dev;
 753    return 0;
 754}
 755
 756#define VOICE_CTL_PAUSE 0
 757#define VOICE_CTL_PREPARE 1
 758#define VOICE_CTL_START 2
 759
 760static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
 761{
 762    int err;
 763
 764    if (ctl == VOICE_CTL_PAUSE) {
 765        err = snd_pcm_drop (handle);
 766        if (err < 0) {
 767            alsa_logerr (err, "Could not stop %s\n", typ);
 768            return -1;
 769        }
 770    }
 771    else {
 772        err = snd_pcm_prepare (handle);
 773        if (err < 0) {
 774            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
 775            return -1;
 776        }
 777        if (ctl == VOICE_CTL_START) {
 778            err = snd_pcm_start(handle);
 779            if (err < 0) {
 780                alsa_logerr (err, "Could not start handle for %s\n", typ);
 781                return -1;
 782            }
 783        }
 784    }
 785
 786    return 0;
 787}
 788
 789static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
 790{
 791    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 792    AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out;
 793
 794    switch (cmd) {
 795    case VOICE_ENABLE:
 796        {
 797            bool poll_mode = apdo->try_poll;
 798
 799            ldebug ("enabling voice\n");
 800            if (poll_mode && alsa_poll_out (hw)) {
 801                poll_mode = 0;
 802            }
 803            hw->poll_mode = poll_mode;
 804            return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE);
 805        }
 806
 807    case VOICE_DISABLE:
 808        ldebug ("disabling voice\n");
 809        if (hw->poll_mode) {
 810            hw->poll_mode = 0;
 811            alsa_fini_poll (&alsa->pollhlp);
 812        }
 813        return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE);
 814    }
 815
 816    return -1;
 817}
 818
 819static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 820{
 821    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 822    struct alsa_params_req req;
 823    struct alsa_params_obt obt;
 824    snd_pcm_t *handle;
 825    struct audsettings obt_as;
 826    Audiodev *dev = drv_opaque;
 827
 828    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
 829    req.freq = as->freq;
 830    req.nchannels = as->nchannels;
 831
 832    if (alsa_open(1, &req, &obt, &handle, dev)) {
 833        return -1;
 834    }
 835
 836    obt_as.freq = obt.freq;
 837    obt_as.nchannels = obt.nchannels;
 838    obt_as.fmt = obt.fmt;
 839    obt_as.endianness = obt.endianness;
 840
 841    audio_pcm_init_info (&hw->info, &obt_as);
 842    hw->samples = obt.samples;
 843
 844    alsa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
 845    if (!alsa->pcm_buf) {
 846        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
 847               hw->samples, 1 << hw->info.shift);
 848        alsa_anal_close1 (&handle);
 849        return -1;
 850    }
 851
 852    alsa->handle = handle;
 853    alsa->dev = dev;
 854    return 0;
 855}
 856
 857static void alsa_fini_in (HWVoiceIn *hw)
 858{
 859    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 860
 861    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
 862
 863    g_free(alsa->pcm_buf);
 864    alsa->pcm_buf = NULL;
 865}
 866
 867static int alsa_run_in (HWVoiceIn *hw)
 868{
 869    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 870    int hwshift = hw->info.shift;
 871    int i;
 872    int live = audio_pcm_hw_get_live_in (hw);
 873    int dead = hw->samples - live;
 874    int decr;
 875    struct {
 876        int add;
 877        int len;
 878    } bufs[2] = {
 879        { .add = hw->wpos, .len = 0 },
 880        { .add = 0,        .len = 0 }
 881    };
 882    snd_pcm_sframes_t avail;
 883    snd_pcm_uframes_t read_samples = 0;
 884
 885    if (!dead) {
 886        return 0;
 887    }
 888
 889    avail = alsa_get_avail (alsa->handle);
 890    if (avail < 0) {
 891        dolog ("Could not get number of captured frames\n");
 892        return 0;
 893    }
 894
 895    if (!avail) {
 896        snd_pcm_state_t state;
 897
 898        state = snd_pcm_state (alsa->handle);
 899        switch (state) {
 900        case SND_PCM_STATE_PREPARED:
 901            avail = hw->samples;
 902            break;
 903        case SND_PCM_STATE_SUSPENDED:
 904            /* stream is suspended and waiting for an application recovery */
 905            if (alsa_resume (alsa->handle)) {
 906                dolog ("Failed to resume suspended input stream\n");
 907                return 0;
 908            }
 909            trace_alsa_resume_in();
 910            break;
 911        default:
 912            trace_alsa_no_frames(state);
 913            return 0;
 914        }
 915    }
 916
 917    decr = audio_MIN (dead, avail);
 918    if (!decr) {
 919        return 0;
 920    }
 921
 922    if (hw->wpos + decr > hw->samples) {
 923        bufs[0].len = (hw->samples - hw->wpos);
 924        bufs[1].len = (decr - (hw->samples - hw->wpos));
 925    }
 926    else {
 927        bufs[0].len = decr;
 928    }
 929
 930    for (i = 0; i < 2; ++i) {
 931        void *src;
 932        struct st_sample *dst;
 933        snd_pcm_sframes_t nread;
 934        snd_pcm_uframes_t len;
 935
 936        len = bufs[i].len;
 937
 938        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
 939        dst = hw->conv_buf + bufs[i].add;
 940
 941        while (len) {
 942            nread = snd_pcm_readi (alsa->handle, src, len);
 943
 944            if (nread <= 0) {
 945                switch (nread) {
 946                case 0:
 947                    trace_alsa_read_zero(len);
 948                    goto exit;
 949
 950                case -EPIPE:
 951                    if (alsa_recover (alsa->handle)) {
 952                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
 953                        goto exit;
 954                    }
 955                    trace_alsa_xrun_in();
 956                    continue;
 957
 958                case -EAGAIN:
 959                    goto exit;
 960
 961                default:
 962                    alsa_logerr (
 963                        nread,
 964                        "Failed to read %ld frames from %p\n",
 965                        len,
 966                        src
 967                        );
 968                    goto exit;
 969                }
 970            }
 971
 972            hw->conv (dst, src, nread);
 973
 974            src = advance (src, nread << hwshift);
 975            dst += nread;
 976
 977            read_samples += nread;
 978            len -= nread;
 979        }
 980    }
 981
 982 exit:
 983    hw->wpos = (hw->wpos + read_samples) % hw->samples;
 984    return read_samples;
 985}
 986
 987static int alsa_read (SWVoiceIn *sw, void *buf, int size)
 988{
 989    return audio_pcm_sw_read (sw, buf, size);
 990}
 991
 992static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
 993{
 994    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 995    AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in;
 996
 997    switch (cmd) {
 998    case VOICE_ENABLE:
 999        {
1000            bool poll_mode = apdo->try_poll;
1001
1002            ldebug ("enabling voice\n");
1003            if (poll_mode && alsa_poll_in (hw)) {
1004                poll_mode = 0;
1005            }
1006            hw->poll_mode = poll_mode;
1007
1008            return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START);
1009        }
1010
1011    case VOICE_DISABLE:
1012        ldebug ("disabling voice\n");
1013        if (hw->poll_mode) {
1014            hw->poll_mode = 0;
1015            alsa_fini_poll (&alsa->pollhlp);
1016        }
1017        return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE);
1018    }
1019
1020    return -1;
1021}
1022
1023static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
1024{
1025    if (!apdo->has_try_poll) {
1026        apdo->try_poll = true;
1027        apdo->has_try_poll = true;
1028    }
1029}
1030
1031static void *alsa_audio_init(Audiodev *dev)
1032{
1033    AudiodevAlsaOptions *aopts;
1034    assert(dev->driver == AUDIODEV_DRIVER_ALSA);
1035
1036    aopts = &dev->u.alsa;
1037    alsa_init_per_direction(aopts->in);
1038    alsa_init_per_direction(aopts->out);
1039
1040    /*
1041     * need to define them, as otherwise alsa produces no sound
1042     * doesn't set has_* so alsa_open can identify it wasn't set by the user
1043     */
1044    if (!dev->u.alsa.out->has_period_length) {
1045        /* 1024 frames assuming 44100Hz */
1046        dev->u.alsa.out->period_length = 1024 * 1000000 / 44100;
1047    }
1048    if (!dev->u.alsa.out->has_buffer_length) {
1049        /* 4096 frames assuming 44100Hz */
1050        dev->u.alsa.out->buffer_length = 4096ll * 1000000 / 44100;
1051    }
1052
1053    /*
1054     * OptsVisitor sets unspecified optional fields to zero, but do not depend
1055     * on it...
1056     */
1057    if (!dev->u.alsa.in->has_period_length) {
1058        dev->u.alsa.in->period_length = 0;
1059    }
1060    if (!dev->u.alsa.in->has_buffer_length) {
1061        dev->u.alsa.in->buffer_length = 0;
1062    }
1063
1064    return dev;
1065}
1066
1067static void alsa_audio_fini (void *opaque)
1068{
1069}
1070
1071static struct audio_pcm_ops alsa_pcm_ops = {
1072    .init_out = alsa_init_out,
1073    .fini_out = alsa_fini_out,
1074    .run_out  = alsa_run_out,
1075    .write    = alsa_write,
1076    .ctl_out  = alsa_ctl_out,
1077
1078    .init_in  = alsa_init_in,
1079    .fini_in  = alsa_fini_in,
1080    .run_in   = alsa_run_in,
1081    .read     = alsa_read,
1082    .ctl_in   = alsa_ctl_in,
1083};
1084
1085static struct audio_driver alsa_audio_driver = {
1086    .name           = "alsa",
1087    .descr          = "ALSA http://www.alsa-project.org",
1088    .init           = alsa_audio_init,
1089    .fini           = alsa_audio_fini,
1090    .pcm_ops        = &alsa_pcm_ops,
1091    .can_be_default = 1,
1092    .max_voices_out = INT_MAX,
1093    .max_voices_in  = INT_MAX,
1094    .voice_size_out = sizeof (ALSAVoiceOut),
1095    .voice_size_in  = sizeof (ALSAVoiceIn)
1096};
1097
1098static void register_audio_alsa(void)
1099{
1100    audio_driver_register(&alsa_audio_driver);
1101}
1102type_init(register_audio_alsa);
1103