static void ALSA_PlayAudio(_THIS) { int status; snd_pcm_uframes_t frames_left; const Uint8 *sample_buf = (const Uint8 *) mixbuf; const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) * this->spec.channels; swizzle_alsa_channels(this); frames_left = ((snd_pcm_uframes_t) this->spec.samples); while ( frames_left > 0 && this->enabled ) { /* This works, but needs more testing before going live */ /*SDL_NAME(snd_pcm_wait)(pcm_handle, -1);*/ status = SDL_NAME(snd_pcm_writei)(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 = SDL_NAME(snd_pcm_recover)(pcm_handle, status, 0); if ( status < 0 ) { /* Hmm, not much we can do - abort */ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", SDL_NAME(snd_strerror)(status)); this->enabled = 0; return; } continue; } sample_buf += status * frame_size; frames_left -= status; } }
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 int ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen) { Uint8 *sample_buf = (Uint8 *) buffer; const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) * this->spec.channels; const int total_frames = buflen / frame_size; snd_pcm_uframes_t frames_left = total_frames; SDL_assert((buflen % frame_size) == 0); while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) { /* !!! FIXME: This works, but needs more testing before going live */ /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */ int status = ALSA_snd_pcm_readi(this->hidden->pcm_handle, sample_buf, frames_left); if (status < 0) { /*printf("ALSA: capture error %d\n", status);*/ 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 read failed (unrecoverable): %s\n", ALSA_snd_strerror(status)); return -1; } continue; } /*printf("ALSA: captured %d bytes\n", status * frame_size);*/ sample_buf += status * frame_size; frames_left -= status; } swizzle_alsa_channels(this, buffer, total_frames - frames_left); return (total_frames - frames_left) * frame_size; }
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) { 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) ) { /* !!! FIXME: This works, but needs more testing before going live */ /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */ int 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; } }