From efae7bfb72de4e354457345a4f2474083fd6b9d6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 12 Nov 2018 23:06:31 -0800 Subject: Convert the Solaris backend to C++ --- Alc/backends/solaris.c | 360 ---------------------------------------------- Alc/backends/solaris.cpp | 363 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 363 insertions(+), 360 deletions(-) delete mode 100644 Alc/backends/solaris.c create mode 100644 Alc/backends/solaris.cpp (limited to 'Alc') diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c deleted file mode 100644 index 71282204..00000000 --- a/Alc/backends/solaris.c +++ /dev/null @@ -1,360 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "alMain.h" -#include "alu.h" -#include "alconfig.h" -#include "threads.h" -#include "compat.h" - -#include "backends/base.h" - -#include - - -typedef struct ALCsolarisBackend { - DERIVE_FROM_TYPE(ALCbackend); - - int fd; - - ALubyte *mix_data; - int data_size; - - ATOMIC(ALenum) killNow; - althrd_t thread; -} ALCsolarisBackend; - -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 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, ClockLatency, getClockLatency) -static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock) -static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend) - -DEFINE_ALCBACKEND_VTABLE(ALCsolarisBackend); - - -static const ALCchar solaris_device[] = "Solaris Default"; - -static const char *solaris_driver = "/dev/audio"; - - -static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(ALCsolarisBackend, ALCbackend, self); - - self->fd = -1; - self->mix_data = NULL; - ATOMIC_INIT(&self->killNow, AL_FALSE); -} - -static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) -{ - if(self->fd != -1) - close(self->fd); - self->fd = -1; - - free(self->mix_data); - self->mix_data = NULL; - self->data_size = 0; - - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); -} - - -static int ALCsolarisBackend_mixerProc(void *ptr) -{ - ALCsolarisBackend *self = ptr; - 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); - - frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); - - ALCsolarisBackend_lock(self); - while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && - ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) - { - 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; - } - - 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, write_ptr, to_write); - if(wrote < 0) - { - 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; - } - - to_write -= wrote; - write_ptr += wrote; - } - } - ALCsolarisBackend_unlock(self); - - return 0; -} - - -static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name) -{ - ALCdevice *device; - - if(!name) - name = solaris_device; - else if(strcmp(name, solaris_device) != 0) - return ALC_INVALID_VALUE; - - self->fd = open(solaris_driver, O_WRONLY); - if(self->fd == -1) - { - ERR("Could not open %s: %s\n", solaris_driver, strerror(errno)); - return ALC_INVALID_VALUE; - } - - device = STATIC_CAST(ALCbackend,self)->mDevice; - alstr_copy_cstr(&device->DeviceName, name); - - return ALC_NO_ERROR; -} - -static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; - audio_info_t info; - ALsizei frameSize; - ALsizei numChannels; - - AUDIO_INITINFO(&info); - - info.play.sample_rate = device->Frequency; - - if(device->FmtChans != DevFmtMono) - device->FmtChans = DevFmtStereo; - numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); - info.play.channels = numChannels; - - switch(device->FmtType) - { - case DevFmtByte: - info.play.precision = 8; - info.play.encoding = AUDIO_ENCODING_LINEAR; - break; - case DevFmtUByte: - info.play.precision = 8; - info.play.encoding = AUDIO_ENCODING_LINEAR8; - break; - case DevFmtUShort: - case DevFmtInt: - case DevFmtUInt: - case DevFmtFloat: - device->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - info.play.precision = 16; - info.play.encoding = AUDIO_ENCODING_LINEAR; - break; - } - - frameSize = numChannels * BytesFromDevFmt(device->FmtType); - info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; - - if(ioctl(self->fd, AUDIO_SETINFO, &info) < 0) - { - ERR("ioctl failed: %s\n", strerror(errno)); - return ALC_FALSE; - } - - if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels) - { - ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels); - return ALC_FALSE; - } - - if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) || - (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) || - (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) || - (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt))) - { - ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType), - info.play.precision, info.play.encoding); - return ALC_FALSE; - } - - device->Frequency = info.play.sample_rate; - device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; - - SetDefaultChannelOrder(device); - - free(self->mix_data); - self->data_size = device->UpdateSize * FrameSizeFromDevFmt( - device->FmtChans, device->FmtType, device->AmbiOrder - ); - self->mix_data = calloc(1, self->data_size); - - return ALC_TRUE; -} - -static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self) -{ - ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); - if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success) - return ALC_FALSE; - return ALC_TRUE; -} - -static void ALCsolarisBackend_stop(ALCsolarisBackend *self) -{ - int res; - - if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) - return; - - althrd_join(self->thread, &res); - - if(ioctl(self->fd, AUDIO_DRAIN) < 0) - ERR("Error draining device: %s\n", strerror(errno)); -} - - -typedef struct ALCsolarisBackendFactory { - DERIVE_FROM_TYPE(ALCbackendFactory); -} ALCsolarisBackendFactory; -#define ALCSOLARISBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsolarisBackendFactory, ALCbackendFactory) } } - -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, al_string *outnames); -static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type); -DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory); - - -ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void) -{ - static ALCsolarisBackendFactory factory = ALCSOLARISBACKENDFACTORY_INITIALIZER; - return STATIC_CAST(ALCbackendFactory, &factory); -} - - -static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory* UNUSED(self)) -{ - ConfigValueStr(NULL, "solaris", "device", &solaris_driver); - return ALC_TRUE; -} - -static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory* UNUSED(self), ALCbackend_Type type) -{ - if(type == ALCbackend_Playback) - return ALC_TRUE; - return ALC_FALSE; -} - -static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) -{ - switch(type) - { - case ALL_DEVICE_PROBE: - { -#ifdef HAVE_STAT - struct stat buf; - if(stat(solaris_driver, &buf) == 0) -#endif - alstr_append_range(outnames, solaris_device, solaris_device+sizeof(solaris_device)); - } - break; - - case CAPTURE_DEVICE_PROBE: - break; - } -} - -ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) -{ - if(type == ALCbackend_Playback) - { - ALCsolarisBackend *backend; - NEW_OBJ(backend, ALCsolarisBackend)(device); - if(!backend) return NULL; - return STATIC_CAST(ALCbackend, backend); - } - - return NULL; -} diff --git a/Alc/backends/solaris.cpp b/Alc/backends/solaris.cpp new file mode 100644 index 00000000..953163fd --- /dev/null +++ b/Alc/backends/solaris.cpp @@ -0,0 +1,363 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "alconfig.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include + + +struct ALCsolarisBackend final : public ALCbackend { + int fd; + + ALubyte *mix_data; + int data_size; + + ATOMIC(ALenum) killNow; + althrd_t thread; +}; + +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 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, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend) + +DEFINE_ALCBACKEND_VTABLE(ALCsolarisBackend); + + +static const ALCchar solaris_device[] = "Solaris Default"; + +static const char *solaris_driver = "/dev/audio"; + + +static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device) +{ + new (self) ALCsolarisBackend{}; + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCsolarisBackend, ALCbackend, self); + + self->fd = -1; + self->mix_data = nullptr; + ATOMIC_INIT(&self->killNow, AL_FALSE); +} + +static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) +{ + if(self->fd != -1) + close(self->fd); + self->fd = -1; + + free(self->mix_data); + self->mix_data = nullptr; + self->data_size = 0; + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); + self->~ALCsolarisBackend(); +} + + +static int ALCsolarisBackend_mixerProc(void *ptr) +{ + ALCsolarisBackend *self = static_cast(ptr); + 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); + + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); + + ALCsolarisBackend_lock(self); + while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) && + ATOMIC_LOAD(&device->Connected, almemory_order_acquire)) + { + FD_ZERO(&wfds); + FD_SET(self->fd, &wfds); + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + ALCsolarisBackend_unlock(self); + sret = select(self->fd+1, nullptr, &wfds, nullptr, &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; + } + + 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, write_ptr, to_write); + if(wrote < 0) + { + 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; + } + + to_write -= wrote; + write_ptr += wrote; + } + } + ALCsolarisBackend_unlock(self); + + return 0; +} + + +static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name) +{ + ALCdevice *device; + + if(!name) + name = solaris_device; + else if(strcmp(name, solaris_device) != 0) + return ALC_INVALID_VALUE; + + self->fd = open(solaris_driver, O_WRONLY); + if(self->fd == -1) + { + ERR("Could not open %s: %s\n", solaris_driver, strerror(errno)); + return ALC_INVALID_VALUE; + } + + device = STATIC_CAST(ALCbackend,self)->mDevice; + alstr_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; +} + +static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + audio_info_t info; + ALsizei frameSize; + ALsizei numChannels; + + AUDIO_INITINFO(&info); + + info.play.sample_rate = device->Frequency; + + if(device->FmtChans != DevFmtMono) + device->FmtChans = DevFmtStereo; + numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); + info.play.channels = numChannels; + + switch(device->FmtType) + { + case DevFmtByte: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + case DevFmtUByte: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_LINEAR8; + break; + case DevFmtUShort: + case DevFmtInt: + case DevFmtUInt: + case DevFmtFloat: + device->FmtType = DevFmtShort; + /* fall-through */ + case DevFmtShort: + info.play.precision = 16; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + } + + frameSize = numChannels * BytesFromDevFmt(device->FmtType); + info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; + + if(ioctl(self->fd, AUDIO_SETINFO, &info) < 0) + { + ERR("ioctl failed: %s\n", strerror(errno)); + return ALC_FALSE; + } + + if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels) + { + ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels); + return ALC_FALSE; + } + + if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) || + (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) || + (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) || + (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt))) + { + ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType), + info.play.precision, info.play.encoding); + return ALC_FALSE; + } + + device->Frequency = info.play.sample_rate; + device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; + + SetDefaultChannelOrder(device); + + free(self->mix_data); + self->data_size = device->UpdateSize * FrameSizeFromDevFmt( + device->FmtChans, device->FmtType, device->AmbiOrder + ); + self->mix_data = static_cast(calloc(1, self->data_size)); + + return ALC_TRUE; +} + +static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self) +{ + ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE); + if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success) + return ALC_FALSE; + return ALC_TRUE; +} + +static void ALCsolarisBackend_stop(ALCsolarisBackend *self) +{ + int res; + + if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE)) + return; + + althrd_join(self->thread, &res); + + if(ioctl(self->fd, AUDIO_DRAIN) < 0) + ERR("Error draining device: %s\n", strerror(errno)); +} + + +struct ALCsolarisBackendFactory final : public ALCbackendFactory { + ALCsolarisBackendFactory() noexcept; +}; + +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, al_string *outnames); +static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory); + + +ALCsolarisBackendFactory::ALCsolarisBackendFactory() noexcept + : ALCbackendFactory{GET_VTABLE2(ALCsolarisBackendFactory, ALCbackendFactory)} +{ } + +ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void) +{ + static ALCsolarisBackendFactory factory{}; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory* UNUSED(self)) +{ + ConfigValueStr(nullptr, "solaris", "device", &solaris_driver); + return ALC_TRUE; +} + +static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + { +#ifdef HAVE_STAT + struct stat buf; + if(stat(solaris_driver, &buf) == 0) +#endif + alstr_append_range(outnames, solaris_device, solaris_device+sizeof(solaris_device)); + } + break; + + case CAPTURE_DEVICE_PROBE: + break; + } +} + +ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCsolarisBackend *backend; + NEW_OBJ(backend, ALCsolarisBackend)(device); + if(!backend) return nullptr; + return STATIC_CAST(ALCbackend, backend); + } + + return nullptr; +} -- cgit v1.2.3