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