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