From e68f5ca99ac536e93e56ddd8115c058e9627aacb Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 20 Jun 2025 15:23:59 -0700
Subject: [PATCH] alsa: use udev if available instead of a hotplug thread
This makes detecting audio device changes more responsive.
---
src/audio/alsa/SDL_alsa_audio.c | 69 +++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 3 deletions(-)
diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c
index 9cc991299e968..f8bd072bb33f3 100644
--- a/src/audio/alsa/SDL_alsa_audio.c
+++ b/src/audio/alsa/SDL_alsa_audio.c
@@ -38,6 +38,7 @@
#include "../SDL_sysaudio.h"
#include "SDL_alsa_audio.h"
+#include "../../core/linux/SDL_udev.h"
#if SDL_ALSA_DEBUG
#define LOGDEBUG(...) SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "ALSA: " __VA_ARGS__)
@@ -1441,6 +1442,65 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
}
#endif
+#ifdef SDL_USE_LIBUDEV
+
+static bool udev_initialized;
+
+static void ALSA_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
+{
+ if (!devpath) {
+ return;
+ }
+
+ switch (udev_type) {
+ case SDL_UDEV_DEVICEADDED:
+ ALSA_HotplugIteration(NULL, NULL);
+ break;
+
+ case SDL_UDEV_DEVICEREMOVED:
+ ALSA_HotplugIteration(NULL, NULL);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static bool ALSA_start_udev()
+{
+ udev_initialized = SDL_UDEV_Init();
+ if (udev_initialized) {
+ // Set up the udev callback
+ if (!SDL_UDEV_AddCallback(ALSA_udev_callback)) {
+ SDL_UDEV_Quit();
+ udev_initialized = false;
+ }
+ }
+ return udev_initialized;
+}
+
+static void ALSA_stop_udev()
+{
+ if (udev_initialized) {
+ SDL_UDEV_DelCallback(ALSA_udev_callback);
+ SDL_UDEV_Quit();
+ udev_initialized = false;
+ }
+}
+
+#else
+
+static bool ALSA_start_udev()
+{
+ return false;
+}
+
+static void ALSA_stop_udev()
+{
+}
+
+#endif // SDL_USE_LIBUDEV
+
static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{
ALSA_guess_device_prefix();
@@ -1456,11 +1516,13 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevi
*default_recording = SDL_AddAudioDevice(/*recording=*/true, "ALSA default recording device", NULL, (void *)&default_recording_handle);
}
+ if (!ALSA_start_udev()) {
#if SDL_ALSA_HOTPLUG_THREAD
- SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 0);
- ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL);
- // if the thread doesn't spin, oh well, you just don't get further hotplug events.
+ SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 0);
+ ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL);
+ // if the thread doesn't spin, oh well, you just don't get further hotplug events.
#endif
+ }
}
static void ALSA_DeinitializeStart(void)
@@ -1475,6 +1537,7 @@ static void ALSA_DeinitializeStart(void)
ALSA_hotplug_thread = NULL;
}
#endif
+ ALSA_stop_udev();
// Shutting down! Clean up any data we've gathered.
for (dev = hotplug_devices; dev; dev = next) {