blob: e75b7842d95bf16d82225125030ed0f4790b395c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.sound.midi;
import org.apache.harmony.sound.internal.nls.Messages;
public class ShortMessage extends MidiMessage {
public static final int ACTIVE_SENSING = 254;
public static final int CHANNEL_PRESSURE = 208;
public static final int CONTINUE = 251;
public static final int CONTROL_CHANGE = 176;
public static final int END_OF_EXCLUSIVE = 247;
public static final int MIDI_TIME_CODE = 241;
public static final int NOTE_OFF = 128;
public static final int NOTE_ON = 144;
public static final int PITCH_BEND = 224;
public static final int POLY_PRESSURE = 160;
public static final int PROGRAM_CHANGE = 192;
public static final int SONG_POSITION_POINTER = 242;
public static final int SONG_SELECT = 243;
public static final int START = 250;
public static final int STOP = 252;
public static final int SYSTEM_RESET = 255;
public static final int TIMING_CLOCK = 248;
public static final int TUNE_REQUEST = 246;
public ShortMessage() {
super(new byte[] {-112, 64, 127});
}
protected ShortMessage(byte[] data) {
super(data);
}
@Override
public Object clone() {
return new ShortMessage(this.getMessage());
}
public int getChannel() {
/*
* channel change from 0 up to 15
*/
if ((data == null) || (data.length == 0)) {
return 0;
}
return data[0] & 0x0F;
}
public int getCommand() {
/*
* command should be divisible by 16 without rest
*/
if ((data == null) || (data.length == 0)) {
return 0;
}
return (data[0] & 0xFF) - getChannel();
}
public int getData1() {
if ((data == null) || (data.length == 0)) {
return 0;
} else if (data.length < 2) {
return 0;
} else {
return data[1] & 0xFF;
}
}
public int getData2() {
if ((data == null) || (data.length == 0)) {
return 0;
} else if (data.length < 3) {
return 0;
} else {
return data[2] & 0xFF;
}
}
protected final int getDataLength(int status)
throws InvalidMidiDataException {
// FIXME
/*
* I have some question about this method. I didn't understand how
* should to work this method, but some results I get by experimental
* method. From 0 up to 127, from 256 up to 383 and so on this method
* throw out exception, i.e. after 256 begin cycle with some small
* differences in the first lap, from 0 up to 255. From the second lap
* and so on this method, getDataLenght(int), throw out exception with
* value of status from 496 up to 511, from 752 up to 767 and so on,
* i.e. on the last 16 number of 256-lap. And now differences in the
* first lap. This method don't throw out exception with value of status
* from 240 up to 255. It has next behavior:
* - value of status equals 240 -- throw out exception;
* - 241 -- return 1;
* - 242 -- return 2;
* - 243 -- return 1;
* - from 244 up to 245 -- throw out exception;
* - from 246 up to 255 -- return 0;
*/
if (status < 0) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
if (((status % 256) >= 0) && ((status % 256) <= 127)) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
if (((status / 256) == 0)
&& ((status == 240) || (status == 244) || (status == 245))) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
if (((status / 256) != 0) && ((status % 256) >= 244)
&& ((status % 256) <= 255)) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
if ((status / 256) == 0) {
if ((status == 241) || (status == 243)) {
return 1;
} else if (status == 242) {
return 2;
} else if ((status >= 246) && (status <= 255)) {
return 0;
}
}
if (((status % 256) >= 128) && ((status % 256) <= 191)) {
return 2;
} else if (((status % 256) >= 192) && ((status % 256) <= 223)) {
return 1;
} else {
return 2;
}
}
public void setMessage(int status) throws InvalidMidiDataException {
/*
* value of variable status is more or equals 246 and less or equals 255
*/
if ((status < 246) || (status > 255)) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
super.setMessage(new byte[] {(byte) status}, 1);
}
public void setMessage(int status, int data1, int data2)
throws InvalidMidiDataException {
// FIXME
/*
* In the Sun's implementation variables data1 and data2 don't use; I
* don't find situation when this variables influence on result of
* functions getData1() and getData2(). But function getDataLength(int)
* return 0 when I modify status byte from 246 up to 255, and so I think
* it's true.
*/
if ((status < 246) || (status > 255)) {
// sound.04=Invalid status byte: {0}
throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$
}
super.setMessage(new byte[] {(byte) status}, 1);
}
public void setMessage(int command, int channel, int data1, int data2)
throws InvalidMidiDataException {
// FIXME
/*
* value of variable command is more or equals 128 and less or equals
* 239
*/
if ((command < 128) || (command > 239)) {
/*
* when this exception throw out, the value of variable command
* should be the hexadecimal number
*/
// sound.05=command out of range: {0}
throw new InvalidMidiDataException(Messages.getString("sound.05", command)); //$NON-NLS-1$
}
/*
* value of variable channel is more or equals 0 and less or equals 15
*/
if ((channel < 0) || (channel > 15)) {
// sound.06=channel out of range: {0}
throw new InvalidMidiDataException(Messages.getString("sound.06", channel)); //$NON-NLS-1$
}
/*
* value of data1 and data2 is more or equals 0 and less or equals 127,
* but when command more or equals 192 and less or equals 223 the second
* data, data2, is unused, because getDataLength(int) return 1 in this
* case, and in other cases it return 2
*/
if ((getDataLength(command) >= 1) && ((data1 < 0) || (data1 > 127))) {
// sound.07=data1 out of range: {0}
throw new InvalidMidiDataException(Messages.getString("sound.07", data1)); //$NON-NLS-1$
}
if ((getDataLength(command) == 2) && ((data2 < 0) || (data2 > 127))) {
// sound.08=data2 out of range: {0}
throw new InvalidMidiDataException(Messages.getString("sound.08", data2)); //$NON-NLS-1$
}
int tcom = command - (command % 16);
if (getDataLength(command) == 1) {
super.setMessage(new byte[] {(byte) (tcom + channel), (byte) data1}, 2);
} else {
super.setMessage(new byte[] {(byte) (tcom + channel), (byte) data1,
(byte) data2}, 3);
}
}
}