[PATCH 23/37] audio: lookup "audio-" object types, and realize them

marcandre.lureau@redhat.com posted 37 patches 2 weeks, 3 days ago
Maintainers: Gerd Hoffmann <kraxel@redhat.com>, Christian Schoenebeck <qemu_oss@crudebyte.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Thomas Huth <huth@tuxfamily.org>, Alexandre Ratchov <alex@caoua.org>, Laurent Vivier <laurent@vivier.eu>, Manos Pitsidianakis <manos.pitsidianakis@linaro.org>, "Michael S. Tsirkin" <mst@redhat.com>, Alistair Francis <alistair@alistair23.me>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Peter Maydell <peter.maydell@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, "Alex Bennée" <alex.bennee@linaro.org>, "Daniel P. Berrangé" <berrange@redhat.com>, Eduardo Habkost <eduardo@habkost.net>, John Snow <jsnow@redhat.com>, Cleber Rosa <crosa@redhat.com>
[PATCH 23/37] audio: lookup "audio-" object types, and realize them
Posted by marcandre.lureau@redhat.com 2 weeks, 3 days ago
From: Marc-André Lureau <marcandre.lureau@redhat.com>

Now "audio_driver" is a detail implementation of AudioMixengBackend and
not required to implement an AudioBackend.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/qemu/audio.h |  1 +
 audio/audio.c        | 40 ++++++++++++++++++++++++++--------------
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/include/qemu/audio.h b/include/qemu/audio.h
index 474d761f0be..1eeead2a722 100644
--- a/include/qemu/audio.h
+++ b/include/qemu/audio.h
@@ -51,6 +51,7 @@ typedef struct AudioBackend {
 typedef struct AudioBackendClass {
     ObjectClass parent_class;
 
+    bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
     const char *(*get_id)(AudioBackend *be);
 #ifdef CONFIG_GIO
     bool (*set_dbus_server)(AudioBackend *be,
diff --git a/audio/audio.c b/audio/audio.c
index 7e23a63d401..f6896229cfb 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1561,24 +1561,16 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
     return total;
 }
 
-static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
+static bool audio_mixeng_backend_realize(AudioBackend *abe,
+                                         Audiodev *dev, Error **errp)
 {
-    const char *drvname = AudiodevDriver_str(dev->driver);
-    struct audio_driver *drv = audio_driver_lookup(drvname);
+    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
+    audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
 
-    if (!drv) {
-        error_setg(errp, "Unknown audio driver `%s'", drvname);
-        qapi_free_Audiodev(dev);
-        return NULL;
-    }
-
-    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(object_new(TYPE_AUDIO_MIXENG_BACKEND));
     be->dev = dev;
-
     be->drv_opaque = drv->init(be->dev, errp);
     if (!be->drv_opaque) {
-        object_unref(OBJECT(be));
-        return NULL;
+        return false;
     }
 
     if (!drv->pcm_ops->get_buffer_in) {
@@ -1600,7 +1592,26 @@ static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
         be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
     }
 
-    return AUDIO_BACKEND(be);
+    return true;
+}
+
+static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
+{
+    const char *drvname = AudiodevDriver_str(dev->driver);
+    g_autofree char *type = g_strconcat("audio-", drvname, NULL);
+    AudioBackend *be = AUDIO_BACKEND(object_new(type));
+
+    if (!be) {
+        error_setg(errp, "Unknown audio driver `%s'", drvname);
+        return NULL;
+    }
+
+    if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) {
+        object_unref(OBJECT(be));
+        return NULL;
+    }
+
+    return be;
 }
 
 static void audio_vm_change_state_handler (void *opaque, bool running,
@@ -1643,6 +1654,7 @@ static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data
 {
     AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
 
+    be->realize = audio_mixeng_backend_realize;
     be->get_id = audio_mixeng_backend_get_id;
 }
 
-- 
2.52.0


Re: [PATCH 23/37] audio: lookup "audio-" object types, and realize them
Posted by Mark Cave-Ayland 5 days, 15 hours ago
On 23/01/2026 07:49, marcandre.lureau@redhat.com wrote:

> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Now "audio_driver" is a detail implementation of AudioMixengBackend and
> not required to implement an AudioBackend.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>   include/qemu/audio.h |  1 +
>   audio/audio.c        | 40 ++++++++++++++++++++++++++--------------
>   2 files changed, 27 insertions(+), 14 deletions(-)
> 
> diff --git a/include/qemu/audio.h b/include/qemu/audio.h
> index 474d761f0be..1eeead2a722 100644
> --- a/include/qemu/audio.h
> +++ b/include/qemu/audio.h
> @@ -51,6 +51,7 @@ typedef struct AudioBackend {
>   typedef struct AudioBackendClass {
>       ObjectClass parent_class;
>   
> +    bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
>       const char *(*get_id)(AudioBackend *be);
>   #ifdef CONFIG_GIO
>       bool (*set_dbus_server)(AudioBackend *be,
> diff --git a/audio/audio.c b/audio/audio.c
> index 7e23a63d401..f6896229cfb 100644
> --- a/audio/audio.c
> +++ b/audio/audio.c
> @@ -1561,24 +1561,16 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
>       return total;
>   }
>   
> -static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
> +static bool audio_mixeng_backend_realize(AudioBackend *abe,
> +                                         Audiodev *dev, Error **errp)
>   {
> -    const char *drvname = AudiodevDriver_str(dev->driver);
> -    struct audio_driver *drv = audio_driver_lookup(drvname);
> +    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
> +    audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
>   
> -    if (!drv) {
> -        error_setg(errp, "Unknown audio driver `%s'", drvname);
> -        qapi_free_Audiodev(dev);
> -        return NULL;
> -    }
> -
> -    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(object_new(TYPE_AUDIO_MIXENG_BACKEND));
>       be->dev = dev;
> -
>       be->drv_opaque = drv->init(be->dev, errp);
>       if (!be->drv_opaque) {
> -        object_unref(OBJECT(be));
> -        return NULL;
> +        return false;
>       }
>   
>       if (!drv->pcm_ops->get_buffer_in) {
> @@ -1600,7 +1592,26 @@ static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
>           be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
>       }
>   
> -    return AUDIO_BACKEND(be);
> +    return true;
> +}
> +
> +static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
> +{
> +    const char *drvname = AudiodevDriver_str(dev->driver);
> +    g_autofree char *type = g_strconcat("audio-", drvname, NULL);
> +    AudioBackend *be = AUDIO_BACKEND(object_new(type));
> +
> +    if (!be) {
> +        error_setg(errp, "Unknown audio driver `%s'", drvname);
> +        return NULL;
> +    }
> +
> +    if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) {
> +        object_unref(OBJECT(be));
> +        return NULL;
> +    }
> +
> +    return be;
>   }
>   
>   static void audio_vm_change_state_handler (void *opaque, bool running,
> @@ -1643,6 +1654,7 @@ static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data
>   {
>       AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
>   
> +    be->realize = audio_mixeng_backend_realize;
>       be->get_id = audio_mixeng_backend_get_id;
>   }

I'm wondering if an AudioBackendClass realize() method is the right way 
to handle this, and if instead an object_property_set() function could 
be used to set a "driver" property?


ATB,

Mark.


Re: [PATCH 23/37] audio: lookup "audio-" object types, and realize them
Posted by Marc-André Lureau 5 days, 12 hours ago
Hi

On Wed, Feb 4, 2026 at 3:33 PM Mark Cave-Ayland
<mark.caveayland@nutanix.com> wrote:
>
> On 23/01/2026 07:49, marcandre.lureau@redhat.com wrote:
>
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > Now "audio_driver" is a detail implementation of AudioMixengBackend and
> > not required to implement an AudioBackend.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >   include/qemu/audio.h |  1 +
> >   audio/audio.c        | 40 ++++++++++++++++++++++++++--------------
> >   2 files changed, 27 insertions(+), 14 deletions(-)
> >
> > diff --git a/include/qemu/audio.h b/include/qemu/audio.h
> > index 474d761f0be..1eeead2a722 100644
> > --- a/include/qemu/audio.h
> > +++ b/include/qemu/audio.h
> > @@ -51,6 +51,7 @@ typedef struct AudioBackend {
> >   typedef struct AudioBackendClass {
> >       ObjectClass parent_class;
> >
> > +    bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
> >       const char *(*get_id)(AudioBackend *be);
> >   #ifdef CONFIG_GIO
> >       bool (*set_dbus_server)(AudioBackend *be,
> > diff --git a/audio/audio.c b/audio/audio.c
> > index 7e23a63d401..f6896229cfb 100644
> > --- a/audio/audio.c
> > +++ b/audio/audio.c
> > @@ -1561,24 +1561,16 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
> >       return total;
> >   }
> >
> > -static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
> > +static bool audio_mixeng_backend_realize(AudioBackend *abe,
> > +                                         Audiodev *dev, Error **errp)
> >   {
> > -    const char *drvname = AudiodevDriver_str(dev->driver);
> > -    struct audio_driver *drv = audio_driver_lookup(drvname);
> > +    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
> > +    audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
> >
> > -    if (!drv) {
> > -        error_setg(errp, "Unknown audio driver `%s'", drvname);
> > -        qapi_free_Audiodev(dev);
> > -        return NULL;
> > -    }
> > -
> > -    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(object_new(TYPE_AUDIO_MIXENG_BACKEND));
> >       be->dev = dev;
> > -
> >       be->drv_opaque = drv->init(be->dev, errp);
> >       if (!be->drv_opaque) {
> > -        object_unref(OBJECT(be));
> > -        return NULL;
> > +        return false;
> >       }
> >
> >       if (!drv->pcm_ops->get_buffer_in) {
> > @@ -1600,7 +1592,26 @@ static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
> >           be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
> >       }
> >
> > -    return AUDIO_BACKEND(be);
> > +    return true;
> > +}
> > +
> > +static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
> > +{
> > +    const char *drvname = AudiodevDriver_str(dev->driver);
> > +    g_autofree char *type = g_strconcat("audio-", drvname, NULL);
> > +    AudioBackend *be = AUDIO_BACKEND(object_new(type));
> > +
> > +    if (!be) {
> > +        error_setg(errp, "Unknown audio driver `%s'", drvname);
> > +        return NULL;
> > +    }
> > +
> > +    if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) {
> > +        object_unref(OBJECT(be));
> > +        return NULL;
> > +    }
> > +
> > +    return be;
> >   }
> >
> >   static void audio_vm_change_state_handler (void *opaque, bool running,
> > @@ -1643,6 +1654,7 @@ static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data
> >   {
> >       AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
> >
> > +    be->realize = audio_mixeng_backend_realize;
> >       be->get_id = audio_mixeng_backend_get_id;
> >   }
>
> I'm wondering if an AudioBackendClass realize() method is the right way
> to handle this, and if instead an object_property_set() function could
> be used to set a "driver" property?
>

By the end of the refactoring, "driver" is gone. Effectively, each
(current) backend will inherit from AudioMixengBe.
Re: [PATCH 23/37] audio: lookup "audio-" object types, and realize them
Posted by Mark Cave-Ayland 4 days, 10 hours ago
On 04/02/2026 14:39, Marc-André Lureau wrote:

> Hi
> 
> On Wed, Feb 4, 2026 at 3:33 PM Mark Cave-Ayland
> <mark.caveayland@nutanix.com> wrote:
>>
>> On 23/01/2026 07:49, marcandre.lureau@redhat.com wrote:
>>
>>> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>
>>> Now "audio_driver" is a detail implementation of AudioMixengBackend and
>>> not required to implement an AudioBackend.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>>    include/qemu/audio.h |  1 +
>>>    audio/audio.c        | 40 ++++++++++++++++++++++++++--------------
>>>    2 files changed, 27 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/include/qemu/audio.h b/include/qemu/audio.h
>>> index 474d761f0be..1eeead2a722 100644
>>> --- a/include/qemu/audio.h
>>> +++ b/include/qemu/audio.h
>>> @@ -51,6 +51,7 @@ typedef struct AudioBackend {
>>>    typedef struct AudioBackendClass {
>>>        ObjectClass parent_class;
>>>
>>> +    bool (*realize)(AudioBackend *be, Audiodev *dev, Error **errp);
>>>        const char *(*get_id)(AudioBackend *be);
>>>    #ifdef CONFIG_GIO
>>>        bool (*set_dbus_server)(AudioBackend *be,
>>> diff --git a/audio/audio.c b/audio/audio.c
>>> index 7e23a63d401..f6896229cfb 100644
>>> --- a/audio/audio.c
>>> +++ b/audio/audio.c
>>> @@ -1561,24 +1561,16 @@ size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size)
>>>        return total;
>>>    }
>>>
>>> -static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
>>> +static bool audio_mixeng_backend_realize(AudioBackend *abe,
>>> +                                         Audiodev *dev, Error **errp)
>>>    {
>>> -    const char *drvname = AudiodevDriver_str(dev->driver);
>>> -    struct audio_driver *drv = audio_driver_lookup(drvname);
>>> +    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(abe);
>>> +    audio_driver *drv = AUDIO_MIXENG_BACKEND_GET_CLASS(be)->driver;
>>>
>>> -    if (!drv) {
>>> -        error_setg(errp, "Unknown audio driver `%s'", drvname);
>>> -        qapi_free_Audiodev(dev);
>>> -        return NULL;
>>> -    }
>>> -
>>> -    AudioMixengBackend *be = AUDIO_MIXENG_BACKEND(object_new(TYPE_AUDIO_MIXENG_BACKEND));
>>>        be->dev = dev;
>>> -
>>>        be->drv_opaque = drv->init(be->dev, errp);
>>>        if (!be->drv_opaque) {
>>> -        object_unref(OBJECT(be));
>>> -        return NULL;
>>> +        return false;
>>>        }
>>>
>>>        if (!drv->pcm_ops->get_buffer_in) {
>>> @@ -1600,7 +1592,26 @@ static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
>>>            be->period_ticks = be->dev->timer_period * (int64_t)SCALE_US;
>>>        }
>>>
>>> -    return AUDIO_BACKEND(be);
>>> +    return true;
>>> +}
>>> +
>>> +static AudioBackend *audio_be_new(Audiodev *dev, Error **errp)
>>> +{
>>> +    const char *drvname = AudiodevDriver_str(dev->driver);
>>> +    g_autofree char *type = g_strconcat("audio-", drvname, NULL);
>>> +    AudioBackend *be = AUDIO_BACKEND(object_new(type));
>>> +
>>> +    if (!be) {
>>> +        error_setg(errp, "Unknown audio driver `%s'", drvname);
>>> +        return NULL;
>>> +    }
>>> +
>>> +    if (!AUDIO_BACKEND_GET_CLASS(be)->realize(be, dev, errp)) {
>>> +        object_unref(OBJECT(be));
>>> +        return NULL;
>>> +    }
>>> +
>>> +    return be;
>>>    }
>>>
>>>    static void audio_vm_change_state_handler (void *opaque, bool running,
>>> @@ -1643,6 +1654,7 @@ static void audio_mixeng_backend_class_init(ObjectClass *klass, const void *data
>>>    {
>>>        AudioBackendClass *be = AUDIO_BACKEND_CLASS(klass);
>>>
>>> +    be->realize = audio_mixeng_backend_realize;
>>>        be->get_id = audio_mixeng_backend_get_id;
>>>    }
>>
>> I'm wondering if an AudioBackendClass realize() method is the right way
>> to handle this, and if instead an object_property_set() function could
>> be used to set a "driver" property?
>>
> 
> By the end of the refactoring, "driver" is gone. Effectively, each
> (current) backend will inherit from AudioMixengBe.

(goes and looks)

I see, so this happens in part 2 of the series. If the property were 
exposed directly to callers then I'd prefer to use an object setter to 
bind the Audiodev to the backend. However in this case it's all nicely 
tucked away in audio_be_new() so it doesn't really matter. Hence:

Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com>


ATB,

Mark.