diff options
-rw-r--r-- | Alc/ALc.c | 118 | ||||
-rw-r--r-- | Alc/backends/base.h | 2 | ||||
-rw-r--r-- | Alc/backends/null.c | 160 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 3 |
4 files changed, 193 insertions, 90 deletions
@@ -46,6 +46,7 @@ ************************************************/ struct BackendInfo { const char *name; + ALCbackendFactory* (*getFactory)(void); ALCboolean (*Init)(BackendFuncs*); void (*Deinit)(void); void (*Probe)(enum DevProbe); @@ -55,51 +56,51 @@ struct BackendInfo { #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } static struct BackendInfo BackendList[] = { #ifdef HAVE_PULSEAUDIO - { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs }, + { "pulse", NULL, alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs }, #endif #ifdef HAVE_ALSA - { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs }, + { "alsa", NULL, alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs }, #endif #ifdef HAVE_COREAUDIO - { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, + { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, #endif #ifdef HAVE_OSS - { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs }, + { "oss", NULL, alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs }, #endif #ifdef HAVE_SOLARIS - { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs }, + { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs }, #endif #ifdef HAVE_SNDIO - { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, + { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, #endif #ifdef HAVE_QSA - { "qsa", alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, + { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, #endif #ifdef HAVE_MMDEVAPI - { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, + { "mmdevapi", NULL, alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, #endif #ifdef HAVE_DSOUND - { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs }, + { "dsound", NULL, alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs }, #endif #ifdef HAVE_WINMM - { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs }, + { "winmm", NULL, alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs }, #endif #ifdef HAVE_PORTAUDIO - { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs }, + { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs }, #endif #ifdef HAVE_OPENSL - { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, + { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, #endif - { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs }, + { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #ifdef HAVE_WAVE - { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs }, + { "wave", NULL, alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs }, #endif - { NULL, NULL, NULL, NULL, EmptyFuncs } + { NULL, NULL, NULL, NULL, NULL, EmptyFuncs } }; static struct BackendInfo BackendLoopback = { - "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs + "loopback", NULL, alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs }; #undef EmptyFuncs @@ -1059,7 +1060,7 @@ static void alc_initconfig(void) len = (next ? ((size_t)(next-devs)) : strlen(devs)); while(len > 0 && isspace(devs[len-1])) len--; - for(n = i;BackendList[n].Init;n++) + for(n = i;BackendList[n].name;n++) { if(len == strlen(BackendList[n].name) && strncmp(BackendList[n].name, devs, len) == 0) @@ -1069,7 +1070,7 @@ static void alc_initconfig(void) do { BackendList[n] = BackendList[n+1]; ++n; - } while(BackendList[n].Init); + } while(BackendList[n].name); } else { @@ -1091,14 +1092,40 @@ static void alc_initconfig(void) if(endlist) { BackendList[i].name = NULL; + BackendList[i].getFactory = NULL; BackendList[i].Init = NULL; BackendList[i].Deinit = NULL; BackendList[i].Probe = NULL; } } - for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++) + for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++) { + if(BackendList[i].getFactory) + { + ALCbackendFactory *factory = BackendList[i].getFactory(); + if(!VCALL0(factory,init,())) + { + WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); + continue; + } + + TRACE("Initialized backend \"%s\"\n", BackendList[i].name); + if(!PlaybackBackend.name && VCALL(factory,support,(ALCbackend_Playback))) + { + PlaybackBackend = BackendList[i]; + TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); + } +#if 0 + if(!CaptureBackend.name && VCALL(factory,support,(ALCbackend_Capture))) + { + CaptureBackend = BackendList[i]; + TRACE("Added \"%s\" for capture\n", CaptureBackend.name); + } +#endif + continue; + } + if(!BackendList[i].Init(&BackendList[i].Funcs)) { WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); @@ -1205,8 +1232,16 @@ static void alc_deinit(void) memset(&PlaybackBackend, 0, sizeof(PlaybackBackend)); memset(&CaptureBackend, 0, sizeof(CaptureBackend)); - for(i = 0;BackendList[i].Deinit;i++) - BackendList[i].Deinit(); + for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++) + { + if(!BackendList[i].getFactory) + BackendList[i].Deinit(); + else + { + ALCbackendFactory *factory = BackendList[i].getFactory(); + VCALL0(factory,deinit,()); + } + } BackendLoopback.Deinit(); alc_deinit_safe(); @@ -1225,10 +1260,26 @@ static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type) *list = NULL; *listsize = 0; - if(type == ALL_DEVICE_PROBE && PlaybackBackend.Probe) - PlaybackBackend.Probe(type); - else if(type == CAPTURE_DEVICE_PROBE && CaptureBackend.Probe) - CaptureBackend.Probe(type); + if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory)) + { + if(!PlaybackBackend.getFactory) + PlaybackBackend.Probe(type); + else + { + ALCbackendFactory *factory = PlaybackBackend.getFactory(); + VCALL(factory,probe,(type)); + } + } + else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory)) + { + if(!CaptureBackend.getFactory) + CaptureBackend.Probe(type); + else + { + ALCbackendFactory *factory = CaptureBackend.getFactory(); + VCALL(factory,probe,(type)); + } + } UnlockLists(); } @@ -2937,7 +2988,21 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->NumUpdates = 4; device->UpdateSize = 1024; - device->Backend = create_backend_wrapper(device); + if(!PlaybackBackend.getFactory) + device->Backend = create_backend_wrapper(device); + else + { + ALCbackendFactory *factory = PlaybackBackend.getFactory(); + device->Backend = VCALL(factory,createBackend,(device)); + } + if(!device->Backend) + { + DeleteCriticalSection(&device->Mutex); + al_free(device); + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + if(ConfigValueStr(NULL, "channels", &fmt)) { @@ -3077,6 +3142,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) // Find a playback device to open if((err=VCALL(device->Backend,open,(deviceName))) != ALC_NO_ERROR) { + DELETE_OBJ(device->Backend); DeleteCriticalSection(&device->Mutex); al_free(device); alcSetError(NULL, err); diff --git a/Alc/backends/base.h b/Alc/backends/base.h index 7c1b918b..272a3f65 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -115,4 +115,6 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ } +ALCbackendFactory *ALCnullBackendFactory_getFactory(void); + #endif /* AL_BACKENDS_BASE_H */ diff --git a/Alc/backends/null.c b/Alc/backends/null.c index 9742424c..d21ebf0c 100644 --- a/Alc/backends/null.c +++ b/Alc/backends/null.c @@ -29,19 +29,24 @@ #include "alu.h" #include "threads.h" +#include "backends/base.h" + + +typedef struct ALCnullBackend { + DERIVE_FROM_TYPE(ALCbackend); -typedef struct { volatile int killNow; althread_t thread; -} null_data; +} ALCnullBackend; +#define ALCNULLBACKEND_INITIALIZER { { GET_VTABLE2(ALCbackend, ALCnullBackend) } } static const ALCchar nullDevice[] = "No Output"; -static ALuint NullProc(ALvoid *ptr) +static ALuint ALCnullBackend_mixerProc(ALvoid *ptr) { - ALCdevice *Device = (ALCdevice*)ptr; - null_data *data = (null_data*)Device->ExtraData; + ALCnullBackend *self = (ALCnullBackend*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; ALuint now, start; ALuint64 avail, done; @@ -50,118 +55,129 @@ static ALuint NullProc(ALvoid *ptr) 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 += (U64(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 = (Device->UpdateSize - (avail-done)) * 1000 / - Device->Frequency; + ALuint restTime = (device->UpdateSize - (avail-done)) * 1000 / + device->Frequency; Sleep(restTime); continue; } do { - aluMixData(Device, NULL, Device->UpdateSize); - done += Device->UpdateSize; - } while(avail-done >= Device->UpdateSize); + 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 void ALCnullBackend_Destruct(ALCnullBackend* UNUSED(self)) { - null_data *data; +} - if(!deviceName) - deviceName = nullDevice; - else if(strcmp(deviceName, nullDevice) != 0) +static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) +{ + ALCdevice *device; + + 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; - if(!StartThread(&data->thread, NullProc, device)) - 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 ALint64 ALCnullBackend_getLatency(ALCnullBackend *self) { - null_data *data = (null_data*)device->ExtraData; + return ALCbackend_getLatency(STATIC_CAST(ALCbackend, self)); +} - if(!data->thread) - return; +static void ALCnullBackend_lock(ALCnullBackend *self) +{ + ALCbackend_lock(STATIC_CAST(ALCbackend, self)); +} - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; +static void ALCnullBackend_unlock(ALCnullBackend *self) +{ + ALCbackend_unlock(STATIC_CAST(ALCbackend, self)); +} - data->killNow = 0; +static void ALCnullBackend_Delete(ALCnullBackend *self) +{ + free(self); } +DEFINE_ALCBACKEND_VTABLE(ALCnullBackend); + -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 -}; +typedef struct ALCnullBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCnullBackendFactory; +#define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCnullBackendFactory, ALCbackendFactory) } } -ALCboolean alc_null_init(BackendFuncs *func_list) +ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory* UNUSED(self)) { - *func_list = null_funcs; return ALC_TRUE; } -void alc_null_deinit(void) +void ALCnullBackendFactory_deinit(ALCnullBackendFactory* UNUSED(self)) { } -void alc_null_probe(enum DevProbe type) +ALCboolean ALCnullBackendFactory_support(ALCnullBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type) { switch(type) { @@ -172,3 +188,25 @@ void alc_null_probe(enum DevProbe type) break; } } + +ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device) +{ + ALCnullBackend *backend; + + backend = calloc(1, sizeof(*backend)); + if(!backend) return NULL; + SET_VTABLE2(ALCnullBackend, ALCbackend, backend); + + STATIC_CAST(ALCbackend, backend)->mDevice = device; + + return STATIC_CAST(ALCbackend, backend); +} + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory); + + +ALCbackendFactory *ALCnullBackendFactory_getFactory(void) +{ + static ALCnullBackendFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 01a2ec37..74c5b0e6 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -497,9 +497,6 @@ void alc_opensl_probe(enum DevProbe type); ALCboolean alc_qsa_init(BackendFuncs *func_list); void alc_qsa_deinit(void); void alc_qsa_probe(enum DevProbe type); -ALCboolean alc_null_init(BackendFuncs *func_list); -void alc_null_deinit(void); -void alc_null_probe(enum DevProbe type); ALCboolean alc_loopback_init(BackendFuncs *func_list); void alc_loopback_deinit(void); void alc_loopback_probe(enum DevProbe type); |