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 18 package javax.sound.midi; 19 20 import java.util.ArrayList; 21 22 import org.apache.harmony.sound.internal.nls.Messages; 23 24 public class Track { 25 private ArrayList<MidiEvent> events; //vector of events contain in the Track 26 27 private MidiEvent badEvent; //variable to save event which I try to add 28 //to empty Track; see description below 29 30 private long tick; 31 32 Track() { 33 /* 34 * create an empty Track; new Track must contain only meta-event End of Track. 35 * MetaMessage with MetaMessage.data contains -1, 47 and 0 is meta-event 36 */ 37 events = new ArrayList<MidiEvent>(); 38 events.add(new MidiEvent(new MetaMessage(new byte[] {-1, 47, 0}), 0)); 39 } 40 public boolean add(MidiEvent event) { 41 //FIXME 42 /* 43 * Some words about badEvent. 44 * When I write tests, I find following situation in the RI: 45 * if I want to add to empty Track new event that is not meta-event End of Track, 46 * I catch exception ArrayIndexOutOfBoundsException with meaning -1, and my 47 * event doesn't add to Track, but meta-event adds. If I try to add the same 48 * event after it, method Track.add(MidiEvent) return 'false', and my event 49 * doesn't add again. So, I want to delete this event and use method 50 * Track.remove(MidiEvent) for it, but it return 'false' too! And only after 51 * this "shamanism" I can add this event to Track normally. 52 * And only for this situation I use variable badEvent. 53 * 54 * See test org.apache.harmony.sound.tests.javax.sound.midi.TrackTest 55 * for more details 56 */ 57 58 /* 59 * if event equals null or badEvent, this method return 'false' 60 */ 61 if (event == null || event == badEvent) { 62 return false; 63 } 64 /* 65 * If event equals meta-event End of Track and Track in this moment 66 * doesn't contain some events, i.e. Track.size() return 0, this 67 * event accrue to Track; 68 * if Track is not empty, but it doesn't contain meta-event, 69 * this event accrue to the end of Track; 70 * in any case addition of this meta-event is successful, this method 71 * return 'true' even if meta-event End of Track already contains in the Track 72 */ 73 if (event.getMessage().getMessage()[0] == -1 && 74 event.getMessage().getMessage()[1] == 47 && 75 event.getMessage().getMessage()[2] == 0 ) { 76 if (events.size() == 0) { 77 return events.add(event); 78 } 79 byte[] bt = events.get(events.size() - 1).getMessage().getMessage(); 80 if ((bt[0] != -1) && (bt[1] != 47) && (bt[2] != 0)) { 81 return events.add(event); 82 } 83 return true; 84 } 85 /* 86 * after use method Track.add(MidiEvent) Track must contain meta-event 87 * End of Track; so, at first I add this event to Track if it doesn't 88 * contain meta-event and parameter 'event' is not meta-event 89 */ 90 if (events.size() == 0) { 91 events.add(new MidiEvent(new MetaMessage(new byte[] {-1, 47, 0}), 0)); 92 badEvent = event; 93 // sounds.01=-1 94 throw new ArrayIndexOutOfBoundsException(Messages.getString("sound.01")); //$NON-NLS-1$ 95 } 96 byte[] bt = events.get(events.size() - 1).getMessage().getMessage(); 97 if ((bt[0] != -1) && (bt[1] != 47) && (bt[2] != 0)) { 98 events.add(new MidiEvent(new MetaMessage(new byte[] {-1, 47, 0}), 0)); 99 } 100 101 if (events.contains(event)) { 102 return false; 103 } 104 105 /* 106 * events in the Track must take up position in ascending ticks 107 */ 108 if (events.size() == 1) { 109 events.add(0, event); 110 } 111 for (int i = 0; i < events.size() - 1; i++ ) { 112 if (events.get(i).getTick() <= event.getTick()) { 113 continue; 114 } 115 events.add(i, event); 116 break; 117 } 118 /* 119 * method Track.ticks() return the biggest value of tick of all events 120 * and save it even I remove event with the biggest values of tick 121 */ 122 if (tick < event.getTick()) { 123 tick = event.getTick(); 124 } 125 return true; 126 } 127 128 public MidiEvent get(int index) throws ArrayIndexOutOfBoundsException { 129 if (index < 0 || index >= events.size()) { 130 // sound.02=Index: {0}, Size: {1} 131 throw new ArrayIndexOutOfBoundsException(Messages.getString("sound.02", index, events.size())); //$NON-NLS-1$ 132 } 133 return events.get(index); 134 } 135 136 public boolean remove(MidiEvent event) { 137 /* 138 * if I remove event that equals badEvent, I "delete" badEvent 139 */ 140 if (event == badEvent) { 141 badEvent = null; 142 return false; 143 } 144 /* 145 * method Track.ticks() always return the biggest value that ever has been 146 * in the Track; so only when Track is empty Track.ticks() return 0 147 */ 148 if (events.remove(event)) { 149 if (events.size() == 0) { 150 tick = 0; 151 } 152 return true; 153 } 154 return false; 155 } 156 157 public int size() { 158 return events.size(); 159 } 160 161 public long ticks() { 162 return tick; 163 } 164 } 165