From 6cba25187fee21a7a8885df32eb85ef6854c53bb Mon Sep 17 00:00:00 2001 From: Ian Monroe Date: Sun, 31 May 2026 11:07:53 -0700 Subject: [PATCH] audio: add a SDL_GetPhysicalAudioDevice method, for mapping logical to physical device ids --- include/SDL3/SDL_audio.h | 15 +++++++++++++++ src/audio/SDL_audio.c | 14 ++++++++++++++ src/dynapi/SDL_dynapi.exports | 1 + src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + 6 files changed, 33 insertions(+) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 1757ff0353..b55b548190 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -759,6 +759,21 @@ extern SDL_DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(SDL_AudioDevic */ extern SDL_DECLSPEC bool SDLCALL SDL_IsAudioDevicePhysical(SDL_AudioDeviceID devid); +/** + * Get the physical audio device associated with a logical audio device. + * + * If `devid` is already a physical device, this function returns `devid`. + * If `devid` is an invalid device, it returns 0. + * + * \param devid the device ID to query. + * \returns the physical device ID, or 0 on error. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.5.0. + */ +extern SDL_DECLSPEC SDL_AudioDeviceID SDLCALL SDL_GetPhysicalAudioDevice(SDL_AudioDeviceID devid); + /** * Determine if an audio device is a playback device (instead of recording). * diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 4284a7fd27..2999da962d 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -538,6 +538,20 @@ static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceI return NULL; } +SDL_AudioDeviceID SDL_GetPhysicalAudioDevice(SDL_AudioDeviceID devid) +{ + if (SDL_IsAudioDevicePhysical(devid)) { + return devid; + } + + SDL_AudioDeviceID result = 0; + SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); + if (device) { + result = device->instance_id; + ReleaseAudioDevice(device); + } + return result; +} // this assumes you hold the _physical_ device lock for this logical device! This will not unlock the lock or close the physical device! // It also will not unref the physical device, since we might be shutting down; SDL_CloseAudioDevice handles the unref. static void DestroyLogicalAudioDevice(SDL_LogicalAudioDevice *logdev) diff --git a/src/dynapi/SDL_dynapi.exports b/src/dynapi/SDL_dynapi.exports index 9864557071..fb3faeeac3 100644 --- a/src/dynapi/SDL_dynapi.exports +++ b/src/dynapi/SDL_dynapi.exports @@ -1290,3 +1290,4 @@ _SDL_LoadJPG _SDL_HasSVE2 _SDL_GamepadHasCapSense _SDL_GetGamepadCapSense +_SDL_GetPhysicalAudioDevice diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 3958a52aa6..0f2d6d4b6a 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1291,6 +1291,7 @@ SDL3_0.0.0 { SDL_HasSVE2; SDL_GamepadHasCapSense; SDL_GetGamepadCapSense; + SDL_GetPhysicalAudioDevice; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index b54d32ae6d..f90d41dd6d 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1317,3 +1317,4 @@ #define SDL_HasSVE2 SDL_HasSVE2_REAL #define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL #define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL +#define SDL_GetPhysicalAudioDevice SDL_GetPhysicalAudioDevice_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 4f8ac0ba0c..74a5b933b0 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1325,3 +1325,4 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG,(const char *a),(a),return) SDL_DYNAPI_PROC(bool,SDL_HasSVE2,(void),(),return) SDL_DYNAPI_PROC(bool,SDL_GamepadHasCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return) SDL_DYNAPI_PROC(bool,SDL_GetGamepadCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return) +SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetPhysicalAudioDevice,(SDL_AudioDeviceID a),(a),return)