RFR: 8074211: javax.sound.midi: Error with send System Exclusive messages of different length [v2]
Alec Su
duke at openjdk.org
Sun Oct 29 14:19:03 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 refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains two new commits since the last revision:
- Add a testcase for the buffer issue on Windows
- Resolve the message size issue when sending SysexMessage on Windows
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/16399/files
- new: https://git.openjdk.org/jdk/pull/16399/files/16918dd5..a6b499f3
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=16399&range=01
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=16399&range=00-01
Stats: 113 lines in 5 files changed: 84 ins; 2 del; 27 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