diff options
Diffstat (limited to 'libjava/classpath/javax/sound/midi/ShortMessage.java')
-rw-r--r-- | libjava/classpath/javax/sound/midi/ShortMessage.java | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/libjava/classpath/javax/sound/midi/ShortMessage.java b/libjava/classpath/javax/sound/midi/ShortMessage.java new file mode 100644 index 000000000..08b873703 --- /dev/null +++ b/libjava/classpath/javax/sound/midi/ShortMessage.java @@ -0,0 +1,336 @@ +/* ShortMessage.java -- A MIDI message no longer than 3 bytes + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.sound.midi; + +/** + * A short MIDI message that is no longer than 3 bytes long. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class ShortMessage extends MidiMessage +{ + /** + * Status byte for Time Code message. + */ + public static final int MIDI_TIME_CODE = 0xF1; + + /** + * Status byte for Song Position Pointer message. + */ + public static final int SONG_POSITION_POINTER = 0xF2; + + /** + * Status byte for Song Select message. + */ + public static final int SONG_SELECT = 0xF3; + + /** + * Status byte for Tune Request message. + */ + public static final int TUNE_REQUEST = 0xF6; + + /** + * Status byte for End Of Exclusive message. + */ + public static final int END_OF_EXCLUSIVE = 0xF7; + + /** + * Status byte for Timing Clock message. + */ + public static final int TIMING_CLOCK = 0xF8; + + /** + * Status byte for Start message. + */ + public static final int START = 0xFA; + + /** + * Status byte for Continue message. + */ + public static final int CONTINUE = 0xFB; + + /** + * Status byte for Stop message. + */ + public static final int STOP = 0xFC; + + /** + * Status byte for Active Sensing message. + */ + public static final int ACTIVE_SENSING = 0xFE; + + /** + * Status byte for System Reset message. + */ + public static final int SYSTEM_RESET = 0xFF; + + /** + * Status nibble for Note Off message. + */ + public static final int NOTE_OFF = 0x80; + + /** + * Status nibble for Note On message. + */ + public static final int NOTE_ON = 0x90; + + /** + * Status nibble for Poly Pressure message. + */ + public static final int POLY_PRESSURE = 0xA0; + + /** + * Status nibble for Control Change message. + */ + public static final int CONTROL_CHANGE = 0xB0; + + /** + * Status nibble for Program Change message. + */ + public static final int PROGRAM_CHANGE = 0xC0; + + /** + * Statue nibble for Channel Pressure message. + */ + public static final int CHANNEL_PRESSURE = 0xD0; + + /** + * Status nibble for Pitch Bend message. + */ + public static final int PITCH_BEND = 0xE0; + + // Create and initialize a default, arbitrary message. + private static byte[] defaultMessage; + static + { + defaultMessage = new byte[1]; + defaultMessage[0] = (byte) STOP; + } + + /** + * Create a short MIDI message. + * + * The spec requires that this represent a valid MIDI message, but doesn't + * specify what it should be. We've chosen the STOP message for our + * implementation. + */ + public ShortMessage() + { + this(defaultMessage); + } + + /** + * Create a short MIDI message. + * + * The data argument should be a valid MIDI message. Unfortunately the spec + * does not allow us to throw an InvalidMidiDataException if data is invalid. + * + * @param data the message data + */ + protected ShortMessage(byte[] data) + { + super(data); + } + + /** + * Set the MIDI message. + * + * @param status the status byte for this message + * @param data1 the first data byte for this message + * @param data2 the second data byte for this message + * @throws InvalidMidiDataException if status is bad, or data is out of range + */ + public void setMessage(int status, int data1, int data2) + throws InvalidMidiDataException + { + length = getDataLength(status); + length++; + if (data == null || data.length < length) + data = new byte[length]; + data[0] = (byte) status; + if (length > 1) + { + if (data1 < 0 || data1 > 127) + throw new InvalidMidiDataException("data1 (" + data1 + + ") must be between 0 and 127."); + data[1] = (byte) data1; + if (length > 2) + { + if (data2 < 0 || data2 > 127) + throw new InvalidMidiDataException("data2 (" + data2 + + ") must be between 0 and 127."); + data[2] = (byte) data2; + } + } + } + + public void setMessage(int command, int channel, int data1, int data2) + throws InvalidMidiDataException + { + // TODO: This could probably stand some error checking. + // It currently assumes command and channel are valid values. + setMessage(command + channel, data1, data2); + } + + /** + * Set the MIDI message to one that requires no data bytes. + * + * @param status the status byte for this message + * @throws InvalidMidiDataException if status is bad, or requires data + */ + public void setMessage(int status) throws InvalidMidiDataException + { + int length = getDataLength(status); + if (length != 0) + throw new InvalidMidiDataException("Status byte 0x" + + Integer.toHexString(status) + + " requires " + + length + " bytes of data."); + setMessage(status, 0, 0); + } + + + /** + * Return the number of data bytes needed for a given MIDI status byte. + * + * @param status the status byte for a short MIDI message + * @return the number of data bytes needed for this status byte + * @throws InvalidMidiDataException if status is an invalid status byte + */ + protected final int getDataLength(int status) throws InvalidMidiDataException + { + int originalStatus = status; + + if ((status & 0xF0) != 0xF0) + status &= 0xF0; + + switch (status) + { + case NOTE_OFF: + case NOTE_ON: + case POLY_PRESSURE: + case CONTROL_CHANGE: + case PITCH_BEND: + case SONG_POSITION_POINTER: + return 2; + + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + case SONG_SELECT: + case 0xF5: // FIXME: unofficial bus select. Not in spec?? + return 1; + + case TUNE_REQUEST: + case END_OF_EXCLUSIVE: + case TIMING_CLOCK: + case START: + case CONTINUE: + case STOP: + case ACTIVE_SENSING: + case SYSTEM_RESET: + return 0; + + default: + throw new InvalidMidiDataException("Invalid status: 0x" + + Integer.toHexString(originalStatus)); + } + } + + /** + * Get the channel information from this MIDI message, assuming it is a + * MIDI channel message. + * + * @return the MIDI channel for this message + */ + public int getChannel() + { + return data[0] & 0x0F; + } + + /** + * Get the command nibble from this MIDI message, assuming it is a MIDI + * channel message. + * + * @return the MIDI command for this message + */ + public int getCommand() + { + return data[0] & 0xF0; + } + + /** + * Get the first data byte from this message, assuming it exists, and + * zero otherwise. + * + * @return the first data byte or zero if none exists. + */ + public int getData1() + { + if (length > 1) + return data[1]; + else + return 0; + } + + /** + * Get the second data byte from this message, assuming it exists, and + * zero otherwise. + * + * @return the second date byte or zero if none exists. + */ + public int getData2() + { + if (length > 2) + return data[2]; + else + return 0; + } + + /* Create a deep-copy clone of this object. + * @see java.lang.Object#clone() + */ + public Object clone() + { + byte message[] = new byte[length]; + System.arraycopy(data, 0, message, 0, length); + return new ShortMessage(message); + } +} |