audio/dbus: convert to QOM lifecycle methods
Migrate the D-Bus audio backend from the legacy driver init/fini callbacks to proper QOM realize and finalize methods. The DBusAudio struct fields are now embedded directly in the AudioDbus QOM object instead of being allocated separately as drv_opaque. This allows accessing the backend state through proper QOM type casting with AUDIO_DBUS() rather than casting drv_opaque pointers. Reviewed-by: Mark Cave-Ayland <mark.caveayland@nutanix.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Marc-André Lureau committed
Jan 16, 2026 at 11:39 UTC
06e1312b7d2557b467620ca629f18dac2536b02b
1 file changed
+39
-37
audio/dbusaudio.c
+39
-37
@@ -48,21 +48,20 @@
48
#define TYPE_AUDIO_DBUS "audio-dbus"
49
OBJECT_DECLARE_SIMPLE_TYPE(AudioDbus, AUDIO_DBUS)
50
51
+static AudioBackendClass *audio_dbus_parent_class;
52
+
53
struct AudioDbus {
54
AudioMixengBackend parent_obj;
53
-};
54
-
55
-static struct audio_driver dbus_audio_driver;
55
57
-typedef struct DBusAudio {
58
- Audiodev *dev;
56
GDBusObjectManagerServer *server;
57
bool p2p;
58
GDBusObjectSkeleton *audio;
59
QemuDBusDisplay1Audio *iface;
60
GHashTable *out_listeners;
61
GHashTable *in_listeners;
65
-} DBusAudio;
62
+};
63
+
64
+static struct audio_driver dbus_audio_driver;
65
66
typedef struct DBusVoiceOut {
67
HWVoiceOut hw;
@@ -105,7 +104,7 @@ static void *dbus_get_buffer_out(HWVoiceOut *hw, size_t *size)
104
105
static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
106
{
108
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
107
+ AudioDbus *da = AUDIO_DBUS(hw->s);
108
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
109
GHashTableIter iter;
110
QemuDBusDisplay1AudioOutListener *listener = NULL;
@@ -162,9 +161,9 @@ dbus_init_out_listener(QemuDBusDisplay1AudioOutListener *listener,
161
}
162
163
static guint
165
-dbus_audio_get_nsamples(DBusAudio *da)
164
+dbus_audio_get_nsamples(AudioDbus *da)
165
{
167
- AudiodevDBusOptions *opts = &da->dev->u.dbus;
166
+ AudiodevDBusOptions *opts = &AUDIO_MIXENG_BACKEND(da)->dev->u.dbus;
167
168
if (opts->has_nsamples && opts->nsamples) {
169
return opts->nsamples;
@@ -176,7 +175,7 @@ dbus_audio_get_nsamples(DBusAudio *da)
175
static int
176
dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
177
{
179
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
178
+ AudioDbus *da = AUDIO_DBUS(hw->s);
179
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
180
GHashTableIter iter;
181
QemuDBusDisplay1AudioOutListener *listener = NULL;
@@ -195,7 +194,7 @@ dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
194
static void
195
dbus_fini_out(HWVoiceOut *hw)
196
{
198
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
197
+ AudioDbus *da = AUDIO_DBUS(hw->s);
198
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
199
GHashTableIter iter;
200
QemuDBusDisplay1AudioOutListener *listener = NULL;
@@ -214,7 +213,7 @@ dbus_fini_out(HWVoiceOut *hw)
213
static void
214
dbus_enable_out(HWVoiceOut *hw, bool enable)
215
{
217
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
216
+ AudioDbus *da = AUDIO_DBUS(hw->s);
217
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
218
GHashTableIter iter;
219
QemuDBusDisplay1AudioOutListener *listener = NULL;
@@ -256,7 +255,7 @@ dbus_volume_out_listener(HWVoiceOut *hw,
255
static void
256
dbus_volume_out(HWVoiceOut *hw, Volume *vol)
257
{
259
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
258
+ AudioDbus *da = AUDIO_DBUS(hw->s);
259
DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw);
260
GHashTableIter iter;
261
QemuDBusDisplay1AudioOutListener *listener = NULL;
@@ -290,7 +289,7 @@ dbus_init_in_listener(QemuDBusDisplay1AudioInListener *listener, HWVoiceIn *hw)
289
static int
290
dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
291
{
293
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
292
+ AudioDbus *da = AUDIO_DBUS(hw->s);
293
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
294
GHashTableIter iter;
295
QemuDBusDisplay1AudioInListener *listener = NULL;
@@ -309,7 +308,7 @@ dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
308
static void
309
dbus_fini_in(HWVoiceIn *hw)
310
{
312
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
311
+ AudioDbus *da = AUDIO_DBUS(hw->s);
312
GHashTableIter iter;
313
QemuDBusDisplay1AudioInListener *listener = NULL;
314
@@ -346,7 +345,7 @@ dbus_volume_in_listener(HWVoiceIn *hw,
345
static void
346
dbus_volume_in(HWVoiceIn *hw, Volume *vol)
347
{
349
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
348
+ AudioDbus *da = AUDIO_DBUS(hw->s);
349
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
350
GHashTableIter iter;
351
QemuDBusDisplay1AudioInListener *listener = NULL;
@@ -363,7 +362,7 @@ dbus_volume_in(HWVoiceIn *hw, Volume *vol)
362
static size_t
363
dbus_read(HWVoiceIn *hw, void *buf, size_t size)
364
{
366
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
365
+ AudioDbus *da = AUDIO_DBUS(hw->s);
366
/* DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); */
367
GHashTableIter iter;
368
QemuDBusDisplay1AudioInListener *listener = NULL;
@@ -398,7 +397,7 @@ dbus_read(HWVoiceIn *hw, void *buf, size_t size)
397
static void
398
dbus_enable_in(HWVoiceIn *hw, bool enable)
399
{
401
- DBusAudio *da = (DBusAudio *)hw->s->drv_opaque;
400
+ AudioDbus *da = AUDIO_DBUS(hw->s);
401
DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw);
402
GHashTableIter iter;
403
QemuDBusDisplay1AudioInListener *listener = NULL;
@@ -416,28 +415,31 @@ dbus_enable_in(HWVoiceIn *hw, bool enable)
415
}
416
}
417
419
-static void *
420
-dbus_audio_init(Audiodev *dev, Error **errp)
418
+static bool
419
+audio_dbus_realize(AudioBackend *abe, Audiodev *dev, Error **errp)
420
{
422
- DBusAudio *da;
421
+ AudioDbus *da = AUDIO_DBUS(abe);
422
423
if (!qemu_using_dbus_display(errp)) {
425
- return NULL;
424
+ qapi_free_Audiodev(dev);
425
+ return false;
426
+ }
427
+
428
+ if (!audio_dbus_parent_class->realize(abe, dev, errp)) {
429
+ return false;
430
}
431
428
- da = g_new0(DBusAudio, 1);
429
- da->dev = dev;
432
da->out_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
431
- g_free, g_object_unref);
433
+ g_free, g_object_unref);
434
da->in_listeners = g_hash_table_new_full(g_str_hash, g_str_equal,
433
- g_free, g_object_unref);
434
- return da;
435
+ g_free, g_object_unref);
436
+ return true;
437
}
438
439
static void
438
-dbus_audio_fini(void *opaque)
440
+audio_dbus_finalize(Object *obj)
441
{
440
- DBusAudio *da = opaque;
442
+ AudioDbus *da = AUDIO_DBUS(obj);
443
444
if (da->server) {
445
g_dbus_object_manager_server_unexport(da->server,
@@ -448,14 +450,13 @@ dbus_audio_fini(void *opaque)
450
g_clear_pointer(&da->in_listeners, g_hash_table_unref);
451
g_clear_pointer(&da->out_listeners, g_hash_table_unref);
452
g_clear_object(&da->server);
451
- g_free(da);
453
}
454
455
static void
456
listener_out_vanished_cb(GDBusConnection *connection,
457
gboolean remote_peer_vanished,
458
GError *error,
458
- DBusAudio *da)
459
+ AudioDbus *da)
460
{
461
char *name = g_object_get_data(G_OBJECT(connection), "name");
462
@@ -466,7 +467,7 @@ static void
467
listener_in_vanished_cb(GDBusConnection *connection,
468
gboolean remote_peer_vanished,
469
GError *error,
469
- DBusAudio *da)
470
+ AudioDbus *da)
471
{
472
char *name = g_object_get_data(G_OBJECT(connection), "name");
473
@@ -482,7 +483,7 @@ dbus_audio_register_listener(AudioMixengBackend *s,
483
GVariant *arg_listener,
484
bool out)
485
{
485
- DBusAudio *da = s->drv_opaque;
486
+ AudioDbus *da = AUDIO_DBUS(s);
487
const char *sender =
488
da->p2p ? "p2p" : g_dbus_method_invocation_get_sender(invocation);
489
g_autoptr(GDBusConnection) listener_conn = NULL;
@@ -667,9 +668,8 @@ dbus_audio_set_server(AudioBackend *s,
668
bool p2p,
669
Error **errp)
670
{
670
- DBusAudio *da = AUDIO_MIXENG_BACKEND(s)->drv_opaque;
671
+ AudioDbus *da = AUDIO_DBUS(s);
672
672
- g_assert(da);
673
g_assert(!da->server);
674
675
da->server = g_object_ref(server);
@@ -711,8 +711,6 @@ static struct audio_pcm_ops dbus_pcm_ops = {
711
712
static struct audio_driver dbus_audio_driver = {
713
.name = "dbus",
714
- .init = dbus_audio_init,
715
- .fini = dbus_audio_fini,
714
.pcm_ops = &dbus_pcm_ops,
715
.max_voices_out = INT_MAX,
716
.max_voices_in = INT_MAX,
@@ -725,6 +723,9 @@ static void audio_dbus_class_init(ObjectClass *klass, const void *data)
723
AudioBackendClass *b = AUDIO_BACKEND_CLASS(klass);
724
AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
725
726
+ audio_dbus_parent_class = AUDIO_BACKEND_CLASS(object_class_get_parent(klass));
727
+
728
+ b->realize = audio_dbus_realize;
729
b->set_dbus_server = dbus_audio_set_server;
730
k->driver = &dbus_audio_driver;
731
}
@@ -734,6 +735,7 @@ static const TypeInfo audio_types[] = {
735
.name = TYPE_AUDIO_DBUS,
736
.parent = TYPE_AUDIO_MIXENG_BACKEND,
737
.instance_size = sizeof(AudioDbus),
738
+ .instance_finalize = audio_dbus_finalize,
739
.class_init = audio_dbus_class_init,
740
},
741
};