Path: blob/master/src/java.desktop/share/classes/javax/sound/midi/SysexMessage.java
41159 views
/*1* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.sound.midi;2627import com.sun.media.sound.MidiUtils;2829/**30* A {@code SysexMessage} object represents a MIDI system exclusive message.31* <p>32* When a system exclusive message is read from a MIDI file, it always has a33* defined length. Data from a system exclusive message from a MIDI file should34* be stored in the data array of a {@code SysexMessage} as follows: the system35* exclusive message status byte (0xF0 or 0xF7), all message data bytes, and36* finally the end-of-exclusive flag (0xF7). The length reported by the37* {@code SysexMessage} object is therefore the length of the system exclusive38* data plus two: one byte for the status byte and one for the end-of-exclusive39* flag.40* <p>41* As dictated by the Standard MIDI Files specification, two status byte values42* are legal for a {@code SysexMessage} read from a MIDI file:43* <ul>44* <li>0xF0: System Exclusive message (same as in MIDI wire protocol)45* <li>0xF7: Special System Exclusive message46* </ul>47* When Java Sound is used to handle system exclusive data that is being48* received using MIDI wire protocol, it should place the data in one or more49* {@code SysexMessages}. In this case, the length of the system exclusive data50* is not known in advance; the end of the system exclusive data is marked by an51* end-of-exclusive flag (0xF7) in the MIDI wire byte stream.52* <ul>53* <li>0xF0: System Exclusive message (same as in MIDI wire protocol)54* <li>0xF7: End of Exclusive (EOX)55* </ul>56* The first {@code SysexMessage} object containing data for a particular system57* exclusive message should have the status value 0xF0. If this message contains58* all the system exclusive data for the message, it should end with the status59* byte 0xF7 (EOX). Otherwise, additional system exclusive data should be sent60* in one or more {@code SysexMessages} with a status value of 0xF7. The61* {@code SysexMessage} containing the last of the data for the system exclusive62* message should end with the value 0xF7 (EOX) to mark the end of the system63* exclusive message.64* <p>65* If system exclusive data from {@code SysexMessages} objects is being66* transmitted using MIDI wire protocol, only the initial 0xF0 status byte, the67* system exclusive data itself, and the final 0xF7 (EOX) byte should be68* propagated; any 0xF7 status bytes used to indicate that a69* {@code SysexMessage} contains continuing system exclusive data should not be70* propagated via MIDI wire protocol.71*72* @author David Rivas73* @author Kara Kytle74* @author Florian Bomers75*/76public class SysexMessage extends MidiMessage {7778// Status byte defines7980/**81* Status byte for System Exclusive message (0xF0, or 240).82*83* @see MidiMessage#getStatus84*/85public static final int SYSTEM_EXCLUSIVE = 0xF0; // 2408687/**88* Status byte for Special System Exclusive message (0xF7, or 247), which is89* used in MIDI files. It has the same value as END_OF_EXCLUSIVE, which is90* used in the real-time "MIDI wire" protocol.91*92* @see MidiMessage#getStatus93*/94public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; // 2479596/**97* The data bytes for this system exclusive message. These are initialized98* to {@code null} and are set explicitly by99* {@link #setMessage(int, byte[], int, long) setMessage}.100*/101//protected byte[] data = null;102103/**104* Constructs a new {@code SysexMessage}. The contents of the new message105* are guaranteed to specify a valid MIDI message. Subsequently, you may set106* the contents of the message using one of the {@code setMessage} methods.107*108* @see #setMessage109*/110public SysexMessage() {111this(new byte[2]);112// Default sysex message data: SOX followed by EOX113data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF);114data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);115}116117/**118* Constructs a new {@code SysexMessage} and sets the data for the message.119* The first byte of the data array must be a valid system exclusive status120* byte (0xF0 or 0xF7). The contents of the message can be changed by using121* one of the {@code setMessage} methods.122*123* @param data the system exclusive message data including the status byte124* @param length the length of the valid message data in the array,125* including the status byte; it should be non-negative and less126* than or equal to {@code data.length}127* @throws InvalidMidiDataException if the parameter values do not specify a128* valid MIDI meta message129* @see #setMessage(byte[], int)130* @see #setMessage(int, byte[], int)131* @see #getData()132* @since 1.7133*/134public SysexMessage(byte[] data, int length)135throws InvalidMidiDataException {136super(null);137setMessage(data, length);138}139140/**141* Constructs a new {@code SysexMessage} and sets the data for the message.142* The contents of the message can be changed by using one of the143* {@code setMessage} methods.144*145* @param status the status byte for the message; it must be a valid system146* exclusive status byte (0xF0 or 0xF7)147* @param data the system exclusive message data (without the status byte)148* @param length the length of the valid message data in the array; it149* should be non-negative and less than or equal to150* {@code data.length}151* @throws InvalidMidiDataException if the parameter values do not specify a152* valid MIDI system exclusive message153* @see #setMessage(byte[], int)154* @see #setMessage(int, byte[], int)155* @see #getData()156* @since 1.7157*/158public SysexMessage(int status, byte[] data, int length)159throws InvalidMidiDataException {160super(null);161setMessage(status, data, length);162}163164/**165* Constructs a new {@code SysexMessage}.166*167* @param data an array of bytes containing the complete message. The168* message data may be changed using the {@code setMessage} method.169* @see #setMessage170*/171protected SysexMessage(byte[] data) {172super(data);173}174175/**176* Sets the data for the system exclusive message. The first byte of the177* data array must be a valid system exclusive status byte (0xF0 or 0xF7).178*179* @param data the system exclusive message data180* @param length the length of the valid message data in the array,181* including the status byte182* @throws InvalidMidiDataException if the parameter values do not specify a183* valid MIDI system exclusive message184*/185@Override186public void setMessage(byte[] data, int length) throws InvalidMidiDataException {187MidiUtils.checkSysexStatus(data, length);188super.setMessage(data, length);189}190191/**192* Sets the data for the system exclusive message.193*194* @param status the status byte for the message (0xF0 or 0xF7)195* @param data the system exclusive message data196* @param length the length of the valid message data in the array197* @throws InvalidMidiDataException if the status byte is invalid for a198* system exclusive message199*/200public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException {201MidiUtils.checkSysexStatus(status);202if (length < 0 || length > data.length) {203throw new IndexOutOfBoundsException("length out of bounds: "+length);204}205this.length = length + 1;206207if (this.data==null || this.data.length < this.length) {208this.data = new byte[this.length];209}210211this.data[0] = (byte) (status & 0xFF);212if (length > 0) {213System.arraycopy(data, 0, this.data, 1, length);214}215}216217/**218* Obtains a copy of the data for the system exclusive message. The returned219* array of bytes does not include the status byte.220*221* @return array containing the system exclusive message data222*/223public byte[] getData() {224byte[] returnedArray = new byte[length - 1];225System.arraycopy(data, 1, returnedArray, 0, (length - 1));226return returnedArray;227}228229/**230* Creates a new object of the same class and with the same contents as this231* object.232*233* @return a clone of this instance234*/235@Override236public Object clone() {237byte[] newData = new byte[length];238System.arraycopy(data, 0, newData, 0, newData.length);239return new SysexMessage(newData);240}241}242243244