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.
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<Line> sourceLines = new Vector<>();
94
95
96 /**
97 * Target lines currently open.
98 */
99 private final Vector<Line> 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<Line.Info> 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] = 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<Line.Info> 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] = 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] = 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] = 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) ) {
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 }
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 @SuppressWarnings("unchecked")
457 Vector<Line> localSourceLines = (Vector<Line>)sourceLines.clone();
458 for (int i = 0; i < localSourceLines.size(); i++) {
459
460 // if any other open line is running, return
461
462 // this covers clips and source data lines
475
476 // if any other open line is running, return
477 // this covers target data lines
478 if (localTargetLines.elementAt(i) instanceof AbstractDataLine) {
479 AbstractDataLine targetLine = (AbstractDataLine)localTargetLines.elementAt(i);
480 if ( targetLine.isStartedRunning() && (!targetLine.equals(line)) ) {
481 if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") found running targetLine: " + targetLine);
482 return;
483 }
484 }
485 }
486
487 // otherwise, stop
488 if (Printer.debug) Printer.debug("AbstractMixer: stop(line): stopping the mixer");
489 started = false;
490 implStop();
491
492 if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") succeeded");
493 }
494
495
496
497 /**
498 * Determines whether this is a source line for this mixer.
499 * Right now this just checks whether it's supported, but should
500 * check whether it actually belongs to this mixer....
501 */
502 final boolean isSourceLine(Line.Info info) {
503
504 for (int i = 0; i < sourceLineInfo.length; i++) {
505 if (info.matches(sourceLineInfo[i])) {
506 return true;
507 }
508 }
509
510 return false;
511 }
512
513
514 /**
515 * Determines whether this is a target line for this mixer.
516 * Right now this just checks whether it's supported, but should
517 * check whether it actually belongs to this mixer....
518 */
519 final boolean isTargetLine(Line.Info info) {
520
521 for (int i = 0; i < targetLineInfo.length; i++) {
522 if (info.matches(targetLineInfo[i])) {
523 return true;
524 }
525 }
526
527 return false;
528 }
529
530
531 /**
532 * Returns the first complete Line.Info object it finds that
533 * matches the one specified, or null if no matching Line.Info
534 * object is found.
535 */
536 final Line.Info getLineInfo(Line.Info info) {
537 if (info == null) {
538 return null;
539 }
540 // $$kk: 05.31.99: need to change this so that
541 // the format and buffer size get set in the
542 // returned info object for data lines??
543 for (int i = 0; i < sourceLineInfo.length; i++) {
544 if (info.matches(sourceLineInfo[i])) {
545 return sourceLineInfo[i];
546 }
547 }
548
549 for (int i = 0; i < targetLineInfo.length; i++) {
550 if (info.matches(targetLineInfo[i])) {
551 return targetLineInfo[i];
552 }
553 }
554
555 return null;
556 }
557
558 }
|
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.
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 mixer 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 (Printer.trace) Printer.trace(">> AbstractMixer: open()");
286 if (!isOpen()) {
287 implOpen();
288 // if the mixer is not currently open, set open to true and send event
289 setOpen(true);
290 if (manual) {
291 manuallyOpened = true;
292 }
293 }
294
295 if (Printer.trace) Printer.trace("<< AbstractMixer: open() succeeded");
296 }
297
298 // METHOD FOR INTERNAL IMPLEMENTATION USE
299
300 /**
301 * The default implementation of this method just determines whether
302 * this line is a source or target line, calls open(no-arg) on the
303 * mixer, and adds the line to the appropriate vector.
304 * The mixer may be opened at a format different than the line's
305 * format if it is a DataLine.
306 */
307 final synchronized void open(Line line) throws LineUnavailableException {
308
309 if (Printer.trace) Printer.trace(">> AbstractMixer: open(line = " + line + ")");
310
311 // $$kk: 06.11.99: ignore ourselves for now
312 if (this.equals(line)) {
313 if (Printer.trace) Printer.trace("<< AbstractMixer: open(" + line + ") nothing done");
314 return;
315 }
316
317 // source line?
318 if (isSourceLine(line.getLineInfo())) {
319 if (! sourceLines.contains(line) ) {
326 }
327 } else {
328 // target line?
329 if(isTargetLine(line.getLineInfo())) {
330 if (! targetLines.contains(line) ) {
331 // call the no-arg open method for the mixer; it should open at its
332 // default format if it is not open yet
333 open(false);
334
335 // we opened successfully! add the line to the list
336 targetLines.addElement(line);
337 }
338 } else {
339 if (Printer.err) Printer.err("Unknown line received for AbstractMixer.open(Line): " + line);
340 }
341 }
342
343 if (Printer.trace) Printer.trace("<< AbstractMixer: open(" + line + ") completed");
344 }
345
346 /**
347 * Removes this line from the list of open source lines and
348 * open target lines, if it exists in either.
349 * If the list is now empty, closes the mixer.
350 */
351 final synchronized void close(Line line) {
352
353 if (Printer.trace) Printer.trace(">> AbstractMixer: close(" + line + ")");
354
355 // $$kk: 06.11.99: ignore ourselves for now
356 if (this.equals(line)) {
357 if (Printer.trace) Printer.trace("<< AbstractMixer: close(" + line + ") nothing done");
358 return;
359 }
360
361 sourceLines.removeElement(line);
362 targetLines.removeElement(line);
363
364 if (Printer.debug) Printer.debug("AbstractMixer: close(line): sourceLines.size() now: " + sourceLines.size());
365 if (Printer.debug) Printer.debug("AbstractMixer: close(line): targetLines.size() now: " + targetLines.size());
366
367
368 if (sourceLines.isEmpty() && targetLines.isEmpty() && !manuallyOpened) {
369 if (Printer.trace) Printer.trace("AbstractMixer: close(" + line + "): need to close the mixer");
370 close();
371 }
372
373 if (Printer.trace) Printer.trace("<< AbstractMixer: close(" + line + ") succeeded");
374 }
375
376 /**
377 * Close all lines and then close this mixer.
378 */
379 @Override
380 public final synchronized void close() {
381 if (Printer.trace) Printer.trace(">> AbstractMixer: close()");
382 if (isOpen()) {
383 // close all source lines
384 Line[] localLines = getSourceLines();
385 for (int i = 0; i<localLines.length; i++) {
386 localLines[i].close();
387 }
388
389 // close all target lines
390 localLines = getTargetLines();
391 for (int i = 0; i<localLines.length; i++) {
392 localLines[i].close();
393 }
394
395 implClose();
396
397 // set the open state to false and send events
398 setOpen(false);
399 }
407 final synchronized void start(Line line) {
408
409 if (Printer.trace) Printer.trace(">> AbstractMixer: start(" + line + ")");
410
411 // $$kk: 06.11.99: ignore ourselves for now
412 if (this.equals(line)) {
413 if (Printer.trace) Printer.trace("<< AbstractMixer: start(" + line + ") nothing done");
414 return;
415 }
416
417 // we just start the mixer regardless of anything else here.
418 if (!started) {
419 if (Printer.debug) Printer.debug("AbstractMixer: start(line): starting the mixer");
420 implStart();
421 started = true;
422 }
423
424 if (Printer.trace) Printer.trace("<< AbstractMixer: start(" + line + ") succeeded");
425 }
426
427 /**
428 * Stops the mixer if this was the last running line.
429 */
430 final synchronized void stop(Line line) {
431
432 if (Printer.trace) Printer.trace(">> AbstractMixer: stop(" + line + ")");
433
434 // $$kk: 06.11.99: ignore ourselves for now
435 if (this.equals(line)) {
436 if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") nothing done");
437 return;
438 }
439
440 @SuppressWarnings("unchecked")
441 Vector<Line> localSourceLines = (Vector<Line>)sourceLines.clone();
442 for (int i = 0; i < localSourceLines.size(); i++) {
443
444 // if any other open line is running, return
445
446 // this covers clips and source data lines
459
460 // if any other open line is running, return
461 // this covers target data lines
462 if (localTargetLines.elementAt(i) instanceof AbstractDataLine) {
463 AbstractDataLine targetLine = (AbstractDataLine)localTargetLines.elementAt(i);
464 if ( targetLine.isStartedRunning() && (!targetLine.equals(line)) ) {
465 if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") found running targetLine: " + targetLine);
466 return;
467 }
468 }
469 }
470
471 // otherwise, stop
472 if (Printer.debug) Printer.debug("AbstractMixer: stop(line): stopping the mixer");
473 started = false;
474 implStop();
475
476 if (Printer.trace) Printer.trace("<< AbstractMixer: stop(" + line + ") succeeded");
477 }
478
479 /**
480 * Determines whether this is a source line for this mixer.
481 * Right now this just checks whether it's supported, but should
482 * check whether it actually belongs to this mixer....
483 */
484 final boolean isSourceLine(Line.Info info) {
485
486 for (int i = 0; i < sourceLineInfo.length; i++) {
487 if (info.matches(sourceLineInfo[i])) {
488 return true;
489 }
490 }
491
492 return false;
493 }
494
495 /**
496 * Determines whether this is a target 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 isTargetLine(Line.Info info) {
501
502 for (int i = 0; i < targetLineInfo.length; i++) {
503 if (info.matches(targetLineInfo[i])) {
504 return true;
505 }
506 }
507
508 return false;
509 }
510
511 /**
512 * Returns the first complete Line.Info object it finds that
513 * matches the one specified, or null if no matching Line.Info
514 * object is found.
515 */
516 final Line.Info getLineInfo(Line.Info info) {
517 if (info == null) {
518 return null;
519 }
520 // $$kk: 05.31.99: need to change this so that
521 // the format and buffer size get set in the
522 // returned info object for data lines??
523 for (int i = 0; i < sourceLineInfo.length; i++) {
524 if (info.matches(sourceLineInfo[i])) {
525 return sourceLineInfo[i];
526 }
527 }
528
529 for (int i = 0; i < targetLineInfo.length; i++) {
530 if (info.matches(targetLineInfo[i])) {
531 return targetLineInfo[i];
532 }
533 }
534 return null;
535 }
536 }
|