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

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.6   root      266:     QLIST_INIT (&hw->sw_head);
1.1.1.2   root      267: #ifdef DAC
1.1.1.6   root      268:     QLIST_INIT (&hw->cap_head);
1.1.1.2   root      269: #endif
1.1       root      270:     if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
                    271:         goto err0;
                    272:     }
                    273: 
                    274:     if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
                    275:         dolog ("hw->samples=%d\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]
1.1.1.2   root      286:         [hw->info.swap_endianness]
1.1.1.3   root      287:         [audio_bits_to_index (hw->info.bits)];
1.1       root      288: 
                    289:     if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
                    290:         goto err1;
                    291:     }
                    292: 
1.1.1.6   root      293:     QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
1.1       root      294:     glue (s->nb_hw_voices_, TYPE) -= 1;
1.1.1.2   root      295: #ifdef DAC
1.1.1.5   root      296:     audio_attach_capture (hw);
1.1.1.2   root      297: #endif
1.1       root      298:     return hw;
                    299: 
                    300:  err1:
                    301:     glue (hw->pcm_ops->fini_, TYPE) (hw);
                    302:  err0:
1.1.1.9 ! root      303:     g_free (hw);
1.1       root      304:     return NULL;
                    305: }
                    306: 
1.1.1.5   root      307: static HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
1.1       root      308: {
                    309:     HW *hw;
                    310: 
                    311:     if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
1.1.1.5   root      312:         hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
1.1       root      313:         if (hw) {
                    314:             return hw;
                    315:         }
                    316:     }
                    317: 
1.1.1.5   root      318:     hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, as);
1.1       root      319:     if (hw) {
                    320:         return hw;
                    321:     }
                    322: 
1.1.1.5   root      323:     hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
1.1       root      324:     if (hw) {
                    325:         return hw;
                    326:     }
                    327: 
1.1.1.5   root      328:     return glue (audio_pcm_hw_find_any_, TYPE) (NULL);
1.1       root      329: }
                    330: 
                    331: static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
                    332:     const char *sw_name,
1.1.1.4   root      333:     struct audsettings *as
1.1       root      334:     )
                    335: {
                    336:     SW *sw;
                    337:     HW *hw;
1.1.1.4   root      338:     struct audsettings hw_as;
1.1       root      339: 
                    340:     if (glue (conf.fixed_, TYPE).enabled) {
                    341:         hw_as = glue (conf.fixed_, TYPE).settings;
                    342:     }
                    343:     else {
                    344:         hw_as = *as;
                    345:     }
                    346: 
                    347:     sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
                    348:     if (!sw) {
                    349:         dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
                    350:                sw_name ? sw_name : "unknown", sizeof (*sw));
                    351:         goto err1;
                    352:     }
                    353: 
1.1.1.5   root      354:     hw = glue (audio_pcm_hw_add_, TYPE) (&hw_as);
1.1       root      355:     if (!hw) {
                    356:         goto err2;
                    357:     }
                    358: 
                    359:     glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
                    360: 
1.1.1.2   root      361:     if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
1.1       root      362:         goto err3;
                    363:     }
                    364: 
                    365:     return sw;
                    366: 
                    367: err3:
                    368:     glue (audio_pcm_hw_del_sw_, TYPE) (sw);
1.1.1.5   root      369:     glue (audio_pcm_hw_gc_, TYPE) (&hw);
1.1       root      370: err2:
1.1.1.9 ! root      371:     g_free (sw);
1.1       root      372: err1:
                    373:     return NULL;
                    374: }
                    375: 
1.1.1.5   root      376: static void glue (audio_close_, TYPE) (SW *sw)
1.1       root      377: {
                    378:     glue (audio_pcm_sw_fini_, TYPE) (sw);
                    379:     glue (audio_pcm_hw_del_sw_, TYPE) (sw);
1.1.1.5   root      380:     glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
1.1.1.9 ! root      381:     g_free (sw);
1.1       root      382: }
                    383: 
                    384: void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
                    385: {
                    386:     if (sw) {
1.1.1.5   root      387:         if (audio_bug (AUDIO_FUNC, !card)) {
                    388:             dolog ("card=%p\n", card);
1.1       root      389:             return;
                    390:         }
                    391: 
1.1.1.5   root      392:         glue (audio_close_, TYPE) (sw);
1.1       root      393:     }
                    394: }
                    395: 
                    396: SW *glue (AUD_open_, TYPE) (
                    397:     QEMUSoundCard *card,
                    398:     SW *sw,
                    399:     const char *name,
                    400:     void *callback_opaque ,
1.1.1.6   root      401:     audio_callback_fn callback_fn,
1.1.1.4   root      402:     struct audsettings *as
1.1       root      403:     )
                    404: {
1.1.1.5   root      405:     AudioState *s = &glob_audio_state;
1.1       root      406: #ifdef DAC
                    407:     int live = 0;
                    408:     SW *old_sw = NULL;
                    409: #endif
                    410: 
                    411:     ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
                    412:             name, as->freq, as->nchannels, as->fmt);
                    413: 
1.1.1.5   root      414:     if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
                    415:         dolog ("card=%p name=%p callback_fn=%p as=%p\n",
                    416:                card, name, callback_fn, as);
