Finally add audiodev= options to audio frontends so users can specify which backend to use when multiple backends exist. Not specifying an audiodev= option currently causes the first audiodev to be used, this is fixed in the next commit.
Example usage: -audiodev pa,id=foo -device AC97,audiodev=foo Signed-off-by: Kővágó, Zoltán <dirty.ice...@gmail.com> --- audio/audio.h | 3 +++ hw/audio/ac97.c | 1 + hw/audio/adlib.c | 1 + hw/audio/cs4231a.c | 1 + hw/audio/es1370.c | 7 ++++- hw/audio/gus.c | 1 + hw/audio/hda-codec.c | 1 + hw/audio/milkymist-ac97.c | 6 +++++ hw/audio/pcspk.c | 1 + hw/audio/pl041.c | 1 + hw/audio/sb16.c | 1 + hw/audio/wm8750.c | 6 +++++ hw/core/qdev-properties-system.c | 57 ++++++++++++++++++++++++++++++++++++++++ hw/usb/dev-audio.c | 1 + include/hw/qdev-properties.h | 3 +++ 15 files changed, 90 insertions(+), 1 deletion(-) diff --git a/audio/audio.h b/audio/audio.h index 0085a07..68545b6 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -177,4 +177,7 @@ void audio_legacy_help(void); AudioState *audio_state_by_name(const char *name); const char *audio_get_id(QEMUSoundCard *card); +#define DEFINE_AUDIO_PROPERTIES(_s, _f) \ + DEFINE_PROP_AUDIODEV("audiodev", _s, _f) + #endif /* audio.h */ diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index fa75f33..a835cb6 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1393,6 +1393,7 @@ static int ac97_init (PCIBus *bus) } static Property ac97_properties[] = { + DEFINE_AUDIO_PROPERTIES(AC97LinkState, card), DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0), DEFINE_PROP_END_OF_LIST (), }; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index f8f0f55..58de8b0 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -352,6 +352,7 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) } static Property adlib_properties[] = { + DEFINE_AUDIO_PROPERTIES(AdlibState, card), DEFINE_PROP_UINT32 ("iobase", AdlibState, port, 0x220), DEFINE_PROP_UINT32 ("freq", AdlibState, freq, 44100), DEFINE_PROP_END_OF_LIST (), diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 626a173..43a1a39 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -672,6 +672,7 @@ static int cs4231a_init (ISABus *bus) } static Property cs4231a_properties[] = { + DEFINE_AUDIO_PROPERTIES(CSState, card), 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 f6e74cb..fe6110d 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -1047,6 +1047,11 @@ static int es1370_init (PCIBus *bus) return 0; } +static Property es1370_properties[] = { + DEFINE_AUDIO_PROPERTIES(ES1370State, card), + DEFINE_PROP_END_OF_LIST(), +}; + static void es1370_class_init (ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS (klass); @@ -1061,6 +1066,7 @@ static void es1370_class_init (ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_SOUND, dc->categories); dc->desc = "ENSONIQ AudioPCI ES1370"; dc->vmsd = &vmstate_es1370; + dc->props = es1370_properties; } static const TypeInfo es1370_info = { @@ -1077,4 +1083,3 @@ static void es1370_register_types (void) } type_init (es1370_register_types) - diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 6107824..ee08d50 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -284,6 +284,7 @@ static int GUS_init (ISABus *bus) } static Property gus_properties[] = { + DEFINE_AUDIO_PROPERTIES(GUSState, card), 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 8693b7a..dba3331 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -613,6 +613,7 @@ static const VMStateDescription vmstate_hda_audio = { }; static Property hda_audio_properties[] = { + DEFINE_AUDIO_PROPERTIES(HDAAudioState, card), DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c index 15169e2..b63fd6f 100644 --- a/hw/audio/milkymist-ac97.c +++ b/hw/audio/milkymist-ac97.c @@ -323,6 +323,11 @@ static const VMStateDescription vmstate_milkymist_ac97 = { } }; +static Property milkymist_ac97_properties[] = { + DEFINE_AUDIO_PROPERTIES(MilkymistAC97State, card), + DEFINE_PROP_END_OF_LIST(), +}; + static void milkymist_ac97_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -331,6 +336,7 @@ static void milkymist_ac97_class_init(ObjectClass *klass, void *data) k->init = milkymist_ac97_init; dc->reset = milkymist_ac97_reset; dc->vmsd = &vmstate_milkymist_ac97; + dc->props = milkymist_ac97_properties; } static const TypeInfo milkymist_ac97_info = { diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 302debf..85d6d00 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -181,6 +181,7 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp) } static Property pcspk_properties[] = { + DEFINE_AUDIO_PROPERTIES(PCSpkState, card), DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1), DEFINE_PROP_PTR("pit", PCSpkState, pit), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index 19982f2..c003b26 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -616,6 +616,7 @@ static const VMStateDescription vmstate_pl041 = { }; static Property pl041_device_properties[] = { + DEFINE_AUDIO_PROPERTIES(PL041State, codec.card), /* 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 a159dcc..4bbb718 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1391,6 +1391,7 @@ static int SB16_init (ISABus *bus) } static Property sb16_properties[] = { + DEFINE_AUDIO_PROPERTIES(SB16State, card), 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/wm8750.c b/hw/audio/wm8750.c index 4c4333c..049ddf9 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -695,6 +695,11 @@ void wm8750_set_bclk_in(void *opaque, int new_hz) wm8750_clk_update(s, 1); } +static Property wm8750_properties[] = { + DEFINE_AUDIO_PROPERTIES(WM8750State, card), + DEFINE_PROP_END_OF_LIST(), +}; + static void wm8750_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -705,6 +710,7 @@ static void wm8750_class_init(ObjectClass *klass, void *data) sc->recv = wm8750_rx; sc->send = wm8750_tx; dc->vmsd = &vmstate_wm8750; + dc->props = wm8750_properties; } static const TypeInfo wm8750_info = { diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 249976e..3807c86 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -10,6 +10,7 @@ * See the COPYING file in the top-level directory. */ +#include "audio/audio.h" #include "net/net.h" #include "hw/qdev.h" #include "qapi/qmp/qerror.h" @@ -357,6 +358,62 @@ PropertyInfo qdev_prop_vlan = { .set = set_vlan, }; +/* --- audiodev --- */ +static void get_audiodev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop); + char *p = g_strdup(audio_get_id(card)); + + visit_type_str(v, &p, name, errp); + g_free(p); +} + +static void set_audiodev(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop); + AudioState *state; + Error *local_err = NULL; + int err = 0; + char *str; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, &str, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + state = audio_state_by_name(str); + + if (!state) { + err = -ENOENT; + goto out; + } + card->state = state; + +out: + error_set_from_qdev_prop_error(errp, err, dev, prop, str); + g_free(str); +} + +PropertyInfo qdev_prop_audiodev = { + .name = "str", + .description = "ID of an audiodev to use as a backend", + /* release done on shutdown */ + .get = get_audiodev, + .set = set_audiodev, +}; + void qdev_prop_set_drive(DeviceState *dev, const char *name, BlockBackend *value, Error **errp) { diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 0171579..48ac992 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -662,6 +662,7 @@ static const VMStateDescription vmstate_usb_audio = { }; static Property usb_audio_properties[] = { + DEFINE_AUDIO_PROPERTIES(USBAudioState, card), DEFINE_PROP_UINT32("debug", USBAudioState, debug, 0), DEFINE_PROP_UINT32("buffer", USBAudioState, buffer, 8 * USBAUDIO_PACKET_SIZE), diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 77538a8..edebcfa 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -26,6 +26,7 @@ extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; extern PropertyInfo qdev_prop_blocksize; extern PropertyInfo qdev_prop_pci_host_devaddr; +extern PropertyInfo qdev_prop_audiodev; extern PropertyInfo qdev_prop_arraylen; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ @@ -163,6 +164,8 @@ extern PropertyInfo qdev_prop_arraylen; DEFINE_PROP_DEFAULT(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t) #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) +#define DEFINE_PROP_AUDIODEV(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard) #define DEFINE_PROP_END_OF_LIST() \ {} -- 2.4.5