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...
- Check for specific availability instead of waiting for "device ready."
- Don't use snd_pcm_wait, just use a simple SDL_Delay (nothing to recover).
- Fixed SDL_max call that should have been SDL_min (now using SDL_clamp).
- ALSA_RecordDevice() now returns 0 if no availability, which kicks us back
to WaitDevice to try again, as an extra safety check.
The keys and values of device_hash are pairs
`(SDL_AudioDeviceID devid, void *dev)` where dev can be either a
`SDL_AudioDevice *` or a `SDL_LogicalAudioDevice *`, depending on
bit 1 of devid.
We can confirm that we have got this right by looking at the
instance_id member, because logical audio devices happen to start with
the devid, whereas physical devices start with a pointer which is
unlikely to match the devid by chance.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This info shows up in `pw-top` ...Gnome's sound preferences (etc) would
already show something more app-specific, but this command line tool shows
specific stream names.
Previously, we would WaitDevice first, but that would feed a silent buffer
to AAudio upfront, introducing latency. When this change was made, the
semaphore count should have been adjusted, since we're waiting on one less
buffer.
Fixes#12882.
- Add checks that ObtainPhysicalAudioDevice() was previously doing
(is subsystem initialized, is device valid).
- Remove optimizations that copy string to stack to release device_hash_lock
before SDL_GetPersistentString is called. Probably not necessary, and made
the code more complex.
This warning is actually wrong, as the variable is only used if the string pointer is valid, in which case it was initialized, but this is needed to quiet MSVC.
These callbacks run in a thread we don't control, but might call SDL_SetError,
which will claim a TLS slot that never gets otherwise deallocated. To prevent
the leak, finish each callback by explicitly freeing any thread-local data.
Fixes#12732.
SDL still manages hotplug and default device management here, but if a user
wants to use an external tool, such as `pactl move-sink-input`, to put it
onto a different device, they probably know what they're doing and we
shouldn't stop them.
If this turns out to have some unexpected consequences, though, we can revisit
the change.
Fixes https://github.com/libsdl-org/sdl2-compat/issues/367
Otherwise, in the time it takes the thread to start and other init tasks to
complete, we tend to get an underrun on some systems, which ALSA logs to
stderr.
So this is moved to an InitThread implementation, which runs from the device
thread, right before it begins its main loop.
Reference PR #12632.
When the flushing is not able to keep up with the audio stream coming in, it
will end up flushing forever and block API clients from getting any audio.
The example program in #9706 get some audio with SDL 3, while do not get any
audio with SDL 2, which I suspect is because SDL 3 is quicker at flushing the audio.
A fix for the SDL 2 issue is available in #12378.
If the pipewire thread invokes output_callback() while we're still
waiting inside PIPEWIRE_OpenDevice(), we will deadlock. The pipewire
thread owns the loop lock and is blocked on the audio device lock,
which cannot be released because pw_thread_loop_wait() needs to
reacquire the loop lock before it can return and allow
PIPEWIRE_OpenDevice() to complete and release the device lock.