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
  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
  39struct pollhlp {
  40    snd_pcm_t *handle;
  41    struct pollfd *pfds;
  42    int count;
  43    int mask;
  44    AudioState *s;
  45};
  46
  47typedef struct ALSAVoiceOut {
  48    HWVoiceOut hw;
  49    snd_pcm_t *handle;
  50    struct pollhlp pollhlp;
  51    Audiodev *dev;
  52} ALSAVoiceOut;
  53
  54typedef struct ALSAVoiceIn {
  55    HWVoiceIn hw;
  56    snd_pcm_t *handle;
  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 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
  86static 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
 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(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
 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 = g_new0(struct pollfd, count);
 226
 227    err = snd_pcm_poll_descriptors (handle, pfds, count);
 228    if (err < 0) {
 229        alsa_logerr (err, "Could not initialize poll mode\n"
 230                     "Could not obtain poll descriptors\n");
 231        g_free (pfds);
 232        return -1;
 233    }
 234
 235    for (i = 0; i < count; ++i) {
 236        if (pfds[i].events & POLLIN) {
 237            qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler, NULL, hlp);
 238        }
 239        if (pfds[i].events & POLLOUT) {
 240            trace_alsa_pollout(i, pfds[i].fd);
 241            qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp);
 242        }
 243        trace_alsa_set_handler(pfds[i].events, i, pfds[i].fd, err);
 244
 245    }
 246    hlp->pfds = pfds;
 247    hlp->count = count;
 248    hlp->handle = handle;
 249    hlp->mask = mask;
 250    return 0;
 251}
 252
 253static int alsa_poll_out (HWVoiceOut *hw)
 254{
 255    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 256
 257    return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLOUT);
 258}
 259
 260static int alsa_poll_in (HWVoiceIn *hw)
 261{
 262    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 263
 264    return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN);
 265}
 266
 267static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
 268{
 269    switch (fmt) {
 270    case AUDIO_FORMAT_S8:
 271        return SND_PCM_FORMAT_S8;
 272
 273    case AUDIO_FORMAT_U8:
 274        return SND_PCM_FORMAT_U8;
 275
 276    case AUDIO_FORMAT_S16:
 277        if (endianness) {
 278            return SND_PCM_FORMAT_S16_BE;
 279        } else {
 280            return SND_PCM_FORMAT_S16_LE;
 281        }
 282
 283    case AUDIO_FORMAT_U16:
 284        if (endianness) {
 285            return SND_PCM_FORMAT_U16_BE;
 286        } else {
 287            return SND_PCM_FORMAT_U16_LE;
 288        }
 289
 290    case AUDIO_FORMAT_S32:
 291        if (endianness) {
 292            return SND_PCM_FORMAT_S32_BE;
 293        } else {
 294            return SND_PCM_FORMAT_S32_LE;
 295        }
 296
 297    case AUDIO_FORMAT_U32:
 298        if (endianness) {
 299            return SND_PCM_FORMAT_U32_BE;
 300        } else {
 301            return SND_PCM_FORMAT_U32_LE;
 302        }
 303
 304    case AUDIO_FORMAT_F32:
 305        if (endianness) {
 306            return SND_PCM_FORMAT_FLOAT_BE;
 307        } else {
 308            return SND_PCM_FORMAT_FLOAT_LE;
 309        }
 310
 311    default:
 312        dolog ("Internal logic error: Bad audio format %d\n", fmt);
 313#ifdef DEBUG_AUDIO
 314        abort ();
 315#endif
 316        return SND_PCM_FORMAT_U8;
 317    }
 318}
 319
 320static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt,
 321                           int *endianness)
 322{
 323    switch (alsafmt) {
 324    case SND_PCM_FORMAT_S8:
 325        *endianness = 0;
 326        *fmt = AUDIO_FORMAT_S8;
 327        break;
 328
 329    case SND_PCM_FORMAT_U8:
 330        *endianness = 0;
 331        *fmt = AUDIO_FORMAT_U8;
 332        break;
 333
 334    case SND_PCM_FORMAT_S16_LE:
 335        *endianness = 0;
 336        *fmt = AUDIO_FORMAT_S16;
 337        break;
 338
 339    case SND_PCM_FORMAT_U16_LE:
 340        *endianness = 0;
 341        *fmt = AUDIO_FORMAT_U16;
 342        break;
 343
 344    case SND_PCM_FORMAT_S16_BE:
 345        *endianness = 1;
 346        *fmt = AUDIO_FORMAT_S16;
 347        break;
 348
 349    case SND_PCM_FORMAT_U16_BE:
 350        *endianness = 1;
 351        *fmt = AUDIO_FORMAT_U16;
 352        break;
 353
 354    case SND_PCM_FORMAT_S32_LE:
 355        *endianness = 0;
 356        *fmt = AUDIO_FORMAT_S32;
 357        break;
 358
 359    case SND_PCM_FORMAT_U32_LE:
 360        *endianness = 0;
 361        *fmt = AUDIO_FORMAT_U32;
 362        break;
 363
 364    case SND_PCM_FORMAT_S32_BE:
 365        *endianness = 1;
 366        *fmt = AUDIO_FORMAT_S32;
 367        break;
 368
 369    case SND_PCM_FORMAT_U32_BE:
 370        *endianness = 1;
 371        *fmt = AUDIO_FORMAT_U32;
 372        break;
 373
 374    case SND_PCM_FORMAT_FLOAT_LE:
 375        *endianness = 0;
 376        *fmt = AUDIO_FORMAT_F32;
 377        break;
 378
 379    case SND_PCM_FORMAT_FLOAT_BE:
 380        *endianness = 1;
 381        *fmt = AUDIO_FORMAT_F32;
 382        break;
 383
 384    default:
 385        dolog ("Unrecognized audio format %d\n", alsafmt);
 386        return -1;
 387    }
 388
 389    return 0;
 390}
 391
 392static void alsa_dump_info (struct alsa_params_req *req,
 393                            struct alsa_params_obt *obt,
 394                            snd_pcm_format_t obtfmt,
 395                            AudiodevAlsaPerDirectionOptions *apdo)
 396{
 397    dolog("parameter | requested value | obtained value\n");
 398    dolog("format    |      %10d |     %10d\n", req->fmt, obtfmt);
 399    dolog("channels  |      %10d |     %10d\n",
 400          req->nchannels, obt->nchannels);
 401    dolog("frequency |      %10d |     %10d\n", req->freq, obt->freq);
 402    dolog("============================================\n");
 403    dolog("requested: buffer len %" PRId32 " period len %" PRId32 "\n",
 404          apdo->buffer_length, apdo->period_length);
 405    dolog("obtained: samples %ld\n", obt->samples);
 406}
 407
 408static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
 409{
 410    int err;
 411    snd_pcm_sw_params_t *sw_params;
 412
 413    snd_pcm_sw_params_alloca (&sw_params);
 414
 415    err = snd_pcm_sw_params_current (handle, sw_params);
 416    if (err < 0) {
 417        dolog ("Could not fully initialize DAC\n");
 418        alsa_logerr (err, "Failed to get current software parameters\n");
 419        return;
 420    }
 421
 422    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
 423    if (err < 0) {
 424        dolog ("Could not fully initialize DAC\n");
 425        alsa_logerr (err, "Failed to set software threshold to %ld\n",
 426                     threshold);
 427        return;
 428    }
 429
 430    err = snd_pcm_sw_params (handle, sw_params);
 431    if (err < 0) {
 432        dolog ("Could not fully initialize DAC\n");
 433        alsa_logerr (err, "Failed to set software parameters\n");
 434        return;
 435    }
 436}
 437
 438static int alsa_open(bool in, struct alsa_params_req *req,
 439                     struct alsa_params_obt *obt, snd_pcm_t **handlep,
 440                     Audiodev *dev)
 441{
 442    AudiodevAlsaOptions *aopts = &dev->u.alsa;
 443    AudiodevAlsaPerDirectionOptions *apdo = in ? aopts->in : aopts->out;
 444    snd_pcm_t *handle;
 445    snd_pcm_hw_params_t *hw_params;
 446    int err;
 447    unsigned int freq, nchannels;
 448    const char *pcm_name = apdo->dev ?: "default";
 449    snd_pcm_uframes_t obt_buffer_size;
 450    const char *typ = in ? "ADC" : "DAC";
 451    snd_pcm_format_t obtfmt;
 452
 453    freq = req->freq;
 454    nchannels = req->nchannels;
 455
 456    snd_pcm_hw_params_alloca (&hw_params);
 457
 458    err = snd_pcm_open (
 459        &handle,
 460        pcm_name,
 461        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
 462        SND_PCM_NONBLOCK
 463        );
 464    if (err < 0) {
 465        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
 466        return -1;
 467    }
 468
 469    err = snd_pcm_hw_params_any (handle, hw_params);
 470    if (err < 0) {
 471        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
 472        goto err;
 473    }
 474
 475    err = snd_pcm_hw_params_set_access (
 476        handle,
 477        hw_params,
 478        SND_PCM_ACCESS_RW_INTERLEAVED
 479        );
 480    if (err < 0) {
 481        alsa_logerr2 (err, typ, "Failed to set access type\n");
 482        goto err;
 483    }
 484
 485    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
 486    if (err < 0) {
 487        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
 488    }
 489
 490    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
 491    if (err < 0) {
 492        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
 493        goto err;
 494    }
 495
 496    err = snd_pcm_hw_params_set_channels_near (
 497        handle,
 498        hw_params,
 499        &nchannels
 500        );
 501    if (err < 0) {
 502        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
 503                      req->nchannels);
 504        goto err;
 505    }
 506
 507    if (apdo->buffer_length) {
 508        int dir = 0;
 509        unsigned int btime = apdo->buffer_length;
 510
 511        err = snd_pcm_hw_params_set_buffer_time_near(
 512            handle, hw_params, &btime, &dir);
 513
 514        if (err < 0) {
 515            alsa_logerr2(err, typ, "Failed to set buffer time to %" PRId32 "\n",
 516                         apdo->buffer_length);
 517            goto err;
 518        }
 519
 520        if (apdo->has_buffer_length && btime != apdo->buffer_length) {
 521            dolog("Requested buffer time %" PRId32
 522                  " was rejected, using %u\n", apdo->buffer_length, btime);
 523        }
 524    }
 525
 526    if (apdo->period_length) {
 527        int dir = 0;
 528        unsigned int ptime = apdo->period_length;
 529
 530        err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &ptime,
 531                                                     &dir);
 532
 533        if (err < 0) {
 534            alsa_logerr2(err, typ, "Failed to set period time to %" PRId32 "\n",
 535                         apdo->period_length);
 536            goto err;
 537        }
 538
 539        if (apdo->has_period_length && ptime != apdo->period_length) {
 540            dolog("Requested period time %" PRId32 " was rejected, using %d\n",
 541                  apdo->period_length, ptime);
 542        }
 543    }
 544
 545    err = snd_pcm_hw_params (handle, hw_params);
 546    if (err < 0) {
 547        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
 548        goto err;
 549    }
 550
 551    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
 552    if (err < 0) {
 553        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
 554        goto err;
 555    }
 556
 557    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
 558    if (err < 0) {
 559        alsa_logerr2 (err, typ, "Failed to get format\n");
 560        goto err;
 561    }
 562
 563    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
 564        dolog ("Invalid format was returned %d\n", obtfmt);
 565        goto err;
 566    }
 567
 568    err = snd_pcm_prepare (handle);
 569    if (err < 0) {
 570        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
 571        goto err;
 572    }
 573
 574    if (!in && aopts->has_threshold && aopts->threshold) {
 575        struct audsettings as = { .freq = freq };
 576        alsa_set_threshold(
 577            handle,
 578            audio_buffer_frames(qapi_AudiodevAlsaPerDirectionOptions_base(apdo),
 579                                &as, aopts->threshold));
 580    }
 581
 582    obt->nchannels = nchannels;
 583    obt->freq = freq;
 584    obt->samples = obt_buffer_size;
 585
 586    *handlep = handle;
 587
 588    if (DEBUG_ALSA || obtfmt != req->fmt ||
 589        obt->nchannels != req->nchannels || obt->freq != req->freq) {
 590        dolog ("Audio parameters for %s\n", typ);
 591        alsa_dump_info(req, obt, obtfmt, apdo);
 592    }
 593
 594    return 0;
 595
 596 err:
 597    alsa_anal_close1 (&handle);
 598    return -1;
 599}
 600
 601static size_t alsa_buffer_get_free(HWVoiceOut *hw)
 602{
 603    ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
 604    snd_pcm_sframes_t avail;
 605    size_t alsa_free, generic_free, generic_in_use;
 606
 607    avail = snd_pcm_avail_update(alsa->handle);
 608    if (avail < 0) {
 609        if (avail == -EPIPE) {
 610            if (!alsa_recover(alsa->handle)) {
 611                avail = snd_pcm_avail_update(alsa->handle);
 612            }
 613        }
 614        if (avail < 0) {
 615            alsa_logerr(avail,
 616                        "Could not obtain number of available frames\n");
 617            avail = 0;
 618        }
 619    }
 620
 621    alsa_free = avail * hw->info.bytes_per_frame;
 622    generic_free = audio_generic_buffer_get_free(hw);
 623    generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free;
 624    if (generic_in_use) {
 625        /*
 626         * This code can only be reached in the unlikely case that
 627         * snd_pcm_avail_update() returned a larger number of frames
 628         * than snd_pcm_writei() could write. Make sure that all
 629         * remaining bytes in the generic buffer can be written.
 630         */
 631        alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0;
 632    }
 633
 634    return alsa_free;
 635}
 636
 637static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
 638{
 639    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 640    size_t pos = 0;
 641    size_t len_frames = len / hw->info.bytes_per_frame;
 642
 643    while (len_frames) {
 644        char *src = advance(buf, pos);
 645        snd_pcm_sframes_t written;
 646
 647        written = snd_pcm_writei(alsa->handle, src, len_frames);
 648
 649        if (written <= 0) {
 650            switch (written) {
 651            case 0:
 652                trace_alsa_wrote_zero(len_frames);
 653                return pos;
 654
 655            case -EPIPE:
 656                if (alsa_recover(alsa->handle)) {
 657                    alsa_logerr(written, "Failed to write %zu frames\n",
 658                                len_frames);
 659                    return pos;
 660                }
 661                trace_alsa_xrun_out();
 662                continue;
 663
 664            case -ESTRPIPE:
 665                /*
 666                 * stream is suspended and waiting for an application
 667                 * recovery
 668                 */
 669                if (alsa_resume(alsa->handle)) {
 670                    alsa_logerr(written, "Failed to write %zu frames\n",
 671                                len_frames);
 672                    return pos;
 673                }
 674                trace_alsa_resume_out();
 675                continue;
 676
 677            case -EAGAIN:
 678                return pos;
 679
 680            default:
 681                alsa_logerr(written, "Failed to write %zu frames from %p\n",
 682                            len, src);
 683                return pos;
 684            }
 685        }
 686
 687        pos += written * hw->info.bytes_per_frame;
 688        if (written < len_frames) {
 689            break;
 690        }
 691        len_frames -= written;
 692    }
 693
 694    return pos;
 695}
 696
 697static void alsa_fini_out (HWVoiceOut *hw)
 698{
 699    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 700
 701    ldebug ("alsa_fini\n");
 702    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
 703}
 704
 705static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as,
 706                         void *drv_opaque)
 707{
 708    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 709    struct alsa_params_req req;
 710    struct alsa_params_obt obt;
 711    snd_pcm_t *handle;
 712    struct audsettings obt_as;
 713    Audiodev *dev = drv_opaque;
 714
 715    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
 716    req.freq = as->freq;
 717    req.nchannels = as->nchannels;
 718
 719    if (alsa_open(0, &req, &obt, &handle, dev)) {
 720        return -1;
 721    }
 722
 723    obt_as.freq = obt.freq;
 724    obt_as.nchannels = obt.nchannels;
 725    obt_as.fmt = obt.fmt;
 726    obt_as.endianness = obt.endianness;
 727
 728    audio_pcm_init_info (&hw->info, &obt_as);
 729    hw->samples = obt.samples;
 730
 731    alsa->pollhlp.s = hw->s;
 732    alsa->handle = handle;
 733    alsa->dev = dev;
 734    return 0;
 735}
 736
 737#define VOICE_CTL_PAUSE 0
 738#define VOICE_CTL_PREPARE 1
 739#define VOICE_CTL_START 2
 740
 741static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
 742{
 743    int err;
 744
 745    if (ctl == VOICE_CTL_PAUSE) {
 746        err = snd_pcm_drop (handle);
 747        if (err < 0) {
 748            alsa_logerr (err, "Could not stop %s\n", typ);
 749            return -1;
 750        }
 751    } else {
 752        err = snd_pcm_prepare (handle);
 753        if (err < 0) {
 754            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
 755            return -1;
 756        }
 757        if (ctl == VOICE_CTL_START) {
 758            err = snd_pcm_start(handle);
 759            if (err < 0) {
 760                alsa_logerr (err, "Could not start handle for %s\n", typ);
 761                return -1;
 762            }
 763        }
 764    }
 765
 766    return 0;
 767}
 768
 769static void alsa_enable_out(HWVoiceOut *hw, bool enable)
 770{
 771    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 772    AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out;
 773
 774    if (enable) {
 775        bool poll_mode = apdo->try_poll;
 776
 777        ldebug("enabling voice\n");
 778        if (poll_mode && alsa_poll_out(hw)) {
 779            poll_mode = 0;
 780        }
 781        hw->poll_mode = poll_mode;
 782        alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE);
 783    } else {
 784        ldebug("disabling voice\n");
 785        if (hw->poll_mode) {
 786            hw->poll_mode = 0;
 787            alsa_fini_poll(&alsa->pollhlp);
 788        }
 789        alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE);
 790    }
 791}
 792
 793static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 794{
 795    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 796    struct alsa_params_req req;
 797    struct alsa_params_obt obt;
 798    snd_pcm_t *handle;
 799    struct audsettings obt_as;
 800    Audiodev *dev = drv_opaque;
 801
 802    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
 803    req.freq = as->freq;
 804    req.nchannels = as->nchannels;
 805
 806    if (alsa_open(1, &req, &obt, &handle, dev)) {
 807        return -1;
 808    }
 809
 810    obt_as.freq = obt.freq;
 811    obt_as.nchannels = obt.nchannels;
 812    obt_as.fmt = obt.fmt;
 813    obt_as.endianness = obt.endianness;
 814
 815    audio_pcm_init_info (&hw->info, &obt_as);
 816    hw->samples = obt.samples;
 817
 818    alsa->pollhlp.s = hw->s;
 819    alsa->handle = handle;
 820    alsa->dev = dev;
 821    return 0;
 822}
 823
 824static void alsa_fini_in (HWVoiceIn *hw)
 825{
 826    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 827
 828    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
 829}
 830
 831static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
 832{
 833    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 834    size_t pos = 0;
 835
 836    while (len) {
 837        void *dst = advance(buf, pos);
 838        snd_pcm_sframes_t nread;
 839
 840        nread = snd_pcm_readi(
 841            alsa->handle, dst, len / hw->info.bytes_per_frame);
 842
 843        if (nread <= 0) {
 844            switch (nread) {
 845            case 0:
 846                trace_alsa_read_zero(len);
 847                return pos;
 848
 849            case -EPIPE:
 850                if (alsa_recover(alsa->handle)) {
 851                    alsa_logerr(nread, "Failed to read %zu frames\n", len);
 852                    return pos;
 853                }
 854                trace_alsa_xrun_in();
 855                continue;
 856
 857            case -EAGAIN:
 858                return pos;
 859
 860            default:
 861                alsa_logerr(nread, "Failed to read %zu frames to %p\n",
 862                            len, dst);
 863                return pos;
 864            }
 865        }
 866
 867        pos += nread * hw->info.bytes_per_frame;
 868        len -= nread * hw->info.bytes_per_frame;
 869    }
 870
 871    return pos;
 872}
 873
 874static void alsa_enable_in(HWVoiceIn *hw, bool enable)
 875{
 876    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 877    AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in;
 878
 879    if (enable) {
 880        bool poll_mode = apdo->try_poll;
 881
 882        ldebug("enabling voice\n");
 883        if (poll_mode && alsa_poll_in(hw)) {
 884            poll_mode = 0;
 885        }
 886        hw->poll_mode = poll_mode;
 887
 888        alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START);
 889    } else {
 890        ldebug ("disabling voice\n");
 891        if (hw->poll_mode) {
 892            hw->poll_mode = 0;
 893            alsa_fini_poll(&alsa->pollhlp);
 894        }
 895        alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE);
 896    }
 897}
 898
 899static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
 900{
 901    if (!apdo->has_try_poll) {
 902        apdo->try_poll = false;
 903        apdo->has_try_poll = true;
 904    }
 905}
 906
 907static void *alsa_audio_init(Audiodev *dev, Error **errp)
 908{
 909    AudiodevAlsaOptions *aopts;
 910    assert(dev->driver == AUDIODEV_DRIVER_ALSA);
 911
 912    aopts = &dev->u.alsa;
 913    alsa_init_per_direction(aopts->in);
 914    alsa_init_per_direction(aopts->out);
 915
 916    /* don't set has_* so alsa_open can identify it wasn't set by the user */
 917    if (!dev->u.alsa.out->has_period_length) {
 918        /* 256 frames assuming 44100Hz */
 919        dev->u.alsa.out->period_length = 5805;
 920    }
 921    if (!dev->u.alsa.out->has_buffer_length) {
 922        /* 4096 frames assuming 44100Hz */
 923        dev->u.alsa.out->buffer_length = 92880;
 924    }
 925
 926    if (!dev->u.alsa.in->has_period_length) {
 927        /* 256 frames assuming 44100Hz */
 928        dev->u.alsa.in->period_length = 5805;
 929    }
 930    if (!dev->u.alsa.in->has_buffer_length) {
 931        /* 4096 frames assuming 44100Hz */
 932        dev->u.alsa.in->buffer_length = 92880;
 933    }
 934
 935    return dev;
 936}
 937
 938static void alsa_audio_fini (void *opaque)
 939{
 940}
 941
 942static struct audio_pcm_ops alsa_pcm_ops = {
 943    .init_out = alsa_init_out,
 944    .fini_out = alsa_fini_out,
 945    .write    = alsa_write,
 946    .buffer_get_free = alsa_buffer_get_free,
 947    .run_buffer_out = audio_generic_run_buffer_out,
 948    .enable_out = alsa_enable_out,
 949
 950    .init_in  = alsa_init_in,
 951    .fini_in  = alsa_fini_in,
 952    .read     = alsa_read,
 953    .run_buffer_in = audio_generic_run_buffer_in,
 954    .enable_in = alsa_enable_in,
 955};
 956
 957static struct audio_driver alsa_audio_driver = {
 958    .name           = "alsa",
 959    .descr          = "ALSA http://www.alsa-project.org",
 960    .init           = alsa_audio_init,
 961    .fini           = alsa_audio_fini,
 962    .pcm_ops        = &alsa_pcm_ops,
 963    .max_voices_out = INT_MAX,
 964    .max_voices_in  = INT_MAX,
 965    .voice_size_out = sizeof (ALSAVoiceOut),
 966    .voice_size_in  = sizeof (ALSAVoiceIn)
 967};
 968
 969static void register_audio_alsa(void)
 970{
 971    audio_driver_register(&alsa_audio_driver);
 972}
 973type_init(register_audio_alsa);
 974