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