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