Skip to content

Commit e47cf61

Browse files
AlecJYprrace
authored andcommitted
8074211: javax.sound.midi: Error with send System Exclusive messages of different length
8250667: MIDI sysex over USB scrambled when reply length matches previous message Reviewed-by: prr
1 parent 6d82436 commit e47cf61

File tree

5 files changed

+46
-26
lines changed

5 files changed

+46
-26
lines changed

src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiIn.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -301,7 +301,7 @@ INT32 prepareBuffers(MidiDeviceHandle* handle) {
301301
}
302302
sysex = (SysExQueue*) handle->longBuffers;
303303
for (i = 0; i<sysex->count; i++) {
304-
MIDIHDR* hdr = &(sysex->header[i]);
304+
MIDIHDR* hdr = &(sysex->headerInfo[i].header);
305305
midiInPrepareHeader((HMIDIIN) handle->deviceHandle, hdr, sizeof(MIDIHDR));
306306
err = midiInAddBuffer((HMIDIIN) handle->deviceHandle, hdr, sizeof(MIDIHDR));
307307
}
@@ -320,7 +320,7 @@ INT32 unprepareBuffers(MidiDeviceHandle* handle) {
320320
}
321321
sysex = (SysExQueue*) handle->longBuffers;
322322
for (i = 0; i<sysex->count; i++) {
323-
err = midiInUnprepareHeader((HMIDIIN) handle->deviceHandle, &(sysex->header[i]), sizeof(MIDIHDR));
323+
err = midiInUnprepareHeader((HMIDIIN) handle->deviceHandle, &(sysex->headerInfo[i].header), sizeof(MIDIHDR));
324324
}
325325
MIDIIN_CHECK_ERROR;
326326
return (INT32) err;
@@ -502,7 +502,7 @@ void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
502502
}
503503
sysex = (SysExQueue*) handle->longBuffers;
504504
if (msg->type == LONG_MESSAGE && sysex) {
505-
MIDIHDR* hdr = &(sysex->header[msg->data.l.index]);
505+
MIDIHDR* hdr = &(sysex->headerInfo[msg->data.l.index].header);
506506
//fprintf(stdout, "ReleaseMessage index %d\n", msg->data.l.index); fflush(stdout);
507507
hdr->dwBytesRecorded = 0;
508508
midiInAddBuffer((HMIDIIN) handle->deviceHandle, hdr, sizeof(MIDIHDR));

src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_MidiOut.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -161,7 +161,7 @@ INT32 unprepareLongBuffers(MidiDeviceHandle* handle) {
161161
}
162162
sysex = (SysExQueue*) handle->longBuffers;
163163
for (i = 0; i<sysex->count; i++) {
164-
MIDIHDR* hdr = &(sysex->header[i]);
164+
MIDIHDR* hdr = &(sysex->headerInfo[i].header);
165165
if (hdr->dwFlags) {
166166
err = midiOutUnprepareHeader((HMIDIOUT) handle->deviceHandle, hdr, sizeof(MIDIHDR));
167167
}
@@ -170,8 +170,9 @@ INT32 unprepareLongBuffers(MidiDeviceHandle* handle) {
170170
return (INT32) err;
171171
}
172172

173-
INT32 freeLongBuffer(MIDIHDR* hdr, HMIDIOUT deviceHandle, INT32 minToLeaveData) {
173+
INT32 freeLongBuffer(MidiHeaderInfo* info, HMIDIOUT deviceHandle, INT32 minToLeaveData) {
174174
MMRESULT err = MMSYSERR_NOERROR;
175+
MIDIHDR* hdr = &(info->header);
175176

176177
if (!hdr) {
177178
ERROR0("MIDI_OUT_freeLongBuffer: hdr == NULL\n");
@@ -180,10 +181,11 @@ INT32 freeLongBuffer(MIDIHDR* hdr, HMIDIOUT deviceHandle, INT32 minToLeaveData)
180181
if (hdr->dwFlags && deviceHandle) {
181182
err = midiOutUnprepareHeader(deviceHandle, hdr, sizeof(MIDIHDR));
182183
}
183-
if (hdr->lpData && (((INT32) hdr->dwBufferLength) < minToLeaveData || minToLeaveData < 0)) {
184+
if (hdr->lpData && (info->bufferLength < minToLeaveData || minToLeaveData < 0)) {
184185
free(hdr->lpData);
185186
hdr->lpData=NULL;
186187
hdr->dwBufferLength=0;
188+
info->bufferLength=0;
187189
}
188190
hdr->dwBytesRecorded=0;
189191
hdr->dwFlags=0;
@@ -201,7 +203,7 @@ INT32 freeLongBuffers(MidiDeviceHandle* handle) {
201203
}
202204
sysex = (SysExQueue*) handle->longBuffers;
203205
for (i = 0; i<sysex->count; i++) {
204-
err = freeLongBuffer(&(sysex->header[i]), (HMIDIOUT) handle->deviceHandle, -1);
206+
err = freeLongBuffer(&(sysex->headerInfo[i]), (HMIDIOUT) handle->deviceHandle, -1);
205207
}
206208
MIDIOUT_CHECK_ERROR;
207209
return (INT32) err;
@@ -352,6 +354,7 @@ INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT
352354
INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 size, UINT32 timestamp) {
353355
MMRESULT err;
354356
SysExQueue* sysex;
357+
MidiHeaderInfo* info = NULL;
355358
MIDIHDR* hdr = NULL;
356359
INT32 remainingSize;
357360
int i;
@@ -378,10 +381,12 @@ INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 siz
378381
while (!hdr && handle->platformData) {
379382
/* find a non-queued header */
380383
for (i = 0; i < sysex->count; i++) {
381-
hdr = &(sysex->header[i]);
384+
info = &(sysex->headerInfo[i]);
385+
hdr = &(info->header);
382386
if ((hdr->dwFlags & MHDR_DONE) || (hdr->dwFlags == 0)) {
383387
break;
384388
}
389+
info = NULL;
385390
hdr = NULL;
386391
}
387392
/* wait for a buffer to free up */
@@ -404,22 +409,26 @@ INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data, UINT32 siz
404409
}
405410

406411
TRACE2("-> sending %d bytes with buffer index=%d\n", (int) size, (int) hdr->dwUser);
407-
freeLongBuffer(hdr, handle->deviceHandle, (INT32) size);
412+
freeLongBuffer(info, handle->deviceHandle, (INT32) size);
408413
if (hdr->lpData == NULL) {
409414
hdr->lpData = malloc(size);
410-
hdr->dwBufferLength = size;
415+
info->bufferLength = size;
411416
}
417+
// Because midiOutLongMsg() ignores dwBytesRecorded, set both
418+
// dwBufferLength to the size of the data. The actual buffer
419+
// size is recorded in info->bufferLength.
420+
hdr->dwBufferLength = size;
412421
hdr->dwBytesRecorded = size;
413422
memcpy(hdr->lpData, data, size);
414423
err = midiOutPrepareHeader((HMIDIOUT) handle->deviceHandle, hdr, sizeof(MIDIHDR));
415424
if (err != MMSYSERR_NOERROR) {
416-
freeLongBuffer(hdr, handle->deviceHandle, -1);
425+
freeLongBuffer(info, handle->deviceHandle, -1);
417426
MIDIOUT_CHECK_ERROR;
418427
return (INT32) err;
419428
}
420429
err = midiOutLongMsg((HMIDIOUT) handle->deviceHandle, hdr, sizeof(MIDIHDR));
421430
if (err != MMSYSERR_NOERROR) {
422-
freeLongBuffer(hdr, handle->deviceHandle, -1);
431+
freeLongBuffer(info, handle->deviceHandle, -1);
423432
ERROR0("ERROR: MIDI_OUT_SendLongMessage: midiOutLongMsg returned error:\n");
424433
MIDIOUT_CHECK_ERROR;
425434
return (INT32) err;

src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Util.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -89,7 +89,7 @@ int MIDI_WinCreateLongBufferQueue(MidiDeviceHandle* handle, int count, int size,
8989
SysExQueue* sysex;
9090
int i;
9191
UBYTE* dataPtr;
92-
int structSize = sizeof(SysExQueue) + ((count - 1) * sizeof(MIDIHDR));
92+
int structSize = sizeof(SysExQueue) + ((count - 1) * sizeof(MidiHeaderInfo));
9393

9494
sysex = (SysExQueue*) malloc(structSize);
9595
if (!sysex) return FALSE;
@@ -112,10 +112,11 @@ int MIDI_WinCreateLongBufferQueue(MidiDeviceHandle* handle, int count, int size,
112112
// set up headers
113113
dataPtr = preAllocatedMem;
114114
for (i=0; i<count; i++) {
115-
sysex->header[i].lpData = dataPtr;
116-
sysex->header[i].dwBufferLength = size;
115+
sysex->headerInfo[i].header.lpData = dataPtr;
116+
sysex->headerInfo[i].header.dwBufferLength = size;
117+
sysex->headerInfo[i].bufferLength = size;
117118
// user data is the index of the buffer
118-
sysex->header[i].dwUser = (DWORD) i;
119+
sysex->headerInfo[i].header.dwUser = (DWORD) i;
119120
dataPtr += size;
120121
}
121122
return TRUE;

src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_Util.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -46,12 +46,17 @@
4646

4747
#include "PlatformMidi.h"
4848

49+
typedef struct tag_MidiHeaderInfo {
50+
MIDIHDR header; // Windows specific structure to hold meta info
51+
INT32 bufferLength; // the actual length of the buffer in MIDIHDR
52+
} MidiHeaderInfo;
53+
4954
typedef struct tag_SysExQueue {
50-
int count; // number of sys ex headers
51-
int size; // data size per sys ex header
52-
int ownsLinearMem; // true when linearMem is to be disposed
53-
UBYTE* linearMem; // where the actual sys ex data is, count*size bytes
54-
MIDIHDR header[1]; // Windows specific structure to hold meta info
55+
int count; // number of sys ex headers
56+
int size; // data size per sys ex header
57+
int ownsLinearMem; // true when linearMem is to be disposed
58+
UBYTE* linearMem; // where the actual sys ex data is, count*size bytes
59+
MidiHeaderInfo headerInfo[1]; // a structure to hold MIDIHDR and the actual buffer length
5560
} SysExQueue;
5661

5762
/* set the startTime field in MidiDeviceHandle */

test/jdk/javax/sound/midi/SysexMessage/SendRawSysexMessage.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
/**
3636
* @test
37-
* @bug 8237495 8301310
37+
* @bug 8074211 8237495 8301310
3838
* @summary fail with memory errors when asked to send a sysex message starting
3939
* with 0xF7
4040
*/
@@ -114,6 +114,11 @@ private static void test(MidiDevice.Info info) throws Exception {
114114
(byte) SPECIAL_SYSTEM_EXCLUSIVE}), -1);
115115
System.err.println("note off");
116116
r.send(new ShortMessage(ShortMessage.NOTE_OFF, 5, 5), -1);
117+
// The three parts of the sysex below are added for
118+
// JDK-8301310, but it can also used to test JDK-8074211.
119+
// However, The testcase does not fail when JDK-8074211 occurs.
120+
// It's recommended to setup a loopback MIDI device then check
121+
// whether the sysex received is the same as the testcase.
117122
System.err.println("sysex part 1 of 3");
118123
r.send(new SysexMessage(new byte[]{
119124
(byte) SYSTEM_EXCLUSIVE, 0x7D, 0x01, 0x02}, 4), -1);

0 commit comments

Comments
 (0)