From faa5c9ac3f577582b02770e720c6b0459966bbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 14:31:15 +0400 Subject: [PATCH 01/36] qdev: add qdev_find_default_bus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper is used next by -audio code. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- include/monitor/qdev.h | 3 +++ system/qdev-monitor.c | 25 +++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) 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/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; } } From 5c7b8a6d61a0af15d531f82eef8ddd97e40c1ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 15:16:29 +0400 Subject: [PATCH 02/36] hw/audio: look up the default bus from the device class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize and simplify the device model creation. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/soundhw.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/hw/audio/soundhw.c b/hw/audio/soundhw.c index 63a6855635..29158c115c 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/soundhw.c @@ -22,6 +22,8 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" +#include "hw/qdev-core.h" +#include "monitor/qdev.h" #include "qemu/option.h" #include "qemu/help_option.h" #include "qemu/error-report.h" @@ -110,33 +112,19 @@ void select_soundhw(const char *name, const char *audiodev) void soundhw_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; 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); + PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); c->init_pci(pci_bus, audiodev_id); } } From 07af152c760ee0e651c3d579fbc0dd474d87bd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 15:45:41 +0400 Subject: [PATCH 03/36] audio: rename audio_define->audio_add_audiodev() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For readability. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 8 ++++---- audio/audio.h | 4 ++-- system/vl.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 89f091bc88..6197fa1788 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1712,7 +1712,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); } } } @@ -2142,10 +2142,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 +2156,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; diff --git a/audio/audio.h b/audio/audio.h index fcc22307be..eb5b5d662d 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -168,8 +168,8 @@ void audio_sample_to_uint64(const void *samples, int pos, 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_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); diff --git a/system/vl.c b/system/vl.c index 17bbc092c8..4814ef11da 100644 --- a/system/vl.c +++ b/system/vl.c @@ -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); @@ -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); + audio_add_audiodev(dev); select_soundhw(model, dev->id); g_free(model); } else { - audio_define_default(dev, &error_fatal); + audio_add_default_audiodev(dev, &error_fatal); } break; } From 635af5706833e6c818ce5eb31fad4b0a826e7b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 16:05:00 +0400 Subject: [PATCH 04/36] hw/audio: use better naming for -audio model handling code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the functions are about "-audio model=" handling, a simpler way to setup audio. Rename functions/variables to reflect this better. audio_register_model_with_cb() dropped "pci" from the name, since it will be generalized next. deprecated_register_soundhw() was actually not a function to be removed since it's used for "-audio model=" aliasing. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/ac97.c | 5 +- hw/audio/adlib.c | 4 +- hw/audio/cs4231a.c | 4 +- hw/audio/es1370.c | 5 +- hw/audio/gus.c | 4 +- hw/audio/intel-hda.c | 4 +- hw/audio/meson.build | 2 +- hw/audio/{soundhw.c => model.c} | 58 +++++++++---------- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 5 +- hw/audio/virtio-snd-pci.c | 4 +- include/hw/audio/model.h | 14 +++++ include/hw/audio/soundhw.h | 13 ----- .../codeconverter/test_regexps.py | 2 +- system/vl.c | 6 +- 15 files changed, 65 insertions(+), 67 deletions(-) rename hw/audio/{soundhw.c => model.c} (68%) create mode 100644 include/hw/audio/model.h delete mode 100644 include/hw/audio/soundhw.h diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 828333b66a..9dee5bb143 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -18,7 +18,7 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/pci/pci_device.h" #include "hw/qdev-properties.h" @@ -1362,8 +1362,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", 0, TYPE_AC97); } type_init(ac97_register_types) diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 772435f04c..d0b2817843 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" @@ -323,7 +323,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, 1, TYPE_ADLIB); } type_init (adlib_register_types) diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 7931fcfec8..0979cf5f16 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" @@ -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", 1, TYPE_CS4231A); } type_init (cs4231a_register_types) diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 6b0da0746e..066b9906fa 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -26,7 +26,7 @@ #define VERBOSE_ES1370 0 #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/pci/pci_device.h" #include "migration/vmstate.h" @@ -905,8 +905,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", 0, TYPE_ES1370); } type_init (es1370_register_types) diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 91d07e0f81..d5b1e62135 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" @@ -320,7 +320,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", 1, TYPE_GUS); } type_init (gus_register_types) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index b256c8ccea..6a0db0dd9e 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -26,7 +26,7 @@ #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" @@ -1324,7 +1324,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/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 68% rename from hw/audio/soundhw.c rename to hw/audio/model.c index 29158c115c..ddfefea706 100644 --- a/hw/audio/soundhw.c +++ b/hw/audio/model.c @@ -32,9 +32,9 @@ #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; @@ -42,38 +42,38 @@ struct soundhw { int (*init_pci) (PCIBus *bus, 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, + int (*init_pci)(PCIBus *bus, 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].isa = 0; + audio_models[audio_models_count].init_pci = init_pci; + 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, + int isa, 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].isa = isa; + 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 { @@ -82,19 +82,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; @@ -109,9 +109,9 @@ void select_soundhw(const char *name, const char *audiodev) } } -void soundhw_init(void) +void audio_model_init(void) { - struct soundhw *c = selected; + struct audio_model *c = selected; if (!c) { return; diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index a719912872..48ef830292 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/isa/isa.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "qemu/module.h" #include "qemu/timer.h" diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 03c82f2777..5faa3f5fe3 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" @@ -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", 1, TYPE_SB16); } type_init (sb16_register_types) diff --git a/hw/audio/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c index 9eb0007392..613538e46f 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" @@ -88,7 +88,7 @@ static int virtio_snd_pci_init(PCIBus *bus, const char *audiodev) 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_with_cb("virtio", "Virtio Sound", virtio_snd_pci_init); } type_init(virtio_snd_pci_register); diff --git a/include/hw/audio/model.h b/include/hw/audio/model.h new file mode 100644 index 0000000000..aa237e9eb6 --- /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, + int (*init_pci)(PCIBus *bus, const char *audiodev)); +void audio_register_model(const char *name, const char *descr, + int isa, 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/scripts/codeconverter/codeconverter/test_regexps.py b/scripts/codeconverter/codeconverter/test_regexps.py index 4526268ae8..fe7354b473 100644 --- a/scripts/codeconverter/codeconverter/test_regexps.py +++ b/scripts/codeconverter/codeconverter/test_regexps.py @@ -264,7 +264,7 @@ def test_initial_includes(): #define SILENT_ES1370 #include "qemu/osdep.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" diff --git a/system/vl.c b/system/vl.c index 4814ef11da..dc2ea4c298 100644 --- a/system/vl.c +++ b/system/vl.c @@ -86,7 +86,7 @@ #include "migration/snapshot.h" #include "system/tpm.h" #include "system/dma.h" -#include "hw/audio/soundhw.h" +#include "hw/audio/model.h" #include "audio/audio.h" #include "system/cpus.h" #include "system/cpu-timers.h" @@ -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); @@ -3088,7 +3088,7 @@ void qemu_init(int argc, char **argv) visit_free(v); if (model) { audio_add_audiodev(dev); - select_soundhw(model, dev->id); + audio_set_model(model, dev->id); g_free(model); } else { audio_add_default_audiodev(dev, &error_fatal); From 341eaea215a963016f814bdd11c45c68c9bf1e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 16:13:38 +0400 Subject: [PATCH 05/36] hw/audio/virtio-snd-pci: remove custom model callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit virtio-snd can rely on the default code to instantiate the device and set the audiodev. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/virtio-snd-pci.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/hw/audio/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c index 613538e46f..b78eaff851 100644 --- a/hw/audio/virtio-snd-pci.c +++ b/hw/audio/virtio-snd-pci.c @@ -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); - audio_register_model_with_cb("virtio", "Virtio Sound", virtio_snd_pci_init); + audio_register_model("virtio", "Virtio Sound", 0, TYPE_VIRTIO_SND_PCI); } type_init(virtio_snd_pci_register); From 96da2b29f4c65db17aa491b24f50eea93dc885d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Oct 2025 16:22:40 +0400 Subject: [PATCH 06/36] hw/audio: simplify 'hda' audio init code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency, use only qdev_device_add() to instantiate the devices. We can't rely on automatic bus lookup for the "hda-duplex" device though as it may end up on a different "intel-hda" bus... This allows to make init() callback bus-agnostic next. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/intel-hda.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 6a0db0dd9e..c46b195b62 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/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" @@ -1305,15 +1305,19 @@ static const TypeInfo hda_codec_device_type_info = { */ static int intel_hda_and_codec_init(PCIBus *bus, 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); + object_unref(intel_hda); + return 0; } From b181226e4e7ac4b5136d9ce0c0ace46e50416b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 14:22:45 +0400 Subject: [PATCH 07/36] hw/audio: generalize audio_model.init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is no longer PCI bus only. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/intel-hda.c | 4 +--- hw/audio/model.c | 12 ++++-------- include/hw/audio/model.h | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index c46b195b62..758e130c93 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -1303,7 +1303,7 @@ 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) { g_autoptr(QDict) props = qdict_new(); DeviceState *intel_hda, *codec; @@ -1317,8 +1317,6 @@ static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev) qdev_prop_set_string(codec, "audiodev", audiodev); qdev_realize_and_unref(codec, hdabus, &error_fatal); object_unref(intel_hda); - - return 0; } static void intel_hda_register_types(void) diff --git a/hw/audio/model.c b/hw/audio/model.c index ddfefea706..7af0d960f5 100644 --- a/hw/audio/model.c +++ b/hw/audio/model.c @@ -24,14 +24,11 @@ #include "qemu/osdep.h" #include "hw/qdev-core.h" #include "monitor/qdev.h" -#include "qemu/option.h" -#include "qemu/help_option.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/model.h" struct audio_model { @@ -39,20 +36,20 @@ struct audio_model { const char *descr; const char *typename; int isa; - int (*init_pci) (PCIBus *bus, const char *audiodev); + void (*init)(const char *audiodev); }; static struct audio_model audio_models[9]; static int audio_models_count; void audio_register_model_with_cb(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus, const char *audiodev)) + void (*init_audio_model)(const char *audiodev)) { 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].isa = 0; - audio_models[audio_models_count].init_pci = init_pci; + audio_models[audio_models_count].init = init_audio_model; audio_models_count++; } @@ -124,7 +121,6 @@ void audio_model_init(void) qdev_realize_and_unref(dev, bus, &error_fatal); } else { assert(!c->isa); - PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL); - c->init_pci(pci_bus, audiodev_id); + c->init(audiodev_id); } } diff --git a/include/hw/audio/model.h b/include/hw/audio/model.h index aa237e9eb6..4d0be93042 100644 --- a/include/hw/audio/model.h +++ b/include/hw/audio/model.h @@ -3,7 +3,7 @@ #define HW_AUDIO_MODEL_H void audio_register_model_with_cb(const char *name, const char *descr, - int (*init_pci)(PCIBus *bus, const char *audiodev)); + void (*init_audio_model)(const char *audiodev)); void audio_register_model(const char *name, const char *descr, int isa, const char *typename); From 5fb347dea0367609f316d10a3ac69018ce00d128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 27 Oct 2025 17:44:10 +0400 Subject: [PATCH 08/36] hw/audio: drop audio_model.isa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That's no longer necessary, the code is bus-agnostic. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/cs4231a.c | 2 +- hw/audio/es1370.c | 2 +- hw/audio/gus.c | 2 +- hw/audio/model.c | 8 +------- hw/audio/sb16.c | 2 +- hw/audio/virtio-snd-pci.c | 2 +- include/hw/audio/model.h | 2 +- 9 files changed, 9 insertions(+), 15 deletions(-) diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 9dee5bb143..6b9013ebb8 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1362,7 +1362,7 @@ static const TypeInfo ac97_info = { static void ac97_register_types(void) { type_register_static(&ac97_info); - audio_register_model("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 d0b2817843..6aae365f47 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -323,7 +323,7 @@ static const TypeInfo adlib_info = { static void adlib_register_types (void) { type_register_static (&adlib_info); - audio_register_model("adlib", ADLIB_DESC, 1, TYPE_ADLIB); + audio_register_model("adlib", ADLIB_DESC, TYPE_ADLIB); } type_init (adlib_register_types) diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 0979cf5f16..3b80a61378 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -723,7 +723,7 @@ static const TypeInfo cs4231a_info = { static void cs4231a_register_types (void) { type_register_static (&cs4231a_info); - audio_register_model("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 066b9906fa..721c02be0a 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -905,7 +905,7 @@ static const TypeInfo es1370_info = { static void es1370_register_types (void) { type_register_static (&es1370_info); - audio_register_model("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 d5b1e62135..45ea04bf89 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -320,7 +320,7 @@ static const TypeInfo gus_info = { static void gus_register_types (void) { type_register_static (&gus_info); - audio_register_model("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/model.c b/hw/audio/model.c index 7af0d960f5..40929c6e77 100644 --- a/hw/audio/model.c +++ b/hw/audio/model.c @@ -26,16 +26,13 @@ #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/audio/model.h" struct audio_model { const char *name; const char *descr; const char *typename; - int isa; void (*init)(const char *audiodev); }; @@ -48,18 +45,16 @@ void audio_register_model_with_cb(const char *name, const char *descr, 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].isa = 0; audio_models[audio_models_count].init = init_audio_model; audio_models_count++; } void audio_register_model(const char *name, const char *descr, - int isa, const char *typename) + const char *typename) { 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].isa = isa; audio_models[audio_models_count].typename = typename; audio_models_count++; } @@ -120,7 +115,6 @@ void audio_model_init(void) qdev_prop_set_string(dev, "audiodev", audiodev_id); qdev_realize_and_unref(dev, bus, &error_fatal); } else { - assert(!c->isa); c->init(audiodev_id); } } diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 5faa3f5fe3..e86aafd488 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1470,7 +1470,7 @@ static const TypeInfo sb16_info = { static void sb16_register_types (void) { type_register_static (&sb16_info); - audio_register_model("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/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c index b78eaff851..230581ed63 100644 --- a/hw/audio/virtio-snd-pci.c +++ b/hw/audio/virtio-snd-pci.c @@ -74,7 +74,7 @@ static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = { static void virtio_snd_pci_register(void) { virtio_pci_types_register(&virtio_snd_pci_info); - audio_register_model("virtio", "Virtio Sound", 0, TYPE_VIRTIO_SND_PCI); + audio_register_model("virtio", "Virtio Sound", TYPE_VIRTIO_SND_PCI); } type_init(virtio_snd_pci_register); diff --git a/include/hw/audio/model.h b/include/hw/audio/model.h index 4d0be93042..c38b359413 100644 --- a/include/hw/audio/model.h +++ b/include/hw/audio/model.h @@ -5,7 +5,7 @@ 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, - int isa, const char *typename); + const char *typename); void audio_model_init(void); void audio_print_available_models(void); From f991647ed49737a082131ebb9602a116b57fa435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 17:38:42 +0400 Subject: [PATCH 09/36] audio: start making AudioState a QOM Object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM brings some conveniences for introspection, type checking, reference counting, interfaces etc. This is only the first step to introduce QOM in audio/ (I have more in the pipeline) Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 43 ++++++++++++++++++++++++++++++++----------- audio/audio.h | 7 +++++++ audio/audio_int.h | 2 ++ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 6197fa1788..e1696403ae 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1617,8 +1617,19 @@ static void audio_vm_change_state_handler (void *opaque, bool running, audio_reset_timer (s); } -static void free_audio_state(AudioState *s) +static void audio_state_init(Object *obj) { + AudioState *s = AUDIO_STATE(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); +} + +static void audio_state_finalize(Object *obj) +{ + AudioState *s = AUDIO_STATE(obj); HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; @@ -1663,8 +1674,6 @@ static void free_audio_state(AudioState *s) timer_free(s->ts); s->ts = NULL; } - - g_free(s); } void audio_cleanup(void) @@ -1673,7 +1682,7 @@ void audio_cleanup(void) while (!QTAILQ_EMPTY(&audio_states)) { AudioState *s = QTAILQ_FIRST(&audio_states); QTAILQ_REMOVE(&audio_states, s, list); - free_audio_state(s); + object_unref(s); } } @@ -1732,18 +1741,13 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) AudioState *s; struct audio_driver *driver; - s = g_new0(AudioState, 1); + s = AUDIO_STATE(object_new(TYPE_AUDIO_STATE)); - 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); - if (dev) { /* -audiodev option */ s->dev = dev; @@ -1796,7 +1800,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) return s; out: - free_audio_state(s); + object_unref(s); return NULL; } @@ -2320,3 +2324,20 @@ AudiodevList *qmp_query_audiodevs(Error **errp) } return ret; } + +static const TypeInfo audio_state_info = { + .name = TYPE_AUDIO_STATE, + .parent = TYPE_OBJECT, + .instance_size = sizeof(AudioState), + .instance_init = audio_state_init, + .instance_finalize = audio_state_finalize, + .abstract = false, /* TODO: subclass drivers and make it abstract */ + .class_size = sizeof(AudioStateClass), +}; + +static void register_types(void) +{ + type_register_static(&audio_state_info); +} + +type_init(register_types); diff --git a/audio/audio.h b/audio/audio.h index eb5b5d662d..e41c5bc55a 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -80,6 +80,10 @@ typedef struct SWVoiceOut SWVoiceOut; typedef struct CaptureVoiceOut CaptureVoiceOut; typedef struct SWVoiceIn SWVoiceIn; +struct AudioStateClass { + ObjectClass parent_class; +}; + typedef struct AudioState AudioState; typedef struct QEMUSoundCard { char *name; @@ -182,4 +186,7 @@ const char *audio_get_id(QEMUSoundCard *card); #define DEFINE_AUDIO_PROPERTIES(_s, _f) \ DEFINE_PROP_AUDIODEV("audiodev", _s, _f) +#define TYPE_AUDIO_STATE "audio-state" +OBJECT_DECLARE_TYPE(AudioState, AudioStateClass, AUDIO_STATE) + #endif /* QEMU_AUDIO_H */ diff --git a/audio/audio_int.h b/audio/audio_int.h index f78ca05f92..b2b4d2d10e 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -217,6 +217,8 @@ struct SWVoiceCap { }; typedef struct AudioState { + Object parent; + struct audio_driver *drv; Audiodev *dev; void *drv_opaque; From 6334967f6cb3993dc19883d2bdd314689d0a0c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 17:45:48 +0400 Subject: [PATCH 10/36] audio: register backends in /audiodevs container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM tree now has /audiodevs objects. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 8 ++++++++ qom/object.c | 1 + 2 files changed, 9 insertions(+) diff --git a/audio/audio.c b/audio/audio.c index e1696403ae..c291fd3e65 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1676,6 +1676,11 @@ static void audio_state_finalize(Object *obj) } } +static Object *get_audiodevs_root(void) +{ + return object_get_container("audiodevs"); +} + void audio_cleanup(void) { default_audio_state = NULL; @@ -1742,6 +1747,9 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) struct audio_driver *driver; s = AUDIO_STATE(object_new(TYPE_AUDIO_STATE)); + if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { + goto out; + } if (!atexit_registered) { atexit(audio_cleanup); 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" From ef8105e3f90157ca627d2e8bc63540bbeb82e0b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 22:09:41 +0400 Subject: [PATCH 11/36] audio: use /audiodevs QOM container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit audio_cleanup() is already called at exit (similar to chardev) Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 38 +++++++++++++------------------------- audio/audio_int.h | 2 -- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index c291fd3e65..5bf4307fbd 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -102,8 +102,6 @@ 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; const struct mixeng_volume nominal_volume = { @@ -1684,11 +1682,8 @@ static Object *get_audiodevs_root(void) 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); - object_unref(s); - } + + object_unparent(get_audiodevs_root()); } static bool vmstate_audio_needed(void *opaque) @@ -1739,7 +1734,6 @@ void audio_create_default_audiodevs(void) */ static AudioState *audio_init(Audiodev *dev, Error **errp) { - static bool atexit_registered; int done = 0; const char *drvname; VMChangeStateEntry *vmse; @@ -1747,14 +1741,6 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) struct audio_driver *driver; s = AUDIO_STATE(object_new(TYPE_AUDIO_STATE)); - if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { - goto out; - } - - if (!atexit_registered) { - atexit(audio_cleanup); - atexit_registered = true; - } if (dev) { /* -audiodev option */ @@ -1802,7 +1788,10 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) "(Audio can continue looping even after stopping the VM)\n"); } - QTAILQ_INSERT_TAIL(&audio_states, s, list); + if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { + goto out; + } + object_unref(s); QLIST_INIT (&s->card_head); vmstate_register_any(NULL, &vmstate_audio, s); return s; @@ -2249,15 +2238,14 @@ int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo, AudioState *audio_state_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_STATE(obj); } - error_setg(errp, "audiodev '%s' not found", name); - return NULL; } const char *audio_get_id(QEMUSoundCard *card) diff --git a/audio/audio_int.h b/audio/audio_int.h index b2b4d2d10e..4187a2dbfc 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -235,8 +235,6 @@ typedef struct AudioState { bool timer_running; uint64_t timer_last; - - QTAILQ_ENTRY(AudioState) list; } AudioState; extern const struct mixeng_volume nominal_volume; From bfe95b07d2731c33e73785e17d4199ae43c3d240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 22:48:55 +0400 Subject: [PATCH 12/36] audio/paaudio: remove needless return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/paaudio.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/audio/paaudio.c b/audio/paaudio.c index f3193b08c3..93030f3fc8 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -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; From a9e0a4340ea79fcef54651ed1442a4980bd9b686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:18:41 +0400 Subject: [PATCH 13/36] audio/dsound: simplify init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use dsound_audio_fini() on error & fail if the capture failed to initialize too. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/dsoundaudio.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index f3bb48d007..c8745a3df0 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -638,7 +638,7 @@ 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); + dsound_audio_fini(s); return NULL; } @@ -651,19 +651,14 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) ); if (FAILED (hr)) { dsound_logerr (hr, "Could not create DirectSound instance\n"); - g_free(s); + 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); + dsound_audio_fini(s); return NULL; } @@ -676,17 +671,15 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) ); 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"); + dsound_audio_fini(s); + return NULL; + } - hr = IDirectSoundCapture_Release (s->dsound_capture); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not release DirectSoundCapture\n"); - } - s->dsound_capture = NULL; - } + hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); + if (FAILED(hr)) { + dsound_logerr(hr, "Could not initialize DirectSoundCapture\n"); + dsound_audio_fini(s); + return NULL; } err = dsound_set_cooperative_level(s); From 952742ec6b257e60337042e25deb42a3fd2a40f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:36:05 +0400 Subject: [PATCH 14/36] audio/dsound: report init error via **errp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever NULL is returned, errp should be set. Inline SetCooperativeLevel call to simplify code. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/dsoundaudio.c | 182 +++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 103 deletions(-) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index c8745a3df0..d476e9b441 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -33,6 +33,7 @@ #include "audio_int.h" #include "qemu/host-utils.h" #include "qemu/module.h" +#include "qapi/error.h" #include #include @@ -64,162 +65,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 +352,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 +593,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,7 +608,7 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) hr = CoInitialize (NULL); if (FAILED (hr)) { - dsound_logerr (hr, "Could not initialize COM\n"); + dserror_set(errp, hr, "Could not initialize COM"); dsound_audio_fini(s); return NULL; } @@ -650,14 +621,14 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp) (void **) &s->dsound ); if (FAILED (hr)) { - dsound_logerr (hr, "Could not create DirectSound instance\n"); + 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"); + dserror_set(errp, hr, "Could not initialize DirectSound"); dsound_audio_fini(s); return NULL; } @@ -670,21 +641,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"); + dserror_set(errp, hr, "Could not create DirectSoundCapture instance"); dsound_audio_fini(s); return NULL; } hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); if (FAILED(hr)) { - dsound_logerr(hr, "Could not initialize DirectSoundCapture\n"); + dserror_set(errp, hr, "Could not initialize DirectSoundCapture"); dsound_audio_fini(s); return NULL; } - err = dsound_set_cooperative_level(s); - if (err) { - dsound_audio_fini (s); + 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; } From ebf3a6e856358ce515dda5a36ff05f8116a4341f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:38:45 +0400 Subject: [PATCH 15/36] audio: simplify audio_driver_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Catch and return from error early to avoid indentations and ease the flow & return a bool for success value. All driver init() calls have been checked to set errp on error. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 5bf4307fbd..087e1946e7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1562,35 +1562,27 @@ 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(AudioState *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; + return true; } static void audio_vm_change_state_handler (void *opaque, bool running, @@ -1748,7 +1740,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); } @@ -1768,7 +1760,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); From ee2964259a9635f90b23d5ebe8f88f45ffbf2d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:44:47 +0400 Subject: [PATCH 16/36] audio: move period tick initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of QOM-ification. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 087e1946e7..43db7380f0 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1582,6 +1582,13 @@ static bool audio_driver_init(AudioState *s, struct audio_driver *drv, 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; } @@ -1768,12 +1775,6 @@ 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; - } - vmse = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); if (!vmse) { dolog ("warning: Could not register change state handler\n" From 0eeb7b0554d65b81281fbc06418674a536cd9daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:47:40 +0400 Subject: [PATCH 17/36] audio: drop needless error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only reason it would fail to add the handler is if it's calling a stub. But this cannot happen as audio is only supported with system qemu. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 43db7380f0..155809dee7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1776,10 +1776,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) } 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"); - } + assert(vmse != NULL); if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { goto out; From 7423b3aae67d3d089bef13bad678dbb60a3f432d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 13 Oct 2025 23:53:06 +0400 Subject: [PATCH 18/36] audio: keep vmstate handle with AudioState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOM-ification continues. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 12 ++++++++---- audio/audio_int.h | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 155809dee7..4c3c3fd52f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1622,6 +1622,9 @@ static void audio_state_init(Object *obj) 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); } static void audio_state_finalize(Object *obj) @@ -1671,6 +1674,11 @@ static void audio_state_finalize(Object *obj) timer_free(s->ts); s->ts = NULL; } + + if (s->vmse) { + qemu_del_vm_change_state_handler(s->vmse); + s->vmse = NULL; + } } static Object *get_audiodevs_root(void) @@ -1735,7 +1743,6 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) { int done = 0; const char *drvname; - VMChangeStateEntry *vmse; AudioState *s; struct audio_driver *driver; @@ -1775,9 +1782,6 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) } } - vmse = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); - assert(vmse != NULL); - if (!object_property_try_add_child(get_audiodevs_root(), dev->id, OBJECT(s), errp)) { goto out; } diff --git a/audio/audio_int.h b/audio/audio_int.h index 4187a2dbfc..4a4d69f2bf 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -235,6 +235,7 @@ typedef struct AudioState { bool timer_running; uint64_t timer_last; + VMChangeStateEntry *vmse; } AudioState; extern const struct mixeng_volume nominal_volume; From 582ca26c991049c23c04fe499779657d8ba79561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 00:01:42 +0400 Subject: [PATCH 19/36] audio: register and unregister vmstate with AudioState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proper lifecycle management with QOM state. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/audio/audio.c b/audio/audio.c index 4c3c3fd52f..853930bb48 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1614,6 +1614,8 @@ static void audio_vm_change_state_handler (void *opaque, bool running, audio_reset_timer (s); } +static const VMStateDescription vmstate_audio; + static void audio_state_init(Object *obj) { AudioState *s = AUDIO_STATE(obj); @@ -1625,6 +1627,8 @@ static void audio_state_init(Object *obj) 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_state_finalize(Object *obj) @@ -1679,6 +1683,8 @@ static void audio_state_finalize(Object *obj) qemu_del_vm_change_state_handler(s->vmse); s->vmse = NULL; } + + vmstate_unregister(NULL, &vmstate_audio, s); } static Object *get_audiodevs_root(void) @@ -1787,7 +1793,6 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) } object_unref(s); QLIST_INIT (&s->card_head); - vmstate_register_any(NULL, &vmstate_audio, s); return s; out: From f6d1f9b1b9d976b99198214f2a4f3bfb079bab8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 00:05:22 +0400 Subject: [PATCH 20/36] audio: initialize card_head during object init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/audio.c b/audio/audio.c index 853930bb48..bdaee7855f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1623,6 +1623,7 @@ static void audio_state_init(Object *obj) QLIST_INIT(&s->hw_head_out); QLIST_INIT(&s->hw_head_in); QLIST_INIT(&s->cap_head); + QLIST_INIT(&s->card_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); @@ -1792,7 +1793,6 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) goto out; } object_unref(s); - QLIST_INIT (&s->card_head); return s; out: From 914cb0878f83b5e7e9a94ffa5075fb349cd48866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 12:02:07 +0400 Subject: [PATCH 21/36] audio: remove some needless headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 3 --- audio/audio.h | 1 - audio/dbusaudio.c | 2 -- audio/dsoundaudio.c | 1 - audio/mixeng.c | 4 +++- audio/noaudio.c | 2 -- audio/wavaudio.c | 3 --- audio/wavcapture.c | 1 - 8 files changed, 3 insertions(+), 14 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index bdaee7855f..f334030d96 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -25,7 +25,6 @@ #include "qemu/osdep.h" #include "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" diff --git a/audio/audio.h b/audio/audio.h index e41c5bc55a..3be0c4f24f 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -27,7 +27,6 @@ #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); diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index b44fdd1511..908214a170 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 diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index d476e9b441..bd00c50e80 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -31,7 +31,6 @@ #define AUDIO_CAP "dsound" #include "audio_int.h" -#include "qemu/host-utils.h" #include "qemu/module.h" #include "qapi/error.h" diff --git a/audio/mixeng.c b/audio/mixeng.c index 703ee5448f..be38617e9b 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" #define AUDIO_CAP "mixeng" #include "audio_int.h" +#ifdef FLOAT_MIXENG +#include "qemu/error-report.h" +#endif /* 8 bit */ #define ENDIAN_CONVERSION natural diff --git a/audio/noaudio.c b/audio/noaudio.c index 1b60d8518a..34ff1d2a27 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" #define AUDIO_CAP "noaudio" #include "audio_int.h" diff --git a/audio/wavaudio.c b/audio/wavaudio.c index a8798a1c42..a098b20cad 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -23,10 +23,7 @@ */ #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" #define AUDIO_CAP "wav" diff --git a/audio/wavcapture.c b/audio/wavcapture.c index c60286e162..b990844d48 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,6 +1,5 @@ #include "qemu/osdep.h" #include "qemu/qemu-print.h" -#include "qapi/error.h" #include "qemu/error-report.h" #include "audio.h" From eaeafe3074050e29e3d9d8509021751366ea0b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 12:31:37 +0400 Subject: [PATCH 22/36] audio: remove AUDIO_HOST_ENDIANNESS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 6 +++--- audio/audio.h | 6 ------ audio/spiceaudio.c | 4 ++-- hw/audio/adlib.c | 2 +- hw/audio/asc.c | 2 +- hw/audio/cs4231a.c | 2 +- hw/audio/gus.c | 2 +- 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index f334030d96..18bc9188db 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -274,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) @@ -320,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) @@ -2179,7 +2179,7 @@ audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) .freq = pdo->frequency, .nchannels = pdo->channels, .fmt = pdo->format, - .endianness = AUDIO_HOST_ENDIANNESS, + .endianness = HOST_BIG_ENDIAN, }; } diff --git a/audio/audio.h b/audio/audio.h index 3be0c4f24f..0af911fd9a 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -31,12 +31,6 @@ 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; diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 7f02f7285c..7e737bff9a 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -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; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 6aae365f47..45c0a458f2 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -272,7 +272,7 @@ 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, diff --git a/hw/audio/asc.c b/hw/audio/asc.c index edd42d6d91..41472dc2e3 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -650,7 +650,7 @@ static void asc_realize(DeviceState *dev, Error **errp) 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, &as); diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 3b80a61378..0a5d614f8b 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -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; diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 45ea04bf89..d13a95eb5a 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -255,7 +255,7 @@ 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, From d2b15ae4074f8594def26f4bce0a3023042c274a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 13:56:14 +0400 Subject: [PATCH 23/36] audio: introduce AUD_set_volume_{in,out}_lr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are 2 sets of functions since the introduction of multi-channel Volume structure: AUD_set_volume_{in,out} and audio_set_volume_{in,out}. Use the AUD_ prefix for consistency with other audio.c functions. Rename the stereo function with "_lr" suffix. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 16 ++-------------- audio/audio.h | 21 ++++++++++++++++----- hw/audio/ac97.c | 4 ++-- hw/audio/asc.c | 2 +- hw/audio/hda-codec.c | 4 ++-- hw/audio/lm4549.c | 2 +- hw/audio/via-ac97.c | 2 +- hw/audio/virtio-snd.c | 4 ++-- hw/audio/wm8750.c | 12 ++++++------ hw/display/xlnx_dp.c | 2 +- hw/usb/dev-audio.c | 4 ++-- 11 files changed, 36 insertions(+), 37 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 18bc9188db..8723f4e66e 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1949,13 +1949,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; @@ -1971,13 +1965,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; diff --git a/audio/audio.h b/audio/audio.h index 0af911fd9a..c8515afcd2 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -119,9 +119,6 @@ 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; @@ -129,8 +126,22 @@ typedef struct Volume { 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); +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 ( QEMUSoundCard *card, diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index 6b9013ebb8..c3e5f9c8bb 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -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) diff --git a/hw/audio/asc.c b/hw/audio/asc.c index 41472dc2e3..991316e984 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -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; } } diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index 66edad280f..cc87557954 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -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); } } diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index a4a77c8dc6..dccbf56068 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -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/via-ac97.c b/hw/audio/via-ac97.c index d5231e1cf2..62341e5600 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) diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index eca3319e59..88777977a9 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -463,7 +463,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) 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, @@ -471,7 +471,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) 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); diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 2846b55fe2..7a36c4bd3f 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -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])); } diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index ef73e1815f..882ae3c4b4 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -1334,7 +1334,7 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp) 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); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 26af709f31..f59e5a53f0 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -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; @@ -981,7 +981,7 @@ static void usb_audio_reinit(USBDevice *dev, unsigned channels) s->out.voice = AUD_open_out(&s->card, 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); } From 04536d704584127a971607c675516271c6eb4502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 14:43:36 +0400 Subject: [PATCH 24/36] audio/replay: fix type punning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.h | 6 ++++-- audio/mixeng.c | 6 ++---- audio/mixeng.h | 1 - include/system/replay.h | 3 ++- replay/replay-audio.c | 2 +- replay/stubs-system.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/audio/audio.h b/audio/audio.h index c8515afcd2..61ff900b7e 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -171,9 +171,11 @@ int wav_start_capture(AudioState *state, CaptureState *s, const char *path, void audio_cleanup(void); -void audio_sample_to_uint64(const void *samples, int pos, +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(void *samples, int pos, +void audio_sample_from_uint64(st_sample *sample, int pos, uint64_t left, uint64_t right); void audio_add_audiodev(Audiodev *audio); diff --git a/audio/mixeng.c b/audio/mixeng.c index be38617e9b..af9ec3d4d2 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -404,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 @@ -412,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 @@ -427,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/include/system/replay.h b/include/system/replay.h index 1c87c97fdd..1e63c0784c 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 "audio/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/replay/replay-audio.c b/replay/replay-audio.c index ed2ba2164b..3413801062 100644 --- a/replay/replay-audio.c +++ b/replay/replay-audio.c @@ -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) From 6fcd22cfdb74bbe776513dcdedaf8557c860a0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 14:06:08 +0400 Subject: [PATCH 25/36] audio: move internal APIs to audio_int.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some check-patch issues while at it. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio-hmp-cmds.c | 2 +- audio/audio.h | 21 --------------------- audio/audio_int.h | 24 ++++++++++++++++++++++++ audio/wavcapture.c | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c index 8774c09f18..819f8fa9d8 100644 --- a/audio/audio-hmp-cmds.c +++ b/audio/audio-hmp-cmds.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "audio/audio.h" +#include "audio_int.h" #include "monitor/hmp.h" #include "monitor/monitor.h" #include "qapi/error.h" diff --git a/audio/audio.h b/audio/audio.h index 61ff900b7e..c0cad7d976 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -38,15 +38,6 @@ typedef struct audsettings { 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 @@ -88,9 +79,6 @@ 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( @@ -160,15 +148,6 @@ 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); typedef struct st_sample st_sample; diff --git a/audio/audio_int.h b/audio/audio_int.h index 4a4d69f2bf..d1badbf235 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -29,12 +29,19 @@ #define FLOAT_MIXENG /* #define RECIPROCAL */ #endif +#include "audio.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 { @@ -187,6 +194,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(AudioState *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); diff --git a/audio/wavcapture.c b/audio/wavcapture.c index b990844d48..0fbc695d23 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include "qemu/qemu-print.h" #include "qemu/error-report.h" -#include "audio.h" +#include "audio_int.h" typedef struct { FILE *f; From 7d75c12ad113a71a8440f706121f53abfb907582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 16:35:28 +0400 Subject: [PATCH 26/36] audio: rename AudioState -> AudioBackend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Naming is hard. But in general in QEMU, a host "backend" is the term used to fullfill the request made by the device or frontend. AudioBackend will become an abstract base class in a follow-up series. Currently the frontend is QEMUSoundCard, we are going to drop that next. Note that "audiodev" is the corresponding QAPI type name (or configuration). Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/alsaaudio.c | 2 +- audio/audio-hmp-cmds.c | 2 +- audio/audio.c | 90 ++++++++++++++++---------------- audio/audio.h | 16 +++--- audio/audio_int.h | 20 +++---- audio/audio_template.h | 20 +++---- audio/dbusaudio.c | 8 +-- audio/ossaudio.c | 4 +- audio/wavcapture.c | 2 +- hw/audio/pcspk.c | 2 +- hw/core/machine.c | 2 +- hw/core/qdev-properties-system.c | 6 +-- ui/dbus.c | 8 +-- ui/vnc.c | 10 ++-- ui/vnc.h | 2 +- 15 files changed, 97 insertions(+), 97 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 9b6c01c0ef..797cb478e6 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -41,7 +41,7 @@ struct pollhlp { struct pollfd *pfds; int count; int mask; - AudioState *s; + AudioBackend *s; }; typedef struct ALSAVoiceOut { diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c index 819f8fa9d8..1e56af21ab 100644 --- a/audio/audio-hmp-cmds.c +++ b/audio/audio-hmp-cmds.c @@ -67,7 +67,7 @@ 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); if (!as) { error_report_err(local_err); diff --git a/audio/audio.c b/audio/audio.c index 8723f4e66e..8044d55c5c 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -99,7 +99,7 @@ static audio_driver *audio_driver_lookup(const char *name) return NULL; } -static AudioState *default_audio_state; +static AudioBackend *default_audio_be; const struct mixeng_volume nominal_volume = { .mute = 0, @@ -380,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; @@ -460,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); @@ -798,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; @@ -816,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, @@ -838,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; @@ -921,7 +921,7 @@ 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; @@ -969,7 +969,7 @@ 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) { @@ -1137,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; @@ -1291,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; @@ -1339,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; @@ -1386,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); @@ -1559,7 +1559,7 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) return total; } -static bool audio_driver_init(AudioState *s, struct audio_driver *drv, +static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv, Audiodev *dev, Error **errp) { s->drv_opaque = drv->init(dev, errp); @@ -1592,7 +1592,7 @@ static bool audio_driver_init(AudioState *s, struct audio_driver *drv, 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; @@ -1613,9 +1613,9 @@ static void audio_vm_change_state_handler (void *opaque, bool running, static const VMStateDescription vmstate_audio; -static void audio_state_init(Object *obj) +static void audio_be_init(Object *obj) { - AudioState *s = AUDIO_STATE(obj); + AudioBackend *s = AUDIO_BACKEND(obj); QLIST_INIT(&s->hw_head_out); QLIST_INIT(&s->hw_head_in); @@ -1629,9 +1629,9 @@ static void audio_state_init(Object *obj) vmstate_register_any(NULL, &vmstate_audio, s); } -static void audio_state_finalize(Object *obj) +static void audio_be_finalize(Object *obj) { - AudioState *s = AUDIO_STATE(obj); + AudioBackend *s = AUDIO_BACKEND(obj); HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; @@ -1692,7 +1692,7 @@ static Object *get_audiodevs_root(void) void audio_cleanup(void) { - default_audio_state = NULL; + default_audio_be = NULL; object_unparent(get_audiodevs_root()); } @@ -1743,14 +1743,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) { int done = 0; const char *drvname; - AudioState *s; + AudioBackend *s; struct audio_driver *driver; - s = AUDIO_STATE(object_new(TYPE_AUDIO_STATE)); + s = AUDIO_BACKEND(object_new(TYPE_AUDIO_BACKEND)); if (dev) { /* -audiodev option */ @@ -1766,7 +1766,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) { @@ -1797,11 +1797,11 @@ out: 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); @@ -1809,21 +1809,21 @@ 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) { - if (!card->state) { - card->state = audio_get_default_audio_state(errp); - if (!card->state) { + if (!card->be) { + card->be = audio_get_default_audio_be(errp); + if (!card->be) { return false; } } card->name = g_strdup (name); memset (&card->entries, 0, sizeof (card->entries)); - QLIST_INSERT_HEAD(&card->state->card_head, card, entries); + QLIST_INSERT_HEAD(&card->be->card_head, card, entries); return true; } @@ -1837,7 +1837,7 @@ void AUD_remove_card (QEMUSoundCard *card) 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 @@ -2220,7 +2220,7 @@ 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) { Object *obj = object_resolve_path_component(get_audiodevs_root(), name); @@ -2228,15 +2228,15 @@ AudioState *audio_state_by_name(const char *name, Error **errp) error_setg(errp, "audiodev '%s' not found", name); return NULL; } else { - return AUDIO_STATE(obj); + return AUDIO_BACKEND(obj); } } const char *audio_get_id(QEMUSoundCard *card) { - if (card->state) { - assert(card->state->dev); - return card->state->dev->id; + if (card->be) { + assert(card->be->dev); + return card->be->dev->id; } else { return ""; } @@ -2305,19 +2305,19 @@ AudiodevList *qmp_query_audiodevs(Error **errp) return ret; } -static const TypeInfo audio_state_info = { - .name = TYPE_AUDIO_STATE, +static const TypeInfo audio_be_info = { + .name = TYPE_AUDIO_BACKEND, .parent = TYPE_OBJECT, - .instance_size = sizeof(AudioState), - .instance_init = audio_state_init, - .instance_finalize = audio_state_finalize, + .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(AudioStateClass), + .class_size = sizeof(AudioBackendClass), }; static void register_types(void) { - type_register_static(&audio_state_info); + type_register_static(&audio_be_info); } type_init(register_types); diff --git a/audio/audio.h b/audio/audio.h index c0cad7d976..1d56f111ea 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -64,14 +64,14 @@ typedef struct SWVoiceOut SWVoiceOut; typedef struct CaptureVoiceOut CaptureVoiceOut; typedef struct SWVoiceIn SWVoiceIn; -struct AudioStateClass { +struct AudioBackendClass { ObjectClass parent_class; }; -typedef struct AudioState AudioState; +typedef struct AudioBackend AudioBackend; typedef struct QEMUSoundCard { char *name; - AudioState *state; + AudioBackend *be; QLIST_ENTRY (QEMUSoundCard) entries; } QEMUSoundCard; @@ -82,7 +82,7 @@ typedef struct QEMUAudioTimeStamp { bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp); void AUD_remove_card (QEMUSoundCard *card); CaptureVoiceOut *AUD_add_capture( - AudioState *s, + AudioBackend *s, struct audsettings *as, struct audio_capture_ops *ops, void *opaque @@ -164,14 +164,14 @@ 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); +AudioBackend *audio_be_by_name(const char *name, Error **errp); +AudioBackend *audio_get_default_audio_be(Error **errp); const char *audio_get_id(QEMUSoundCard *card); #define DEFINE_AUDIO_PROPERTIES(_s, _f) \ DEFINE_PROP_AUDIODEV("audiodev", _s, _f) -#define TYPE_AUDIO_STATE "audio-state" -OBJECT_DECLARE_TYPE(AudioState, AudioStateClass, AUDIO_STATE) +#define TYPE_AUDIO_BACKEND "audio-backend" +OBJECT_DECLARE_TYPE(AudioBackend, AudioBackendClass, AUDIO_BACKEND) #endif /* QEMU_AUDIO_H */ diff --git a/audio/audio_int.h b/audio/audio_int.h index d1badbf235..338af38fd1 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -60,7 +60,7 @@ struct audio_pcm_info { int swap_endianness; }; -typedef struct AudioState AudioState; +typedef struct AudioBackend AudioBackend; typedef struct SWVoiceCap SWVoiceCap; typedef struct STSampleBuffer { @@ -69,7 +69,7 @@ typedef struct STSampleBuffer { } STSampleBuffer; typedef struct HWVoiceOut { - AudioState *s; + AudioBackend *s; int enabled; int poll_mode; int pending_disable; @@ -90,7 +90,7 @@ typedef struct HWVoiceOut { } HWVoiceOut; typedef struct HWVoiceIn { - AudioState *s; + AudioBackend *s; int enabled; int poll_mode; struct audio_pcm_info info; @@ -112,7 +112,7 @@ typedef struct HWVoiceIn { struct SWVoiceOut { QEMUSoundCard *card; - AudioState *s; + AudioBackend *s; struct audio_pcm_info info; t_sample *conv; STSampleBuffer resample_buf; @@ -129,7 +129,7 @@ struct SWVoiceOut { struct SWVoiceIn { QEMUSoundCard *card; - AudioState *s; + AudioBackend *s; int active; struct audio_pcm_info info; void *rate; @@ -150,7 +150,7 @@ struct audio_driver { void *(*init) (Audiodev *, Error **); void (*fini) (void *); #ifdef CONFIG_GIO - void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); + void (*set_dbus_server)(AudioBackend *s, GDBusObjectManagerServer *manager, bool p2p); #endif struct audio_pcm_ops *pcm_ops; int max_voices_out; @@ -208,7 +208,7 @@ static inline void *advance(void *p, size_t incr) return (uint8_t *)p + incr; } -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); void audio_generic_run_buffer_in(HWVoiceIn *hw); @@ -240,7 +240,7 @@ struct SWVoiceCap { QLIST_ENTRY (SWVoiceCap) entries; }; -typedef struct AudioState { +typedef struct AudioBackend { Object parent; struct audio_driver *drv; @@ -260,7 +260,7 @@ typedef struct AudioState { bool timer_running; uint64_t timer_last; VMChangeStateEntry *vmse; -} AudioState; +} AudioBackend; extern const struct mixeng_volume nominal_volume; @@ -273,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..b3c10a0709 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); @@ -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 ) @@ -494,7 +494,7 @@ SW *glue (AUD_open_, TYPE) ( struct audsettings *as ) { - AudioState *s; + AudioBackend *s; AudiodevPerDirectionOptions *pdo; if (audio_bug(__func__, !card || !name || !callback_fn || !as)) { @@ -503,7 +503,7 @@ SW *glue (AUD_open_, TYPE) ( goto fail; } - s = card->state; + s = card->be; pdo = glue(audio_get_pdo_, TYPE)(s->dev); ldebug ("open %s, freq %d, nchannels %d, fmt %d\n", diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 908214a170..49cef38e3e 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -458,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, @@ -615,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, @@ -631,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, @@ -646,7 +646,7 @@ dbus_audio_register_in_listener(AudioState *s, } static void -dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p) +dbus_audio_set_server(AudioBackend *s, GDBusObjectManagerServer *server, bool p2p) { DBusAudio *da = s->drv_opaque; diff --git a/audio/ossaudio.c b/audio/ossaudio.c index c5858284a1..4a549b26a2 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -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"); } diff --git a/audio/wavcapture.c b/audio/wavcapture.c index 0fbc695d23..b33a38ff45 100644 --- a/audio/wavcapture.c +++ b/audio/wavcapture.c @@ -103,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/hw/audio/pcspk.c b/hw/audio/pcspk.c index 48ef830292..e0b0949918 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -196,7 +196,7 @@ 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->card.be && AUD_register_card(s_spk, &s->card, errp)) { pcspk_audio_init(s); } } diff --git a/hw/core/machine.c b/hw/core/machine.c index cd63803000..28d2833c5d 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -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..4d815684d1 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -499,16 +499,16 @@ static void set_audiodev(Object *obj, Visitor *v, const char* name, { const Property *prop = opaque; QEMUSoundCard *card = object_field_prop_ptr(obj, prop); - AudioState *state; + 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; + card->be = state; } } diff --git a/ui/dbus.c b/ui/dbus.c index dd0336702d..84cff47ec7 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -220,16 +220,16 @@ 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) { return; } - if (!g_str_equal(audio_state->drv->name, "dbus")) { + if (!g_str_equal(audio_be->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); + audio_be->drv->set_dbus_server(audio_be, 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..e2137c5ed1 100644 --- a/ui/vnc.h +++ b/ui/vnc.h @@ -184,7 +184,7 @@ struct VncDisplay VncDisplaySASL sasl; #endif - AudioState *audio_state; + AudioBackend *audio_be; VMChangeStateEntry *vmstate_handler_entry; }; From 9628ad8a6efbf097046f84898a2409ac357b22a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 21 Oct 2025 17:07:43 +0400 Subject: [PATCH 27/36] audio: remove QEMUSoundCard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no clear need for this extra intermediary structure between the audio backend and its user. Signed-off-by: Marc-André Lureau Suggested-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 29 ++++++++++------------------- audio/audio.h | 21 ++++++++------------- audio/audio_int.h | 3 --- audio/audio_template.h | 22 ++++++++++------------ hw/audio/ac97.c | 25 ++++++++++++------------- hw/audio/adlib.c | 9 ++++----- hw/audio/asc.c | 9 +++------ hw/audio/cs4231a.c | 8 ++++---- hw/audio/es1370.c | 23 +++++++++++------------ hw/audio/gus.c | 9 ++++----- hw/audio/hda-codec.c | 15 +++++++-------- hw/audio/lm4549.c | 8 ++++---- hw/audio/lm4549.h | 2 +- hw/audio/pcspk.c | 9 +++++---- hw/audio/pl041.c | 2 +- hw/audio/sb16.c | 16 ++++++++-------- hw/audio/via-ac97.c | 9 ++++----- hw/audio/virtio-snd.c | 13 ++++++------- hw/audio/wm8750.c | 23 +++++++++++------------ hw/core/qdev-properties-system.c | 11 +++++------ hw/display/xlnx_dp.c | 6 +++--- hw/usb/dev-audio.c | 11 +++++------ include/hw/audio/asc.h | 2 +- include/hw/audio/virtio-snd.h | 2 +- include/hw/display/xlnx_dp.h | 2 +- include/hw/isa/vt82c686.h | 2 +- include/hw/qdev-properties-system.h | 2 +- 27 files changed, 131 insertions(+), 162 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 8044d55c5c..d9a5695eb8 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1620,7 +1620,6 @@ static void audio_be_init(Object *obj) QLIST_INIT(&s->hw_head_out); QLIST_INIT(&s->hw_head_in); QLIST_INIT(&s->cap_head); - QLIST_INIT(&s->card_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); @@ -1812,28 +1811,20 @@ AudioBackend *audio_get_default_audio_be(Error **errp) 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->be) { - card->be = audio_get_default_audio_be(errp); - if (!card->be) { + 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->be->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( @@ -2232,11 +2223,11 @@ AudioBackend *audio_be_by_name(const char *name, Error **errp) } } -const char *audio_get_id(QEMUSoundCard *card) +const char *audio_be_get_id(AudioBackend *be) { - if (card->be) { - assert(card->be->dev); - return card->be->dev->id; + if (be) { + assert(be->dev); + return be->dev->id; } else { return ""; } diff --git a/audio/audio.h b/audio/audio.h index 1d56f111ea..0a016bdabc 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -69,18 +69,13 @@ struct AudioBackendClass { }; typedef struct AudioBackend AudioBackend; -typedef struct QEMUSoundCard { - char *name; - AudioBackend *be; - QLIST_ENTRY (QEMUSoundCard) entries; -} QEMUSoundCard; typedef struct QEMUAudioTimeStamp { uint64_t old_ts; } QEMUAudioTimeStamp; -bool AUD_register_card (const char *name, QEMUSoundCard *card, Error **errp); -void AUD_remove_card (QEMUSoundCard *card); +bool AUD_backend_check(AudioBackend **be, Error **errp); + CaptureVoiceOut *AUD_add_capture( AudioBackend *s, struct audsettings *as, @@ -90,7 +85,7 @@ CaptureVoiceOut *AUD_add_capture( void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); SWVoiceOut *AUD_open_out ( - QEMUSoundCard *card, + AudioBackend *be, SWVoiceOut *sw, const char *name, void *callback_opaque, @@ -98,7 +93,7 @@ SWVoiceOut *AUD_open_out ( struct audsettings *settings ); -void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw); +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, int on); @@ -131,8 +126,8 @@ AUD_set_volume_in_lr(SWVoiceIn *sw, bool mut, uint8_t lvol, uint8_t rvol) { }); } -SWVoiceIn *AUD_open_in ( - QEMUSoundCard *card, +SWVoiceIn *AUD_open_in( + AudioBackend *be, SWVoiceIn *sw, const char *name, void *callback_opaque, @@ -140,7 +135,7 @@ SWVoiceIn *AUD_open_in ( struct audsettings *settings ); -void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw); +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, int on); int AUD_is_active_in (SWVoiceIn *sw); @@ -166,7 +161,7 @@ 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_get_id(QEMUSoundCard *card); +const char *audio_be_get_id(AudioBackend *be); #define DEFINE_AUDIO_PROPERTIES(_s, _f) \ DEFINE_PROP_AUDIODEV("audiodev", _s, _f) diff --git a/audio/audio_int.h b/audio/audio_int.h index 338af38fd1..c4453b3a29 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -111,7 +111,6 @@ typedef struct HWVoiceIn { } HWVoiceIn; struct SWVoiceOut { - QEMUSoundCard *card; AudioBackend *s; struct audio_pcm_info info; t_sample *conv; @@ -128,7 +127,6 @@ struct SWVoiceOut { }; struct SWVoiceIn { - QEMUSoundCard *card; AudioBackend *s; int active; struct audio_pcm_info info; @@ -248,7 +246,6 @@ typedef struct AudioBackend { 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; diff --git a/audio/audio_template.h b/audio/audio_template.h index b3c10a0709..d621008f38 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -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 ) { - AudioBackend *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->be; 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,7 +560,7 @@ SW *glue (AUD_open_, TYPE) ( return sw; fail: - glue (AUD_close_, TYPE) (card, sw); + glue(AUD_close_, TYPE)(be, sw); return NULL; } diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index c3e5f9c8bb..a91bf52b95 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -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; } @@ -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) diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 45c0a458f2..4e6c80b8e0 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -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; } @@ -275,7 +274,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) 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), }; diff --git a/hw/audio/asc.c b/hw/audio/asc.c index 991316e984..5c3f6c8f86 100644 --- a/hw/audio/asc.c +++ b/hw/audio/asc.c @@ -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,7 +641,7 @@ 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; } @@ -652,10 +650,9 @@ static void asc_realize(DeviceState *dev, Error **errp) as.fmt = AUDIO_FORMAT_U8; 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 0a5d614f8b..ec9643b817 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -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]; @@ -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), diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 721c02be0a..0628f03310 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -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) diff --git a/hw/audio/gus.c b/hw/audio/gus.c index d13a95eb5a..d253329021 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -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; } @@ -258,7 +258,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp) 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), diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index cc87557954..f7ae2aa1fd 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -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]; @@ -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/lm4549.c b/hw/audio/lm4549.c index dccbf56068..c51ec0e66f 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -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, diff --git a/hw/audio/lm4549.h b/hw/audio/lm4549.h index 61c3ab12dd..1d858e2a04 100644 --- a/hw/audio/lm4549.h +++ b/hw/audio/lm4549.h @@ -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/pcspk.c b/hw/audio/pcspk.c index e0b0949918..a41f5b11f0 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -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.be && 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 e86aafd488..8109d124d1 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -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), diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index 62341e5600..019d296853 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -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.c b/hw/audio/virtio-snd.c index 88777977a9..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,7 +457,7 @@ 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, @@ -465,7 +465,7 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) &as); 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, @@ -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 7a36c4bd3f..d399c335c3 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -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; @@ -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/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 4d815684d1..24c835c5f4 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -487,18 +487,17 @@ 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); + AudioBackend **be = object_field_prop_ptr(obj, prop); AudioBackend *state; g_autofree char *str = NULL; @@ -508,7 +507,7 @@ static void set_audiodev(Object *obj, Visitor *v, const char* name, state = audio_be_by_name(str, errp); if (state) { - card->be = state; + *be = state; } } diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index 882ae3c4b4..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,7 +1328,7 @@ 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, @@ -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/usb/dev-audio.c b/hw/usb/dev-audio.c index f59e5a53f0..c8e032ab64 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -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 { @@ -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,7 +978,7 @@ 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); 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..a60c2f597c 100644 --- a/include/hw/audio/asc.h +++ b/include/hw/audio/asc.h @@ -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/virtio-snd.h b/include/hw/audio/virtio-snd.h index 8dafedb276..0ad80bc9be 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/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..802a1427c9 100644 --- a/include/hw/display/xlnx_dp.h +++ b/include/hw/display/xlnx_dp.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..48c412ce81 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -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) From 2d18978b7fdd4b226fe9bef1a8df53c7dfede3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 27 Oct 2025 18:31:32 +0400 Subject: [PATCH 28/36] audio/dbus: use a helper function to set the backend dbus server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 17 +++++++++++++++++ audio/audio.h | 9 +++++++++ audio/audio_int.h | 5 ++++- audio/dbusaudio.c | 9 +++++++-- ui/dbus.c | 8 +------- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index d9a5695eb8..3229829bef 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2223,6 +2223,23 @@ AudioBackend *audio_be_by_name(const char *name, Error **errp) } } +#ifdef CONFIG_GIO +bool audio_be_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp) +{ + 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) { diff --git a/audio/audio.h b/audio/audio.h index 0a016bdabc..08753f621a 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -28,6 +28,9 @@ #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); @@ -162,6 +165,12 @@ 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) diff --git a/audio/audio_int.h b/audio/audio_int.h index c4453b3a29..d66f7aac32 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -148,7 +148,10 @@ struct audio_driver { void *(*init) (Audiodev *, Error **); void (*fini) (void *); #ifdef CONFIG_GIO - void (*set_dbus_server)(AudioBackend *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; diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 49cef38e3e..c97c34b486 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -645,8 +645,11 @@ dbus_audio_register_in_listener(AudioBackend *s, arg_listener, false); } -static void -dbus_audio_set_server(AudioBackend *s, GDBusObjectManagerServer *server, bool p2p) +static bool +dbus_audio_set_server(AudioBackend *s, + GDBusObjectManagerServer *server, + bool p2p, + Error **errp) { DBusAudio *da = s->drv_opaque; @@ -669,6 +672,8 @@ dbus_audio_set_server(AudioBackend *s, GDBusObjectManagerServer *server, bool p2 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 = { diff --git a/ui/dbus.c b/ui/dbus.c index 84cff47ec7..fbe108af1e 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -221,15 +221,9 @@ dbus_display_complete(UserCreatable *uc, Error **errp) if (dd->audiodev && *dd->audiodev) { AudioBackend *audio_be = audio_be_by_name(dd->audiodev, errp); - if (!audio_be) { + if (!audio_be || !audio_be_set_dbus_server(audio_be, dd->server, dd->p2p, errp)) { return; } - if (!g_str_equal(audio_be->drv->name, "dbus")) { - error_setg(errp, "Audiodev '%s' is not compatible with DBus", - dd->audiodev); - return; - } - audio_be->drv->set_dbus_server(audio_be, dd->server, dd->p2p); } consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); From 1e4ebc895ac41eddc67b123121aca2bd58e1d0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 17:30:41 +0400 Subject: [PATCH 29/36] audio: move audio.h under include/qemu/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Reviewed-by: Akihiko Odaki --- MAINTAINERS | 1 + audio/alsaaudio.c | 2 +- audio/audio.c | 2 +- audio/audio_int.h | 2 +- audio/audio_win_int.c | 2 +- audio/coreaudio.m | 2 +- audio/dbusaudio.c | 2 +- audio/dsoundaudio.c | 2 +- audio/jackaudio.c | 2 +- audio/mixeng.c | 2 +- audio/noaudio.c | 2 +- audio/ossaudio.c | 2 +- audio/paaudio.c | 2 +- audio/pwaudio.c | 2 +- audio/sdlaudio.c | 2 +- audio/sndioaudio.c | 2 +- audio/spiceaudio.c | 2 +- audio/wavaudio.c | 2 +- hw/arm/integratorcp.c | 2 +- hw/arm/musicpal.c | 2 +- hw/arm/realview.c | 2 +- hw/arm/versatilepb.c | 2 +- hw/arm/vexpress.c | 2 +- hw/arm/xlnx-zcu102.c | 2 +- hw/audio/ac97.c | 2 +- hw/audio/adlib.c | 2 +- hw/audio/asc.c | 2 +- hw/audio/cs4231a.c | 2 +- hw/audio/es1370.c | 2 +- hw/audio/gus.c | 2 +- hw/audio/hda-codec.c | 2 +- hw/audio/lm4549.c | 2 +- hw/audio/lm4549.h | 2 +- hw/audio/marvell_88w8618.c | 2 +- hw/audio/pcspk.c | 2 +- hw/audio/sb16.c | 2 +- hw/audio/wm8750.c | 2 +- hw/core/machine.c | 2 +- hw/core/qdev-properties-system.c | 2 +- hw/ppc/prep.c | 2 +- hw/usb/dev-audio.c | 2 +- include/hw/audio/asc.h | 2 +- include/hw/audio/virtio-snd.h | 2 +- include/hw/display/xlnx_dp.h | 2 +- include/hw/isa/vt82c686.h | 2 +- {audio => include/qemu}/audio.h | 0 include/system/replay.h | 2 +- replay/replay-audio.c | 2 +- scripts/codeconverter/codeconverter/test_regexps.py | 2 +- system/runstate.c | 2 +- system/vl.c | 2 +- ui/dbus.c | 3 +-- ui/vnc.h | 2 +- 53 files changed, 52 insertions(+), 52 deletions(-) rename {audio => include/qemu}/audio.h (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 64491c800c..24323e8800 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2977,6 +2977,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 797cb478e6..d1e4817081 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" diff --git a/audio/audio.c b/audio/audio.c index 3229829bef..19499abe16 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -23,7 +23,7 @@ */ #include "qemu/osdep.h" -#include "audio.h" +#include "qemu/audio.h" #include "migration/vmstate.h" #include "qemu/timer.h" #include "qapi/error.h" diff --git a/audio/audio_int.h b/audio/audio_int.h index d66f7aac32..8d4f4ca8fc 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -29,7 +29,7 @@ #define FLOAT_MIXENG /* #define RECIPROCAL */ #endif -#include "audio.h" +#include "qemu/audio.h" #include "mixeng.h" #ifdef CONFIG_GIO 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..8b3cd6db16 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" diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index c97c34b486..157d36428e 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -35,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" diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index bd00c50e80..8b773ded21 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -27,7 +27,7 @@ */ #include "qemu/osdep.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "dsound" #include "audio_int.h" diff --git a/audio/jackaudio.c b/audio/jackaudio.c index 974a3caad3..28face9989 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" diff --git a/audio/mixeng.c b/audio/mixeng.c index af9ec3d4d2..e63c76e021 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -24,7 +24,7 @@ */ #include "qemu/osdep.h" #include "qemu/bswap.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "mixeng" #include "audio_int.h" diff --git a/audio/noaudio.c b/audio/noaudio.c index 34ff1d2a27..b136b74e26 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "noaudio" #include "audio_int.h" diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 4a549b26a2..5ba91f6793 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" diff --git a/audio/paaudio.c b/audio/paaudio.c index 93030f3fc8..8eb80ede45 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 diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 8e13b58286..8f6c0900c8 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 diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 641357e5ee..4ef73c8dfb 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__ diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c index 8eb35e1e53..f4f53b1c6f 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" diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 7e737bff9a..77ba89ffaa 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 diff --git a/audio/wavaudio.c b/audio/wavaudio.c index a098b20cad..4d9c921305 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" -#include "audio.h" +#include "qemu/audio.h" #define AUDIO_CAP "wav" #include "audio_int.h" diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index b1d8fbd470..81ed051b98 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -26,7 +26,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 329b162eb2..6032301bb6 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -36,7 +36,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 5c9050490b..892bdc8db2 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -29,7 +29,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 5cf1a70d10..cba77864e8 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -25,7 +25,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 60cd375fe7..d26a07f0f5 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -44,7 +44,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 14b6641a71..4ed346a88d 100644 --- a/hw/arm/xlnx-zcu102.c +++ b/hw/arm/xlnx-zcu102.c @@ -25,7 +25,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 a91bf52b95..be7a39377f 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/pci/pci_device.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 4e6c80b8e0..19d3a5f128 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -26,7 +26,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" #include "qemu/error-report.h" diff --git a/hw/audio/asc.c b/hw/audio/asc.c index 5c3f6c8f86..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" diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index ec9643b817..98fdbc5b72 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index 0628f03310..9873ffadab 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/pci/pci_device.h" #include "migration/vmstate.h" #include "qemu/cutils.h" diff --git a/hw/audio/gus.c b/hw/audio/gus.c index d253329021..68f89e994c 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -26,7 +26,7 @@ #include "qapi/error.h" #include "qemu/module.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index f7ae2aa1fd..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" diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index c51ec0e66f..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" diff --git a/hw/audio/lm4549.h b/hw/audio/lm4549.h index 1d858e2a04..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); 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/pcspk.c b/hw/audio/pcspk.c index a41f5b11f0..916c56fa4c 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "hw/isa/isa.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "qemu/module.h" #include "qemu/timer.h" #include "qemu/error-report.h" diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 8109d124d1..1e3c4caf5e 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/irq.h" #include "hw/isa/isa.h" #include "hw/qdev-properties.h" diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index d399c335c3..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 diff --git a/hw/core/machine.c b/hw/core/machine.c index 28d2833c5d..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" }, diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 24c835c5f4..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" 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 c8e032ab64..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); diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h index a60c2f597c..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 diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index 0ad80bc9be..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" diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h index 802a1427c9..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" diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index 48c412ce81..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" diff --git a/audio/audio.h b/include/qemu/audio.h similarity index 100% rename from audio/audio.h rename to include/qemu/audio.h diff --git a/include/system/replay.h b/include/system/replay.h index 1e63c0784c..68f91bdfbf 100644 --- a/include/system/replay.h +++ b/include/system/replay.h @@ -16,7 +16,7 @@ #include "qapi/qapi-types-run-state.h" #include "qapi/qapi-types-ui.h" #include "block/aio.h" -#include "audio/audio.h" +#include "qemu/audio.h" /* replay clock kinds */ enum ReplayClockKind { diff --git a/replay/replay-audio.c b/replay/replay-audio.c index 3413801062..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) { diff --git a/scripts/codeconverter/codeconverter/test_regexps.py b/scripts/codeconverter/codeconverter/test_regexps.py index fe7354b473..b00e9ef15b 100644 --- a/scripts/codeconverter/codeconverter/test_regexps.py +++ b/scripts/codeconverter/codeconverter/test_regexps.py @@ -265,7 +265,7 @@ def test_initial_includes(): #include "qemu/osdep.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "hw/pci/pci.h" #include "migration/vmstate.h" #include "qemu/module.h" 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 dc2ea4c298..29f5389151 100644 --- a/system/vl.c +++ b/system/vl.c @@ -87,7 +87,7 @@ #include "system/tpm.h" #include "system/dma.h" #include "hw/audio/model.h" -#include "audio/audio.h" +#include "qemu/audio.h" #include "system/cpus.h" #include "system/cpu-timers.h" #include "exec/icount.h" diff --git a/ui/dbus.c b/ui/dbus.c index fbe108af1e..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" diff --git a/ui/vnc.h b/ui/vnc.h index e2137c5ed1..4d8363ebf3 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.h" #include "qemu/bitmap.h" #include "crypto/tlssession.h" #include "qemu/buffer.h" From 98e901ff9b6dced79d12d6f73d170aa584947294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Oct 2025 18:19:12 +0400 Subject: [PATCH 30/36] audio: remove dependency on spice header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is no longer required. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audio/meson.build b/audio/meson.build index 59f0a431d5..37789437fb 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,5 +1,5 @@ -system_ss.add([spice_headers, files('audio.c')]) system_ss.add(files( + 'audio.c', 'audio-hmp-cmds.c', 'mixeng.c', 'noaudio.c', From 690c82a27168b4e23a5dad6159ccd899a6ad2990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 15 Oct 2025 10:40:01 +0400 Subject: [PATCH 31/36] audio: cleanup, use bool for booleans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use slightly better types for the job. Fix some checkpatch issues. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- audio/audio.c | 30 +++++++++++++++--------------- audio/audio_int.h | 12 ++++++------ audio/audio_template.h | 6 +++--- include/qemu/audio.h | 8 ++++---- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 19499abe16..86e674410a 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -405,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; @@ -419,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; } } @@ -475,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); @@ -911,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; @@ -928,7 +928,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) 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); @@ -959,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,7 +974,7 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) 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); @@ -993,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); } @@ -1152,8 +1152,8 @@ static void audio_run_out(AudioBackend *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); } @@ -1206,13 +1206,13 @@ static void audio_run_out(AudioBackend *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; @@ -1257,7 +1257,7 @@ static void audio_run_out(AudioBackend *s) sw->total_hw_samples_mixed -= played; if (!sw->total_hw_samples_mixed) { - sw->empty = 1; + sw->empty = true; } } } diff --git a/audio/audio_int.h b/audio/audio_int.h index 8d4f4ca8fc..df13a466e4 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -70,9 +70,9 @@ typedef struct STSampleBuffer { typedef struct HWVoiceOut { AudioBackend *s; - int enabled; + bool enabled; int poll_mode; - int pending_disable; + bool pending_disable; struct audio_pcm_info info; f_sample *clip; @@ -91,7 +91,7 @@ typedef struct HWVoiceOut { typedef struct HWVoiceIn { AudioBackend *s; - int enabled; + bool enabled; int poll_mode; struct audio_pcm_info info; @@ -117,8 +117,8 @@ struct SWVoiceOut { 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; @@ -128,7 +128,7 @@ struct SWVoiceOut { struct SWVoiceIn { AudioBackend *s; - int active; + bool active; struct audio_pcm_info info; void *rate; size_t total_hw_samples_acquired; diff --git a/audio/audio_template.h b/audio/audio_template.h index d621008f38..7a8c431f2d 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -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) { @@ -564,7 +564,7 @@ SW *glue (AUD_open_, TYPE) ( 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/include/qemu/audio.h b/include/qemu/audio.h index 08753f621a..0f224810c7 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -99,8 +99,8 @@ SWVoiceOut *AUD_open_out ( 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, int on); -int AUD_is_active_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); @@ -140,8 +140,8 @@ SWVoiceIn *AUD_open_in( 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, int on); -int AUD_is_active_in (SWVoiceIn *sw); +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); From 9cba1ce9360d53adaf48dffa4c5a3bbfcb59f333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 16 Oct 2025 17:46:07 +0400 Subject: [PATCH 32/36] audio: move capture API to own header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For modularity/clarity reasons, move the capture API in a specific header. The current audio/ header license is MIT. Signed-off-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé --- MAINTAINERS | 2 +- audio/audio_int.h | 1 + include/qemu/audio-capture.h | 43 ++++++++++++++++++++++++++++++++++++ include/qemu/audio.h | 31 -------------------------- ui/vnc.h | 2 +- 5 files changed, 46 insertions(+), 33 deletions(-) create mode 100644 include/qemu/audio-capture.h diff --git a/MAINTAINERS b/MAINTAINERS index 24323e8800..c78aa1f565 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2977,7 +2977,7 @@ X: audio/paaudio.c X: audio/sdlaudio.c X: audio/sndioaudio.c X: audio/spiceaudio.c -F: include/qemu/audio.h +F: include/qemu/audio*.h F: qapi/audio.json ALSA Audio backend diff --git a/audio/audio_int.h b/audio/audio_int.h index df13a466e4..5834ebea5e 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -30,6 +30,7 @@ /* #define RECIPROCAL */ #endif #include "qemu/audio.h" +#include "qemu/audio-capture.h" #include "mixeng.h" #ifdef CONFIG_GIO 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 index 0f224810c7..c56af895d6 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -41,30 +41,7 @@ typedef struct audsettings { int endianness; } audsettings; -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; struct AudioBackendClass { @@ -79,14 +56,6 @@ typedef struct QEMUAudioTimeStamp { bool AUD_backend_check(AudioBackend **be, Error **errp); -CaptureVoiceOut *AUD_add_capture( - AudioBackend *s, - struct audsettings *as, - struct audio_capture_ops *ops, - void *opaque - ); -void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque); - SWVoiceOut *AUD_open_out ( AudioBackend *be, SWVoiceOut *sw, diff --git a/ui/vnc.h b/ui/vnc.h index 4d8363ebf3..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 "qemu/audio.h" +#include "qemu/audio-capture.h" #include "qemu/bitmap.h" #include "crypto/tlssession.h" #include "qemu/buffer.h" From 8da8bf74aedee100b9c470d58c3a5e6b99ef8d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 18 Oct 2025 00:15:57 +0400 Subject: [PATCH 33/36] audio: drop needless audio_driver "descr" field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was it ever used? Signed-off-by: Marc-André Lureau Reviewed-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daudé --- audio/alsaaudio.c | 1 - audio/audio_int.h | 1 - audio/coreaudio.m | 1 - audio/dbusaudio.c | 1 - audio/dsoundaudio.c | 1 - audio/jackaudio.c | 1 - audio/noaudio.c | 1 - audio/ossaudio.c | 1 - audio/paaudio.c | 1 - audio/pwaudio.c | 1 - audio/sdlaudio.c | 1 - audio/sndioaudio.c | 1 - audio/spiceaudio.c | 1 - audio/wavaudio.c | 1 - 14 files changed, 14 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index d1e4817081..89f6dad1a9 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -956,7 +956,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_int.h b/audio/audio_int.h index 5834ebea5e..b2b8002477 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -145,7 +145,6 @@ 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 diff --git a/audio/coreaudio.m b/audio/coreaudio.m index 8b3cd6db16..997017a1e9 100644 --- a/audio/coreaudio.m +++ b/audio/coreaudio.m @@ -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 157d36428e..d729a810aa 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -695,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 8b773ded21..7a03d1dad8 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -685,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 28face9989..7a3fcaedba 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -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/noaudio.c b/audio/noaudio.c index b136b74e26..4ed9d2156c 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -129,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 5ba91f6793..ab8791bece 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -779,7 +779,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 8eb80ede45..6b9b6d219a 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -922,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 8f6c0900c8..0fd59d9fe6 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -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 4ef73c8dfb..a7a9652d29 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -490,7 +490,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 f4f53b1c6f..8197b8b0b4 100644 --- a/audio/sndioaudio.c +++ b/audio/sndioaudio.c @@ -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 77ba89ffaa..7db2d1f0df 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -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 4d9c921305..46460a5d57 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -205,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, From b8afda670446a2c89e9964a6dd5a6e0f0c026253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 22 Oct 2025 09:53:51 +0200 Subject: [PATCH 34/36] audio: Remove pointless local variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau --- audio/ossaudio.c | 12 ++---------- audio/sdlaudio.c | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index ab8791bece..86c4805675 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -493,10 +493,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 +509,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 +517,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 +624,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 +638,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 +646,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; diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index a7a9652d29..707110973a 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -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) * From 0d254317716ab3a7ba3760c1270db83274598862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 22 Oct 2025 09:53:52 +0200 Subject: [PATCH 35/36] audio: Rename @endianness argument as @big_endian for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @endianness is used as a boolean, rename for clarity. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau --- audio/alsaaudio.c | 32 ++++++-------------------------- audio/ossaudio.c | 14 +++----------- audio/paaudio.c | 8 ++++---- audio/pwaudio.c | 12 ++++++------ 4 files changed, 19 insertions(+), 47 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 89f6dad1a9..7d7da576dc 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -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); diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 86c4805675..c6cad47a01 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -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); diff --git a/audio/paaudio.c b/audio/paaudio.c index 6b9b6d219a..0c06a39719 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -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); diff --git a/audio/pwaudio.c b/audio/pwaudio.c index 0fd59d9fe6..30f717ccac 100644 --- a/audio/pwaudio.c +++ b/audio/pwaudio.c @@ -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); From 05404916bf89867e613da271ebff1a556c206965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 22 Oct 2025 14:57:53 +0400 Subject: [PATCH 36/36] audio: deprecate HMP audio commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The command is niche and better served by the host audio system. There is no QMP equivalent, fortunately. You can capture the audio stream via remote desktop protocols too (dbus, vnc, spice). Signed-off-by: Marc-André Lureau Acked-by: Dr. David Alan Gilbert Reviewed-by: Daniel P. Berrangé Message-Id: <20251022105753.1474739-1-marcandre.lureau@redhat.com> --- audio/audio-hmp-cmds.c | 7 +++++++ audio/meson.build | 5 +++-- docs/about/deprecated.rst | 20 ++++++++++++++++++++ hmp-commands-info.hx | 6 ++++-- hmp-commands.hx | 9 +++++++-- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/audio/audio-hmp-cmds.c b/audio/audio-hmp-cmds.c index 1e56af21ab..1ffb5ebc74 100644 --- a/audio/audio-hmp-cmds.c +++ b/audio/audio-hmp-cmds.c @@ -28,6 +28,7 @@ #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); @@ -69,6 +74,8 @@ void hmp_wavcapture(Monitor *mon, const QDict *qdict) Error *local_err = NULL; 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); return; diff --git a/audio/meson.build b/audio/meson.build index 37789437fb..b2dca2c640 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -1,12 +1,13 @@ system_ss.add(files( 'audio.c', - 'audio-hmp-cmds.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/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",