From: Marc-André Lureau <[email protected]> Introduce a sub-class for current "audio_driver" based implementations. Future AudioBackend implementations can do without it.
Next cleanup will actually remove "audio_driver" struct altogether and make the subclass proper QOM objects. Public APIs still rely on backend being an AudioDriver. They will assert() if not. This will be addressed later to allow other backends. Signed-off-by: Marc-André Lureau <[email protected]> --- audio/audio_int.h | 25 +++++--- audio/audio_template.h | 18 +++--- include/qemu/audio.h | 17 +++++- audio/alsaaudio.c | 2 +- audio/audio.c | 126 +++++++++++++++++++++++++++++++---------- audio/dbusaudio.c | 8 +-- audio/ossaudio.c | 4 +- ui/dbus.c | 3 +- 8 files changed, 142 insertions(+), 61 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index b2b8002477..e1f962875f 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -61,7 +61,7 @@ struct audio_pcm_info { int swap_endianness; }; -typedef struct AudioBackend AudioBackend; +typedef struct AudioDriver AudioDriver; typedef struct SWVoiceCap SWVoiceCap; typedef struct STSampleBuffer { @@ -70,7 +70,7 @@ typedef struct STSampleBuffer { } STSampleBuffer; typedef struct HWVoiceOut { - AudioBackend *s; + AudioDriver *s; bool enabled; int poll_mode; bool pending_disable; @@ -91,7 +91,7 @@ typedef struct HWVoiceOut { } HWVoiceOut; typedef struct HWVoiceIn { - AudioBackend *s; + AudioDriver *s; bool enabled; int poll_mode; struct audio_pcm_info info; @@ -112,7 +112,7 @@ typedef struct HWVoiceIn { } HWVoiceIn; struct SWVoiceOut { - AudioBackend *s; + AudioDriver *s; struct audio_pcm_info info; t_sample *conv; STSampleBuffer resample_buf; @@ -128,7 +128,7 @@ struct SWVoiceOut { }; struct SWVoiceIn { - AudioBackend *s; + AudioDriver *s; bool active; struct audio_pcm_info info; void *rate; @@ -241,8 +241,12 @@ struct SWVoiceCap { QLIST_ENTRY (SWVoiceCap) entries; }; -typedef struct AudioBackend { - Object parent; +struct AudioDriverClass { + AudioBackendClass parent_class; +}; + +struct AudioDriver { + AudioBackend parent_obj; struct audio_driver *drv; Audiodev *dev; @@ -260,7 +264,7 @@ typedef struct AudioBackend { bool timer_running; uint64_t timer_last; VMChangeStateEntry *vmse; -} AudioBackend; +}; extern const struct mixeng_volume nominal_volume; @@ -273,7 +277,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(AudioBackend *s, const char *msg); +void audio_run(AudioDriver *s, const char *msg); const char *audio_application_name(void); @@ -326,4 +330,7 @@ void audio_create_pdos(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); +#define TYPE_AUDIO_DRIVER "audio-driver" +OBJECT_DECLARE_TYPE(AudioDriver, AudioDriverClass, AUDIO_DRIVER) + #endif /* QEMU_AUDIO_INT_H */ diff --git a/audio/audio_template.h b/audio/audio_template.h index 1ab3c47fd7..925a878f6d 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)(AudioBackend *s, +static void glue(audio_init_nb_voices_, TYPE)(AudioDriver *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; - AudioBackend *s = hw->s; + AudioDriver *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)(AudioBackend *s, HW *hw) +static HW *glue(audio_pcm_hw_find_any_, TYPE)(AudioDriver *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)(AudioBackend *s, HW *hw) +static HW *glue(audio_pcm_hw_find_any_enabled_, TYPE)(AudioDriver *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)(AudioBackend *s, HW *hw) return NULL; } -static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioBackend *s, HW *hw, +static HW *glue(audio_pcm_hw_find_specific_, TYPE)(AudioDriver *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)(AudioBackend *s, HW *hw, return NULL; } -static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioBackend *s, +static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioDriver *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)(AudioBackend *s, struct audsettings *as) +static HW *glue(audio_pcm_hw_add_, TYPE)(AudioDriver *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)(AudioBackend *s, struct audsettings *as } static SW *glue(audio_pcm_create_voice_pair_, TYPE)( - AudioBackend *s, + AudioDriver *s, const char *sw_name, struct audsettings *as ) @@ -494,7 +494,7 @@ SW *glue (AUD_open_, TYPE) ( struct audsettings *as ) { - AudioBackend *s = be; + AudioDriver *s = AUDIO_DRIVER(be); AudiodevPerDirectionOptions *pdo; if (audio_bug(__func__, !be || !name || !callback_fn || !as)) { diff --git a/include/qemu/audio.h b/include/qemu/audio.h index 2562710bec..f83f8326ab 100644 --- a/include/qemu/audio.h +++ b/include/qemu/audio.h @@ -44,11 +44,21 @@ typedef struct audsettings { typedef struct SWVoiceOut SWVoiceOut; typedef struct SWVoiceIn SWVoiceIn; -struct AudioBackendClass { +typedef struct AudioBackend { + Object parent_obj; +} AudioBackend; + +typedef struct AudioBackendClass { ObjectClass parent_class; -}; -typedef struct AudioBackend AudioBackend; + const char *(*get_id)(AudioBackend *be); +#ifdef CONFIG_GIO + bool (*set_dbus_server)(AudioBackend *be, + GDBusObjectManagerServer *manager, + bool p2p, + Error **errp); +#endif +} AudioBackendClass; typedef struct QEMUAudioTimeStamp { uint64_t old_ts; @@ -129,6 +139,7 @@ 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_can_set_dbus_server(AudioBackend *be); bool audio_be_set_dbus_server(AudioBackend *be, GDBusObjectManagerServer *server, bool p2p, diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 7d7da576dc..278c74c5de 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -41,7 +41,7 @@ struct pollhlp { struct pollfd *pfds; int count; int mask; - AudioBackend *s; + AudioDriver *s; }; typedef struct ALSAVoiceOut { diff --git a/audio/audio.c b/audio/audio.c index 0f992a775c..4a43761528 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -36,6 +36,7 @@ #include "qemu/log.h" #include "qemu/module.h" #include "qemu/help_option.h" +#include "qom/object.h" #include "system/system.h" #include "system/replay.h" #include "system/runstate.h" @@ -383,7 +384,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len) /* * Capture */ -static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioBackend *s, +static CaptureVoiceOut *audio_pcm_capture_find_specific(AudioDriver *s, struct audsettings *as) { CaptureVoiceOut *cap; @@ -463,7 +464,7 @@ static void audio_detach_capture (HWVoiceOut *hw) static int audio_attach_capture (HWVoiceOut *hw) { - AudioBackend *s = hw->s; + AudioDriver *s = hw->s; CaptureVoiceOut *cap; audio_detach_capture (hw); @@ -801,7 +802,7 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) /* * Timer */ -static int audio_is_timer_needed(AudioBackend *s) +static int audio_is_timer_needed(AudioDriver *s) { HWVoiceIn *hwi = NULL; HWVoiceOut *hwo = NULL; @@ -819,7 +820,7 @@ static int audio_is_timer_needed(AudioBackend *s) return 0; } -static void audio_reset_timer(AudioBackend *s) +static void audio_reset_timer(AudioDriver *s) { if (audio_is_timer_needed(s)) { timer_mod_anticipate_ns(s->ts, @@ -841,7 +842,7 @@ static void audio_reset_timer(AudioBackend *s) static void audio_timer (void *opaque) { int64_t now, diff; - AudioBackend *s = opaque; + AudioDriver *s = opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); diff = now - s->timer_last; @@ -924,7 +925,7 @@ void AUD_set_active_out(SWVoiceOut *sw, bool on) hw = sw->hw; if (sw->active != on) { - AudioBackend *s = sw->s; + AudioDriver *s = sw->s; SWVoiceOut *temp_sw; SWVoiceCap *sc; @@ -972,7 +973,7 @@ void AUD_set_active_in(SWVoiceIn *sw, bool on) hw = sw->hw; if (sw->active != on) { - AudioBackend *s = sw->s; + AudioDriver *s = sw->s; SWVoiceIn *temp_sw; if (on) { @@ -1140,7 +1141,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) return clipped; } -static void audio_run_out(AudioBackend *s) +static void audio_run_out(AudioDriver *s) { HWVoiceOut *hw = NULL; SWVoiceOut *sw; @@ -1294,7 +1295,7 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) return conv; } -static void audio_run_in(AudioBackend *s) +static void audio_run_in(AudioDriver *s) { HWVoiceIn *hw = NULL; @@ -1342,7 +1343,7 @@ static void audio_run_in(AudioBackend *s) } } -static void audio_run_capture(AudioBackend *s) +static void audio_run_capture(AudioDriver *s) { CaptureVoiceOut *cap; @@ -1389,7 +1390,7 @@ static void audio_run_capture(AudioBackend *s) } } -void audio_run(AudioBackend *s, const char *msg) +void audio_run(AudioDriver *s, const char *msg) { audio_run_out(s); audio_run_in(s); @@ -1562,8 +1563,8 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) return total; } -static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv, - Audiodev *dev, Error **errp) +static bool audio_driver_do_init(AudioDriver *s, struct audio_driver *drv, + Audiodev *dev, Error **errp) { s->drv_opaque = drv->init(dev, errp); if (!s->drv_opaque) { @@ -1595,7 +1596,7 @@ static bool audio_driver_init(AudioBackend *s, struct audio_driver *drv, static void audio_vm_change_state_handler (void *opaque, bool running, RunState state) { - AudioBackend *s = opaque; + AudioDriver *s = opaque; HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; @@ -1618,7 +1619,47 @@ static const VMStateDescription vmstate_audio; static void audio_be_init(Object *obj) { - AudioBackend *s = AUDIO_BACKEND(obj); +} + +static void audio_be_finalize(Object *obj) +{ +} + +static const char *audio_driver_get_id(AudioBackend *be) +{ + return AUDIO_DRIVER(be)->dev->id; +} + +#ifdef CONFIG_GIO +static bool audio_driver_set_dbus_server(AudioBackend *be, + GDBusObjectManagerServer *manager, + bool p2p, + Error **errp) +{ + AudioDriver *d = AUDIO_DRIVER(be); + + if (!d->drv->set_dbus_server) { + return false; + } + + return d->drv->set_dbus_server(be, manager, p2p, errp); +} + +#endif + +static void audio_driver_class_init(ObjectClass *klass, const void *data) +{ + AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass); + + be->get_id = audio_driver_get_id; +#ifdef CONFIG_GIO + be->set_dbus_server = audio_driver_set_dbus_server; +#endif +} + +static void audio_driver_init(Object *obj) +{ + AudioDriver *s = AUDIO_DRIVER(obj); QLIST_INIT(&s->hw_head_out); QLIST_INIT(&s->hw_head_in); @@ -1631,9 +1672,9 @@ static void audio_be_init(Object *obj) vmstate_register_any(NULL, &vmstate_audio, s); } -static void audio_be_finalize(Object *obj) +static void audio_driver_finalize(Object *obj) { - AudioBackend *s = AUDIO_BACKEND(obj); + AudioDriver *s = AUDIO_DRIVER(obj); HWVoiceOut *hwo, *hwon; HWVoiceIn *hwi, *hwin; @@ -1749,10 +1790,10 @@ static AudioBackend *audio_init(Audiodev *dev, Error **errp) { int done = 0; const char *drvname; - AudioBackend *s; + AudioDriver *s; struct audio_driver *driver; - s = AUDIO_BACKEND(object_new(TYPE_AUDIO_BACKEND)); + s = AUDIO_DRIVER(object_new(TYPE_AUDIO_DRIVER)); if (dev) { /* -audiodev option */ @@ -1760,7 +1801,7 @@ static AudioBackend *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_do_init(s, driver, dev, errp); } else { error_setg(errp, "Unknown audio driver `%s'", drvname); } @@ -1780,7 +1821,7 @@ static AudioBackend *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_do_init(s, driver, dev, NULL)) { break; } qapi_free_Audiodev(dev); @@ -1792,7 +1833,7 @@ static AudioBackend *audio_init(Audiodev *dev, Error **errp) goto out; } object_unref(s); - return s; + return AUDIO_BACKEND(s); out: object_unref(s); @@ -1831,17 +1872,19 @@ bool AUD_backend_check(AudioBackend **be, Error **errp) static struct audio_pcm_ops capture_pcm_ops; CaptureVoiceOut *AUD_add_capture( - AudioBackend *s, + AudioBackend *be, struct audsettings *as, struct audio_capture_ops *ops, void *cb_opaque ) { + AudioDriver *s = AUDIO_DRIVER(be); CaptureVoiceOut *cap; struct capture_callback *cb; if (!s) { - error_report("Capturing without setting an audiodev is not supported"); + /* TODO: implement an interface instead (or drop capture support) */ + error_report("Capturing without setting an audiodev driver is not supported"); abort(); } @@ -2227,27 +2270,36 @@ AudioBackend *audio_be_by_name(const char *name, Error **errp) } #ifdef CONFIG_GIO +bool audio_be_can_set_dbus_server(AudioBackend *be) +{ + /* + * AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be); + * return klass->set_dbus_server != NULL; + */ + return AUDIO_DRIVER(be)->drv->set_dbus_server != NULL; +} + bool audio_be_set_dbus_server(AudioBackend *be, GDBusObjectManagerServer *server, bool p2p, Error **errp) { - assert(be != NULL); + AudioBackendClass *klass = AUDIO_BACKEND_GET_CLASS(be); - if (!be->drv->set_dbus_server) { - error_setg(errp, "Audiodev '%s' is not compatible with DBus", be->dev->id); + if (!audio_be_can_set_dbus_server(be)) { + error_setg(errp, "Audiodev '%s' is not compatible with DBus", + audio_be_get_id(be)); return false; } - return be->drv->set_dbus_server(be, server, p2p, errp); + return klass->set_dbus_server(be, server, p2p, errp); } #endif const char *audio_be_get_id(AudioBackend *be) { if (be) { - assert(be->dev); - return be->dev->id; + return AUDIO_BACKEND_GET_CLASS(be)->get_id(be); } else { return ""; } @@ -2322,13 +2374,25 @@ static const TypeInfo audio_be_info = { .instance_size = sizeof(AudioBackend), .instance_init = audio_be_init, .instance_finalize = audio_be_finalize, - .abstract = false, /* TODO: subclass drivers and make it abstract */ + .abstract = true, .class_size = sizeof(AudioBackendClass), }; +static const TypeInfo audio_driver_info = { + .name = TYPE_AUDIO_DRIVER, + .parent = TYPE_AUDIO_BACKEND, + .instance_size = sizeof(AudioDriver), + .instance_init = audio_driver_init, + .instance_finalize = audio_driver_finalize, + .abstract = false, + .class_size = sizeof(AudioDriverClass), + .class_init = audio_driver_class_init, +}; + static void register_types(void) { type_register_static(&audio_be_info); + type_register_static(&audio_driver_info); } type_init(register_types); diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index 1fe7c4ed64..71b2a6c2cf 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -464,7 +464,7 @@ listener_in_vanished_cb(GDBusConnection *connection, } static gboolean -dbus_audio_register_listener(AudioBackend *s, +dbus_audio_register_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -621,7 +621,7 @@ dbus_audio_register_listener(AudioBackend *s, } static gboolean -dbus_audio_register_out_listener(AudioBackend *s, +dbus_audio_register_out_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -637,7 +637,7 @@ dbus_audio_register_out_listener(AudioBackend *s, } static gboolean -dbus_audio_register_in_listener(AudioBackend *s, +dbus_audio_register_in_listener(AudioDriver *s, GDBusMethodInvocation *invocation, #ifdef G_OS_UNIX GUnixFDList *fd_list, @@ -657,7 +657,7 @@ dbus_audio_set_server(AudioBackend *s, bool p2p, Error **errp) { - DBusAudio *da = s->drv_opaque; + DBusAudio *da = AUDIO_DRIVER(s)->drv_opaque; g_assert(da); g_assert(!da->server); diff --git a/audio/ossaudio.c b/audio/ossaudio.c index c6cad47a01..9576cdba51 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) { - AudioBackend *s = opaque; + AudioDriver *s = opaque; audio_run(s, "oss_poll_out"); } static void oss_helper_poll_in (void *opaque) { - AudioBackend *s = opaque; + AudioDriver *s = opaque; audio_run(s, "oss_poll_in"); } diff --git a/ui/dbus.c b/ui/dbus.c index 45fb3c1aa3..b0caa9b154 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -220,7 +220,7 @@ dbus_display_complete(UserCreatable *uc, Error **errp) } AudioBackend *audio_be = audio_get_default_audio_be(NULL); - if (audio_be && !g_str_equal(audio_be->drv->name, "dbus")) { + if (audio_be && !audio_be_can_set_dbus_server(audio_be)) { audio_be = NULL; } if (dd->audiodev && *dd->audiodev) { @@ -233,7 +233,6 @@ dbus_display_complete(UserCreatable *uc, Error **errp) return; } - consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); for (idx = 0;; idx++) { if (!qemu_console_lookup_by_index(idx)) { -- 2.51.1
