Skip to content

Commit c046249

Browse files
committed
alsa: Simplify ALSA_WaitDevice.
- 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.
1 parent b4ac5f4 commit c046249

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

src/audio/alsa/SDL_alsa_audio.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -348,26 +348,22 @@ static char *get_pcm_str(void *handle)
348348
// This function waits until it is possible to write a full sound buffer
349349
static bool ALSA_WaitDevice(SDL_AudioDevice *device)
350350
{
351-
const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
352-
const int delay = SDL_max(fulldelay, 10);
351+
const int sample_frames = device->sample_frames;
352+
const int fulldelay = (int) ((((Uint64) sample_frames) * 1000) / device->spec.freq);
353+
const int delay = SDL_clamp(fulldelay, 1, 5);
354+
int total_delays = 0;
353355

354-
while (!SDL_GetAtomicInt(&device->shutdown)) {
355-
const int rc = ALSA_snd_pcm_wait(device->hidden->pcm, delay);
356-
if (rc < 0 && (rc != -EAGAIN)) {
357-
const int status = ALSA_snd_pcm_recover(device->hidden->pcm, rc, 0);
358-
if (status < 0) {
359-
// Hmm, not much we can do - abort
360-
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc));
361-
return false;
362-
}
363-
continue;
364-
}
356+
SDL_assert(fulldelay > 0); // so the `fulldelay * 5` below produces a reasonable result.
365357

366-
if (rc > 0) {
367-
break; // ready to go!
358+
while (!SDL_GetAtomicInt(&device->shutdown) && (ALSA_snd_pcm_avail(device->hidden->pcm) < sample_frames)) {
359+
if (total_delays >= (fulldelay * 5)) {
360+
// Hmm, not much we can do - abort
361+
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: hardware seems to have frozen, giving up on it.");
362+
return false;
363+
} else {
364+
SDL_Delay(delay);
365+
total_delays += delay; // THIS IS NOT EXACT, but just so we don't wait forever on problems...
368366
}
369-
370-
// Timed out! Make sure we aren't shutting down and then wait again.
371367
}
372368

373369
return true;
@@ -431,8 +427,11 @@ static int ALSA_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
431427
SDL_assert((buflen % frame_size) == 0);
432428

433429
const snd_pcm_sframes_t total_available = ALSA_snd_pcm_avail(device->hidden->pcm);
434-
const int total_frames = SDL_min(buflen / frame_size, total_available);
430+
if (total_available == 0) {
431+
return 0; // go back to WaitDevice and try again.
432+
}
435433

434+
const int total_frames = SDL_min(buflen / frame_size, total_available);
436435
const int rc = ALSA_snd_pcm_readi(device->hidden->pcm, buffer, total_frames);
437436

438437
SDL_assert(rc != -EAGAIN); // assuming this can't happen if we used snd_pcm_wait and queried for available space. snd_pcm_recover won't handle it!

0 commit comments

Comments
 (0)