aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-02-18 15:58:15 -0800
committerChris Robinson <[email protected]>2017-02-18 15:58:15 -0800
commitd8c42918f46e2439c81c4d4562df8fa7ad2e01fd (patch)
tree59b4a7ee1b50aa7cc9d8d43cc87ae20af72060dc /Alc
parent909193a345469529ec98b8b01379738facee861d (diff)
Use select() to wait for audio with OSS and Solaris
Diffstat (limited to 'Alc')
-rw-r--r--Alc/backends/oss.c146
-rw-r--r--Alc/backends/solaris.c76
2 files changed, 137 insertions, 85 deletions
diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c
index 2da096f6..8934181b 100644
--- a/Alc/backends/oss.c
+++ b/Alc/backends/oss.c
@@ -269,42 +269,64 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
{
ALCplaybackOSS *self = (ALCplaybackOSS*)ptr;
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- ALint frameSize;
+ struct timeval timeout;
+ ALubyte *write_ptr;
+ ALint frame_size;
+ ALint to_write;
ssize_t wrote;
+ fd_set wfds;
+ int sret;
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ ALCplaybackOSS_lock(self);
while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
{
- ALint len = self->data_size;
- ALubyte *WritePtr = self->mix_data;
+ FD_ZERO(&wfds);
+ FD_SET(self->fd, &wfds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ ALCplaybackOSS_unlock(self);
+ sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
+ ALCplaybackOSS_lock(self);
+ if(sret < 0)
+ {
+ if(errno == EINTR)
+ continue;
+ ERR("select failed: %s\n", strerror(errno));
+ aluHandleDisconnect(device);
+ break;
+ }
+ else if(sret == 0)
+ {
+ WARN("select timeout\n");
+ continue;
+ }
- aluMixData(device, WritePtr, len/frameSize);
- while(len > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
+ write_ptr = self->mix_data;
+ to_write = self->data_size;
+ aluMixData(device, write_ptr, to_write/frame_size);
+ while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
{
- wrote = write(self->fd, WritePtr, len);
+ wrote = write(self->fd, write_ptr, to_write);
if(wrote < 0)
{
- if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
- {
- ERR("write failed: %s\n", strerror(errno));
- ALCplaybackOSS_lock(self);
- aluHandleDisconnect(device);
- ALCplaybackOSS_unlock(self);
- break;
- }
-
- al_nssleep(1000000);
- continue;
+ if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+ continue;
+ ERR("write failed: %s\n", strerror(errno));
+ aluHandleDisconnect(device);
+ break;
}
- len -= wrote;
- WritePtr += wrote;
+ to_write -= wrote;
+ write_ptr += wrote;
}
}
+ ALCplaybackOSS_unlock(self);
return 0;
}
@@ -492,7 +514,6 @@ typedef struct ALCcaptureOSS {
int fd;
ll_ringbuffer_t *ring;
- ATOMIC(ALenum) doCapture;
ATOMIC(ALenum) killNow;
althrd_t thread;
@@ -520,41 +541,55 @@ static int ALCcaptureOSS_recordProc(void *ptr)
{
ALCcaptureOSS *self = (ALCcaptureOSS*)ptr;
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- int frameSize;
+ struct timeval timeout;
+ int frame_size;
+ fd_set rfds;
ssize_t amt;
+ int sret;
SetRTPriority();
althrd_setname(althrd_current(), RECORD_THREAD_NAME);
- frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
while(!ATOMIC_LOAD_SEQ(&self->killNow))
{
ll_ringbuffer_data_t vec[2];
- amt = 0;
- if(ATOMIC_LOAD_SEQ(&self->doCapture))
+ FD_ZERO(&rfds);
+ FD_SET(self->fd, &rfds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ sret = select(self->fd+1, &rfds, NULL, NULL, &timeout);
+ if(sret < 0)
{
- ll_ringbuffer_get_write_vector(self->ring, vec);
- if(vec[0].len > 0)
- {
- amt = read(self->fd, vec[0].buf, vec[0].len*frameSize);
- if(amt < 0)
- {
- ERR("read failed: %s\n", strerror(errno));
- ALCcaptureOSS_lock(self);
- aluHandleDisconnect(device);
- ALCcaptureOSS_unlock(self);
- break;
- }
- ll_ringbuffer_write_advance(self->ring, amt/frameSize);
- }
+ if(errno == EINTR)
+ continue;
+ ERR("select failed: %s\n", strerror(errno));
+ aluHandleDisconnect(device);
+ break;
}
- if(amt == 0)
+ else if(sret == 0)
{
- al_nssleep(1000000);
+ WARN("select timeout\n");
continue;
}
+
+ ll_ringbuffer_get_write_vector(self->ring, vec);
+ if(vec[0].len > 0)
+ {
+ amt = read(self->fd, vec[0].buf, vec[0].len*frame_size);
+ if(amt < 0)
+ {
+ ERR("read failed: %s\n", strerror(errno));
+ ALCcaptureOSS_lock(self);
+ aluHandleDisconnect(device);
+ ALCcaptureOSS_unlock(self);
+ break;
+ }
+ ll_ringbuffer_write_advance(self->ring, amt/frame_size);
+ }
}
return 0;
@@ -566,7 +601,6 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device)
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
SET_VTABLE2(ALCcaptureOSS, ALCbackend, self);
- ATOMIC_INIT(&self->doCapture, AL_FALSE);
ATOMIC_INIT(&self->killNow, AL_FALSE);
}
@@ -690,15 +724,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
return ALC_OUT_OF_MEMORY;
}
- if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
- {
- ll_ringbuffer_free(self->ring);
- self->ring = NULL;
- close(self->fd);
- self->fd = -1;
- return ALC_OUT_OF_MEMORY;
- }
-
al_string_copy_cstr(&device->DeviceName, name);
return ALC_NO_ERROR;
@@ -706,11 +731,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
static void ALCcaptureOSS_close(ALCcaptureOSS *self)
{
- int res;
-
- ATOMIC_STORE_SEQ(&self->killNow, AL_TRUE);
- althrd_join(self->thread, &res);
-
close(self->fd);
self->fd = -1;
@@ -720,13 +740,23 @@ static void ALCcaptureOSS_close(ALCcaptureOSS *self)
static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self)
{
- ATOMIC_STORE_SEQ(&self->doCapture, AL_TRUE);
+ ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
+ if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
+ return ALC_FALSE;
return ALC_TRUE;
}
static void ALCcaptureOSS_stop(ALCcaptureOSS *self)
{
- ATOMIC_STORE_SEQ(&self->doCapture, AL_FALSE);
+ int res;
+
+ if(ATOMIC_EXCHANGE_SEQ(ALenum, &self->killNow, AL_TRUE))
+ return;
+
+ althrd_join(self->thread, &res);
+
+ if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
+ ERR("Error resetting device: %s\n", strerror(errno));
}
static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples)
diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c
index 792f717a..c70e0b46 100644
--- a/Alc/backends/solaris.c
+++ b/Alc/backends/solaris.c
@@ -50,7 +50,7 @@ typedef struct ALCsolarisBackend {
ALubyte *mix_data;
int data_size;
- volatile int killNow;
+ ATOMIC(ALenum) killNow;
althrd_t thread;
} ALCsolarisBackend;
@@ -84,6 +84,7 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi
SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
self->fd = -1;
+ ATOMIC_INIT(&self->killNow, AL_FALSE);
}
static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
@@ -103,43 +104,65 @@ static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
static int ALCsolarisBackend_mixerProc(void *ptr)
{
ALCsolarisBackend *self = ptr;
- ALCdevice *Device = STATIC_CAST(ALCbackend,self)->mDevice;
- ALint frameSize;
- int wrote;
+ ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+ struct timeval timeout;
+ ALubyte *write_ptr;
+ ALint frame_size;
+ ALint to_write;
+ ssize_t wrote;
+ fd_set wfds;
+ int sret;
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
+ frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
- while(!self->killNow && Device->Connected)
+ ALCsolarisBackend_lock(self);
+ while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
{
- ALint len = self->data_size;
- ALubyte *WritePtr = self->mix_data;
+ FD_ZERO(&wfds);
+ FD_SET(self->fd, &wfds);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ ALCsolarisBackend_unlock(self);
+ sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
+ ALCsolarisBackend_lock(self);
+ if(sret < 0)
+ {
+ if(errno == EINTR)
+ continue;
+ ERR("select failed: %s\n", strerror(errno));
+ aluHandleDisconnect(device);
+ break;
+ }
+ else if(sret == 0)
+ {
+ WARN("select timeout\n");
+ continue;
+ }
- aluMixData(Device, WritePtr, len/frameSize);
- while(len > 0 && !self->killNow)
+ write_ptr = self->mix_data;
+ to_write = self->data_size;
+ aluMixData(device, write_ptr, to_write/frame_size);
+ while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
{
- wrote = write(self->fd, WritePtr, len);
+ wrote = write(self->fd, write_ptr, to_write);
if(wrote < 0)
{
- if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
- {
- ERR("write failed: %s\n", strerror(errno));
- ALCsolarisBackend_lock(self);
- aluHandleDisconnect(Device);
- ALCsolarisBackend_unlock(self);
- break;
- }
-
- al_nssleep(1000000);
- continue;
+ if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+ continue;
+ ERR("write failed: %s\n", strerror(errno));
+ aluHandleDisconnect(device);
+ break;
}
- len -= wrote;
- WritePtr += wrote;
+ to_write -= wrote;
+ write_ptr += wrote;
}
}
+ ALCsolarisBackend_unlock(self);
return 0;
}
@@ -250,7 +273,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self)
{
- self->killNow = 0;
+ ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success)
return ALC_FALSE;
return ALC_TRUE;
@@ -260,10 +283,9 @@ static void ALCsolarisBackend_stop(ALCsolarisBackend *self)
{
int res;
- if(self->killNow)
+ if(ATOMIC_EXCHANGE_SEQ(int, &self->killNow, AL_TRUE))
return;
- self->killNow = 1;
althrd_join(self->thread, &res);
if(ioctl(self->fd, AUDIO_DRAIN) < 0)