Annotation of qemu/audio/audio_template.h, revision 1.1.1.10

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.