aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/alsa.c140
1 files changed, 66 insertions, 74 deletions
diff --git a/Alc/alsa.c b/Alc/alsa.c
index 75d02686..32181370 100644
--- a/Alc/alsa.c
+++ b/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,32 +918,79 @@ 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;
+ }
+
+ return RingBufferSize(data->ring);
}
-static ALCuint alsa_available_samples(ALCdevice *pDevice)
+static void alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
{
- alsa_data *data = (alsa_data*)pDevice->ExtraData;
- return RingBufferSize(data->ring);
+ alsa_data *data = (alsa_data*)Device->ExtraData;
+
+ if(Samples <= alsa_available_samples(Device))
+ ReadRingBuffer(data->ring, Buffer, Samples);
+ else
+ alcSetError(Device, ALC_INVALID_VALUE);
}