diff options
Diffstat (limited to 'Alc/backends/null.c')
-rw-r--r-- | Alc/backends/null.c | 184 |
1 files changed, 117 insertions, 67 deletions
diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 93b38063..a7056369 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -27,139 +27,175 @@ #include "alMain.h" #include "alu.h" +#include "threads.h" +#include "compat.h" +#include "backends/base.h" -typedef struct { - volatile int killNow; - ALvoid *thread; -} null_data; +typedef struct ALCnullBackend { + DERIVE_FROM_TYPE(ALCbackend); + + volatile int killNow; + althread_t thread; +} ALCnullBackend; +DECLARE_ALCBACKEND_VTABLE(ALCnullBackend); + +static ALuint ALCnullBackend_mixerProc(ALvoid *ptr); + +static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device); +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct) +static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name); +static void ALCnullBackend_close(ALCnullBackend *self); +static ALCboolean ALCnullBackend_reset(ALCnullBackend *self); +static ALCboolean ALCnullBackend_start(ALCnullBackend *self); +static void ALCnullBackend_stop(ALCnullBackend *self); +static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock) static const ALCchar nullDevice[] = "No Output"; -static ALuint NullProc(ALvoid *ptr) + +static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device) { - ALCdevice *Device = (ALCdevice*)ptr; - null_data *data = (null_data*)Device->ExtraData; + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCnullBackend, ALCbackend, self); +} + + +static ALuint ALCnullBackend_mixerProc(ALvoid *ptr) +{ + ALCnullBackend *self = (ALCnullBackend*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; ALuint now, start; ALuint64 avail, done; - const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / - Device->Frequency / 2; + + SetRTPriority(); + SetThreadName(MIXER_THREAD_NAME); done = 0; start = timeGetTime(); - while(!data->killNow && Device->Connected) + while(!self->killNow && device->Connected) { now = timeGetTime(); - avail = (ALuint64)(now-start) * Device->Frequency / 1000; + avail = (ALuint64)(now-start) * device->Frequency / 1000; if(avail < done) { /* Timer wrapped (50 days???). Add the remainder of the cycle to * the available count and reset the number of samples done */ - avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done; + avail += (U64(1)<<32)*device->Frequency/1000 - done; done = 0; } - if(avail-done < Device->UpdateSize) + if(avail-done < device->UpdateSize) { + ALuint restTime = (ALuint)((device->UpdateSize - (avail-done)) * 1000 / + device->Frequency); Sleep(restTime); continue; } - while(avail-done >= Device->UpdateSize) - { - aluMixData(Device, NULL, Device->UpdateSize); - done += Device->UpdateSize; - } + do { + aluMixData(device, NULL, device->UpdateSize); + done += device->UpdateSize; + } while(avail-done >= device->UpdateSize); } return 0; } -static ALCenum null_open_playback(ALCdevice *device, const ALCchar *deviceName) + +static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) { - null_data *data; + ALCdevice *device; - if(!deviceName) - deviceName = nullDevice; - else if(strcmp(deviceName, nullDevice) != 0) + if(!name) + name = nullDevice; + else if(strcmp(name, nullDevice) != 0) return ALC_INVALID_VALUE; - data = (null_data*)calloc(1, sizeof(*data)); + device = STATIC_CAST(ALCbackend, self)->mDevice; + device->DeviceName = strdup(name); - device->DeviceName = strdup(deviceName); - device->ExtraData = data; return ALC_NO_ERROR; } -static void null_close_playback(ALCdevice *device) +static void ALCnullBackend_close(ALCnullBackend* UNUSED(self)) { - null_data *data = (null_data*)device->ExtraData; +} - free(data); - device->ExtraData = NULL; +static ALCboolean ALCnullBackend_reset(ALCnullBackend *self) +{ + SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_TRUE; } -static ALCboolean null_reset_playback(ALCdevice *device) +static ALCboolean ALCnullBackend_start(ALCnullBackend *self) { - SetDefaultWFXChannelOrder(device); + if(!StartThread(&self->thread, ALCnullBackend_mixerProc, self)) + return ALC_FALSE; return ALC_TRUE; } -static ALCboolean null_start_playback(ALCdevice *device) +static void ALCnullBackend_stop(ALCnullBackend *self) { - null_data *data = (null_data*)device->ExtraData; + if(!self->thread) + return; - data->thread = StartThread(NullProc, device); - if(data->thread == NULL) - return ALC_FALSE; + self->killNow = 1; + StopThread(self->thread); + self->thread = NULL; - return ALC_TRUE; + self->killNow = 0; } -static void null_stop_playback(ALCdevice *device) + +static void ALCnullBackend_Delete(ALCnullBackend *self) { - null_data *data = (null_data*)device->ExtraData; + free(self); +} - if(!data->thread) - return; +DEFINE_ALCBACKEND_VTABLE(ALCnullBackend); + + +typedef struct ALCnullBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCnullBackendFactory; +#define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCnullBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCnullBackendFactory_getFactory(void); + +static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory *self); +static DECLARE_FORWARD(ALCnullBackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory *self, ALCbackend_Type type); +static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory); - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - data->killNow = 0; +ALCbackendFactory *ALCnullBackendFactory_getFactory(void) +{ + static ALCnullBackendFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); } -static const BackendFuncs null_funcs = { - null_open_playback, - null_close_playback, - null_reset_playback, - null_start_playback, - null_stop_playback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - ALCdevice_LockDefault, - ALCdevice_UnlockDefault, - ALCdevice_GetLatencyDefault -}; - -ALCboolean alc_null_init(BackendFuncs *func_list) +static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory* UNUSED(self)) { - *func_list = null_funcs; return ALC_TRUE; } -void alc_null_deinit(void) +static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory* UNUSED(self), ALCbackend_Type type) { + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; } -void alc_null_probe(enum DevProbe type) +static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { @@ -170,3 +206,17 @@ void alc_null_probe(enum DevProbe type) break; } } + +static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + ALCnullBackend *backend; + + assert(type == ALCbackend_Playback); + + backend = calloc(1, sizeof(*backend)); + if(!backend) return NULL; + + ALCnullBackend_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); +} |