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