aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends/solaris.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/backends/solaris.c')
-rw-r--r--Alc/backends/solaris.c112
1 files changed, 67 insertions, 45 deletions
diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c
index 52ca9090..71282204 100644
--- a/Alc/backends/solaris.c
+++ b/Alc/backends/solaris.c
@@ -22,6 +22,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -33,6 +34,7 @@
#include "alMain.h"
#include "alu.h"
+#include "alconfig.h"
#include "threads.h"
#include "compat.h"
@@ -49,7 +51,7 @@ typedef struct ALCsolarisBackend {
ALubyte *mix_data;
int data_size;
- volatile int killNow;
+ ATOMIC(ALenum) killNow;
althrd_t thread;
} ALCsolarisBackend;
@@ -58,13 +60,12 @@ static int ALCsolarisBackend_mixerProc(void *ptr);
static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device);
static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self);
static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name);
-static void ALCsolarisBackend_close(ALCsolarisBackend *self);
static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self);
static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self);
static void ALCsolarisBackend_stop(ALCsolarisBackend *self);
static DECLARE_FORWARD2(ALCsolarisBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ClockLatency, getClockLatency)
static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock)
static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend)
@@ -83,6 +84,8 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi
SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
self->fd = -1;
+ self->mix_data = NULL;
+ ATOMIC_INIT(&self->killNow, AL_FALSE);
}
static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
@@ -102,43 +105,67 @@ 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, device->AmbiOrder);
- while(!self->killNow && Device->Connected)
+ ALCsolarisBackend_lock(self);
+ while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+ ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
{
- 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, "Failed to wait for playback buffer: %s", strerror(errno));
+ 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, "Failed to write playback samples: %s",
+ strerror(errno));
+ break;
}
- len -= wrote;
- WritePtr += wrote;
+ to_write -= wrote;
+ write_ptr += wrote;
}
}
+ ALCsolarisBackend_unlock(self);
return 0;
}
@@ -161,23 +188,17 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na
}
device = STATIC_CAST(ALCbackend,self)->mDevice;
- al_string_copy_cstr(&device->DeviceName, name);
+ alstr_copy_cstr(&device->DeviceName, name);
return ALC_NO_ERROR;
}
-static void ALCsolarisBackend_close(ALCsolarisBackend *self)
-{
- close(self->fd);
- self->fd = -1;
-}
-
static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
{
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
audio_info_t info;
- ALuint frameSize;
- int numChannels;
+ ALsizei frameSize;
+ ALsizei numChannels;
AUDIO_INITINFO(&info);
@@ -185,7 +206,7 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
if(device->FmtChans != DevFmtMono)
device->FmtChans = DevFmtStereo;
- numChannels = ChannelsFromDevFmt(device->FmtChans);
+ numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
info.play.channels = numChannels;
switch(device->FmtType)
@@ -219,9 +240,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
return ALC_FALSE;
}
- if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels)
+ if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels)
{
- ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels);
+ ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels);
return ALC_FALSE;
}
@@ -241,7 +262,9 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
SetDefaultChannelOrder(device);
free(self->mix_data);
- self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+ device->FmtChans, device->FmtType, device->AmbiOrder
+ );
self->mix_data = calloc(1, self->data_size);
return ALC_TRUE;
@@ -249,7 +272,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;
@@ -259,10 +282,9 @@ static void ALCsolarisBackend_stop(ALCsolarisBackend *self)
{
int res;
- if(self->killNow)
+ if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
return;
- self->killNow = 1;
althrd_join(self->thread, &res);
if(ioctl(self->fd, AUDIO_DRAIN) < 0)
@@ -280,7 +302,7 @@ ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory *self);
static DECLARE_FORWARD(ALCsolarisBackendFactory, ALCbackendFactory, void, deinit)
static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory *self, ALCbackend_Type type);
-static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type);
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type, al_string *outnames);
static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory);
@@ -305,7 +327,7 @@ static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory
return ALC_FALSE;
}
-static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type)
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
switch(type)
{
@@ -315,7 +337,7 @@ static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self
struct stat buf;
if(stat(solaris_driver, &buf) == 0)
#endif
- AppendAllDevicesList(solaris_device);
+ alstr_append_range(outnames, solaris_device, solaris_device+sizeof(solaris_device));
}
break;