@@ -348,26 +348,22 @@ static char *get_pcm_str(void *handle)
348
348
// This function waits until it is possible to write a full sound buffer
349
349
static bool ALSA_WaitDevice (SDL_AudioDevice * device )
350
350
{
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 ;
353
355
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.
365
357
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...
368
366
}
369
-
370
- // Timed out! Make sure we aren't shutting down and then wait again.
371
367
}
372
368
373
369
return true;
@@ -431,8 +427,11 @@ static int ALSA_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
431
427
SDL_assert ((buflen % frame_size ) == 0 );
432
428
433
429
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
+ }
435
433
434
+ const int total_frames = SDL_min (buflen / frame_size , total_available );
436
435
const int rc = ALSA_snd_pcm_readi (device -> hidden -> pcm , buffer , total_frames );
437
436
438
437
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