Esempio n. 1
0
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;
	}
}
Esempio n. 2
0
static unsigned int ALSA_RW_GetDMAPos (soundcardinfo_t *sc)
{
	int frames;
	frames = psnd_pcm_avail_update(sc->handle);
	if (frames < 0)
	{
		psnd_pcm_start (sc->handle);
		psnd_pcm_recover(sc->handle, frames, true);
		frames = psnd_pcm_avail_update(sc->handle);
	}
	if (frames >= 0)
	{
		sc->sn.samplepos = (sc->snd_sent + frames) * sc->sn.numchannels;
	}
	return sc->sn.samplepos;
}
Esempio n. 3
0
static unsigned int ALSA_MMap_GetDMAPos (soundcardinfo_t *sc)
{
	const snd_pcm_channel_area_t *areas;
	snd_pcm_uframes_t offset;
	snd_pcm_uframes_t nframes = sc->sn.samples / sc->sn.numchannels;

	psnd_pcm_avail_update (sc->handle);
	psnd_pcm_mmap_begin (sc->handle, &areas, &offset, &nframes);
	offset *= sc->sn.numchannels;
	nframes *= sc->sn.numchannels;
	sc->sn.samplepos = offset;
	sc->sn.buffer = areas->addr;
	return sc->sn.samplepos;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
static ALCuint alsa_available_samples(ALCdevice *Device)
{
    alsa_data *data = (alsa_data*)Device->ExtraData;
    snd_pcm_sframes_t avail;

    avail = (Device->Connected ? psnd_pcm_avail_update(data->pcmHandle) : 0);
    if(avail < 0)
    {
        AL_PRINT("avail update failed: %s\n", psnd_strerror(avail));

        if((avail=psnd_pcm_recover(data->pcmHandle, avail, 1)) >= 0 &&
           (avail=psnd_pcm_prepare(data->pcmHandle)) >= 0)
        {
            if(data->doCapture)
                avail = psnd_pcm_start(data->pcmHandle);
            if(avail >= 0)
                avail = psnd_pcm_avail_update(data->pcmHandle);
        }
        if(avail < 0)
        {
            AL_PRINT("restore error: %s\n", psnd_strerror(avail));
            aluHandleDisconnect(Device);
        }
    }
    while(avail > 0)
    {
        snd_pcm_sframes_t amt;

        amt = psnd_pcm_bytes_to_frames(data->pcmHandle, data->size);
        if(avail < amt) amt = avail;

        amt = psnd_pcm_readi(data->pcmHandle, data->buffer, amt);
        if(amt < 0)
        {
            AL_PRINT("read error: %s\n", psnd_strerror(amt));

            if(amt == -EAGAIN)
                continue;
            if((amt=psnd_pcm_recover(data->pcmHandle, amt, 1)) >= 0 &&
               (amt=psnd_pcm_prepare(data->pcmHandle)) >= 0)
            {
                if(data->doCapture)
                    amt = psnd_pcm_start(data->pcmHandle);
                if(amt >= 0)
                    amt = psnd_pcm_avail_update(data->pcmHandle);
            }
            if(amt < 0)
            {
                AL_PRINT("restore error: %s\n", psnd_strerror(amt));
                aluHandleDisconnect(Device);
                break;
            }
            avail = amt;
            continue;
        }

        WriteRingBuffer(data->ring, data->buffer, amt);
        avail -= amt;
    }

    return RingBufferSize(data->ring);
}