diff options
Diffstat (limited to 'Alc/backends')
-rw-r--r-- | Alc/backends/base.h | 1 | ||||
-rw-r--r-- | Alc/backends/dsound.c | 511 |
2 files changed, 292 insertions, 220 deletions
diff --git a/Alc/backends/base.h b/Alc/backends/base.h index d18ca400..31f46a1a 100644 --- a/Alc/backends/base.h +++ b/Alc/backends/base.h @@ -126,6 +126,7 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ ALCbackendFactory *ALCpulseBackendFactory_getFactory(void); ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c index b09208ae..f487a6cb 100644 --- a/Alc/backends/dsound.c +++ b/Alc/backends/dsound.c @@ -38,6 +38,8 @@ #include "compat.h" #include "alstring.h" +#include "backends/base.h" + #ifndef DSSPEAKER_5POINT1 # define DSSPEAKER_5POINT1 0x00000006 #endif @@ -68,41 +70,6 @@ static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnum #define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW -typedef struct { - // DirectSound Playback Device - IDirectSound *DS; - IDirectSoundBuffer *PrimaryBuffer; - IDirectSoundBuffer *Buffer; - IDirectSoundNotify *Notifies; - HANDLE NotifyEvent; - - volatile int killNow; - althrd_t thread; -} DSoundPlaybackData; - -typedef struct { - // DirectSound Capture Device - IDirectSoundCapture *DSC; - IDirectSoundCaptureBuffer *DSCbuffer; - DWORD BufferBytes; - DWORD Cursor; - RingBuffer *Ring; -} DSoundCaptureData; - - -typedef struct { - al_string name; - GUID guid; -} DevMap; -DECL_VECTOR(DevMap) - -vector_DevMap PlaybackDevices; -vector_DevMap CaptureDevices; - - -#define MAX_UPDATES 128 - - static ALCboolean DSoundLoad(void) { if(!ds_handle) @@ -132,6 +99,17 @@ static ALCboolean DSoundLoad(void) } +#define MAX_UPDATES 128 + +typedef struct { + al_string name; + GUID guid; +} DevMap; +DECL_VECTOR(DevMap) + +vector_DevMap PlaybackDevices; +vector_DevMap CaptureDevices; + static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCWSTR desc, LPCWSTR UNUSED(drvname), LPVOID data) { vector_DevMap *devices = data; @@ -180,10 +158,49 @@ static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCWSTR desc, LPCWSTR UNUSED } -FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) +typedef struct ALCdsoundPlayback { + DERIVE_FROM_TYPE(ALCbackend); + + IDirectSound *DS; + IDirectSoundBuffer *PrimaryBuffer; + IDirectSoundBuffer *Buffer; + IDirectSoundNotify *Notifies; + HANDLE NotifyEvent; + + volatile int killNow; + althrd_t thread; +} ALCdsoundPlayback; + +static int ALCdsoundPlayback_mixerProc(void *ptr); + +static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device); +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, Destruct) +static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name); +static void ALCdsoundPlayback_close(ALCdsoundPlayback *self); +static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self); +static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self); +static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self); +static DECLARE_FORWARD2(ALCdsoundPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCdsoundPlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCdsoundPlayback); + + +static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device) { - ALCdevice *Device = (ALCdevice*)ptr; - DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData; + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self); +} + + +FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) +{ + ALCdsoundPlayback *self = ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DSBCAPS DSBCaps; DWORD LastCursor = 0; DWORD PlayCursor; @@ -200,43 +217,43 @@ FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) memset(&DSBCaps, 0, sizeof(DSBCaps)); DSBCaps.dwSize = sizeof(DSBCaps); - err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps); + err = IDirectSoundBuffer_GetCaps(self->Buffer, &DSBCaps); if(FAILED(err)) { ERR("Failed to get buffer caps: 0x%lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - FragSize = Device->UpdateSize * FrameSize; + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + FragSize = device->UpdateSize * FrameSize; - IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL); - while(!data->killNow) + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL); + while(!self->killNow) { // Get current play cursor - IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL); + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL); avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; if(avail < FragSize) { if(!Playing) { - err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING); + err = IDirectSoundBuffer_Play(self->Buffer, 0, 0, DSBPLAY_LOOPING); if(FAILED(err)) { ERR("Failed to play buffer: 0x%lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } Playing = TRUE; } - avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE); + avail = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); if(avail != WAIT_OBJECT_0) ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); continue; @@ -246,18 +263,18 @@ FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) // Lock output buffer WriteCnt1 = 0; WriteCnt2 = 0; - err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + err = IDirectSoundBuffer_Lock(self->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); // If the buffer is lost, restore it and lock if(err == DSERR_BUFFERLOST) { WARN("Buffer lost, restoring...\n"); - err = IDirectSoundBuffer_Restore(data->Buffer); + err = IDirectSoundBuffer_Restore(self->Buffer); if(SUCCEEDED(err)) { Playing = FALSE; LastCursor = 0; - err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + err = IDirectSoundBuffer_Lock(self->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); } } @@ -265,18 +282,18 @@ FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) if(SUCCEEDED(err)) { // If we have an active context, mix data directly into output buffer otherwise fill with silence - aluMixData(Device, WritePtr1, WriteCnt1/FrameSize); - aluMixData(Device, WritePtr2, WriteCnt2/FrameSize); + aluMixData(device, WritePtr1, WriteCnt1/FrameSize); + aluMixData(device, WritePtr2, WriteCnt2/FrameSize); // Unlock output buffer only when successfully locked - IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); + IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); } else { ERR("Buffer lock error: %#lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } @@ -288,9 +305,9 @@ FORCE_ALIGN static int DSoundPlaybackProc(void *ptr) return 0; } -static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) +static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *deviceName) { - DSoundPlaybackData *data = NULL; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; LPGUID guid = NULL; HRESULT hr, hrcom; @@ -328,60 +345,55 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - //Initialise requested device - data = calloc(1, sizeof(DSoundPlaybackData)); - if(!data) - return ALC_OUT_OF_MEMORY; - hr = DS_OK; - data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->NotifyEvent == NULL) + self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL) hr = E_FAIL; //DirectSound Init code if(SUCCEEDED(hr)) - hr = DirectSoundCreate(guid, &data->DS, NULL); + hr = DirectSoundCreate(guid, &self->DS, NULL); if(SUCCEEDED(hr)) - hr = IDirectSound_SetCooperativeLevel(data->DS, GetForegroundWindow(), DSSCL_PRIORITY); + hr = IDirectSound_SetCooperativeLevel(self->DS, GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) { - if(data->DS) - IDirectSound_Release(data->DS); - if(data->NotifyEvent) - CloseHandle(data->NotifyEvent); - free(data); + if(self->DS) + IDirectSound_Release(self->DS); + self->DS = NULL; + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + ERR("Device init failed: 0x%08lx\n", hr); return ALC_INVALID_VALUE; } al_string_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; + return ALC_NO_ERROR; } -static void DSoundClosePlayback(ALCdevice *device) +static void ALCdsoundPlayback_close(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = device->ExtraData; - - if(data->Notifies) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; - - IDirectSound_Release(data->DS); - CloseHandle(data->NotifyEvent); - free(data); - device->ExtraData = NULL; + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + + IDirectSound_Release(self->DS); + self->DS = NULL; + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; } -static ALCboolean DSoundResetPlayback(ALCdevice *device) +static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD speakers; @@ -389,15 +401,15 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device) memset(&OutputType, 0, sizeof(OutputType)); - if(data->Notifies) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; switch(device->FmtType) { @@ -420,7 +432,7 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device) break; } - hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers); + hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers); if(SUCCEEDED(hr)) { if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) @@ -513,21 +525,21 @@ retry_open: else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - if(data->PrimaryBuffer) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->PrimaryBuffer) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; } else { - if(SUCCEEDED(hr) && !data->PrimaryBuffer) + if(SUCCEEDED(hr) && !self->PrimaryBuffer) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; - hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL); + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->PrimaryBuffer, NULL); } if(SUCCEEDED(hr)) - hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format); + hr = IDirectSoundBuffer_SetFormat(self->PrimaryBuffer,&OutputType.Format); } if(SUCCEEDED(hr)) @@ -545,7 +557,7 @@ retry_open: DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; - hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL); + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->Buffer, NULL); if(FAILED(hr) && device->FmtType == DevFmtFloat) { device->FmtType = DevFmtShort; @@ -555,7 +567,7 @@ retry_open: if(SUCCEEDED(hr)) { - hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies); + hr = IDirectSoundBuffer_QueryInterface(self->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&self->Notifies); if(SUCCEEDED(hr)) { DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; @@ -565,62 +577,93 @@ retry_open: { notifies[i].dwOffset = i * device->UpdateSize * OutputType.Format.nBlockAlign; - notifies[i].hEventNotify = data->NotifyEvent; + notifies[i].hEventNotify = self->NotifyEvent; } - if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK) + if(IDirectSoundNotify_SetNotificationPositions(self->Notifies, device->NumUpdates, notifies) != DS_OK) hr = E_FAIL; } } if(FAILED(hr)) { - if(data->Notifies != NULL) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer != NULL) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->Notifies != NULL) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer != NULL) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; return ALC_FALSE; } - ResetEvent(data->NotifyEvent); + ResetEvent(self->NotifyEvent); SetDefaultWFXChannelOrder(device); return ALC_TRUE; } -static ALCboolean DSoundStartPlayback(ALCdevice *device) +static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; - - data->killNow = 0; - if(althrd_create(&data->thread, DSoundPlaybackProc, device) != althrd_success) + self->killNow = 0; + if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } -static void DSoundStopPlayback(ALCdevice *device) +static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = device->ExtraData; int res; - if(data->killNow) + if(self->killNow) return; - data->killNow = 1; - althrd_join(data->thread, &res); + self->killNow = 1; + althrd_join(self->thread, &res); + + IDirectSoundBuffer_Stop(self->Buffer); +} + + + +typedef struct ALCdsoundCapture { + DERIVE_FROM_TYPE(ALCbackend); - IDirectSoundBuffer_Stop(data->Buffer); + IDirectSoundCapture *DSC; + IDirectSoundCaptureBuffer *DSCbuffer; + DWORD BufferBytes; + DWORD Cursor; + RingBuffer *Ring; +} ALCdsoundCapture; + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct) +static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name); +static void ALCdsoundCapture_close(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self); +static void ALCdsoundCapture_stop(ALCdsoundCapture *self); +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCdsoundCapture); + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCdsoundCapture, ALCbackend, self); } -static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) +static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName) { - DSoundCaptureData *data = NULL; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; WAVEFORMATEXTENSIBLE InputType; DSCBUFFERDESC DSCBDescription; LPGUID guid = NULL; @@ -676,16 +719,8 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) break; } - //Initialise requested device - data = calloc(1, sizeof(DSoundCaptureData)); - if(!data) - return ALC_OUT_OF_MEMORY; - - hr = DS_OK; - //DirectSoundCapture Init code - if(SUCCEEDED(hr)) - hr = DirectSoundCaptureCreate(guid, &data->DSC, NULL); + hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL); if(SUCCEEDED(hr)) { memset(&InputType, 0, sizeof(InputType)); @@ -770,12 +805,12 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign; DSCBDescription.lpwfxFormat = &InputType.Format; - hr = IDirectSoundCapture_CreateCaptureBuffer(data->DSC, &DSCBDescription, &data->DSCbuffer, NULL); + hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL); } if(SUCCEEDED(hr)) { - data->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); - if(data->Ring == NULL) + self->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); + if(self->Ring == NULL) hr = DSERR_OUTOFMEMORY; } @@ -783,158 +818,156 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) { ERR("Device init failed: 0x%08lx\n", hr); - DestroyRingBuffer(data->Ring); - data->Ring = NULL; - if(data->DSCbuffer != NULL) - IDirectSoundCaptureBuffer_Release(data->DSCbuffer); - data->DSCbuffer = NULL; - if(data->DSC) - IDirectSoundCapture_Release(data->DSC); - data->DSC = NULL; + DestroyRingBuffer(self->Ring); + self->Ring = NULL; + if(self->DSCbuffer != NULL) + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; + if(self->DSC) + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; - free(data); return ALC_INVALID_VALUE; } - data->BufferBytes = DSCBDescription.dwBufferBytes; + self->BufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(device); al_string_copy_cstr(&device->DeviceName, deviceName); - device->ExtraData = data; return ALC_NO_ERROR; } -static void DSoundCloseCapture(ALCdevice *device) +static void ALCdsoundCapture_close(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; - - DestroyRingBuffer(data->Ring); - data->Ring = NULL; + DestroyRingBuffer(self->Ring); + self->Ring = NULL; - if(data->DSCbuffer != NULL) + if(self->DSCbuffer != NULL) { - IDirectSoundCaptureBuffer_Stop(data->DSCbuffer); - IDirectSoundCaptureBuffer_Release(data->DSCbuffer); - data->DSCbuffer = NULL; + IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; } - IDirectSoundCapture_Release(data->DSC); - data->DSC = NULL; - - free(data); - device->ExtraData = NULL; + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; } -static void DSoundStartCapture(ALCdevice *device) +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; HRESULT hr; - hr = IDirectSoundCaptureBuffer_Start(data->DSCbuffer, DSCBSTART_LOOPING); + hr = IDirectSoundCaptureBuffer_Start(self->DSCbuffer, DSCBSTART_LOOPING); if(FAILED(hr)) { ERR("start failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_FALSE; } + + return ALC_TRUE; } -static void DSoundStopCapture(ALCdevice *device) +static void ALCdsoundCapture_stop(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; HRESULT hr; - hr = IDirectSoundCaptureBuffer_Stop(data->DSCbuffer); + hr = IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); if(FAILED(hr)) { ERR("stop failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); } } -static ALCenum DSoundCaptureSamples(ALCdevice *Device, ALCvoid *pBuffer, ALCuint lSamples) +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) { - DSoundCaptureData *data = Device->ExtraData; - ReadRingBuffer(data->Ring, pBuffer, lSamples); + ReadRingBuffer(self->Ring, buffer, samples); return ALC_NO_ERROR; } -static ALCuint DSoundAvailableSamples(ALCdevice *Device) +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) { - DSoundCaptureData *data = Device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DWORD ReadCursor, LastCursor, BufferBytes, NumBytes; VOID *ReadPtr1, *ReadPtr2; DWORD ReadCnt1, ReadCnt2; DWORD FrameSize; HRESULT hr; - if(!Device->Connected) + if(!device->Connected) goto done; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - BufferBytes = data->BufferBytes; - LastCursor = data->Cursor; + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + BufferBytes = self->BufferBytes; + LastCursor = self->Cursor; - hr = IDirectSoundCaptureBuffer_GetCurrentPosition(data->DSCbuffer, NULL, &ReadCursor); + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(self->DSCbuffer, NULL, &ReadCursor); if(SUCCEEDED(hr)) { NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes; if(NumBytes == 0) goto done; - hr = IDirectSoundCaptureBuffer_Lock(data->DSCbuffer, LastCursor, NumBytes, + hr = IDirectSoundCaptureBuffer_Lock(self->DSCbuffer, LastCursor, NumBytes, &ReadPtr1, &ReadCnt1, &ReadPtr2, &ReadCnt2, 0); } if(SUCCEEDED(hr)) { - WriteRingBuffer(data->Ring, ReadPtr1, ReadCnt1/FrameSize); + WriteRingBuffer(self->Ring, ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != NULL) - WriteRingBuffer(data->Ring, ReadPtr2, ReadCnt2/FrameSize); - hr = IDirectSoundCaptureBuffer_Unlock(data->DSCbuffer, + WriteRingBuffer(self->Ring, ReadPtr2, ReadCnt2/FrameSize); + hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer, ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); - data->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; + self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; } if(FAILED(hr)) { ERR("update failed: 0x%08lx\n", hr); - aluHandleDisconnect(Device); + aluHandleDisconnect(device); } done: - return RingBufferSize(data->Ring); + return RingBufferSize(self->Ring); } -static const BackendFuncs DSoundFuncs = { - DSoundOpenPlayback, - DSoundClosePlayback, - DSoundResetPlayback, - DSoundStartPlayback, - DSoundStopPlayback, - DSoundOpenCapture, - DSoundCloseCapture, - DSoundStartCapture, - DSoundStopCapture, - DSoundCaptureSamples, - DSoundAvailableSamples, - ALCdevice_GetLatencyDefault -}; +typedef struct ALCdsoundBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCdsoundBackendFactory; +#define ALCDSOUNDBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory *self); +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory *self); +static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory *self, ALCbackend_Type type); +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory); + +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void) +{ + static ALCdsoundBackendFactory factory = ALCDSOUNDBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} -ALCboolean alcDSoundInit(BackendFuncs *FuncList) + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(self)) { VECTOR_INIT(PlaybackDevices); VECTOR_INIT(CaptureDevices); if(!DSoundLoad()) return ALC_FALSE; - *FuncList = DSoundFuncs; return ALC_TRUE; } -void alcDSoundDeinit(void) +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory* UNUSED(self)) { DevMap *iter, *end; @@ -955,7 +988,14 @@ void alcDSoundDeinit(void) ds_handle = NULL; } -void alcDSoundProbe(enum DevProbe type) +static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type) { DevMap *iter, *end; HRESULT hr, hrcom; @@ -1005,3 +1045,34 @@ void alcDSoundProbe(enum DevProbe type) if(SUCCEEDED(hrcom)) CoUninitialize(); } + +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCdsoundPlayback *backend; + + backend = ALCdsoundPlayback_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCdsoundPlayback_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + if(type == ALCbackend_Capture) + { + ALCdsoundCapture *backend; + + backend = ALCdsoundCapture_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCdsoundCapture_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} |