diff options
Diffstat (limited to 'Alc/backends/base.c')
-rw-r--r-- | Alc/backends/base.c | 187 |
1 files changed, 28 insertions, 159 deletions
diff --git a/Alc/backends/base.c b/Alc/backends/base.c index ebeb31bf..9d8614b1 100644 --- a/Alc/backends/base.c +++ b/Alc/backends/base.c @@ -4,17 +4,22 @@ #include <stdlib.h> #include "alMain.h" +#include "alu.h" #include "backends/base.h" +extern inline ALuint64 GetDeviceClockTime(ALCdevice *device); +extern inline void ALCdevice_Lock(ALCdevice *device); +extern inline void ALCdevice_Unlock(ALCdevice *device); +extern inline ClockLatency GetClockLatency(ALCdevice *device); + /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) { - int ret; - self->mDevice = device; - ret = almtx_init(&self->mMutex, almtx_recursive); + int ret = almtx_init(&self->mMutex, almtx_recursive); assert(ret == althrd_success); + self->mDevice = device; } void ALCbackend_Destruct(ALCbackend *self) @@ -37,9 +42,27 @@ ALCuint ALCbackend_availableSamples(ALCbackend* UNUSED(self)) return 0; } -ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self)) +ClockLatency ALCbackend_getClockLatency(ALCbackend *self) { - return 0; + ALCdevice *device = self->mDevice; + ALuint refcount; + ClockLatency ret; + + do { + while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1)) + althrd_yield(); + ret.ClockTime = GetDeviceClockTime(device); + ATOMIC_THREAD_FENCE(almemory_order_acquire); + } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed)); + + /* NOTE: The device will generally have about all but one periods filled at + * any given time during playback. Without a more accurate measurement from + * the output, this is an okay approximation. + */ + ret.Latency = device->UpdateSize * DEVICE_CLOCK_RES / device->Frequency * + maxu(device->NumUpdates-1, 1); + + return ret; } void ALCbackend_lock(ALCbackend *self) @@ -59,157 +82,3 @@ void ALCbackend_unlock(ALCbackend *self) void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self)) { } - - -/* Wrappers to use an old-style backend with the new interface. */ -typedef struct PlaybackWrapper { - DERIVE_FROM_TYPE(ALCbackend); - - const BackendFuncs *Funcs; -} PlaybackWrapper; - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs); -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); -static void PlaybackWrapper_close(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self); -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self); -static void PlaybackWrapper_stop(PlaybackWrapper *self); -static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALint64, getLatency) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) -DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); - -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(PlaybackWrapper, ALCbackend, self); - - self->Funcs = funcs; -} - -static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->OpenPlayback(device, name); -} - -static void PlaybackWrapper_close(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->ClosePlayback(device); -} - -static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->ResetPlayback(device); -} - -static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->StartPlayback(device); -} - -static void PlaybackWrapper_stop(PlaybackWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StopPlayback(device); -} - - -typedef struct CaptureWrapper { - DERIVE_FROM_TYPE(ALCbackend); - - const BackendFuncs *Funcs; -} CaptureWrapper; - -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) -static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); -static void CaptureWrapper_close(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset) -static ALCboolean CaptureWrapper_start(CaptureWrapper *self); -static void CaptureWrapper_stop(CaptureWrapper *self); -static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples); -static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALint64, getLatency) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) -static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) -DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) -DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); - -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs) -{ - ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); - SET_VTABLE2(CaptureWrapper, ALCbackend, self); - - self->Funcs = funcs; -} - -static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->OpenCapture(device, name); -} - -static void CaptureWrapper_close(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->CloseCapture(device); -} - -static ALCboolean CaptureWrapper_start(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StartCapture(device); - return ALC_TRUE; -} - -static void CaptureWrapper_stop(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - self->Funcs->StopCapture(device); -} - -static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->CaptureSamples(device, buffer, samples); -} - -static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self) -{ - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return self->Funcs->AvailableSamples(device); -} - - -ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type) -{ - if(type == ALCbackend_Playback) - { - PlaybackWrapper *backend; - - NEW_OBJ(backend, PlaybackWrapper)(device, funcs); - if(!backend) return NULL; - - return STATIC_CAST(ALCbackend, backend); - } - - if(type == ALCbackend_Capture) - { - CaptureWrapper *backend; - - NEW_OBJ(backend, CaptureWrapper)(device, funcs); - if(!backend) return NULL; - - return STATIC_CAST(ALCbackend, backend); - } - - return NULL; -} |