Read capture data from ALSA when querying the available sample count
This commit is contained in:
parent
98c01a40e6
commit
1915fe831f
142
Alc/alsa.c
142
Alc/alsa.c
@ -40,7 +40,6 @@ typedef struct {
|
||||
ALsizei size;
|
||||
|
||||
RingBuffer *ring;
|
||||
int doCapture;
|
||||
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
@ -58,6 +57,7 @@ MAKE_FUNC(snd_pcm_open);
|
||||
MAKE_FUNC(snd_pcm_close);
|
||||
MAKE_FUNC(snd_pcm_nonblock);
|
||||
MAKE_FUNC(snd_pcm_frames_to_bytes);
|
||||
MAKE_FUNC(snd_pcm_bytes_to_frames);
|
||||
MAKE_FUNC(snd_pcm_hw_params_malloc);
|
||||
MAKE_FUNC(snd_pcm_hw_params_free);
|
||||
MAKE_FUNC(snd_pcm_hw_params_any);
|
||||
@ -154,6 +154,7 @@ LOAD_FUNC(snd_pcm_open);
|
||||
LOAD_FUNC(snd_pcm_close);
|
||||
LOAD_FUNC(snd_pcm_nonblock);
|
||||
LOAD_FUNC(snd_pcm_frames_to_bytes);
|
||||
LOAD_FUNC(snd_pcm_bytes_to_frames);
|
||||
LOAD_FUNC(snd_pcm_hw_params_malloc);
|
||||
LOAD_FUNC(snd_pcm_hw_params_free);
|
||||
LOAD_FUNC(snd_pcm_hw_params_any);
|
||||
@ -465,53 +466,6 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALuint ALSANoMMapCaptureProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
snd_pcm_sframes_t avail;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
avail = (snd_pcm_uframes_t)data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1);
|
||||
avail = psnd_pcm_readi(data->pcmHandle, data->buffer, avail);
|
||||
switch(avail)
|
||||
{
|
||||
case -EAGAIN:
|
||||
continue;
|
||||
case -ESTRPIPE:
|
||||
case -EPIPE:
|
||||
case -EINTR:
|
||||
avail = psnd_pcm_recover(data->pcmHandle, avail, 1);
|
||||
if(avail >= 0)
|
||||
psnd_pcm_prepare(data->pcmHandle);
|
||||
break;
|
||||
default:
|
||||
if (avail >= 0 && data->doCapture)
|
||||
WriteRingBuffer(data->ring, data->buffer, avail);
|
||||
break;
|
||||
}
|
||||
if(avail < 0)
|
||||
{
|
||||
avail = psnd_pcm_prepare(data->pcmHandle);
|
||||
if(avail < 0)
|
||||
AL_PRINT("prepare error: %s\n", psnd_strerror(avail));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
alsa_data *data;
|
||||
@ -937,15 +891,9 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
|
||||
goto error;
|
||||
}
|
||||
|
||||
pDevice->ExtraData = data;
|
||||
data->thread = StartThread(ALSANoMMapCaptureProc, pDevice);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
AL_PRINT("Could not create capture thread\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
pDevice->szDeviceName = strdup(deviceName);
|
||||
|
||||
pDevice->ExtraData = data;
|
||||
return ALC_TRUE;
|
||||
|
||||
error:
|
||||
@ -962,9 +910,6 @@ static void alsa_close_capture(ALCdevice *pDevice)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
|
||||
data->killNow = 1;
|
||||
StopThread(data->thread);
|
||||
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
DestroyRingBuffer(data->ring);
|
||||
|
||||
@ -973,34 +918,81 @@ static void alsa_close_capture(ALCdevice *pDevice)
|
||||
pDevice->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void alsa_start_capture(ALCdevice *pDevice)
|
||||
static void alsa_start_capture(ALCdevice *Device)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
data->doCapture = 1;
|
||||
alsa_data *data = (alsa_data*)Device->ExtraData;
|
||||
int err;
|
||||
|
||||
err = psnd_pcm_start(data->pcmHandle);
|
||||
if(err < 0)
|
||||
{
|
||||
AL_PRINT("start failed: %s\n", psnd_strerror(err));
|
||||
aluHandleDisconnect(Device);
|
||||
}
|
||||
}
|
||||
|
||||
static void alsa_stop_capture(ALCdevice *pDevice)
|
||||
static void alsa_stop_capture(ALCdevice *Device)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
data->doCapture = 0;
|
||||
alsa_data *data = (alsa_data*)Device->ExtraData;
|
||||
psnd_pcm_drain(data->pcmHandle);
|
||||
}
|
||||
|
||||
static void alsa_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
static ALCuint alsa_available_samples(ALCdevice *Device)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
alsa_data *data = (alsa_data*)Device->ExtraData;
|
||||
snd_pcm_sframes_t avail;
|
||||
snd_pcm_sframes_t amt;
|
||||
|
||||
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
|
||||
ReadRingBuffer(data->ring, pBuffer, lSamples);
|
||||
else
|
||||
alcSetError(pDevice, ALC_INVALID_VALUE);
|
||||
}
|
||||
avail = (Device->Connected ? psnd_pcm_avail_update(data->pcmHandle) : 0);
|
||||
if(avail < 0)
|
||||
{
|
||||
AL_PRINT("avail update failed: %s\n", psnd_strerror(avail));
|
||||
|
||||
psnd_pcm_recover(data->pcmHandle, avail, 1);
|
||||
amt = psnd_pcm_prepare(data->pcmHandle);
|
||||
if(amt < 0)
|
||||
{
|
||||
AL_PRINT("prepare error: %s\n", psnd_strerror(amt));
|
||||
aluHandleDisconnect(Device);
|
||||
}
|
||||
}
|
||||
else while(avail > 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(amt == -EAGAIN)
|
||||
continue;
|
||||
psnd_pcm_recover(data->pcmHandle, avail, 1);
|
||||
amt = psnd_pcm_prepare(data->pcmHandle);
|
||||
if(amt < 0)
|
||||
{
|
||||
AL_PRINT("prepare error: %s\n", psnd_strerror(amt));
|
||||
aluHandleDisconnect(Device);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
WriteRingBuffer(data->ring, data->buffer, amt);
|
||||
avail -= amt;
|
||||
}
|
||||
|
||||
static ALCuint alsa_available_samples(ALCdevice *pDevice)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)pDevice->ExtraData;
|
||||
return RingBufferSize(data->ring);
|
||||
}
|
||||
|
||||
static void alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
|
||||
{
|
||||
alsa_data *data = (alsa_data*)Device->ExtraData;
|
||||
|
||||
if(Samples <= alsa_available_samples(Device))
|
||||
ReadRingBuffer(data->ring, Buffer, Samples);
|
||||
else
|
||||
alcSetError(Device, ALC_INVALID_VALUE);
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs alsa_funcs = {
|
||||
alsa_open_playback,
|
||||
|
Loading…
x
Reference in New Issue
Block a user