Some games may not receive the DSBPN_OFFSETSTOP event and get stuck if CloseHandle is called immediately after IDirectSoundBuffer::Stop. To solve this problem, DSBPN_OFFSETSTOP is notified early in the STATE_STOPPING state instead of STATE_STOPPED.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41292 Signed-off-by: Hiroki Awata castaneai@by.black --- dlls/dsound/buffer.c | 3 +++ dlls/dsound/mixer.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index fafa6fc6015..7e2773b14d4 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -318,7 +318,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface) AcquireSRWLockExclusive(&This->lock);
if (This->state == STATE_PLAYING) + { This->state = STATE_STOPPING; + DSOUND_CheckEvent(This, 0, 0); + } else if (This->state == STATE_STARTING) { This->state = STATE_STOPPED; diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index a6402b09eff..3eb682ef7b8 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -213,8 +213,8 @@ void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len if(dsb->nrofnotifies == 0) return;
- if(dsb->state == STATE_STOPPED){ - TRACE("Stopped...\n"); + if(dsb->state == STATE_STOPPING){ + TRACE("Stopping...\n"); /* DSBPN_OFFSETSTOP notifies are always at the start of the sorted array */ for(left = 0; left < dsb->nrofnotifies; ++left){ if(dsb->notifies[left].dwOffset != DSBPN_OFFSETSTOP) @@ -225,6 +225,10 @@ void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len } return; } + if(dsb->state == STATE_STOPPED){ + TRACE("Stopped...\n"); + return; + }
for(first = 0; first < dsb->nrofnotifies && dsb->notifies[first].dwOffset == DSBPN_OFFSETSTOP; ++first) ;