[PATCH 1/5] midimap: Handle MIDI running status.

Andrew Eikum aeikum at codeweavers.com
Thu May 26 11:17:34 CDT 2022


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Thu, May 26, 2022 at 11:38:43PM +0900, Akihiro Sagawa wrote:
> 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>
> ---
>  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-devel mailing list