@samitouri / QOSamiQemu / commits / 58e9ca99db

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