audio/dsound: convert to QOM lifecycle methods
Migrate the DirectSound audio backend from the legacy driver init/fini callbacks to proper QOM realize and finalize methods. The dsound struct fields are now embedded directly in the AudioDsound QOM object instead of being allocated separately as drv_opaque. This allows accessing the backend state through proper QOM type casting with AUDIO_DSOUND() rather than casting drv_opaque pointers. The DirectSound and DirectSoundCapture COM objects are now managed through the QOM lifecycle, with initialization in realize and cleanup in finalize. 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 19:30 UTC
58e9ca99db121c9b148e2abef6ec9d3c4d52c569
2 files changed
+45
-51
audio/dsound_template.h
+4
-5
@@ -72,7 +72,7 @@ static int glue (dsound_lock_, TYPE) (
72
DWORD *blen1p,
73
DWORD *blen2p,
74
int entire,
75
- dsound *s
75
+ AudioDsound *s
76
)
77
{
78
HRESULT hr;
@@ -166,7 +166,7 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
166
{
167
int err;
168
HRESULT hr;
169
- dsound *s = drv_opaque;
169
+ AudioDsound *s = AUDIO_DSOUND(hw->s);
170
WAVEFORMATEX wfx;
171
struct audsettings obt_as;
172
#ifdef DSBTYPE_IN
@@ -174,13 +174,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
174
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
175
DSCBUFFERDESC bd;
176
DSCBCAPS bc;
177
- AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.in;
177
+ AudiodevPerDirectionOptions *pdo = hw->s->dev->u.dsound.in;
178
#else
179
const char *typ = "DAC";
180
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
181
DSBUFFERDESC bd;
182
DSBCAPS bc;
183
- AudiodevPerDirectionOptions *pdo = s->dev->u.dsound.out;
183
+ AudiodevPerDirectionOptions *pdo = hw->s->dev->u.dsound.out;
184
#endif
185
186
if (!s->FIELD2) {
@@ -256,7 +256,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
256
}
257
hw->size_emul = bc.dwBufferBytes;
258
hw->samples = bc.dwBufferBytes / hw->info.bytes_per_frame;
259
- ds->s = s;
259
260
#ifdef DEBUG_DSOUND
261
dolog ("caps %ld, desc %ld\n",
audio/dsoundaudio.c
+41
-46
@@ -45,40 +45,30 @@
45
#define TYPE_AUDIO_DSOUND "audio-dsound"
46
OBJECT_DECLARE_SIMPLE_TYPE(AudioDsound, AUDIO_DSOUND)
47
48
+static AudioBackendClass *audio_dsound_parent_class;
49
+
50
struct AudioDsound {
51
AudioMixengBackend parent_obj;
52
+
53
+ LPDIRECTSOUND dsound;
54
+ LPDIRECTSOUNDCAPTURE dsound_capture;
55
+ struct audsettings settings;
56
};
57
58
static struct audio_driver dsound_audio_driver;
59
54
-static void audio_dsound_class_init(ObjectClass *klass, const void *data)
55
-{
56
- AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
57
-
58
- k->driver = &dsound_audio_driver;
59
-}
60
-
60
/* #define DEBUG_DSOUND */
61
63
-typedef struct {
64
- LPDIRECTSOUND dsound;
65
- LPDIRECTSOUNDCAPTURE dsound_capture;
66
- struct audsettings settings;
67
- Audiodev *dev;
68
-} dsound;
69
-
62
typedef struct {
63
HWVoiceOut hw;
64
LPDIRECTSOUNDBUFFER dsound_buffer;
65
bool first_time;
74
- dsound *s;
66
} DSoundVoiceOut;
67
68
typedef struct {
69
HWVoiceIn hw;
70
LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
71
bool first_time;
81
- dsound *s;
72
} DSoundVoiceIn;
73
74
static const char *dserror(HRESULT hr)
@@ -276,7 +266,7 @@ static void print_wave_format (WAVEFORMATEX *wfx)
266
}
267
#endif
268
279
-static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
269
+static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, AudioDsound *s)
270
{
271
HRESULT hr;
272
@@ -295,7 +285,7 @@ static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb, dsound *s)
285
#undef DSBTYPE_IN
286
287
static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp,
298
- dsound *s)
288
+ AudioDsound *s)
289
{
290
HRESULT hr;
291
@@ -328,7 +318,7 @@ static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,
318
}
319
320
static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb,
331
- dsound *s)
321
+ AudioDsound *s)
322
{
323
int err;
324
LPVOID p1, p2;
@@ -372,9 +362,9 @@ static void dsound_enable_out(HWVoiceOut *hw, bool enable)
362
{
363
HRESULT hr;
364
DWORD status;
365
+ AudioDsound *s = AUDIO_DSOUND(hw->s);
366
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
367
LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
377
- dsound *s = ds->s;
368
369
if (!dsb) {
370
dolog ("Attempt to control voice without a buffer\n");
@@ -450,7 +440,7 @@ static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size)
440
assert(req_size > 0);
441
442
err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
453
- &act_size, NULL, false, ds->s);
443
+ &act_size, NULL, false, AUDIO_DSOUND(hw->s));
444
if (err) {
445
dolog("Failed to lock buffer\n");
446
*size = 0;
@@ -553,7 +543,7 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size)
543
}
544
545
err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL,
556
- &act_size, NULL, false, ds->s);
546
+ &act_size, NULL, false, AUDIO_DSOUND(hw->s));
547
if (err) {
548
dolog("Failed to lock buffer\n");
549
*size = 0;
@@ -577,13 +567,12 @@ static void dsound_put_buffer_in(HWVoiceIn *hw, void *buf, size_t len)
567
hw->pos_emul = (hw->pos_emul + len) % hw->size_emul;
568
}
569
580
-static void dsound_audio_fini (void *opaque)
570
+static void audio_dsound_finalize(Object *obj)
571
{
572
+ AudioDsound *s = AUDIO_DSOUND(obj);
573
HRESULT hr;
583
- dsound *s = opaque;
574
575
if (!s->dsound) {
586
- g_free(s);
576
return;
577
}
578
@@ -594,7 +583,6 @@ static void dsound_audio_fini (void *opaque)
583
s->dsound = NULL;
584
585
if (!s->dsound_capture) {
597
- g_free(s);
586
return;
587
}
588
@@ -603,18 +591,21 @@ static void dsound_audio_fini (void *opaque)
591
dsound_logerr (hr, "Could not release DirectSoundCapture\n");
592
}
593
s->dsound_capture = NULL;
606
-
607
- g_free(s);
594
}
595
610
-static void *dsound_audio_init(Audiodev *dev, Error **errp)
596
+static bool
597
+audio_dsound_realize(AudioBackend *abe, Audiodev *dev, Error **errp)
598
{
599
+ AudioDsound *s = AUDIO_DSOUND(abe);
600
HRESULT hr;
613
- dsound *s = g_new0(dsound, 1);
601
AudiodevDsoundOptions *dso;
602
603
assert(dev->driver == AUDIODEV_DRIVER_DSOUND);
617
- s->dev = dev;
604
+
605
+ if (!audio_dsound_parent_class->realize(abe, dev, errp)) {
606
+ return false;
607
+ }
608
+
609
dso = &dev->u.dsound;
610
611
if (!dso->has_latency) {
@@ -625,8 +616,7 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
616
hr = CoInitialize (NULL);
617
if (FAILED (hr)) {
618
dserror_set(errp, hr, "Could not initialize COM");
628
- dsound_audio_fini(s);
629
- return NULL;
619
+ return false;
620
}
621
622
hr = CoCreateInstance (
@@ -638,15 +628,13 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
628
);
629
if (FAILED (hr)) {
630
dserror_set(errp, hr, "Could not create DirectSound instance");
641
- dsound_audio_fini(s);
642
- return NULL;
631
+ return false;
632
}
633
634
hr = IDirectSound_Initialize (s->dsound, NULL);
635
if (FAILED (hr)) {
636
dserror_set(errp, hr, "Could not initialize DirectSound");
648
- dsound_audio_fini(s);
649
- return NULL;
637
+ return false;
638
}
639
640
hr = CoCreateInstance (
@@ -658,15 +646,13 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
646
);
647
if (FAILED (hr)) {
648
dserror_set(errp, hr, "Could not create DirectSoundCapture instance");
661
- dsound_audio_fini(s);
662
- return NULL;
649
+ return false;
650
}
651
652
hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
653
if (FAILED(hr)) {
654
dserror_set(errp, hr, "Could not initialize DirectSoundCapture");
668
- dsound_audio_fini(s);
669
- return NULL;
655
+ return false;
656
}
657
658
hr = IDirectSound_SetCooperativeLevel (
@@ -676,11 +662,10 @@ static void *dsound_audio_init(Audiodev *dev, Error **errp)
662
);
663
if (FAILED(hr)) {
664
dserror_set(errp, hr, "Could not set cooperative level");
679
- dsound_audio_fini(s);
680
- return NULL;
665
+ return false;
666
}
667
683
- return s;
668
+ return true;
669
}
670
671
static struct audio_pcm_ops dsound_pcm_ops = {
@@ -702,8 +687,6 @@ static struct audio_pcm_ops dsound_pcm_ops = {
687
688
static struct audio_driver dsound_audio_driver = {
689
.name = "dsound",
705
- .init = dsound_audio_init,
706
- .fini = dsound_audio_fini,
690
.pcm_ops = &dsound_pcm_ops,
691
.max_voices_out = INT_MAX,
692
.max_voices_in = 1,
@@ -711,12 +694,24 @@ static struct audio_driver dsound_audio_driver = {
694
.voice_size_in = sizeof (DSoundVoiceIn)
695
};
696
697
+static void audio_dsound_class_init(ObjectClass *klass, const void *data)
698
+{
699
+ AudioBackendClass *b = AUDIO_BACKEND_CLASS(klass);
700
+ AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_CLASS(klass);
701
+
702
+ audio_dsound_parent_class = AUDIO_BACKEND_CLASS(object_class_get_parent(klass));
703
+
704
+ b->realize = audio_dsound_realize;
705
+ k->driver = &dsound_audio_driver;
706
+}
707
+
708
static const TypeInfo audio_types[] = {
709
{
710
.name = TYPE_AUDIO_DSOUND,
711
.parent = TYPE_AUDIO_MIXENG_BACKEND,
712
.instance_size = sizeof(AudioDsound),
713
.class_init = audio_dsound_class_init,
714
+ .instance_finalize = audio_dsound_finalize,
715
},
716
};
717