[PATCH 2/3] mmdevapi: Don't stop sending event signals after IAudioClient::Stop

Andrew Eikum aeikum at codeweavers.com
Fri Jun 27 11:04:23 CDT 2014


---
 dlls/mmdevapi/tests/capture.c     |  6 +++---
 dlls/mmdevapi/tests/render.c      |  6 +++---
 dlls/winealsa.drv/mmdevdrv.c      | 40 +++++++++++++++++++--------------------
 dlls/winecoreaudio.drv/mmdevdrv.c | 27 +++++++++++---------------
 dlls/wineoss.drv/mmdevdrv.c       | 34 +++++++++++++++++----------------
 5 files changed, 54 insertions(+), 59 deletions(-)

diff --git a/dlls/mmdevapi/tests/capture.c b/dlls/mmdevapi/tests/capture.c
index e84fb26..23075ea 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 91ed029..44472a6 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 7d41110..a4c02bf 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 626add1..7d8f4a0 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 922cbb0..ce95138 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;
 }
 
-- 
2.0.0





More information about the wine-patches mailing list