From 2e2ff80567b4f64f5670330421421762a724b7c5 Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Tue, 29 May 2018 08:18:36 -0500 Subject: [PATCH] winmm: Return a continuous stream position in MIDI stream. Signed-off-by: Akihiro Sagawa Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/winmm/tests/midi.c | 8 ++++---- dlls/winmm/winmm.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/dlls/winmm/tests/midi.c b/dlls/winmm/tests/midi.c index c78e465782a..091a500db79 100644 --- a/dlls/winmm/tests/midi.c +++ b/dlls/winmm/tests/midi.c @@ -869,7 +869,7 @@ static void test_midiStream(UINT udev, HWND hwnd) expected = 50; ret = get_position(hm, TIME_MS); - todo_wine ok(ret >= expected && ret < expected + MARGIN, "expected %ums or greater, got %ums\n", expected, ret); + ok(ret >= expected && ret < expected + MARGIN, "expected %ums or greater, got %ums\n", expected, ret); expected = ret; Sleep(100); @@ -882,7 +882,7 @@ static void test_midiStream(UINT udev, HWND hwnd) Sleep(1); ret = get_position(hm, TIME_MS); - todo_wine ok(ret > expected && ret < expected + MARGIN, "expected greater than %ums, got %ums\n", expected, ret); + ok(ret > expected && ret < expected + MARGIN, "expected greater than %ums, got %ums\n", expected, ret); expected = ret; ret = WaitForSingleObject(records.done, INFINITE); @@ -893,7 +893,7 @@ static void test_midiStream(UINT udev, HWND hwnd) expected = 250; /* = 12 ticks in 120 BPM */ ret = get_position(hm, TIME_MS); - ok(ret >= expected - MARGIN && ret <= expected + MARGIN, + todo_wine ok(ret >= expected - MARGIN && ret <= expected + MARGIN, "expected greater than %ums, got %ums\n", expected, ret); trace("after playing, got %ums\n", ret); @@ -924,7 +924,7 @@ static void test_midiStream(UINT udev, HWND hwnd) ok(!rc, "midiStreamStop(dev=%d) rc=%s\n", udev, mmsys_error(rc)); ret = get_position(hm, TIME_MS); - todo_wine ok(ret == 0, "expected 0ms, got %ums\n", ret); + ok(ret == 0, "expected 0ms, got %ums\n", ret); rc = midiStreamClose(hm); ok(!rc, "midiStreamClose(dev=%d) rc=%s\n", udev, mmsys_error(rc)); diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 76807ab3c59..2031c79d1c7 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -918,6 +918,7 @@ typedef struct WINE_MIDIStream { DWORD dwPositionMS; DWORD dwPulses; DWORD dwStartTicks; + DWORD dwElapsedMS; WORD wFlags; WORD status; HANDLE hEvent; @@ -973,6 +974,20 @@ static DWORD MMSYSTEM_MidiStream_Convert(WINE_MIDIStream* lpMidiStrm, DWORD puls return ret; } +static DWORD midistream_get_playing_position(WINE_MIDIStream* lpMidiStrm) +{ + switch (lpMidiStrm->status) { + case MSM_STATUS_STOPPED: + case MSM_STATUS_PAUSED: + return lpMidiStrm->dwElapsedMS; + case MSM_STATUS_PLAYING: + return GetTickCount() - lpMidiStrm->dwStartTicks; + default: + FIXME("Unknown playing status %hu\n", lpMidiStrm->status); + return 0; + } +} + /************************************************************************** * MMSYSTEM_MidiStream_MessageHandler [internal] */ @@ -988,7 +1003,11 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI return FALSE; case WINE_MSM_STOP: TRACE("STOP\n"); + EnterCriticalSection(&lpMidiStrm->lock); lpMidiStrm->status = MSM_STATUS_STOPPED; + lpMidiStrm->dwPulses = 0; + lpMidiStrm->dwElapsedMS = 0; + LeaveCriticalSection(&lpMidiStrm->lock); /* this is not quite what MS doc says... */ midiOutReset(lpMidiStrm->hDevice); /* empty list of already submitted buffers */ @@ -1008,13 +1027,22 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI 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; + if (lpMidiStrm->status != MSM_STATUS_PLAYING) { + EnterCriticalSection(&lpMidiStrm->lock); + lpMidiStrm->dwStartTicks = GetTickCount() - lpMidiStrm->dwElapsedMS; + lpMidiStrm->status = MSM_STATUS_PLAYING; + LeaveCriticalSection(&lpMidiStrm->lock); + } 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; + if (lpMidiStrm->status != MSM_STATUS_PAUSED) { + EnterCriticalSection(&lpMidiStrm->lock); + lpMidiStrm->dwElapsedMS = GetTickCount() - lpMidiStrm->dwStartTicks; + lpMidiStrm->status = MSM_STATUS_PAUSED; + LeaveCriticalSection(&lpMidiStrm->lock); + } SetEvent((HANDLE)msg->wParam); break; /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent @@ -1302,6 +1330,7 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID, lpMidiStrm->dwTimeDiv = 24; /* ticks per quarter note */ lpMidiStrm->dwPositionMS = 0; lpMidiStrm->status = MSM_STATUS_PAUSED; + lpMidiStrm->dwElapsedMS = 0; mosm.dwStreamID = (DWORD)lpMidiStrm; /* FIXME: the correct value is not allocated yet for MAPPER */ @@ -1460,7 +1489,7 @@ MMRESULT WINAPI midiStreamPosition(HMIDISTRM hMidiStrm, LPMMTIME lpMMT, UINT cbm lpMMT->wType = TIME_MS; /* fall through to alternative format */ case TIME_MS: - lpMMT->u.ms = lpMidiStrm->dwPositionMS; + lpMMT->u.ms = midistream_get_playing_position(lpMidiStrm); TRACE("=> %d ms\n", lpMMT->u.ms); break; case TIME_TICKS: