[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-2d-dev
Subject:    Re: RFR: 8074211: javax.sound.midi: Error with send System Exclusive messages of different length [v
From:       Phil Race <prr () openjdk ! org>
Date:       2023-10-30 21:32:31
Message-ID: QdTUrHyFcxWL5K7HTemAPhM1tr4PYNaFjGUDK2pa5Iw=.209644ed-2290-4178-b9df-3cb7b599830b () github ! com
[Download RAW message or body]

On Sun, 29 Oct 2023 14:29:45 GMT, Alec Su <duke@openjdk.org> wrote:

> > JVM attempts to reuse the buffer for sending MIDI out data when the buffer size \
> > is enough. It use `dwBytesRecorded` in `MIDIHDR` structure to indicate the actual \
> > size of the data. However, `midiOutLongMsg()` ignores `dwBytesRecorded`, although \
> > it did not mentioned in the documentation. I've tested on Windows 7, 10 and 11. \
> > All of them have the same behavior. 
> > The bug cannot be easily reproduced because some MIDI drivers filter out any \
> > malformed MIDI data. The example code below create a special case to make sure \
> > all MIDI data are legally when the bug is triggered. 
> > 
> > import javax.sound.midi.*;
> > 
> > public class MidiTest {
> > public static class RawMidiMessage extends MidiMessage {
> > public RawMidiMessage(byte[] data) {
> > super(data);
> > }
> > 
> > @Override
> > public Object clone() {
> > return new RawMidiMessage(this.getMessage());
> > }
> > }
> > 
> > public static void main(String[] args) {
> > var deviceInfos = MidiSystem.getMidiDeviceInfo();
> > for (var info : deviceInfos) {
> > try (MidiDevice device = MidiSystem.getMidiDevice(info)) {
> > if (device.getMaxReceivers() != 0) {
> > System.out.println("Open MIDI port: " + info.getName());
> > device.open();
> > Receiver receiver = device.getReceiver();
> > // Send two sysex messages at once
> > receiver.send(new RawMidiMessage(new byte[]{
> > (byte) 0xF0, 0x7D, 0x01, (byte) 0xF7,
> > (byte) 0xF0, 0x7D, 0x02, (byte) 0xF7
> > }), -1);
> > // Send another sysex message
> > receiver.send(new RawMidiMessage(new byte[]{(byte) 0xF0, 0x7D, 0x03, (byte) \
> > 0xF7}), -1); }
> > } catch (MidiUnavailableException e) {
> > e.printStackTrace();
> > }
> > }
> > }
> > }
> > 
> > 
> > The expected messages received should be the following three messages
> > 
> > F0 7D 01 F7
> > F0 7D 02 F7
> > F0 7D 03 F7
> > 
> > 
> > But acually four messages was received with the second message repeated twice.
> > 
> > F0 7D 01 F7
> > F0 7D 02 F7
> > F0 7D 03 F7
> > F0 7D 02 F7
> > 
> > 
> > To resolve the issue, I add a new variable to backup the actual buffer size and \
> > set `dwBufferLength` of `MIDIHDR` structure to the size of MIDI data. After \
> > calling `midiOutLongMsg()`, I restore the original buffer size if the buf...
> 
> Alec Su has updated the pull request incrementally with one additional commit since \
> the last revision: 
> Code cleanup

> It use `dwBytesRecorded` in `MIDIHDR` structure to indicate the actual size of the \
> data However, `midiOutLongMsg()` ignores `dwBytesRecorded`, although it did not \
> mentioned in the documentation.


This seems to be documented by Microsoft only in the most obscure fashion.

If you look at the doc for midiOutPrepareHeader
https://learn.microsoft.com/en-us/previous-versions/dd798477(v=vs.85)
it says "Before calling the function, set the lpData, dwBufferLength, and dwFlags \
members of the [MIDIHDR](https://learn.microsoft.com/en-us/previous-versions/dd798449(v=vs.85)) \
structure"

So no mention of dwBytesRecorded.

WAVEHDR is a very similar struct to MIDIHDR and if you look at this WAVEHDR doc it \
says

https://learn.microsoft.com/en-us/previous-versions/dd743837(v=vs.85)

    dwBytesRecorded
    When the header is used in input, specifies how much data is in the buffer.

So I infer the same is true for MIDI

Therefore dwBytesRecorded is only used for input and dwBufferLength is what's \
important for output.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/16399#issuecomment-1786077861


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic