blob: d73e12022d6389491dbe9b15c70a2ffa91630e22 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.media.sound;
27
28import java.util.Vector;
29
30import javax.sound.sampled.AudioSystem;
31import javax.sound.sampled.Control;
32import javax.sound.sampled.Mixer;
33import javax.sound.sampled.Line;
34import javax.sound.sampled.LineEvent;
35import javax.sound.sampled.LineListener;
36import javax.sound.sampled.LineUnavailableException;
37
38
39/**
40 * AbstractLine
41 *
42 * @author Kara Kytle
43 */
44abstract class AbstractLine implements Line {
45
46 protected Line.Info info;
47 protected Control[] controls;
48 protected AbstractMixer mixer;
49 private boolean open = false;
50 private Vector listeners = new Vector();
51
52 /**
53 * Global event thread
54 */
55 private static final EventDispatcher eventDispatcher;
56
57 static {
58 // create and start the global event thread
59
60 // $$kk: 12.21.98:
61 // 1) probably don't want a single global event queue
62 // 2) need a way to stop this thread when the engine is done
63
64 eventDispatcher = new EventDispatcher();
65 eventDispatcher.start();
66 }
67
68
69 /**
70 * Constructs a new AbstractLine.
71 * @param mixer the mixer with which this line is associated
72 * @param controls set of supported controls
73 */
74 protected AbstractLine(Line.Info info, AbstractMixer mixer, Control[] controls) {
75
76 if (controls == null) {
77 controls = new Control[0];
78 }
79
80 this.info = info;
81 this.mixer = mixer;
82 this.controls = controls;
83 }
84
85
86 // LINE METHODS
87
88 public Line.Info getLineInfo() {
89 return info;
90 }
91
92
93 public boolean isOpen() {
94 return open;
95 }
96
97
98 public void addLineListener(LineListener listener) {
99
100 synchronized(listeners) {
101 if ( ! (listeners.contains(listener)) ) {
102 listeners.addElement(listener);
103 }
104 }
105 }
106
107
108 /**
109 * Removes an audio listener.
110 * @param listener listener to remove
111 */
112 public void removeLineListener(LineListener listener) {
113 listeners.removeElement(listener);
114 }
115
116
117 /**
118 * Obtains the set of controls supported by the
119 * line. If no controls are supported, returns an
120 * array of length 0.
121 * @return control set
122 */
123 public Control[] getControls() {
124
125 Control[] returnedArray = new Control[controls.length];
126
127 for (int i = 0; i < controls.length; i++) {
128 returnedArray[i] = controls[i];
129 }
130
131 return returnedArray;
132 }
133
134
135 public boolean isControlSupported(Control.Type controlType) {
136
137 // protect against a NullPointerException
138 if (controlType == null) {
139 return false;
140 }
141
142 for (int i = 0; i < controls.length; i++) {
143 if (controlType == controls[i].getType()) {
144 return true;
145 }
146 }
147
148 return false;
149 }
150
151
152 public Control getControl(Control.Type controlType) {
153
154 // protect against a NullPointerException
155 if (controlType != null) {
156
157 for (int i = 0; i < controls.length; i++) {
158 if (controlType == controls[i].getType()) {
159 return controls[i];
160 }
161 }
162 }
163
164 throw new IllegalArgumentException("Unsupported control type: " + controlType);
165 }
166
167
168 // HELPER METHODS
169
170
171 /**
172 * This method sets the open state and generates
173 * events if it changes.
174 */
175 protected void setOpen(boolean open) {
176
177 if (Printer.trace) Printer.trace("> "+getClass().getName()+" (AbstractLine): setOpen(" + open + ") this.open: " + this.open);
178
179 boolean sendEvents = false;
180 long position = getLongFramePosition();
181
182 synchronized (this) {
183 if (this.open != open) {
184 this.open = open;
185 sendEvents = true;
186 }
187 }
188
189 if (sendEvents) {
190 if (open) {
191 sendEvents(new LineEvent(this, LineEvent.Type.OPEN, position));
192 } else {
193 sendEvents(new LineEvent(this, LineEvent.Type.CLOSE, position));
194 }
195 }
196 if (Printer.trace) Printer.trace("< "+getClass().getName()+" (AbstractLine): setOpen(" + open + ") this.open: " + this.open);
197 }
198
199
200 /**
201 * Send line events.
202 */
203 protected void sendEvents(LineEvent event) {
204 eventDispatcher.sendAudioEvents(event, listeners);
205 }
206
207
208 /**
209 * This is an error in the API: getFramePosition
210 * should return a long value. At CD quality,
211 * the int value wraps around after 13 hours.
212 */
213 public final int getFramePosition() {
214 return (int) getLongFramePosition();
215 }
216
217
218 /**
219 * Return the frame position in a long value
220 * This implementation returns AudioSystem.NOT_SPECIFIED.
221 */
222 public long getLongFramePosition() {
223 return AudioSystem.NOT_SPECIFIED;
224 }
225
226
227 // $$kk: 06.03.99: returns the mixer used in construction.
228 // this is a hold-over from when there was a public method like
229 // this on line and should be fixed!!
230 protected AbstractMixer getMixer() {
231 return mixer;
232 }
233
234 protected EventDispatcher getEventDispatcher() {
235 return eventDispatcher;
236 }
237
238 // ABSTRACT METHODS
239
240 public abstract void open() throws LineUnavailableException;
241 public abstract void close();
242}