From: Akihiro Sagawa sagawa.aki@gmail.com
Signed-off-by: Akihiro Sagawa sagawa.aki@gmail.com Signed-off-by: Andrew Eikum aeikum@codeweavers.com ---
v3: Fix leak, small code style changes.
In v2, use an anoymous event object to avoid a race.
dlls/winmm/winmm.c | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index da87be2feb..76807ab3c5 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -1004,15 +1004,18 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI (HDRVR)lpMidiStrm->hDevice, MM_MOM_DONE, lpwm->mod.dwInstance, (DWORD_PTR)lphdr, 0); } + SetEvent((HANDLE)msg->wParam); return TRUE; case WINE_MSM_RESUME: /* FIXME: send out cc64 0 (turn off sustain pedal) on every channel */ lpMidiStrm->dwStartTicks = GetTickCount() - lpMidiStrm->dwPositionMS; lpMidiStrm->status = MSM_STATUS_PLAYING; + SetEvent((HANDLE)msg->wParam); return TRUE; case WINE_MSM_PAUSE: /* FIXME: send out cc64 0 (turn off sustain pedal) on every channel */ lpMidiStrm->status = MSM_STATUS_PAUSED; + SetEvent((HANDLE)msg->wParam); break; /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent * by native mcimidi, it doesn't look like a correct one". @@ -1387,20 +1390,49 @@ MMRESULT WINAPI midiStreamOut(HMIDISTRM hMidiStrm, LPMIDIHDR lpMidiHdr, return ret; }
+static MMRESULT midistream_post_message_and_wait(WINE_MIDIStream* lpMidiStrm, UINT msg, LPARAM lParam) +{ + HANDLE hObjects[2]; + + hObjects[0] = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!hObjects[0]) + return MMSYSERR_ERROR; + + if (!PostThreadMessageA(lpMidiStrm->dwThreadID, msg, (WPARAM)hObjects[0], lParam)) { + WARN("bad PostThreadMessage\n"); + CloseHandle(hObjects[0]); + return MMSYSERR_ERROR; + } + + if (GetCurrentThreadId() != lpMidiStrm->dwThreadID) { + DWORD ret; + hObjects[1] = lpMidiStrm->hThread; + ret = WaitForMultipleObjects(sizeof(hObjects)/sizeof(hObjects[0]), hObjects, + FALSE, INFINITE); + if (ret != WAIT_OBJECT_0) { + CloseHandle(hObjects[0]); + WARN("bad WaitForSingleObject (%u)\n", ret); + return MMSYSERR_ERROR; + } + } + + CloseHandle(hObjects[0]); + + return MMSYSERR_NOERROR; +} + /************************************************************************** * midiStreamPause [WINMM.@] */ MMRESULT WINAPI midiStreamPause(HMIDISTRM hMidiStrm) { WINE_MIDIStream* lpMidiStrm; - DWORD ret = MMSYSERR_NOERROR;
TRACE("(%p)!\n", hMidiStrm);
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) return MMSYSERR_INVALHANDLE; - PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_PAUSE, 0, 0); - return ret; + return midistream_post_message_and_wait(lpMidiStrm, WINE_MSM_PAUSE, 0); }
/************************************************************************** @@ -1496,14 +1528,12 @@ MMRESULT WINAPI midiStreamProperty(HMIDISTRM hMidiStrm, LPBYTE lpPropData, DWORD MMRESULT WINAPI midiStreamRestart(HMIDISTRM hMidiStrm) { WINE_MIDIStream* lpMidiStrm; - MMRESULT ret = MMSYSERR_NOERROR;
TRACE("(%p)!\n", hMidiStrm);
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) return MMSYSERR_INVALHANDLE; - PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_RESUME, 0, 0); - return ret; + return midistream_post_message_and_wait(lpMidiStrm, WINE_MSM_RESUME, 0); }
/************************************************************************** @@ -1512,14 +1542,12 @@ MMRESULT WINAPI midiStreamRestart(HMIDISTRM hMidiStrm) MMRESULT WINAPI midiStreamStop(HMIDISTRM hMidiStrm) { WINE_MIDIStream* lpMidiStrm; - MMRESULT ret = MMSYSERR_NOERROR;
TRACE("(%p)!\n", hMidiStrm);
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) return MMSYSERR_INVALHANDLE; - PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_STOP, 0, 0); - return ret; + return midistream_post_message_and_wait(lpMidiStrm, WINE_MSM_STOP, 0); }
struct mm_starter