History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/audio/AudioDevice.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/audio/AudioDevice.java+429−0
@@ -0,0 +1,429 @@
1+/*
2+ * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.audio;
27+
28+import java.util.Hashtable;
29+import java.util.Vector;
30+import java.util.Enumeration;
31+import java.io.IOException;
32+import java.io.InputStream;
33+import java.io.BufferedInputStream;
34+import java.io.OutputStream;
35+import java.io.ByteArrayInputStream;
36+
37+import javax.sound.sampled.*;
38+import javax.sound.midi.*;
39+import com.sun.media.sound.DataPusher;
40+import com.sun.media.sound.Toolkit;
41+
42+/**
43+ * This class provides an interface to the Headspace Audio engine through
44+ * the Java Sound API.
45+ *
46+ * This class emulates systems with multiple audio channels, mixing
47+ * multiple streams for the workstation's single-channel device.
48+ *
49+ * @see AudioData
50+ * @see AudioDataStream
51+ * @see AudioStream
52+ * @see AudioStreamSequence
53+ * @see ContinuousAudioDataStream
54+ * @author David Rivas
55+ * @author Kara Kytle
56+ * @author Jan Borgersen
57+ * @author Florian Bomers
58+ */
59+
60+public class
61+ AudioDevice {
62+
63+ private boolean DEBUG = false /*true*/ ;
64+
65+ /** Hashtable of audio clips / input streams. */
66+ private Hashtable clipStreams;
67+
68+ private Vector infos;
69+
70+ /** Are we currently playing audio? */
71+ private boolean playing = false;
72+
73+ /** Handle to the JS audio mixer. */
74+ private Mixer mixer = null;
75+
76+
77+
78+ /**
79+ * The default audio player. This audio player is initialized
80+ * automatically.
81+ */
82+ public static final AudioDevice device = new AudioDevice();
83+
84+ /**
85+ * Create an AudioDevice instance.
86+ */
87+ private AudioDevice() {
88+
89+ clipStreams = new Hashtable();
90+ infos = new Vector();
91+ }
92+
93+
94+ private synchronized void startSampled( AudioInputStream as,
95+ InputStream in ) throws UnsupportedAudioFileException,
96+ LineUnavailableException {
97+
98+ Info info = null;
99+ DataPusher datapusher = null;
100+ DataLine.Info lineinfo = null;
101+ SourceDataLine sourcedataline = null;
102+
103+ // if ALAW or ULAW, we must convert....
104+ as = Toolkit.getPCMConvertedAudioInputStream(as);
105+
106+ if( as==null ) {
107+ // could not convert
108+ return;
109+ }
110+
111+ lineinfo = new DataLine.Info(SourceDataLine.class,
112+ as.getFormat());
113+ if( !(AudioSystem.isLineSupported(lineinfo))) {
114+ return;
115+ }
116+ sourcedataline = (SourceDataLine)AudioSystem.getLine(lineinfo);
117+ datapusher = new DataPusher(sourcedataline, as);
118+
119+ info = new Info( null, in, datapusher );
120+ infos.addElement( info );
121+
122+ datapusher.start();
123+ }
124+
125+ private synchronized void startMidi( InputStream bis,
126+ InputStream in ) throws InvalidMidiDataException,
127+ MidiUnavailableException {
128+
129+ Sequencer sequencer = null;
130+ Info info = null;
131+
132+ sequencer = MidiSystem.getSequencer( );
133+ sequencer.open();
134+ try {
135+ sequencer.setSequence( bis );
136+ } catch( IOException e ) {
137+ throw new InvalidMidiDataException( e.getMessage() );
138+ }
139+
140+ info = new Info( sequencer, in, null );
141+
142+ infos.addElement( info );
143+
144+ // fix for bug 4302884: Audio device is not released when AudioClip stops
145+ sequencer.addMetaEventListener(info);
146+
147+ sequencer.start();
148+
149+ }
150+
151+
152+
153+ /**
154+ * Open an audio channel.
155+ */
156+ public synchronized void openChannel(InputStream in) {
157+
158+
159+ if(DEBUG) {
160+ System.out.println("AudioDevice: openChannel");
161+ System.out.println("input stream =" + in);
162+ }
163+
164+ Info info = null;
165+
166+ // is this already playing? if so, then just return
167+ for(int i=0; i<infos.size(); i++) {
168+ info = (AudioDevice.Info)infos.elementAt(i);
169+ if( info.in == in ) {
170+
171+ return;
172+ }
173+ }
174+
175+
176+ AudioInputStream as = null;
177+
178+ if( in instanceof AudioStream ) {
179+
180+ if ( ((AudioStream)in).midiformat != null ) {
181+
182+ // it's a midi file
183+ try {
184+ startMidi( ((AudioStream)in).stream, in );
185+ } catch (Exception e) {
186+ return;
187+ }
188+
189+
190+ } else if( ((AudioStream)in).ais != null ) {
191+
192+ // it's sampled audio
193+ try {
194+ startSampled( ((AudioStream)in).ais, in );
195+ } catch (Exception e) {
196+ return;
197+ }
198+
199+ }
200+ } else if (in instanceof AudioDataStream ) {
201+ if (in instanceof ContinuousAudioDataStream) {
202+ try {
203+ AudioInputStream ais = new AudioInputStream(in,
204+ ((AudioDataStream)in).getAudioData().format,
205+ AudioSystem.NOT_SPECIFIED);
206+ startSampled(ais, in );
207+ } catch (Exception e) {
208+ return;
209+ }
210+ }
211+ else {
212+ try {
213+ AudioInputStream ais = new AudioInputStream(in,
214+ ((AudioDataStream)in).getAudioData().format,
215+ ((AudioDataStream)in).getAudioData().buffer.length);
216+ startSampled(ais, in );
217+ } catch (Exception e) {
218+ return;
219+ }
220+ }
221+ } else {
222+ BufferedInputStream bis = new BufferedInputStream( in, 1024 );
223+
224+ try {
225+
226+ try {
227+ as = AudioSystem.getAudioInputStream(bis);
228+ } catch(IOException ioe) {
229+ return;
230+ }
231+
232+ startSampled( as, in );
233+
234+ } catch( UnsupportedAudioFileException e ) {
235+
236+ try {
237+ try {
238+ MidiFileFormat mff =
239+ MidiSystem.getMidiFileFormat( bis );
240+ } catch(IOException ioe1) {
241+ return;
242+ }
243+
244+ startMidi( bis, in );
245+
246+
247+ } catch( InvalidMidiDataException e1 ) {
248+
249+ // $$jb:08.01.99: adding this section to make some of our other
250+ // legacy classes work.....
251+ // not MIDI either, special case handling for all others
252+
253+ AudioFormat defformat = new AudioFormat( AudioFormat.Encoding.ULAW,
254+ 8000, 8, 1, 1, 8000, true );
255+ try {
256+ AudioInputStream defaif = new AudioInputStream( bis,
257+ defformat, AudioSystem.NOT_SPECIFIED);
258+ startSampled( defaif, in );
259+ } catch (UnsupportedAudioFileException es) {
260+ return;
261+ } catch (LineUnavailableException es2) {
262+ return;
263+ }
264+
265+ } catch( MidiUnavailableException e2 ) {
266+
267+ // could not open sequence
268+ return;
269+ }
270+
271+ } catch( LineUnavailableException e ) {
272+
273+ return;
274+ }
275+ }
276+
277+ // don't forget adjust for a new stream.
278+ notify();
279+ }
280+
281+
282+ /**
283+ * Close an audio channel.
284+ */
285+ public synchronized void closeChannel(InputStream in) {
286+
287+ if(DEBUG) {
288+ System.out.println("AudioDevice.closeChannel");
289+ }
290+
291+ if (in == null) return; // can't go anywhere here!
292+
293+ Info info;
294+
295+ for(int i=0; i<infos.size(); i++) {
296+
297+ info = (AudioDevice.Info)infos.elementAt(i);
298+
299+ if( info.in == in ) {
300+
301+ if( info.sequencer != null ) {
302+
303+ info.sequencer.stop();
304+ //info.sequencer.close();
305+ infos.removeElement( info );
306+
307+ } else if( info.datapusher != null ) {
308+
309+ info.datapusher.stop();
310+ infos.removeElement( info );
311+ }
312+ }
313+ }
314+ notify();
315+ }
316+
317+
318+ /**
319+ * Open the device (done automatically)
320+ */
321+ public synchronized void open() {
322+
323+ // $$jb: 06.24.99: This is done on a per-stream
324+ // basis using the new JS API now.
325+ }
326+
327+
328+ /**
329+ * Close the device (done automatically)
330+ */
331+ public synchronized void close() {
332+
333+ // $$jb: 06.24.99: This is done on a per-stream
334+ // basis using the new JS API now.
335+
336+ }
337+
338+
339+ /**
340+ * Play open audio stream(s)
341+ */
342+ public void play() {
343+
344+ // $$jb: 06.24.99: Holdover from old architechture ...
345+ // we now open/close the devices as needed on a per-stream
346+ // basis using the JavaSound API.
347+
348+ if (DEBUG) {
349+ System.out.println("exiting play()");
350+ }
351+ }
352+
353+ /**
354+ * Close streams
355+ */
356+ public synchronized void closeStreams() {
357+
358+ Info info;
359+
360+ for(int i=0; i<infos.size(); i++) {
361+
362+ info = (AudioDevice.Info)infos.elementAt(i);
363+
364+ if( info.sequencer != null ) {
365+
366+ info.sequencer.stop();
367+ info.sequencer.close();
368+ infos.removeElement( info );
369+
370+ } else if( info.datapusher != null ) {
371+
372+ info.datapusher.stop();
373+ infos.removeElement( info );
374+ }
375+ }
376+
377+
378+ if (DEBUG) {
379+ System.err.println("Audio Device: Streams all closed.");
380+ }
381+ // Empty the hash table.
382+ clipStreams = new Hashtable();
383+ infos = new Vector();
384+ }
385+
386+ /**
387+ * Number of channels currently open.
388+ */
389+ public int openChannels() {
390+ return infos.size();
391+ }
392+
393+ /**
394+ * Make the debug info print out.
395+ */
396+ void setVerbose(boolean v) {
397+ DEBUG = v;
398+ }
399+
400+
401+
402+
403+
404+
405+ // INFO CLASS
406+
407+ class Info implements MetaEventListener {
408+
409+ Sequencer sequencer;
410+ InputStream in;
411+ DataPusher datapusher;
412+
413+ Info( Sequencer sequencer, InputStream in, DataPusher datapusher ) {
414+
415+ this.sequencer = sequencer;
416+ this.in = in;
417+ this.datapusher = datapusher;
418+ }
419+
420+ public void meta(MetaMessage event) {
421+ if (event.getType() == 47 && sequencer != null) {
422+ sequencer.close();
423+ }
424+ }
425+ }
426+
427+
428+
429+}