Exemplo n.º 1
0
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;
    }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
    }
}