aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends/winmm.c
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-06-10 05:30:02 +0200
committerSven Gothel <[email protected]>2014-06-10 05:30:02 +0200
commitf95bf4457fbc31112fa82dacbc1b7e094b9fd1cf (patch)
tree965ba5b8e6fc8e6bfe7a981c1dfb1179bb9adcde /Alc/backends/winmm.c
parent7297c3214a4c648aaee81a9877da15b88f798197 (diff)
parentc07fb7b45c1e345dbaa439882250de5b2213026f (diff)
Merge branch 'UPSTREAM' into UPSTREAM_MERGE
Diffstat (limited to 'Alc/backends/winmm.c')
-rw-r--r--Alc/backends/winmm.c333
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;
}
}