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/com/sun/media/sound/DataPusher.java
38924 views
1
/*
2
* Copyright (c) 2002, 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 com.sun.media.sound;
27
28
import java.util.Arrays;
29
30
import javax.sound.sampled.*;
31
32
/**
33
* Class to write an AudioInputStream to a SourceDataLine.
34
* Was previously an inner class in various classes like JavaSoundAudioClip
35
* and sun.audio.AudioDevice.
36
* It auto-opens and closes the SourceDataLine.
37
*
38
* @author Kara Kytle
39
* @author Florian Bomers
40
*/
41
42
public final class DataPusher implements Runnable {
43
44
private static final int AUTO_CLOSE_TIME = 5000;
45
private static final boolean DEBUG = false;
46
47
private final SourceDataLine source;
48
private final AudioFormat format;
49
50
// stream as source data
51
private final AudioInputStream ais;
52
53
// byte array as source data
54
private final byte[] audioData;
55
private final int audioDataByteLength;
56
private int pos;
57
private int newPos = -1;
58
private boolean looping;
59
60
private Thread pushThread = null;
61
private int wantedState;
62
private int threadState;
63
64
private final int STATE_NONE = 0;
65
private final int STATE_PLAYING = 1;
66
private final int STATE_WAITING = 2;
67
private final int STATE_STOPPING = 3;
68
private final int STATE_STOPPED = 4;
69
private final int BUFFER_SIZE = 16384;
70
71
public DataPusher(SourceDataLine sourceLine, AudioFormat format, byte[] audioData, int byteLength) {
72
this(sourceLine, format, null, audioData, byteLength);
73
}
74
75
public DataPusher(SourceDataLine sourceLine, AudioInputStream ais) {
76
this(sourceLine, ais.getFormat(), ais, null, 0);
77
}
78
79
private DataPusher(final SourceDataLine source, final AudioFormat format,
80
final AudioInputStream ais, final byte[] audioData,
81
final int audioDataByteLength) {
82
this.source = source;
83
this.format = format;
84
this.ais = ais;
85
this.audioDataByteLength = audioDataByteLength;
86
this.audioData = audioData == null ? null : Arrays.copyOf(audioData,
87
audioData.length);
88
}
89
90
public synchronized void start() {
91
start(false);
92
}
93
94
public synchronized void start(boolean loop) {
95
if (DEBUG || Printer.debug) Printer.debug("> DataPusher.start(loop="+loop+")");
96
try {
97
if (threadState == STATE_STOPPING) {
98
// wait that the thread has finished stopping
99
if (DEBUG || Printer.trace)Printer.trace("DataPusher.start(): calling stop()");
100
stop();
101
}
102
looping = loop;
103
newPos = 0;
104
wantedState = STATE_PLAYING;
105
if (!source.isOpen()) {
106
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.open()");
107
source.open(format);
108
}
109
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.flush()");
110
source.flush();
111
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.start()");
112
source.start();
113
if (pushThread == null) {
114
if (DEBUG || Printer.debug) Printer.debug("DataPusher.start(): Starting push");
115
pushThread = JSSecurityManager.createThread(this,
116
null, // name
117
false, // daemon
118
-1, // priority
119
true); // doStart
120
}
121
notifyAll();
122
} catch (Exception e) {
123
if (DEBUG || Printer.err) e.printStackTrace();
124
}
125
if (DEBUG || Printer.debug) Printer.debug("< DataPusher.start(loop="+loop+")");
126
}
127
128
129
public synchronized void stop() {
130
if (DEBUG || Printer.debug) Printer.debug("> DataPusher.stop()");
131
if (threadState == STATE_STOPPING
132
|| threadState == STATE_STOPPED
133
|| pushThread == null) {
134
if (DEBUG || Printer.debug) Printer.debug("DataPusher.stop(): nothing to do");
135
return;
136
}
137
if (DEBUG || Printer.debug) Printer.debug("DataPusher.stop(): Stopping push");
138
139
wantedState = STATE_WAITING;
140
if (source != null) {
141
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.flush()");
142
source.flush();
143
}
144
notifyAll();
145
int maxWaitCount = 50; // 5 seconds
146
while ((maxWaitCount-- >= 0) && (threadState == STATE_PLAYING)) {
147
try {
148
wait(100);
149
} catch (InterruptedException e) { }
150
}
151
if (DEBUG || Printer.debug) Printer.debug("< DataPusher.stop()");
152
}
153
154
synchronized void close() {
155
if (source != null) {
156
if (DEBUG || Printer.trace)Printer.trace("DataPusher.close(): source.close()");
157
source.close();
158
}
159
}
160
161
/**
162
* Write data to the source data line.
163
*/
164
public void run() {
165
byte[] buffer = null;
166
boolean useStream = (ais != null);
167
if (useStream) {
168
buffer = new byte[BUFFER_SIZE];
169
} else {
170
buffer = audioData;
171
}
172
while (wantedState != STATE_STOPPING) {
173
//try {
174
if (wantedState == STATE_WAITING) {
175
// wait for 5 seconds - maybe the clip is to be played again
176
if (DEBUG || Printer.debug)Printer.debug("DataPusher.run(): waiting 5 seconds");
177
try {
178
synchronized(this) {
179
threadState = STATE_WAITING;
180
wantedState = STATE_STOPPING;
181
wait(AUTO_CLOSE_TIME);
182
}
183
} catch (InterruptedException ie) {}
184
if (DEBUG || Printer.debug)Printer.debug("DataPusher.run(): waiting finished");
185
continue;
186
}
187
if (newPos >= 0) {
188
pos = newPos;
189
newPos = -1;
190
}
191
threadState = STATE_PLAYING;
192
int toWrite = BUFFER_SIZE;
193
if (useStream) {
194
try {
195
pos = 0; // always write from beginning of buffer
196
// don't use read(byte[]), because some streams
197
// may not override that method
198
toWrite = ais.read(buffer, 0, buffer.length);
199
} catch (java.io.IOException ioe) {
200
// end of stream
201
toWrite = -1;
202
}
203
} else {
204
if (toWrite > audioDataByteLength - pos) {
205
toWrite = audioDataByteLength - pos;
206
}
207
if (toWrite == 0) {
208
toWrite = -1; // end of "stream"
209
}
210
}
211
if (toWrite < 0) {
212
if (DEBUG || Printer.debug) Printer.debug("DataPusher.run(): Found end of stream");
213
if (!useStream && looping) {
214
if (DEBUG || Printer.debug)Printer.debug("DataPusher.run(): setting pos back to 0");
215
pos = 0;
216
continue;
217
}
218
if (DEBUG || Printer.debug)Printer.debug("DataPusher.run(): calling drain()");
219
wantedState = STATE_WAITING;
220
source.drain();
221
continue;
222
}
223
if (DEBUG || Printer.debug) Printer.debug("> DataPusher.run(): Writing " + toWrite + " bytes");
224
int bytesWritten = source.write(buffer, pos, toWrite);
225
pos += bytesWritten;
226
if (DEBUG || Printer.debug) Printer.debug("< DataPusher.run(): Wrote " + bytesWritten + " bytes");
227
}
228
threadState = STATE_STOPPING;
229
if (DEBUG || Printer.debug)Printer.debug("DataPusher: closing device");
230
if (Printer.trace)Printer.trace("DataPusher: source.flush()");
231
source.flush();
232
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.stop()");
233
source.stop();
234
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.flush()");
235
source.flush();
236
if (DEBUG || Printer.trace)Printer.trace("DataPusher: source.close()");
237
source.close();
238
threadState = STATE_STOPPED;
239
synchronized (this) {
240
pushThread = null;
241
notifyAll();
242
}
243
if (DEBUG || Printer.debug)Printer.debug("DataPusher:end of thread");
244
}
245
246
} // class DataPusher
247
248