qemu/audio/audio_template.h
<<
>>
Prefs
   1/*
   2 * QEMU Audio subsystem header
   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#ifdef DAC
  26#define NAME "playback"
  27#define HWBUF hw->mix_buf
  28#define TYPE out
  29#define HW HWVoiceOut
  30#define SW SWVoiceOut
  31#else
  32#define NAME "capture"
  33#define TYPE in
  34#define HW HWVoiceIn
  35#define SW SWVoiceIn
  36#define HWBUF hw->conv_buf
  37#endif
  38
  39static void glue(audio_init_nb_voices_, TYPE)(AudioState *s,
  40                                              struct audio_driver *drv)
  41{
  42    int max_voices = glue (drv->max_voices_, TYPE);
  43    int voice_size = glue (drv->voice_size_, TYPE);
  44
  45    if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
  46        if (!max_voices) {
  47#ifdef DAC
  48            dolog ("Driver `%s' does not support " NAME "\n", drv->name);
  49#endif
  50        }
  51        else {
  52            dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
  53                   drv->name,
  54                   glue (s->nb_hw_voices_, TYPE),
  55                   max_voices);
  56        }
  57        glue (s->nb_hw_voices_, TYPE) = max_voices;
  58    }
  59
  60    if (audio_bug(__func__, !voice_size && max_voices)) {
  61        dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
  62               drv->name, max_voices);
  63        glue (s->nb_hw_voices_, TYPE) = 0;
  64    }
  65
  66    if (audio_bug(__func__, voice_size && !max_voices)) {
  67        dolog ("drv=`%s' voice_size=%d max_voices=0\n",
  68               drv->name, voice_size);
  69    }
  70}
  71
  72static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
  73{
  74    g_free(hw->buf_emul);
  75    g_free (HWBUF);
  76    HWBUF = NULL;
  77}
  78
  79static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw)
  80{
  81    if (glue(audio_get_pdo_, TYPE)(hw->s->dev)->mixing_engine) {
  82        size_t samples = hw->samples;
  83        if (audio_bug(__func__, samples == 0)) {
  84            dolog("Attempted to allocate empty buffer\n");
  85        }
  86
  87        HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples);
  88        HWBUF->size = samples;
  89    } else {
  90        HWBUF = NULL;
  91    }
  92}
  93
  94static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
  95{
  96    g_free (sw->buf);
  97
  98    if (sw->rate) {
  99        st_rate_stop (sw->rate);
 100    }
 101
 102    sw->buf = NULL;
 103    sw->rate = NULL;
 104}
 105
 106static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
 107{
 108    int samples;
 109
 110    if (!glue(audio_get_pdo_, TYPE)(sw->s->dev)->mixing_engine) {
 111        return 0;
 112    }
 113
 114    samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
 115
 116    sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
 117    if (!sw->buf) {
 118        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
 119               SW_NAME (sw), samples);
 120        return -1;
 121    }
 122
 123#ifdef DAC
 124    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
 125#else
 126    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
 127#endif
 128    if (!sw->rate) {
 129        g_free (sw->buf);
 130        sw->buf = NULL;
 131        return -1;
 132    }
 133    return 0;
 134}
 135
 136static int glue (audio_pcm_sw_init_, TYPE) (
 137    SW *sw,
 138    HW *hw,
 139    const char *name,
 140    struct audsettings *as
 141    )
 142{
 143    int err;
 144
 145    audio_pcm_init_info (&sw->info, as);
 146    sw->hw = hw;
 147    sw->active = 0;
 148#ifdef DAC
 149    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
 150    sw->total_hw_samples_mixed = 0;
 151    sw->empty = 1;
 152#else
 153    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
 154#endif
 155
 156#ifdef DAC
 157    sw->conv = mixeng_conv
 158#else
 159    sw->clip = mixeng_clip
 160#endif
 161        [sw->info.nchannels == 2]
 162        [sw->info.sign]
 163        [sw->info.swap_endianness]
 164        [audio_bits_to_index (sw->info.bits)];
 165
 166    sw->name = g_strdup (name);
 167    err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
 168    if (err) {
 169        g_free (sw->name);
 170        sw->name = NULL;
 171    }
 172    return err;
 173}
 174
 175static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
 176{
 177    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
 178    g_free (sw->name);
 179    sw->name = NULL;
 180}
 181
 182static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
 183{
 184    QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
 185}
 186
 187static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
 188{
 189    QLIST_REMOVE (sw, entries);
 190}
 191
 192static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
 193{
 194    HW *hw = *hwp;
 195    AudioState *s = hw->s;
 196
 197    if (!hw->sw_head.lh_first) {
 198#ifdef DAC
 199        audio_detach_capture (hw);
 200#endif
 201        QLIST_REMOVE (hw, entries);
 202        glue (hw->pcm_ops->fini_, TYPE) (hw);
 203        glue (s->nb_hw_voices_, TYPE) += 1;
 204        glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
 205        g_free (hw);
 206        *hwp = NULL;
 207    }
 208}
 209
 210static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioState *s, HW *hw)
 211{
 212    return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
 213}
 214
 215static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw)
 216{
 217    while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
 218        if (hw->enabled) {
 219            return hw;
 220        }
 221    }
 222    return NULL;
 223}
 224
 225static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw,
 226                                                   struct audsettings *as)
 227{
 228    while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) {
 229        if (audio_pcm_info_eq (&hw->info, as)) {
 230            return hw;
 231        }
 232    }
 233    return NULL;
 234}
 235
 236static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s,
 237                                             struct audsettings *as)
 238{
 239    HW *hw;
 240    struct audio_driver *drv = s->drv;
 241
 242    if (!glue (s->nb_hw_voices_, TYPE)) {
 243        return NULL;
 244    }
 245
 246    if (audio_bug(__func__, !drv)) {
 247        dolog ("No host audio driver\n");
 248        return NULL;
 249    }
 250
 251    if (audio_bug(__func__, !drv->pcm_ops)) {
 252        dolog ("Host audio driver without pcm_ops\n");
 253        return NULL;
 254    }
 255
 256    hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE));
 257    if (!hw) {
 258        dolog ("Can not allocate voice `%s' size %d\n",
 259               drv->name, glue (drv->voice_size_, TYPE));
 260        return NULL;
 261    }
 262
 263    hw->s = s;
 264    hw->pcm_ops = drv->pcm_ops;
 265
 266    QLIST_INIT (&hw->sw_head);
 267#ifdef DAC
 268    QLIST_INIT (&hw->cap_head);
 269#endif
 270    if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) {
 271        goto err0;
 272    }
 273
 274    if (audio_bug(__func__, hw->samples <= 0)) {
 275        dolog("hw->samples=%zd\n", hw->samples);
 276        goto err1;
 277    }
 278
 279#ifdef DAC
 280    hw->clip = mixeng_clip
 281#else
 282    hw->conv = mixeng_conv
 283#endif
 284        [hw->info.nchannels == 2]
 285        [hw->info.sign]
 286        [hw->info.swap_endianness]
 287        [audio_bits_to_index (hw->info.bits)];
 288
 289    glue(audio_pcm_hw_alloc_resources_, TYPE)(hw);
 290
 291    QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
 292    glue (s->nb_hw_voices_, TYPE) -= 1;
 293#ifdef DAC
 294    audio_attach_capture (hw);
 295#endif
 296    return hw;
 297
 298 err1:
 299    glue (hw->pcm_ops->fini_, TYPE) (hw);
 300 err0:
 301    g_free (hw);
 302    return NULL;
 303}
 304
 305AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
 306{
 307    switch (dev->driver) {
 308    case AUDIODEV_DRIVER_NONE:
 309        return dev->u.none.TYPE;
 310    case AUDIODEV_DRIVER_ALSA:
 311        return qapi_AudiodevAlsaPerDirectionOptions_base(dev->u.alsa.TYPE);
 312    case AUDIODEV_DRIVER_COREAUDIO:
 313        return qapi_AudiodevCoreaudioPerDirectionOptions_base(
 314            dev->u.coreaudio.TYPE);
 315    case AUDIODEV_DRIVER_DSOUND:
 316        return dev->u.dsound.TYPE;
 317    case AUDIODEV_DRIVER_OSS:
 318        return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
 319    case AUDIODEV_DRIVER_PA:
 320        return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
 321    case AUDIODEV_DRIVER_SDL:
 322        return dev->u.sdl.TYPE;
 323    case AUDIODEV_DRIVER_SPICE:
 324        return dev->u.spice.TYPE;
 325    case AUDIODEV_DRIVER_WAV:
 326        return dev->u.wav.TYPE;
 327
 328    case AUDIODEV_DRIVER__MAX:
 329        break;
 330    }
 331    abort();
 332}
 333
 334static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as)
 335{
 336    HW *hw;
 337    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
 338
 339    if (!pdo->mixing_engine || pdo->fixed_settings) {
 340        hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
 341        if (!pdo->mixing_engine || hw) {
 342            return hw;
 343        }
 344    }
 345
 346    hw = glue(audio_pcm_hw_find_specific_, TYPE)(s, NULL, as);
 347    if (hw) {
 348        return hw;
 349    }
 350
 351    hw = glue(audio_pcm_hw_add_new_, TYPE)(s, as);
 352    if (hw) {
 353        return hw;
 354    }
 355
 356    return glue(audio_pcm_hw_find_any_, TYPE)(s, NULL);
 357}
 358
 359static SW *glue(audio_pcm_create_voice_pair_, TYPE)(
 360    AudioState *s,
 361    const char *sw_name,
 362    struct audsettings *as
 363    )
 364{
 365    SW *sw;
 366    HW *hw;
 367    struct audsettings hw_as;
 368    AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev);
 369
 370    if (pdo->fixed_settings) {
 371        hw_as = audiodev_to_audsettings(pdo);
 372    }
 373    else {
 374        hw_as = *as;
 375    }
 376
 377    sw = audio_calloc(__func__, 1, sizeof(*sw));
 378    if (!sw) {
 379        dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
 380               sw_name ? sw_name : "unknown", sizeof (*sw));
 381        goto err1;
 382    }
 383    sw->s = s;
 384
 385    hw = glue(audio_pcm_hw_add_, TYPE)(s, &hw_as);
 386    if (!hw) {
 387        goto err2;
 388    }
 389
 390    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
 391
 392    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
 393        goto err3;
 394    }
 395
 396    return sw;
 397
 398err3:
 399    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
 400    glue (audio_pcm_hw_gc_, TYPE) (&hw);
 401err2:
 402    g_free (sw);
 403err1:
 404    return NULL;
 405}
 406
 407static void glue (audio_close_, TYPE) (SW *sw)
 408{
 409    glue (audio_pcm_sw_fini_, TYPE) (sw);
 410    glue (audio_pcm_hw_del_sw_, TYPE) (sw);
 411    glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
 412    g_free (sw);
 413}
 414
 415void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
 416{
 417    if (sw) {
 418        if (audio_bug(__func__, !card)) {
 419            dolog ("card=%p\n", card);
 420            return;
 421        }
 422
 423        glue (audio_close_, TYPE) (sw);
 424    }
 425}
 426
 427SW *glue (AUD_open_, TYPE) (
 428    QEMUSoundCard *card,
 429    SW *sw,
 430    const char *name,
 431    void *callback_opaque ,
 432    audio_callback_fn callback_fn,
 433    struct audsettings *as
 434    )
 435{
 436    AudioState *s;
 437    AudiodevPerDirectionOptions *pdo;
 438
 439    if (audio_bug(__func__, !card || !name || !callback_fn || !as)) {
 440        dolog ("card=%p name=%p callback_fn=%p as=%p\n",
 441               card, name, callback_fn, as);
 442        goto fail;
 443    }
 444
 445    s = card->state;
 446    pdo = glue(audio_get_pdo_, TYPE)(s->dev);
 447
 448    ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
 449            name, as->freq, as->nchannels, as->fmt);
 450
 451    if (audio_bug(__func__, audio_validate_settings(as))) {
 452        audio_print_settings (as);
 453        goto fail;
 454    }
 455
 456    if (audio_bug(__func__, !s->drv)) {
 457        dolog ("Can not open `%s' (no host audio driver)\n", name);
 458        goto fail;
 459    }
 460
 461    if (sw && audio_pcm_info_eq (&sw->info, as)) {
 462        return sw;
 463    }
 464
 465    if (!pdo->fixed_settings && sw) {
 466        glue (AUD_close_, TYPE) (card, sw);
 467        sw = NULL;
 468    }
 469
 470    if (sw) {
 471        HW *hw = sw->hw;
 472
 473        if (!hw) {
 474            dolog ("Internal logic error voice `%s' has no hardware store\n",
 475                   SW_NAME (sw));
 476            goto fail;
 477        }
 478
 479        glue (audio_pcm_sw_fini_, TYPE) (sw);
 480        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
 481            goto fail;
 482        }
 483    }
 484    else {
 485        sw = glue(audio_pcm_create_voice_pair_, TYPE)(s, name, as);
 486        if (!sw) {
 487            dolog ("Failed to create voice `%s'\n", name);
 488            return NULL;
 489        }
 490    }
 491
 492    sw->card = card;
 493    sw->vol = nominal_volume;
 494    sw->callback.fn = callback_fn;
 495    sw->callback.opaque = callback_opaque;
 496
 497#ifdef DEBUG_AUDIO
 498    dolog ("%s\n", name);
 499    audio_pcm_print_info ("hw", &sw->hw->info);
 500    audio_pcm_print_info ("sw", &sw->info);
 501#endif
 502
 503    return sw;
 504
 505 fail:
 506    glue (AUD_close_, TYPE) (card, sw);
 507    return NULL;
 508}
 509
 510int glue (AUD_is_active_, TYPE) (SW *sw)
 511{
 512    return sw ? sw->active : 0;
 513}
 514
 515void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
 516{
 517    if (!sw) {
 518        return;
 519    }
 520
 521    ts->old_ts = sw->hw->ts_helper;
 522}
 523
 524uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
 525{
 526    uint64_t delta, cur_ts, old_ts;
 527
 528    if (!sw) {
 529        return 0;
 530    }
 531
 532    cur_ts = sw->hw->ts_helper;
 533    old_ts = ts->old_ts;
 534    /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
 535
 536    if (cur_ts >= old_ts) {
 537        delta = cur_ts - old_ts;
 538    }
 539    else {
 540        delta = UINT64_MAX - old_ts + cur_ts;
 541    }
 542
 543    if (!delta) {
 544        return 0;
 545    }
 546
 547    return muldiv64 (delta, sw->hw->info.freq, 1000000);
 548}
 549
 550#undef TYPE
 551#undef HW
 552#undef SW
 553#undef HWBUF
 554#undef NAME
 555