001package org.intellimate.izou.system.sound;
002
003import org.intellimate.izou.addon.AddOnModel;
004import org.intellimate.izou.main.Main;
005
006import javax.sound.sampled.AudioFormat;
007import javax.sound.sampled.DataLine;
008
009/**
010 * the delegation to DataLine.
011 * @author LeanderK
012 * @version 1.0
013 */
014public class IzouSoundDataLine extends IzouSoundLineBaseClass implements DataLine {
015    private final DataLine dataLine;
016
017    public IzouSoundDataLine(DataLine dataLine, Main main, boolean isPermanent, AddOnModel addOnModel) {
018        super(dataLine, main, isPermanent, addOnModel);
019        this.dataLine = dataLine;
020    }
021
022    /**
023     * Drains queued data from the line by continuing data I/O until the
024     * data line's internal buffer has been emptied.
025     * This method blocks until the draining is complete.  Because this is a
026     * blocking method, it should be used with care.  If <code>drain()</code>
027     * is invoked on a stopped line that has data in its queue, the method will
028     * block until the line is running and the data queue becomes empty.  If
029     * <code>drain()</code> is invoked by one thread, and another continues to
030     * fill the data queue, the operation will not complete.
031     * This method always returns when the data line is closed.
032     *
033     * @see #flush()
034     */
035    @Override
036    public void drain() {
037        dataLine.drain();
038    }
039
040    /**
041     * Flushes queued data from the line.  The flushed data is discarded.
042     * In some cases, not all queued data can be discarded.  For example, a
043     * mixer can flush data from the buffer for a specific input line, but any
044     * unplayed data already in the output buffer (the result of the mix) will
045     * still be played.  You can invoke this method after pausing a line (the
046     * normal case) if you want to skip the "stale" data when you restart
047     * playback or capture. (It is legal to flush a line that is not stopped,
048     * but doing so on an active line is likely to cause a discontinuity in the
049     * data, resulting in a perceptible click.)
050     *
051     * @see #stop()
052     * @see #drain()
053     */
054    @Override
055    public void flush() {
056        dataLine.flush();
057    }
058
059    /**
060     * Allows a line to engage in data I/O.  If invoked on a line
061     * that is already running, this method does nothing.  Unless the data in
062     * the buffer has been flushed, the line resumes I/O starting
063     * with the first frame that was unprocessed at the time the line was
064     * stopped. When audio capture or playback starts, a
065     * <code>LineEvent.Type#START START</code> event is generated.
066     *
067     * @see #stop()
068     * @see #isRunning()
069     */
070    @Override
071    public void start() {
072        dataLine.start();
073    }
074
075    /**
076     * Stops the line.  A stopped line should cease I/O activity.
077     * If the line is open and running, however, it should retain the resources required
078     * to resume activity.  A stopped line should retain any audio data in its buffer
079     * instead of discarding it, so that upon resumption the I/O can continue where it left off,
080     * if possible.  (This doesn't guarantee that there will never be discontinuities beyond the
081     * current buffer, of course; if the stopped condition continues
082     * for too long, input or output samples might be dropped.)  If desired, the retained data can be
083     * discarded by invoking the <code>flush</code> method.
084     * When audio capture or playback stops, a <code>LineEvent.Type#STOP STOP</code> event is generated.
085     *
086     * @see #start()
087     * @see #isRunning()
088     * @see #flush()
089     */
090    @Override
091    public void stop() {
092        dataLine.stop();
093    }
094
095    /**
096     * Indicates whether the line is running.  The default is <code>false</code>.
097     * An open line begins running when the first data is presented in response to an
098     * invocation of the <code>start</code> method, and continues
099     * until presentation ceases in response to a call to <code>stop</code> or
100     * because playback completes.
101     * @return <code>true</code> if the line is running, otherwise <code>false</code>
102     * @see #start()
103     * @see #stop()
104     */
105    @Override
106    public boolean isRunning() {
107        return dataLine.isRunning();
108    }
109
110    /**
111     * Indicates whether the line is engaging in active I/O (such as playback
112     * or capture).  When an inactive line becomes active, it sends a
113     * <code>LineEvent.Type#START START</code> event to its listeners.  Similarly, when
114     * an active line becomes inactive, it sends a
115     * <code>LineEvent.Type#STOP STOP</code> event.
116     * @return <code>true</code> if the line is actively capturing or rendering
117     * sound, otherwise <code>false</code>
118     * @see #isOpen
119     * @see #addLineListener
120     * @see #removeLineListener
121     */
122    @Override
123    public boolean isActive() {
124        return dataLine.isActive();
125    }
126
127    /**
128     * Obtains the current format (encoding, sample rate, number of channels,
129     * etc.) of the data line's audio data.
130     *
131     * <p>If the line is not open and has never been opened, it returns
132     * the default format. The default format is an implementation
133     * specific audio format, or, if the <code>DataLine.Info</code>
134     * object, which was used to retrieve this <code>DataLine</code>,
135     * specifies at least one fully qualified audio format, the
136     * last one will be used as the default format. Opening the
137     * line with a specific audio format (e.g.
138     * SourceDataLine#open(AudioFormat)) will override the
139     * default format.
140     *
141     * @return current audio data format
142     * @see AudioFormat
143     */
144    @Override
145    public AudioFormat getFormat() {
146        return dataLine.getFormat();
147    }
148
149    /**
150     * Obtains the maximum number of bytes of data that will fit in the data line's
151     * internal buffer.  For a source data line, this is the size of the buffer to
152     * which data can be written.  For a target data line, it is the size of
153     * the buffer from which data can be read.  Note that
154     * the units used are bytes, but will always correspond to an integral
155     * number of sample frames of audio data.
156     *
157     * @return the size of the buffer in bytes
158     */
159    @Override
160    public int getBufferSize() {
161        return dataLine.getBufferSize();
162    }
163
164    /**
165     * Obtains the number of bytes of data currently available to the
166     * application for processing in the data line's internal buffer.  For a
167     * source data line, this is the amount of data that can be written to the
168     * buffer without blocking.  For a target data line, this is the amount of data
169     * available to be read by the application.  For a clip, this value is always
170     * 0 because the audio data is loaded into the buffer when the clip is opened,
171     * and persists without modification until the clip is closed.
172     * <p>
173     * Note that the units used are bytes, but will always
174     * correspond to an integral number of sample frames of audio data.
175     * <p>
176     * An application is guaranteed that a read or
177     * write operation of up to the number of bytes returned from
178     * <code>available()</code> will not block; however, there is no guarantee
179     * that attempts to read or write more data will block.
180     *
181     * @return the amount of data available, in bytes
182     */
183    @Override
184    public int available() {
185        return dataLine.available();
186    }
187
188    /**
189     * Obtains the current position in the audio data, in sample frames.
190     * The frame position measures the number of sample
191     * frames captured by, or rendered from, the line since it was opened.
192     * This return value will wrap around after 2^31 frames. It is recommended
193     * to use <code>getLongFramePosition</code> instead.
194     *
195     * @return the number of frames already processed since the line was opened
196     * @see #getLongFramePosition()
197     */
198    @Override
199    public int getFramePosition() {
200        return dataLine.getFramePosition();
201    }
202
203    /**
204     * Obtains the current position in the audio data, in sample frames.
205     * The frame position measures the number of sample
206     * frames captured by, or rendered from, the line since it was opened.
207     *
208     * @return the number of frames already processed since the line was opened
209     * @since 1.5
210     */
211    @Override
212    public long getLongFramePosition() {
213        return dataLine.getLongFramePosition();
214    }
215
216    /**
217     * Obtains the current position in the audio data, in microseconds.
218     * The microsecond position measures the time corresponding to the number
219     * of sample frames captured by, or rendered from, the line since it was opened.
220     * The level of precision is not guaranteed.  For example, an implementation
221     * might calculate the microsecond position from the current frame position
222     * and the audio sample frame rate.  The precision in microseconds would
223     * then be limited to the number of microseconds per sample frame.
224     *
225     * @return the number of microseconds of data processed since the line was opened
226     */
227    @Override
228    public long getMicrosecondPosition() {
229        return dataLine.getMicrosecondPosition();
230    }
231
232    /**
233     * Obtains the current volume level for the line.  This level is a measure
234     * of the signal's current amplitude, and should not be confused with the
235     * current setting of a gain control. The range is from 0.0 (silence) to
236     * 1.0 (maximum possible amplitude for the sound waveform).  The units
237     * measure linear amplitude, not decibels.
238     *
239     * @return the current amplitude of the signal in this line, or
240     * <code>AudioSystem#NOT_SPECIFIED</code>
241     */
242    @Override
243    public float getLevel() {
244        return dataLine.getLevel();
245    }
246}