diff options
author | Sven Gothel <[email protected]> | 2014-06-10 05:30:02 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-10 05:30:02 +0200 |
commit | f95bf4457fbc31112fa82dacbc1b7e094b9fd1cf (patch) | |
tree | 965ba5b8e6fc8e6bfe7a981c1dfb1179bb9adcde /Alc/backends/winmm.c | |
parent | 7297c3214a4c648aaee81a9877da15b88f798197 (diff) | |
parent | c07fb7b45c1e345dbaa439882250de5b2213026f (diff) |
Merge branch 'UPSTREAM' into UPSTREAM_MERGE
Diffstat (limited to 'Alc/backends/winmm.c')
-rw-r--r-- | Alc/backends/winmm.c | 333 |
1 files changed, 142 insertions, 191 deletions
diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c index 7082a874..624af37a 100644 --- a/Alc/backends/winmm.c +++ b/Alc/backends/winmm.c @@ -39,10 +39,9 @@ typedef struct { // MMSYSTEM Device volatile ALboolean killNow; - HANDLE WaveThreadEvent; - HANDLE WaveThread; - DWORD WaveThreadID; - volatile LONG WaveBuffersCommitted; + althrd_t thread; + + RefCount WaveBuffersCommitted; WAVEHDR WaveBuffer[4]; union { @@ -56,87 +55,106 @@ typedef struct { } WinMMData; -static ALCchar **PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static ALCchar **CaptureDeviceList; -static ALuint NumCaptureDevices; +static vector_al_string PlaybackDevices; +static vector_al_string CaptureDevices; + +static void clear_devlist(vector_al_string *list) +{ + al_string *iter, *end; + + iter = VECTOR_ITER_BEGIN(*list); + end = VECTOR_ITER_END(*list); + for(;iter != end;iter++) + AL_STRING_DEINIT(*iter); + VECTOR_RESIZE(*list, 0); +} static void ProbePlaybackDevices(void) { + al_string *iter, *end; + ALuint numdevs; ALuint i; - for(i = 0;i < NumPlaybackDevices;i++) - free(PlaybackDeviceList[i]); + clear_devlist(&PlaybackDevices); - NumPlaybackDevices = waveOutGetNumDevs(); - PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) + numdevs = waveOutGetNumDevs(); + VECTOR_RESERVE(PlaybackDevices, numdevs); + for(i = 0;i < numdevs;i++) { - WAVEOUTCAPS WaveCaps; + WAVEOUTCAPSW WaveCaps; + al_string dname; - PlaybackDeviceList[i] = NULL; - if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) + AL_STRING_INIT(dname); + if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - char name[1024]; - ALuint count, j; - - count = 0; + ALuint count = 0; do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1); + al_string_copy_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; - for(j = 0;j < i;j++) + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) { - if(strcmp(name, PlaybackDeviceList[j]) == 0) + if(al_string_cmp(*iter, dname) == 0) break; } - } while(j != i); + } while(iter != end); - PlaybackDeviceList[i] = strdup(name); + TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); } + VECTOR_PUSH_BACK(PlaybackDevices, dname); } } static void ProbeCaptureDevices(void) { + al_string *iter, *end; + ALuint numdevs; ALuint i; - for(i = 0;i < NumCaptureDevices;i++) - free(CaptureDeviceList[i]); + clear_devlist(&CaptureDevices); - NumCaptureDevices = waveInGetNumDevs(); - CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices); - for(i = 0;i < NumCaptureDevices;i++) + numdevs = waveInGetNumDevs(); + VECTOR_RESERVE(CaptureDevices, numdevs); + for(i = 0;i < numdevs;i++) { - WAVEINCAPS WaveInCaps; + WAVEINCAPSW WaveCaps; + al_string dname; - CaptureDeviceList[i] = NULL; - if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) + AL_STRING_INIT(dname); + if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - char name[1024]; - ALuint count, j; - - count = 0; + ALuint count = 0; do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveInCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1); + al_string_copy_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; - for(j = 0;j < i;j++) + iter = VECTOR_ITER_BEGIN(CaptureDevices); + end = VECTOR_ITER_END(CaptureDevices); + for(;iter != end;iter++) { - if(strcmp(name, CaptureDeviceList[j]) == 0) + if(al_string_cmp(*iter, dname) == 0) break; } - } while(j != i); + } while(iter != end); - CaptureDeviceList[i] = strdup(name); + TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); } + VECTOR_PUSH_BACK(CaptureDevices, dname); } } @@ -155,28 +173,19 @@ static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR in if(msg != WOM_DONE) return; - InterlockedDecrement(&data->WaveBuffersCommitted); - PostThreadMessage(data->WaveThreadID, msg, 0, param1); + DecrementRef(&data->WaveBuffersCommitted); + PostThreadMessage(data->thread, msg, 0, param1); } -/* - PlaybackThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its - audio data. -*/ -FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param) +FORCE_ALIGN static int PlaybackThreadProc(void *arg) { - ALCdevice *Device = (ALCdevice*)param; + ALCdevice *Device = (ALCdevice*)arg; WinMMData *data = Device->ExtraData; - LPWAVEHDR WaveHdr; - ALuint FrameSize; + WAVEHDR *WaveHdr; MSG msg; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); while(GetMessage(&msg, NULL, 0, 0)) { @@ -185,24 +194,20 @@ FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param) if(data->killNow) { - if(data->WaveBuffersCommitted == 0) + if(ReadRef(&data->WaveBuffersCommitted) == 0) break; continue; } - WaveHdr = ((LPWAVEHDR)msg.lParam); - aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength/FrameSize); + WaveHdr = ((WAVEHDR*)msg.lParam); + aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength / + data->Format.nBlockAlign); // Send buffer back to play more data waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - // Signal Wave Thread completed event - if(data->WaveThreadEvent) - SetEvent(data->WaveThreadEvent); - - ExitThread(0); return 0; } @@ -220,26 +225,18 @@ static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR inst if(msg != WIM_DATA) return; - InterlockedDecrement(&data->WaveBuffersCommitted); - PostThreadMessage(data->WaveThreadID, msg, 0, param1); + DecrementRef(&data->WaveBuffersCommitted); + PostThreadMessage(data->thread, msg, 0, param1); } -/* - CaptureThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new - audio data. -*/ -static DWORD WINAPI CaptureThreadProc(LPVOID param) +static int CaptureThreadProc(void *arg) { - ALCdevice *Device = (ALCdevice*)param; + ALCdevice *Device = (ALCdevice*)arg; WinMMData *data = Device->ExtraData; - LPWAVEHDR WaveHdr; - ALuint FrameSize; + WAVEHDR *WaveHdr; MSG msg; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - SetThreadName("alsoft-record"); + althrd_setname(althrd_current(), "alsoft-record"); while(GetMessage(&msg, NULL, 0, 0)) { @@ -250,19 +247,15 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param) if(data->killNow) break; - WaveHdr = ((LPWAVEHDR)msg.lParam); - WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, WaveHdr->dwBytesRecorded/FrameSize); + WaveHdr = ((WAVEHDR*)msg.lParam); + WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, + WaveHdr->dwBytesRecorded/data->Format.nBlockAlign); // Send buffer back to capture more data waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - // Signal Wave Thread completed event - if(data->WaveThreadEvent) - SetEvent(data->WaveThreadEvent); - - ExitThread(0); return 0; } @@ -270,24 +263,26 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param) static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName) { WinMMData *data = NULL; - UINT DeviceID = 0; + const al_string *iter, *end; + UINT DeviceID; MMRESULT res; - ALuint i = 0; - if(!PlaybackDeviceList) + if(VECTOR_SIZE(PlaybackDevices) == 0) ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid - for(i = 0;i < NumPlaybackDevices;i++) + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) { - if(PlaybackDeviceList[i] && - (!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0)) + if(!al_string_empty(*iter) && + (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { - DeviceID = i; + DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices)); break; } } - if(i == NumPlaybackDevices) + if(iter == end) return ALC_INVALID_VALUE; data = calloc(1, sizeof(*data)); @@ -329,20 +324,10 @@ retry_open: goto failure; } - data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->WaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - - Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]); + al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); return ALC_NO_ERROR; failure: - if(data->WaveThreadEvent) - CloseHandle(data->WaveThreadEvent); - if(data->WaveHandle.Out) waveOutClose(data->WaveHandle.Out); @@ -356,9 +341,6 @@ static void WinMMClosePlayback(ALCdevice *device) WinMMData *data = (WinMMData*)device->ExtraData; // Close the Wave device - CloseHandle(data->WaveThreadEvent); - data->WaveThreadEvent = 0; - waveOutClose(data->WaveHandle.Out); data->WaveHandle.Out = 0; @@ -426,11 +408,11 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device) ALint BufferSize; ALuint i; - data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &data->WaveThreadID); - if(data->WaveThread == NULL) + data->killNow = AL_FALSE; + if(althrd_create(&data->thread, PlaybackThreadProc, device) != althrd_success) return ALC_FALSE; - data->WaveBuffersCommitted = 0; + InitRef(&data->WaveBuffersCommitted, 0); // Create 4 Buffers BufferSize = device->UpdateSize*device->NumUpdates / 4; @@ -441,12 +423,12 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device) { memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR)); data->WaveBuffer[i].dwBufferLength = BufferSize; - data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : + data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (data->WaveBuffer[i-1].lpData + data->WaveBuffer[i-1].dwBufferLength)); waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR)); waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } return ALC_TRUE; @@ -458,19 +440,12 @@ static void WinMMStopPlayback(ALCdevice *device) void *buffer = NULL; int i; - if(data->WaveThread == NULL) + if(data->killNow) return; // Set flag to stop processing headers data->killNow = AL_TRUE; - - // Wait for signal that Wave Thread has been destroyed - WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE); - - CloseHandle(data->WaveThread); - data->WaveThread = 0; - - data->killNow = AL_FALSE; + althrd_join(data->thread, &i); // Release the wave buffers for(i = 0;i < 4;i++) @@ -485,28 +460,31 @@ static void WinMMStopPlayback(ALCdevice *device) static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) { + const al_string *iter, *end; ALbyte *BufferData = NULL; DWORD CapturedDataSize; WinMMData *data = NULL; - UINT DeviceID = 0; ALint BufferSize; + UINT DeviceID; MMRESULT res; ALuint i; - if(!CaptureDeviceList) + if(VECTOR_SIZE(CaptureDevices) == 0) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid - for(i = 0;i < NumCaptureDevices;i++) + iter = VECTOR_ITER_BEGIN(CaptureDevices); + end = VECTOR_ITER_END(CaptureDevices); + for(;iter != end;iter++) { - if(CaptureDeviceList[i] && - (!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0)) + if(!al_string_empty(*iter) && + (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { - DeviceID = i; + DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices)); break; } } - if(i == NumCaptureDevices) + if(iter == end) return ALC_INVALID_VALUE; switch(Device->FmtChans) @@ -560,13 +538,6 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) goto failure; } - data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->WaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - // Allocate circular memory buffer for the captured audio CapturedDataSize = Device->UpdateSize*Device->NumUpdates; @@ -578,7 +549,7 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) if(!data->Ring) goto failure; - data->WaveBuffersCommitted = 0; + InitRef(&data->WaveBuffersCommitted, 0); // Create 4 Buffers of 50ms each BufferSize = data->Format.nAvgBytesPerSec / 20; @@ -592,27 +563,23 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) { memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR)); data->WaveBuffer[i].dwBufferLength = BufferSize; - data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : + data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (data->WaveBuffer[i-1].lpData + data->WaveBuffer[i-1].dwBufferLength)); data->WaveBuffer[i].dwFlags = 0; data->WaveBuffer[i].dwLoops = 0; waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)Device, 0, &data->WaveThreadID); - if (data->WaveThread == NULL) + if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success) goto failure; - Device->DeviceName = strdup(CaptureDeviceList[DeviceID]); + al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: - if(data->WaveThread) - CloseHandle(data->WaveThread); - if(BufferData) { for(i = 0;i < 4;i++) @@ -623,9 +590,6 @@ failure: if(data->Ring) DestroyRingBuffer(data->Ring); - if(data->WaveThreadEvent) - CloseHandle(data->WaveThreadEvent); - if(data->WaveHandle.In) waveInClose(data->WaveHandle.In); @@ -642,16 +606,13 @@ static void WinMMCloseCapture(ALCdevice *Device) /* Tell the processing thread to quit and wait for it to do so. */ data->killNow = AL_TRUE; - PostThreadMessage(data->WaveThreadID, WM_QUIT, 0, 0); + PostThreadMessage(data->thread, WM_QUIT, 0, 0); - WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE); + althrd_join(data->thread, &i); /* Make sure capture is stopped and all pending buffers are flushed. */ waveInReset(data->WaveHandle.In); - CloseHandle(data->WaveThread); - data->WaveThread = 0; - // Release the wave buffers for(i = 0;i < 4;i++) { @@ -665,9 +626,6 @@ static void WinMMCloseCapture(ALCdevice *Device) data->Ring = NULL; // Close the Wave device - CloseHandle(data->WaveThreadEvent); - data->WaveThreadEvent = 0; - waveInClose(data->WaveHandle.In); data->WaveHandle.In = 0; @@ -701,6 +659,17 @@ static ALCuint WinMMAvailableSamples(ALCdevice *Device) } +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)); +} + static const BackendFuncs WinMMFuncs = { WinMMOpenPlayback, WinMMClosePlayback, @@ -718,52 +687,34 @@ static const BackendFuncs WinMMFuncs = { ALCboolean alcWinMMInit(BackendFuncs *FuncList) { + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + *FuncList = WinMMFuncs; return ALC_TRUE; } void alcWinMMDeinit() { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) - free(PlaybackDeviceList[i]); - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - - NumPlaybackDevices = 0; - - - for(i = 0;i < NumCaptureDevices;i++) - free(CaptureDeviceList[i]); - free(CaptureDeviceList); - CaptureDeviceList = NULL; - - NumCaptureDevices = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); } void alcWinMMProbe(enum DevProbe type) { - ALuint i; - switch(type) { case ALL_DEVICE_PROBE: ProbePlaybackDevices(); - for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i]) - AppendAllDevicesList(PlaybackDeviceList[i]); - } + VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: ProbeCaptureDevices(); - for(i = 0;i < NumCaptureDevices;i++) - { - if(CaptureDeviceList[i]) - AppendCaptureDeviceList(CaptureDeviceList[i]); - } + VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2); break; } } |