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/AbstractMixer.java
38924 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 com.sun.media.sound;
27
28
import java.util.Vector;
29
30
import javax.sound.sampled.Control;
31
import javax.sound.sampled.Mixer;
32
import javax.sound.sampled.Line;
33
import javax.sound.sampled.LineUnavailableException;
34
35
/**
36
* Abstract Mixer. Implements Mixer (with abstract methods) and specifies
37
* some other common methods for use by our implementation.
38
*
39
* @author Kara Kytle
40
*/
41
//$$fb 2002-07-26: let AbstractMixer be an AbstractLine and NOT an AbstractDataLine!
42
abstract class AbstractMixer extends AbstractLine implements Mixer {
43
44
// STATIC VARIABLES
45
protected static final int PCM = 0;
46
protected static final int ULAW = 1;
47
protected static final int ALAW = 2;
48
49
50
// IMMUTABLE PROPERTIES
51
52
/**
53
* Info object describing this mixer.
54
*/
55
private final Mixer.Info mixerInfo;
56
57
/**
58
* source lines provided by this mixer
59
*/
60
protected Line.Info[] sourceLineInfo;
61
62
/**
63
* target lines provided by this mixer
64
*/
65
protected Line.Info[] targetLineInfo;
66
67
/**
68
* if any line of this mixer is started
69
*/
70
private boolean started = false;
71
72
/**
73
* if this mixer had been opened manually with open()
74
* If it was, then it won't be closed automatically,
75
* only when close() is called manually.
76
*/
77
private boolean manuallyOpened = false;
78
79
80
/**
81
* Supported formats for the mixer.
82
*/
83
//$$fb DELETE
84
//protected Vector formats = new Vector();
85
86
87
// STATE VARIABLES
88
89
90
/**
91
* Source lines (ports) currently open
92
*/
93
private final Vector sourceLines = new Vector();
94
95
96
/**
97
* Target lines currently open.
98
*/
99
private final Vector targetLines = new Vector();
100
101
102
/**
103
* Constructs a new AbstractMixer.
104
* @param mixer the mixer with which this line is associated
105
* @param controls set of supported controls
106
*/
107
protected AbstractMixer(Mixer.Info mixerInfo,
108
Control[] controls,
109
Line.Info[] sourceLineInfo,
110
Line.Info[] targetLineInfo) {
111
112
// Line.Info, AbstractMixer, Control[]
113
super(new Line.Info(Mixer.class), null, controls);
114
115
// setup the line part
116
this.mixer = this;
117
if (controls == null) {
118
controls = new Control[0];
119
}
120
121
// setup the mixer part
122
this.mixerInfo = mixerInfo;
123
this.sourceLineInfo = sourceLineInfo;
124
this.targetLineInfo = targetLineInfo;
125
}
126
127
128
// MIXER METHODS
129
130
131
public final Mixer.Info getMixerInfo() {
132
return mixerInfo;
133
}
134
135
136
public final Line.Info[] getSourceLineInfo() {
137
Line.Info[] localArray = new Line.Info[sourceLineInfo.length];
138
System.arraycopy(sourceLineInfo, 0, localArray, 0, sourceLineInfo.length);
139
return localArray;
140
}
141
142
143
public final Line.Info[] getTargetLineInfo() {
144
145
Line.Info[] localArray = new Line.Info[targetLineInfo.length];
146
System.arraycopy(targetLineInfo, 0, localArray, 0, targetLineInfo.length);
147
return localArray;
148
}
149
150
151
public final Line.Info[] getSourceLineInfo(Line.Info info) {
152
153
int i;
154
Vector vec = new Vector();
155
156
for (i = 0; i < sourceLineInfo.length; i++) {
157
158
if (info.matches(sourceLineInfo[i])) {
159
vec.addElement(sourceLineInfo[i]);
160
}
161
}
162
163
Line.Info[] returnedArray = new Line.Info[vec.size()];
164
for (i = 0; i < returnedArray.length; i++) {
165
returnedArray[i] = (Line.Info)vec.elementAt(i);
166
}
167
168
return returnedArray;
169
}
170
171
172
public final Line.Info[] getTargetLineInfo(Line.Info info) {
173
174
int i;
175
Vector vec = new Vector();
176
177
for (i = 0; i < targetLineInfo.length; i++) {
178
179
if (info.matches(targetLineInfo[i])) {
180
vec.addElement(targetLineInfo[i]);
181
}
182
}
183
184
Line.Info[] returnedArray = new Line.Info[vec.size()];
185
for (i = 0; i < returnedArray.length; i++) {
186
returnedArray[i] = (Line.Info)vec.elementAt(i);
187
}
188
189
return returnedArray;
190
}
191
192
193
public final boolean isLineSupported(Line.Info info) {
194
195
int i;
196
197
for (i = 0; i < sourceLineInfo.length; i++) {
198
199
if (info.matches(sourceLineInfo[i])) {
200
return true;
201
}
202
}
203
204
for (i = 0; i < targetLineInfo.length; i++) {
205
206
if (info.matches(targetLineInfo[i])) {
207
return true;
208
}
209
}
210
211
return false;
212
}
213
214
215
public abstract Line getLine(Line.Info info) throws LineUnavailableException;
216
217
public abstract int getMaxLines(Line.Info info);
218
219
protected abstract void implOpen() throws LineUnavailableException;
220
protected abstract void implStart();
221
protected abstract void implStop();
222
protected abstract void implClose();
223
224
225
public final Line[] getSourceLines() {
226
227
Line[] localLines;
228
229
synchronized(sourceLines) {
230
231
localLines = new Line[sourceLines.size()];
232
233
for (int i = 0; i < localLines.length; i++) {
234
localLines[i] = (Line)sourceLines.elementAt(i);
235
}
236
}
237
238
return localLines;
239
}
240
241
242
public final Line[] getTargetLines() {
243
244
Line[] localLines;
245
246
synchronized(targetLines) {
247
248
localLines = new Line[targetLines.size()];
249
250
for (int i = 0; i < localLines.length; i++) {
251
localLines[i] = (Line)targetLines.elementAt(i);
252
}
253
}
254
255
return localLines;
256
}
257
258
259
/**
260
* Default implementation always throws an exception.
261
*/
262
public final void synchronize(Line[] lines, boolean maintainSync) {
263
throw new IllegalArgumentException("Synchronization not supported by this mixer.");
264
}
265
266
267
/**
268
* Default implementation always throws an exception.
269
*/
270
public final void unsynchronize(Line[] lines) {
271
throw new IllegalArgumentException("Synchronization not supported by this mixer.");
272
}
273
274
275
/**
276
* Default implementation always returns false.
277
*/
278
public final boolean isSynchronizationSupported(Line[] lines,
279
boolean maintainSync) {
280
return false;
281
}
282
283
284
// OVERRIDES OF ABSTRACT DATA LINE METHODS
285
286
/**
287
* This implementation tries to open the mixer with its current format and buffer size settings.
288
*/
289
public final synchronized void open() throws LineUnavailableException {
290
open(true);
291
}
292
293
/**
294
* This implementation tries to open the mixer with its current format and buffer size settings.
295
*/
296
final synchronized void open(boolean manual) throws LineUnavailableException {
297
if (Printer.trace) Printer.trace(">> AbstractMixer: open()");
298
if (!isOpen()) {
299
implOpen();
300
// if the mixer is not currently open, set open to true and send event
301
setOpen(true);
302
if (manual) {
303
manuallyOpened = true;
304
}
305
}
306
307
if (Printer.trace) Printer.trace("<< AbstractMixer: open() succeeded");
308
}
309
310
311
// METHOD FOR INTERNAL IMPLEMENTATION USE
312
313
314
/**
315
* The default implementation of this method just determines whether
316
* this line is a source or target line, calls open(no-arg) on the
317
* mixer, and adds the line to the appropriate vector.
318
* The mixer may be opened at a format different than the line's
319
* format if it is a DataLine.
320
*/
321
final synchronized void open(Line line) throws LineUnavailableException {
322
323
if (Printer.trace) Printer.trace(">> AbstractMixer: open(line = " + line + ")");
324
325
// $$kk: 06.11.99: ignore ourselves for now
326
if (this.equals(line)) {
327
if (Printer.trace) Printer.trace("<< AbstractMixer: open(" + line + ") nothing done");
328
return;
329
}
330
331
// source line?
332
if (isSourceLine(line.getLineInfo())) {
333
if (! sourceLines.contains(line) ) {
334
// call the no-arg open method for the mixer; it should open at its
335
// default format if it is not open yet
336
open(false);
337
338
// we opened successfully! add the line to the list
339
sourceLines.addElement(line);
340
}
341
} else {
342
// target line?
343
if(isTargetLine(line.getLineInfo())) {
344
if (! targetLines.contains(line) ) {
345
// call the no-arg open method for the mixer; it should open at its
346
// default format if it is not open yet
347
open(false);
348
349
// we opened successfully! add the line to the list
350
targetLines.addElement(line);
351
}
352
} else {
353
if (Printer.err) Printer.err("Unknown line received for AbstractMixer.open(Line): " + line);
354
}
355
}
356
357
if (Printer.trace) Printer.trace("<< AbstractMixer: open(" + line + ") completed");
358
}
359
360
361
/**
362
* Removes this line from the list of open source lines and
363
* open target lines, if it exists in either.
364
* If the list is now empty, closes the mixer.
365
*/
366
final synchronized void close(Line line) {
367
368
if (Printer.trace) Printer.trace(">> AbstractMixer: close(" + line + ")");
369
370
// $$kk: 06.11.99: ignore ourselves for now
371
if (this.equals(line)) {
372
if (Printer.trace) Printer.trace("<< AbstractMixer: close(" + line + ") nothing done");
373
return;
374
}
375
376
sourceLines.removeElement(line);
377
targetLines.removeElement(line);
378
379
if (Printer.debug) Printer.debug("AbstractMixer: close(line): sourceLines.size() now: " + sourceLines.size());
380
if (Printer.debug) Printer.debug("AbstractMixer: close(line): targetLines.size() now: " + targetLines.size());
381
382
383
if (sourceLines.isEmpty() && targetLines.isEmpty() && !manuallyOpened) {
384
if (Printer.trace) Printer.trace("AbstractMixer: close(" + line + "): need to close the mixer");
385
close();
386
}
387
388
if (Printer.trace) Printer.trace("<< AbstractMixer: close(" + line + ") succeeded");
389
}
390
391
392
/**
393
* Close all lines and then close this mixer.
394
*/
395
public final synchronized void close() {
396
if (Printer.trace) Printer.trace(">> AbstractMixer: close()");
397
if (isOpen()) {
398
// close all source lines
399
Line[] localLines = getSourceLines();
400
for (int i = 0; i<localLines.length; i++) {
401
localLines[i].close();
402
}
403
404
// close all target lines
405
localLines = getTargetLines();
406
for (int i = 0; i<localLines.length; i++) {
407
localLines[i].close();
408
}
409
410
implClose();
411
412
// set the open state to false and send events
413
setOpen(false);
414
}
415
manuallyOpened = false;
416
if (Printer.trace) Printer.trace("<< AbstractMixer: close() succeeded");
417
}
418
419
/**
420
* Starts the mixer.
421
*/
422
final synchronized void start(Line line) {
423
424
if (Printer.trace) Printer.trace(">> AbstractMixer: start(" + line + ")");
425
426
// $$kk: 06.11.99: ignore ourselves for now
427
if (this.equals(line)) {
428
if (Printer.trace) Printer.trace("<< AbstractMixer: start(" + line + ") nothing done");
429
return;
430
}
431
432
// we just start the mixer regardless of anything else here.
433
if (!started) {
434
if (Printer.debug) Printer.debug("AbstractMixer: start(line): starting the mixer");
435
implStart();
436
started = true;
437
}
438
439
if (Printer.trace) Printer.trace("<< AbstractMixer: start(" + line + ") succeeded");
440
}
441
442
443
/**
444
* Stops the mixer if this was the last running line.
445
*/
446
final synchronized void stop(Line line) {
447
448
if (Printer.trace) Printer.trace(">> AbstractMixer: stop(" + line + ")");
449
450
// $$kk: 06.11.99: ignore ourselves for now
451
if (this.equals(line)) {
452
if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") nothing done");
453
return;
454
}
455
456
Vector localSourceLines = (Vector)sourceLines.clone();
457
for (int i = 0; i < localSourceLines.size(); i++) {
458
459
// if any other open line is running, return
460
461
// this covers clips and source data lines
462
if (localSourceLines.elementAt(i) instanceof AbstractDataLine) {
463
AbstractDataLine sourceLine = (AbstractDataLine)localSourceLines.elementAt(i);
464
if ( sourceLine.isStartedRunning() && (!sourceLine.equals(line)) ) {
465
if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") found running sourceLine: " + sourceLine);
466
return;
467
}
468
}
469
}
470
471
Vector localTargetLines = (Vector)targetLines.clone();
472
for (int i = 0; i < localTargetLines.size(); i++) {
473
474
// if any other open line is running, return
475
// this covers target data lines
476
if (localTargetLines.elementAt(i) instanceof AbstractDataLine) {
477
AbstractDataLine targetLine = (AbstractDataLine)localTargetLines.elementAt(i);
478
if ( targetLine.isStartedRunning() && (!targetLine.equals(line)) ) {
479
if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") found running targetLine: " + targetLine);
480
return;
481
}
482
}
483
}
484
485
// otherwise, stop
486
if (Printer.debug) Printer.debug("AbstractMixer: stop(line): stopping the mixer");
487
started = false;
488
implStop();
489
490
if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") succeeded");
491
}
492
493
494
495
/**
496
* Determines whether this is a source line for this mixer.
497
* Right now this just checks whether it's supported, but should
498
* check whether it actually belongs to this mixer....
499
*/
500
final boolean isSourceLine(Line.Info info) {
501
502
for (int i = 0; i < sourceLineInfo.length; i++) {
503
if (info.matches(sourceLineInfo[i])) {
504
return true;
505
}
506
}
507
508
return false;
509
}
510
511
512
/**
513
* Determines whether this is a target line for this mixer.
514
* Right now this just checks whether it's supported, but should
515
* check whether it actually belongs to this mixer....
516
*/
517
final boolean isTargetLine(Line.Info info) {
518
519
for (int i = 0; i < targetLineInfo.length; i++) {
520
if (info.matches(targetLineInfo[i])) {
521
return true;
522
}
523
}
524
525
return false;
526
}
527
528
529
/**
530
* Returns the first complete Line.Info object it finds that
531
* matches the one specified, or null if no matching Line.Info
532
* object is found.
533
*/
534
final Line.Info getLineInfo(Line.Info info) {
535
if (info == null) {
536
return null;
537
}
538
// $$kk: 05.31.99: need to change this so that
539
// the format and buffer size get set in the
540
// returned info object for data lines??
541
for (int i = 0; i < sourceLineInfo.length; i++) {
542
if (info.matches(sourceLineInfo[i])) {
543
return sourceLineInfo[i];
544
}
545
}
546
547
for (int i = 0; i < targetLineInfo.length; i++) {
548
if (info.matches(targetLineInfo[i])) {
549
return targetLineInfo[i];
550
}
551
}
552
553
return null;
554
}
555
556
}
557
558