src/share/classes/javax/sound/midi/SysexMessage.java

Print this page


   1 /*
   2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.sound.midi;
  27 
  28 /**
  29  * A <code>SysexMessage</code> object represents a MIDI system exclusive message.
  30  * <p>
  31  * When a system exclusive message is read from a MIDI file, it always has
  32  * a defined length.  Data from a system exclusive message from a MIDI file
  33  * should be stored in the data array of a <code>SysexMessage</code> as
  34  * follows: the system exclusive message status byte (0xF0 or 0xF7), all
  35  * message data bytes, and finally the end-of-exclusive flag (0xF7).
  36  * The length reported by the <code>SysexMessage</code> object is therefore
  37  * the length of the system exclusive data plus two: one byte for the status
  38  * byte and one for the end-of-exclusive flag.
  39  * <p>
  40  * As dictated by the Standard MIDI Files specification, two status byte values are legal
  41  * for a <code>SysexMessage</code> read from a MIDI file:
  42  * <ul>
  43  * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li>
  44  * <li>0xF7: Special System Exclusive message</li>
  45  * </ul>
  46  * <p>
  47  * When Java Sound is used to handle system exclusive data that is being received
  48  * using MIDI wire protocol, it should place the data in one or more
  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
  51  * 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)</li>
  54  * <li>0xF7: End of Exclusive (EOX)</li>
  55  * </ul>
  56  * The first <code>SysexMessage</code> object containing data for a particular system
  57  * exclusive message should have the status value 0xF0.  If this message contains all
  58  * the system exclusive data
  59  * for the message, it should end with the status byte 0xF7 (EOX).
  60  * Otherwise, additional system exclusive data should be sent in one or more
  61  * <code>SysexMessages</code> with a status value of 0xF7.  The <code>SysexMessage</code>
  62  * containing the last of the data for the system exclusive message should end with the
  63  * value 0xF7 (EOX) to mark the end of the system exclusive message.
  64  * <p>
  65  * If system exclusive data from <code>SysexMessages</code> objects is being transmitted
  66  * using MIDI wire protocol, only the initial 0xF0 status byte, the system exclusive
  67  * data itself, and the final 0xF7 (EOX) byte should be propagated; any 0xF7 status
  68  * bytes used to indicate that a <code>SysexMessage</code> contains continuing system
  69  * exclusive data should not be propagated via MIDI wire protocol.

  70  *
  71  * @author David Rivas
  72  * @author Kara Kytle
  73  * @author Florian Bomers
  74  */
  75 public class SysexMessage extends MidiMessage {
  76 
  77 
  78     // Status byte defines
  79 
  80 
  81     /**
  82      * Status byte for System Exclusive message (0xF0, or 240).

  83      * @see MidiMessage#getStatus
  84      */
  85     public static final int SYSTEM_EXCLUSIVE                    = 0xF0; // 240
  86 
  87 
  88     /**
  89      * Status byte for Special System Exclusive message (0xF7, or 247), which is used
  90      * in MIDI files.  It has the same value as END_OF_EXCLUSIVE, which
  91      * is used in the real-time "MIDI wire" protocol.

  92      * @see MidiMessage#getStatus
  93      */
  94     public static final int SPECIAL_SYSTEM_EXCLUSIVE    = 0xF7; // 247
  95 
  96 
  97     // Instance variables
  98 
  99 
 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      */
 105     //protected byte[] data = null;
 106 
 107 
 108     /**
 109      * Constructs a new <code>SysexMessage</code>. The
 110      * contents of the new message are guaranteed to specify
 111      * a valid MIDI message.  Subsequently, you may set the
 112      * contents of the message using one of the <code>setMessage</code>
 113      * methods.
 114      * @see #setMessage
 115      */
 116     public SysexMessage() {
 117         this(new byte[2]);
 118         // Default sysex message data: SOX followed by EOX
 119         data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF);
 120         data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);
 121     }
 122 
 123     /**
 124      * Constructs a new {@code SysexMessage} and sets the data for
 125      * the message. The first byte of the data array must be a valid system
 126      * exclusive status byte (0xF0 or 0xF7).
 127      * The contents of the message can be changed by using one of
 128      * the {@code setMessage} methods.
 129      *
 130      * @param data the system exclusive message data including the status byte
 131      * @param length the length of the valid message data in the array,
 132      *     including the status byte; it should be non-negative and less than
 133      *     or equal to {@code data.length}
 134      * @throws InvalidMidiDataException if the parameter values
 135      *     do not specify a valid MIDI meta message.
 136      * @see #setMessage(byte[], int)
 137      * @see #setMessage(int, byte[], int)
 138      * @see #getData()
 139      * @since 1.7
 140      */
 141     public SysexMessage(byte[] data, int length)
 142             throws InvalidMidiDataException {
 143         super(null);
 144         setMessage(data, length);
 145     }
 146 
 147     /**
 148      * Constructs a new {@code SysexMessage} and sets the data for the message.
 149      * The contents of the message can be changed by using one of
 150      * the {@code setMessage} methods.
 151      *
 152      * @param status the status byte for the message; it must be a valid system
 153      *     exclusive status byte (0xF0 or 0xF7)
 154      * @param data the system exclusive message data (without the status byte)
 155      * @param length the length of the valid message data in the array;
 156      *     it should be non-negative and less than or equal to
 157      *     {@code data.length}
 158      * @throws InvalidMidiDataException if the parameter values
 159      *     do not specify a valid MIDI meta message.
 160      * @see #setMessage(byte[], int)
 161      * @see #setMessage(int, byte[], int)
 162      * @see #getData()
 163      * @since 1.7
 164      */
 165     public SysexMessage(int status, byte[] data, int length)
 166             throws InvalidMidiDataException {
 167         super(null);
 168         setMessage(status, data, length);
 169     }
 170 
 171 
 172     /**
 173      * Constructs a new <code>SysexMessage</code>.
 174      * @param data an array of bytes containing the complete message.
 175      * The message data may be changed using the <code>setMessage</code>
 176      * method.
 177      * @see #setMessage
 178      */
 179     protected SysexMessage(byte[] data) {
 180         super(data);
 181     }
 182 
 183 
 184     /**
 185      * Sets the data for the system exclusive message.   The
 186      * first byte of the data array must be a valid system
 187      * exclusive status byte (0xF0 or 0xF7).
 188      * @param data the system exclusive message data
 189      * @param length the length of the valid message data in
 190      * the array, including the status byte.
 191      */
 192     public void setMessage(byte[] data, int length) throws InvalidMidiDataException {
 193         int status = (data[0] & 0xFF);
 194         if ((status != 0xF0) && (status != 0xF7)) {
 195             throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
 196         }
 197         super.setMessage(data, length);
 198     }
 199 
 200 
 201     /**
 202      * Sets the data for the system exclusive message.

 203      * @param status the status byte for the message (0xF0 or 0xF7)
 204      * @param data the system exclusive message data
 205      * @param length the length of the valid message data in
 206      * the array
 207      * @throws InvalidMidiDataException if the status byte is invalid for a sysex message
 208      */
 209     public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException {
 210         if ( (status != 0xF0) && (status != 0xF7) ) {
 211             throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
 212         }
 213         if (length < 0 || length > data.length) {
 214             throw new IndexOutOfBoundsException("length out of bounds: "+length);
 215         }
 216         this.length = length + 1;
 217 
 218         if (this.data==null || this.data.length < this.length) {
 219             this.data = new byte[this.length];
 220         }
 221 
 222         this.data[0] = (byte) (status & 0xFF);
 223         if (length > 0) {
 224             System.arraycopy(data, 0, this.data, 1, length);
 225         }
 226     }
 227 
 228 
 229     /**
 230      * Obtains a copy of the data for the system exclusive message.
 231      * The returned array of bytes does not include the status byte.
 232      * @return array containing the system exclusive message data.

 233      */
 234     public byte[] getData() {
 235         byte[] returnedArray = new byte[length - 1];
 236         System.arraycopy(data, 1, returnedArray, 0, (length - 1));
 237         return returnedArray;
 238     }
 239 
 240 
 241     /**
 242      * Creates a new object of the same class and with the same contents
 243      * as this object.

 244      * @return a clone of this instance
 245      */
 246     public Object clone() {
 247         byte[] newData = new byte[length];
 248         System.arraycopy(data, 0, newData, 0, newData.length);
 249         SysexMessage event = new SysexMessage(newData);
 250         return event;
 251     }
 252 }
   1 /*
   2  * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.sound.midi;
  27 
  28 /**
  29  * A {@code SysexMessage} object represents a MIDI system exclusive message.
  30  * <p>
  31  * When a system exclusive message is read from a MIDI file, it always has a
  32  * defined length. Data from a system exclusive message from a MIDI file should
  33  * be stored in the data array of a {@code SysexMessage} as follows: the system
  34  * exclusive message status byte (0xF0 or 0xF7), all message data bytes, and
  35  * finally the end-of-exclusive flag (0xF7). The length reported by the
  36  * {@code SysexMessage} object is therefore the length of the system exclusive
  37  * data plus two: one byte for the status byte and one for the end-of-exclusive
  38  * flag.
  39  * <p>
  40  * As dictated by the Standard MIDI Files specification, two status byte values
  41  * are legal for a {@code SysexMessage} read from a MIDI file:
  42  * <ul>
  43  * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li>
  44  * <li>0xF7: Special System Exclusive message</li>
  45  * </ul>
  46  * When Java Sound is used to handle system exclusive data that is being
  47  * received 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  * is not known in advance; the end of the system exclusive data is marked by an
  50  * end-of-exclusive flag (0xF7) in the MIDI wire byte stream.
  51  * <ul>
  52  * <li>0xF0: System Exclusive message (same as in MIDI wire protocol)</li>
  53  * <li>0xF7: End of Exclusive (EOX)</li>
  54  * </ul>
  55  * The first {@code SysexMessage} object containing data for a particular system
  56  * exclusive message should have the status value 0xF0. If this message contains
  57  * all the system exclusive data for the message, it should end with the status
  58  * byte 0xF7 (EOX). Otherwise, additional system exclusive data should be sent
  59  * in one or more {@code SysexMessages} with a status value of 0xF7. The
  60  * {@code SysexMessage} containing the last of the data for the system exclusive
  61  * message should end with the value 0xF7 (EOX) to mark the end of the system
  62  * exclusive message.
  63  * <p>
  64  * If system exclusive data from {@code SysexMessages} objects is being
  65  * transmitted using MIDI wire protocol, only the initial 0xF0 status byte, the
  66  * system exclusive data itself, and the final 0xF7 (EOX) byte should be
  67  * propagated; any 0xF7 status bytes used to indicate that a
  68  * {@code SysexMessage} contains continuing system exclusive data should not be
  69  * propagated via MIDI wire protocol.
  70  *
  71  * @author David Rivas
  72  * @author Kara Kytle
  73  * @author Florian Bomers
  74  */
  75 public class SysexMessage extends MidiMessage {
  76 

  77     // Status byte defines
  78 

  79     /**
  80      * Status byte for System Exclusive message (0xF0, or 240).
  81      *
  82      * @see MidiMessage#getStatus
  83      */
  84     public static final int SYSTEM_EXCLUSIVE                    = 0xF0; // 240
  85 

  86     /**
  87      * Status byte for Special System Exclusive message (0xF7, or 247), which is
  88      * used in MIDI files. It has the same value as END_OF_EXCLUSIVE, which is
  89      * used in the real-time "MIDI wire" protocol.
  90      *
  91      * @see MidiMessage#getStatus
  92      */
  93     public static final int SPECIAL_SYSTEM_EXCLUSIVE    = 0xF7; // 247
  94 
  95     /**
  96      * The data bytes for this system exclusive message. These are initialized
  97      * to {@code null} and are set explicitly by
  98      * {@link #setMessage(int, byte[], int, long) setMessage}.




  99      */
 100     //protected byte[] data = null;
 101 

 102     /**
 103      * Constructs a new {@code SysexMessage}. The contents of the new message
 104      * are guaranteed to specify a valid MIDI message. Subsequently, you may set
 105      * the contents of the message using one of the {@code setMessage} methods.
 106      *

 107      * @see #setMessage
 108      */
 109     public SysexMessage() {
 110         this(new byte[2]);
 111         // Default sysex message data: SOX followed by EOX
 112         data[0] = (byte) (SYSTEM_EXCLUSIVE & 0xFF);
 113         data[1] = (byte) (ShortMessage.END_OF_EXCLUSIVE & 0xFF);
 114     }
 115 
 116     /**
 117      * Constructs a new {@code SysexMessage} and sets the data for the message.
 118      * The first byte of the data array must be a valid system exclusive status
 119      * byte (0xF0 or 0xF7). The contents of the message can be changed by using
 120      * one of the {@code setMessage} methods.

 121      *
 122      * @param  data the system exclusive message data including the status byte
 123      * @param  length the length of the valid message data in the array,
 124      *         including the status byte; it should be non-negative and less
 125      *         than or equal to {@code data.length}
 126      * @throws InvalidMidiDataException if the parameter values do not specify a
 127      *         valid MIDI meta message.
 128      * @see #setMessage(byte[], int)
 129      * @see #setMessage(int, byte[], int)
 130      * @see #getData()
 131      * @since 1.7
 132      */
 133     public SysexMessage(byte[] data, int length)
 134             throws InvalidMidiDataException {
 135         super(null);
 136         setMessage(data, length);
 137     }
 138 
 139     /**
 140      * Constructs a new {@code SysexMessage} and sets the data for the message.
 141      * The contents of the message can be changed by using one of the
 142      * {@code setMessage} methods.
 143      *
 144      * @param  status the status byte for the message; it must be a valid system
 145      *         exclusive status byte (0xF0 or 0xF7)
 146      * @param  data the system exclusive message data (without the status byte)
 147      * @param  length the length of the valid message data in the array; it
 148      *         should be non-negative and less than or equal to
 149      *         {@code data.length}
 150      * @throws InvalidMidiDataException if the parameter values do not specify a
 151      *         valid MIDI meta message
 152      * @see #setMessage(byte[], int)
 153      * @see #setMessage(int, byte[], int)
 154      * @see #getData()
 155      * @since 1.7
 156      */
 157     public SysexMessage(int status, byte[] data, int length)
 158             throws InvalidMidiDataException {
 159         super(null);
 160         setMessage(status, data, length);
 161     }
 162 

 163     /**
 164      * Constructs a new {@code SysexMessage}.
 165      *
 166      * @param  data an array of bytes containing the complete message. The
 167      *         message data may be changed using the {@code setMessage} method.
 168      * @see #setMessage
 169      */
 170     protected SysexMessage(byte[] data) {
 171         super(data);
 172     }
 173 

 174     /**
 175      * Sets the data for the system exclusive message. The first byte of the
 176      * data array must be a valid system exclusive status byte (0xF0 or 0xF7).
 177      *
 178      * @param  data the system exclusive message data
 179      * @param  length the length of the valid message data in the array,
 180      *         including the status byte
 181      */
 182     public void setMessage(byte[] data, int length) throws InvalidMidiDataException {
 183         int status = (data[0] & 0xFF);
 184         if ((status != 0xF0) && (status != 0xF7)) {
 185             throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
 186         }
 187         super.setMessage(data, length);
 188     }
 189 

 190     /**
 191      * Sets the data for the system exclusive message.
 192      *
 193      * @param  status the status byte for the message (0xF0 or 0xF7)
 194      * @param  data the system exclusive message data
 195      * @param  length the length of the valid message data in the array
 196      * @throws InvalidMidiDataException if the status byte is invalid for a
 197      *         sysex message
 198      */
 199     public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException {
 200         if ( (status != 0xF0) && (status != 0xF7) ) {
 201             throw new InvalidMidiDataException("Invalid status byte for sysex message: 0x" + Integer.toHexString(status));
 202         }
 203         if (length < 0 || length > data.length) {
 204             throw new IndexOutOfBoundsException("length out of bounds: "+length);
 205         }
 206         this.length = length + 1;
 207 
 208         if (this.data==null || this.data.length < this.length) {
 209             this.data = new byte[this.length];
 210         }
 211 
 212         this.data[0] = (byte) (status & 0xFF);
 213         if (length > 0) {
 214             System.arraycopy(data, 0, this.data, 1, length);
 215         }
 216     }
 217 

 218     /**
 219      * Obtains a copy of the data for the system exclusive message. The returned
 220      * array of bytes does not include the status byte.
 221      *
 222      * @return array containing the system exclusive message data
 223      */
 224     public byte[] getData() {
 225         byte[] returnedArray = new byte[length - 1];
 226         System.arraycopy(data, 1, returnedArray, 0, (length - 1));
 227         return returnedArray;
 228     }
 229 

 230     /**
 231      * Creates a new object of the same class and with the same contents as this
 232      * object.
 233      *
 234      * @return a clone of this instance
 235      */
 236     public Object clone() {
 237         byte[] newData = new byte[length];
 238         System.arraycopy(data, 0, newData, 0, newData.length);
 239         SysexMessage event = new SysexMessage(newData);
 240         return event;
 241     }
 242 }