SDL: Wait a bit when snd_pcm_avail() returns 0

From 6a152676bb7519aec86f6045e2bdda088bc83b91 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 30 Sep 2023 10:48:44 -0700
Subject: [PATCH] Wait a bit when snd_pcm_avail() returns 0

The hardware might report that it's ready and still need a bit of time to start processing samples
---
 src/audio/alsa/SDL_alsa_audio.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c
index 7e100cf9ba7b..90559b05aec3 100644
--- a/src/audio/alsa/SDL_alsa_audio.c
+++ b/src/audio/alsa/SDL_alsa_audio.c
@@ -337,7 +337,7 @@ static void ALSA_WaitDevice(SDL_AudioDevice *device)
             const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
             if (status < 0) {
                 // Hmm, not much we can do - abort
-                SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_avail failed (unrecoverable): %s", ALSA_snd_strerror(rc));
+                SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
                 SDL_AudioDeviceDisconnected(device);
             }
             return;
@@ -384,9 +384,20 @@ static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buf
 
 static Uint8 *ALSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
 {
-    const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
+    snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
+    if (rc <= 0) {
+        // Wait a bit and try again, maybe the hardware isn't quite ready yet?
+        SDL_Delay(10);
+
+        rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
+        if (rc <= 0) {
+            // We'll catch it next time
+            *buffer_size = 0;
+            return NULL;
+        }
+    }
+
     const int requested_frames = SDL_min(device->sample_frames, rc);
-    SDL_assert(requested_frames > 0);
     const int requested_bytes = requested_frames * SDL_AUDIO_FRAMESIZE(device->spec);
     SDL_assert(requested_bytes <= *buffer_size);
     //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA GETDEVICEBUF: NEED %d BYTES", requested_bytes);