001package org.intellimate.izou.system.sound;
002
003import org.intellimate.izou.addon.AddOnModel;
004import org.intellimate.izou.main.Main;
005
006import javax.sound.sampled.*;
007import java.io.IOException;
008
009/**
010 * delegates the Clip-Methods
011 * @author LeanderK
012 * @version 1.0
013 */
014public class IzouSoundLineClip extends IzouSoundDataLine implements Clip {
015    private final Clip clip;
016
017    public IzouSoundLineClip(Clip clip, Main main, boolean isPermanent, AddOnModel addOnModel) {
018        super(clip, main, isPermanent, addOnModel);
019        this.clip = clip;
020    }
021
022    /**
023     * Opens the clip, meaning that it should acquire any required
024     * system resources and become operational.  The clip is opened
025     * with the format and audio data indicated.
026     * If this operation succeeds, the line is marked as open and an
027     * <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched
028     * to the line's listeners.
029     * <p>
030     * Invoking this method on a line which is already open is illegal
031     * and may result in an IllegalStateException.
032     * <p>
033     * Note that some lines, once closed, cannot be reopened.  Attempts
034     * to reopen such a line will always result in a
035     * <code>{@link LineUnavailableException}</code>.
036     *
037     * @param format the format of the supplied audio data
038     * @param data a byte array containing audio data to load into the clip
039     * @param offset the point at which to start copying, expressed in
040     * <em>bytes</em> from the beginning of the array
041     * @param bufferSize the number of <em>bytes</em>
042     * of data to load into the clip from the array.
043     * @throws LineUnavailableException if the line cannot be
044     * opened due to resource restrictions
045     * @throws IllegalArgumentException if the buffer size does not represent
046     * an integral number of sample frames,
047     * or if <code>format</code> is not fully specified or invalid
048     * @throws IllegalStateException if the line is already open
049     * @throws SecurityException if the line cannot be
050     * opened due to security restrictions
051     *
052     * @see #close
053     * @see #isOpen
054     * @see LineListener
055     */
056    @Override
057    public void open(AudioFormat format, byte[] data, int offset, int bufferSize) throws LineUnavailableException {
058        opening();
059        clip.open(format, data, offset, bufferSize);
060    }
061
062    /**
063     * Opens the clip with the format and audio data present in the provided audio
064     * input stream.  Opening a clip means that it should acquire any required
065     * system resources and become operational.  If this operation
066     * input stream.  If this operation
067     * succeeds, the line is marked open and an
068     * <code>{@link LineEvent.Type#OPEN OPEN}</code> event is dispatched
069     * to the line's listeners.
070     * <p>
071     * Invoking this method on a line which is already open is illegal
072     * and may result in an IllegalStateException.
073     * <p>
074     * Note that some lines, once closed, cannot be reopened.  Attempts
075     * to reopen such a line will always result in a
076     * <code>{@link LineUnavailableException}</code>.
077     *
078     * @param stream an audio input stream from which audio data will be read into
079     * the clip
080     * @throws LineUnavailableException if the line cannot be
081     * opened due to resource restrictions
082     * @throws IOException if an I/O exception occurs during reading of
083     * the stream
084     * @throws IllegalArgumentException if the stream's audio format
085     * is not fully specified or invalid
086     * @throws IllegalStateException if the line is already open
087     * @throws SecurityException if the line cannot be
088     * opened due to security restrictions
089     *
090     * @see #close
091     * @see #isOpen
092     * @see LineListener
093     */
094    @Override
095    public void open(AudioInputStream stream) throws LineUnavailableException, IOException {
096        opening();
097        clip.open(stream);
098    }
099
100    /**
101     * Obtains the media length in sample frames.
102     * @return the media length, expressed in sample frames,
103     * or <code>AudioSystem.NOT_SPECIFIED</code> if the line is not open.
104     * @see AudioSystem#NOT_SPECIFIED
105     */
106    @Override
107    public int getFrameLength() {
108        return clip.getFrameLength();
109    }
110
111    /**
112     * Obtains the media duration in microseconds
113     * @return the media duration, expressed in microseconds,
114     * or <code>AudioSystem.NOT_SPECIFIED</code> if the line is not open.
115     * @see AudioSystem#NOT_SPECIFIED
116     */
117    @Override
118    public long getMicrosecondLength() {
119        return clip.getMicrosecondLength();
120    }
121
122    /**
123     * Sets the media position in sample frames.  The position is zero-based;
124     * the first frame is frame number zero.  When the clip begins playing the
125     * next time, it will start by playing the frame at this position.
126     * <p>
127     * To obtain the current position in sample frames, use the
128     * <code>{@link DataLine#getFramePosition getFramePosition}</code>
129     * method of <code>DataLine</code>.
130     *
131     * @param frames the desired new media position, expressed in sample frames
132     */
133    @Override
134    public void setFramePosition(int frames) {
135        clip.setFramePosition(frames);
136    }
137
138    /**
139     * Sets the media position in microseconds.  When the clip begins playing the
140     * next time, it will start at this position.
141     * The level of precision is not guaranteed.  For example, an implementation
142     * might calculate the microsecond position from the current frame position
143     * and the audio sample frame rate.  The precision in microseconds would
144     * then be limited to the number of microseconds per sample frame.
145     * <p>
146     * To obtain the current position in microseconds, use the
147     * <code>{@link DataLine#getMicrosecondPosition getMicrosecondPosition}</code>
148     * method of <code>DataLine</code>.
149     *
150     * @param microseconds the desired new media position, expressed in microseconds
151     */
152    @Override
153    public void setMicrosecondPosition(long microseconds) {
154        clip.setMicrosecondPosition(microseconds);
155    }
156
157    /**
158     * Sets the first and last sample frames that will be played in
159     * the loop.  The ending point must be greater than
160     * or equal to the starting point, and both must fall within the
161     * the size of the loaded media.  A value of 0 for the starting
162     * point means the beginning of the loaded media.  Similarly, a value of -1
163     * for the ending point indicates the last frame of the media.
164     * @param start the loop's starting position, in sample frames (zero-based)
165     * @param end the loop's ending position, in sample frames (zero-based), or
166     * -1 to indicate the final frame
167     * @throws IllegalArgumentException if the requested
168     * loop points cannot be set, usually because one or both falls outside
169     * the media's duration or because the ending point is
170     * before the starting point
171     */
172    @Override
173    public void setLoopPoints(int start, int end) {
174        clip.setLoopPoints(start, end);
175    }
176
177    /**
178     * Starts looping playback from the current position.   Playback will
179     * continue to the loop's end point, then loop back to the loop start point
180     * <code>count</code> times, and finally continue playback to the end of
181     * the clip.
182     * <p>
183     * If the current position when this method is invoked is greater than the
184     * loop end point, playback simply continues to the
185     * end of the clip without looping.
186     * <p>
187     * A <code>count</code> value of 0 indicates that any current looping should
188     * cease and playback should continue to the end of the clip.  The behavior
189     * is undefined when this method is invoked with any other value during a
190     * loop operation.
191     * <p>
192     * If playback is stopped during looping, the current loop status is
193     * cleared; the behavior of subsequent loop and start requests is not
194     * affected by an interrupted loop operation.
195     *
196     * @param count the number of times playback should loop back from the
197     * loop's end position to the loop's  start position, or
198     * <code>{@link #LOOP_CONTINUOUSLY}</code> to indicate that looping should
199     * continue until interrupted
200     */
201    @Override
202    public void loop(int count) {
203        clip.loop(count);
204    }
205}