|
@@ -333,33 +333,34 @@ static void no_swizzle(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen)
|
|
|
/* This function waits until it is possible to write a full sound buffer */
|
|
|
static void ALSA_WaitDevice(SDL_AudioDevice *device)
|
|
|
{
|
|
|
- const snd_pcm_sframes_t needed = (snd_pcm_sframes_t)device->sample_frames;
|
|
|
- while (!SDL_AtomicGet(&device->shutdown)) {
|
|
|
- const snd_pcm_sframes_t rc = ALSA_snd_pcm_avail(device->hidden->pcm_handle);
|
|
|
- if (rc < 0 && rc != -EAGAIN) {
|
|
|
- int status = rc;
|
|
|
+ const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
|
|
|
+ const int delay = SDL_max(fulldelay, 10);
|
|
|
|
|
|
- status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, status, 0);
|
|
|
+ while (!SDL_AtomicGet(&device->shutdown)) {
|
|
|
+ const int rc = ALSA_snd_pcm_wait(device->hidden->pcm_handle, delay);
|
|
|
+ if (rc < 0 && (rc != -EAGAIN)) {
|
|
|
+ const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
|
|
|
if (status < 0) {
|
|
|
/* Hmm, not much we can do - abort */
|
|
|
- fprintf(stderr, "ALSA snd_pcm_avail failed (unrecoverable): %s\n",
|
|
|
+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA snd_pcm_avail failed (unrecoverable): %s\n",
|
|
|
ALSA_snd_strerror(rc));
|
|
|
SDL_AudioDeviceDisconnected(device);
|
|
|
}
|
|
|
return;
|
|
|
- } else if (rc < needed) {
|
|
|
- const Uint32 delay = ((needed - (SDL_max(rc, 0))) * 1000) / device->spec.freq;
|
|
|
- SDL_Delay(SDL_max(delay, 10));
|
|
|
- } else {
|
|
|
- break; /* ready to go! */
|
|
|
}
|
|
|
+
|
|
|
+ if (rc > 0) {
|
|
|
+ break; // ready to go!
|
|
|
+ }
|
|
|
+
|
|
|
+ // Timed out! Make sure we aren't shutting down and then wait again.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
|
|
|
{
|
|
|
SDL_assert(buffer == device->hidden->mixbuf);
|
|
|
- Uint8 *sample_buf = device->hidden->mixbuf;
|
|
|
+ Uint8 *sample_buf = (Uint8 *) buffer; // !!! FIXME: deal with this without casting away constness
|
|
|
const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec);
|
|
|
snd_pcm_uframes_t frames_left = (snd_pcm_uframes_t) (buflen / frame_size);
|
|
|
|
|
@@ -368,6 +369,7 @@ static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buf
|
|
|
while ((frames_left > 0) && !SDL_AtomicGet(&device->shutdown)) {
|
|
|
int status = ALSA_snd_pcm_writei(device->hidden->pcm_handle,
|
|
|
sample_buf, frames_left);
|
|
|
+ //SDL_Log("ALSA PLAYDEVICE: WROTE %d of %d bytes", (status >= 0) ? ((int) (status * frame_size)) : status, (int) (frames_left * frame_size));
|
|
|
if (status < 0) {
|
|
|
if (status == -EAGAIN) {
|
|
|
/* Apparently snd_pcm_recover() doesn't handle this case -
|
|
@@ -399,6 +401,13 @@ 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);
|
|
|
+ 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_Log("ALSA GETDEVICEBUF: NEED %d BYTES", requested_bytes);
|
|
|
+ *buffer_size = requested_bytes;
|
|
|
return device->hidden->mixbuf;
|
|
|
}
|
|
|
|