From 274aa0242e7bc91e5927663fd663581147496a78 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 23 Jun 2025 00:06:15 -0400
Subject: [PATCH] audio: Let apps save an audio stream from destruction during
SDL_Quit(). (#13244)
This is a special-case piece of functionality, generally these are expected
to go away during shutdown, but maybe someone is switching between audio
subsystems or something...
---
include/SDL3/SDL_audio.h | 12 ++++++++++++
src/audio/SDL_audio.c | 13 ++++++++++---
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h
index b91586fd6ac5c..90e0018b90561 100644
--- a/include/SDL3/SDL_audio.h
+++ b/include/SDL3/SDL_audio.h
@@ -1064,6 +1064,15 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
/**
* Get the properties associated with an audio stream.
*
+ * The application can hang any data it wants here, but
+ * the following properties are understood by SDL:
+ *
+ * - `SDL_PROP_AUDIOSTREAM_KEEP_ON_SHUTDOWN_BOOLEAN`: if true, the stream will
+ * not be automatically destroyed during SDL_Quit(). This property is
+ * ignored for streams created through SDL_OpenAudioDeviceStream(). Streams
+ * bound to devices that aren't destroyed will still be unbound.
+ * Default false. (since SDL 3.4.0)
+ *
* \param stream the SDL_AudioStream to query.
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
@@ -1074,6 +1083,9 @@ extern SDL_DECLSPEC SDL_AudioStream * SDLCALL SDL_CreateAudioStream(const SDL_Au
*/
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetAudioStreamProperties(SDL_AudioStream *stream);
+#define SDL_PROP_AUDIOSTREAM_KEEP_ON_SHUTDOWN_BOOLEAN "SDL.audiostream.keep_on_shutdown"
+
+
/**
* Query the current format of an audio stream.
*
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 90d9f9bba6321..e672e0dac0ff4 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -1073,9 +1073,16 @@ void SDL_QuitAudio(void)
current_audio.impl.DeinitializeStart();
- // Destroy any audio streams that still exist...
- while (current_audio.existing_streams) {
- SDL_DestroyAudioStream(current_audio.existing_streams);
+ // Destroy any audio streams that still exist...unless app asked to keep it.
+ SDL_AudioStream *next = NULL;
+ for (SDL_AudioStream *i = current_audio.existing_streams; i; i = next) {
+ next = i->next;
+ if (i->simplified || !SDL_GetBooleanProperty(i->props, SDL_PROP_AUDIOSTREAM_KEEP_ON_SHUTDOWN_BOOLEAN, false)) {
+ SDL_DestroyAudioStream(i);
+ } else {
+ i->prev = NULL;
+ i->next = NULL;
+ }
}
SDL_LockRWLockForWriting(current_audio.device_hash_lock);