1 /* 2 * Copyright (c) 1999, 2010, 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 javax.sound.sampled; 27 28 /** 29 * The <code>Line</code> interface represents a mono or multi-channel 30 * audio feed. A line is an element of the digital audio 31 * "pipeline," such as a mixer, an input or output port, 32 * or a data path into or out of a mixer. 33 * <p> 34 * A line can have controls, such as gain, pan, and reverb. 35 * The controls themselves are instances of classes that extend the 36 * base <code>{@link Control}</code> class. 37 * The <code>Line</code> interface provides two accessor methods for 38 * obtaining the line's controls: <code>{@link #getControls getControls}</code> returns the 39 * entire set, and <code>{@link #getControl getControl}</code> returns a single control of 40 * specified type. 41 * <p> 42 * Lines exist in various states at different times. When a line opens, it reserves system 43 * resources for itself, and when it closes, these resources are freed for 44 * other objects or applications. The <code>{@link #isOpen()}</code> method lets 45 * you discover whether a line is open or closed. 46 * An open line need not be processing data, however. Such processing is 47 * typically initiated by subinterface methods such as 48 * <code>{@link SourceDataLine#write SourceDataLine.write}</code> and 49 * <code>{@link TargetDataLine#read TargetDataLine.read}</code>. 50 *<p> 51 * You can register an object to receive notifications whenever the line's 52 * state changes. The object must implement the <code>{@link LineListener}</code> 53 * interface, which consists of the single method 54 * <code>{@link LineListener#update update}</code>. 55 * This method will be invoked when a line opens and closes (and, if it's a 56 * {@link DataLine}, when it starts and stops). 57 *<p> 58 * An object can be registered to listen to multiple lines. The event it 59 * receives in its <code>update</code> method will specify which line created 60 * the event, what type of event it was 61 * (<code>OPEN</code>, <code>CLOSE</code>, <code>START</code>, or <code>STOP</code>), 62 * and how many sample frames the line had processed at the time the event occurred. 63 * <p> 64 * Certain line operations, such as open and close, can generate security 65 * exceptions if invoked by unprivileged code when the line is a shared audio 66 * resource. 67 * 68 * @author Kara Kytle 69 * 70 * @see LineEvent 71 * @since 1.3 72 */ 73 public interface Line extends AutoCloseable { 74 75 /** 76 * Obtains the <code>Line.Info</code> object describing this 77 * line. 78 * @return description of the line 79 */ 80 public Line.Info getLineInfo(); 81 82 /** 83 * Opens the line, indicating that it should acquire any required 84 * system resources and become operational. 85 * If this operation 86 * succeeds, the line is marked as open, and an <code>OPEN</code> event is dispatched 87 * to the line's listeners. 88 * <p> 89 * Note that some lines, once closed, cannot be reopened. Attempts 90 * to reopen such a line will always result in an <code>LineUnavailableException</code>. 91 * <p> 92 * Some types of lines have configurable properties that may affect 93 * resource allocation. For example, a <code>DataLine</code> must 94 * be opened with a particular format and buffer size. Such lines 95 * should provide a mechanism for configuring these properties, such 96 * as an additional <code>open</code> method or methods which allow 97 * an application to specify the desired settings. 98 * <p> 99 * This method takes no arguments, and opens the line with the current 100 * settings. For <code>{@link SourceDataLine}</code> and 101 * <code>{@link TargetDataLine}</code> objects, this means that the line is 102 * opened with default settings. For a <code>{@link Clip}</code>, however, 103 * the buffer size is determined when data is loaded. Since this method does not 104 * allow the application to specify any data to load, an IllegalArgumentException 105 * is thrown. Therefore, you should instead use one of the <code>open</code> methods 106 * provided in the <code>Clip</code> interface to load data into the <code>Clip</code>. 107 * <p> 108 * For <code>DataLine</code>'s, if the <code>DataLine.Info</code> 109 * object which was used to retrieve the line, specifies at least 110 * one fully qualified audio format, the last one will be used 111 * as the default format. 112 * 113 * @throws IllegalArgumentException if this method is called on a Clip instance. 114 * @throws LineUnavailableException if the line cannot be 115 * opened due to resource restrictions. 116 * @throws SecurityException if the line cannot be 117 * opened due to security restrictions. 118 * 119 * @see #close 120 * @see #isOpen 121 * @see LineEvent 122 * @see DataLine 123 * @see Clip#open(AudioFormat, byte[], int, int) 124 * @see Clip#open(AudioInputStream) 125 */ 126 public void open() throws LineUnavailableException; 127 128 129 /** 130 * Closes the line, indicating that any system resources 131 * in use by the line can be released. If this operation 132 * succeeds, the line is marked closed and a <code>CLOSE</code> event is dispatched 133 * to the line's listeners. 134 * @throws SecurityException if the line cannot be 135 * closed due to security restrictions. 136 * 137 * @see #open 138 * @see #isOpen 139 * @see LineEvent 140 */ 141 public void close(); 142 143 144 145 /** 146 * Indicates whether the line is open, meaning that it has reserved 147 * system resources and is operational, although it might not currently be 148 * playing or capturing sound. 149 * @return <code>true</code> if the line is open, otherwise <code>false</code> 150 * 151 * @see #open() 152 * @see #close() 153 */ 154 public boolean isOpen(); 155 156 157 /** 158 * Obtains the set of controls associated with this line. 159 * Some controls may only be available when the line is open. 160 * If there are no controls, this method returns an array of length 0. 161 * @return the array of controls 162 * @see #getControl 163 */ 164 public Control[] getControls(); 165 166 /** 167 * Indicates whether the line supports a control of the specified type. 168 * Some controls may only be available when the line is open. 169 * @param control the type of the control for which support is queried 170 * @return <code>true</code> if at least one control of the specified type is 171 * supported, otherwise <code>false</code>. 172 */ 173 public boolean isControlSupported(Control.Type control); 174 175 176 /** 177 * Obtains a control of the specified type, 178 * if there is any. 179 * Some controls may only be available when the line is open. 180 * @param control the type of the requested control 181 * @return a control of the specified type 182 * @throws IllegalArgumentException if a control of the specified type 183 * is not supported 184 * @see #getControls 185 * @see #isControlSupported(Control.Type control) 186 */ 187 public Control getControl(Control.Type control); 188 189 190 /** 191 * Adds a listener to this line. Whenever the line's status changes, the 192 * listener's <code>update()</code> method is called with a <code>LineEvent</code> object 193 * that describes the change. 194 * @param listener the object to add as a listener to this line 195 * @see #removeLineListener 196 * @see LineListener#update 197 * @see LineEvent 198 */ 199 public void addLineListener(LineListener listener); 200 201 202 /** 203 * Removes the specified listener from this line's list of listeners. 204 * @param listener listener to remove 205 * @see #addLineListener 206 */ 207 public void removeLineListener(LineListener listener); 208 209 210 /** 211 * A <code>Line.Info</code> object contains information about a line. 212 * The only information provided by <code>Line.Info</code> itself 213 * is the Java class of the line. 214 * A subclass of <code>Line.Info</code> adds other kinds of information 215 * about the line. This additional information depends on which <code>Line</code> 216 * subinterface is implemented by the kind of line that the <code>Line.Info</code> 217 * subclass describes. 218 * <p> 219 * A <code>Line.Info</code> can be retrieved using various methods of 220 * the <code>Line</code>, <code>Mixer</code>, and <code>AudioSystem</code> 221 * interfaces. Other such methods let you pass a <code>Line.Info</code> as 222 * an argument, to learn whether lines matching the specified configuration 223 * are available and to obtain them. 224 * 225 * @author Kara Kytle 226 * 227 * @see Line#getLineInfo 228 * @see Mixer#getSourceLineInfo 229 * @see Mixer#getTargetLineInfo 230 * @see Mixer#getLine <code>Mixer.getLine(Line.Info)</code> 231 * @see Mixer#getSourceLineInfo(Line.Info) <code>Mixer.getSourceLineInfo(Line.Info)</code> 232 * @see Mixer#getSourceLineInfo(Line.Info) <code>Mixer.getTargetLineInfo(Line.Info)</code> 233 * @see Mixer#isLineSupported <code>Mixer.isLineSupported(Line.Info)</code> 234 * @see AudioSystem#getLine <code>AudioSystem.getLine(Line.Info)</code> 235 * @see AudioSystem#getSourceLineInfo <code>AudioSystem.getSourceLineInfo(Line.Info)</code> 236 * @see AudioSystem#getTargetLineInfo <code>AudioSystem.getTargetLineInfo(Line.Info)</code> 237 * @see AudioSystem#isLineSupported <code>AudioSystem.isLineSupported(Line.Info)</code> 238 * @since 1.3 239 */ 240 public static class Info { 241 242 /** 243 * The class of the line described by the info object. 244 */ 245 private final Class<?> lineClass; 246 247 248 /** 249 * Constructs an info object that describes a line of the specified class. 250 * This constructor is typically used by an application to 251 * describe a desired line. 252 * @param lineClass the class of the line that the new Line.Info object describes 253 */ 254 public Info(Class<?> lineClass) { 255 256 if (lineClass == null) { 257 this.lineClass = Line.class; 258 } else { 259 this.lineClass = lineClass; 260 } 261 } 262 263 264 265 /** 266 * Obtains the class of the line that this Line.Info object describes. 267 * @return the described line's class 268 */ 269 public Class<?> getLineClass() { 270 return lineClass; 271 } 272 273 274 /** 275 * Indicates whether the specified info object matches this one. 276 * To match, the specified object must be identical to or 277 * a special case of this one. The specified info object 278 * must be either an instance of the same class as this one, 279 * or an instance of a sub-type of this one. In addition, the 280 * attributes of the specified object must be compatible with the 281 * capabilities of this one. Specifically, the routing configuration 282 * for the specified info object must be compatible with that of this 283 * one. 284 * Subclasses may add other criteria to determine whether the two objects 285 * match. 286 * 287 * @param info the info object which is being compared to this one 288 * @return <code>true</code> if the specified object matches this one, 289 * <code>false</code> otherwise 290 */ 291 public boolean matches(Info info) { 292 293 // $$kk: 08.30.99: is this backwards? 294 // dataLine.matches(targetDataLine) == true: targetDataLine is always dataLine 295 // targetDataLine.matches(dataLine) == false 296 // so if i want to make sure i get a targetDataLine, i need: 297 // targetDataLine.matches(prospective_match) == true 298 // => prospective_match may be other things as well, but it is at least a targetDataLine 299 // targetDataLine defines the requirements which prospective_match must meet. 300 301 302 // "if this Class object represents a declared class, this method returns 303 // true if the specified Object argument is an instance of the represented 304 // class (or of any of its subclasses)" 305 // GainControlClass.isInstance(MyGainObj) => true 306 // GainControlClass.isInstance(MySpecialGainInterfaceObj) => true 307 308 // this_class.isInstance(that_object) => that object can by cast to this class 309 // => that_object's class may be a subtype of this_class 310 // => that may be more specific (subtype) of this 311 312 // "If this Class object represents an interface, this method returns true 313 // if the class or any superclass of the specified Object argument implements 314 // this interface" 315 // GainControlClass.isInstance(MyGainObj) => true 316 // GainControlClass.isInstance(GenericControlObj) => may be false 317 // => that may be more specific 318 319 if (! (this.getClass().isInstance(info)) ) { 320 return false; 321 } 322 323 324 // this.isAssignableFrom(that) => this is same or super to that 325 // => this is at least as general as that 326 // => that may be subtype of this 327 328 if (! (getLineClass().isAssignableFrom(info.getLineClass())) ) { 329 return false; 330 } 331 332 return true; 333 } 334 335 336 /** 337 * Obtains a textual description of the line info. 338 * @return a string description 339 */ 340 public String toString() { 341 342 String fullPackagePath = "javax.sound.sampled."; 343 String initialString = new String(getLineClass().toString()); 344 String finalString; 345 346 int index = initialString.indexOf(fullPackagePath); 347 348 if (index != -1) { 349 finalString = initialString.substring(0, index) + initialString.substring( (index + fullPackagePath.length()), initialString.length() ); 350 } else { 351 finalString = initialString; 352 } 353 354 return finalString; 355 } 356 357 } // class Info 358 359 } // interface Line