001/* Track.java -- A track of MIDI events
002   Copyright (C) 2005 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.sound.midi;
040
041import java.util.HashSet;
042import java.util.Vector;
043
044/**
045 * A Track contains a list of timecoded MIDI events for processing
046 * by a Sequencer.
047 *
048 * @author Anthony Green (green@redhat.com)
049 * @since 1.3
050 *
051 */
052public class Track
053{
054  /**
055   * The list of MidiEvents for this track.
056   */
057  Vector events = new Vector();
058
059  // A HashSet to speed processing
060  private HashSet eventSet = new HashSet();
061
062  // This is only instantiable within this package.
063  Track()
064  {
065  }
066
067  /**
068   * Add a new event to this track.  Specific events may only be added once.
069   * The event will be inserted into the appropriate spot in the event list
070   * based on its timecode.
071   *
072   * @param event the event to add
073   * @return true if the event was added, false otherwise
074   */
075  public boolean add(MidiEvent event)
076  {
077    synchronized (events)
078    {
079      if (eventSet.contains(event))
080        return false;
081
082      eventSet.add(event);
083
084      long targetTick = event.getTick();
085      int i = events.size() - 1;
086      while (i >= 0 && (((MidiEvent)events.get(i)).getTick() > targetTick))
087        i--;
088      events.add(i+1, event);
089      return true;
090    }
091  }
092
093  /**
094   * Remove an event from this track.
095   *
096   * @param event the event to remove
097   * @return true if the event was removed, false otherwise
098   */
099  public boolean remove(MidiEvent event)
100  {
101    synchronized (events)
102    {
103      if (! eventSet.remove(event))
104        return false;
105
106      int i = events.indexOf(event);
107      if (i >= 0)
108        {
109          events.remove(i);
110          return true;
111        }
112
113      throw new InternalError("event in set but not list");
114    }
115  }
116
117  /**
118   * Get an event idetified by its order index
119   *
120   * @param index the location of the event to get
121   * @return the event at index
122   * @throws ArrayIndexOutOfBoundsException if index is out of bounds
123   */
124  public MidiEvent get(int index) throws ArrayIndexOutOfBoundsException
125  {
126    synchronized (events)
127    {
128      try
129      {
130        return (MidiEvent) events.get(index);
131      }
132      catch (IndexOutOfBoundsException e)
133      {
134        throw (ArrayIndexOutOfBoundsException)
135          new ArrayIndexOutOfBoundsException().initCause(e);
136      }
137    }
138  }
139
140
141  /**
142   * Get the number events in this track.
143   *
144   * @return the number of events in this track
145   */
146  public int size()
147  {
148    return events.size();
149  }
150
151  /**
152   * Get the length of the track in MIDI ticks.
153   *
154   * @return the length of the track in MIDI ticks
155   */
156  public long ticks()
157  {
158    synchronized (events)
159    {
160      int size = events.size();
161      return ((MidiEvent) events.get(size - 1)).getTick();
162    }
163  }
164 }