Turn even more methods into member functions

This commit is contained in:
Chris Robinson
2018-12-28 14:06:15 -08:00
parent 200e267b81
commit b7f5166d59
5 changed files with 274 additions and 267 deletions
+17 -13
View File
@@ -171,9 +171,10 @@ void deviceList(int type, al::vector<DevMap> *devmap)
/* Wrappers to use an old-style backend with the new interface. */
struct PlaybackWrapper final : public ALCbackend {
std::unique_ptr<qsa_data> mExtraData;
PlaybackWrapper(ALCdevice *device) noexcept : ALCbackend{device} { }
~PlaybackWrapper() override;
std::unique_ptr<qsa_data> mExtraData;
};
static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device);
@@ -620,11 +621,12 @@ static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device)
}
static void PlaybackWrapper_Destruct(PlaybackWrapper *self)
{
if(self->mExtraData)
qsa_close_playback(self);
{ self->~PlaybackWrapper(); }
self->~PlaybackWrapper();
PlaybackWrapper::~PlaybackWrapper()
{
if(mExtraData)
qsa_close_playback(this);
}
static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
@@ -654,9 +656,10 @@ static void PlaybackWrapper_stop(PlaybackWrapper *self)
/***********/
struct CaptureWrapper final : public ALCbackend {
std::unique_ptr<qsa_data> mExtraData;
CaptureWrapper(ALCdevice *device) noexcept : ALCbackend{device} { }
~CaptureWrapper() override;
std::unique_ptr<qsa_data> mExtraData;
};
static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device);
@@ -778,7 +781,7 @@ static void qsa_close_capture(CaptureWrapper *self)
if (data->pcmHandle!=nullptr)
snd_pcm_close(data->pcmHandle);
data->pcmHandle = nullptr
data->pcmHandle = nullptr;
self->mExtraData = nullptr;
}
@@ -921,11 +924,12 @@ static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device)
}
static void CaptureWrapper_Destruct(CaptureWrapper *self)
{
if(self->mExtraData)
qsa_close_capture(self);
{ self->~CaptureWrapper(); }
self->~CaptureWrapper();
CaptureWrapper::~CaptureWrapper()
{
if(mExtraData)
qsa_close_capture(this);
}
static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
+43 -38
View File
@@ -33,13 +33,23 @@
#include "compat.h"
namespace {
#ifdef _WIN32
#define DEVNAME_PREFIX "OpenAL Soft on "
#else
#define DEVNAME_PREFIX ""
#endif
constexpr ALCchar defaultDeviceName[] = DEVNAME_PREFIX "Default Device";
struct ALCsdl2Backend final : public ALCbackend {
ALCsdl2Backend(ALCdevice *device) noexcept : ALCbackend{device} { }
~ALCsdl2Backend() override;
static void audioCallbackC(void *ptr, Uint8 *stream, int len);
void audioCallback(Uint8 *stream, int len);
SDL_AudioDeviceID mDeviceID{0u};
ALsizei mFrameSize{0};
@@ -47,58 +57,52 @@ struct ALCsdl2Backend final : public ALCbackend {
DevFmtChannels mFmtChans{};
DevFmtType mFmtType{};
ALuint mUpdateSize{0u};
ALCsdl2Backend(ALCdevice *device) noexcept : ALCbackend{device} { }
};
static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device);
static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self);
static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name);
static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self);
static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self);
static void ALCsdl2Backend_stop(ALCsdl2Backend *self);
static DECLARE_FORWARD2(ALCsdl2Backend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ALCuint, availableSamples)
static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ClockLatency, getClockLatency)
static void ALCsdl2Backend_lock(ALCsdl2Backend *self);
static void ALCsdl2Backend_unlock(ALCsdl2Backend *self);
void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device);
void ALCsdl2Backend_Destruct(ALCsdl2Backend *self);
ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name);
ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self);
ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self);
void ALCsdl2Backend_stop(ALCsdl2Backend *self);
DECLARE_FORWARD2(ALCsdl2Backend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ALCuint, availableSamples)
DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ClockLatency, getClockLatency)
void ALCsdl2Backend_lock(ALCsdl2Backend *self);
void ALCsdl2Backend_unlock(ALCsdl2Backend *self);
DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend)
DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend);
static const ALCchar defaultDeviceName[] = DEVNAME_PREFIX "Default Device";
static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device)
void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device)
{
new (self) ALCsdl2Backend{device};
SET_VTABLE2(ALCsdl2Backend, ALCbackend, self);
}
static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self)
{
if(self->mDeviceID)
SDL_CloseAudioDevice(self->mDeviceID);
self->mDeviceID = 0;
void ALCsdl2Backend_Destruct(ALCsdl2Backend *self)
{ self->~ALCsdl2Backend(); }
self->~ALCsdl2Backend();
ALCsdl2Backend::~ALCsdl2Backend()
{
if(mDeviceID)
SDL_CloseAudioDevice(mDeviceID);
mDeviceID = 0;
}
void ALCsdl2Backend::audioCallbackC(void *ptr, Uint8 *stream, int len)
{ static_cast<ALCsdl2Backend*>(ptr)->audioCallback(stream, len); }
static void ALCsdl2Backend_audioCallback(void *ptr, Uint8 *stream, int len)
void ALCsdl2Backend::audioCallback(Uint8 *stream, int len)
{
auto self = static_cast<ALCsdl2Backend*>(ptr);
assert((len % self->mFrameSize) == 0);
aluMixData(self->mDevice, stream, len / self->mFrameSize);
assert((len % mFrameSize) == 0);
aluMixData(mDevice, stream, len / mFrameSize);
}
static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name)
ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name)
{
ALCdevice *device{self->mDevice};
SDL_AudioSpec want, have;
SDL_zero(want);
SDL_zero(have);
SDL_AudioSpec want{}, have{};
want.freq = device->Frequency;
switch(device->FmtType)
@@ -113,7 +117,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name)
}
want.channels = (device->FmtChans == DevFmtMono) ? 1 : 2;
want.samples = device->UpdateSize;
want.callback = ALCsdl2Backend_audioCallback;
want.callback = &ALCsdl2Backend::audioCallbackC;
want.userdata = self;
/* Passing nullptr to SDL_OpenAudioDevice opens a default, which isn't
@@ -170,7 +174,7 @@ static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name)
return ALC_NO_ERROR;
}
static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self)
ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self)
{
ALCdevice *device{self->mDevice};
device->Frequency = self->mFrequency;
@@ -182,27 +186,28 @@ static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self)
return ALC_TRUE;
}
static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self)
ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self)
{
SDL_PauseAudioDevice(self->mDeviceID, 0);
return ALC_TRUE;
}
static void ALCsdl2Backend_stop(ALCsdl2Backend *self)
void ALCsdl2Backend_stop(ALCsdl2Backend *self)
{
SDL_PauseAudioDevice(self->mDeviceID, 1);
}
static void ALCsdl2Backend_lock(ALCsdl2Backend *self)
void ALCsdl2Backend_lock(ALCsdl2Backend *self)
{
SDL_LockAudioDevice(self->mDeviceID);
}
static void ALCsdl2Backend_unlock(ALCsdl2Backend *self)
void ALCsdl2Backend_unlock(ALCsdl2Backend *self)
{
SDL_UnlockAudioDevice(self->mDeviceID);
}
} // namespace
BackendFactory &SDL2BackendFactory::getFactory()
{
+90 -94
View File
@@ -43,6 +43,11 @@ static const ALCchar sndio_device[] = "SndIO Default";
struct SndioPlayback final : public ALCbackend {
SndioPlayback(ALCdevice *device) noexcept : ALCbackend{device} { }
~SndioPlayback() override;
int mixerProc();
sio_hdl *mSndHandle{nullptr};
al::vector<ALubyte> mBuffer;
@@ -50,70 +55,65 @@ struct SndioPlayback final : public ALCbackend {
std::atomic<bool> mKillNow{true};
std::thread mThread;
SndioPlayback(ALCdevice *device) noexcept : ALCbackend{device} { }
static constexpr inline const char *CurrentPrefix() noexcept { return "SndioPlayback::"; }
};
static int SndioPlayback_mixerProc(SndioPlayback *self);
static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device);
static void SndioPlayback_Destruct(SndioPlayback *self);
static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name);
static ALCboolean SndioPlayback_reset(SndioPlayback *self);
static ALCboolean SndioPlayback_start(SndioPlayback *self);
static void SndioPlayback_stop(SndioPlayback *self);
static DECLARE_FORWARD2(SndioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
static DECLARE_FORWARD(SndioPlayback, ALCbackend, ALCuint, availableSamples)
static DECLARE_FORWARD(SndioPlayback, ALCbackend, ClockLatency, getClockLatency)
static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, lock)
static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, unlock)
void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device);
void SndioPlayback_Destruct(SndioPlayback *self);
ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name);
ALCboolean SndioPlayback_reset(SndioPlayback *self);
ALCboolean SndioPlayback_start(SndioPlayback *self);
void SndioPlayback_stop(SndioPlayback *self);
DECLARE_FORWARD2(SndioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
DECLARE_FORWARD(SndioPlayback, ALCbackend, ALCuint, availableSamples)
DECLARE_FORWARD(SndioPlayback, ALCbackend, ClockLatency, getClockLatency)
DECLARE_FORWARD(SndioPlayback, ALCbackend, void, lock)
DECLARE_FORWARD(SndioPlayback, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(SndioPlayback)
DEFINE_ALCBACKEND_VTABLE(SndioPlayback);
static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device)
void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device)
{
new (self) SndioPlayback{device};
SET_VTABLE2(SndioPlayback, ALCbackend, self);
}
static void SndioPlayback_Destruct(SndioPlayback *self)
{
if(self->mSndHandle)
sio_close(self->mSndHandle);
self->mSndHandle = nullptr;
void SndioPlayback_Destruct(SndioPlayback *self)
{ self->~SndioPlayback(); }
self->~SndioPlayback();
SndioPlayback::~SndioPlayback()
{
if(mSndHandle)
sio_close(mSndHandle);
mSndHandle = nullptr;
}
static int SndioPlayback_mixerProc(SndioPlayback *self)
int SndioPlayback::mixerProc()
{
ALCdevice *device{self->mDevice};
SetRTPriority();
althrd_setname(MIXER_THREAD_NAME);
const ALsizei frameSize{device->frameSizeFromFmt()};
const ALsizei frameSize{mDevice->frameSizeFromFmt()};
while(!self->mKillNow.load(std::memory_order_acquire) &&
device->Connected.load(std::memory_order_acquire))
while(!mKillNow.load(std::memory_order_acquire) &&
mDevice->Connected.load(std::memory_order_acquire))
{
auto WritePtr = static_cast<ALubyte*>(self->mBuffer.data());
size_t len{self->mBuffer.size()};
auto WritePtr = static_cast<ALubyte*>(mBuffer.data());
size_t len{mBuffer.size()};
SndioPlayback_lock(self);
aluMixData(device, WritePtr, len/frameSize);
SndioPlayback_unlock(self);
while(len > 0 && !self->mKillNow.load(std::memory_order_acquire))
SndioPlayback_lock(this);
aluMixData(mDevice, WritePtr, len/frameSize);
SndioPlayback_unlock(this);
while(len > 0 && !mKillNow.load(std::memory_order_acquire))
{
size_t wrote{sio_write(self->mSndHandle, WritePtr, len)};
size_t wrote{sio_write(mSndHandle, WritePtr, len)};
if(wrote == 0)
{
ERR("sio_write failed\n");
SndioPlayback_lock(self);
aluHandleDisconnect(device, "Failed to write playback samples");
SndioPlayback_unlock(self);
SndioPlayback_lock(this);
aluHandleDisconnect(mDevice, "Failed to write playback samples");
SndioPlayback_unlock(this);
break;
}
@@ -126,7 +126,7 @@ static int SndioPlayback_mixerProc(SndioPlayback *self)
}
static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name)
ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name)
{
ALCdevice *device{self->mDevice};
@@ -146,7 +146,7 @@ static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name)
return ALC_NO_ERROR;
}
static ALCboolean SndioPlayback_reset(SndioPlayback *self)
ALCboolean SndioPlayback_reset(SndioPlayback *self)
{
ALCdevice *device{self->mDevice};
sio_par par;
@@ -234,7 +234,7 @@ static ALCboolean SndioPlayback_reset(SndioPlayback *self)
return ALC_TRUE;
}
static ALCboolean SndioPlayback_start(SndioPlayback *self)
ALCboolean SndioPlayback_start(SndioPlayback *self)
{
if(!sio_start(self->mSndHandle))
{
@@ -244,7 +244,7 @@ static ALCboolean SndioPlayback_start(SndioPlayback *self)
try {
self->mKillNow.store(false, std::memory_order_release);
self->mThread = std::thread(SndioPlayback_mixerProc, self);
self->mThread = std::thread{std::mem_fn(&SndioPlayback::mixerProc), self};
return ALC_TRUE;
}
catch(std::exception& e) {
@@ -256,7 +256,7 @@ static ALCboolean SndioPlayback_start(SndioPlayback *self)
return ALC_FALSE;
}
static void SndioPlayback_stop(SndioPlayback *self)
void SndioPlayback_stop(SndioPlayback *self)
{
if(self->mKillNow.exchange(true, std::memory_order_acq_rel) || !self->mThread.joinable())
return;
@@ -268,6 +268,11 @@ static void SndioPlayback_stop(SndioPlayback *self)
struct SndioCapture final : public ALCbackend {
SndioCapture(ALCdevice *device) noexcept : ALCbackend{device} { }
~SndioCapture() override;
int recordProc();
sio_hdl *mSndHandle{nullptr};
RingBufferPtr mRing;
@@ -275,84 +280,75 @@ struct SndioCapture final : public ALCbackend {
std::atomic<bool> mKillNow{true};
std::thread mThread;
SndioCapture(ALCdevice *device) noexcept : ALCbackend{device} { }
static constexpr inline const char *CurrentPrefix() noexcept { return "SndioCapture::"; }
};
static int SndioCapture_recordProc(SndioCapture *self);
static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device);
static void SndioCapture_Destruct(SndioCapture *self);
static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name);
static DECLARE_FORWARD(SndioCapture, ALCbackend, ALCboolean, reset)
static ALCboolean SndioCapture_start(SndioCapture *self);
static void SndioCapture_stop(SndioCapture *self);
static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples);
static ALCuint SndioCapture_availableSamples(SndioCapture *self);
static DECLARE_FORWARD(SndioCapture, ALCbackend, ClockLatency, getClockLatency)
static DECLARE_FORWARD(SndioCapture, ALCbackend, void, lock)
static DECLARE_FORWARD(SndioCapture, ALCbackend, void, unlock)
void SndioCapture_Construct(SndioCapture *self, ALCdevice *device);
void SndioCapture_Destruct(SndioCapture *self);
ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name);
DECLARE_FORWARD(SndioCapture, ALCbackend, ALCboolean, reset)
ALCboolean SndioCapture_start(SndioCapture *self);
void SndioCapture_stop(SndioCapture *self);
ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples);
ALCuint SndioCapture_availableSamples(SndioCapture *self);
DECLARE_FORWARD(SndioCapture, ALCbackend, ClockLatency, getClockLatency)
DECLARE_FORWARD(SndioCapture, ALCbackend, void, lock)
DECLARE_FORWARD(SndioCapture, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(SndioCapture)
DEFINE_ALCBACKEND_VTABLE(SndioCapture);
static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device)
void SndioCapture_Construct(SndioCapture *self, ALCdevice *device)
{
new (self) SndioCapture{device};
SET_VTABLE2(SndioCapture, ALCbackend, self);
}
static void SndioCapture_Destruct(SndioCapture *self)
{
if(self->mSndHandle)
sio_close(self->mSndHandle);
self->mSndHandle = nullptr;
void SndioCapture_Destruct(SndioCapture *self)
{ self->~SndioCapture(); }
self->~SndioCapture();
SndioCapture::~SndioCapture()
{
if(mSndHandle)
sio_close(mSndHandle);
mSndHandle = nullptr;
}
static int SndioCapture_recordProc(SndioCapture *self)
int SndioCapture::recordProc()
{
ALCdevice *device{self->mDevice};
RingBuffer *ring{self->mRing.get()};
SetRTPriority();
althrd_setname(RECORD_THREAD_NAME);
const ALsizei frameSize{device->frameSizeFromFmt()};
const ALsizei frameSize{mDevice->frameSizeFromFmt()};
while(!self->mKillNow.load(std::memory_order_acquire) &&
device->Connected.load(std::memory_order_acquire))
while(!mKillNow.load(std::memory_order_acquire) &&
mDevice->Connected.load(std::memory_order_acquire))
{
size_t total, todo;
auto data = ring->getWriteVector();
todo = data.first.len + data.second.len;
auto data = mRing->getWriteVector();
size_t todo{data.first.len + data.second.len};
if(todo == 0)
{
static char junk[4096];
sio_read(self->mSndHandle, junk, minz(sizeof(junk)/frameSize, device->UpdateSize)*frameSize);
sio_read(mSndHandle, junk,
minz(sizeof(junk)/frameSize, mDevice->UpdateSize)*frameSize);
continue;
}
total = 0;
size_t total{0u};
data.first.len *= frameSize;
data.second.len *= frameSize;
todo = minz(todo, device->UpdateSize) * frameSize;
todo = minz(todo, mDevice->UpdateSize) * frameSize;
while(total < todo)
{
size_t got;
if(!data.first.len)
data.first = data.second;
got = sio_read(self->mSndHandle, data.first.buf, minz(todo-total, data.first.len));
size_t got{sio_read(mSndHandle, data.first.buf, minz(todo-total, data.first.len))};
if(!got)
{
SndioCapture_lock(self);
aluHandleDisconnect(device, "Failed to read capture samples");
SndioCapture_unlock(self);
SndioCapture_lock(this);
aluHandleDisconnect(mDevice, "Failed to read capture samples");
SndioCapture_unlock(this);
break;
}
@@ -360,14 +356,14 @@ static int SndioCapture_recordProc(SndioCapture *self)
data.first.len -= got;
total += got;
}
ring->writeAdvance(total / frameSize);
mRing->writeAdvance(total / frameSize);
}
return 0;
}
static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name)
ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name)
{
ALCdevice *device{self->mDevice};
sio_par par;
@@ -470,7 +466,7 @@ static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name)
return ALC_NO_ERROR;
}
static ALCboolean SndioCapture_start(SndioCapture *self)
ALCboolean SndioCapture_start(SndioCapture *self)
{
if(!sio_start(self->mSndHandle))
{
@@ -480,7 +476,7 @@ static ALCboolean SndioCapture_start(SndioCapture *self)
try {
self->mKillNow.store(false, std::memory_order_release);
self->mThread = std::thread(SndioCapture_recordProc, self);
self->mThread = std::thread{std::mem_fn(&SndioCapture::recordProc), self};
return ALC_TRUE;
}
catch(std::exception& e) {
@@ -492,7 +488,7 @@ static ALCboolean SndioCapture_start(SndioCapture *self)
return ALC_FALSE;
}
static void SndioCapture_stop(SndioCapture *self)
void SndioCapture_stop(SndioCapture *self)
{
if(self->mKillNow.exchange(true, std::memory_order_acq_rel) || !self->mThread.joinable())
return;
@@ -502,14 +498,14 @@ static void SndioCapture_stop(SndioCapture *self)
ERR("Error stopping device\n");
}
static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples)
ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples)
{
RingBuffer *ring{self->mRing.get()};
ring->read(buffer, samples);
return ALC_NO_ERROR;
}
static ALCuint SndioCapture_availableSamples(SndioCapture *self)
ALCuint SndioCapture_availableSamples(SndioCapture *self)
{
RingBuffer *ring{self->mRing.get()};
return ring->readSpace();
+61 -62
View File
@@ -49,7 +49,17 @@
namespace {
struct ALCsolarisBackend final : public ALCbackend {
constexpr ALCchar solaris_device[] = "Solaris Default";
const char *solaris_driver = "/dev/audio";
struct SolarisBackend final : public ALCbackend {
SolarisBackend(ALCdevice *device) noexcept : ALCbackend{device} { }
~SolarisBackend() override;
int mixerProc();
int mFd{-1};
al::vector<ALubyte> mBuffer;
@@ -57,74 +67,65 @@ struct ALCsolarisBackend final : public ALCbackend {
std::atomic<bool> mKillNow{true};
std::thread mThread;
ALCsolarisBackend(ALCdevice *device) noexcept : ALCbackend{device} { }
static constexpr inline const char *CurrentPrefix() noexcept { return "SolarisBackend::"; }
};
static int ALCsolarisBackend_mixerProc(ALCsolarisBackend *self);
void SolarisBackend_Construct(SolarisBackend *self, ALCdevice *device);
void SolarisBackend_Destruct(SolarisBackend *self);
ALCenum SolarisBackend_open(SolarisBackend *self, const ALCchar *name);
ALCboolean SolarisBackend_reset(SolarisBackend *self);
ALCboolean SolarisBackend_start(SolarisBackend *self);
void SolarisBackend_stop(SolarisBackend *self);
DECLARE_FORWARD2(SolarisBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
DECLARE_FORWARD(SolarisBackend, ALCbackend, ALCuint, availableSamples)
DECLARE_FORWARD(SolarisBackend, ALCbackend, ClockLatency, getClockLatency)
DECLARE_FORWARD(SolarisBackend, ALCbackend, void, lock)
DECLARE_FORWARD(SolarisBackend, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(SolarisBackend)
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(SolarisBackend);
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)
void SolarisBackend_Construct(SolarisBackend *self, ALCdevice *device)
{
new (self) ALCsolarisBackend{device};
SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
new (self) SolarisBackend{device};
SET_VTABLE2(SolarisBackend, ALCbackend, self);
}
static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
{
if(self->mFd != -1)
close(self->mFd);
self->mFd = -1;
void SolarisBackend_Destruct(SolarisBackend *self)
{ self->~SolarisBackend(); }
self->~ALCsolarisBackend();
SolarisBackend::~SolarisBackend()
{
if(mFd != -1)
close(mFd);
mFd = -1;
}
static int ALCsolarisBackend_mixerProc(ALCsolarisBackend *self)
int SolarisBackend::mixerProc()
{
ALCdevice *device{self->mDevice};
SetRTPriority();
althrd_setname(MIXER_THREAD_NAME);
const int frame_size{device->frameSizeFromFmt()};
const int frame_size{mDevice->frameSizeFromFmt()};
ALCsolarisBackend_lock(self);
while(!self->mKillNow.load(std::memory_order_acquire) &&
device->Connected.load(std::memory_order_acquire))
SolarisBackend_lock(this);
while(!mKillNow.load(std::memory_order_acquire) &&
mDevice->Connected.load(std::memory_order_acquire))
{
pollfd pollitem{};
pollitem.fd = self->mFd;
pollitem.fd = mFd;
pollitem.events = POLLOUT;
ALCsolarisBackend_unlock(self);
SolarisBackend_unlock(this);
int pret{poll(&pollitem, 1, 1000)};
ALCsolarisBackend_lock(self);
SolarisBackend_lock(this);
if(pret < 0)
{
if(errno == EINTR || errno == EAGAIN)
continue;
ERR("poll failed: %s\n", strerror(errno));
aluHandleDisconnect(device, "Failed to wait for playback buffer: %s", strerror(errno));
aluHandleDisconnect(mDevice, "Failed to wait for playback buffer: %s",
strerror(errno));
break;
}
else if(pret == 0)
@@ -133,19 +134,19 @@ static int ALCsolarisBackend_mixerProc(ALCsolarisBackend *self)
continue;
}
ALubyte *write_ptr{self->mBuffer.data()};
size_t to_write{self->mBuffer.size()};
aluMixData(device, write_ptr, to_write/frame_size);
while(to_write > 0 && !self->mKillNow.load(std::memory_order_acquire))
ALubyte *write_ptr{mBuffer.data()};
size_t to_write{mBuffer.size()};
aluMixData(mDevice, write_ptr, to_write/frame_size);
while(to_write > 0 && !mKillNow.load(std::memory_order_acquire))
{
ssize_t wrote{write(self->mFd, write_ptr, to_write)};
ssize_t wrote{write(mFd, 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));
aluHandleDisconnect(mDevice, "Failed to write playback samples: %s",
strerror(errno));
break;
}
@@ -153,16 +154,14 @@ static int ALCsolarisBackend_mixerProc(ALCsolarisBackend *self)
write_ptr += wrote;
}
}
ALCsolarisBackend_unlock(self);
SolarisBackend_unlock(this);
return 0;
}
static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name)
ALCenum SolarisBackend_open(SolarisBackend *self, const ALCchar *name)
{
ALCdevice *device;
if(!name)
name = solaris_device;
else if(strcmp(name, solaris_device) != 0)
@@ -175,13 +174,13 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na
return ALC_INVALID_VALUE;
}
device = self->mDevice;
ALCdevice *device{self->mDevice};
device->DeviceName = name;
return ALC_NO_ERROR;
}
static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
ALCboolean SolarisBackend_reset(SolarisBackend *self)
{
ALCdevice *device{self->mDevice};
audio_info_t info;
@@ -256,11 +255,11 @@ static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
return ALC_TRUE;
}
static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self)
ALCboolean SolarisBackend_start(SolarisBackend *self)
{
try {
self->mKillNow.store(false, std::memory_order_release);
self->mThread = std::thread(ALCsolarisBackend_mixerProc, self);
self->mThread = std::thread{std::mem_fn(&SolarisBackend::mixerProc), self};
return ALC_TRUE;
}
catch(std::exception& e) {
@@ -271,7 +270,7 @@ static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self)
return ALC_FALSE;
}
static void ALCsolarisBackend_stop(ALCsolarisBackend *self)
void SolarisBackend_stop(SolarisBackend *self)
{
if(self->mKillNow.exchange(true, std::memory_order_acq_rel) || !self->mThread.joinable())
return;
@@ -322,8 +321,8 @@ ALCbackend *SolarisBackendFactory::createBackend(ALCdevice *device, ALCbackend_T
{
if(type == ALCbackend_Playback)
{
ALCsolarisBackend *backend;
NEW_OBJ(backend, ALCsolarisBackend)(device);
SolarisBackend *backend;
NEW_OBJ(backend, SolarisBackend)(device);
return backend;
}
+63 -60
View File
@@ -78,7 +78,12 @@ void fwrite32le(ALuint val, FILE *f)
}
struct ALCwaveBackend final : public ALCbackend {
struct WaveBackend final : public ALCbackend {
WaveBackend(ALCdevice *device) noexcept : ALCbackend{device} { }
~WaveBackend() override;
int mixerProc();
FILE *mFile{nullptr};
long mDataStart{-1};
@@ -87,81 +92,79 @@ struct ALCwaveBackend final : public ALCbackend {
std::atomic<ALenum> mKillNow{AL_TRUE};
std::thread mThread;
ALCwaveBackend(ALCdevice *device) noexcept : ALCbackend{device} { }
static constexpr inline const char *CurrentPrefix() noexcept { return "WaveBackend::"; }
};
int ALCwaveBackend_mixerProc(ALCwaveBackend *self);
void WaveBackend_Construct(WaveBackend *self, ALCdevice *device);
void WaveBackend_Destruct(WaveBackend *self);
ALCenum WaveBackend_open(WaveBackend *self, const ALCchar *name);
ALCboolean WaveBackend_reset(WaveBackend *self);
ALCboolean WaveBackend_start(WaveBackend *self);
void WaveBackend_stop(WaveBackend *self);
DECLARE_FORWARD2(WaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
DECLARE_FORWARD(WaveBackend, ALCbackend, ALCuint, availableSamples)
DECLARE_FORWARD(WaveBackend, ALCbackend, ClockLatency, getClockLatency)
DECLARE_FORWARD(WaveBackend, ALCbackend, void, lock)
DECLARE_FORWARD(WaveBackend, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(WaveBackend)
void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device);
void ALCwaveBackend_Destruct(ALCwaveBackend *self);
ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name);
ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self);
ALCboolean ALCwaveBackend_start(ALCwaveBackend *self);
void ALCwaveBackend_stop(ALCwaveBackend *self);
DECLARE_FORWARD2(ALCwaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALCuint, availableSamples)
DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ClockLatency, getClockLatency)
DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, lock)
DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(ALCwaveBackend)
DEFINE_ALCBACKEND_VTABLE(WaveBackend);
DEFINE_ALCBACKEND_VTABLE(ALCwaveBackend);
void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device)
void WaveBackend_Construct(WaveBackend *self, ALCdevice *device)
{
new (self) ALCwaveBackend{device};
SET_VTABLE2(ALCwaveBackend, ALCbackend, self);
new (self) WaveBackend{device};
SET_VTABLE2(WaveBackend, ALCbackend, self);
}
void ALCwaveBackend_Destruct(ALCwaveBackend *self)
{
if(self->mFile)
fclose(self->mFile);
self->mFile = nullptr;
void WaveBackend_Destruct(WaveBackend *self)
{ self->~WaveBackend(); }
self->~ALCwaveBackend();
WaveBackend::~WaveBackend()
{
if(mFile)
fclose(mFile);
mFile = nullptr;
}
int ALCwaveBackend_mixerProc(ALCwaveBackend *self)
int WaveBackend::mixerProc()
{
ALCdevice *device{self->mDevice};
const milliseconds restTime{device->UpdateSize*1000/device->Frequency / 2};
const milliseconds restTime{mDevice->UpdateSize*1000/mDevice->Frequency / 2};
althrd_setname(MIXER_THREAD_NAME);
const ALsizei frameSize{device->frameSizeFromFmt()};
const ALsizei frameSize{mDevice->frameSizeFromFmt()};
ALint64 done{0};
auto start = std::chrono::steady_clock::now();
while(!self->mKillNow.load(std::memory_order_acquire) &&
device->Connected.load(std::memory_order_acquire))
while(!mKillNow.load(std::memory_order_acquire) &&
mDevice->Connected.load(std::memory_order_acquire))
{
auto now = std::chrono::steady_clock::now();
/* This converts from nanoseconds to nanosamples, then to samples. */
ALint64 avail{std::chrono::duration_cast<seconds>((now-start) * device->Frequency).count()};
if(avail-done < device->UpdateSize)
ALint64 avail{std::chrono::duration_cast<seconds>((now-start) *
mDevice->Frequency).count()};
if(avail-done < mDevice->UpdateSize)
{
std::this_thread::sleep_for(restTime);
continue;
}
while(avail-done >= device->UpdateSize)
while(avail-done >= mDevice->UpdateSize)
{
ALCwaveBackend_lock(self);
aluMixData(device, self->mBuffer.data(), device->UpdateSize);
ALCwaveBackend_unlock(self);
done += device->UpdateSize;
WaveBackend_lock(this);
aluMixData(mDevice, mBuffer.data(), mDevice->UpdateSize);
WaveBackend_unlock(this);
done += mDevice->UpdateSize;
if(!IS_LITTLE_ENDIAN)
{
const ALsizei bytesize{device->bytesFromFmt()};
const ALsizei bytesize{mDevice->bytesFromFmt()};
ALsizei i;
if(bytesize == 2)
{
ALushort *samples = reinterpret_cast<ALushort*>(self->mBuffer.data());
const auto len = static_cast<ALsizei>(self->mBuffer.size() / 2);
ALushort *samples = reinterpret_cast<ALushort*>(mBuffer.data());
const auto len = static_cast<ALsizei>(mBuffer.size() / 2);
for(i = 0;i < len;i++)
{
ALushort samp = samples[i];
@@ -170,8 +173,8 @@ int ALCwaveBackend_mixerProc(ALCwaveBackend *self)
}
else if(bytesize == 4)
{
ALuint *samples = reinterpret_cast<ALuint*>(self->mBuffer.data());
const auto len = static_cast<ALsizei>(self->mBuffer.size() / 4);
ALuint *samples = reinterpret_cast<ALuint*>(mBuffer.data());
const auto len = static_cast<ALsizei>(mBuffer.size() / 4);
for(i = 0;i < len;i++)
{
ALuint samp = samples[i];
@@ -181,14 +184,14 @@ int ALCwaveBackend_mixerProc(ALCwaveBackend *self)
}
}
size_t fs{fwrite(self->mBuffer.data(), frameSize, device->UpdateSize, self->mFile)};
size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile)};
(void)fs;
if(ferror(self->mFile))
if(ferror(mFile))
{
ERR("Error writing to file\n");
ALCwaveBackend_lock(self);
aluHandleDisconnect(device, "Failed to write playback samples");
ALCwaveBackend_unlock(self);
WaveBackend_lock(this);
aluHandleDisconnect(mDevice, "Failed to write playback samples");
WaveBackend_unlock(this);
break;
}
}
@@ -198,11 +201,11 @@ int ALCwaveBackend_mixerProc(ALCwaveBackend *self)
* and current time from growing too large, while maintaining the
* correct number of samples to render.
*/
if(done >= device->Frequency)
if(done >= mDevice->Frequency)
{
seconds s{done/device->Frequency};
seconds s{done/mDevice->Frequency};
start += s;
done -= device->Frequency*s.count();
done -= mDevice->Frequency*s.count();
}
}
@@ -210,7 +213,7 @@ int ALCwaveBackend_mixerProc(ALCwaveBackend *self)
}
ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
ALCenum WaveBackend_open(WaveBackend *self, const ALCchar *name)
{
const char *fname{GetConfigValue(nullptr, "wave", "file", "")};
if(!fname[0]) return ALC_INVALID_VALUE;
@@ -240,7 +243,7 @@ ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
return ALC_NO_ERROR;
}
ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
ALCboolean WaveBackend_reset(WaveBackend *self)
{
ALCdevice *device{self->mDevice};
ALuint channels=0, bits=0, chanmask=0;
@@ -344,11 +347,11 @@ ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
return ALC_TRUE;
}
ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
ALCboolean WaveBackend_start(WaveBackend *self)
{
try {
self->mKillNow.store(AL_FALSE, std::memory_order_release);
self->mThread = std::thread(ALCwaveBackend_mixerProc, self);
self->mThread = std::thread{std::mem_fn(&WaveBackend::mixerProc), self};
return ALC_TRUE;
}
catch(std::exception& e) {
@@ -359,7 +362,7 @@ ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
return ALC_FALSE;
}
void ALCwaveBackend_stop(ALCwaveBackend *self)
void WaveBackend_stop(WaveBackend *self)
{
if(self->mKillNow.exchange(AL_TRUE, std::memory_order_acq_rel) || !self->mThread.joinable())
return;
@@ -402,8 +405,8 @@ ALCbackend *WaveBackendFactory::createBackend(ALCdevice *device, ALCbackend_Type
{
if(type == ALCbackend_Playback)
{
ALCwaveBackend *backend;
NEW_OBJ(backend, ALCwaveBackend)(device);
WaveBackend *backend;
NEW_OBJ(backend, WaveBackend)(device);
return backend;
}