Home | History | Annotate | Download | only in midi
      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