mmdevapi: Don't stop sending event signals after IAudioClient::Stop.
This commit is contained in:
parent
d5b597fee5
commit
b950b9a835
|
@ -424,7 +424,7 @@ static void test_capture(IAudioClient *ac, HANDLE handle, WAVEFORMATEX *wfx)
|
||||||
|
|
||||||
/* Still receiving events! */
|
/* Still receiving events! */
|
||||||
r = WaitForSingleObject(handle, 20);
|
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);
|
hr = IAudioClient_Reset(ac);
|
||||||
ok(hr == S_OK, "Reset failed: %08x\n", hr);
|
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");
|
ok(ResetEvent(handle), "ResetEvent\n");
|
||||||
|
|
||||||
r = WaitForSingleObject(handle, 120);
|
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);
|
hr = IAudioClient_SetEventHandle(ac, NULL);
|
||||||
ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
|
ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
|
||||||
|
|
||||||
r = WaitForSingleObject(handle, 70);
|
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);
|
hr = IAudioClient_Start(ac);
|
||||||
ok(hr == S_OK, "Start failed: %08x\n", hr);
|
ok(hr == S_OK, "Start failed: %08x\n", hr);
|
||||||
|
|
|
@ -651,7 +651,7 @@ static void test_event(void)
|
||||||
|
|
||||||
/* Still receiving events! */
|
/* Still receiving events! */
|
||||||
r = WaitForSingleObject(event, 20);
|
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);
|
hr = IAudioClient_Reset(ac);
|
||||||
ok(hr == S_OK, "Reset failed: %08x\n", hr);
|
ok(hr == S_OK, "Reset failed: %08x\n", hr);
|
||||||
|
@ -659,13 +659,13 @@ static void test_event(void)
|
||||||
ok(ResetEvent(event), "ResetEvent\n");
|
ok(ResetEvent(event), "ResetEvent\n");
|
||||||
|
|
||||||
r = WaitForSingleObject(event, 120);
|
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);
|
hr = IAudioClient_SetEventHandle(ac, NULL);
|
||||||
ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
|
ok(hr == E_INVALIDARG, "SetEventHandle(NULL) returns %08x\n", hr);
|
||||||
|
|
||||||
r = WaitForSingleObject(event, 70);
|
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 */
|
/* test releasing a playing stream */
|
||||||
hr = IAudioClient_Start(ac);
|
hr = IAudioClient_Start(ac);
|
||||||
|
|
|
@ -889,9 +889,21 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
|
||||||
{
|
{
|
||||||
ACImpl *This = impl_from_IAudioClient(iface);
|
ACImpl *This = impl_from_IAudioClient(iface);
|
||||||
ULONG ref;
|
ULONG ref;
|
||||||
|
|
||||||
ref = InterlockedDecrement(&This->ref);
|
ref = InterlockedDecrement(&This->ref);
|
||||||
TRACE("(%p) Refcount now %u\n", This, ref);
|
TRACE("(%p) Refcount now %u\n", This, ref);
|
||||||
if(!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);
|
IAudioClient_Stop(iface);
|
||||||
IMMDevice_Release(This->parent);
|
IMMDevice_Release(This->parent);
|
||||||
IUnknown_Release(This->pUnkFTMarshal);
|
IUnknown_Release(This->pUnkFTMarshal);
|
||||||
|
@ -2191,12 +2203,14 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||||
This->bufsize_frames);
|
This->bufsize_frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!This->timer){
|
||||||
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
|
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, alsa_push_buffer_data,
|
||||||
This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
|
This, 0, This->mmdev_period_rt / 10000, WT_EXECUTEINTIMERTHREAD)){
|
||||||
LeaveCriticalSection(&This->lock);
|
LeaveCriticalSection(&This->lock);
|
||||||
WARN("Unable to create timer: %u\n", GetLastError());
|
WARN("Unable to create timer: %u\n", GetLastError());
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
This->started = TRUE;
|
This->started = TRUE;
|
||||||
|
|
||||||
|
@ -2208,8 +2222,6 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||||
static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
{
|
{
|
||||||
ACImpl *This = impl_from_IAudioClient(iface);
|
ACImpl *This = impl_from_IAudioClient(iface);
|
||||||
HANDLE event;
|
|
||||||
BOOL wait;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
@ -2225,24 +2237,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
return S_FALSE;
|
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;
|
This->started = FALSE;
|
||||||
|
|
||||||
LeaveCriticalSection(&This->lock);
|
LeaveCriticalSection(&This->lock);
|
||||||
|
|
||||||
if(event && wait)
|
|
||||||
WaitForSingleObject(event, INFINITE);
|
|
||||||
CloseHandle(event);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -827,6 +827,16 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
|
||||||
ref = InterlockedDecrement(&This->ref);
|
ref = InterlockedDecrement(&This->ref);
|
||||||
TRACE("(%p) Refcount now %u\n", This, ref);
|
TRACE("(%p) Refcount now %u\n", This, ref);
|
||||||
if(!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){
|
if(This->aqueue){
|
||||||
AQBuffer *buf, *next;
|
AQBuffer *buf, *next;
|
||||||
QueuedBufInfo *bufinfo, *bufinfo2;
|
QueuedBufInfo *bufinfo, *bufinfo2;
|
||||||
|
@ -1706,7 +1716,7 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||||
return AUDCLNT_E_EVENTHANDLE_NOT_SET;
|
return AUDCLNT_E_EVENTHANDLE_NOT_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(This->event)
|
if(This->event && !This->timer)
|
||||||
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb,
|
if(!CreateTimerQueueTimer(&This->timer, g_timer_q, ca_period_cb,
|
||||||
This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){
|
This, 0, This->period_ms, WT_EXECUTEINTIMERTHREAD)){
|
||||||
This->timer = NULL;
|
This->timer = NULL;
|
||||||
|
@ -1739,8 +1749,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
ACImpl *This = impl_from_IAudioClient(iface);
|
ACImpl *This = impl_from_IAudioClient(iface);
|
||||||
AudioTimeStamp tstamp;
|
AudioTimeStamp tstamp;
|
||||||
OSStatus sc;
|
OSStatus sc;
|
||||||
HANDLE event = NULL;
|
|
||||||
BOOL wait = FALSE;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
@ -1761,15 +1769,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
return S_OK;
|
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;
|
This->playing = StateInTransition;
|
||||||
|
|
||||||
sc = AudioQueueGetCurrentTime(This->aqueue, NULL, &tstamp, NULL);
|
sc = AudioQueueGetCurrentTime(This->aqueue, NULL, &tstamp, NULL);
|
||||||
|
@ -1794,10 +1793,6 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
|
|
||||||
OSSpinLockUnlock(&This->lock);
|
OSSpinLockUnlock(&This->lock);
|
||||||
|
|
||||||
if(event && wait)
|
|
||||||
WaitForSingleObject(event, INFINITE);
|
|
||||||
CloseHandle(event);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -712,9 +712,21 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface)
|
||||||
{
|
{
|
||||||
ACImpl *This = impl_from_IAudioClient(iface);
|
ACImpl *This = impl_from_IAudioClient(iface);
|
||||||
ULONG ref;
|
ULONG ref;
|
||||||
|
|
||||||
ref = InterlockedDecrement(&This->ref);
|
ref = InterlockedDecrement(&This->ref);
|
||||||
TRACE("(%p) Refcount now %u\n", This, ref);
|
TRACE("(%p) Refcount now %u\n", This, ref);
|
||||||
if(!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);
|
IAudioClient_Stop(iface);
|
||||||
IMMDevice_Release(This->parent);
|
IMMDevice_Release(This->parent);
|
||||||
IUnknown_Release(This->pUnkFTMarshal);
|
IUnknown_Release(This->pUnkFTMarshal);
|
||||||
|
@ -1542,10 +1554,12 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||||
return AUDCLNT_E_NOT_STOPPED;
|
return AUDCLNT_E_NOT_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!This->timer){
|
||||||
if(!CreateTimerQueueTimer(&This->timer, g_timer_q,
|
if(!CreateTimerQueueTimer(&This->timer, g_timer_q,
|
||||||
oss_period_callback, This, 0, This->period_us / 1000,
|
oss_period_callback, This, 0, This->period_us / 1000,
|
||||||
WT_EXECUTEINTIMERTHREAD))
|
WT_EXECUTEINTIMERTHREAD))
|
||||||
ERR("Unable to create period timer: %u\n", GetLastError());
|
ERR("Unable to create period timer: %u\n", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
This->playing = TRUE;
|
This->playing = TRUE;
|
||||||
|
|
||||||
|
@ -1557,8 +1571,6 @@ static HRESULT WINAPI AudioClient_Start(IAudioClient *iface)
|
||||||
static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
{
|
{
|
||||||
ACImpl *This = impl_from_IAudioClient(iface);
|
ACImpl *This = impl_from_IAudioClient(iface);
|
||||||
HANDLE event;
|
|
||||||
DWORD wait;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
@ -1574,20 +1586,10 @@ static HRESULT WINAPI AudioClient_Stop(IAudioClient *iface)
|
||||||
return S_FALSE;
|
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;
|
This->playing = FALSE;
|
||||||
|
|
||||||
LeaveCriticalSection(&This->lock);
|
LeaveCriticalSection(&This->lock);
|
||||||
|
|
||||||
if(event && wait)
|
|
||||||
WaitForSingleObject(event, INFINITE);
|
|
||||||
CloseHandle(event);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue