diff --git a/dlls/mmdevapi/tests/capture.c b/dlls/mmdevapi/tests/capture.c index e84fb2636e0..23075ea633e 100644 --- a/dlls/mmdevapi/tests/capture.c +++ b/dlls/mmdevapi/tests/capture.c @@ -424,7 +424,7 @@ static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx) /* Still receiving events! */ r = WaitForSingleObject(handle, 20); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r); hr = IAudioClient_Reset(ac); ok(hr == S_OK, "Reset failed: %08x\n", hr); @@ -432,13 +432,13 @@ static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx) ok(ResetEvent(handle), "ResetEvent\n"); r = WaitForSingleObject(handle, 120); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r); hr = IAudioClient_SetEventHandle(ac, NULL); ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr); r = WaitForSingleObject(handle, 70); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r); hr = IAudioClient_Start(ac); ok(hr == S_OK, "Start failed: %08x\n", hr); diff --git a/dlls/mmdevapi/tests/render.c b/dlls/mmdevapi/tests/render.c index 91ed0293a74..44472a691de 100644 --- a/dlls/mmdevapi/tests/render.c +++ b/dlls/mmdevapi/tests/render.c @@ -651,7 +651,7 @@ static void test_event(void) /* Still receiving events! */ r = WaitForSingleObject(event, 20); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(event) after Stop gave %x\n", r); hr = IAudioClient_Reset(ac); ok(hr == S_OK, "Reset failed: %08x\n", hr); @@ -659,13 +659,13 @@ static void test_event(void) ok(ResetEvent(event), "ResetEvent\n"); r = WaitForSingleObject(event, 120); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(event) after Reset gave %x\n", r); hr = IAudioClient_SetEventHandle(ac, NULL); ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr); r = WaitForSingleObject(event, 70); - todo_wine ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r); + ok(r == WAIT_OBJECT_0, "Wait(NULL event) gave %x\n", r); /* test releasing a playing stream */ hr = IAudioClient_Start(ac); diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 7d41110be2d..a4c02bf1ae2 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -889,9 +889,21 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface) { ACImpl *This = impl_from_IAudioClient(iface); ULONG ref; + ref = InterlockedDecrement(&This->ref); TRACE("(%p) Refcount now %u\n", This, ref); if(!ref){ + if(This->timer){ + HANDLE event; + DWORD wait; + event = CreateEventW(NULL, TRUE, FALSE, NULL); + wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); + wait = wait && GetLastError() == ERROR_IO_PENDING; + if(event && wait) + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } + IAudioClient_Stop(iface); IMMDevice_Release(This->parent); IUnknown_Release(This->pUnkFTMarshal); @@ -2191,11 +2203,13 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) This->bufsize_frames); } - if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data, - This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){ - LeaveCriticalSection(&This->lock); - WARN("Unable to create timer: %u\n", GetLastError()); - return E_OUTOFMEMORY; + if(!This->timer){ + if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data, + This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){ + LeaveCriticalSection(&This->lock); + WARN("Unable to create timer: %u\n", GetLastError()); + return E_OUTOFMEMORY; + } } This->started = TRUE; @@ -2208,8 +2222,6 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) { ACImpl *This = impl_from_IAudioClient(iface); - HANDLE event; - BOOL wait; TRACE("(%p)\n", This); @@ -2225,24 +2237,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) return S_FALSE; } - /* Stop without losing written frames or position. - * snd_pcm_pause would be appropriate but is unsupported by dmix. - * snd_pcm_drain yields EAGAIN in NONBLOCK mode, except with Pulse. */ - - event = CreateEventW(NULL, TRUE, FALSE, NULL); - wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); - if(wait) - WARN("DeleteTimerQueueTimer error %u\n", GetLastError()); - wait = wait && GetLastError() == ERROR_IO_PENDING; - This->started = FALSE; LeaveCriticalSection(&This->lock); - if(event && wait) - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - return S_OK; } diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c index 626add1d6dd..7d8f4a0f13d 100644 --- a/dlls/winecoreaudio.drv/mmdevdrv.c +++ b/dlls/winecoreaudio.drv/mmdevdrv.c @@ -827,6 +827,16 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface) ref = InterlockedDecrement(&This->ref); TRACE("(%p) Refcount now %u\n", This, ref); if(!ref){ + if(This->timer){ + HANDLE event; + BOOL wait; + event = CreateEventW(NULL, TRUE, FALSE, NULL); + wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); + wait = wait && GetLastError() == ERROR_IO_PENDING; + if(event && wait) + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } if(This->aqueue){ AQBuffer *buf, *next; QueuedBufInfo *bufinfo, *bufinfo2; @@ -1706,7 +1716,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) return AUDCLNT_E_EVENTHANDLE_NOT_SET; } - if(This->event) + if(This->event && !This->timer) if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb, This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){ This->timer = NULL; @@ -1739,8 +1749,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) ACImpl *This = impl_from_IAudioClient(iface); AudioTimeStamp tstamp; OSStatus sc; - HANDLE event = NULL; - BOOL wait = FALSE; TRACE("(%p)\n", This); @@ -1761,15 +1769,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) return S_OK; } - if(This->timer){ - event = CreateEventW(NULL, TRUE, FALSE, NULL); - wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); - This->timer = NULL; - if(wait) - WARN("DeleteTimerQueueTimer error %u\n", GetLastError()); - wait = wait && GetLastError() == ERROR_IO_PENDING; - } - This->playing = StateInTransition; sc = AudioQueueGetCurrentTime(This->aqueue, NULL, &tstamp, NULL); @@ -1794,10 +1793,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) OSSpinLockUnlock(&This->lock); - if(event && wait) - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - return S_OK; } diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 922cbb0413b..ce95138c334 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -712,9 +712,21 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface) { ACImpl *This = impl_from_IAudioClient(iface); ULONG ref; + ref = InterlockedDecrement(&This->ref); TRACE("(%p) Refcount now %u\n", This, ref); if(!ref){ + if(This->timer){ + HANDLE event; + DWORD wait; + event = CreateEventW(NULL, TRUE, FALSE, NULL); + wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); + wait = wait && GetLastError() == ERROR_IO_PENDING; + if(event && wait) + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } + IAudioClient_Stop(iface); IMMDevice_Release(This->parent); IUnknown_Release(This->pUnkFTMarshal); @@ -1542,10 +1554,12 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) return AUDCLNT_E_NOT_STOPPED; } - if(!CreateTimerQueueTimer(&This->timer, g_timer_q, - oss_period_callback, This, 0, This->period_us / 1000, - WT_EXECUTEINTIMERTHREAD)) - ERR("Unable to create period timer: %u\n", GetLastError()); + if(!This->timer){ + if(!CreateTimerQueueTimer(&This->timer, g_timer_q, + oss_period_callback, This, 0, This->period_us / 1000, + WT_EXECUTEINTIMERTHREAD)) + ERR("Unable to create period timer: %u\n", GetLastError()); + } This->playing = TRUE; @@ -1557,8 +1571,6 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface) static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) { ACImpl *This = impl_from_IAudioClient(iface); - HANDLE event; - DWORD wait; TRACE("(%p)\n", This); @@ -1574,20 +1586,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface) return S_FALSE; } - event = CreateEventW(NULL, TRUE, FALSE, NULL); - wait = !DeleteTimerQueueTimer(g_timer_q, This->timer, event); - if(wait) - WARN("DeleteTimerQueueTimer error %u\n", GetLastError()); - wait = wait && GetLastError() == ERROR_IO_PENDING; - This->playing = FALSE; LeaveCriticalSection(&This->lock); - if(event && wait) - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - return S_OK; }