⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
static void audio_timer (void *opaque){    AudioState *s = opaque;    audio_run_out (s);    audio_run_in (s);    audio_run_capture (s);    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);}static struct audio_option audio_options[] = {    /* DAC */    {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,     "Use fixed settings for host DAC", NULL, 0},    {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq,     "Frequency for fixed host DAC", NULL, 0},    {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt,     "Format for fixed host DAC", NULL, 0},    {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels,     "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},    {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices,     "Number of voices for DAC", NULL, 0},    /* ADC */    {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled,     "Use fixed settings for host ADC", NULL, 0},    {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq,     "Frequency for fixed host ADC", NULL, 0},    {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt,     "Format for fixed host ADC", NULL, 0},    {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels,     "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},    {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices,     "Number of voices for ADC", NULL, 0},    /* Misc */    {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hz,     "Timer period in HZ (0 - use lowest possible)", NULL, 0},    {"PLIVE", AUD_OPT_BOOL, &conf.plive,     "(undocumented)", NULL, 0},    {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,     "print logging messages to montior instead of stderr", NULL, 0},    {NULL, 0, NULL, NULL, NULL, 0}};static void audio_pp_nb_voices (const char *typ, int nb){    switch (nb) {    case 0:        printf ("Does not support %s\n", typ);        break;    case 1:        printf ("One %s voice\n", typ);        break;    case INT_MAX:        printf ("Theoretically supports many %s voices\n", typ);        break;    default:        printf ("Theoretically supports upto %d %s voices\n", nb, typ);        break;    }}void AUD_help (void){    size_t i;    audio_process_options ("AUDIO", audio_options);    for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {        struct audio_driver *d = drvtab[i];        if (d->options) {            audio_process_options (d->name, d->options);        }    }    printf ("Audio options:\n");    audio_print_options ("AUDIO", audio_options);    printf ("\n");    printf ("Available drivers:\n");    for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {        struct audio_driver *d = drvtab[i];        printf ("Name: %s\n", d->name);        printf ("Description: %s\n", d->descr);        audio_pp_nb_voices ("playback", d->max_voices_out);        audio_pp_nb_voices ("capture", d->max_voices_in);        if (d->options) {            printf ("Options:\n");            audio_print_options (d->name, d->options);        }        else {            printf ("No options\n");        }        printf ("\n");    }    printf (        "Options are settable through environment variables.\n"        "Example:\n"#ifdef _WIN32        "  set QEMU_AUDIO_DRV=wav\n"        "  set QEMU_WAV_PATH=c:\\tune.wav\n"#else        "  export QEMU_AUDIO_DRV=wav\n"        "  export QEMU_WAV_PATH=$HOME/tune.wav\n"        "(for csh replace export with setenv in the above)\n"#endif        "  qemu ...\n\n"        );}static int audio_driver_init (AudioState *s, struct audio_driver *drv){    if (drv->options) {        audio_process_options (drv->name, drv->options);    }    s->drv_opaque = drv->init ();    if (s->drv_opaque) {        audio_init_nb_voices_out (s, drv);        audio_init_nb_voices_in (s, drv);        s->drv = drv;        return 0;    }    else {        dolog ("Could not init `%s' audio driver\n", drv->name);        return -1;    }}static void audio_vm_change_state_handler (void *opaque, int running){    AudioState *s = opaque;    HWVoiceOut *hwo = NULL;    HWVoiceIn *hwi = NULL;    int op = running ? VOICE_ENABLE : VOICE_DISABLE;    while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {        hwo->pcm_ops->ctl_out (hwo, op);    }    while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {        hwi->pcm_ops->ctl_in (hwi, op);    }}static void audio_atexit (void){    AudioState *s = &glob_audio_state;    HWVoiceOut *hwo = NULL;    HWVoiceIn *hwi = NULL;    while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {        SWVoiceCap *sc;        hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);        hwo->pcm_ops->fini_out (hwo);        for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {            CaptureVoiceOut *cap = sc->cap;            struct capture_callback *cb;            for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {                cb->ops.destroy (cb->opaque);            }        }    }    while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {        hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);        hwi->pcm_ops->fini_in (hwi);    }    if (s->drv) {        s->drv->fini (s->drv_opaque);    }}static void audio_save (QEMUFile *f, void *opaque){    (void) f;    (void) opaque;}static int audio_load (QEMUFile *f, void *opaque, int version_id){    (void) f;    (void) opaque;    if (version_id != 1) {        return -EINVAL;    }    return 0;}void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card){    card->audio = s;    card->name = qemu_strdup (name);    memset (&card->entries, 0, sizeof (card->entries));    LIST_INSERT_HEAD (&s->card_head, card, entries);}void AUD_remove_card (QEMUSoundCard *card){    LIST_REMOVE (card, entries);    card->audio = NULL;    qemu_free (card->name);}AudioState *AUD_init (void){    size_t i;    int done = 0;    const char *drvname;    AudioState *s = &glob_audio_state;    LIST_INIT (&s->hw_head_out);    LIST_INIT (&s->hw_head_in);    LIST_INIT (&s->cap_head);    atexit (audio_atexit);    s->ts = qemu_new_timer (vm_clock, audio_timer, s);    if (!s->ts) {        dolog ("Could not create audio timer\n");        return NULL;    }    audio_process_options ("AUDIO", audio_options);    s->nb_hw_voices_out = conf.fixed_out.nb_voices;    s->nb_hw_voices_in = conf.fixed_in.nb_voices;    if (s->nb_hw_voices_out <= 0) {        dolog ("Bogus number of playback voices %d, setting to 1\n",               s->nb_hw_voices_out);        s->nb_hw_voices_out = 1;    }    if (s->nb_hw_voices_in <= 0) {        dolog ("Bogus number of capture voices %d, setting to 0\n",               s->nb_hw_voices_in);        s->nb_hw_voices_in = 0;    }    {        int def;        drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);    }    if (drvname) {        int found = 0;        for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {            if (!strcmp (drvname, drvtab[i]->name)) {                done = !audio_driver_init (s, drvtab[i]);                found = 1;                break;            }        }        if (!found) {            dolog ("Unknown audio driver `%s'\n", drvname);            dolog ("Run with -audio-help to list available drivers\n");        }    }    if (!done) {        for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {            if (drvtab[i]->can_be_default) {                done = !audio_driver_init (s, drvtab[i]);            }        }    }    if (!done) {        done = !audio_driver_init (s, &no_audio_driver);        if (!done) {            dolog ("Could not initialize audio subsystem\n");        }        else {            dolog ("warning: Using timer based audio emulation\n");        }    }    if (done) {        VMChangeStateEntry *e;        if (conf.period.hz <= 0) {            if (conf.period.hz < 0) {                dolog ("warning: Timer period is negative - %d "                       "treating as zero\n",                       conf.period.hz);            }            conf.period.ticks = 1;        }        else {            conf.period.ticks = ticks_per_sec / conf.period.hz;        }        e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);        if (!e) {            dolog ("warning: Could not register change state handler\n"                   "(Audio can continue looping even after stopping the VM)\n");        }    }    else {        qemu_del_timer (s->ts);        return NULL;    }    LIST_INIT (&s->card_head);    register_savevm ("audio", 0, 1, audio_save, audio_load, s);    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);    return s;}CaptureVoiceOut *AUD_add_capture (    AudioState *s,    audsettings_t *as,    struct audio_capture_ops *ops,    void *cb_opaque    ){    CaptureVoiceOut *cap;    struct capture_callback *cb;    if (!s) {        /* XXX suppress */        s = &glob_audio_state;    }    if (audio_validate_settings (as)) {        dolog ("Invalid settings were passed when trying to add capture\n");        audio_print_settings (as);        goto err0;    }    cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb));    if (!cb) {        dolog ("Could not allocate capture callback information, size %zu\n",               sizeof (*cb));        goto err0;    }    cb->ops = *ops;    cb->opaque = cb_opaque;    cap = audio_pcm_capture_find_specific (s, as);    if (cap) {        LIST_INSERT_HEAD (&cap->cb_head, cb, entries);        return cap;    }    else {        HWVoiceOut *hw;        CaptureVoiceOut *cap;        cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap));        if (!cap) {            dolog ("Could not allocate capture voice, size %zu\n",                   sizeof (*cap));            goto err1;        }        hw = &cap->hw;        LIST_INIT (&hw->sw_head);        LIST_INIT (&cap->cb_head);        /* XXX find a more elegant way */        hw->samples = 4096 * 4;        hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples,                                    sizeof (st_sample_t));        if (!hw->mix_buf) {            dolog ("Could not allocate capture mix buffer (%d samples)\n",                   hw->samples);            goto err2;        }        audio_pcm_init_info (&hw->info, as);        cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);        if (!cap->buf) {            dolog ("Could not allocate capture buffer "                   "(%d samples, each %d bytes)\n",                   hw->samples, 1 << hw->info.shift);            goto err3;        }        hw->clip = mixeng_clip            [hw->info.nchannels == 2]            [hw->info.sign]            [hw->info.swap_endianness]            [hw->info.bits == 16];        LIST_INSERT_HEAD (&s->cap_head, cap, entries);        LIST_INSERT_HEAD (&cap->cb_head, cb, entries);        hw = NULL;        while ((hw = audio_pcm_hw_find_any_out (s, hw))) {            audio_attach_capture (s, hw);        }        return cap;    err3:        qemu_free (cap->hw.mix_buf);    err2:        qemu_free (cap);    err1:        qemu_free (cb);    err0:        return NULL;    }}void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque){    struct capture_callback *cb;    for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {        if (cb->opaque == cb_opaque) {            cb->ops.destroy (cb_opaque);            LIST_REMOVE (cb, entries);            qemu_free (cb);            if (!cap->cb_head.lh_first) {                SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;                while (sw) {                    SWVoiceCap *sc = (SWVoiceCap *) sw;#ifdef DEBUG_CAPTURE                    dolog ("freeing %s\n", sw->name);#endif                    sw1 = sw->entries.le_next;                    if (sw->rate) {                        st_rate_stop (sw->rate);                        sw->rate = NULL;                    }                    LIST_REMOVE (sw, entries);                    LIST_REMOVE (sc, entries);                    qemu_free (sc);                    sw = sw1;                }                LIST_REMOVE (cap, entries);                qemu_free (cap);            }            return;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -