Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/sound/sampled/DirectAudio/bug6372428.java
38855 views
1
/*
2
* Copyright (c) 2006, 2016, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import javax.sound.sampled.AudioFormat;
25
import javax.sound.sampled.AudioSystem;
26
import javax.sound.sampled.DataLine;
27
import javax.sound.sampled.LineUnavailableException;
28
import javax.sound.sampled.SourceDataLine;
29
import javax.sound.sampled.TargetDataLine;
30
31
/*
32
* @test
33
* @bug 6372428
34
* @summary playback and capture doesn't interrupt after terminating thread that
35
* calls start()
36
* @run main bug6372428
37
* @key headful
38
*/
39
public class bug6372428 {
40
public bug6372428() {
41
}
42
43
public static void main(final String[] args) {
44
bug6372428 pThis = new bug6372428();
45
boolean failed1 = false;
46
boolean failed2 = false;
47
log("");
48
log("****************************************************************");
49
log("*** Playback Test");
50
log("****************************************************************");
51
log("");
52
try {
53
pThis.testPlayback();
54
} catch (IllegalArgumentException | LineUnavailableException e) {
55
System.out.println("Playback test is not applicable. Skipped");
56
} catch (Exception ex) {
57
ex.printStackTrace();
58
failed1 = true;
59
}
60
log("");
61
log("");
62
log("****************************************************************");
63
log("*** Capture Test");
64
log("****************************************************************");
65
log("");
66
try {
67
pThis.testRecord();
68
} catch (IllegalArgumentException | LineUnavailableException e) {
69
System.out.println("Record test is not applicable. Skipped");
70
} catch (Exception ex) {
71
ex.printStackTrace();
72
failed2 = true;
73
}
74
log("");
75
log("");
76
log("****************************************************************");
77
if (failed1 || failed2) {
78
String s = "";
79
if (failed1 && failed2)
80
s = "playback and capture";
81
else if (failed1)
82
s = "playback only";
83
else
84
s = "capture only";
85
throw new RuntimeException("Test FAILED (" + s + ")");
86
}
87
log("*** All tests passed successfully.");
88
}
89
90
final static int DATA_LENGTH = 15; // in seconds
91
final static int PLAYTHREAD_DELAY = 5; // in seconds
92
93
// playback test classes/routines
94
95
class PlayThread extends Thread {
96
SourceDataLine line;
97
public PlayThread(SourceDataLine line) {
98
this.line = line;
99
this.setDaemon(true);
100
}
101
102
public void run() {
103
log("PlayThread: starting...");
104
line.start();
105
log("PlayThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
106
delay(PLAYTHREAD_DELAY * 1000);
107
log("PlayThread: exiting...");
108
}
109
}
110
111
class WriteThread extends Thread {
112
SourceDataLine line;
113
byte[] data;
114
volatile int remaining;
115
volatile boolean stopRequested = false;
116
public WriteThread(SourceDataLine line, byte[] data) {
117
this.line = line;
118
this.data = data;
119
remaining = data.length;
120
this.setDaemon(true);
121
}
122
123
public void run() {
124
while (remaining > 0 && !stopRequested) {
125
int avail = line.available();
126
if (avail > 0) {
127
if (avail > remaining)
128
avail = remaining;
129
int written = line.write(data, data.length - remaining, avail);
130
remaining -= written;
131
log("WriteThread: " + written + " bytes written");
132
} else {
133
delay(100);
134
}
135
}
136
if (remaining == 0) {
137
log("WriteThread: all data has been written, draining");
138
line.drain();
139
} else {
140
log("WriteThread: stop requested");
141
}
142
log("WriteThread: stopping");
143
line.stop();
144
log("WriteThread: exiting");
145
}
146
147
public boolean isCompleted() {
148
return (remaining <= 0);
149
}
150
151
public void requestStop() {
152
stopRequested = true;
153
}
154
}
155
156
void testPlayback() throws LineUnavailableException {
157
// prepare audio data
158
AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
159
byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
160
161
// create & open source data line
162
//SourceDataLine line = AudioSystem.getSourceDataLine(format);
163
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
164
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
165
166
line.open(format);
167
168
// start write data thread
169
WriteThread p1 = new WriteThread(line, soundData);
170
p1.start();
171
172
// start line
173
PlayThread p2 = new PlayThread(line);
174
p2.start();
175
176
// monitor line
177
long lineTime1 = line.getMicrosecondPosition() / 1000;
178
long realTime1 = currentTimeMillis();
179
while (true) {
180
delay(500);
181
if (!line.isActive()) {
182
log("audio data played completely");
183
break;
184
}
185
long lineTime2 = line.getMicrosecondPosition() / 1000;
186
long realTime2 = currentTimeMillis();
187
long dLineTime = lineTime2 - lineTime1;
188
long dRealTime = realTime2 - realTime1;
189
log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
190
if (dLineTime < 0) {
191
throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
192
}
193
if (dRealTime < 450) {
194
// delay() has been interrupted?
195
continue;
196
}
197
lineTime1 = lineTime2;
198
realTime1 = realTime2;
199
}
200
}
201
202
203
// recording test classes/routines
204
205
class RecordThread extends Thread {
206
TargetDataLine line;
207
public RecordThread(TargetDataLine line) {
208
this.line = line;
209
this.setDaemon(true);
210
}
211
212
public void run() {
213
log("RecordThread: starting...");
214
line.start();
215
log("RecordThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
216
delay(PLAYTHREAD_DELAY * 1000);
217
log("RecordThread: exiting...");
218
}
219
}
220
221
class ReadThread extends Thread {
222
TargetDataLine line;
223
byte[] data;
224
volatile int remaining;
225
public ReadThread(TargetDataLine line, byte[] data) {
226
this.line = line;
227
this.data = data;
228
remaining = data.length;
229
this.setDaemon(true);
230
}
231
232
public void run() {
233
log("ReadThread: buffer size is " + data.length + " bytes");
234
delay(200);
235
while ((remaining > 0) && line.isOpen()) {
236
int avail = line.available();
237
if (avail > 0) {
238
if (avail > remaining)
239
avail = remaining;
240
int read = line.read(data, data.length - remaining, avail);
241
remaining -= read;
242
log("ReadThread: " + read + " bytes read");
243
} else {
244
delay(100);
245
}
246
if (remaining <= 0) {
247
log("ReadThread: record buffer is full, exiting");
248
break;
249
}
250
}
251
if (remaining > 0) {
252
log("ReadThread: line has been stopped, exiting");
253
}
254
}
255
256
public int getCount() {
257
return data.length - remaining;
258
}
259
public boolean isCompleted() {
260
return (remaining <= 0);
261
}
262
}
263
264
void testRecord() throws LineUnavailableException {
265
// prepare audio data
266
AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
267
268
// create & open target data line
269
//TargetDataLine line = AudioSystem.getTargetDataLine(format);
270
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
271
TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info);
272
273
line.open(format);
274
275
// start read data thread
276
byte[] data = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
277
ReadThread p1 = new ReadThread(line, data);
278
p1.start();
279
280
// start line
281
//new RecordThread(line).start();
282
RecordThread p2 = new RecordThread(line);
283
p2.start();
284
285
// monitor line
286
long endTime = currentTimeMillis() + DATA_LENGTH * 1000;
287
288
long realTime1 = currentTimeMillis();
289
long lineTime1 = line.getMicrosecondPosition() / 1000;
290
291
while (realTime1 < endTime && !p1.isCompleted()) {
292
delay(100);
293
long lineTime2 = line.getMicrosecondPosition() / 1000;
294
long realTime2 = currentTimeMillis();
295
long dLineTime = lineTime2 - lineTime1;
296
long dRealTime = realTime2 - realTime1;
297
log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
298
if (dLineTime < 0) {
299
line.stop();
300
line.close();
301
throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
302
}
303
if (dRealTime < 450) {
304
// delay() has been interrupted?
305
continue;
306
}
307
lineTime1 = lineTime2;
308
realTime1 = realTime2;
309
}
310
log("stopping line...");
311
line.stop();
312
line.close();
313
314
/*
315
log("");
316
log("");
317
log("");
318
log("recording completed, delaying 5 sec");
319
log("recorded " + p1.getCount() + " bytes, " + DATA_LENGTH + " seconds: " + (p1.getCount() * 8 / DATA_LENGTH) + " bit/sec");
320
log("");
321
log("");
322
log("");
323
delay(5000);
324
log("starting playing...");
325
playRecorded(format, data);
326
*/
327
}
328
329
void playRecorded(AudioFormat format, byte[] data) throws Exception {
330
//SourceDataLine line = AudioSystem.getSourceDataLine(format);
331
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
332
SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
333
334
line.open();
335
line.start();
336
337
int remaining = data.length;
338
while (remaining > 0) {
339
int avail = line.available();
340
if (avail > 0) {
341
if (avail > remaining)
342
avail = remaining;
343
int written = line.write(data, data.length - remaining, avail);
344
remaining -= written;
345
log("Playing: " + written + " bytes written");
346
} else {
347
delay(100);
348
}
349
}
350
351
line.drain();
352
line.stop();
353
}
354
355
// helper routines
356
static long startTime = currentTimeMillis();
357
static long currentTimeMillis() {
358
//return System.nanoTime() / 1000000L;
359
return System.currentTimeMillis();
360
}
361
static void log(String s) {
362
long time = currentTimeMillis() - startTime;
363
long ms = time % 1000;
364
time /= 1000;
365
long sec = time % 60;
366
time /= 60;
367
long min = time % 60;
368
time /= 60;
369
System.out.println(""
370
+ (time < 10 ? "0" : "") + time
371
+ ":" + (min < 10 ? "0" : "") + min
372
+ ":" + (sec < 10 ? "0" : "") + sec
373
+ "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
374
+ " (" + Thread.currentThread().getName() + ") " + s);
375
}
376
static void delay(int millis) {
377
try {
378
Thread.sleep(millis);
379
} catch (InterruptedException e) {}
380
}
381
}
382
383