Akihiro Sagawa : midimap: Handle MIDI running status.

Alexandre Julliard julliard at winehq.org
Thu May 26 15:46:27 CDT 2022


Module: wine
Branch: master
Commit: 4c535a7f7546f2dfe504c47dfc416d3cdd0a5ab0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4c535a7f7546f2dfe504c47dfc416d3cdd0a5ab0

Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date:   Thu May 26 23:38:43 2022 +0900

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 <sagawa.aki at gmail.com>
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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;
 }
 




More information about the wine-cvs mailing list