From 4c535a7f7546f2dfe504c47dfc416d3cdd0a5ab0 Mon Sep 17 00:00:00 2001 From: Akihiro Sagawa Date: Thu, 26 May 2022 23:38:43 +0900 Subject: [PATCH] midimap: Handle MIDI running status. Wine's midiOutShortMsg() can't handle the MIDI message if the status byte is omitted. Omitting status byte is valid and called "running status". Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53003 Signed-off-by: Akihiro Sagawa Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/midimap/midimap.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/dlls/midimap/midimap.c b/dlls/midimap/midimap.c index 12555f5309a..e04fe721364 100644 --- a/dlls/midimap/midimap.c +++ b/dlls/midimap/midimap.c @@ -101,6 +101,7 @@ typedef struct tagMIDIMAPDATA struct tagMIDIMAPDATA* self; MIDIOUTPORT* ChannelMap[16]; MIDIOPENDESC midiDesc; + BYTE runningStatus; WORD wCbFlags; } MIDIMAPDATA; @@ -301,6 +302,7 @@ static DWORD modOpen(DWORD_PTR *lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags) mom->self = mom; mom->wCbFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); mom->midiDesc = *lpDesc; + mom->runningStatus = 0; for (chn = 0; chn < 16; chn++) { @@ -380,6 +382,7 @@ static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD_PTR dwPara if (ret != MMSYSERR_NOERROR) break; } } + mom->runningStatus = 0; lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; lpMidiHdr->dwFlags |= MHDR_DONE; MIDIMAP_NotifyClient(mom, MOM_DONE, (DWORD_PTR)lpMidiHdr, 0L); @@ -388,16 +391,31 @@ static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD_PTR dwPara static DWORD modData(MIDIMAPDATA* mom, DWORD_PTR dwParam) { - BYTE lb = LOBYTE(LOWORD(dwParam)); - WORD chn = lb & 0x0F; + BYTE status = LOBYTE(LOWORD(dwParam)); + WORD chn; DWORD ret = MMSYSERR_NOERROR; if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR; + if (status < 0x80) + { + if (mom->runningStatus) + { + status = mom->runningStatus; + dwParam = ((LOWORD(dwParam) << 8) | status); + } + else + { + FIXME("ooch %Ix\n", dwParam); + return MMSYSERR_NOERROR; + } + } + chn = status & 0x0F; + if (!mom->ChannelMap[chn]) return MMSYSERR_NOERROR; - switch (lb & 0xF0) + switch (status & 0xF0) { case 0x80: case 0x90: @@ -423,6 +441,7 @@ static DWORD modData(MIDIMAPDATA* mom, DWORD_PTR dwParam) } ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam); } + mom->runningStatus = status; break; case 0xF0: for (chn = 0; chn < 16; chn++) @@ -430,6 +449,9 @@ static DWORD modData(MIDIMAPDATA* mom, DWORD_PTR dwParam) if (mom->ChannelMap[chn]->loaded > 0) ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam); } + /* system common message */ + if (status <= 0xF7) + mom->runningStatus = 0; break; default: FIXME("ooch %Ix\n", dwParam); @@ -511,6 +533,8 @@ static DWORD modReset(MIDIMAPDATA* mom) if (ret != MMSYSERR_NOERROR) break; } } + mom->runningStatus = 0; + return ret; } -- 2.11.4.GIT