static void ALSA_MMap_Submit (soundcardinfo_t *sc, int start, int end) { int state; int count = end - start; const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t nframes; snd_pcm_uframes_t offset; nframes = count / sc->sn.numchannels; psnd_pcm_avail_update (sc->handle); psnd_pcm_mmap_begin (sc->handle, &areas, &offset, &nframes); state = psnd_pcm_state (sc->handle); switch (state) { case SND_PCM_STATE_PREPARED: psnd_pcm_mmap_commit (sc->handle, offset, nframes); psnd_pcm_start (sc->handle); break; case SND_PCM_STATE_RUNNING: psnd_pcm_mmap_commit (sc->handle, offset, nframes); break; default: break; } }
static ALuint ALSAProc(ALvoid *ptr) { ALCdevice *pDevice = (ALCdevice*)ptr; alsa_data *data = (alsa_data*)pDevice->ExtraData; const snd_pcm_channel_area_t *areas = NULL; snd_pcm_sframes_t avail, commitres; snd_pcm_uframes_t offset, frames; char *WritePtr; int err; while(!data->killNow) { int state = verify_state(data->pcmHandle); if(state < 0) { AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state)); aluHandleDisconnect(pDevice); break; } avail = psnd_pcm_avail_update(data->pcmHandle); if(avail < 0) { AL_PRINT("available update failed: %s\n", psnd_strerror(avail)); continue; } // make sure there's frames to process if(avail >= 0 && avail < (snd_pcm_sframes_t)pDevice->UpdateSize) { if(state != SND_PCM_STATE_RUNNING) { err = psnd_pcm_start(data->pcmHandle); if(err < 0) { AL_PRINT("start failed: %s\n", psnd_strerror(err)); continue; } } if(psnd_pcm_wait(data->pcmHandle, 1000) == 0) AL_PRINT("Wait timeout... buffer size too low?\n"); continue; } avail -= avail%pDevice->UpdateSize; // it is possible that contiguous areas are smaller, thus we use a loop while(avail > 0) { frames = avail; err = psnd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames); if(err < 0) { AL_PRINT("mmap begin error: %s\n", psnd_strerror(err)); break; } WritePtr = (char*)areas->addr + (offset * areas->step / 8); aluMixData(pDevice, WritePtr, frames); commitres = psnd_pcm_mmap_commit(data->pcmHandle, offset, frames); if(commitres < 0 || (commitres-frames) != 0) { AL_PRINT("mmap commit error: %s\n", psnd_strerror(commitres >= 0 ? -EPIPE : commitres)); break; } avail -= frames; } } return 0; }