24 */ |
24 */ |
25 |
25 |
26 package javax.sound.midi; |
26 package javax.sound.midi; |
27 |
27 |
28 /** |
28 /** |
29 * A <code>SysexMessage</code> object represents a MIDI system exclusive message. |
29 * A {@code SysexMessage} object represents a MIDI system exclusive message. |
30 * <p> |
30 * <p> |
31 * When a system exclusive message is read from a MIDI file, it always has |
31 * When a system exclusive message is read from a MIDI file, it always has a |
32 * a defined length. Data from a system exclusive message from a MIDI file |
32 * defined length. Data from a system exclusive message from a MIDI file should |
33 * should be stored in the data array of a <code>SysexMessage</code> as |
33 * be stored in the data array of a {@code SysexMessage} as follows: the system |
34 * follows: the system exclusive message status byte (0xF0 or 0xF7), all |
34 * exclusive message status byte (0xF0 or 0xF7), all message data bytes, and |
35 * message data bytes, and finally the end-of-exclusive flag (0xF7). |
35 * finally the end-of-exclusive flag (0xF7). The length reported by the |
36 * The length reported by the <code>SysexMessage</code> object is therefore |
36 * {@code SysexMessage} object is therefore the length of the system exclusive |
37 * the length of the system exclusive data plus two: one byte for the status |
37 * data plus two: one byte for the status byte and one for the end-of-exclusive |
38 * byte and one for the end-of-exclusive flag. |
38 * flag. |
39 * <p> |
39 * <p> |
40 * As dictated by the Standard MIDI Files specification, two status byte values are legal |
40 * As dictated by the Standard MIDI Files specification, two status byte values |
41 * for a <code>SysexMessage</code> read from a MIDI file: |
41 * are legal for a {@code SysexMessage} read from a MIDI file: |
42 * <ul> |
42 * <ul> |
43 * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li> |
43 * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li> |
44 * <li>0xF7: Special System Exclusive message</li> |
44 * <li>0xF7: Special System Exclusive message</li> |
45 * </ul> |
45 * </ul> |
46 * <p> |
46 * When Java Sound is used to handle system exclusive data that is being |
47 * When Java Sound is used to handle system exclusive data that is being received |
47 * received using MIDI wire protocol, it should place the data in one or more |
48 * using MIDI wire protocol, it should place the data in one or more |
48 * {@code SysexMessages}. In this case, the length of the system exclusive data |
49 * <code>SysexMessages</code>. In this case, the length of the system exclusive data |
|
50 * is not known in advance; the end of the system exclusive data is marked by an |
49 * is not known in advance; the end of the system exclusive data is marked by an |
51 * end-of-exclusive flag (0xF7) in the MIDI wire byte stream. |
50 * end-of-exclusive flag (0xF7) in the MIDI wire byte stream. |
52 * <ul> |
51 * <ul> |
53 * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li> |
52 * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li> |
54 * <li>0xF7: End of Exclusive (EOX)</li> |
53 * <li>0xF7: End of Exclusive (EOX)</li> |
55 * </ul> |
54 * </ul> |
56 * The first <code>SysexMessage</code> object containing data for a particular system |
55 * The first {@code SysexMessage} object containing data for a particular system |
57 * exclusive message should have the status value 0xF0. If this message contains all |
56 * exclusive message should have the status value 0xF0. If this message contains |
58 * the system exclusive data |
57 * all the system exclusive data for the message, it should end with the status |
59 * for the message, it should end with the status byte 0xF7 (EOX). |
58 * byte 0xF7 (EOX). Otherwise, additional system exclusive data should be sent |
60 * Otherwise, additional system exclusive data should be sent in one or more |
59 * in one or more {@code SysexMessages} with a status value of 0xF7. The |
61 * <code>SysexMessages</code> with a status value of 0xF7. The <code>SysexMessage</code> |
60 * {@code SysexMessage} containing the last of the data for the system exclusive |
62 * containing the last of the data for the system exclusive message should end with the |
61 * message should end with the value 0xF7 (EOX) to mark the end of the system |
63 * value 0xF7 (EOX) to mark the end of the system exclusive message. |
62 * exclusive message. |
64 * <p> |
63 * <p> |
65 * If system exclusive data from <code>SysexMessages</code> objects is being transmitted |
64 * If system exclusive data from {@code SysexMessages} objects is being |
66 * using MIDI wire protocol, only the initial 0xF0 status byte, the system exclusive |
65 * transmitted using MIDI wire protocol, only the initial 0xF0 status byte, the |
67 * data itself, and the final 0xF7 (EOX) byte should be propagated; any 0xF7 status |
66 * system exclusive data itself, and the final 0xF7 (EOX) byte should be |
68 * bytes used to indicate that a <code>SysexMessage</code> contains continuing system |
67 * propagated; any 0xF7 status bytes used to indicate that a |
69 * exclusive data should not be propagated via MIDI wire protocol. |
68 * {@code SysexMessage} contains continuing system exclusive data should not be |
|
69 * propagated via MIDI wire protocol. |
70 * |
70 * |
71 * @author David Rivas |
71 * @author David Rivas |
72 * @author Kara Kytle |
72 * @author Kara Kytle |
73 * @author Florian Bomers |
73 * @author Florian Bomers |
74 */ |
74 */ |
75 public class SysexMessage extends MidiMessage { |
75 public class SysexMessage extends MidiMessage { |
76 |
76 |
77 |
|
78 // Status byte defines |
77 // Status byte defines |
79 |
78 |
80 |
|
81 /** |
79 /** |
82 * Status byte for System Exclusive message (0xF0, or 240). |
80 * Status byte for System Exclusive message (0xF0, or 240). |
|
81 * |
83 * @see MidiMessage#getStatus |
82 * @see MidiMessage#getStatus |
84 */ |
83 */ |
85 public static final int SYSTEM_EXCLUSIVE = 0xF0; // 240 |
84 public static final int SYSTEM_EXCLUSIVE = 0xF0; // 240 |
86 |
85 |
87 |
86 /** |
88 /** |
87 * Status byte for Special System Exclusive message (0xF7, or 247), which is |
89 * Status byte for Special System Exclusive message (0xF7, or 247), which is used |
88 * used in MIDI files. It has the same value as END_OF_EXCLUSIVE, which is |
90 * in MIDI files. It has the same value as END_OF_EXCLUSIVE, which |
89 * used in the real-time "MIDI wire" protocol. |
91 * is used in the real-time "MIDI wire" protocol. |
90 * |
92 * @see MidiMessage#getStatus |
91 * @see MidiMessage#getStatus |
93 */ |
92 */ |
94 public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; // 247 |
93 public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; // 247 |
95 |
94 |
96 |
95 /** |
97 // Instance variables |
96 * The data bytes for this system exclusive message. These are initialized |
98 |
97 * to {@code null} and are set explicitly by |
99 |
98 * {@link #setMessage(int, byte[], int, long) setMessage}. |
100 /* |
|
101 * The data bytes for this system exclusive message. These are |
|
102 * initialized to <code>null</code> and are set explicitly |
|
103 * by {@link #setMessage(int, byte[], int, long) setMessage}. |
|
104 */ |
99 */ |
105 //protected byte[] data = null; |
100 //protected byte[] data = null; |
106 |
101 |
107 |
102 /** |
108 /** |
103 * Constructs a new {@code SysexMessage}. The contents of the new message |
109 * Constructs a new <code>SysexMessage</code>. The |
104 * are guaranteed to specify a valid MIDI message. Subsequently, you may set |
110 * contents of the new message are guaranteed to specify |
105 * the contents of the message using one of the {@code setMessage} methods. |
111 * a valid MIDI message. Subsequently, you may set the |
106 * |
112 * contents of the message using one of the <code>setMessage</code> |
|
113 * methods. |
|
114 * @see #setMessage |
107 * @see #setMessage |
115 */ |
108 */ |
116 public SysexMessage() { |
109 public SysexMessage() { |
117 this(new byte[2]); |
110 this(new byte[2]); |
118 // Default sysex message data: SOX followed by EOX |
111 // Default sysex message data: SOX followed by EOX |
119 data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF); |
112 data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF); |
120 data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF); |
113 data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF); |
121 } |
114 } |
122 |
115 |
123 /** |
116 /** |
124 * Constructs a new {@code SysexMessage} and sets the data for |
117 * Constructs a new {@code SysexMessage} and sets the data for the message. |
125 * the message. The first byte of the data array must be a valid system |
118 * The first byte of the data array must be a valid system exclusive status |
126 * exclusive status byte (0xF0 or 0xF7). |
119 * byte (0xF0 or 0xF7). The contents of the message can be changed by using |
127 * The contents of the message can be changed by using one of |
120 * one of the {@code setMessage} methods. |
128 * the {@code setMessage} methods. |
121 * |
129 * |
122 * @param data the system exclusive message data including the status byte |
130 * @param data the system exclusive message data including the status byte |
123 * @param length the length of the valid message data in the array, |
131 * @param length the length of the valid message data in the array, |
124 * including the status byte; it should be non-negative and less |
132 * including the status byte; it should be non-negative and less than |
125 * than or equal to {@code data.length} |
133 * or equal to {@code data.length} |
126 * @throws InvalidMidiDataException if the parameter values do not specify a |
134 * @throws InvalidMidiDataException if the parameter values |
127 * valid MIDI meta message. |
135 * do not specify a valid MIDI meta message. |
|
136 * @see #setMessage(byte[], int) |
128 * @see #setMessage(byte[], int) |
137 * @see #setMessage(int, byte[], int) |
129 * @see #setMessage(int, byte[], int) |
138 * @see #getData() |
130 * @see #getData() |
139 * @since 1.7 |
131 * @since 1.7 |
140 */ |
132 */ |
166 throws InvalidMidiDataException { |
158 throws InvalidMidiDataException { |
167 super(null); |
159 super(null); |
168 setMessage(status, data, length); |
160 setMessage(status, data, length); |
169 } |
161 } |
170 |
162 |
171 |
163 /** |
172 /** |
164 * Constructs a new {@code SysexMessage}. |
173 * Constructs a new <code>SysexMessage</code>. |
165 * |
174 * @param data an array of bytes containing the complete message. |
166 * @param data an array of bytes containing the complete message. The |
175 * The message data may be changed using the <code>setMessage</code> |
167 * message data may be changed using the {@code setMessage} method. |
176 * method. |
|
177 * @see #setMessage |
168 * @see #setMessage |
178 */ |
169 */ |
179 protected SysexMessage(byte[] data) { |
170 protected SysexMessage(byte[] data) { |
180 super(data); |
171 super(data); |
181 } |
172 } |
182 |
173 |
183 |
174 /** |
184 /** |
175 * Sets the data for the system exclusive message. The first byte of the |
185 * Sets the data for the system exclusive message. The |
176 * data array must be a valid system exclusive status byte (0xF0 or 0xF7). |
186 * first byte of the data array must be a valid system |
177 * |
187 * exclusive status byte (0xF0 or 0xF7). |
178 * @param data the system exclusive message data |
188 * @param data the system exclusive message data |
179 * @param length the length of the valid message data in the array, |
189 * @param length the length of the valid message data in |
180 * including the status byte |
190 * the array, including the status byte. |
|
191 */ |
181 */ |
192 public void setMessage(byte[] data, int length) throws InvalidMidiDataException { |
182 public void setMessage(byte[] data, int length) throws InvalidMidiDataException { |
193 int status = (data[0] & 0xFF); |
183 int status = (data[0] & 0xFF); |
194 if ((status != 0xF0) && (status != 0xF7)) { |
184 if ((status != 0xF0) && (status != 0xF7)) { |
195 throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status)); |
185 throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status)); |
196 } |
186 } |
197 super.setMessage(data, length); |
187 super.setMessage(data, length); |
198 } |
188 } |
199 |
189 |
200 |
|
201 /** |
190 /** |
202 * Sets the data for the system exclusive message. |
191 * Sets the data for the system exclusive message. |
203 * @param status the status byte for the message (0xF0 or 0xF7) |
192 * |
204 * @param data the system exclusive message data |
193 * @param status the status byte for the message (0xF0 or 0xF7) |
205 * @param length the length of the valid message data in |
194 * @param data the system exclusive message data |
206 * the array |
195 * @param length the length of the valid message data in the array |
207 * @throws InvalidMidiDataException if the status byte is invalid for a sysex message |
196 * @throws InvalidMidiDataException if the status byte is invalid for a |
|
197 * sysex message |
208 */ |
198 */ |
209 public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException { |
199 public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException { |
210 if ( (status != 0xF0) && (status != 0xF7) ) { |
200 if ( (status != 0xF0) && (status != 0xF7) ) { |
211 throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status)); |
201 throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status)); |
212 } |
202 } |
223 if (length > 0) { |
213 if (length > 0) { |
224 System.arraycopy(data, 0, this.data, 1, length); |
214 System.arraycopy(data, 0, this.data, 1, length); |
225 } |
215 } |
226 } |
216 } |
227 |
217 |
228 |
218 /** |
229 /** |
219 * Obtains a copy of the data for the system exclusive message. The returned |
230 * Obtains a copy of the data for the system exclusive message. |
220 * array of bytes does not include the status byte. |
231 * The returned array of bytes does not include the status byte. |
221 * |
232 * @return array containing the system exclusive message data. |
222 * @return array containing the system exclusive message data |
233 */ |
223 */ |
234 public byte[] getData() { |
224 public byte[] getData() { |
235 byte[] returnedArray = new byte[length - 1]; |
225 byte[] returnedArray = new byte[length - 1]; |
236 System.arraycopy(data, 1, returnedArray, 0, (length - 1)); |
226 System.arraycopy(data, 1, returnedArray, 0, (length - 1)); |
237 return returnedArray; |
227 return returnedArray; |
238 } |
228 } |
239 |
229 |
240 |
230 /** |
241 /** |
231 * Creates a new object of the same class and with the same contents as this |
242 * Creates a new object of the same class and with the same contents |
232 * object. |
243 * as this object. |
233 * |
244 * @return a clone of this instance |
234 * @return a clone of this instance |
245 */ |
235 */ |
246 public Object clone() { |
236 public Object clone() { |
247 byte[] newData = new byte[length]; |
237 byte[] newData = new byte[length]; |
248 System.arraycopy(data, 0, newData, 0, newData.length); |
238 System.arraycopy(data, 0, newData, 0, newData.length); |