diff --git a/MAINTAINERS b/MAINTAINERS index 030d505200..a6a1d36f52 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2978,6 +2978,7 @@ X: audio/paaudio.c X: audio/sdlaudio.c X: audio/sndioaudio.c X: audio/spiceaudio.c +F: include/qemu/audio*.h F: qapi/audio.json ALSA Audio backend diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 9b6c01c0ef..7d7da576dc 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -26,7 +26,7 @@ #include #include "qemu/main-loop.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #include "trace.h" #pragma GCC diagnostic ignored "-Waddress" @@ -41,7 +41,7 @@ struct pollhlp { struct pollfd *pfds; int count; int mask; - AudioState *s; + AudioBackend *s; }; typedef struct ALSAVoiceOut { @@ -264,7 +264,7 @@ static int alsa_poll_in (HWVoiceIn *hw) return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN); } -static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) +static snd_pcm_format_t aud_to_alsafmt(AudioFormat fmt, bool big_endian) { switch (fmt) { case AUDIO_FORMAT_S8: @@ -274,39 +274,19 @@ static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness) return SND_PCM_FORMAT_U8; case AUDIO_FORMAT_S16: - if (endianness) { - return SND_PCM_FORMAT_S16_BE; - } else { - return SND_PCM_FORMAT_S16_LE; - } + return big_endian ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE; case AUDIO_FORMAT_U16: - if (endianness) { - return SND_PCM_FORMAT_U16_BE; - } else { - return SND_PCM_FORMAT_U16_LE; - } + return big_endian ? SND_PCM_FORMAT_U16_BE : SND_PCM_FORMAT_U16_LE; case AUDIO_FORMAT_S32: - if (endianness) { - return SND_PCM_FORMAT_S32_BE; - } else { - return SND_PCM_FORMAT_S32_LE; - } + return big_endian ? SND_PCM_FORMAT_S32_BE : SND_PCM_FORMAT_S32_LE; case AUDIO_FORMAT_U32: - if (endianness) { - return SND_PCM_FORMAT_U32_BE; - } else { - return SND_PCM_FORMAT_U32_LE; - } + return big_endian ? SND_PCM_FORMAT_U32_BE : SND_PCM_FORMAT_U32_LE; case AUDIO_FORMAT_F32: - if (endianness) { - return SND_PCM_FORMAT_FLOAT_BE; - } else { - return SND_PCM_FORMAT_FLOAT_LE; - } + return big_endian ? SND_PCM_FORMAT_FLOAT_BE : SND_PCM_FORMAT_FLOAT_LE; default: dolog ("Internal logic error: Bad audio format %d\n", fmt); @@ -956,7 +936,6 @@ static struct audio_pcm_ops alsa_pcm_ops = { static struct audio_driver alsa_audio_driver = { .name = "alsa", - .descr = "ALSA http://www.alsa-project.org", .init = alsa_audio_init, .fini = alsa_audio_fini, .pcm_ops = &alsa_pcm_ops, diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c index 8774c09f18..1ffb5ebc74 100644 --- a/audio/audio-hmp-cmds.c +++ b/audio/audio-hmp-cmds.c @@ -23,11 +23,12 @@ */ #include "qemu/osdep.h" -#include "audio/audio.h" +#include "audio_int.h" #include "monitor/hmp.h" #include "monitor/monitor.h" #include "qapi/error.h" #include "qobject/qdict.h" +#include "qemu/error-report.h" static QLIST_HEAD (capture_list_head, CaptureState) capture_head; @@ -36,6 +37,8 @@ void hmp_info_capture(Monitor *mon, const QDict *qdict) int i; CaptureState *s; + warn_report_once("'info capture' is deprecated since v10.2, to be removed"); + for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) { monitor_printf(mon, "[%d]: ", i); s->ops.info (s->opaque); @@ -48,6 +51,8 @@ void hmp_stopcapture(Monitor *mon, const QDict *qdict) int n = qdict_get_int(qdict, "n"); CaptureState *s; + warn_report_once("'stopcapture' is deprecated since v10.2, to be removed"); + for (s = capture_head.lh_first, i = 0; s; s = s->entries.le_next, ++i) { if (i == n) { s->ops.destroy (s->opaque); @@ -67,7 +72,9 @@ void hmp_wavcapture(Monitor *mon, const QDict *qdict) const char *audiodev = qdict_get_str(qdict, "audiodev"); CaptureState *s; Error *local_err = NULL; - AudioState *as = audio_state_by_name(audiodev, &local_err); + AudioBackend *as = audio_be_by_name(audiodev, &local_err); + + warn_report_once("'wavcapture' is deprecated since v10.2, to be removed"); if (!as) { error_report_err(local_err); diff --git a/audio/audio.c b/audio/audio.c index 89f091bc88..86e674410a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -23,9 +23,8 @@ */ #include "qemu/osdep.h" -#include "audio.h" +#include "qemu/audio.h" #include "migration/vmstate.h" -#include "monitor/monitor.h" #include "qemu/timer.h" #include "qapi/error.h" #include "qapi/clone-visitor.h" @@ -33,7 +32,6 @@ #include "qapi/qapi-visit-audio.h" #include "qapi/qapi-commands-audio.h" #include "qobject/qdict.h" -#include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" @@ -41,7 +39,6 @@ #include "system/system.h" #include "system/replay.h" #include "system/runstate.h" -#include "ui/qemu-spice.h" #include "trace.h" #define AUDIO_CAP "audio" @@ -102,9 +99,7 @@ static audio_driver *audio_driver_lookup(const char *name) return NULL; } -static QTAILQ_HEAD(AudioStateHead, AudioState) audio_states = - QTAILQ_HEAD_INITIALIZER(audio_states); -static AudioState *default_audio_state; +static AudioBackend *default_audio_be; const struct mixeng_volume nominal_volume = { .mute = 0, @@ -279,7 +274,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *a && info->is_signed == is_signed && info->is_float == is_float && info->bits == bits - && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS); + && info->swap_endianness == (as->endianness != HOST_BIG_ENDIAN); } void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as) @@ -325,7 +320,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as) info->nchannels = as->nchannels; info->bytes_per_frame = as->nchannels * mul; info->bytes_per_second = info->freq * info->bytes_per_frame; - info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS); + info->swap_endianness = (as->endianness != HOST_BIG_ENDIAN); } void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) @@ -385,7 +380,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) /* * Capture */ -static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioState *s, +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioBackend *s, struct audsettings *as) { CaptureVoiceOut *cap; @@ -410,7 +405,7 @@ static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd) } } -static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled) +static void audio_capture_maybe_changed(CaptureVoiceOut *cap, bool enabled) { if (cap->hw.enabled != enabled) { audcnotification_e cmd; @@ -424,11 +419,11 @@ static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap) { HWVoiceOut *hw = &cap->hw; SWVoiceOut *sw; - int enabled = 0; + bool enabled = false; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active) { - enabled = 1; + enabled = true; break; } } @@ -465,7 +460,7 @@ static void audio_detach_capture (HWVoiceOut *hw) static int audio_attach_capture (HWVoiceOut *hw) { - AudioState *s = hw->s; + AudioBackend *s = hw->s; CaptureVoiceOut *cap; audio_detach_capture (hw); @@ -480,7 +475,7 @@ static int audio_attach_capture (HWVoiceOut *hw) sw = &sc->sw; sw->hw = hw_cap; sw->info = hw->info; - sw->empty = 1; + sw->empty = true; sw->active = hw->enabled; sw->vol = nominal_volume; sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq); @@ -803,7 +798,7 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) /* * Timer */ -static int audio_is_timer_needed(AudioState *s) +static int audio_is_timer_needed(AudioBackend *s) { HWVoiceIn *hwi = NULL; HWVoiceOut *hwo = NULL; @@ -821,7 +816,7 @@ static int audio_is_timer_needed(AudioState *s) return 0; } -static void audio_reset_timer (AudioState *s) +static void audio_reset_timer(AudioBackend *s) { if (audio_is_timer_needed(s)) { timer_mod_anticipate_ns(s->ts, @@ -843,7 +838,7 @@ static void audio_reset_timer (AudioState *s) static void audio_timer (void *opaque) { int64_t now, diff; - AudioState *s = opaque; + AudioBackend *s = opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); diff = now - s->timer_last; @@ -916,7 +911,7 @@ int AUD_get_buffer_size_out(SWVoiceOut *sw) return sw->hw->samples * sw->hw->info.bytes_per_frame; } -void AUD_set_active_out (SWVoiceOut *sw, int on) +void AUD_set_active_out(SWVoiceOut *sw, bool on) { HWVoiceOut *hw; @@ -926,14 +921,14 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) hw = sw->hw; if (sw->active != on) { - AudioState *s = sw->s; + AudioBackend *s = sw->s; SWVoiceOut *temp_sw; SWVoiceCap *sc; if (on) { hw->pending_disable = 0; if (!hw->enabled) { - hw->enabled = 1; + hw->enabled = true; if (s->vm_running) { if (hw->pcm_ops->enable_out) { hw->pcm_ops->enable_out(hw, true); @@ -964,7 +959,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) } } -void AUD_set_active_in (SWVoiceIn *sw, int on) +void AUD_set_active_in(SWVoiceIn *sw, bool on) { HWVoiceIn *hw; @@ -974,12 +969,12 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) hw = sw->hw; if (sw->active != on) { - AudioState *s = sw->s; + AudioBackend *s = sw->s; SWVoiceIn *temp_sw; if (on) { if (!hw->enabled) { - hw->enabled = 1; + hw->enabled = true; if (s->vm_running) { if (hw->pcm_ops->enable_in) { hw->pcm_ops->enable_in(hw, true); @@ -998,7 +993,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) } if (nb_active == 1) { - hw->enabled = 0; + hw->enabled = false; if (hw->pcm_ops->enable_in) { hw->pcm_ops->enable_in(hw, false); } @@ -1142,7 +1137,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) return clipped; } -static void audio_run_out (AudioState *s) +static void audio_run_out(AudioBackend *s) { HWVoiceOut *hw = NULL; SWVoiceOut *sw; @@ -1157,8 +1152,8 @@ static void audio_run_out (AudioState *s) sw = hw->sw_head.lh_first; if (hw->pending_disable) { - hw->enabled = 0; - hw->pending_disable = 0; + hw->enabled = false; + hw->pending_disable = false; if (hw->pcm_ops->enable_out) { hw->pcm_ops->enable_out(hw, false); } @@ -1211,13 +1206,13 @@ static void audio_run_out (AudioState *s) #ifdef DEBUG_OUT dolog ("Disabling voice\n"); #endif - hw->enabled = 0; - hw->pending_disable = 0; + hw->enabled = false; + hw->pending_disable = false; if (hw->pcm_ops->enable_out) { hw->pcm_ops->enable_out(hw, false); } for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { - sc->sw.active = 0; + sc->sw.active = false; audio_recalc_and_notify_capture (sc->cap); } continue; @@ -1262,7 +1257,7 @@ static void audio_run_out (AudioState *s) sw->total_hw_samples_mixed -= played; if (!sw->total_hw_samples_mixed) { - sw->empty = 1; + sw->empty = true; } } } @@ -1296,7 +1291,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) return conv; } -static void audio_run_in (AudioState *s) +static void audio_run_in(AudioBackend *s) { HWVoiceIn *hw = NULL; @@ -1344,7 +1339,7 @@ static void audio_run_in (AudioState *s) } } -static void audio_run_capture (AudioState *s) +static void audio_run_capture(AudioBackend *s) { CaptureVoiceOut *cap; @@ -1391,7 +1386,7 @@ static void audio_run_capture (AudioState *s) } } -void audio_run(AudioState *s, const char *msg) +void audio_run(AudioBackend *s, const char *msg) { audio_run_out(s); audio_run_in(s); @@ -1564,41 +1559,40 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) return total; } -static int audio_driver_init(AudioState *s, struct audio_driver *drv, - Audiodev *dev, Error **errp) +static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv, + Audiodev *dev, Error **errp) { - Error *local_err = NULL; - - s->drv_opaque = drv->init(dev, &local_err); - - if (s->drv_opaque) { - if (!drv->pcm_ops->get_buffer_in) { - drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in; - drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in; - } - if (!drv->pcm_ops->get_buffer_out) { - drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out; - drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out; - } - - audio_init_nb_voices_out(s, drv, 1); - audio_init_nb_voices_in(s, drv, 0); - s->drv = drv; - return 0; - } else { - if (local_err) { - error_propagate(errp, local_err); - } else { - error_setg(errp, "Could not init `%s' audio driver", drv->name); - } - return -1; + s->drv_opaque = drv->init(dev, errp); + if (!s->drv_opaque) { + return false; } + + if (!drv->pcm_ops->get_buffer_in) { + drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in; + drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in; + } + if (!drv->pcm_ops->get_buffer_out) { + drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out; + drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out; + } + + audio_init_nb_voices_out(s, drv, 1); + audio_init_nb_voices_in(s, drv, 0); + s->drv = drv; + + if (dev->timer_period <= 0) { + s->period_ticks = 1; + } else { + s->period_ticks = dev->timer_period * (int64_t)SCALE_US; + } + + return true; } static void audio_vm_change_state_handler (void *opaque, bool running, RunState state) { - AudioState *s = opaque; + AudioBackend *s = opaque; HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; @@ -1617,8 +1611,26 @@ static void audio_vm_change_state_handler (void *opaque, bool running, audio_reset_timer (s); } -static void free_audio_state(AudioState *s) +static const VMStateDescription vmstate_audio; + +static void audio_be_init(Object *obj) { + AudioBackend *s = AUDIO_BACKEND(obj); + + QLIST_INIT(&s->hw_head_out); + QLIST_INIT(&s->hw_head_in); + QLIST_INIT(&s->cap_head); + s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); + + s->vmse = qemu_add_vm_change_state_handler(audio_vm_change_state_handler, s); + assert(s->vmse != NULL); + + vmstate_register_any(NULL, &vmstate_audio, s); +} + +static void audio_be_finalize(Object *obj) +{ + AudioBackend *s = AUDIO_BACKEND(obj); HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; @@ -1664,17 +1676,24 @@ static void free_audio_state(AudioState *s) s->ts = NULL; } - g_free(s); + if (s->vmse) { + qemu_del_vm_change_state_handler(s->vmse); + s->vmse = NULL; + } + + vmstate_unregister(NULL, &vmstate_audio, s); +} + +static Object *get_audiodevs_root(void) +{ + return object_get_container("audiodevs"); } void audio_cleanup(void) { - default_audio_state = NULL; - while (!QTAILQ_EMPTY(&audio_states)) { - AudioState *s = QTAILQ_FIRST(&audio_states); - QTAILQ_REMOVE(&audio_states, s, list); - free_audio_state(s); - } + default_audio_be = NULL; + + object_unparent(get_audiodevs_root()); } static bool vmstate_audio_needed(void *opaque) @@ -1712,7 +1731,7 @@ void audio_create_default_audiodevs(void) visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_free(v); - audio_define_default(dev, &error_abort); + audio_add_default_audiodev(dev, &error_abort); } } } @@ -1723,26 +1742,14 @@ void audio_create_default_audiodevs(void) * if dev == NULL => legacy implicit initialization, return the already created * state or create a new one */ -static AudioState *audio_init(Audiodev *dev, Error **errp) +static AudioBackend *audio_init(Audiodev *dev, Error **errp) { - static bool atexit_registered; int done = 0; const char *drvname; - VMChangeStateEntry *vmse; - AudioState *s; + AudioBackend *s; struct audio_driver *driver; - s = g_new0(AudioState, 1); - - QLIST_INIT (&s->hw_head_out); - QLIST_INIT (&s->hw_head_in); - QLIST_INIT (&s->cap_head); - if (!atexit_registered) { - atexit(audio_cleanup); - atexit_registered = true; - } - - s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); + s = AUDIO_BACKEND(object_new(TYPE_AUDIO_BACKEND)); if (dev) { /* -audiodev option */ @@ -1750,7 +1757,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); if (driver) { - done = !audio_driver_init(s, driver, dev, errp); + done = audio_driver_init(s, driver, dev, errp); } else { error_setg(errp, "Unknown audio driver `%s'", drvname); } @@ -1758,7 +1765,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) goto out; } } else { - assert(!default_audio_state); + assert(!default_audio_be); for (;;) { AudiodevListEntry *e = QSIMPLEQ_FIRST(&default_audiodevs); if (!e) { @@ -1770,7 +1777,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) g_free(e); drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); - if (!audio_driver_init(s, driver, dev, NULL)) { + if (audio_driver_init(s, driver, dev, NULL)) { break; } qapi_free_Audiodev(dev); @@ -1778,33 +1785,22 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) } } - if (dev->timer_period <= 0) { - s->period_ticks = 1; - } else { - s->period_ticks = dev->timer_period * (int64_t)SCALE_US; + if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { + goto out; } - - vmse = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); - if (!vmse) { - dolog ("warning: Could not register change state handler\n" - "(Audio can continue looping even after stopping the VM)\n"); - } - - QTAILQ_INSERT_TAIL(&audio_states, s, list); - QLIST_INIT (&s->card_head); - vmstate_register_any(NULL, &vmstate_audio, s); + object_unref(s); return s; out: - free_audio_state(s); + object_unref(s); return NULL; } -AudioState *audio_get_default_audio_state(Error **errp) +AudioBackend *audio_get_default_audio_be(Error **errp) { - if (!default_audio_state) { - default_audio_state = audio_init(NULL, errp); - if (!default_audio_state) { + if (!default_audio_be) { + default_audio_be = audio_init(NULL, errp); + if (!default_audio_be) { if (!QSIMPLEQ_EMPTY(&audiodevs)) { error_append_hint(errp, "Perhaps you wanted to use -audio or set audiodev=%s?\n", QSIMPLEQ_FIRST(&audiodevs)->dev->id); @@ -1812,35 +1808,27 @@ AudioState *audio_get_default_audio_state(Error **errp) } } - return default_audio_state; + return default_audio_be; } -bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp) +bool AUD_backend_check(AudioBackend **be, Error **errp) { - if (!card->state) { - card->state = audio_get_default_audio_state(errp); - if (!card->state) { + assert(be != NULL); + + if (!*be) { + *be = audio_get_default_audio_be(errp); + if (!*be) { return false; } } - card->name = g_strdup (name); - memset (&card->entries, 0, sizeof (card->entries)); - QLIST_INSERT_HEAD(&card->state->card_head, card, entries); - return true; } -void AUD_remove_card (QEMUSoundCard *card) -{ - QLIST_REMOVE (card, entries); - g_free (card->name); -} - static struct audio_pcm_ops capture_pcm_ops; CaptureVoiceOut *AUD_add_capture( - AudioState *s, + AudioBackend *s, struct audsettings *as, struct audio_capture_ops *ops, void *cb_opaque @@ -1952,13 +1940,7 @@ void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque) } } -void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol) -{ - Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } }; - audio_set_volume_out(sw, &vol); -} - -void audio_set_volume_out(SWVoiceOut *sw, Volume *vol) +void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol) { if (sw) { HWVoiceOut *hw = sw->hw; @@ -1974,13 +1956,7 @@ void audio_set_volume_out(SWVoiceOut *sw, Volume *vol) } } -void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol) -{ - Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } }; - audio_set_volume_in(sw, &vol); -} - -void audio_set_volume_in(SWVoiceIn *sw, Volume *vol) +void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol) { if (sw) { HWVoiceIn *hw = sw->hw; @@ -2142,10 +2118,10 @@ void audio_parse_option(const char *opt) visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_free(v); - audio_define(dev); + audio_add_audiodev(dev); } -void audio_define(Audiodev *dev) +void audio_add_audiodev(Audiodev *dev) { AudiodevListEntry *e; @@ -2156,7 +2132,7 @@ void audio_define(Audiodev *dev) QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); } -void audio_define_default(Audiodev *dev, Error **errp) +void audio_add_default_audiodev(Audiodev *dev, Error **errp) { AudiodevListEntry *e; @@ -2182,7 +2158,7 @@ audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) .freq = pdo->frequency, .nchannels = pdo->channels, .fmt = pdo->format, - .endianness = AUDIO_HOST_ENDIANNESS, + .endianness = HOST_BIG_ENDIAN, }; } @@ -2235,24 +2211,40 @@ int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, audioformat_bytes_per_sample(as->fmt); } -AudioState *audio_state_by_name(const char *name, Error **errp) +AudioBackend *audio_be_by_name(const char *name, Error **errp) { - AudioState *s; - QTAILQ_FOREACH(s, &audio_states, list) { - assert(s->dev); - if (strcmp(name, s->dev->id) == 0) { - return s; - } + Object *obj = object_resolve_path_component(get_audiodevs_root(), name); + + if (!obj) { + error_setg(errp, "audiodev '%s' not found", name); + return NULL; + } else { + return AUDIO_BACKEND(obj); } - error_setg(errp, "audiodev '%s' not found", name); - return NULL; } -const char *audio_get_id(QEMUSoundCard *card) +#ifdef CONFIG_GIO +bool audio_be_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp) { - if (card->state) { - assert(card->state->dev); - return card->state->dev->id; + assert(be != NULL); + + if (!be->drv->set_dbus_server) { + error_setg(errp, "Audiodev '%s' is not compatible with DBus", be->dev->id); + return false; + } + + return be->drv->set_dbus_server(be, server, p2p, errp); +} +#endif + +const char *audio_be_get_id(AudioBackend *be) +{ + if (be) { + assert(be->dev); + return be->dev->id; } else { return ""; } @@ -2320,3 +2312,20 @@ AudiodevList *qmp_query_audiodevs(Error **errp) } return ret; } + +static const TypeInfo audio_be_info = { + .name = TYPE_AUDIO_BACKEND, + .parent = TYPE_OBJECT, + .instance_size = sizeof(AudioBackend), + .instance_init = audio_be_init, + .instance_finalize = audio_be_finalize, + .abstract = false, /* TODO: subclass drivers and make it abstract */ + .class_size = sizeof(AudioBackendClass), +}; + +static void register_types(void) +{ + type_register_static(&audio_be_info); +} + +type_init(register_types); diff --git a/audio/audio.h b/audio/audio.h deleted file mode 100644 index fcc22307be..0000000000 --- a/audio/audio.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * QEMU Audio subsystem header - * - * Copyright (c) 2003-2005 Vassili Karpov (malc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef QEMU_AUDIO_H -#define QEMU_AUDIO_H - -#include "qemu/queue.h" -#include "qapi/qapi-types-audio.h" -#include "hw/qdev-properties.h" -#include "hw/qdev-properties-system.h" - -typedef void (*audio_callback_fn) (void *opaque, int avail); - -#if HOST_BIG_ENDIAN -#define AUDIO_HOST_ENDIANNESS 1 -#else -#define AUDIO_HOST_ENDIANNESS 0 -#endif - -typedef struct audsettings { - int freq; - int nchannels; - AudioFormat fmt; - int endianness; -} audsettings; - -audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo); -int audioformat_bytes_per_sample(AudioFormat fmt); -int audio_buffer_frames(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs); -int audio_buffer_samples(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs); -int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, - audsettings *as, int def_usecs); - -typedef enum { - AUD_CNOTIFY_ENABLE, - AUD_CNOTIFY_DISABLE -} audcnotification_e; - -struct audio_capture_ops { - void (*notify) (void *opaque, audcnotification_e cmd); - void (*capture) (void *opaque, const void *buf, int size); - void (*destroy) (void *opaque); -}; - -struct capture_ops { - void (*info) (void *opaque); - void (*destroy) (void *opaque); -}; - -typedef struct CaptureState { - void *opaque; - struct capture_ops ops; - QLIST_ENTRY (CaptureState) entries; -} CaptureState; - -typedef struct SWVoiceOut SWVoiceOut; -typedef struct CaptureVoiceOut CaptureVoiceOut; -typedef struct SWVoiceIn SWVoiceIn; - -typedef struct AudioState AudioState; -typedef struct QEMUSoundCard { - char *name; - AudioState *state; - QLIST_ENTRY (QEMUSoundCard) entries; -} QEMUSoundCard; - -typedef struct QEMUAudioTimeStamp { - uint64_t old_ts; -} QEMUAudioTimeStamp; - -void AUD_vlog (const char *cap, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0); -void AUD_log (const char *cap, const char *fmt, ...) G_GNUC_PRINTF(2, 3); - -bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp); -void AUD_remove_card (QEMUSoundCard *card); -CaptureVoiceOut *AUD_add_capture( - AudioState *s, - struct audsettings *as, - struct audio_capture_ops *ops, - void *opaque - ); -void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); - -SWVoiceOut *AUD_open_out ( - QEMUSoundCard *card, - SWVoiceOut *sw, - const char *name, - void *callback_opaque, - audio_callback_fn callback_fn, - struct audsettings *settings - ); - -void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw); -size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size); -int AUD_get_buffer_size_out (SWVoiceOut *sw); -void AUD_set_active_out (SWVoiceOut *sw, int on); -int AUD_is_active_out (SWVoiceOut *sw); - -void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); -uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); - -void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol); -void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol); - -#define AUDIO_MAX_CHANNELS 16 -typedef struct Volume { - bool mute; - int channels; - uint8_t vol[AUDIO_MAX_CHANNELS]; -} Volume; - -void audio_set_volume_out(SWVoiceOut *sw, Volume *vol); -void audio_set_volume_in(SWVoiceIn *sw, Volume *vol); - -SWVoiceIn *AUD_open_in ( - QEMUSoundCard *card, - SWVoiceIn *sw, - const char *name, - void *callback_opaque, - audio_callback_fn callback_fn, - struct audsettings *settings - ); - -void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw); -size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size); -void AUD_set_active_in (SWVoiceIn *sw, int on); -int AUD_is_active_in (SWVoiceIn *sw); - -void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); -uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); - -static inline void *advance (void *p, int incr) -{ - uint8_t *d = p; - return (d + incr); -} - -int wav_start_capture(AudioState *state, CaptureState *s, const char *path, - int freq, int bits, int nchannels); - -void audio_cleanup(void); - -void audio_sample_to_uint64(const void *samples, int pos, - uint64_t *left, uint64_t *right); -void audio_sample_from_uint64(void *samples, int pos, - uint64_t left, uint64_t right); - -void audio_define(Audiodev *audio); -void audio_define_default(Audiodev *dev, Error **errp); -void audio_parse_option(const char *opt); -void audio_create_default_audiodevs(void); -void audio_init_audiodevs(void); -void audio_help(void); - -AudioState *audio_state_by_name(const char *name, Error **errp); -AudioState *audio_get_default_audio_state(Error **errp); -const char *audio_get_id(QEMUSoundCard *card); - -#define DEFINE_AUDIO_PROPERTIES(_s, _f) \ - DEFINE_PROP_AUDIODEV("audiodev", _s, _f) - -#endif /* QEMU_AUDIO_H */ diff --git a/audio/audio_int.h b/audio/audio_int.h index f78ca05f92..b2b8002477 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -29,12 +29,20 @@ #define FLOAT_MIXENG /* #define RECIPROCAL */ #endif +#include "qemu/audio.h" +#include "qemu/audio-capture.h" #include "mixeng.h" #ifdef CONFIG_GIO #include #endif +void G_GNUC_PRINTF(2, 0) +AUD_vlog(const char *cap, const char *fmt, va_list ap); + +void G_GNUC_PRINTF(2, 3) +AUD_log(const char *cap, const char *fmt, ...); + struct audio_pcm_ops; struct audio_callback { @@ -53,7 +61,7 @@ struct audio_pcm_info { int swap_endianness; }; -typedef struct AudioState AudioState; +typedef struct AudioBackend AudioBackend; typedef struct SWVoiceCap SWVoiceCap; typedef struct STSampleBuffer { @@ -62,10 +70,10 @@ typedef struct STSampleBuffer { } STSampleBuffer; typedef struct HWVoiceOut { - AudioState *s; - int enabled; + AudioBackend *s; + bool enabled; int poll_mode; - int pending_disable; + bool pending_disable; struct audio_pcm_info info; f_sample *clip; @@ -83,8 +91,8 @@ typedef struct HWVoiceOut { } HWVoiceOut; typedef struct HWVoiceIn { - AudioState *s; - int enabled; + AudioBackend *s; + bool enabled; int poll_mode; struct audio_pcm_info info; @@ -104,15 +112,14 @@ typedef struct HWVoiceIn { } HWVoiceIn; struct SWVoiceOut { - QEMUSoundCard *card; - AudioState *s; + AudioBackend *s; struct audio_pcm_info info; t_sample *conv; STSampleBuffer resample_buf; void *rate; size_t total_hw_samples_mixed; - int active; - int empty; + bool active; + bool empty; HWVoiceOut *hw; char *name; struct mixeng_volume vol; @@ -121,9 +128,8 @@ struct SWVoiceOut { }; struct SWVoiceIn { - QEMUSoundCard *card; - AudioState *s; - int active; + AudioBackend *s; + bool active; struct audio_pcm_info info; void *rate; size_t total_hw_samples_acquired; @@ -139,11 +145,13 @@ struct SWVoiceIn { typedef struct audio_driver audio_driver; struct audio_driver { const char *name; - const char *descr; void *(*init) (Audiodev *, Error **); void (*fini) (void *); #ifdef CONFIG_GIO - void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); + bool (*set_dbus_server)(AudioBackend *be, + GDBusObjectManagerServer *manager, + bool p2p, + Error **errp); #endif struct audio_pcm_ops *pcm_ops; int max_voices_out; @@ -187,6 +195,23 @@ struct audio_pcm_ops { void (*volume_in)(HWVoiceIn *hw, Volume *vol); }; +audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo); +int audioformat_bytes_per_sample(AudioFormat fmt); +int audio_buffer_frames(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs); +int audio_buffer_samples(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs); +int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, + audsettings *as, int def_usecs); + +static inline void *advance(void *p, size_t incr) +{ + return (uint8_t *)p + incr; +} + +int wav_start_capture(AudioBackend *state, CaptureState *s, const char *path, + int freq, int bits, int nchannels); + void audio_generic_run_buffer_in(HWVoiceIn *hw); void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size); @@ -216,13 +241,14 @@ struct SWVoiceCap { QLIST_ENTRY (SWVoiceCap) entries; }; -typedef struct AudioState { +typedef struct AudioBackend { + Object parent; + struct audio_driver *drv; Audiodev *dev; void *drv_opaque; QEMUTimer *ts; - QLIST_HEAD (card_listhead, QEMUSoundCard) card_head; QLIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; QLIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; QLIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head; @@ -233,9 +259,8 @@ typedef struct AudioState { bool timer_running; uint64_t timer_last; - - QTAILQ_ENTRY(AudioState) list; -} AudioState; + VMChangeStateEntry *vmse; +} AudioBackend; extern const struct mixeng_volume nominal_volume; @@ -248,7 +273,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); int audio_bug (const char *funcname, int cond); -void audio_run(AudioState *s, const char *msg); +void audio_run(AudioBackend *s, const char *msg); const char *audio_application_name(void); diff --git a/audio/audio_template.h b/audio/audio_template.h index c29d79c443..7a8c431f2d 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -36,7 +36,7 @@ #define HWBUF hw->conv_buf #endif -static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, +static void glue(audio_init_nb_voices_, TYPE)(AudioBackend *s, struct audio_driver *drv, int min_voices) { int max_voices = glue (drv->max_voices_, TYPE); @@ -166,10 +166,10 @@ static int glue (audio_pcm_sw_init_, TYPE) ( audio_pcm_init_info (&sw->info, as); sw->hw = hw; - sw->active = 0; + sw->active = false; #ifdef DAC sw->total_hw_samples_mixed = 0; - sw->empty = 1; + sw->empty = true; #endif if (sw->info.is_float) { @@ -221,7 +221,7 @@ static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw) static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp) { HW *hw = *hwp; - AudioState *s = hw->s; + AudioBackend *s = hw->s; if (!hw->sw_head.lh_first) { #ifdef DAC @@ -236,12 +236,12 @@ static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp) } } -static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioState *s, HW *hw) +static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioBackend *s, HW *hw) { return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first; } -static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw) +static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioBackend *s, HW *hw) { while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) { if (hw->enabled) { @@ -251,7 +251,7 @@ static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioState *s, HW *hw) return NULL; } -static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw, +static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioBackend *s, HW *hw, struct audsettings *as) { while ((hw = glue(audio_pcm_hw_find_any_, TYPE)(s, hw))) { @@ -262,7 +262,7 @@ static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioState *s, HW *hw, return NULL; } -static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, +static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioBackend *s, struct audsettings *as) { HW *hw; @@ -398,7 +398,7 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) abort(); } -static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as) +static HW *glue(audio_pcm_hw_add_, TYPE)(AudioBackend *s, struct audsettings *as) { HW *hw; AudiodevPerDirectionOptions *pdo = glue(audio_get_pdo_, TYPE)(s->dev); @@ -424,7 +424,7 @@ static HW *glue(audio_pcm_hw_add_, TYPE)(AudioState *s, struct audsettings *as) } static SW *glue(audio_pcm_create_voice_pair_, TYPE)( - AudioState *s, + AudioBackend *s, const char *sw_name, struct audsettings *as ) @@ -473,11 +473,11 @@ static void glue (audio_close_, TYPE) (SW *sw) g_free (sw); } -void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) +void glue(AUD_close_, TYPE)(AudioBackend *be, SW *sw) { if (sw) { - if (audio_bug(__func__, !card)) { - dolog ("card=%p\n", card); + if (audio_bug(__func__, !be)) { + dolog("backend=%p\n", be); return; } @@ -486,7 +486,7 @@ void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) } SW *glue (AUD_open_, TYPE) ( - QEMUSoundCard *card, + AudioBackend *be, SW *sw, const char *name, void *callback_opaque , @@ -494,16 +494,15 @@ SW *glue (AUD_open_, TYPE) ( struct audsettings *as ) { - AudioState *s; + AudioBackend *s = be; AudiodevPerDirectionOptions *pdo; - if (audio_bug(__func__, !card || !name || !callback_fn || !as)) { - dolog ("card=%p name=%p callback_fn=%p as=%p\n", - card, name, callback_fn, as); + if (audio_bug(__func__, !be || !name || !callback_fn || !as)) { + dolog("backend=%p name=%p callback_fn=%p as=%p\n", + be, name, callback_fn, as); goto fail; } - s = card->state; pdo = glue(audio_get_pdo_, TYPE)(s->dev); ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", @@ -524,7 +523,7 @@ SW *glue (AUD_open_, TYPE) ( } if (!pdo->fixed_settings && sw) { - glue (AUD_close_, TYPE) (card, sw); + glue(AUD_close_, TYPE)(be, sw); sw = NULL; } @@ -548,7 +547,6 @@ SW *glue (AUD_open_, TYPE) ( } } - sw->card = card; sw->vol = nominal_volume; sw->callback.fn = callback_fn; sw->callback.opaque = callback_opaque; @@ -562,11 +560,11 @@ SW *glue (AUD_open_, TYPE) ( return sw; fail: - glue (AUD_close_, TYPE) (card, sw); + glue(AUD_close_, TYPE)(be, sw); return NULL; } -int glue (AUD_is_active_, TYPE) (SW *sw) +bool glue(AUD_is_active_, TYPE)(SW *sw) { return sw ? sw->active : 0; } diff --git a/audio/audio_win_int.c b/audio/audio_win_int.c index 316f118f50..44a8ff24a6 100644 --- a/audio/audio_win_int.c +++ b/audio/audio_win_int.c @@ -7,7 +7,7 @@ #include #include -#include "audio.h" +#include "qemu/audio.h" #include "audio_int.h" #include "audio_win_int.h" diff --git a/audio/coreaudio.m b/audio/coreaudio.m index cadd729d50..997017a1e9 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -28,7 +28,7 @@ #include "qemu/main-loop.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "coreaudio" #include "audio_int.h" @@ -664,7 +664,6 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { static struct audio_driver coreaudio_audio_driver = { .name = "coreaudio", - .descr = "CoreAudio http://developer.apple.com/audio/coreaudio.html", .init = coreaudio_audio_init, .fini = coreaudio_audio_fini, .pcm_ops = &coreaudio_pcm_ops, diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index b44fdd1511..d729a810aa 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -24,9 +24,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" -#include "qemu/host-utils.h" #include "qemu/module.h" -#include "qemu/timer.h" #include "qemu/dbus.h" #ifdef G_OS_UNIX @@ -37,7 +35,7 @@ #include "ui/dbus-display1.h" #define AUDIO_CAP "dbus" -#include "audio.h" +#include "qemu/audio.h" #include "audio_int.h" #include "trace.h" @@ -460,7 +458,7 @@ listener_in_vanished_cb(GDBusConnection *connection, } static gboolean -dbus_audio_register_listener(AudioState *s, +dbus_audio_register_listener(AudioBackend *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -617,7 +615,7 @@ dbus_audio_register_listener(AudioState *s, } static gboolean -dbus_audio_register_out_listener(AudioState *s, +dbus_audio_register_out_listener(AudioBackend *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -633,7 +631,7 @@ dbus_audio_register_out_listener(AudioState *s, } static gboolean -dbus_audio_register_in_listener(AudioState *s, +dbus_audio_register_in_listener(AudioBackend *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -647,8 +645,11 @@ dbus_audio_register_in_listener(AudioState *s, arg_listener, false); } -static void -dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p) +static bool +dbus_audio_set_server(AudioBackend *s, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp) { DBusAudio *da = s->drv_opaque; @@ -671,6 +672,8 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p) g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio), G_DBUS_INTERFACE_SKELETON(da->iface)); g_dbus_object_manager_server_export(da->server, da->audio); + + return true; } static struct audio_pcm_ops dbus_pcm_ops = { @@ -692,7 +695,6 @@ static struct audio_pcm_ops dbus_pcm_ops = { static struct audio_driver dbus_audio_driver = { .name = "dbus", - .descr = "Timer based audio exposed with DBus interface", .init = dbus_audio_init, .fini = dbus_audio_fini, .set_dbus_server = dbus_audio_set_server, diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index f3bb48d007..7a03d1dad8 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -27,12 +27,12 @@ */ #include "qemu/osdep.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "dsound" #include "audio_int.h" -#include "qemu/host-utils.h" #include "qemu/module.h" +#include "qapi/error.h" #include #include @@ -64,162 +64,154 @@ typedef struct { dsound *s; } DSoundVoiceIn; -static void dsound_log_hresult (HRESULT hr) +static const char *dserror(HRESULT hr) { - const char *str = "BUG"; - switch (hr) { case DS_OK: - str = "The method succeeded"; - break; + return "The method succeeded"; #ifdef DS_NO_VIRTUALIZATION case DS_NO_VIRTUALIZATION: - str = "The buffer was created, but another 3D algorithm was substituted"; - break; + return "The buffer was created, but another 3D algorithm was substituted"; #endif #ifdef DS_INCOMPLETE case DS_INCOMPLETE: - str = "The method succeeded, but not all the optional effects were obtained"; - break; + return "The method succeeded, but not all the optional effects were obtained"; #endif #ifdef DSERR_ACCESSDENIED case DSERR_ACCESSDENIED: - str = "The request failed because access was denied"; - break; + return "The request failed because access was denied"; #endif #ifdef DSERR_ALLOCATED case DSERR_ALLOCATED: - str = "The request failed because resources, " - "such as a priority level, were already in use " - "by another caller"; - break; + return "The request failed because resources, " + "such as a priority level, were already in use " + "by another caller"; #endif #ifdef DSERR_ALREADYINITIALIZED case DSERR_ALREADYINITIALIZED: - str = "The object is already initialized"; - break; + return "The object is already initialized"; #endif #ifdef DSERR_BADFORMAT case DSERR_BADFORMAT: - str = "The specified wave format is not supported"; - break; + return "The specified wave format is not supported"; #endif #ifdef DSERR_BADSENDBUFFERGUID case DSERR_BADSENDBUFFERGUID: - str = "The GUID specified in an audiopath file " - "does not match a valid mix-in buffer"; - break; + return "The GUID specified in an audiopath file " + "does not match a valid mix-in buffer"; #endif #ifdef DSERR_BUFFERLOST case DSERR_BUFFERLOST: - str = "The buffer memory has been lost and must be restored"; - break; + return "The buffer memory has been lost and must be restored"; #endif #ifdef DSERR_BUFFERTOOSMALL case DSERR_BUFFERTOOSMALL: - str = "The buffer size is not great enough to " - "enable effects processing"; - break; + return "The buffer size is not great enough to " + "enable effects processing"; #endif #ifdef DSERR_CONTROLUNAVAIL case DSERR_CONTROLUNAVAIL: - str = "The buffer control (volume, pan, and so on) " - "requested by the caller is not available. " - "Controls must be specified when the buffer is created, " - "using the dwFlags member of DSBUFFERDESC"; - break; + return "The buffer control (volume, pan, and so on) " + "requested by the caller is not available. " + "Controls must be specified when the buffer is created, " + "using the dwFlags member of DSBUFFERDESC"; #endif #ifdef DSERR_DS8_REQUIRED case DSERR_DS8_REQUIRED: - str = "A DirectSound object of class CLSID_DirectSound8 or later " - "is required for the requested functionality. " - "For more information, see IDirectSound8 Interface"; - break; + return "A DirectSound object of class CLSID_DirectSound8 or later " + "is required for the requested functionality. " + "For more information, see IDirectSound8 Interface"; #endif #ifdef DSERR_FXUNAVAILABLE case DSERR_FXUNAVAILABLE: - str = "The effects requested could not be found on the system, " - "or they are in the wrong order or in the wrong location; " - "for example, an effect expected in hardware " - "was found in software"; - break; + return "The effects requested could not be found on the system, " + "or they are in the wrong order or in the wrong location; " + "for example, an effect expected in hardware " + "was found in software"; #endif #ifdef DSERR_GENERIC case DSERR_GENERIC: - str = "An undetermined error occurred inside the DirectSound subsystem"; - break; + return "An undetermined error occurred inside the DirectSound subsystem"; #endif #ifdef DSERR_INVALIDCALL case DSERR_INVALIDCALL: - str = "This function is not valid for the current state of this object"; - break; + return "This function is not valid for the current state of this object"; #endif #ifdef DSERR_INVALIDPARAM case DSERR_INVALIDPARAM: - str = "An invalid parameter was passed to the returning function"; - break; + return "An invalid parameter was passed to the returning function"; #endif #ifdef DSERR_NOAGGREGATION case DSERR_NOAGGREGATION: - str = "The object does not support aggregation"; - break; + return "The object does not support aggregation"; #endif #ifdef DSERR_NODRIVER case DSERR_NODRIVER: - str = "No sound driver is available for use, " - "or the given GUID is not a valid DirectSound device ID"; - break; + return "No sound driver is available for use, " + "or the given GUID is not a valid DirectSound device ID"; #endif #ifdef DSERR_NOINTERFACE case DSERR_NOINTERFACE: - str = "The requested COM interface is not available"; - break; + return "The requested COM interface is not available"; #endif #ifdef DSERR_OBJECTNOTFOUND case DSERR_OBJECTNOTFOUND: - str = "The requested object was not found"; - break; + return "The requested object was not found"; #endif #ifdef DSERR_OTHERAPPHASPRIO case DSERR_OTHERAPPHASPRIO: - str = "Another application has a higher priority level, " + return "Another application has a higher priority level, " "preventing this call from succeeding"; - break; #endif #ifdef DSERR_OUTOFMEMORY case DSERR_OUTOFMEMORY: - str = "The DirectSound subsystem could not allocate " + return "The DirectSound subsystem could not allocate " "sufficient memory to complete the caller's request"; - break; #endif #ifdef DSERR_PRIOLEVELNEEDED case DSERR_PRIOLEVELNEEDED: - str = "A cooperative level of DSSCL_PRIORITY or higher is required"; - break; + return "A cooperative level of DSSCL_PRIORITY or higher is required"; #endif #ifdef DSERR_SENDLOOP case DSERR_SENDLOOP: - str = "A circular loop of send effects was detected"; - break; + return "A circular loop of send effects was detected"; #endif #ifdef DSERR_UNINITIALIZED case DSERR_UNINITIALIZED: - str = "The Initialize method has not been called " - "or has not been called successfully " - "before other methods were called"; - break; + return "The Initialize method has not been called " + "or has not been called successfully " + "before other methods were called"; #endif #ifdef DSERR_UNSUPPORTED case DSERR_UNSUPPORTED: - str = "The function called is not supported at this time"; - break; + return "The function called is not supported at this time"; #endif default: - AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT 0x%lx)\n", hr); - return; + return NULL; } - AUD_log (AUDIO_CAP, "Reason: %s\n", str); +} + +static void dserror_set(Error **errp, HRESULT hr, const char *msg) +{ + const char *str = dserror(hr); + + if (str) { + error_setg(errp, "%s: %s", msg, str); + } else { + error_setg(errp, "%s: Unknown (HRESULT: 0x%lx)", msg, hr); + } +} + +static void dsound_log_hresult(HRESULT hr) +{ + const char *str = dserror(hr); + + if (str) { + AUD_log (AUDIO_CAP, "Reason: %s\n", str); + } else { + AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT: 0x%lx)\n", hr); + } } static void G_GNUC_PRINTF (2, 3) dsound_logerr ( @@ -359,27 +351,6 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, dsound_unlock_out (dsb, p1, p2, blen1, blen2); } -static int dsound_set_cooperative_level(dsound *s) -{ - HRESULT hr; - HWND hwnd; - - hwnd = GetDesktopWindow(); - hr = IDirectSound_SetCooperativeLevel ( - s->dsound, - hwnd, - DSSCL_PRIORITY - ); - - if (FAILED (hr)) { - dsound_logerr (hr, "Could not set cooperative level for window %p\n", - hwnd); - return -1; - } - - return 0; -} - static void dsound_enable_out(HWVoiceOut *hw, bool enable) { HRESULT hr; @@ -621,7 +592,6 @@ static void dsound_audio_fini (void *opaque) static void *dsound_audio_init(Audiodev *dev, Error **errp) { - int err; HRESULT hr; dsound *s = g_new0(dsound, 1); AudiodevDsoundOptions *dso; @@ -637,8 +607,8 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) hr = CoInitialize (NULL); if (FAILED (hr)) { - dsound_logerr (hr, "Could not initialize COM\n"); - g_free(s); + dserror_set(errp, hr, "Could not initialize COM"); + dsound_audio_fini(s); return NULL; } @@ -650,20 +620,15 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) (void **) &s->dsound ); if (FAILED (hr)) { - dsound_logerr (hr, "Could not create DirectSound instance\n"); - g_free(s); + dserror_set(errp, hr, "Could not create DirectSound instance"); + dsound_audio_fini(s); return NULL; } hr = IDirectSound_Initialize (s->dsound, NULL); if (FAILED (hr)) { - dsound_logerr (hr, "Could not initialize DirectSound\n"); - - hr = IDirectSound_Release (s->dsound); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not release DirectSound\n"); - } - g_free(s); + dserror_set(errp, hr, "Could not initialize DirectSound"); + dsound_audio_fini(s); return NULL; } @@ -675,23 +640,26 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) (void **) &s->dsound_capture ); if (FAILED (hr)) { - dsound_logerr (hr, "Could not create DirectSoundCapture instance\n"); - } else { - hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not initialize DirectSoundCapture\n"); - - hr = IDirectSoundCapture_Release (s->dsound_capture); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not release DirectSoundCapture\n"); - } - s->dsound_capture = NULL; - } + dserror_set(errp, hr, "Could not create DirectSoundCapture instance"); + dsound_audio_fini(s); + return NULL; } - err = dsound_set_cooperative_level(s); - if (err) { - dsound_audio_fini (s); + hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); + if (FAILED(hr)) { + dserror_set(errp, hr, "Could not initialize DirectSoundCapture"); + dsound_audio_fini(s); + return NULL; + } + + hr = IDirectSound_SetCooperativeLevel ( + s->dsound, + GetDesktopWindow(), + DSSCL_PRIORITY + ); + if (FAILED(hr)) { + dserror_set(errp, hr, "Could not set cooperative level"); + dsound_audio_fini(s); return NULL; } @@ -717,7 +685,6 @@ static struct audio_pcm_ops dsound_pcm_ops = { static struct audio_driver dsound_audio_driver = { .name = "dsound", - .descr = "DirectSound http://wikipedia.org/wiki/DirectSound", .init = dsound_audio_init, .fini = dsound_audio_fini, .pcm_ops = &dsound_pcm_ops, diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 974a3caad3..7a3fcaedba 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -26,7 +26,7 @@ #include "qemu/module.h" #include "qemu/atomic.h" #include "qemu/main-loop.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "jack" #include "audio_int.h" @@ -672,7 +672,6 @@ static struct audio_pcm_ops jack_pcm_ops = { static struct audio_driver jack_driver = { .name = "jack", - .descr = "JACK Audio Connection Kit Client", .init = qjack_init, .fini = qjack_fini, .pcm_ops = &jack_pcm_ops, diff --git a/audio/meson.build b/audio/meson.build index 59f0a431d5..b2dca2c640 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,12 +1,13 @@ -system_ss.add([spice_headers, files('audio.c')]) system_ss.add(files( - 'audio-hmp-cmds.c', + 'audio.c', 'mixeng.c', 'noaudio.c', 'wavaudio.c', - 'wavcapture.c', )) +# deprecated since v10.2, to be removed +system_ss.add(files('audio-hmp-cmds.c', 'wavcapture.c')) + system_ss.add(when: coreaudio, if_true: files('coreaudio.m')) system_ss.add(when: dsound, if_true: files('dsoundaudio.c', 'audio_win_int.c')) diff --git a/audio/mixeng.c b/audio/mixeng.c index 703ee5448f..e63c76e021 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -24,11 +24,13 @@ */ #include "qemu/osdep.h" #include "qemu/bswap.h" -#include "qemu/error-report.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "mixeng" #include "audio_int.h" +#ifdef FLOAT_MIXENG +#include "qemu/error-report.h" +#endif /* 8 bit */ #define ENDIAN_CONVERSION natural @@ -402,7 +404,7 @@ f_sample *mixeng_clip_float[2][2] = { } }; -void audio_sample_to_uint64(const void *samples, int pos, +void audio_sample_to_uint64(const st_sample *sample, int pos, uint64_t *left, uint64_t *right) { #ifdef FLOAT_MIXENG @@ -410,14 +412,13 @@ void audio_sample_to_uint64(const void *samples, int pos, "Coreaudio and floating point samples are not supported by replay yet"); abort(); #else - const struct st_sample *sample = samples; sample += pos; *left = sample->l; *right = sample->r; #endif } -void audio_sample_from_uint64(void *samples, int pos, +void audio_sample_from_uint64(st_sample *sample, int pos, uint64_t left, uint64_t right) { #ifdef FLOAT_MIXENG @@ -425,7 +426,6 @@ void audio_sample_from_uint64(void *samples, int pos, "Coreaudio and floating point samples are not supported by replay yet"); abort(); #else - struct st_sample *sample = samples; sample += pos; sample->l = left; sample->r = right; diff --git a/audio/mixeng.h b/audio/mixeng.h index ead93ac2f7..f63283f408 100644 --- a/audio/mixeng.h +++ b/audio/mixeng.h @@ -33,7 +33,6 @@ struct st_sample { mixeng_real l; mixeng_real r; }; struct mixeng_volume { int mute; int64_t r; int64_t l; }; struct st_sample { int64_t l; int64_t r; }; #endif -typedef struct st_sample st_sample; typedef void (t_sample) (struct st_sample *dst, const void *src, int samples); typedef void (f_sample) (void *dst, const struct st_sample *src, int samples); diff --git a/audio/noaudio.c b/audio/noaudio.c index 1b60d8518a..4ed9d2156c 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -23,10 +23,8 @@ */ #include "qemu/osdep.h" -#include "qemu/host-utils.h" #include "qemu/module.h" -#include "audio.h" -#include "qemu/timer.h" +#include "qemu/audio.h" #define AUDIO_CAP "noaudio" #include "audio_int.h" @@ -131,7 +129,6 @@ static struct audio_pcm_ops no_pcm_ops = { static struct audio_driver no_audio_driver = { .name = "none", - .descr = "Timer based audio emulation", .init = no_audio_init, .fini = no_audio_fini, .pcm_ops = &no_pcm_ops, diff --git a/audio/ossaudio.c b/audio/ossaudio.c index c5858284a1..c6cad47a01 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -29,7 +29,7 @@ #include "qemu/module.h" #include "qemu/host-utils.h" #include "qapi/error.h" -#include "audio.h" +#include "qemu/audio.h" #include "trace.h" #define AUDIO_CAP "oss" @@ -107,13 +107,13 @@ static void oss_anal_close (int *fdp) static void oss_helper_poll_out (void *opaque) { - AudioState *s = opaque; + AudioBackend *s = opaque; audio_run(s, "oss_poll_out"); } static void oss_helper_poll_in (void *opaque) { - AudioState *s = opaque; + AudioBackend *s = opaque; audio_run(s, "oss_poll_in"); } @@ -131,7 +131,7 @@ static void oss_poll_in (HWVoiceIn *hw) qemu_set_fd_handler(oss->fd, oss_helper_poll_in, NULL, hw->s); } -static int aud_to_ossfmt (AudioFormat fmt, int endianness) +static int aud_to_ossfmt(AudioFormat fmt, bool big_endian) { switch (fmt) { case AUDIO_FORMAT_S8: @@ -141,18 +141,10 @@ static int aud_to_ossfmt (AudioFormat fmt, int endianness) return AFMT_U8; case AUDIO_FORMAT_S16: - if (endianness) { - return AFMT_S16_BE; - } else { - return AFMT_S16_LE; - } + return big_endian ? AFMT_S16_BE : AFMT_S16_LE; case AUDIO_FORMAT_U16: - if (endianness) { - return AFMT_U16_BE; - } else { - return AFMT_U16_LE; - } + return big_endian ? AFMT_U16_BE : AFMT_U16_LE; default: dolog ("Internal logic error: Bad audio format %d\n", fmt); @@ -493,10 +485,8 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, { OSSVoiceOut *oss = (OSSVoiceOut *) hw; struct oss_params req, obt; - int endianness; int err; int fd; - AudioFormat effective_fmt; struct audsettings obt_as; Audiodev *dev = drv_opaque; AudiodevOssOptions *oopts = &dev->u.oss; @@ -511,7 +501,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } - err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); + err = oss_to_audfmt(obt.fmt, &obt_as.fmt, &obt_as.endianness); if (err) { oss_anal_close (&fd); return -1; @@ -519,8 +509,6 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; - obt_as.fmt = effective_fmt; - obt_as.endianness = endianness; audio_pcm_init_info (&hw->info, &obt_as); oss->nfrags = obt.nfrags; @@ -628,10 +616,8 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; struct oss_params req, obt; - int endianness; int err; int fd; - AudioFormat effective_fmt; struct audsettings obt_as; Audiodev *dev = drv_opaque; @@ -644,7 +630,7 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) return -1; } - err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); + err = oss_to_audfmt(obt.fmt, &obt_as.fmt, &obt_as.endianness); if (err) { oss_anal_close (&fd); return -1; @@ -652,8 +638,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; - obt_as.fmt = effective_fmt; - obt_as.endianness = endianness; audio_pcm_init_info (&hw->info, &obt_as); oss->nfrags = obt.nfrags; @@ -779,7 +763,6 @@ static struct audio_pcm_ops oss_pcm_ops = { static struct audio_driver oss_audio_driver = { .name = "oss", - .descr = "OSS http://www.opensound.com", .init = oss_audio_init, .fini = oss_audio_fini, .pcm_ops = &oss_pcm_ops, diff --git a/audio/paaudio.c b/audio/paaudio.c index f3193b08c3..0c06a39719 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -2,7 +2,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #include "qapi/error.h" #include @@ -316,7 +316,7 @@ unlock_and_fail: return 0; } -static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness) +static pa_sample_format_t audfmt_to_pa(AudioFormat afmt, bool big_endian) { int format; @@ -327,14 +327,14 @@ static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness) break; case AUDIO_FORMAT_S16: case AUDIO_FORMAT_U16: - format = endianness ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; + format = big_endian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE; break; case AUDIO_FORMAT_S32: case AUDIO_FORMAT_U32: - format = endianness ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; + format = big_endian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE; break; case AUDIO_FORMAT_F32: - format = endianness ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; + format = big_endian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE; break; default: dolog ("Internal logic error: Bad audio format %d\n", afmt); @@ -747,14 +747,13 @@ static void qpa_volume_in(HWVoiceIn *hw, Volume *vol) pa_threaded_mainloop_unlock(c->mainloop); } -static int qpa_validate_per_direction_opts(Audiodev *dev, - AudiodevPaPerDirectionOptions *pdo) +static void qpa_validate_per_direction_opts(Audiodev *dev, + AudiodevPaPerDirectionOptions *pdo) { if (!pdo->has_latency) { pdo->has_latency = true; pdo->latency = 46440; } - return 1; } /* common */ @@ -844,12 +843,8 @@ static void *qpa_audio_init(Audiodev *dev, Error **errp) } } - if (!qpa_validate_per_direction_opts(dev, popts->in)) { - return NULL; - } - if (!qpa_validate_per_direction_opts(dev, popts->out)) { - return NULL; - } + qpa_validate_per_direction_opts(dev, popts->in); + qpa_validate_per_direction_opts(dev, popts->out); g = g_new0(paaudio, 1); server = popts->server; @@ -927,7 +922,6 @@ static struct audio_pcm_ops qpa_pcm_ops = { static struct audio_driver pa_audio_driver = { .name = "pa", - .descr = "http://www.pulseaudio.org/", .init = qpa_audio_init, .fini = qpa_audio_fini, .pcm_ops = &qpa_pcm_ops, diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 8e13b58286..30f717ccac 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -10,7 +10,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #include "qemu/error-report.h" #include "qapi/error.h" #include @@ -324,7 +324,7 @@ done_unlock: } static int -audfmt_to_pw(AudioFormat fmt, int endianness) +audfmt_to_pw(AudioFormat fmt, bool big_endian) { int format; @@ -336,19 +336,19 @@ audfmt_to_pw(AudioFormat fmt, int endianness) format = SPA_AUDIO_FORMAT_U8; break; case AUDIO_FORMAT_S16: - format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE; + format = big_endian ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE; break; case AUDIO_FORMAT_U16: - format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE; + format = big_endian ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE; break; case AUDIO_FORMAT_S32: - format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE; + format = big_endian ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE; break; case AUDIO_FORMAT_U32: - format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE; + format = big_endian ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE; break; case AUDIO_FORMAT_F32: - format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE; + format = big_endian ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE; break; default: dolog("Internal logic error: Bad audio format %d\n", fmt); @@ -838,7 +838,6 @@ static struct audio_pcm_ops qpw_pcm_ops = { static struct audio_driver pw_audio_driver = { .name = "pipewire", - .descr = "http://www.pipewire.org/", .init = qpw_audio_init, .fini = qpw_audio_fini, .pcm_ops = &qpw_pcm_ops, diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 641357e5ee..707110973a 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -27,7 +27,7 @@ #include #include "qemu/module.h" #include "qapi/error.h" -#include "audio.h" +#include "qemu/audio.h" #ifndef _WIN32 #ifdef __sun__ @@ -338,9 +338,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, { SDLVoiceOut *sdl = (SDLVoiceOut *)hw; SDL_AudioSpec req, obt; - int endianness; int err; - AudioFormat effective_fmt; Audiodev *dev = drv_opaque; AudiodevSdlPerDirectionOptions *spdo = dev->u.sdl.out; struct audsettings obt_as; @@ -360,7 +358,7 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, return -1; } - err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness); + err = sdl_to_audfmt(obt.format, &obt_as.fmt, &obt_as.endianness); if (err) { sdl_close_out(sdl); return -1; @@ -368,8 +366,6 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, obt_as.freq = obt.freq; obt_as.nchannels = obt.channels; - obt_as.fmt = effective_fmt; - obt_as.endianness = endianness; audio_pcm_init_info (&hw->info, &obt_as); hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) * @@ -398,9 +394,7 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque) { SDLVoiceIn *sdl = (SDLVoiceIn *)hw; SDL_AudioSpec req, obt; - int endianness; int err; - AudioFormat effective_fmt; Audiodev *dev = drv_opaque; AudiodevSdlPerDirectionOptions *spdo = dev->u.sdl.in; struct audsettings obt_as; @@ -420,7 +414,7 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque) return -1; } - err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness); + err = sdl_to_audfmt(obt.format, &obt_as.fmt, &obt_as.endianness); if (err) { sdl_close_in(sdl); return -1; @@ -428,8 +422,6 @@ static int sdl_init_in(HWVoiceIn *hw, audsettings *as, void *drv_opaque) obt_as.freq = obt.freq; obt_as.nchannels = obt.channels; - obt_as.fmt = effective_fmt; - obt_as.endianness = endianness; audio_pcm_init_info(&hw->info, &obt_as); hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) * @@ -490,7 +482,6 @@ static struct audio_pcm_ops sdl_pcm_ops = { static struct audio_driver sdl_audio_driver = { .name = "sdl", - .descr = "SDL http://www.libsdl.org", .init = sdl_audio_init, .fini = sdl_audio_fini, .pcm_ops = &sdl_pcm_ops, diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 8eb35e1e53..8197b8b0b4 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -18,7 +18,7 @@ #include #include #include "qemu/main-loop.h" -#include "audio.h" +#include "qemu/audio.h" #include "trace.h" #define AUDIO_CAP "sndio" @@ -546,7 +546,6 @@ static struct audio_pcm_ops sndio_pcm_ops = { static struct audio_driver sndio_audio_driver = { .name = "sndio", - .descr = "sndio https://sndio.org", .init = sndio_audio_init, .fini = sndio_audio_fini, .pcm_ops = &sndio_pcm_ops, diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 7f02f7285c..7db2d1f0df 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -26,7 +26,7 @@ #include "ui/qemu-spice.h" #define AUDIO_CAP "spice" -#include "audio.h" +#include "qemu/audio.h" #include "audio_int.h" #if SPICE_INTERFACE_PLAYBACK_MAJOR > 1 || SPICE_INTERFACE_PLAYBACK_MINOR >= 3 @@ -102,7 +102,7 @@ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, #endif settings.nchannels = SPICE_INTERFACE_PLAYBACK_CHAN; settings.fmt = AUDIO_FORMAT_S16; - settings.endianness = AUDIO_HOST_ENDIANNESS; + settings.endianness = HOST_BIG_ENDIAN; audio_pcm_init_info (&hw->info, &settings); hw->samples = LINE_OUT_SAMPLES; @@ -218,7 +218,7 @@ static int line_in_init(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) #endif settings.nchannels = SPICE_INTERFACE_RECORD_CHAN; settings.fmt = AUDIO_FORMAT_S16; - settings.endianness = AUDIO_HOST_ENDIANNESS; + settings.endianness = HOST_BIG_ENDIAN; audio_pcm_init_info (&hw->info, &settings); hw->samples = LINE_IN_SAMPLES; @@ -316,7 +316,6 @@ static struct audio_pcm_ops audio_callbacks = { static struct audio_driver spice_audio_driver = { .name = "spice", - .descr = "spice audio driver", .init = spice_audio_init, .fini = spice_audio_fini, .pcm_ops = &audio_callbacks, diff --git a/audio/wavaudio.c b/audio/wavaudio.c index a8798a1c42..46460a5d57 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -23,11 +23,8 @@ */ #include "qemu/osdep.h" -#include "qemu/host-utils.h" #include "qemu/module.h" -#include "qemu/timer.h" -#include "qapi/opts-visitor.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "wav" #include "audio_int.h" @@ -208,7 +205,6 @@ static struct audio_pcm_ops wav_pcm_ops = { static struct audio_driver wav_audio_driver = { .name = "wav", - .descr = "WAV renderer http://wikipedia.org/wiki/WAV", .init = wav_audio_init, .fini = wav_audio_fini, .pcm_ops = &wav_pcm_ops, diff --git a/audio/wavcapture.c b/audio/wavcapture.c index c60286e162..b33a38ff45 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,8 +1,7 @@ #include "qemu/osdep.h" #include "qemu/qemu-print.h" -#include "qapi/error.h" #include "qemu/error-report.h" -#include "audio.h" +#include "audio_int.h" typedef struct { FILE *f; @@ -104,7 +103,7 @@ static struct capture_ops wav_capture_ops = { .info = wav_capture_info }; -int wav_start_capture(AudioState *state, CaptureState *s, const char *path, +int wav_start_capture(AudioBackend *state, CaptureState *s, const char *path, int freq, int bits, int nchannels) { WAVState *wav; diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index ca6b3769b5..4ee98d6646 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -169,6 +169,26 @@ Use ``job-finalize`` instead. This argument has always been ignored. +Human Machine Protocol (HMP) commands +------------------------------------- + +``wavcapture`` (since 10.2) +'''''''''''''''''''''''''''' + +The ``wavcapture`` command is deprecated and will be removed in a future release. + +Use ``-audiodev wav`` or your host audio system to capture audio. + +``stopcapture`` (since 10.2) +'''''''''''''''''''''''''''' + +The ``stopcapture`` command is deprecated and will be removed in a future release. + +``info`` argument ``capture`` (since 10.2) +'''''''''''''''''''''''''''''''''''''''''' + +The ``info capture`` command is deprecated and will be removed in a future release. + Host Architectures ------------------ diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 2a7f5810d7..41674dcbe1 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -363,18 +363,20 @@ SRST Show host USB devices. ERST +/* BEGIN deprecated */ { .name = "capture", .args_type = "", .params = "", - .help = "show capture information", + .help = "show capture information (deprecated)", .cmd = hmp_info_capture, }, SRST ``info capture`` - Show capture information. + Show capture information (deprecated). ERST +/* END deprecated */ { .name = "snapshots", diff --git a/hmp-commands.hx b/hmp-commands.hx index 15f6082596..5cc4788f12 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -764,11 +764,12 @@ SRST ERST +/* BEGIN deprecated */ { .name = "wavcapture", .args_type = "path:F,audiodev:s,freq:i?,bits:i?,nchannels:i?", .params = "path audiodev [frequency [bits [channels]]]", - .help = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)", + .help = "capture audio to a wave file (deprecated, default frequency=44100 bits=16 channels=2)", .cmd = hmp_wavcapture, }, SRST @@ -782,13 +783,15 @@ SRST - Sample rate = 44100 Hz - CD quality - Bits = 16 - Number of channels = 2 - Stereo + + Deprecated. ERST { .name = "stopcapture", .args_type = "n:i", .params = "capture index", - .help = "stop capture", + .help = "stop capture (deprecated)", .cmd = hmp_stopcapture, }, SRST @@ -797,7 +800,9 @@ SRST info capture + Deprecated. ERST +/* END deprecated */ { .name = "memsave", diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index 031380aada..b030710b29 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -27,7 +27,7 @@ #include "hw/irq.h" #include "hw/sd/sd.h" #include "qom/object.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "target/arm/cpu-qom.h" #define TYPE_INTEGRATOR_CM "integrator_core" diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 1ae7cbd95c..675707691c 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -37,7 +37,7 @@ #include "qemu/cutils.h" #include "qom/object.h" #include "hw/net/mv88w8618_eth.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qemu/error-report.h" #include "target/arm/cpu-qom.h" diff --git a/hw/arm/realview.c b/hw/arm/realview.c index b940cbf2c1..d8327a50d2 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -30,7 +30,7 @@ #include "hw/irq.h" #include "hw/i2c/arm_sbcon_i2c.h" #include "hw/sd/sd.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "target/arm/cpu-qom.h" #define SMP_BOOT_ADDR 0xe0000000 diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 6fc1e62789..c3c99a2da6 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -26,7 +26,7 @@ #include "hw/char/pl011.h" #include "hw/sd/sd.h" #include "qom/object.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "target/arm/cpu-qom.h" #include "qemu/log.h" diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index f30923a658..3492e03a65 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -45,7 +45,7 @@ #include "hw/sd/sd.h" #include "qobject/qlist.h" #include "qom/object.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "target/arm/cpu-qom.h" #define VEXPRESS_BOARD_ID 0x8e0 diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c index 330f375f63..06a3d7dfe7 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -26,7 +26,7 @@ #include "system/device_tree.h" #include "qom/object.h" #include "net/can_emu.h" -#include "audio/audio.h" +#include "qemu/audio.h" struct XlnxZCU102 { MachineState parent_obj; diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 828333b66a..be7a39377f 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -18,8 +18,8 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/pci/pci_device.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -120,7 +120,7 @@ typedef struct AC97BusMasterRegs { struct AC97LinkState { PCIDevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; uint32_t glob_cnt; uint32_t glob_sta; uint32_t cas; @@ -320,7 +320,7 @@ static void open_voice(AC97LinkState *s, int index, int freq) switch (index) { case PI_INDEX: s->voice_pi = AUD_open_in( - &s->card, + s->audio_be, s->voice_pi, "ac97.pi", s, @@ -331,7 +331,7 @@ static void open_voice(AC97LinkState *s, int index, int freq) case PO_INDEX: s->voice_po = AUD_open_out( - &s->card, + s->audio_be, s->voice_po, "ac97.po", s, @@ -342,7 +342,7 @@ static void open_voice(AC97LinkState *s, int index, int freq) case MC_INDEX: s->voice_mc = AUD_open_in( - &s->card, + s->audio_be, s->voice_mc, "ac97.mc", s, @@ -355,17 +355,17 @@ static void open_voice(AC97LinkState *s, int index, int freq) s->invalid_freq[index] = freq; switch (index) { case PI_INDEX: - AUD_close_in(&s->card, s->voice_pi); + AUD_close_in(s->audio_be, s->voice_pi); s->voice_pi = NULL; break; case PO_INDEX: - AUD_close_out(&s->card, s->voice_po); + AUD_close_out(s->audio_be, s->voice_po); s->voice_po = NULL; break; case MC_INDEX: - AUD_close_in(&s->card, s->voice_mc); + AUD_close_in(s->audio_be, s->voice_mc); s->voice_mc = NULL; break; } @@ -416,7 +416,7 @@ static void update_combined_volume_out(AC97LinkState *s) lvol = (lvol * plvol) / 255; rvol = (rvol * prvol) / 255; - AUD_set_volume_out(s->voice_po, mute, lvol, rvol); + AUD_set_volume_out_lr(s->voice_po, mute, lvol, rvol); } static void update_volume_in(AC97LinkState *s) @@ -427,7 +427,7 @@ static void update_volume_in(AC97LinkState *s) get_volume(mixer_load(s, AC97_Record_Gain_Mute), 0x0f, 0, &mute, &lvol, &rvol); - AUD_set_volume_in(s->voice_pi, mute, lvol, rvol); + AUD_set_volume_in_lr(s->voice_pi, mute, lvol, rvol); } static void set_volume(AC97LinkState *s, int index, uint32_t val) @@ -1275,7 +1275,7 @@ static void ac97_realize(PCIDevice *dev, Error **errp) AC97LinkState *s = AC97(dev); uint8_t *c = s->dev.config; - if (!AUD_register_card ("ac97", &s->card, errp)) { + if (!AUD_backend_check (&s->audio_be, errp)) { return; } @@ -1320,14 +1320,13 @@ static void ac97_exit(PCIDevice *dev) { AC97LinkState *s = AC97(dev); - AUD_close_in(&s->card, s->voice_pi); - AUD_close_out(&s->card, s->voice_po); - AUD_close_in(&s->card, s->voice_mc); - AUD_remove_card(&s->card); + AUD_close_in(s->audio_be, s->voice_pi); + AUD_close_out(s->audio_be, s->voice_po); + AUD_close_in(s->audio_be, s->voice_mc); } static const Property ac97_properties[] = { - DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), + DEFINE_AUDIO_PROPERTIES(AC97LinkState, audio_be), }; static void ac97_class_init(ObjectClass *klass, const void *data) @@ -1362,8 +1361,7 @@ static const TypeInfo ac97_info = { static void ac97_register_types(void) { type_register_static(&ac97_info); - deprecated_register_soundhw("ac97", "Intel 82801AA AC97 Audio", - 0, TYPE_AC97); + audio_register_model("ac97", "Intel 82801AA AC97 Audio", TYPE_AC97); } type_init(ac97_register_types) diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 772435f04c..19d3a5f128 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -25,8 +25,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" @@ -57,7 +57,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AdlibState, ADLIB) struct AdlibState { ISADevice parent_obj; - QEMUSoundCard card; + AudioBackend *audio_be; uint32_t freq; uint32_t port; int ticking[2]; @@ -240,7 +240,6 @@ static void Adlib_fini (AdlibState *s) s->active = 0; s->enabled = 0; - AUD_remove_card (&s->card); } static MemoryRegionPortio adlib_portio_list[] = { @@ -255,7 +254,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) AdlibState *s = ADLIB(dev); struct audsettings as; - if (!AUD_register_card ("adlib", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -272,10 +271,10 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) as.freq = s->freq; as.nchannels = SHIFT; as.fmt = AUDIO_FORMAT_S16; - as.endianness = AUDIO_HOST_ENDIANNESS; + as.endianness = HOST_BIG_ENDIAN; s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "adlib", s, @@ -298,7 +297,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) } static const Property adlib_properties[] = { - DEFINE_AUDIO_PROPERTIES(AdlibState, card), + DEFINE_AUDIO_PROPERTIES(AdlibState, audio_be), DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220), DEFINE_PROP_UINT32 ("freq", AdlibState, freq, 44100), }; @@ -323,7 +322,7 @@ static const TypeInfo adlib_info = { static void adlib_register_types (void) { type_register_static (&adlib_info); - deprecated_register_soundhw("adlib", ADLIB_DESC, 1, TYPE_ADLIB); + audio_register_model("adlib", ADLIB_DESC, TYPE_ADLIB); } type_init (adlib_register_types) diff --git a/hw/audio/asc.c b/hw/audio/asc.c index edd42d6d91..0abb106979 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -15,7 +15,7 @@ #include "qapi/error.h" #include "hw/sysbus.h" #include "hw/irq.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/audio/asc.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -489,7 +489,7 @@ static void asc_write(void *opaque, hwaddr addr, uint64_t value, { int vol = (value & 0xe0); - AUD_set_volume_out(s->voice, 0, vol, vol); + AUD_set_volume_out_lr(s->voice, 0, vol, vol); break; } } @@ -634,8 +634,6 @@ static void asc_unrealize(DeviceState *dev) g_free(s->mixbuf); g_free(s->silentbuf); - - AUD_remove_card(&s->card); } static void asc_realize(DeviceState *dev, Error **errp) @@ -643,19 +641,18 @@ static void asc_realize(DeviceState *dev, Error **errp) ASCState *s = ASC(dev); struct audsettings as; - if (!AUD_register_card("Apple Sound Chip", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } as.freq = ASC_FREQ; as.nchannels = 2; as.fmt = AUDIO_FORMAT_U8; - as.endianness = AUDIO_HOST_ENDIANNESS; + as.endianness = HOST_BIG_ENDIAN; - s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb, + s->voice = AUD_open_out(s->audio_be, s->voice, "asc.out", s, asc_out_cb, &as); if (!s->voice) { - AUD_remove_card(&s->card); error_setg(errp, "Initializing audio stream failed"); return; } @@ -702,7 +699,7 @@ static void asc_init(Object *obj) } static const Property asc_properties[] = { - DEFINE_AUDIO_PROPERTIES(ASCState, card), + DEFINE_AUDIO_PROPERTIES(ASCState, audio_be), DEFINE_PROP_UINT8("asctype", ASCState, type, ASC_TYPE_ASC), }; diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 7931fcfec8..98fdbc5b72 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -23,8 +23,8 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -69,7 +69,7 @@ DECLARE_INSTANCE_CHECKER(CSState, CS4231A, struct CSState { ISADevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; MemoryRegion ioports; qemu_irq pic; uint32_t regs[CS_REGS]; @@ -305,7 +305,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) s->tab = ALawDecompressTable; x_law: as.fmt = AUDIO_FORMAT_S16; - as.endianness = AUDIO_HOST_ENDIANNESS; + as.endianness = HOST_BIG_ENDIAN; s->shift = as.nchannels == 2; break; @@ -328,7 +328,7 @@ static void cs_reset_voices (CSState *s, uint32_t val) } s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "cs4231a", s, @@ -678,7 +678,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) return; } - if (!AUD_register_card ("cs4231a", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -694,7 +694,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) } static const Property cs4231a_properties[] = { - DEFINE_AUDIO_PROPERTIES(CSState, card), + DEFINE_AUDIO_PROPERTIES(CSState, audio_be), DEFINE_PROP_UINT32 ("iobase", CSState, port, 0x534), DEFINE_PROP_UINT32 ("irq", CSState, irq, 9), DEFINE_PROP_UINT32 ("dma", CSState, dma, 3), @@ -723,7 +723,7 @@ static const TypeInfo cs4231a_info = { static void cs4231a_register_types (void) { type_register_static (&cs4231a_info); - deprecated_register_soundhw("cs4231a", "CS4231A", 1, TYPE_CS4231A); + audio_register_model("cs4231a", "CS4231A", TYPE_CS4231A); } type_init (cs4231a_register_types) diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 6b0da0746e..9873ffadab 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -26,8 +26,8 @@ #define VERBOSE_ES1370 0 #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/pci/pci_device.h" #include "migration/vmstate.h" #include "qemu/cutils.h" @@ -258,7 +258,7 @@ struct chan { struct ES1370State { PCIDevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; MemoryRegion io; struct chan chan[NB_CHANNELS]; SWVoiceOut *dac_voice[2]; @@ -330,10 +330,10 @@ static void es1370_reset (ES1370State *s) d->scount = 0; d->leftover = 0; if (i == ADC_CHANNEL) { - AUD_close_in (&s->card, s->adc_voice); + AUD_close_in(s->audio_be, s->adc_voice); s->adc_voice = NULL; } else { - AUD_close_out (&s->card, s->dac_voice[i]); + AUD_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] = NULL; } } @@ -412,7 +412,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl) if (i == ADC_CHANNEL) { s->adc_voice = AUD_open_in ( - &s->card, + s->audio_be, s->adc_voice, "es1370.adc", s, @@ -422,7 +422,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl) } else { s->dac_voice[i] = AUD_open_out ( - &s->card, + s->audio_be, s->dac_voice[i], i ? "es1370.dac2" : "es1370.dac1", s, @@ -784,12 +784,12 @@ static int es1370_post_load (void *opaque, int version_id) for (i = 0; i < NB_CHANNELS; ++i) { if (i == ADC_CHANNEL) { if (s->adc_voice) { - AUD_close_in (&s->card, s->adc_voice); + AUD_close_in(s->audio_be, s->adc_voice); s->adc_voice = NULL; } } else { if (s->dac_voice[i]) { - AUD_close_out (&s->card, s->dac_voice[i]); + AUD_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] = NULL; } } @@ -833,7 +833,7 @@ static void es1370_realize(PCIDevice *dev, Error **errp) ES1370State *s = ES1370(dev); uint8_t *c = s->dev.config; - if (!AUD_register_card ("es1370", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -861,15 +861,14 @@ static void es1370_exit(PCIDevice *dev) int i; for (i = 0; i < 2; ++i) { - AUD_close_out(&s->card, s->dac_voice[i]); + AUD_close_out(s->audio_be, s->dac_voice[i]); } - AUD_close_in(&s->card, s->adc_voice); - AUD_remove_card(&s->card); + AUD_close_in(s->audio_be, s->adc_voice); } static const Property es1370_properties[] = { - DEFINE_AUDIO_PROPERTIES(ES1370State, card), + DEFINE_AUDIO_PROPERTIES(ES1370State, audio_be), }; static void es1370_class_init(ObjectClass *klass, const void *data) @@ -905,8 +904,7 @@ static const TypeInfo es1370_info = { static void es1370_register_types (void) { type_register_static (&es1370_info); - deprecated_register_soundhw("es1370", "ENSONIQ AudioPCI ES1370", - 0, TYPE_ES1370); + audio_register_model("es1370", "ENSONIQ AudioPCI ES1370", TYPE_ES1370); } type_init (es1370_register_types) diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 91d07e0f81..68f89e994c 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -25,8 +25,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -49,7 +49,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(GUSState, GUS) struct GUSState { ISADevice dev; GUSEmuState emu; - QEMUSoundCard card; + AudioBackend *audio_be; uint32_t freq; uint32_t port; int pos, left, shift, irqs; @@ -242,7 +242,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp) IsaDmaClass *k; struct audsettings as; - if (!AUD_register_card ("gus", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -255,10 +255,10 @@ static void gus_realizefn (DeviceState *dev, Error **errp) as.freq = s->freq; as.nchannels = 2; as.fmt = AUDIO_FORMAT_S16; - as.endianness = AUDIO_HOST_ENDIANNESS; + as.endianness = HOST_BIG_ENDIAN; s->voice = AUD_open_out ( - &s->card, + s->audio_be, NULL, "gus", s, @@ -267,7 +267,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp) ); if (!s->voice) { - AUD_remove_card (&s->card); error_setg(errp, "No voice"); return; } @@ -292,7 +291,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp) } static const Property gus_properties[] = { - DEFINE_AUDIO_PROPERTIES(GUSState, card), + DEFINE_AUDIO_PROPERTIES(GUSState, audio_be), DEFINE_PROP_UINT32 ("freq", GUSState, freq, 44100), DEFINE_PROP_UINT32 ("iobase", GUSState, port, 0x240), DEFINE_PROP_UINT32 ("irq", GUSState, emu.gusirq, 7), @@ -320,7 +319,7 @@ static const TypeInfo gus_info = { static void gus_register_types (void) { type_register_static (&gus_info); - deprecated_register_soundhw("gus", "Gravis Ultrasound GF1", 1, TYPE_GUS); + audio_register_model("gus", "Gravis Ultrasound GF1", TYPE_GUS); } type_init (gus_register_types) diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index 66edad280f..e90c9de046 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -25,7 +25,7 @@ #include "qemu/host-utils.h" #include "qemu/module.h" #include "intel-hda-defs.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "trace.h" #include "qom/object.h" @@ -178,7 +178,7 @@ struct HDAAudioState { HDACodecDevice hda; const char *name; - QEMUSoundCard card; + AudioBackend *audio_be; const desc_codec *desc; HDAAudioStream st[4]; bool running_compat[16]; @@ -466,9 +466,9 @@ static void hda_audio_set_amp(HDAAudioStream *st) return; } if (st->output) { - AUD_set_volume_out(st->voice.out, muted, left, right); + AUD_set_volume_out_lr(st->voice.out, muted, left, right); } else { - AUD_set_volume_in(st->voice.in, muted, left, right); + AUD_set_volume_in_lr(st->voice.in, muted, left, right); } } @@ -491,7 +491,7 @@ static void hda_audio_setup(HDAAudioStream *st) } else { cb = hda_audio_compat_output_cb; } - st->voice.out = AUD_open_out(&st->state->card, st->voice.out, + st->voice.out = AUD_open_out(st->state->audio_be, st->voice.out, st->node->name, st, cb, &st->as); } else { if (use_timer) { @@ -500,7 +500,7 @@ static void hda_audio_setup(HDAAudioStream *st) } else { cb = hda_audio_compat_input_cb; } - st->voice.in = AUD_open_in(&st->state->card, st->voice.in, + st->voice.in = AUD_open_in(st->state->audio_be, st->voice.in, st->node->name, st, cb, &st->as); } } @@ -696,7 +696,7 @@ static void hda_audio_init(HDACodecDevice *hda, const desc_param *param; uint32_t i, type; - if (!AUD_register_card("hda", &a->card, errp)) { + if (!AUD_backend_check(&a->audio_be, errp)) { return; } @@ -754,12 +754,11 @@ static void hda_audio_exit(HDACodecDevice *hda) } timer_free(st->buft); if (st->output) { - AUD_close_out(&a->card, st->voice.out); + AUD_close_out(a->audio_be, st->voice.out); } else { - AUD_close_in(&a->card, st->voice.in); + AUD_close_in(a->audio_be, st->voice.in); } } - AUD_remove_card(&a->card); } static int hda_audio_post_load(void *opaque, int version) @@ -858,7 +857,7 @@ static const VMStateDescription vmstate_hda_audio = { }; static const Property hda_audio_properties[] = { - DEFINE_AUDIO_PROPERTIES(HDAAudioState, card), + DEFINE_AUDIO_PROPERTIES(HDAAudioState, audio_be), DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true), DEFINE_PROP_BOOL("use-timer", HDAAudioState, use_timer, true), diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index b256c8ccea..758e130c93 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -21,16 +21,16 @@ #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "hw/pci/msi.h" +#include "monitor/qdev.h" #include "qemu/timer.h" #include "qemu/bitops.h" #include "qemu/log.h" #include "qemu/module.h" -#include "qemu/error-report.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "intel-hda.h" #include "migration/vmstate.h" #include "intel-hda-defs.h" -#include "system/dma.h" +#include "qobject/qdict.h" #include "qapi/error.h" #include "qom/object.h" @@ -1303,18 +1303,20 @@ static const TypeInfo hda_codec_device_type_info = { * create intel hda controller with codec attached to it, * so '-soundhw hda' works. */ -static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev) +static void intel_hda_and_codec_init(const char *audiodev) { - DeviceState *controller; + g_autoptr(QDict) props = qdict_new(); + DeviceState *intel_hda, *codec; BusState *hdabus; - DeviceState *codec; - controller = DEVICE(pci_create_simple(bus, -1, "intel-hda")); - hdabus = QLIST_FIRST(&controller->child_bus); + qdict_put_str(props, "driver", "intel-hda"); + intel_hda = qdev_device_add_from_qdict(props, false, &error_fatal); + hdabus = QLIST_FIRST(&intel_hda->child_bus); + codec = qdev_new("hda-duplex"); qdev_prop_set_string(codec, "audiodev", audiodev); qdev_realize_and_unref(codec, hdabus, &error_fatal); - return 0; + object_unref(intel_hda); } static void intel_hda_register_types(void) @@ -1324,7 +1326,7 @@ static void intel_hda_register_types(void) type_register_static(&intel_hda_info_ich6); type_register_static(&intel_hda_info_ich9); type_register_static(&hda_codec_device_type_info); - pci_register_soundhw("hda", "Intel HD Audio", intel_hda_and_codec_init); + audio_register_model_with_cb("hda", "Intel HD Audio", intel_hda_and_codec_init); } type_init(intel_hda_register_types) diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index a4a77c8dc6..745441bd79 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -15,7 +15,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "lm4549.h" #include "migration/vmstate.h" @@ -190,7 +190,7 @@ void lm4549_write(lm4549_state *s, as.endianness = 0; s->voice = AUD_open_out( - &s->card, + s->audio_be, s->voice, "lm4549.out", s, @@ -260,7 +260,7 @@ static int lm4549_post_load(void *opaque, int version_id) as.endianness = 0; s->voice = AUD_open_out( - &s->card, + s->audio_be, s->voice, "lm4549.out", s, @@ -282,7 +282,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque, struct audsettings as; /* Register an audio card */ - if (!AUD_register_card("lm4549", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -300,7 +300,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque, as.endianness = 0; s->voice = AUD_open_out( - &s->card, + s->audio_be, s->voice, "lm4549.out", s, @@ -308,7 +308,7 @@ void lm4549_init(lm4549_state *s, lm4549_callback data_req_cb, void* opaque, &as ); - AUD_set_volume_out(s->voice, 0, 255, 255); + AUD_set_volume_out_lr(s->voice, 0, 255, 255); s->voice_is_active = 0; diff --git a/hw/audio/lm4549.h b/hw/audio/lm4549.h index 61c3ab12dd..bbd73057bf 100644 --- a/hw/audio/lm4549.h +++ b/hw/audio/lm4549.h @@ -12,7 +12,7 @@ #ifndef HW_LM4549_H #define HW_LM4549_H -#include "audio/audio.h" +#include "qemu/audio.h" #include "exec/hwaddr.h" typedef void (*lm4549_callback)(void *opaque); @@ -21,7 +21,7 @@ typedef void (*lm4549_callback)(void *opaque); typedef struct { - QEMUSoundCard card; + AudioBackend *audio_be; SWVoiceOut *voice; uint32_t voice_is_active; diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index c5c79d083a..a483f4e70d 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -16,7 +16,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/audio/wm8750.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qapi/error.h" #include "qemu/module.h" #include "qom/object.h" diff --git a/hw/audio/meson.build b/hw/audio/meson.build index 2990974449..2154cbdb57 100644 --- a/hw/audio/meson.build +++ b/hw/audio/meson.build @@ -1,4 +1,4 @@ -system_ss.add(files('soundhw.c')) +system_ss.add(files('model.c')) system_ss.add(when: 'CONFIG_AC97', if_true: files('ac97.c')) system_ss.add(when: 'CONFIG_ADLIB', if_true: files('fmopl.c', 'adlib.c')) system_ss.add(when: 'CONFIG_ASC', if_true: files('asc.c')) diff --git a/hw/audio/soundhw.c b/hw/audio/model.c similarity index 54% rename from hw/audio/soundhw.c rename to hw/audio/model.c index 63a6855635..40929c6e77 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/model.c @@ -22,56 +22,50 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "qemu/option.h" -#include "qemu/help_option.h" +#include "hw/qdev-core.h" +#include "monitor/qdev.h" #include "qemu/error-report.h" #include "qapi/error.h" -#include "qom/object.h" #include "hw/qdev-properties.h" -#include "hw/isa/isa.h" -#include "hw/pci/pci.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" -struct soundhw { +struct audio_model { const char *name; const char *descr; const char *typename; - int isa; - int (*init_pci) (PCIBus *bus, const char *audiodev); + void (*init)(const char *audiodev); }; -static struct soundhw soundhw[9]; -static int soundhw_count; +static struct audio_model audio_models[9]; +static int audio_models_count; -void pci_register_soundhw(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus, const char *audiodev)) +void audio_register_model_with_cb(const char *name, const char *descr, + void (*init_audio_model)(const char *audiodev)) { - assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); - soundhw[soundhw_count].name = name; - soundhw[soundhw_count].descr = descr; - soundhw[soundhw_count].isa = 0; - soundhw[soundhw_count].init_pci = init_pci; - soundhw_count++; + assert(audio_models_count < ARRAY_SIZE(audio_models) - 1); + audio_models[audio_models_count].name = name; + audio_models[audio_models_count].descr = descr; + audio_models[audio_models_count].init = init_audio_model; + audio_models_count++; } -void deprecated_register_soundhw(const char *name, const char *descr, - int isa, const char *typename) +void audio_register_model(const char *name, const char *descr, + const char *typename) { - assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); - soundhw[soundhw_count].name = name; - soundhw[soundhw_count].descr = descr; - soundhw[soundhw_count].isa = isa; - soundhw[soundhw_count].typename = typename; - soundhw_count++; + assert(audio_models_count < ARRAY_SIZE(audio_models) - 1); + audio_models[audio_models_count].name = name; + audio_models[audio_models_count].descr = descr; + audio_models[audio_models_count].typename = typename; + audio_models_count++; } void audio_print_available_models(void) { - struct soundhw *c; + struct audio_model *c; - if (soundhw_count) { + if (audio_models_count) { printf("Valid audio device model names:\n"); - for (c = soundhw; c->name; ++c) { + for (c = audio_models; c->name; ++c) { printf("%-11s %s\n", c->name, c->descr); } } else { @@ -80,19 +74,19 @@ void audio_print_available_models(void) } } -static struct soundhw *selected = NULL; +static struct audio_model *selected; static const char *audiodev_id; -void select_soundhw(const char *name, const char *audiodev) +void audio_set_model(const char *name, const char *audiodev) { - struct soundhw *c; + struct audio_model *c; if (selected) { error_report("only one -audio option is allowed"); exit(1); } - for (c = soundhw; c->name; ++c) { + for (c = audio_models; c->name; ++c) { if (g_str_equal(c->name, name)) { selected = c; audiodev_id = audiodev; @@ -107,36 +101,20 @@ void select_soundhw(const char *name, const char *audiodev) } } -void soundhw_init(void) +void audio_model_init(void) { - struct soundhw *c = selected; - ISABus *isa_bus = (ISABus *) object_resolve_path_type("", TYPE_ISA_BUS, NULL); - PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); - BusState *bus; + struct audio_model *c = selected; if (!c) { return; } - if (c->isa) { - if (!isa_bus) { - error_report("ISA bus not available for %s", c->name); - exit(1); - } - bus = BUS(isa_bus); - } else { - if (!pci_bus) { - error_report("PCI bus not available for %s", c->name); - exit(1); - } - bus = BUS(pci_bus); - } if (c->typename) { DeviceState *dev = qdev_new(c->typename); + BusState *bus = qdev_find_default_bus(DEVICE_GET_CLASS(dev), &error_fatal); qdev_prop_set_string(dev, "audiodev", audiodev_id); qdev_realize_and_unref(dev, bus, &error_fatal); } else { - assert(!c->isa); - c->init_pci(pci_bus, audiodev_id); + c->init(audiodev_id); } } diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index a719912872..916c56fa4c 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -24,8 +24,8 @@ #include "qemu/osdep.h" #include "hw/isa/isa.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "qemu/module.h" #include "qemu/timer.h" #include "qemu/error-report.h" @@ -49,7 +49,7 @@ struct PCSpkState { MemoryRegion ioport; uint32_t iobase; uint8_t sample_buf[PCSPK_BUF_LEN]; - QEMUSoundCard card; + AudioBackend *audio_be; SWVoiceOut *voice; PITCommonState *pit; unsigned int pit_count; @@ -123,7 +123,7 @@ static int pcspk_audio_init(PCSpkState *s) return 0; } - s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as); + s->voice = AUD_open_out(s->audio_be, s->voice, s_spk, s, pcspk_callback, &as); if (!s->voice) { error_report("pcspk: Could not open voice"); return -1; @@ -196,8 +196,9 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) isa_register_ioport(isadev, &s->ioport, s->iobase); - if (s->card.state && AUD_register_card(s_spk, &s->card, errp)) { + if (s->audio_be && AUD_backend_check(&s->audio_be, errp)) { pcspk_audio_init(s); + return; } } @@ -221,7 +222,7 @@ static const VMStateDescription vmstate_spk = { }; static const Property pcspk_properties[] = { - DEFINE_AUDIO_PROPERTIES(PCSpkState, card), + DEFINE_AUDIO_PROPERTIES(PCSpkState, audio_be), DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, 0x61), DEFINE_PROP_BOOL("migrate", PCSpkState, migrate, true), DEFINE_PROP_LINK("pit", PCSpkState, pit, TYPE_PIT_COMMON, PITCommonState *), diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index 5d9d6c1178..fd3d09611f 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -626,7 +626,7 @@ static const VMStateDescription vmstate_pl041 = { }; static const Property pl041_device_properties[] = { - DEFINE_AUDIO_PROPERTIES(PL041State, codec.card), + DEFINE_AUDIO_PROPERTIES(PL041State, codec.audio_be), /* Non-compact FIFO depth property */ DEFINE_PROP_UINT32("nc_fifo_depth", PL041State, fifo_depth, DEFAULT_FIFO_DEPTH), diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 03c82f2777..1e3c4caf5e 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -23,8 +23,8 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -54,7 +54,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(SB16State, SB16) struct SB16State { ISADevice parent_obj; - QEMUSoundCard card; + AudioBackend *audio_be; qemu_irq pic; uint32_t irq; uint32_t dma; @@ -216,7 +216,7 @@ static void continue_dma8 (SB16State *s) as.endianness = 0; s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "sb16", s, @@ -379,7 +379,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) as.endianness = 0; s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "sb16", s, @@ -880,7 +880,7 @@ static void legacy_reset (SB16State *s) as.endianness = 0; s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "sb16", s, @@ -1287,7 +1287,7 @@ static int sb16_post_load (void *opaque, int version_id) SB16State *s = opaque; if (s->voice) { - AUD_close_out (&s->card, s->voice); + AUD_close_out(s->audio_be, s->voice); s->voice = NULL; } @@ -1303,7 +1303,7 @@ static int sb16_post_load (void *opaque, int version_id) as.endianness = 0; s->voice = AUD_open_out ( - &s->card, + s->audio_be, s->voice, "sb16", s, @@ -1401,7 +1401,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) SB16State *s = SB16 (dev); IsaDmaClass *k; - if (!AUD_register_card ("sb16", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -1440,7 +1440,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) } static const Property sb16_properties[] = { - DEFINE_AUDIO_PROPERTIES(SB16State, card), + DEFINE_AUDIO_PROPERTIES(SB16State, audio_be), DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */ DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220), DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5), @@ -1470,8 +1470,7 @@ static const TypeInfo sb16_info = { static void sb16_register_types (void) { type_register_static (&sb16_info); - deprecated_register_soundhw("sb16", "Creative Sound Blaster 16", - 1, TYPE_SB16); + audio_register_model("sb16", "Creative Sound Blaster 16", TYPE_SB16); } type_init (sb16_register_types) diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index d5231e1cf2..019d296853 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -53,7 +53,7 @@ static void codec_volume_set_out(ViaAC97State *s) rvol /= 255; mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT; mute |= CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT; - AUD_set_volume_out(s->vo, mute, lvol, rvol); + AUD_set_volume_out_lr(s->vo, mute, lvol, rvol); } static void codec_reset(ViaAC97State *s) @@ -239,7 +239,7 @@ static void open_voice_out(ViaAC97State *s) .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8, .endianness = 0, }; - s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as); + s->vo = AUD_open_out(s->audio_be, s->vo, "via-ac97.out", s, out_cb, &as); } static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size) @@ -426,7 +426,7 @@ static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) ViaAC97State *s = VIA_AC97(pci_dev); Object *o = OBJECT(s); - if (!AUD_register_card ("via-ac97", &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -455,12 +455,11 @@ static void via_ac97_exit(PCIDevice *dev) { ViaAC97State *s = VIA_AC97(dev); - AUD_close_out(&s->card, s->vo); - AUD_remove_card(&s->card); + AUD_close_out(s->audio_be, s->vo); } static const Property via_ac97_properties[] = { - DEFINE_AUDIO_PROPERTIES(ViaAC97State, card), + DEFINE_AUDIO_PROPERTIES(ViaAC97State, audio_be), }; static void via_ac97_class_init(ObjectClass *klass, const void *data) diff --git a/hw/audio/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c index 9eb0007392..230581ed63 100644 --- a/hw/audio/virtio-snd-pci.c +++ b/hw/audio/virtio-snd-pci.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "qom/object.h" #include "qapi/error.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "hw/virtio/virtio-pci.h" #include "hw/audio/virtio-snd.h" @@ -71,24 +71,10 @@ static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = { .class_init = virtio_snd_pci_class_init, }; -/* Create a Virtio Sound PCI device, so '-audio driver,model=virtio' works. */ -static int virtio_snd_pci_init(PCIBus *bus, const char *audiodev) -{ - DeviceState *vdev = NULL; - VirtIOSoundPCI *dev = NULL; - - vdev = qdev_new(TYPE_VIRTIO_SND_PCI); - assert(vdev); - dev = VIRTIO_SND_PCI(vdev); - qdev_prop_set_string(DEVICE(&dev->vdev), "audiodev", audiodev); - qdev_realize_and_unref(vdev, BUS(bus), &error_fatal); - return 0; -} - static void virtio_snd_pci_register(void) { virtio_pci_types_register(&virtio_snd_pci_info); - pci_register_soundhw("virtio", "Virtio Sound", virtio_snd_pci_init); + audio_register_model("virtio", "Virtio Sound", TYPE_VIRTIO_SND_PCI); } type_init(virtio_snd_pci_register); diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index eca3319e59..9101560f38 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -78,7 +78,7 @@ static const VMStateDescription vmstate_virtio_snd = { }; static const Property virtio_snd_properties[] = { - DEFINE_AUDIO_PROPERTIES(VirtIOSound, card), + DEFINE_AUDIO_PROPERTIES(VirtIOSound, audio_be), DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks, VIRTIO_SOUND_JACK_DEFAULT), DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams, @@ -391,10 +391,10 @@ static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) if (stream) { virtio_snd_pcm_flush(stream); if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { - AUD_close_out(&stream->pcm->snd->card, stream->voice.out); + AUD_close_out(stream->pcm->snd->audio_be, stream->voice.out); stream->voice.out = NULL; } else if (stream->info.direction == VIRTIO_SND_D_INPUT) { - AUD_close_in(&stream->pcm->snd->card, stream->voice.in); + AUD_close_in(stream->pcm->snd->audio_be, stream->voice.in); stream->voice.in = NULL; } } @@ -457,21 +457,21 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) stream->as = as; if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { - stream->voice.out = AUD_open_out(&s->card, + stream->voice.out = AUD_open_out(s->audio_be, stream->voice.out, "virtio-sound.out", stream, virtio_snd_pcm_out_cb, &as); - AUD_set_volume_out(stream->voice.out, 0, 255, 255); + AUD_set_volume_out_lr(stream->voice.out, 0, 255, 255); } else { - stream->voice.in = AUD_open_in(&s->card, + stream->voice.in = AUD_open_in(s->audio_be, stream->voice.in, "virtio-sound.in", stream, virtio_snd_pcm_in_cb, &as); - AUD_set_volume_in(stream->voice.in, 0, 255, 255); + AUD_set_volume_in_lr(stream->voice.in, 0, 255, 255); } return cpu_to_le32(VIRTIO_SND_S_OK); @@ -1053,7 +1053,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) return; } - if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) { + if (!AUD_backend_check(&vsnd->audio_be, errp)) { return; } @@ -1330,7 +1330,6 @@ static void virtio_snd_unrealize(DeviceState *dev) g_free(vsnd->pcm); vsnd->pcm = NULL; } - AUD_remove_card(&vsnd->card); qemu_mutex_destroy(&vsnd->cmdq_mutex); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]); diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 2846b55fe2..336fb6d20b 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -12,7 +12,7 @@ #include "migration/vmstate.h" #include "qemu/module.h" #include "hw/audio/wm8750.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qom/object.h" #define IN_PORT_N 3 @@ -34,7 +34,7 @@ struct WM8750State { uint8_t i2c_data[2]; int i2c_len; - QEMUSoundCard card; + AudioBackend *audio_be; SWVoiceIn *adc_voice[IN_PORT_N]; SWVoiceOut *dac_voice[OUT_PORT_N]; int enable; @@ -145,30 +145,30 @@ static void wm8750_vol_update(WM8750State *s) { /* FIXME: multiply all volumes by s->invol[2], s->invol[3] */ - AUD_set_volume_in(s->adc_voice[0], s->mute, + AUD_set_volume_in_lr(s->adc_voice[0], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])); - AUD_set_volume_in(s->adc_voice[1], s->mute, + AUD_set_volume_in_lr(s->adc_voice[1], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])); - AUD_set_volume_in(s->adc_voice[2], s->mute, + AUD_set_volume_in_lr(s->adc_voice[2], s->mute, s->inmute[0] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[0]), s->inmute[1] ? 0 : WM8750_INVOL_TRANSFORM(s->invol[1])); /* FIXME: multiply all volumes by s->outvol[0], s->outvol[1] */ /* Speaker: LOUT2VOL ROUT2VOL */ - AUD_set_volume_out(s->dac_voice[0], s->mute, + AUD_set_volume_out_lr(s->dac_voice[0], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[4]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[5])); /* Headphone: LOUT1VOL ROUT1VOL */ - AUD_set_volume_out(s->dac_voice[1], s->mute, + AUD_set_volume_out_lr(s->dac_voice[1], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[2]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[3])); /* MONOOUT: MONOVOL MONOVOL */ - AUD_set_volume_out(s->dac_voice[2], s->mute, + AUD_set_volume_out_lr(s->dac_voice[2], s->mute, s->outmute[0] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6]), s->outmute[1] ? 0 : WM8750_OUTVOL_TRANSFORM(s->outvol[6])); } @@ -188,12 +188,12 @@ static void wm8750_set_format(WM8750State *s) for (i = 0; i < IN_PORT_N; i ++) if (s->adc_voice[i]) { - AUD_close_in(&s->card, s->adc_voice[i]); + AUD_close_in(s->audio_be, s->adc_voice[i]); s->adc_voice[i] = NULL; } for (i = 0; i < OUT_PORT_N; i ++) if (s->dac_voice[i]) { - AUD_close_out(&s->card, s->dac_voice[i]); + AUD_close_out(s->audio_be, s->dac_voice[i]); s->dac_voice[i] = NULL; } @@ -206,11 +206,11 @@ static void wm8750_set_format(WM8750State *s) in_fmt.freq = s->adc_hz; in_fmt.fmt = AUDIO_FORMAT_S16; - s->adc_voice[0] = AUD_open_in(&s->card, s->adc_voice[0], + s->adc_voice[0] = AUD_open_in(s->audio_be, s->adc_voice[0], CODEC ".input1", s, wm8750_audio_in_cb, &in_fmt); - s->adc_voice[1] = AUD_open_in(&s->card, s->adc_voice[1], + s->adc_voice[1] = AUD_open_in(s->audio_be, s->adc_voice[1], CODEC ".input2", s, wm8750_audio_in_cb, &in_fmt); - s->adc_voice[2] = AUD_open_in(&s->card, s->adc_voice[2], + s->adc_voice[2] = AUD_open_in(s->audio_be, s->adc_voice[2], CODEC ".input3", s, wm8750_audio_in_cb, &in_fmt); /* Setup output */ @@ -219,12 +219,12 @@ static void wm8750_set_format(WM8750State *s) out_fmt.freq = s->dac_hz; out_fmt.fmt = AUDIO_FORMAT_S16; - s->dac_voice[0] = AUD_open_out(&s->card, s->dac_voice[0], + s->dac_voice[0] = AUD_open_out(s->audio_be, s->dac_voice[0], CODEC ".speaker", s, wm8750_audio_out_cb, &out_fmt); - s->dac_voice[1] = AUD_open_out(&s->card, s->dac_voice[1], + s->dac_voice[1] = AUD_open_out(s->audio_be, s->dac_voice[1], CODEC ".headphone", s, wm8750_audio_out_cb, &out_fmt); /* MONOMIX is also in stereo for simplicity */ - s->dac_voice[2] = AUD_open_out(&s->card, s->dac_voice[2], + s->dac_voice[2] = AUD_open_out(s->audio_be, s->dac_voice[2], CODEC ".monomix", s, wm8750_audio_out_cb, &out_fmt); /* no sense emulating OUT3 which is a mix of other outputs */ @@ -624,7 +624,7 @@ static void wm8750_realize(DeviceState *dev, Error **errp) { WM8750State *s = WM8750(dev); - if (!AUD_register_card(CODEC, &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -637,7 +637,6 @@ static void wm8750_fini(I2CSlave *i2c) WM8750State *s = WM8750(i2c); wm8750_reset(I2C_SLAVE(s)); - AUD_remove_card(&s->card); g_free(s); } #endif @@ -707,7 +706,7 @@ void wm8750_set_bclk_in(void *opaque, int new_hz) } static const Property wm8750_properties[] = { - DEFINE_AUDIO_PROPERTIES(WM8750State, card), + DEFINE_AUDIO_PROPERTIES(WM8750State, audio_be), }; static void wm8750_class_init(ObjectClass *klass, const void *data) diff --git a/hw/core/machine.c b/hw/core/machine.c index cd63803000..0580550e12 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -36,7 +36,7 @@ #include "hw/virtio/virtio-net.h" #include "hw/virtio/virtio-iommu.h" #include "hw/acpi/generic_event_device.h" -#include "audio/audio.h" +#include "qemu/audio.h" GlobalProperty hw_compat_10_1[] = { { TYPE_ACPI_GED, "x-has-hest-addr", "false" }, @@ -760,7 +760,7 @@ static void machine_set_audiodev(Object *obj, const char *value, { MachineState *ms = MACHINE(obj); - if (!audio_state_by_name(value, errp)) { + if (!audio_be_by_name(value, errp)) { return; } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 13cc91680b..7aa5cbb510 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -27,7 +27,7 @@ #include "qemu/error-report.h" #include "qdev-prop-internal.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "chardev/char-fe.h" #include "system/block-backend.h" #include "system/blockdev.h" @@ -487,28 +487,27 @@ static void get_audiodev(Object *obj, Visitor *v, const char* name, void *opaque, Error **errp) { const Property *prop = opaque; - QEMUSoundCard *card = object_field_prop_ptr(obj, prop); - char *p = g_strdup(audio_get_id(card)); + AudioBackend **be = object_field_prop_ptr(obj, prop); + g_autofree char *id = g_strdup(audio_be_get_id(*be)); - visit_type_str(v, name, &p, errp); - g_free(p); + visit_type_str(v, name, (char **)&id, errp); } static void set_audiodev(Object *obj, Visitor *v, const char* name, void *opaque, Error **errp) { const Property *prop = opaque; - QEMUSoundCard *card = object_field_prop_ptr(obj, prop); - AudioState *state; + AudioBackend **be = object_field_prop_ptr(obj, prop); + AudioBackend *state; g_autofree char *str = NULL; if (!visit_type_str(v, name, &str, errp)) { return; } - state = audio_state_by_name(str, errp); + state = audio_be_by_name(str, errp); if (state) { - card->state = state; + *be = state; } } diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index ef73e1815f..96cbb1b3a7 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -1306,7 +1306,7 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) DisplaySurface *surface; struct audsettings as; - if (!AUD_register_card("xlnx_dp.audio", &s->aud_card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -1328,13 +1328,13 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) as.fmt = AUDIO_FORMAT_S16; as.endianness = 0; - s->amixer_output_stream = AUD_open_out(&s->aud_card, + s->amixer_output_stream = AUD_open_out(s->audio_be, s->amixer_output_stream, "xlnx_dp.audio.out", s, xlnx_dp_audio_callback, &as); - AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255); + AUD_set_volume_out_lr(s->amixer_output_stream, 0, 255, 255); xlnx_dp_audio_activate(s); s->vblank = ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY); ptimer_transaction_begin(s->vblank); @@ -1392,7 +1392,7 @@ static void xlnx_dp_reset(DeviceState *dev) } static const Property xlnx_dp_device_properties[] = { - DEFINE_AUDIO_PROPERTIES(XlnxDPState, aud_card), + DEFINE_AUDIO_PROPERTIES(XlnxDPState, audio_be), }; static void xlnx_dp_class_init(ObjectClass *oc, const void *data) diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index c2fe16e985..5654a60c59 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -46,7 +46,7 @@ #include "trace.h" #include "elf.h" #include "qemu/units.h" -#include "audio/audio.h" +#include "qemu/audio.h" /* SMP is not enabled, for now */ #define MAX_CPUS 1 diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 26af709f31..8dd9d26599 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -35,7 +35,7 @@ #include "hw/usb.h" #include "migration/vmstate.h" #include "desc.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qom/object.h" static void usb_audio_reinit(USBDevice *dev, unsigned channels); @@ -635,7 +635,7 @@ static uint8_t *streambuf_get(struct streambuf *buf, size_t *len) struct USBAudioState { /* qemu interfaces */ USBDevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; /* state */ struct { @@ -805,7 +805,7 @@ static int usb_audio_set_control(USBAudioState *s, uint8_t attrib, } fprintf(stderr, "\n"); } - audio_set_volume_out(s->out.voice, &s->out.vol); + AUD_set_volume_out(s->out.voice, &s->out.vol); } return ret; @@ -931,8 +931,7 @@ static void usb_audio_unrealize(USBDevice *dev) } usb_audio_set_output_altset(s, ALTSET_OFF); - AUD_close_out(&s->card, s->out.voice); - AUD_remove_card(&s->card); + AUD_close_out(s->audio_be, s->out.voice); streambuf_fini(&s->out.buf); } @@ -942,7 +941,7 @@ static void usb_audio_realize(USBDevice *dev, Error **errp) USBAudioState *s = USB_AUDIO(dev); int i; - if (!AUD_register_card(TYPE_USB_AUDIO, &s->card, errp)) { + if (!AUD_backend_check(&s->audio_be, errp)) { return; } @@ -979,9 +978,9 @@ static void usb_audio_reinit(USBDevice *dev, unsigned channels) s->out.as.endianness = 0; streambuf_init(&s->out.buf, s->buffer, s->out.channels); - s->out.voice = AUD_open_out(&s->card, s->out.voice, TYPE_USB_AUDIO, + s->out.voice = AUD_open_out(s->audio_be, s->out.voice, TYPE_USB_AUDIO, s, output_callback, &s->out.as); - audio_set_volume_out(s->out.voice, &s->out.vol); + AUD_set_volume_out(s->out.voice, &s->out.vol); AUD_set_active_out(s->out.voice, 0); } @@ -991,7 +990,7 @@ static const VMStateDescription vmstate_usb_audio = { }; static const Property usb_audio_properties[] = { - DEFINE_AUDIO_PROPERTIES(USBAudioState, card), + DEFINE_AUDIO_PROPERTIES(USBAudioState, audio_be), DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0), DEFINE_PROP_UINT32("buffer", USBAudioState, buffer_user, 0), DEFINE_PROP_BOOL("multi", USBAudioState, multi, false), diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h index 04fac270b6..bb51e9a3d1 100644 --- a/include/hw/audio/asc.h +++ b/include/hw/audio/asc.h @@ -14,7 +14,7 @@ #define HW_AUDIO_ASC_H #include "hw/sysbus.h" -#include "audio/audio.h" +#include "qemu/audio.h" #define ASC_FREQ 22257 @@ -61,7 +61,7 @@ struct ASCState { MemoryRegion mem_regs; MemoryRegion mem_extregs; - QEMUSoundCard card; + AudioBackend *audio_be; SWVoiceOut *voice; uint8_t *mixbuf; int samples; diff --git a/include/hw/audio/model.h b/include/hw/audio/model.h new file mode 100644 index 0000000000..c38b359413 --- /dev/null +++ b/include/hw/audio/model.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef HW_AUDIO_MODEL_H +#define HW_AUDIO_MODEL_H + +void audio_register_model_with_cb(const char *name, const char *descr, + void (*init_audio_model)(const char *audiodev)); +void audio_register_model(const char *name, const char *descr, + const char *typename); + +void audio_model_init(void); +void audio_print_available_models(void); +void audio_set_model(const char *name, const char *audiodev); + +#endif diff --git a/include/hw/audio/soundhw.h b/include/hw/audio/soundhw.h deleted file mode 100644 index 83b3011083..0000000000 --- a/include/hw/audio/soundhw.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef HW_SOUNDHW_H -#define HW_SOUNDHW_H - -void pci_register_soundhw(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus, const char *audiodev)); -void deprecated_register_soundhw(const char *name, const char *descr, - int isa, const char *typename); - -void soundhw_init(void); -void audio_print_available_models(void); -void select_soundhw(const char *name, const char *audiodev); - -#endif diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index 8dafedb276..c176066584 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/virtio-snd.h @@ -17,7 +17,7 @@ #define QEMU_VIRTIO_SOUND_H #include "hw/virtio/virtio.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_snd.h" @@ -216,7 +216,7 @@ struct VirtIOSound { VirtQueue *queues[VIRTIO_SND_VQ_MAX]; uint64_t features; VirtIOSoundPCM *pcm; - QEMUSoundCard card; + AudioBackend *audio_be; VMChangeStateEntry *vmstate; virtio_snd_config snd_conf; QemuMutex cmdq_mutex; diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h index e86a87f235..af859e477d 100644 --- a/include/hw/display/xlnx_dp.h +++ b/include/hw/display/xlnx_dp.h @@ -33,7 +33,7 @@ #include "qemu/fifo8.h" #include "qemu/units.h" #include "hw/dma/xlnx_dpdma.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qom/object.h" #include "hw/ptimer.h" @@ -84,7 +84,7 @@ struct XlnxDPState { struct PixmanPlane v_plane; struct PixmanPlane bout_plane; - QEMUSoundCard aud_card; + AudioBackend *audio_be; SWVoiceOut *amixer_output_stream; int16_t audio_buffer_0[AUD_CHBUF_MAX_DEPTH]; int16_t audio_buffer_1[AUD_CHBUF_MAX_DEPTH]; diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index da1722daf2..ace9e6650e 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -2,7 +2,7 @@ #define HW_VT82C686_H #include "hw/pci/pci_device.h" -#include "audio/audio.h" +#include "qemu/audio.h" #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci" @@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97); struct ViaAC97State { PCIDevice dev; - QEMUSoundCard card; + AudioBackend *audio_be; MemoryRegion sgd; MemoryRegion fm; MemoryRegion midi; diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h index 5c6cc5eae8..45687be005 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -87,7 +87,7 @@ extern const PropertyInfo qdev_prop_virtio_gpu_output_list; .set_default = true) #define DEFINE_PROP_AUDIODEV(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard) + DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, AudioBackend *) #define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) \ DEFINE_PROP(_name, _state, _field, qdev_prop_uuid, QemuUUID) diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 1d57bf6577..de33637869 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -1,6 +1,8 @@ #ifndef MONITOR_QDEV_H #define MONITOR_QDEV_H +#include "hw/qdev-core.h" + /*** monitor commands ***/ void hmp_info_qtree(Monitor *mon, const QDict *qdict); @@ -11,6 +13,7 @@ int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts, Error **errp); DeviceState *qdev_device_add_from_qdict(const QDict *opts, bool from_json, Error **errp); +BusState *qdev_find_default_bus(DeviceClass *dc, Error **errp); /** * qdev_set_id: parent the device and set its id if provided. diff --git a/include/qemu/audio-capture.h b/include/qemu/audio-capture.h new file mode 100644 index 0000000000..a07412db85 --- /dev/null +++ b/include/qemu/audio-capture.h @@ -0,0 +1,43 @@ +/* + * QEMU Audio subsystem + * + * SPDX-License-Identifier: MIT + */ +#ifndef QEMU_AUDIO_CAPTURE_H +#define QEMU_AUDIO_CAPTURE_H + +#include "audio.h" + +typedef struct CaptureVoiceOut CaptureVoiceOut; + +typedef enum { + AUD_CNOTIFY_ENABLE, + AUD_CNOTIFY_DISABLE +} audcnotification_e; + +struct audio_capture_ops { + void (*notify) (void *opaque, audcnotification_e cmd); + void (*capture) (void *opaque, const void *buf, int size); + void (*destroy) (void *opaque); +}; + +struct capture_ops { + void (*info) (void *opaque); + void (*destroy) (void *opaque); +}; + +typedef struct CaptureState { + void *opaque; + struct capture_ops ops; + QLIST_ENTRY(CaptureState) entries; +} CaptureState; + +CaptureVoiceOut *AUD_add_capture( + AudioBackend *be, + struct audsettings *as, + struct audio_capture_ops *ops, + void *opaque + ); +void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); + +#endif /* QEMU_AUDIO_CAPTURE_H */ diff --git a/include/qemu/audio.h b/include/qemu/audio.h new file mode 100644 index 0000000000..c56af895d6 --- /dev/null +++ b/include/qemu/audio.h @@ -0,0 +1,150 @@ +/* + * QEMU Audio subsystem header + * + * Copyright (c) 2003-2005 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef QEMU_AUDIO_H +#define QEMU_AUDIO_H + +#include "qemu/queue.h" +#include "qapi/qapi-types-audio.h" +#include "hw/qdev-properties-system.h" +#ifdef CONFIG_GIO +#include "gio/gio.h" +#endif + +typedef void (*audio_callback_fn) (void *opaque, int avail); + +typedef struct audsettings { + int freq; + int nchannels; + AudioFormat fmt; + int endianness; +} audsettings; + +typedef struct SWVoiceOut SWVoiceOut; +typedef struct SWVoiceIn SWVoiceIn; + +struct AudioBackendClass { + ObjectClass parent_class; +}; + +typedef struct AudioBackend AudioBackend; + +typedef struct QEMUAudioTimeStamp { + uint64_t old_ts; +} QEMUAudioTimeStamp; + +bool AUD_backend_check(AudioBackend **be, Error **errp); + +SWVoiceOut *AUD_open_out ( + AudioBackend *be, + SWVoiceOut *sw, + const char *name, + void *callback_opaque, + audio_callback_fn callback_fn, + struct audsettings *settings + ); + +void AUD_close_out (AudioBackend *be, SWVoiceOut *sw); +size_t AUD_write (SWVoiceOut *sw, void *pcm_buf, size_t size); +int AUD_get_buffer_size_out (SWVoiceOut *sw); +void AUD_set_active_out(SWVoiceOut *sw, bool on); +bool AUD_is_active_out(SWVoiceOut *sw); + +void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts); + +#define AUDIO_MAX_CHANNELS 16 +typedef struct Volume { + bool mute; + int channels; + uint8_t vol[AUDIO_MAX_CHANNELS]; +} Volume; + +void AUD_set_volume_out(SWVoiceOut *sw, Volume *vol); +void AUD_set_volume_in(SWVoiceIn *sw, Volume *vol); + +static inline void +AUD_set_volume_out_lr(SWVoiceOut *sw, bool mut, uint8_t lvol, uint8_t rvol) { + AUD_set_volume_out(sw, &(Volume) { + .mute = mut, .channels = 2, .vol = { lvol, rvol } + }); +} + +static inline void +AUD_set_volume_in_lr(SWVoiceIn *sw, bool mut, uint8_t lvol, uint8_t rvol) { + AUD_set_volume_in(sw, &(Volume) { + .mute = mut, .channels = 2, .vol = { lvol, rvol } + }); +} + +SWVoiceIn *AUD_open_in( + AudioBackend *be, + SWVoiceIn *sw, + const char *name, + void *callback_opaque, + audio_callback_fn callback_fn, + struct audsettings *settings + ); + +void AUD_close_in(AudioBackend *be, SWVoiceIn *sw); +size_t AUD_read (SWVoiceIn *sw, void *pcm_buf, size_t size); +void AUD_set_active_in(SWVoiceIn *sw, bool on); +bool AUD_is_active_in(SWVoiceIn *sw); + +void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); +uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts); + +void audio_cleanup(void); + +typedef struct st_sample st_sample; + +void audio_sample_to_uint64(const st_sample *sample, int pos, + uint64_t *left, uint64_t *right); +void audio_sample_from_uint64(st_sample *sample, int pos, + uint64_t left, uint64_t right); + +void audio_add_audiodev(Audiodev *audio); +void audio_add_default_audiodev(Audiodev *dev, Error **errp); +void audio_parse_option(const char *opt); +void audio_create_default_audiodevs(void); +void audio_init_audiodevs(void); +void audio_help(void); + +AudioBackend *audio_be_by_name(const char *name, Error **errp); +AudioBackend *audio_get_default_audio_be(Error **errp); +const char *audio_be_get_id(AudioBackend *be); +#ifdef CONFIG_GIO +bool audio_be_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp); +#endif + +#define DEFINE_AUDIO_PROPERTIES(_s, _f) \ + DEFINE_PROP_AUDIODEV("audiodev", _s, _f) + +#define TYPE_AUDIO_BACKEND "audio-backend" +OBJECT_DECLARE_TYPE(AudioBackend, AudioBackendClass, AUDIO_BACKEND) + +#endif /* QEMU_AUDIO_H */ diff --git a/include/system/replay.h b/include/system/replay.h index 1c87c97fdd..68f91bdfbf 100644 --- a/include/system/replay.h +++ b/include/system/replay.h @@ -16,6 +16,7 @@ #include "qapi/qapi-types-run-state.h" #include "qapi/qapi-types-ui.h" #include "block/aio.h" +#include "qemu/audio.h" /* replay clock kinds */ enum ReplayClockKind { @@ -165,7 +166,7 @@ void replay_net_packet_event(ReplayNetState *rns, unsigned flags, /*! Saves/restores number of played samples of audio out operation. */ void replay_audio_out(size_t *played); /*! Saves/restores recorded samples of audio in operation. */ -void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size); +void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size); /* VM state operations */ diff --git a/qom/object.c b/qom/object.c index 1856bb36c7..4f32c1aba7 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1730,6 +1730,7 @@ const char *object_property_get_type(Object *obj, const char *name, Error **errp } static const char *const root_containers[] = { + "audiodevs", "chardevs", "objects", "backend" diff --git a/replay/replay-audio.c b/replay/replay-audio.c index ed2ba2164b..1b614f4137 100644 --- a/replay/replay-audio.c +++ b/replay/replay-audio.c @@ -13,7 +13,7 @@ #include "qemu/error-report.h" #include "system/replay.h" #include "replay-internal.h" -#include "audio/audio.h" +#include "qemu/audio.h" void replay_audio_out(size_t *played) { @@ -35,7 +35,7 @@ void replay_audio_out(size_t *played) } } -void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size) +void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size) { int pos; uint64_t left, right; diff --git a/replay/stubs-system.c b/replay/stubs-system.c index 8f2b2d326e..7f85764936 100644 --- a/replay/stubs-system.c +++ b/replay/stubs-system.c @@ -15,7 +15,7 @@ void replay_input_sync_event(void) void replay_add_blocker(const char *feature) { } -void replay_audio_in(size_t *recorded, void *samples, size_t *wpos, size_t size) +void replay_audio_in(size_t *recorded, st_sample *samples, size_t *wpos, size_t size) { } void replay_audio_out(size_t *played) diff --git a/scripts/codeconverter/codeconverter/test_regexps.py b/scripts/codeconverter/codeconverter/test_regexps.py index 4526268ae8..b00e9ef15b 100644 --- a/scripts/codeconverter/codeconverter/test_regexps.py +++ b/scripts/codeconverter/codeconverter/test_regexps.py @@ -264,8 +264,8 @@ def test_initial_includes(): #define SILENT_ES1370 #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" #include "qemu/module.h" diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index ec4a2394ce..f2aa400a77 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -621,6 +621,25 @@ const char *qdev_set_id(DeviceState *dev, char *id, Error **errp) return prop->name; } +BusState *qdev_find_default_bus(DeviceClass *dc, Error **errp) +{ + BusState *bus = NULL; + + assert(dc->bus_type != NULL); + bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type); + if (!bus) { + error_setg(errp, "No '%s' bus found for device '%s'", + dc->bus_type, object_class_get_name(OBJECT_CLASS(dc))); + return NULL; + } + if (qbus_is_full(bus)) { + error_setg(errp, "A '%s' bus was found but is full", dc->bus_type); + return NULL; + } + + return bus; +} + DeviceState *qdev_device_add_from_qdict(const QDict *opts, bool from_json, Error **errp) { @@ -657,10 +676,8 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, return NULL; } } else if (dc->bus_type != NULL) { - bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type); - if (!bus || qbus_is_full(bus)) { - error_setg(errp, "No '%s' bus found for device '%s'", - dc->bus_type, driver); + bus = qdev_find_default_bus(dc, errp); + if (!bus) { return NULL; } } diff --git a/system/runstate.c b/system/runstate.c index 32467aa882..e3ec16ab74 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "block/block.h" #include "block/export.h" #include "chardev/char.h" diff --git a/system/vl.c b/system/vl.c index 17bbc092c8..29f5389151 100644 --- a/system/vl.c +++ b/system/vl.c @@ -86,8 +86,8 @@ #include "migration/snapshot.h" #include "system/tpm.h" #include "system/dma.h" -#include "hw/audio/soundhw.h" -#include "audio/audio.h" +#include "hw/audio/model.h" +#include "qemu/audio.h" #include "system/cpus.h" #include "system/cpu-timers.h" #include "exec/icount.h" @@ -2265,7 +2265,7 @@ static void qemu_record_config_group(const char *group, QDict *dict, Audiodev *dev = NULL; Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict)); if (visit_type_Audiodev(v, NULL, &dev, errp)) { - audio_define(dev); + audio_add_audiodev(dev); } visit_free(v); @@ -2732,7 +2732,7 @@ static void qemu_create_cli_devices(void) { DeviceOption *opt; - soundhw_init(); + audio_model_init(); qemu_opts_foreach(qemu_find_opts("fw_cfg"), parse_fw_cfg, fw_cfg_find(), &error_fatal); @@ -3087,11 +3087,11 @@ void qemu_init(int argc, char **argv) visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_free(v); if (model) { - audio_define(dev); - select_soundhw(model, dev->id); + audio_add_audiodev(dev); + audio_set_model(model, dev->id); g_free(model); } else { - audio_define_default(dev, &error_fatal); + audio_add_default_audiodev(dev, &error_fatal); } break; } diff --git a/ui/dbus.c b/ui/dbus.c index dd0336702d..d2dff33258 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -34,8 +34,7 @@ #include "ui/egl-helpers.h" #include "ui/egl-context.h" #endif -#include "audio/audio.h" -#include "audio/audio_int.h" +#include "qemu/audio.h" #include "qapi/error.h" #include "trace.h" @@ -220,16 +219,10 @@ dbus_display_complete(UserCreatable *uc, Error **errp) } if (dd->audiodev && *dd->audiodev) { - AudioState *audio_state = audio_state_by_name(dd->audiodev, errp); - if (!audio_state) { + AudioBackend *audio_be = audio_be_by_name(dd->audiodev, errp); + if (!audio_be || !audio_be_set_dbus_server(audio_be, dd->server, dd->p2p, errp)) { return; } - if (!g_str_equal(audio_state->drv->name, "dbus")) { - error_setg(errp, "Audiodev '%s' is not compatible with DBus", - dd->audiodev); - return; - } - audio_state->drv->set_dbus_server(audio_state, dd->server, dd->p2p); } consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); diff --git a/ui/vnc.c b/ui/vnc.c index 77c823bf2e..0094ec680c 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1276,7 +1276,7 @@ static void audio_add(VncState *vs) ops.destroy = audio_capture_destroy; ops.capture = audio_capture; - vs->audio_cap = AUD_add_capture(vs->vd->audio_state, &vs->as, &ops, vs); + vs->audio_cap = AUD_add_capture(vs->vd->audio_be, &vs->as, &ops, vs); if (!vs->audio_cap) { error_report("Failed to add audio capture"); } @@ -2193,7 +2193,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) send_ext_key_event_ack(vs); break; case VNC_ENCODING_AUDIO: - if (vs->vd->audio_state) { + if (vs->vd->audio_be) { vnc_set_feature(vs, VNC_FEATURE_AUDIO); send_ext_audio_ack(vs); } @@ -4236,12 +4236,12 @@ void vnc_display_open(const char *id, Error **errp) audiodev = qemu_opt_get(opts, "audiodev"); if (audiodev) { - vd->audio_state = audio_state_by_name(audiodev, errp); - if (!vd->audio_state) { + vd->audio_be = audio_be_by_name(audiodev, errp); + if (!vd->audio_be) { goto fail; } } else { - vd->audio_state = audio_get_default_audio_state(NULL); + vd->audio_be = audio_get_default_audio_be(NULL); } device_id = qemu_opt_get(opts, "display"); diff --git a/ui/vnc.h b/ui/vnc.h index f2dab2f4d9..ec8d0c91b5 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -31,7 +31,7 @@ #include "qemu/thread.h" #include "ui/clipboard.h" #include "ui/console.h" -#include "audio/audio.h" +#include "qemu/audio-capture.h" #include "qemu/bitmap.h" #include "crypto/tlssession.h" #include "qemu/buffer.h" @@ -184,7 +184,7 @@ struct VncDisplay VncDisplaySASL sasl; #endif - AudioState *audio_state; + AudioBackend *audio_be; VMChangeStateEntry *vmstate_handler_entry; };