/* * MidiMessage.java * * This file is part of Tritonus: http://www.tritonus.org/ */ /* * Copyright (c) 1999 - 2002 by Matthias Pfisterer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* |<--- this code is formatted to fit into 80 columns --->| */ package javax.sound.midi; import org.tritonus.share.TDebug; import org.tritonus.share.midi.MidiUtils; /** Base class for MIDI messages. @author Matthias Pfisterer */ public abstract class MidiMessage implements Cloneable { /** The data of the message. This array contains the message separated into bytes. The storage format used for this array follows the way messages are sent via a MIDI cable or stored in a standard MIDI file. See the subclasses of MidiMessage to get more information on the required storage format for each type.<p> At any time after the execution of this class' constructor, this value must refer to an array with at least one element. Especially, <code>null</code> is not allowed. The array may contain more bytes than used to store the MIDI message. The variable {@link #length length} indicates the number of valid bytes. The content of the additional bytes has to be considered implementation-specific.<p> In this implementation, the length of data is always equal to the value of {@link #length length}. However, this is not a specification requirement. Accessing this member from subclasses is highly discouraged. Subclasses should use the constructor or {@link #setMessage(byte[], int) setMessage} to modify the content and {@link #getMessage() getMessage()} to retrieve it. @see #setMessage(byte[], int) @see #getMessage() */ protected byte[] data; /** The length of the message. This value represents the number of bytes in the array {@link #data data} that are valid. At any time after the execution of this class' constructor, this value is guaranteed to be greater or equal to one. Additinally, with the exception of while the control flow is inside this class' method {@link #setMessage(byte[], int) setMessage()} the value is guaranteed to be as least as big as the length of {@link #data data}. It may be less than the length of {@link #data data} in cases where {@link #data data} contains additional (invalid) bytes.<p> Accessing this member from subclasses is highly discouraged. Subclasses should use the constructor or {@link #setMessage(byte[], int) setMessage()} to modify the length and {@link #getLength() getLength()} to retrieve it. @see #getLength() */ protected int length; /** Constructs a MidiMessage. The passed array is used to initialize {@link #data data}. {@link #length length} is initialized to the length of the passed array. Note that a copy of the passed array is made.<p> This constructor does not use {@link #setMessage(byte[], int) setMessage()}. So it is unaffected by overriding setMessage().<p> It is unclear if the argument is allowed to be null. This implementation allows it, resulting in {@link #data data} being null, too. @param abData The data to use to construct the MIDI message. */ protected MidiMessage(byte[] abData) { if (abData != null) { copyToData(abData, abData.length); } } /** Initializes the data of the message. This method sets the data of the MIDI message. <code>nLength</code> bytes of <code>abData</code> are copied to a newly created array, which is set as {@link #data data}. {@link #length length} is initialized to the value of <code>nLength</code>.<p> Open points: should we specify that this class' version of setMessage() (not the ones of derived classes) never throws an exception? Otherwise, we have to specify the cases where exceptions are thrown. For instance: abData == null, abData.length < nLength, ... @param abData The bytes to use as MIDI message. This array may contain trailing invalid bytes. <code>nLength</code> gives the number of valid bytes. This means that the length of <code>abData</code> has to be equal or greater than <code>nLength</code>. @param nLength The length of the MIDI message. This is equal to the number of valid bytes in <code>abData</code>. This value may be less than the length of <code>abData</code>. In this case, the remaining bytes have to be considered invalid. This means that the value of <code>nLength</code> has to be equal or less than the length of <code>abData</code>. */ protected void setMessage(byte[] abData, int nLength) throws InvalidMidiDataException { copyToData(abData, nLength); } /** TODO: */ private void copyToData(byte[] abData, int nLength) { synchronized (this) { data = new byte[nLength]; System.arraycopy(abData, 0, data, 0, nLength); length = nLength; } } /** Return the complete message. This method makes a copy of {@link #data data} and returns a reference to the copy. The returned array contains only the bytes that form the MIDI message, even if {@link #data data} contains additional invalid bytes. This requirement also means that the length of the returned array is equal to {@link #length length} and equal to the value returned by {@link #getLength() getLength()}. @return An array of bytes representing the MIDI message. */ public byte[] getMessage() { byte[] abData = new byte[length]; System.arraycopy(data, 0, abData, 0, length); return abData; } /** Returns the status byte of the message. This method returns the first byte of {@link #data data}, which is always the status byte. @return The status byte of the MIDI message stored in this object. */ public int getStatus() { int nStatus = MidiUtils.getUnsignedInteger(data[0]); return nStatus; } /** Returns the length of the whole message in bytes. This returns the value of the member {@link #length length}. The value returned by this method is always equal to the length of the array returned by {@link #getMessage() getMessage()}. @return The length of the MIDI message in bytes. @see #length @see #getMessage() */ public int getLength() { return length; } /** Create a copy of this MIDI message. @return A new MidiMessage object that is a copy of this one. */ public abstract Object clone(); /** Print content of data[]. This method is used for debugging. */ private void outputData() { String strMessage = "MidiMessage.outputData(): data: ["; for (int i = 0; i < data.length; i++) { strMessage += (data[i] + ", "); } strMessage += "]"; TDebug.out(strMessage); } } /*** MidiMessage.java ***/