RFR: 8074211: javax.sound.midi: Error with send System Exclusive messages of different length [v4]
Alec Su
duke at openjdk.org
Tue Nov 7 16:21:59 UTC 2023
> 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 buffer hasn't been freed due to an error.
>
> It seems that the patch may also resolve JDK-8250667. The extra bytes in the s...
Alec Su has updated the pull request incrementally with one additional commit since the last revision:
Remove OS check in the test
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/16399/files
- new: https://git.openjdk.org/jdk/pull/16399/files/819e2cff..4ae4486b
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=16399&range=03
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=16399&range=02-03
Stats: 1 line in 1 file changed: 0 ins; 1 del; 0 mod
Patch: https://git.openjdk.org/jdk/pull/16399.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/16399/head:pull/16399
PR: https://git.openjdk.org/jdk/pull/16399
More information about the client-libs-dev
mailing list