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 <alsa/asoundlib.h>
  25#include "qemu-common.h"
  26#include "audio.h"
  27
  28#if QEMU_GNUC_PREREQ(4, 3)
  29#pragma GCC diagnostic ignored "-Waddress"
  30#endif
  31
  32#define AUDIO_CAP "alsa"
  33#include "audio_int.h"
  34
  35typedef struct ALSAVoiceOut {
  36    HWVoiceOut hw;
  37    void *pcm_buf;
  38    snd_pcm_t *handle;
  39} ALSAVoiceOut;
  40
  41typedef struct ALSAVoiceIn {
  42    HWVoiceIn hw;
  43    snd_pcm_t *handle;
  44    void *pcm_buf;
  45} ALSAVoiceIn;
  46
  47static struct {
  48    int size_in_usec_in;
  49    int size_in_usec_out;
  50    const char *pcm_name_in;
  51    const char *pcm_name_out;
  52    unsigned int buffer_size_in;
  53    unsigned int period_size_in;
  54    unsigned int buffer_size_out;
  55    unsigned int period_size_out;
  56    unsigned int threshold;
  57
  58    int buffer_size_in_overridden;
  59    int period_size_in_overridden;
  60
  61    int buffer_size_out_overridden;
  62    int period_size_out_overridden;
  63    int verbose;
  64} conf = {
  65    .buffer_size_out = 1024,
  66    .pcm_name_out = "default",
  67    .pcm_name_in = "default",
  68};
  69
  70struct alsa_params_req {
  71    int freq;
  72    snd_pcm_format_t fmt;
  73    int nchannels;
  74    int size_in_usec;
  75    int override_mask;
  76    unsigned int buffer_size;
  77    unsigned int period_size;
  78};
  79
  80struct alsa_params_obt {
  81    int freq;
  82    audfmt_e fmt;
  83    int endianness;
  84    int nchannels;
  85    snd_pcm_uframes_t samples;
  86};
  87
  88static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
  89{
  90    va_list ap;
  91
  92    va_start (ap, fmt);
  93    AUD_vlog (AUDIO_CAP, fmt, ap);
  94    va_end (ap);
  95
  96    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
  97}
  98
  99static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
 100    int err,
 101    const char *typ,
 102    const char *fmt,
 103    ...
 104    )
 105{
 106    va_list ap;
 107
 108    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
 109
 110    va_start (ap, fmt);
 111    AUD_vlog (AUDIO_CAP, fmt, ap);
 112    va_end (ap);
 113
 114    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
 115}
 116
 117static void alsa_anal_close (snd_pcm_t **handlep)
 118{
 119    int err = snd_pcm_close (*handlep);
 120    if (err) {
 121        alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
 122    }
 123    *handlep = NULL;
 124}
 125
 126static int alsa_write (SWVoiceOut *sw, void *buf, int len)
 127{
 128    return audio_pcm_sw_write (sw, buf, len);
 129}
 130
 131static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
 132{
 133    switch (fmt) {
 134    case AUD_FMT_S8:
 135        return SND_PCM_FORMAT_S8;
 136
 137    case AUD_FMT_U8:
 138        return SND_PCM_FORMAT_U8;
 139
 140    case AUD_FMT_S16:
 141        return SND_PCM_FORMAT_S16_LE;
 142
 143    case AUD_FMT_U16:
 144        return SND_PCM_FORMAT_U16_LE;
 145
 146    case AUD_FMT_S32:
 147        return SND_PCM_FORMAT_S32_LE;
 148
 149    case AUD_FMT_U32:
 150        return SND_PCM_FORMAT_U32_LE;
 151
 152    default:
 153        dolog ("Internal logic error: Bad audio format %d\n", fmt);
 154#ifdef DEBUG_AUDIO
 155        abort ();
 156#endif
 157        return SND_PCM_FORMAT_U8;
 158    }
 159}
 160
 161static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt,
 162                           int *endianness)
 163{
 164    switch (alsafmt) {
 165    case SND_PCM_FORMAT_S8:
 166        *endianness = 0;
 167        *fmt = AUD_FMT_S8;
 168        break;
 169
 170    case SND_PCM_FORMAT_U8:
 171        *endianness = 0;
 172        *fmt = AUD_FMT_U8;
 173        break;
 174
 175    case SND_PCM_FORMAT_S16_LE:
 176        *endianness = 0;
 177        *fmt = AUD_FMT_S16;
 178        break;
 179
 180    case SND_PCM_FORMAT_U16_LE:
 181        *endianness = 0;
 182        *fmt = AUD_FMT_U16;
 183        break;
 184
 185    case SND_PCM_FORMAT_S16_BE:
 186        *endianness = 1;
 187        *fmt = AUD_FMT_S16;
 188        break;
 189
 190    case SND_PCM_FORMAT_U16_BE:
 191        *endianness = 1;
 192        *fmt = AUD_FMT_U16;
 193        break;
 194
 195    case SND_PCM_FORMAT_S32_LE:
 196        *endianness = 0;
 197        *fmt = AUD_FMT_S32;
 198        break;
 199
 200    case SND_PCM_FORMAT_U32_LE:
 201        *endianness = 0;
 202        *fmt = AUD_FMT_U32;
 203        break;
 204
 205    case SND_PCM_FORMAT_S32_BE:
 206        *endianness = 1;
 207        *fmt = AUD_FMT_S32;
 208        break;
 209
 210    case SND_PCM_FORMAT_U32_BE:
 211        *endianness = 1;
 212        *fmt = AUD_FMT_U32;
 213        break;
 214
 215    default:
 216        dolog ("Unrecognized audio format %d\n", alsafmt);
 217        return -1;
 218    }
 219
 220    return 0;
 221}
 222
 223static void alsa_dump_info (struct alsa_params_req *req,
 224                            struct alsa_params_obt *obt)
 225{
 226    dolog ("parameter | requested value | obtained value\n");
 227    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
 228    dolog ("channels  |      %10d |     %10d\n",
 229           req->nchannels, obt->nchannels);
 230    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
 231    dolog ("============================================\n");
 232    dolog ("requested: buffer size %d period size %d\n",
 233           req->buffer_size, req->period_size);
 234    dolog ("obtained: samples %ld\n", obt->samples);
 235}
 236
 237static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
 238{
 239    int err;
 240    snd_pcm_sw_params_t *sw_params;
 241
 242    snd_pcm_sw_params_alloca (&sw_params);
 243
 244    err = snd_pcm_sw_params_current (handle, sw_params);
 245    if (err < 0) {
 246        dolog ("Could not fully initialize DAC\n");
 247        alsa_logerr (err, "Failed to get current software parameters\n");
 248        return;
 249    }
 250
 251    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
 252    if (err < 0) {
 253        dolog ("Could not fully initialize DAC\n");
 254        alsa_logerr (err, "Failed to set software threshold to %ld\n",
 255                     threshold);
 256        return;
 257    }
 258
 259    err = snd_pcm_sw_params (handle, sw_params);
 260    if (err < 0) {
 261        dolog ("Could not fully initialize DAC\n");
 262        alsa_logerr (err, "Failed to set software parameters\n");
 263        return;
 264    }
 265}
 266
 267static int alsa_open (int in, struct alsa_params_req *req,
 268                      struct alsa_params_obt *obt, snd_pcm_t **handlep)
 269{
 270    snd_pcm_t *handle;
 271    snd_pcm_hw_params_t *hw_params;
 272    int err;
 273    int size_in_usec;
 274    unsigned int freq, nchannels;
 275    const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
 276    snd_pcm_uframes_t obt_buffer_size;
 277    const char *typ = in ? "ADC" : "DAC";
 278    snd_pcm_format_t obtfmt;
 279
 280    freq = req->freq;
 281    nchannels = req->nchannels;
 282    size_in_usec = req->size_in_usec;
 283
 284    snd_pcm_hw_params_alloca (&hw_params);
 285
 286    err = snd_pcm_open (
 287        &handle,
 288        pcm_name,
 289        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
 290        SND_PCM_NONBLOCK
 291        );
 292    if (err < 0) {
 293        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
 294        return -1;
 295    }
 296
 297    err = snd_pcm_hw_params_any (handle, hw_params);
 298    if (err < 0) {
 299        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
 300        goto err;
 301    }
 302
 303    err = snd_pcm_hw_params_set_access (
 304        handle,
 305        hw_params,
 306        SND_PCM_ACCESS_RW_INTERLEAVED
 307        );
 308    if (err < 0) {
 309        alsa_logerr2 (err, typ, "Failed to set access type\n");
 310        goto err;
 311    }
 312
 313    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
 314    if (err < 0 && conf.verbose) {
 315        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
 316    }
 317
 318    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
 319    if (err < 0) {
 320        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
 321        goto err;
 322    }
 323
 324    err = snd_pcm_hw_params_set_channels_near (
 325        handle,
 326        hw_params,
 327        &nchannels
 328        );
 329    if (err < 0) {
 330        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
 331                      req->nchannels);
 332        goto err;
 333    }
 334
 335    if (nchannels != 1 && nchannels != 2) {
 336        alsa_logerr2 (err, typ,
 337                      "Can not handle obtained number of channels %d\n",
 338                      nchannels);
 339        goto err;
 340    }
 341
 342    if (req->buffer_size) {
 343        unsigned long obt;
 344
 345        if (size_in_usec) {
 346            int dir = 0;
 347            unsigned int btime = req->buffer_size;
 348
 349            err = snd_pcm_hw_params_set_buffer_time_near (
 350                handle,
 351                hw_params,
 352                &btime,
 353                &dir
 354                );
 355            obt = btime;
 356        }
 357        else {
 358            snd_pcm_uframes_t bsize = req->buffer_size;
 359
 360            err = snd_pcm_hw_params_set_buffer_size_near (
 361                handle,
 362                hw_params,
 363                &bsize
 364                );
 365            obt = bsize;
 366        }
 367        if (err < 0) {
 368            alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n",
 369                          size_in_usec ? "time" : "size", req->buffer_size);
 370            goto err;
 371        }
 372
 373        if ((req->override_mask & 2) && (obt - req->buffer_size))
 374            dolog ("Requested buffer %s %u was rejected, using %lu\n",
 375                   size_in_usec ? "time" : "size", req->buffer_size, obt);
 376    }
 377
 378    if (req->period_size) {
 379        unsigned long obt;
 380
 381        if (size_in_usec) {
 382            int dir = 0;
 383            unsigned int ptime = req->period_size;
 384
 385            err = snd_pcm_hw_params_set_period_time_near (
 386                handle,
 387                hw_params,
 388                &ptime,
 389                &dir
 390                );
 391            obt = ptime;
 392        }
 393        else {
 394            int dir = 0;
 395            snd_pcm_uframes_t psize = req->period_size;
 396
 397            err = snd_pcm_hw_params_set_period_size_near (
 398                handle,
 399                hw_params,
 400                &psize,
 401                &dir
 402                );
 403            obt = psize;
 404        }
 405
 406        if (err < 0) {
 407            alsa_logerr2 (err, typ, "Failed to set period %s to %d\n",
 408                          size_in_usec ? "time" : "size", req->period_size);
 409            goto err;
 410        }
 411
 412        if ((req->override_mask & 1) && (obt - req->period_size))
 413            dolog ("Requested period %s %u was rejected, using %lu\n",
 414                   size_in_usec ? "time" : "size", req->period_size, obt);
 415    }
 416
 417    err = snd_pcm_hw_params (handle, hw_params);
 418    if (err < 0) {
 419        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
 420        goto err;
 421    }
 422
 423    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
 424    if (err < 0) {
 425        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
 426        goto err;
 427    }
 428
 429    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
 430    if (err < 0) {
 431        alsa_logerr2 (err, typ, "Failed to get format\n");
 432        goto err;
 433    }
 434
 435    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
 436        dolog ("Invalid format was returned %d\n", obtfmt);
 437        goto err;
 438    }
 439
 440    err = snd_pcm_prepare (handle);
 441    if (err < 0) {
 442        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
 443        goto err;
 444    }
 445
 446    if (!in && conf.threshold) {
 447        snd_pcm_uframes_t threshold;
 448        int bytes_per_sec;
 449
 450        bytes_per_sec = freq << (nchannels == 2);
 451
 452        switch (obt->fmt) {
 453        case AUD_FMT_S8:
 454        case AUD_FMT_U8:
 455            break;
 456
 457        case AUD_FMT_S16:
 458        case AUD_FMT_U16:
 459            bytes_per_sec <<= 1;
 460            break;
 461
 462        case AUD_FMT_S32:
 463        case AUD_FMT_U32:
 464            bytes_per_sec <<= 2;
 465            break;
 466        }
 467
 468        threshold = (conf.threshold * bytes_per_sec) / 1000;
 469        alsa_set_threshold (handle, threshold);
 470    }
 471
 472    obt->nchannels = nchannels;
 473    obt->freq = freq;
 474    obt->samples = obt_buffer_size;
 475
 476    *handlep = handle;
 477
 478    if (conf.verbose &&
 479        (obt->fmt != req->fmt ||
 480         obt->nchannels != req->nchannels ||
 481         obt->freq != req->freq)) {
 482        dolog ("Audio paramters for %s\n", typ);
 483        alsa_dump_info (req, obt);
 484    }
 485
 486#ifdef DEBUG
 487    alsa_dump_info (req, obt);
 488#endif
 489    return 0;
 490
 491 err:
 492    alsa_anal_close (&handle);
 493    return -1;
 494}
 495
 496static int alsa_recover (snd_pcm_t *handle)
 497{
 498    int err = snd_pcm_prepare (handle);
 499    if (err < 0) {
 500        alsa_logerr (err, "Failed to prepare handle %p\n", handle);
 501        return -1;
 502    }
 503    return 0;
 504}
 505
 506static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
 507{
 508    snd_pcm_sframes_t avail;
 509
 510    avail = snd_pcm_avail_update (handle);
 511    if (avail < 0) {
 512        if (avail == -EPIPE) {
 513            if (!alsa_recover (handle)) {
 514                avail = snd_pcm_avail_update (handle);
 515            }
 516        }
 517
 518        if (avail < 0) {
 519            alsa_logerr (avail,
 520                         "Could not obtain number of available frames\n");
 521            return -1;
 522        }
 523    }
 524
 525    return avail;
 526}
 527
 528static int alsa_run_out (HWVoiceOut *hw)
 529{
 530    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 531    int rpos, live, decr;
 532    int samples;
 533    uint8_t *dst;
 534    struct st_sample *src;
 535    snd_pcm_sframes_t avail;
 536
 537    live = audio_pcm_hw_get_live_out (hw);
 538    if (!live) {
 539        return 0;
 540    }
 541
 542    avail = alsa_get_avail (alsa->handle);
 543    if (avail < 0) {
 544        dolog ("Could not get number of available playback frames\n");
 545        return 0;
 546    }
 547
 548    decr = audio_MIN (live, avail);
 549    samples = decr;
 550    rpos = hw->rpos;
 551    while (samples) {
 552        int left_till_end_samples = hw->samples - rpos;
 553        int len = audio_MIN (samples, left_till_end_samples);
 554        snd_pcm_sframes_t written;
 555
 556        src = hw->mix_buf + rpos;
 557        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
 558
 559        hw->clip (dst, src, len);
 560
 561        while (len) {
 562            written = snd_pcm_writei (alsa->handle, dst, len);
 563
 564            if (written <= 0) {
 565                switch (written) {
 566                case 0:
 567                    if (conf.verbose) {
 568                        dolog ("Failed to write %d frames (wrote zero)\n", len);
 569                    }
 570                    goto exit;
 571
 572                case -EPIPE:
 573                    if (alsa_recover (alsa->handle)) {
 574                        alsa_logerr (written, "Failed to write %d frames\n",
 575                                     len);
 576                        goto exit;
 577                    }
 578                    if (conf.verbose) {
 579                        dolog ("Recovering from playback xrun\n");
 580                    }
 581                    continue;
 582
 583                case -EAGAIN:
 584                    goto exit;
 585
 586                default:
 587                    alsa_logerr (written, "Failed to write %d frames to %p\n",
 588                                 len, dst);
 589                    goto exit;
 590                }
 591            }
 592
 593            rpos = (rpos + written) % hw->samples;
 594            samples -= written;
 595            len -= written;
 596            dst = advance (dst, written << hw->info.shift);
 597            src += written;
 598        }
 599    }
 600
 601 exit:
 602    hw->rpos = rpos;
 603    return decr;
 604}
 605
 606static void alsa_fini_out (HWVoiceOut *hw)
 607{
 608    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 609
 610    ldebug ("alsa_fini\n");
 611    alsa_anal_close (&alsa->handle);
 612
 613    if (alsa->pcm_buf) {
 614        qemu_free (alsa->pcm_buf);
 615        alsa->pcm_buf = NULL;
 616    }
 617}
 618
 619static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
 620{
 621    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 622    struct alsa_params_req req;
 623    struct alsa_params_obt obt;
 624    snd_pcm_t *handle;
 625    struct audsettings obt_as;
 626
 627    req.fmt = aud_to_alsafmt (as->fmt);
 628    req.freq = as->freq;
 629    req.nchannels = as->nchannels;
 630    req.period_size = conf.period_size_out;
 631    req.buffer_size = conf.buffer_size_out;
 632    req.size_in_usec = conf.size_in_usec_out;
 633    req.override_mask =
 634        (conf.period_size_out_overridden ? 1 : 0) |
 635        (conf.buffer_size_out_overridden ? 2 : 0);
 636
 637    if (alsa_open (0, &req, &obt, &handle)) {
 638        return -1;
 639    }
 640
 641    obt_as.freq = obt.freq;
 642    obt_as.nchannels = obt.nchannels;
 643    obt_as.fmt = obt.fmt;
 644    obt_as.endianness = obt.endianness;
 645
 646    audio_pcm_init_info (&hw->info, &obt_as);
 647    hw->samples = obt.samples;
 648
 649    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
 650    if (!alsa->pcm_buf) {
 651        dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
 652               hw->samples, 1 << hw->info.shift);
 653        alsa_anal_close (&handle);
 654        return -1;
 655    }
 656
 657    alsa->handle = handle;
 658    return 0;
 659}
 660
 661static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
 662{
 663    int err;
 664
 665    if (pause) {
 666        err = snd_pcm_drop (handle);
 667        if (err < 0) {
 668            alsa_logerr (err, "Could not stop %s\n", typ);
 669            return -1;
 670        }
 671    }
 672    else {
 673        err = snd_pcm_prepare (handle);
 674        if (err < 0) {
 675            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
 676            return -1;
 677        }
 678    }
 679
 680    return 0;
 681}
 682
 683static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
 684{
 685    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 686
 687    switch (cmd) {
 688    case VOICE_ENABLE:
 689        ldebug ("enabling voice\n");
 690        return alsa_voice_ctl (alsa->handle, "playback", 0);
 691
 692    case VOICE_DISABLE:
 693        ldebug ("disabling voice\n");
 694        return alsa_voice_ctl (alsa->handle, "playback", 1);
 695    }
 696
 697    return -1;
 698}
 699
 700static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
 701{
 702    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 703    struct alsa_params_req req;
 704    struct alsa_params_obt obt;
 705    snd_pcm_t *handle;
 706    struct audsettings obt_as;
 707
 708    req.fmt = aud_to_alsafmt (as->fmt);
 709    req.freq = as->freq;
 710    req.nchannels = as->nchannels;
 711    req.period_size = conf.period_size_in;
 712    req.buffer_size = conf.buffer_size_in;
 713    req.size_in_usec = conf.size_in_usec_in;
 714    req.override_mask =
 715        (conf.period_size_in_overridden ? 1 : 0) |
 716        (conf.buffer_size_in_overridden ? 2 : 0);
 717
 718    if (alsa_open (1, &req, &obt, &handle)) {
 719        return -1;
 720    }
 721
 722    obt_as.freq = obt.freq;
 723    obt_as.nchannels = obt.nchannels;
 724    obt_as.fmt = obt.fmt;
 725    obt_as.endianness = obt.endianness;
 726
 727    audio_pcm_init_info (&hw->info, &obt_as);
 728    hw->samples = obt.samples;
 729
 730    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
 731    if (!alsa->pcm_buf) {
 732        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
 733               hw->samples, 1 << hw->info.shift);
 734        alsa_anal_close (&handle);
 735        return -1;
 736    }
 737
 738    alsa->handle = handle;
 739    return 0;
 740}
 741
 742static void alsa_fini_in (HWVoiceIn *hw)
 743{
 744    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 745
 746    alsa_anal_close (&alsa->handle);
 747
 748    if (alsa->pcm_buf) {
 749        qemu_free (alsa->pcm_buf);
 750        alsa->pcm_buf = NULL;
 751    }
 752}
 753
 754static int alsa_run_in (HWVoiceIn *hw)
 755{
 756    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 757    int hwshift = hw->info.shift;
 758    int i;
 759    int live = audio_pcm_hw_get_live_in (hw);
 760    int dead = hw->samples - live;
 761    int decr;
 762    struct {
 763        int add;
 764        int len;
 765    } bufs[2] = {
 766        { hw->wpos, 0 },
 767        { 0, 0 }
 768    };
 769    snd_pcm_sframes_t avail;
 770    snd_pcm_uframes_t read_samples = 0;
 771
 772    if (!dead) {
 773        return 0;
 774    }
 775
 776    avail = alsa_get_avail (alsa->handle);
 777    if (avail < 0) {
 778        dolog ("Could not get number of captured frames\n");
 779        return 0;
 780    }
 781
 782    if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) {
 783        avail = hw->samples;
 784    }
 785
 786    decr = audio_MIN (dead, avail);
 787    if (!decr) {
 788        return 0;
 789    }
 790
 791    if (hw->wpos + decr > hw->samples) {
 792        bufs[0].len = (hw->samples - hw->wpos);
 793        bufs[1].len = (decr - (hw->samples - hw->wpos));
 794    }
 795    else {
 796        bufs[0].len = decr;
 797    }
 798
 799    for (i = 0; i < 2; ++i) {
 800        void *src;
 801        struct st_sample *dst;
 802        snd_pcm_sframes_t nread;
 803        snd_pcm_uframes_t len;
 804
 805        len = bufs[i].len;
 806
 807        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
 808        dst = hw->conv_buf + bufs[i].add;
 809
 810        while (len) {
 811            nread = snd_pcm_readi (alsa->handle, src, len);
 812
 813            if (nread <= 0) {
 814                switch (nread) {
 815                case 0:
 816                    if (conf.verbose) {
 817                        dolog ("Failed to read %ld frames (read zero)\n", len);
 818                    }
 819                    goto exit;
 820
 821                case -EPIPE:
 822                    if (alsa_recover (alsa->handle)) {
 823                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
 824                        goto exit;
 825                    }
 826                    if (conf.verbose) {
 827                        dolog ("Recovering from capture xrun\n");
 828                    }
 829                    continue;
 830
 831                case -EAGAIN:
 832                    goto exit;
 833
 834                default:
 835                    alsa_logerr (
 836                        nread,
 837                        "Failed to read %ld frames from %p\n",
 838                        len,
 839                        src
 840                        );
 841                    goto exit;
 842                }
 843            }
 844
 845            hw->conv (dst, src, nread, &nominal_volume);
 846
 847            src = advance (src, nread << hwshift);
 848            dst += nread;
 849
 850            read_samples += nread;
 851            len -= nread;
 852        }
 853    }
 854
 855 exit:
 856    hw->wpos = (hw->wpos + read_samples) % hw->samples;
 857    return read_samples;
 858}
 859
 860static int alsa_read (SWVoiceIn *sw, void *buf, int size)
 861{
 862    return audio_pcm_sw_read (sw, buf, size);
 863}
 864
 865static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
 866{
 867    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 868
 869    switch (cmd) {
 870    case VOICE_ENABLE:
 871        ldebug ("enabling voice\n");
 872        return alsa_voice_ctl (alsa->handle, "capture", 0);
 873
 874    case VOICE_DISABLE:
 875        ldebug ("disabling voice\n");
 876        return alsa_voice_ctl (alsa->handle, "capture", 1);
 877    }
 878
 879    return -1;
 880}
 881
 882static void *alsa_audio_init (void)
 883{
 884    return &conf;
 885}
 886
 887static void alsa_audio_fini (void *opaque)
 888{
 889    (void) opaque;
 890}
 891
 892static struct audio_option alsa_options[] = {
 893    {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
 894     "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
 895    {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
 896     "DAC period size (0 to go with system default)",
 897     &conf.period_size_out_overridden, 0},
 898    {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
 899     "DAC buffer size (0 to go with system default)",
 900     &conf.buffer_size_out_overridden, 0},
 901
 902    {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
 903     "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
 904    {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
 905     "ADC period size (0 to go with system default)",
 906     &conf.period_size_in_overridden, 0},
 907    {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
 908     "ADC buffer size (0 to go with system default)",
 909     &conf.buffer_size_in_overridden, 0},
 910
 911    {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
 912     "(undocumented)", NULL, 0},
 913
 914    {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
 915     "DAC device name (for instance dmix)", NULL, 0},
 916
 917    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
 918     "ADC device name", NULL, 0},
 919
 920    {"VERBOSE", AUD_OPT_BOOL, &conf.verbose,
 921     "Behave in a more verbose way", NULL, 0},
 922
 923    {NULL, 0, NULL, NULL, NULL, 0}
 924};
 925
 926static struct audio_pcm_ops alsa_pcm_ops = {
 927    alsa_init_out,
 928    alsa_fini_out,
 929    alsa_run_out,
 930    alsa_write,
 931    alsa_ctl_out,
 932
 933    alsa_init_in,
 934    alsa_fini_in,
 935    alsa_run_in,
 936    alsa_read,
 937    alsa_ctl_in
 938};
 939
 940struct audio_driver alsa_audio_driver = {
 941    INIT_FIELD (name           = ) "alsa",
 942    INIT_FIELD (descr          = ) "ALSA http://www.alsa-project.org",
 943    INIT_FIELD (options        = ) alsa_options,
 944    INIT_FIELD (init           = ) alsa_audio_init,
 945    INIT_FIELD (fini           = ) alsa_audio_fini,
 946    INIT_FIELD (pcm_ops        = ) &alsa_pcm_ops,
 947    INIT_FIELD (can_be_default = ) 1,
 948    INIT_FIELD (max_voices_out = ) INT_MAX,
 949    INIT_FIELD (max_voices_in  = ) INT_MAX,
 950    INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
 951    INIT_FIELD (voice_size_in  = ) sizeof (ALSAVoiceIn)
 952};
 953