static void ALSA_RW_Submit (soundcardinfo_t *sc, int start, int end) { // int state; unsigned int frames, offset, ringsize; unsigned chunk; int result; int stride = sc->sn.numchannels * (sc->sn.samplebits/8); while(1) { /*we can't change the data that was already written*/ frames = end - sc->snd_sent; if (frames <= 0) return; // state = psnd_pcm_state (sc->handle); ringsize = sc->sn.samples / sc->sn.numchannels; chunk = frames; offset = sc->snd_sent % ringsize; if (offset + chunk >= ringsize) chunk = ringsize - offset; result = psnd_pcm_writei(sc->handle, sc->sn.buffer + offset*stride, chunk); if (result < chunk) { if (result < 0) return; } sc->snd_sent += chunk; chunk = frames - chunk; if (chunk) { result = psnd_pcm_writei(sc->handle, sc->sn.buffer, chunk); if (result > 0) sc->snd_sent += result; } // if (state == SND_PCM_STATE_PREPARED) // psnd_pcm_start (sc->handle); }; }
static ALuint ALSANoMMapProc(ALvoid *ptr) { ALCdevice *pDevice = (ALCdevice*)ptr; alsa_data *data = (alsa_data*)pDevice->ExtraData; snd_pcm_sframes_t avail; char *WritePtr; SetRTPriority(); 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; } WritePtr = data->buffer; avail = data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1); aluMixData(pDevice, WritePtr, avail); while(avail > 0) { int ret = psnd_pcm_writei(data->pcmHandle, WritePtr, avail); switch (ret) { case -EAGAIN: continue; case -ESTRPIPE: case -EPIPE: case -EINTR: ret = psnd_pcm_recover(data->pcmHandle, ret, 1); if(ret >= 0) psnd_pcm_prepare(data->pcmHandle); break; default: if (ret >= 0) { WritePtr += psnd_pcm_frames_to_bytes(data->pcmHandle, ret); avail -= ret; } break; } if (ret < 0) { ret = psnd_pcm_prepare(data->pcmHandle); if(ret < 0) break; } } } return 0; }