Просмотр исходного кода

wasapi: workaround that AudioClientProperties->Options not being available in old SDKs

Closes: https://github.com/libsdl-org/SDL/issues/15641.
Ozkan Sezer 1 день назад
Родитель
Сommit
bf03728873
3 измененных файлов с 34 добавлено и 10 удалено
  1. 26 10
      src/audio/wasapi/SDL_wasapi.c
  2. 5 0
      src/core/windows/SDL_windows.c
  3. 3 0
      src/core/windows/SDL_windows.h

+ 26 - 10
src/audio/wasapi/SDL_wasapi.c

@@ -64,6 +64,19 @@ static const IID SDL_IID_IAudioClient3 = { 0x7ed4ee07, 0x8e67, 0x4cd4, { 0x8c, 0
 static bool immdevice_initialized = false;
 static bool supports_recording_on_playback_devices = false;
 
+#ifdef __IAudioClient2_INTERFACE_DEFINED__
+#define SDL_AUDCLNT_STREAMOPTIONS_RAW 0x1
+typedef union SDL_AudioClientProperties {
+    AudioClientProperties a;
+    struct _SDL_AudioClientProperties {
+        UINT32 cbSize;
+        BOOL bIsOffload;
+        AUDIO_STREAM_CATEGORY eCategory;
+        int Options; // AUDCLNT_STREAMOPTIONS
+    } s;
+} SDL_AudioClientProperties;
+#endif //
+
 // WASAPI is _really_ particular about various things happening on the same thread, for COM and such,
 //  so we proxy various stuff to a single background thread to manage.
 
@@ -741,10 +754,10 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
     IAudioClient2 *client2 = NULL;
     ret = IAudioClient_QueryInterface(client, &SDL_IID_IAudioClient2, (void **)&client2);
     if (SUCCEEDED(ret)) {
-        AudioClientProperties audioProps;
+        SDL_AudioClientProperties audioProps;
 
         SDL_zero(audioProps);
-        audioProps.cbSize = sizeof(audioProps);
+        audioProps.a.cbSize = sizeof(audioProps);
 
 // Setting AudioCategory_GameChat breaks audio on several devices, including Behringer U-PHORIA UM2 and RODE NT-USB Mini.
 // We'll disable this for now until we understand more about what's happening.
@@ -752,25 +765,28 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
         const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_ROLE);
         if (hint && *hint) {
             if (SDL_strcasecmp(hint, "Communications") == 0) {
-                audioProps.eCategory = AudioCategory_Communications;
+                audioProps.a.eCategory = AudioCategory_Communications;
             } else if (SDL_strcasecmp(hint, "Game") == 0) {
                 // We'll add support for GameEffects as distinct from GameMedia later when we add stream roles
-                audioProps.eCategory = AudioCategory_GameEffects;
+                audioProps.a.eCategory = AudioCategory_GameEffects;
             } else if (SDL_strcasecmp(hint, "GameChat") == 0) {
-                audioProps.eCategory = AudioCategory_GameChat;
+                audioProps.a.eCategory = AudioCategory_GameChat;
             } else if (SDL_strcasecmp(hint, "Movie") == 0) {
-                audioProps.eCategory = AudioCategory_Movie;
+                audioProps.a.eCategory = AudioCategory_Movie;
             } else if (SDL_strcasecmp(hint, "Media") == 0) {
-                audioProps.eCategory = AudioCategory_Media;
+                audioProps.a.eCategory = AudioCategory_Media;
             }
         }
 #endif
 
-        if (SDL_GetHintBoolean(SDL_HINT_AUDIO_DEVICE_RAW_STREAM, false)) {
-            audioProps.Options = AUDCLNT_STREAMOPTIONS_RAW;
+        if (WIN_IsWindows81OrGreater() &&
+            SDL_GetHintBoolean(SDL_HINT_AUDIO_DEVICE_RAW_STREAM, false)) {
+            audioProps.s.Options = SDL_AUDCLNT_STREAMOPTIONS_RAW;
+        } else {
+            audioProps.a.cbSize = sizeof (AudioClientProperties);
         }
 
-        ret = IAudioClient2_SetClientProperties(client2, &audioProps);
+        ret = IAudioClient2_SetClientProperties(client2, (AudioClientProperties *)&audioProps);
         if (FAILED(ret)) {
             // This isn't fatal, let's log it instead of failing
             SDL_LogWarn(SDL_LOG_CATEGORY_AUDIO, "IAudioClient2_SetClientProperties failed: 0x%" SDL_PRIxSLONG, ret);

+ 5 - 0
src/core/windows/SDL_windows.c

@@ -374,6 +374,11 @@ BOOL WIN_IsWindows8OrGreater(void)
     CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0));
 }
 
+BOOL WIN_IsWindows81OrGreater(void)
+{
+    CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0));
+}
+
 BOOL WIN_IsWindows11OrGreater(void)
 {
     return IsWindowsBuildVersionAtLeast(22000);

+ 3 - 0
src/core/windows/SDL_windows.h

@@ -193,6 +193,9 @@ extern BOOL WIN_IsWindows7OrGreater(void);
 // Returns true if we're running on Windows 8 and newer
 extern BOOL WIN_IsWindows8OrGreater(void);
 
+// Returns true if we're running on Windows 8.1 and newer
+extern BOOL WIN_IsWindows81OrGreater(void);
+
 // Returns true if we're running on Windows 11 and newer
 extern BOOL WIN_IsWindows11OrGreater(void);