mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-23 15:55:49 +08:00
audio: Reworked audio device disconnect management.
- No more tapdance to either join the audio device thread or have it detach itself. Significant simplication of and fixes to the locking code to prevent deadlocks. - Physical devices now keep a refcount. Each logical device increments it, as does the existence of a device thread, etc. Last unref destroys the device and takes it out of the device_hash. Since there's a lot of moving parts that might be holding a reference to a physical device, this seemed like a safer way to protect the object. - Disconnected devices now continue to function as zombie devices. Playback devices will still consume data (and just throw it away), and capture devices will continue to produce data (which always be silence). This helps apps that don't handle disconnect events; the device still stops playing/capturing, but bound audio streams will still consume data so they don't allocate more data infinitely, and apps that depend on an audio callback firing regularly to make progress won't hang. Please note that disconnected audio devices must now be explicitly closed! They always _should_ have been, but before this commit, SDL3 would destroy the disconnected device for you (and manually closing afterwards was a safe no-op). Reference Issue #8331. Fixes #8386. (and probably others).
This commit is contained in:
+186
-143
File diff suppressed because it is too large
Load Diff
@@ -244,6 +244,17 @@ struct SDL_AudioDevice
|
||||
// A mutex for locking access to this struct
|
||||
SDL_Mutex *lock;
|
||||
|
||||
// Reference count of the device; logical devices, device threads, etc, add to this.
|
||||
SDL_AtomicInt refcount;
|
||||
|
||||
// These are, initially, set from current_audio, but we might swap them out with Zombie versions on disconnect/failure.
|
||||
int (*WaitDevice)(SDL_AudioDevice *device);
|
||||
int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen);
|
||||
Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size);
|
||||
int (*WaitCaptureDevice)(SDL_AudioDevice *device);
|
||||
int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen);
|
||||
void (*FlushCapture)(SDL_AudioDevice *device);
|
||||
|
||||
// human-readable name of the device. ("SoundBlaster Pro 16")
|
||||
char *name;
|
||||
|
||||
@@ -269,15 +280,9 @@ struct SDL_AudioDevice
|
||||
// non-zero if we are signaling the audio thread to end.
|
||||
SDL_AtomicInt shutdown;
|
||||
|
||||
// non-zero if we want the device to be destroyed (so audio thread knows to do it on termination).
|
||||
SDL_AtomicInt condemned;
|
||||
|
||||
// non-zero if this was a disconnected default device and we're waiting for its replacement.
|
||||
SDL_AtomicInt zombie;
|
||||
|
||||
// non-zero if this has a thread running (which might be `thread` or something provided by the backend!)
|
||||
SDL_AtomicInt thread_alive;
|
||||
|
||||
// SDL_TRUE if this is a capture device instead of an output device
|
||||
SDL_bool iscapture;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user