wasapi: Force WIN_CoInitialize duing device open. Otherwise this won't work if you open a device on a background thread. Fixes #7478.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c
index dc22ecd..c465776 100644
--- a/src/audio/wasapi/SDL_wasapi.c
+++ b/src/audio/wasapi/SDL_wasapi.c
@@ -371,6 +371,11 @@ void WASAPI_UnrefDevice(_THIS)
our callback thread. We do that in WASAPI_ThreadDeinit().
(likewise for this->hidden->coinitialized). */
ReleaseWasapiDevice(this);
+
+ if (SDL_ThreadID() == this->hidden->open_threadid) {
+ WIN_CoUninitialize(); /* if you closed from a different thread than you opened, sorry, it's a leak. We can't help you. */
+ }
+
SDL_free(this->hidden->devid);
SDL_free(this->hidden);
}
@@ -539,6 +544,11 @@ static int WASAPI_OpenDevice(_THIS, const char *devname)
WASAPI_RefDevice(this); /* so CloseDevice() will unref to zero. */
+ if (FAILED(WIN_CoInitialize())) { /* WASAPI uses COM, we need to make sure it's initialized. You have to close the device from the same thread!! */
+ return SDL_SetError("WIN_CoInitialize failed during WASAPI device open");
+ }
+ this->hidden->open_threadid = SDL_ThreadID(); /* set this _after_ coinitialize so we don't uninit if device fails at the wrong moment. */
+
if (!devid) { /* is default device? */
this->hidden->default_device_generation = SDL_AtomicGet(this->iscapture ? &SDL_IMMDevice_DefaultCaptureGeneration : &SDL_IMMDevice_DefaultPlaybackGeneration);
} else {
diff --git a/src/audio/wasapi/SDL_wasapi.h b/src/audio/wasapi/SDL_wasapi.h
index c3485eb..96c2061 100644
--- a/src/audio/wasapi/SDL_wasapi.h
+++ b/src/audio/wasapi/SDL_wasapi.h
@@ -47,6 +47,7 @@ struct SDL_PrivateAudioData
SDL_AudioStream *capturestream;
HANDLE event;
HANDLE task;
+ SDL_threadID open_threadid;
SDL_bool coinitialized;
int framesize;
int default_device_generation;