1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package javax.sound.midi; 19 20import org.apache.harmony.sound.internal.nls.Messages; 21 22public class ShortMessage extends MidiMessage { 23 24 public static final int ACTIVE_SENSING = 254; 25 26 public static final int CHANNEL_PRESSURE = 208; 27 28 public static final int CONTINUE = 251; 29 30 public static final int CONTROL_CHANGE = 176; 31 32 public static final int END_OF_EXCLUSIVE = 247; 33 34 public static final int MIDI_TIME_CODE = 241; 35 36 public static final int NOTE_OFF = 128; 37 38 public static final int NOTE_ON = 144; 39 40 public static final int PITCH_BEND = 224; 41 42 public static final int POLY_PRESSURE = 160; 43 44 public static final int PROGRAM_CHANGE = 192; 45 46 public static final int SONG_POSITION_POINTER = 242; 47 48 public static final int SONG_SELECT = 243; 49 50 public static final int START = 250; 51 52 public static final int STOP = 252; 53 54 public static final int SYSTEM_RESET = 255; 55 56 public static final int TIMING_CLOCK = 248; 57 58 public static final int TUNE_REQUEST = 246; 59 60 public ShortMessage() { 61 super(new byte[] {-112, 64, 127}); 62 } 63 64 protected ShortMessage(byte[] data) { 65 super(data); 66 } 67 68 @Override 69 public Object clone() { 70 return new ShortMessage(this.getMessage()); 71 } 72 73 public int getChannel() { 74 /* 75 * channel change from 0 up to 15 76 */ 77 if ((data == null) || (data.length == 0)) { 78 return 0; 79 } 80 return data[0] & 0x0F; 81 } 82 83 public int getCommand() { 84 /* 85 * command should be divisible by 16 without rest 86 */ 87 if ((data == null) || (data.length == 0)) { 88 return 0; 89 } 90 return (data[0] & 0xFF) - getChannel(); 91 } 92 93 public int getData1() { 94 if ((data == null) || (data.length == 0)) { 95 return 0; 96 } else if (data.length < 2) { 97 return 0; 98 } else { 99 return data[1] & 0xFF; 100 } 101 } 102 103 public int getData2() { 104 if ((data == null) || (data.length == 0)) { 105 return 0; 106 } else if (data.length < 3) { 107 return 0; 108 } else { 109 return data[2] & 0xFF; 110 } 111 } 112 113 protected final int getDataLength(int status) 114 throws InvalidMidiDataException { 115 // FIXME 116 /* 117 * I have some question about this method. I didn't understand how 118 * should to work this method, but some results I get by experimental 119 * method. From 0 up to 127, from 256 up to 383 and so on this method 120 * throw out exception, i.e. after 256 begin cycle with some small 121 * differences in the first lap, from 0 up to 255. From the second lap 122 * and so on this method, getDataLenght(int), throw out exception with 123 * value of status from 496 up to 511, from 752 up to 767 and so on, 124 * i.e. on the last 16 number of 256-lap. And now differences in the 125 * first lap. This method don't throw out exception with value of status 126 * from 240 up to 255. It has next behavior: 127 * - value of status equals 240 -- throw out exception; 128 * - 241 -- return 1; 129 * - 242 -- return 2; 130 * - 243 -- return 1; 131 * - from 244 up to 245 -- throw out exception; 132 * - from 246 up to 255 -- return 0; 133 */ 134 if (status < 0) { 135 // sound.04=Invalid status byte: {0} 136 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 137 } 138 if (((status % 256) >= 0) && ((status % 256) <= 127)) { 139 // sound.04=Invalid status byte: {0} 140 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 141 } 142 if (((status / 256) == 0) 143 && ((status == 240) || (status == 244) || (status == 245))) { 144 // sound.04=Invalid status byte: {0} 145 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 146 } 147 if (((status / 256) != 0) && ((status % 256) >= 244) 148 && ((status % 256) <= 255)) { 149 // sound.04=Invalid status byte: {0} 150 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 151 } 152 153 if ((status / 256) == 0) { 154 if ((status == 241) || (status == 243)) { 155 return 1; 156 } else if (status == 242) { 157 return 2; 158 } else if ((status >= 246) && (status <= 255)) { 159 return 0; 160 } 161 } 162 if (((status % 256) >= 128) && ((status % 256) <= 191)) { 163 return 2; 164 } else if (((status % 256) >= 192) && ((status % 256) <= 223)) { 165 return 1; 166 } else { 167 return 2; 168 } 169 } 170 171 public void setMessage(int status) throws InvalidMidiDataException { 172 /* 173 * value of variable status is more or equals 246 and less or equals 255 174 */ 175 if ((status < 246) || (status > 255)) { 176 // sound.04=Invalid status byte: {0} 177 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 178 } 179 super.setMessage(new byte[] {(byte) status}, 1); 180 } 181 182 public void setMessage(int status, int data1, int data2) 183 throws InvalidMidiDataException { 184 // FIXME 185 /* 186 * In the Sun's implementation variables data1 and data2 don't use; I 187 * don't find situation when this variables influence on result of 188 * functions getData1() and getData2(). But function getDataLength(int) 189 * return 0 when I modify status byte from 246 up to 255, and so I think 190 * it's true. 191 */ 192 if ((status < 246) || (status > 255)) { 193 // sound.04=Invalid status byte: {0} 194 throw new InvalidMidiDataException(Messages.getString("sound.04", status)); //$NON-NLS-1$ 195 } 196 super.setMessage(new byte[] {(byte) status}, 1); 197 } 198 199 public void setMessage(int command, int channel, int data1, int data2) 200 throws InvalidMidiDataException { 201 // FIXME 202 /* 203 * value of variable command is more or equals 128 and less or equals 204 * 239 205 */ 206 if ((command < 128) || (command > 239)) { 207 /* 208 * when this exception throw out, the value of variable command 209 * should be the hexadecimal number 210 */ 211 // sound.05=command out of range: {0} 212 throw new InvalidMidiDataException(Messages.getString("sound.05", command)); //$NON-NLS-1$ 213 } 214 /* 215 * value of variable channel is more or equals 0 and less or equals 15 216 */ 217 if ((channel < 0) || (channel > 15)) { 218 // sound.06=channel out of range: {0} 219 throw new InvalidMidiDataException(Messages.getString("sound.06", channel)); //$NON-NLS-1$ 220 } 221 /* 222 * value of data1 and data2 is more or equals 0 and less or equals 127, 223 * but when command more or equals 192 and less or equals 223 the second 224 * data, data2, is unused, because getDataLength(int) return 1 in this 225 * case, and in other cases it return 2 226 */ 227 if ((getDataLength(command) >= 1) && ((data1 < 0) || (data1 > 127))) { 228 // sound.07=data1 out of range: {0} 229 throw new InvalidMidiDataException(Messages.getString("sound.07", data1)); //$NON-NLS-1$ 230 } 231 if ((getDataLength(command) == 2) && ((data2 < 0) || (data2 > 127))) { 232 // sound.08=data2 out of range: {0} 233 throw new InvalidMidiDataException(Messages.getString("sound.08", data2)); //$NON-NLS-1$ 234 } 235 236 int tcom = command - (command % 16); 237 if (getDataLength(command) == 1) { 238 super.setMessage(new byte[] {(byte) (tcom + channel), (byte) data1}, 2); 239 } else { 240 super.setMessage(new byte[] {(byte) (tcom + channel), (byte) data1, 241 (byte) data2}, 3); 242 } 243 } 244 245} 246