diff options
Diffstat (limited to 'Alc/backends/winmm.c')
-rw-r--r-- | Alc/backends/winmm.c | 199 |
1 files changed, 91 insertions, 108 deletions
diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index bf97ef2e..0d4a02b8 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -29,6 +29,7 @@ #include "alMain.h" #include "alu.h" +#include "ringbuffer.h" #include "threads.h" #include "backends/base.h" @@ -37,7 +38,7 @@ #define WAVE_FORMAT_IEEE_FLOAT 0x0003 #endif -#define DEVNAME_TAIL " on OpenAL Soft" +#define DEVNAME_HEAD "OpenAL Soft on " static vector_al_string PlaybackDevices; @@ -45,8 +46,8 @@ static vector_al_string CaptureDevices; static void clear_devlist(vector_al_string *list) { - VECTOR_FOR_EACH(al_string, *list, al_string_deinit); - VECTOR_RESIZE(*list, 0); + VECTOR_FOR_EACH(al_string, *list, alstr_reset); + VECTOR_RESIZE(*list, 0, 0); } @@ -58,7 +59,7 @@ static void ProbePlaybackDevices(void) clear_devlist(&PlaybackDevices); numdevs = waveOutGetNumDevs(); - VECTOR_RESERVE(PlaybackDevices, numdevs); + VECTOR_RESIZE(PlaybackDevices, 0, numdevs); for(i = 0;i < numdevs;i++) { WAVEOUTCAPSW WaveCaps; @@ -71,24 +72,23 @@ static void ProbePlaybackDevices(void) ALuint count = 0; while(1) { - al_string_copy_wcstr(&dname, WaveCaps.szPname); - if(count == 0) - al_string_append_cstr(&dname, DEVNAME_TAIL); - else + alstr_copy_cstr(&dname, DEVNAME_HEAD); + alstr_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); - al_string_append_cstr(&dname, str); + snprintf(str, sizeof(str), " #%d", count+1); + alstr_append_cstr(&dname, str); } count++; -#define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(PlaybackDevices)) break; + if(iter == VECTOR_END(PlaybackDevices)) break; #undef MATCH_ENTRY } - TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); + TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i); } VECTOR_PUSH_BACK(PlaybackDevices, dname); } @@ -102,7 +102,7 @@ static void ProbeCaptureDevices(void) clear_devlist(&CaptureDevices); numdevs = waveInGetNumDevs(); - VECTOR_RESERVE(CaptureDevices, numdevs); + VECTOR_RESIZE(CaptureDevices, 0, numdevs); for(i = 0;i < numdevs;i++) { WAVEINCAPSW WaveCaps; @@ -115,24 +115,23 @@ static void ProbeCaptureDevices(void) ALuint count = 0; while(1) { - al_string_copy_wcstr(&dname, WaveCaps.szPname); - if(count == 0) - al_string_append_cstr(&dname, DEVNAME_TAIL); - else + alstr_copy_cstr(&dname, DEVNAME_HEAD); + alstr_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) { char str[64]; - snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1); - al_string_append_cstr(&dname, str); + snprintf(str, sizeof(str), " #%d", count+1); + alstr_append_cstr(&dname, str); } count++; -#define MATCH_ENTRY(i) (al_string_cmp(dname, *(i)) == 0) +#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY); - if(iter == VECTOR_ITER_END(CaptureDevices)) break; + if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY } - TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); + TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i); } VECTOR_PUSH_BACK(CaptureDevices, dname); } @@ -149,7 +148,7 @@ typedef struct ALCwinmmPlayback { WAVEFORMATEX Format; - volatile ALboolean killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCwinmmPlayback; @@ -160,13 +159,12 @@ static void CALLBACK ALCwinmmPlayback_waveOutProc(HWAVEOUT device, UINT msg, DWO static int ALCwinmmPlayback_mixerProc(void *arg); static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *name); -static void ALCwinmmPlayback_close(ALCwinmmPlayback *self); static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self); static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self); static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self); static DECLARE_FORWARD2(ALCwinmmPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ALCuint, availableSamples) -static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCwinmmPlayback) @@ -182,7 +180,7 @@ static void ALCwinmmPlayback_Construct(ALCwinmmPlayback *self, ALCdevice *device InitRef(&self->WaveBuffersCommitted, 0); self->OutHdl = NULL; - self->killNow = AL_TRUE; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCwinmmPlayback_Destruct(ALCwinmmPlayback *self) @@ -226,7 +224,7 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg) if(msg.message != WOM_DONE) continue; - if(self->killNow) + if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) { if(ReadRef(&self->WaveBuffersCommitted) == 0) break; @@ -234,8 +232,10 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg) } WaveHdr = ((WAVEHDR*)msg.lParam); + ALCwinmmPlayback_lock(self); aluMixData(device, WaveHdr->lpData, WaveHdr->dwBufferLength / self->Format.nBlockAlign); + ALCwinmmPlayback_unlock(self); // Send buffer back to play more data waveOutWrite(self->OutHdl, WaveHdr, sizeof(WAVEHDR)); @@ -257,14 +257,14 @@ static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *devi ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid -#define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && \ - (!deviceName || al_string_cmp_cstr(*(iter), deviceName) == 0)) +#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && \ + (!deviceName || alstr_cmp_cstr(*(iter), deviceName) == 0)) VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_DEVNAME); - if(iter == VECTOR_ITER_END(PlaybackDevices)) + if(iter == VECTOR_END(PlaybackDevices)) return ALC_INVALID_VALUE; #undef MATCH_DEVNAME - DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices)); + DeviceID = (UINT)(iter - VECTOR_BEGIN(PlaybackDevices)); retry_open: memset(&self->Format, 0, sizeof(WAVEFORMATEX)); @@ -300,7 +300,7 @@ retry_open: goto failure; } - al_string_copy(&device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); + alstr_copy(&device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); return ALC_NO_ERROR; failure: @@ -311,9 +311,6 @@ failure: return ALC_INVALID_VALUE; } -static void ALCwinmmPlayback_close(ALCwinmmPlayback* UNUSED(self)) -{ } - static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -374,7 +371,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self) ALint BufferSize; ALuint i; - self->killNow = AL_FALSE; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; @@ -382,7 +379,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self) // Create 4 Buffers BufferSize = device->UpdateSize*device->NumUpdates / 4; - BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); BufferData = calloc(4, BufferSize); for(i = 0;i < 4;i++) @@ -405,11 +402,8 @@ static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self) void *buffer = NULL; int i; - if(self->killNow) + if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) return; - - // Set flag to stop processing headers - self->killNow = AL_TRUE; althrd_join(self->thread, &i); // Release the wave buffers @@ -432,11 +426,11 @@ typedef struct ALCwinmmCapture { HWAVEIN InHdl; - RingBuffer *Ring; + ll_ringbuffer_t *Ring; WAVEFORMATEX Format; - volatile ALboolean killNow; + ATOMIC(ALenum) killNow; althrd_t thread; } ALCwinmmCapture; @@ -447,13 +441,12 @@ static void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN device, UINT msg, DWORD_ static int ALCwinmmCapture_captureProc(void *arg); static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name); -static void ALCwinmmCapture_close(ALCwinmmCapture *self); static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ALCboolean, reset) static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self); static void ALCwinmmCapture_stop(ALCwinmmCapture *self); static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self); -static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ClockLatency, getClockLatency) static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, lock) static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, unlock) DECLARE_DEFAULT_ALLOCATORS(ALCwinmmCapture) @@ -469,11 +462,38 @@ static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device) InitRef(&self->WaveBuffersCommitted, 0); self->InHdl = NULL; - self->killNow = AL_TRUE; + ATOMIC_INIT(&self->killNow, AL_TRUE); } static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) { + void *buffer = NULL; + int i; + + /* Tell the processing thread to quit and wait for it to do so. */ + if(!ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel)) + { + PostThreadMessage(self->thread, WM_QUIT, 0, 0); + + althrd_join(self->thread, &i); + + /* Make sure capture is stopped and all pending buffers are flushed. */ + waveInReset(self->InHdl); + + // Release the wave buffers + for(i = 0;i < 4;i++) + { + waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); + if(i == 0) buffer = self->WaveBuffer[i].lpData; + self->WaveBuffer[i].lpData = NULL; + } + free(buffer); + } + + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + // Close the Wave device if(self->InHdl) waveInClose(self->InHdl); self->InHdl = 0; @@ -512,12 +532,13 @@ static int ALCwinmmCapture_captureProc(void *arg) continue; /* Don't wait for other buffers to finish before quitting. We're * closing so we don't need them. */ - if(self->killNow) + if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire)) break; WaveHdr = ((WAVEHDR*)msg.lParam); - WriteRingBuffer(self->Ring, (ALubyte*)WaveHdr->lpData, - WaveHdr->dwBytesRecorded/self->Format.nBlockAlign); + ll_ringbuffer_write(self->Ring, WaveHdr->lpData, + WaveHdr->dwBytesRecorded / self->Format.nBlockAlign + ); // Send buffer back to capture more data waveInAddBuffer(self->InHdl, WaveHdr, sizeof(WAVEHDR)); @@ -543,13 +564,13 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid -#define MATCH_DEVNAME(iter) (!al_string_empty(*(iter)) && (!name || al_string_cmp_cstr(*iter, name) == 0)) +#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && (!name || alstr_cmp_cstr(*iter, name) == 0)) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_DEVNAME); - if(iter == VECTOR_ITER_END(CaptureDevices)) + if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; #undef MATCH_DEVNAME - DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices)); + DeviceID = (UINT)(iter - VECTOR_BEGIN(CaptureDevices)); switch(device->FmtChans) { @@ -562,7 +583,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: - case DevFmtBFormat3D: + case DevFmtAmbi3D: return ALC_INVALID_ENUM; } @@ -583,7 +604,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) memset(&self->Format, 0, sizeof(WAVEFORMATEX)); self->Format.wFormatTag = ((device->FmtType == DevFmtFloat) ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM); - self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans); + self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); self->Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; self->Format.nBlockAlign = self->Format.wBitsPerSample * self->Format.nChannels / 8; @@ -605,7 +626,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) if(CapturedDataSize < (self->Format.nSamplesPerSec / 10)) CapturedDataSize = self->Format.nSamplesPerSec / 10; - self->Ring = CreateRingBuffer(self->Format.nBlockAlign, CapturedDataSize); + self->Ring = ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false); if(!self->Ring) goto failure; InitRef(&self->WaveBuffersCommitted, 0); @@ -631,11 +652,11 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) IncrementRef(&self->WaveBuffersCommitted); } - self->killNow = AL_FALSE; + ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success) goto failure; - al_string_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); + alstr_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: @@ -646,8 +667,7 @@ failure: free(BufferData); } - if(self->Ring) - DestroyRingBuffer(self->Ring); + ll_ringbuffer_free(self->Ring); self->Ring = NULL; if(self->InHdl) @@ -657,37 +677,6 @@ failure: return ALC_INVALID_VALUE; } -static void ALCwinmmCapture_close(ALCwinmmCapture *self) -{ - void *buffer = NULL; - int i; - - /* Tell the processing thread to quit and wait for it to do so. */ - self->killNow = AL_TRUE; - PostThreadMessage(self->thread, WM_QUIT, 0, 0); - - althrd_join(self->thread, &i); - - /* Make sure capture is stopped and all pending buffers are flushed. */ - waveInReset(self->InHdl); - - // Release the wave buffers - for(i = 0;i < 4;i++) - { - waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); - if(i == 0) buffer = self->WaveBuffer[i].lpData; - self->WaveBuffer[i].lpData = NULL; - } - free(buffer); - - DestroyRingBuffer(self->Ring); - self->Ring = NULL; - - // Close the Wave device - waveInClose(self->InHdl); - self->InHdl = NULL; -} - static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self) { waveInStart(self->InHdl); @@ -701,27 +690,16 @@ static void ALCwinmmCapture_stop(ALCwinmmCapture *self) static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples) { - ReadRingBuffer(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring, buffer, samples); return ALC_NO_ERROR; } static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) { - return RingBufferSize(self->Ring); + return (ALCuint)ll_ringbuffer_read_space(self->Ring); } -static inline void AppendAllDevicesList2(const al_string *name) -{ - if(!al_string_empty(*name)) - AppendAllDevicesList(al_string_get_cstr(*name)); -} -static inline void AppendCaptureDeviceList2(const al_string *name) -{ - if(!al_string_empty(*name)) - AppendCaptureDeviceList(al_string_get_cstr(*name)); -} - typedef struct ALCwinmmBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCwinmmBackendFactory; @@ -730,7 +708,7 @@ typedef struct ALCwinmmBackendFactory { static ALCboolean ALCwinmmBackendFactory_init(ALCwinmmBackendFactory *self); static void ALCwinmmBackendFactory_deinit(ALCwinmmBackendFactory *self); static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory *self, ALCbackend_Type type); -static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory *self, enum DevProbe type); +static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory *self, enum DevProbe type, al_string *outnames); static ALCbackend* ALCwinmmBackendFactory_createBackend(ALCwinmmBackendFactory *self, ALCdevice *device, ALCbackend_Type type); DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwinmmBackendFactory); @@ -760,19 +738,24 @@ static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory* UN return ALC_FALSE; } -static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory* UNUSED(self), enum DevProbe type) +static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames) { switch(type) { +#define APPEND_OUTNAME(n) do { \ + if(!alstr_empty(*(n))) \ + alstr_append_range(outnames, VECTOR_BEGIN(*(n)), VECTOR_END(*(n))+1); \ +} while(0) case ALL_DEVICE_PROBE: ProbePlaybackDevices(); - VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2); + VECTOR_FOR_EACH(const al_string, PlaybackDevices, APPEND_OUTNAME); break; case CAPTURE_DEVICE_PROBE: ProbeCaptureDevices(); - VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2); + VECTOR_FOR_EACH(const al_string, CaptureDevices, APPEND_OUTNAME); break; +#undef APPEND_OUTNAME } } |