1.1       root      417:         goto fail;
                    418:     }
                    419: 
1.1.1.2   root      420:     if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
1.1       root      421:         audio_print_settings (as);
                    422:         goto fail;
                    423:     }
                    424: 
                    425:     if (audio_bug (AUDIO_FUNC, !s->drv)) {
                    426:         dolog ("Can not open `%s' (no host audio driver)\n", name);
                    427:         goto fail;
                    428:     }
                    429: 
                    430:     if (sw && audio_pcm_info_eq (&sw->info, as)) {
                    431:         return sw;
                    432:     }
                    433: 
                    434: #ifdef DAC
                    435:     if (conf.plive && sw && (!sw->active && !sw->empty)) {
                    436:         live = sw->total_hw_samples_mixed;
                    437: 
                    438: #ifdef DEBUG_PLIVE
                    439:         dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
                    440:         dolog ("Old %s freq %d, bits %d, channels %d\n",
                    441:                SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
                    442:         dolog ("New %s freq %d, bits %d, channels %d\n",
                    443:                name,
1.1.1.6   root      444:                as->freq,
                    445:                (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) ? 16 : 8,
                    446:                as->nchannels);
1.1       root      447: #endif
                    448: 
                    449:         if (live) {
                    450:             old_sw = sw;
                    451:             old_sw->callback.fn = NULL;
                    452:             sw = NULL;
                    453:         }
                    454:     }
                    455: #endif
                    456: 
                    457:     if (!glue (conf.fixed_, TYPE).enabled && sw) {
                    458:         glue (AUD_close_, TYPE) (card, sw);
                    459:         sw = NULL;
                    460:     }
                    461: 
                    462:     if (sw) {
                    463:         HW *hw = sw->hw;
                    464: 
                    465:         if (!hw) {
                    466:             dolog ("Internal logic error voice `%s' has no hardware store\n",
                    467:                    SW_NAME (sw));
                    468:             goto fail;
                    469:         }
                    470: 
                    471:         glue (audio_pcm_sw_fini_, TYPE) (sw);
1.1.1.2   root      472:         if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
1.1       root      473:             goto fail;
                    474:         }
                    475:     }
                    476:     else {
1.1.1.5   root      477:         sw = glue (audio_pcm_create_voice_pair_, TYPE) (name, as);
1.1       root      478:         if (!sw) {
                    479:             dolog ("Failed to create voice `%s'\n", name);
                    480:             return NULL;
                    481:         }
                    482:     }
                    483: 
1.1.1.6   root      484:     sw->card = card;
                    485:     sw->vol = nominal_volume;
                    486:     sw->callback.fn = callback_fn;
                    487:     sw->callback.opaque = callback_opaque;
1.1       root      488: 
                    489: #ifdef DAC
1.1.1.6   root      490:     if (live) {
                    491:         int mixed =
                    492:             (live << old_sw->info.shift)
                    493:             * old_sw->info.bytes_per_second
                    494:             / sw->info.bytes_per_second;
1.1       root      495: 
                    496: #ifdef DEBUG_PLIVE
1.1.1.6   root      497:         dolog ("Silence will be mixed %d\n", mixed);
1.1       root      498: #endif
1.1.1.6   root      499:         sw->total_hw_samples_mixed += mixed;
                    500:     }
1.1       root      501: #endif
                    502: 
                    503: #ifdef DEBUG_AUDIO
1.1.1.6   root      504:     dolog ("%s\n", name);
                    505:     audio_pcm_print_info ("hw", &sw->hw->info);
                    506:     audio_pcm_print_info ("sw", &sw->info);
1.1       root      507: #endif
                    508: 
                    509:     return sw;
                    510: 
                    511:  fail:
                    512:     glue (AUD_close_, TYPE) (card, sw);
                    513:     return NULL;
                    514: }
                    515: 
                    516: int glue (AUD_is_active_, TYPE) (SW *sw)
                    517: {
                    518:     return sw ? sw->active : 0;
                    519: }
                    520: 
                    521: void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
                    522: {
                    523:     if (!sw) {
                    524:         return;
                    525:     }
                    526: 
                    527:     ts->old_ts = sw->hw->ts_helper;
                    528: }
                    529: 
                    530: uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
                    531: {
                    532:     uint64_t delta, cur_ts, old_ts;
                    533: 
                    534:     if (!sw) {
                    535:         return 0;
                    536:     }
                    537: 
                    538:     cur_ts = sw->hw->ts_helper;
                    539:     old_ts = ts->old_ts;
1.1.1.7   root      540:     /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
1.1       root      541: 
                    542:     if (cur_ts >= old_ts) {
                    543:         delta = cur_ts - old_ts;
                    544:     }
                    545:     else {
                    546:         delta = UINT64_MAX - old_ts + cur_ts;
                    547:     }
                    548: 
                    549:     if (!delta) {
                    550:         return 0;
                    551:     }
                    552: 
1.1.1.6   root      553:     return muldiv64 (delta, sw->hw->info.freq, 1000000);
1.1       root      554: }
                    555: 
                    556: #undef TYPE
                    557: #undef HW
                    558: #undef SW
                    559: #undef HWBUF
                    560: #undef NAME

unix.superglobalmegacorp.com

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