[PATCH 3/3] dsound: For capture, use MMDevAPI event API instead of timers
Andrew Eikum
aeikum at codeweavers.com
Wed Aug 21 10:16:08 CDT 2013
---
dlls/dsound/capture.c | 98 +++++++++++++++++++++++++++++++-------------
dlls/dsound/dsound.c | 24 -----------
dlls/dsound/dsound_private.h | 1 -
3 files changed, 70 insertions(+), 53 deletions(-)
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c
index 63bda55..40f1702 100644
--- a/dlls/dsound/capture.c
+++ b/dlls/dsound/capture.c
@@ -59,6 +59,8 @@ typedef struct IDirectSoundCaptureBufferImpl
/* IDirectSoundNotify fields */
DSBPOSITIONNOTIFY *notifies;
int nrofnotifies;
+ HANDLE thread;
+ HANDLE sleepev;
} IDirectSoundCaptureBufferImpl;
/* DirectSoundCaptureDevice implementation structure */
@@ -72,7 +74,6 @@ struct DirectSoundCaptureDevice
WAVEFORMATEX *pwfx;
IDirectSoundCaptureBufferImpl *capture_buffer;
DWORD state;
- UINT timerID;
CRITICAL_SECTION lock;
IMMDevice *mmdevice;
IAudioClient *client;
@@ -80,12 +81,20 @@ struct DirectSoundCaptureDevice
struct list entry;
};
+static DWORD WINAPI DSOUND_capture_thread(void *user);
static void capturebuffer_destroy(IDirectSoundCaptureBufferImpl *This)
{
if (This->device->state == STATE_CAPTURING)
This->device->state = STATE_STOPPING;
+ if(This->thread){
+ SetEvent(This->sleepev);
+ WaitForSingleObject(This->thread, INFINITE);
+ CloseHandle(This->thread);
+ }
+ CloseHandle(This->sleepev);
+
HeapFree(GetProcessHeap(),0, This->pdscbd);
if (This->device->client) {
@@ -739,8 +748,8 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
}
err = IAudioClient_Initialize(device->client,
- AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST,
- 200 * 100000, 50000, device->pwfx, NULL);
+ AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ 200 * 100000, 0, device->pwfx, NULL);
if(FAILED(err)){
WARN("Initialize failed: %08x\n", err);
IAudioClient_Release(device->client);
@@ -753,12 +762,27 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
return err;
}
+ This->sleepev = CreateEventW(NULL, 0, 0, NULL);
+
+ err = IAudioClient_SetEventHandle(device->client, This->sleepev);
+ if(FAILED(err)){
+ WARN("SetEventHandle failed: %08x\n", err);
+ IAudioClient_Release(device->client);
+ device->client = NULL;
+ CloseHandle(This->sleepev);
+ HeapFree(GetProcessHeap(), 0, This->pdscbd);
+ This->device->capture_buffer = 0;
+ HeapFree( GetProcessHeap(), 0, This );
+ return err;
+ }
+
err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
(void**)&device->capture);
if(FAILED(err)){
WARN("GetService failed: %08x\n", err);
IAudioClient_Release(device->client);
device->client = NULL;
+ CloseHandle(This->sleepev);
HeapFree(GetProcessHeap(), 0, This->pdscbd);
This->device->capture_buffer = 0;
HeapFree( GetProcessHeap(), 0, This );
@@ -776,6 +800,7 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
device->client = NULL;
IAudioCaptureClient_Release(device->capture);
device->capture = NULL;
+ CloseHandle(This->sleepev);
HeapFree(GetProcessHeap(), 0, This->pdscbd);
This->device->capture_buffer = 0;
HeapFree( GetProcessHeap(), 0, This );
@@ -783,6 +808,7 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create(
}
device->buffer = newbuf;
device->buflen = buflen;
+ This->thread = CreateThread(NULL, 0, DSOUND_capture_thread, This, 0, NULL);
}
IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface);
@@ -830,9 +856,6 @@ static ULONG DirectSoundCaptureDevice_Release(
if (!ref) {
TRACE("deleting object\n");
- timeKillEvent(device->timerID);
- timeEndPeriod(DS_TIME_RES);
-
EnterCriticalSection(&DSOUND_capturers_lock);
list_remove(&device->entry);
LeaveCriticalSection(&DSOUND_capturers_lock);
@@ -851,29 +874,19 @@ static ULONG DirectSoundCaptureDevice_Release(
return ref;
}
-static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user,
- DWORD_PTR dw1, DWORD_PTR dw2)
+static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device)
{
- DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user;
+ HRESULT hr;
UINT32 packet_frames, packet_bytes, avail_bytes, skip_bytes = 0;
DWORD flags;
BYTE *buf;
- HRESULT hr;
- if(!device->ref)
- return;
-
- EnterCriticalSection(&device->lock);
-
- if(!device->capture_buffer || device->state == STATE_STOPPED){
- LeaveCriticalSection(&device->lock);
- return;
- }
+ if(!device->capture_buffer || device->state == STATE_STOPPED)
+ return S_FALSE;
if(device->state == STATE_STOPPING){
device->state = STATE_STOPPED;
- LeaveCriticalSection(&device->lock);
- return;
+ return S_FALSE;
}
if(device->state == STATE_STARTING)
@@ -882,9 +895,8 @@ static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user
hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames,
&flags, NULL, NULL);
if(FAILED(hr)){
- LeaveCriticalSection(&device->lock);
WARN("GetBuffer failed: %08x\n", hr);
- return;
+ return hr;
}
packet_bytes = packet_frames * device->pwfx->nBlockAlign;
@@ -917,12 +929,44 @@ static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user
hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames);
if(FAILED(hr)){
- LeaveCriticalSection(&device->lock);
WARN("ReleaseBuffer failed: %08x\n", hr);
- return;
+ return hr;
}
- LeaveCriticalSection(&device->lock);
+ return S_OK;
+}
+
+static DWORD WINAPI DSOUND_capture_thread(void *user)
+{
+ IDirectSoundCaptureBufferImpl *buffer = user;
+ HRESULT hr;
+ DWORD ret, wait_ms;
+ REFERENCE_TIME period;
+
+ hr = IAudioClient_GetDevicePeriod(buffer->device->client, &period, NULL);
+ if(FAILED(hr)){
+ WARN("GetDevicePeriod failed: %08x\n", hr);
+ wait_ms = 5;
+ }else
+ wait_ms = MulDiv(5, period, 10000);
+
+ while(buffer->ref){
+ ret = WaitForSingleObject(buffer->sleepev, wait_ms);
+
+ if(!buffer->device->ref)
+ break;
+
+ if(ret == WAIT_OBJECT_0){
+ EnterCriticalSection(&buffer->device->lock);
+
+ DSOUND_capture_data(buffer->device);
+
+ LeaveCriticalSection(&buffer->device->lock);
+ }else if(ret != WAIT_TIMEOUT)
+ WARN("WaitForSingleObject failed: %u\n", GetLastError());
+ }
+
+ return 0;
}
static struct _TestFormat {
@@ -1020,8 +1064,6 @@ static HRESULT DirectSoundCaptureDevice_Initialize(
}
IAudioClient_Release(client);
- device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device);
-
list_add_tail(&DSOUND_capturers, &device->entry);
*ppDevice = device;
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 381d0e1..986168b 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -735,30 +735,6 @@ BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
return hr == S_OK;
}
-UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user)
-{
- UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
- TIMECAPS time;
-
- timeGetDevCaps(&time, sizeof(TIMECAPS));
- TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
- if (triggertime < time.wPeriodMin)
- triggertime = time.wPeriodMin;
- if (res < time.wPeriodMin)
- res = time.wPeriodMin;
- if (timeBeginPeriod(res) == TIMERR_NOCANDO)
- WARN("Could not set minimum resolution, don't expect sound\n");
- id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
- if (!id)
- {
- WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
- id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC);
- if (!id)
- ERR("Could not create timer, sound playback will not occur\n");
- }
- return id;
-}
-
HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
{
HRESULT hr = DS_OK;
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 1a3900c..a8f5f42 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -261,6 +261,5 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) DECLSP
BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
DWORD depth, WORD channels) DECLSPEC_HIDDEN;
-UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user) DECLSPEC_HIDDEN;
HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids,
LPDSENUMCALLBACKW cb, void *user) DECLSPEC_HIDDEN;
--
1.8.3.4
More information about the wine-patches
mailing list