static void ALSA_PlayDevice(_THIS) { const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf; const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) * this->spec.channels; snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples); swizzle_alsa_channels(this, this->hidden->mixbuf, frames_left); while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) { int status; /* This wait is a work-around for a hang when USB devices are unplugged. Normally it should not result in any waiting, but in the case of a USB unplug, it serves as a way to join the playback thread after the timeout occurs */ status = ALSA_snd_pcm_wait(this->hidden->pcm_handle, 1000); if (status == 0) { /*fprintf(stderr, "ALSA timeout waiting for available buffer space\n");*/ SDL_OpenedAudioDeviceDisconnected(this); return; } status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, sample_buf, frames_left); if (status < 0) { if (status == -EAGAIN) { /* Apparently snd_pcm_recover() doesn't handle this case - does it assume snd_pcm_wait() above? */ SDL_Delay(1); continue; } status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0); if (status < 0) { /* Hmm, not much we can do - abort */ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", ALSA_snd_strerror(status)); SDL_OpenedAudioDeviceDisconnected(this); return; } continue; } sample_buf += status * frame_size; frames_left -= status; } }
static void ALSA_PlayDevice(_THIS) { int status; int sample_len; signed short *sample_buf; swizzle_alsa_channels(this); sample_len = this->spec.samples; sample_buf = (signed short *) this->hidden->mixbuf; while (sample_len > 0) { status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, sample_buf, sample_len); if (status < 0) { if (status == -EAGAIN) { SDL_Delay(1); continue; } if (status == -ESTRPIPE) { do { SDL_Delay(1); status = ALSA_snd_pcm_resume(this->hidden->pcm_handle); } while (status == -EAGAIN); } if (status < 0) { status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle); } if (status < 0) { /* Hmm, not much we can do - abort */ this->enabled = 0; return; } continue; } sample_buf += status * this->spec.channels; sample_len -= status; } }
static void ALSA_PlayDevice(_THIS) { int status; const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf; const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) * this->spec.channels; snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples); swizzle_alsa_channels(this); while ( frames_left > 0 && this->enabled ) { /* !!! FIXME: This works, but needs more testing before going live */ /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */ status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, sample_buf, frames_left); if (status < 0) { if (status == -EAGAIN) { /* Apparently snd_pcm_recover() doesn't handle this case - does it assume snd_pcm_wait() above? */ SDL_Delay(1); continue; } status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0); if (status < 0) { /* Hmm, not much we can do - abort */ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", ALSA_snd_strerror(status)); this->enabled = 0; return; } continue; } sample_buf += status * frame_size; frames_left -= status; } }