audio: Split Deinitialize into two stages.

First stage happens before we destroy objects, and is generally used to
shut down hotplug. The second stage is the usual deinit, which cleans up
the lowlevel API, unloads shared libraries, etc.
This commit is contained in:
Ryan C. Gordon
2023-10-18 10:41:20 -04:00
parent e55e556f32
commit 7a52f7b3fd
12 changed files with 85 additions and 12 deletions

View File

@@ -714,6 +714,18 @@ static void WASAPI_FreeDeviceHandle(SDL_AudioDevice *device)
WASAPI_ProxyToManagementThread(mgmtthrtask_FreeDeviceHandle, device, &rc);
}
static int mgmtthrtask_DeinitializeStart(void *userdata)
{
WASAPI_PlatformDeinitializeStart(void);
return 0;
}
static void WASAPI_DeinitializeStart(void)
{
int rc;
WASAPI_ProxyToManagementThread(mgmtthrtask_DeinitializeStart, NULL, &rc);
}
static void WASAPI_Deinitialize(void)
{
DeinitManagementThread();
@@ -736,6 +748,7 @@ static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl)
impl->CaptureFromDevice = WASAPI_CaptureFromDevice;
impl->FlushCapture = WASAPI_FlushCapture;
impl->CloseDevice = WASAPI_CloseDevice;
impl->DeinitializeStart = WASAPI_DeinitializeStart;
impl->Deinitialize = WASAPI_Deinitialize;
impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle;

View File

@@ -58,6 +58,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in
// UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD.
int WASAPI_PlatformInit(void);
void WASAPI_PlatformDeinit(void);
void WASAPI_PlatformDeinitializeStart(void);
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture);
int WASAPI_ActivateDevice(SDL_AudioDevice *device);
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.

View File

@@ -44,15 +44,21 @@ typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE);
static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL;
static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL;
static SDL_bool immdevice_initialized = SDL_FALSE;
/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */
static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } };
int WASAPI_PlatformInit(void)
{
if (SDL_IMMDevice_Init() < 0) { // this will call WIN_CoInitialize for us!
return -1; /* This is set by SDL_IMMDevice_Init */
if (FAILED(WIN_CoInitialize())) {
return SDL_SetError("CoInitialize() failed");
} else if (SDL_IMMDevice_Init() < 0) {
return -1; // Error string is set by SDL_IMMDevice_Init
}
immdevice_initialized = SDL_TRUE;
libavrt = LoadLibrary(TEXT("avrt.dll")); /* this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! */
if (libavrt) {
pAvSetMmThreadCharacteristicsW = (pfnAvSetMmThreadCharacteristicsW)GetProcAddress(libavrt, "AvSetMmThreadCharacteristicsW");
@@ -62,6 +68,14 @@ int WASAPI_PlatformInit(void)
return 0;
}
static void StopWasapiHotplug(void)
{
if (immdevice_initialized) {
SDL_IMMDevice_Quit();
immdevice_initialized = SDL_FALSE;
}
}
void WASAPI_PlatformDeinit(void)
{
if (libavrt) {
@@ -72,7 +86,14 @@ void WASAPI_PlatformDeinit(void)
pAvSetMmThreadCharacteristicsW = NULL;
pAvRevertMmThreadCharacteristics = NULL;
SDL_IMMDevice_Quit(); // This will call WIN_CoUninitialize for us!
StopWasapiHotplug();
WIN_CoUninitialize();
}
void WASAPI_PlatformDeinitializeStart(void)
{
StopWasapiHotplug();
}
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)

View File

@@ -220,7 +220,7 @@ int WASAPI_PlatformInit(void)
return 0;
}
void WASAPI_PlatformDeinit(void)
static void StopWasapiHotplug(void)
{
delete playback_device_event_handler;
playback_device_event_handler = nullptr;
@@ -228,6 +228,17 @@ void WASAPI_PlatformDeinit(void)
capture_device_event_handler = nullptr;
}
void WASAPI_PlatformDeinit(void)
{
StopWasapiHotplug();
}
void WASAPI_PlatformDeinitializeStart(void)
{
StopWasapiHotplug();
}
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture)
{
Platform::String ^ defdevid;