src/share/classes/javax/sound/sampled/Line.java

Print this page


   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
   1 /*
   2  * Copyright (c) 1999, 2014, 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      */
  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      */
 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
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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 Line.Info object
 241          *         describes
 242          */
 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 Line.Info object describes.
 254          *
 255          * @return the described line's class
 256          */
 257         public Class<?> getLineClass() {
 258             return lineClass;
 259         }
 260 

 261         /**
 262          * Indicates whether the specified info object matches this one. To
 263          * match, the specified object must be identical to or a special case of
 264          * this one. The specified info object must be either an instance of
 265          * the same class as this one, or an instance of a sub-type of this one.
 266          * In addition, the attributes of the specified object must be
 267          * compatible with the capabilities of this one. Specifically, the
 268          * routing configuration for the specified info object must be
 269          * compatible with that of this one. Subclasses may add other criteria
 270          * to determine whether the two objects match.


 271          *
 272          * @param  info the info object which is being compared to this one
 273          * @return {@code true} if the specified object matches this one,
 274          *         {@code false} otherwise
 275          */
 276         public boolean matches(Info info) {
 277 
 278             // $$kk: 08.30.99: is this backwards?
 279             // dataLine.matches(targetDataLine) == true: targetDataLine is always dataLine
 280             // targetDataLine.matches(dataLine) == false
 281             // so if i want to make sure i get a targetDataLine, i need:
 282             // targetDataLine.matches(prospective_match) == true
 283             // => prospective_match may be other things as well, but it is at least a targetDataLine
 284             // targetDataLine defines the requirements which prospective_match must meet.
 285 
 286 
 287             // "if this Class object represents a declared class, this method returns
 288             // true if the specified Object argument is an instance of the represented
 289             // class (or of any of its subclasses)"
 290             // GainControlClass.isInstance(MyGainObj) => true
 291             // GainControlClass.isInstance(MySpecialGainInterfaceObj) => true
 292 
 293             // this_class.isInstance(that_object)       => that object can by cast to this class
 294             //                                                                          => that_object's class may be a subtype of this_class
 295             //                                                                          => that may be more specific (subtype) of this
 296 
 297             // "If this Class object represents an interface, this method returns true
 298             // if the class or any superclass of the specified Object argument implements
 299             // this interface"
 300             // GainControlClass.isInstance(MyGainObj) => true
 301             // GainControlClass.isInstance(GenericControlObj) => may be false
 302             // => that may be more specific
 303 
 304             if (! (this.getClass().isInstance(info)) ) {
 305                 return false;
 306             }
 307 

 308             // this.isAssignableFrom(that)  =>  this is same or super to that
 309             //                                                          =>      this is at least as general as that
 310             //                                                          =>      that may be subtype of this
 311 
 312             if (! (getLineClass().isAssignableFrom(info.getLineClass())) ) {
 313                 return false;
 314             }
 315 
 316             return true;
 317         }
 318 

 319         /**
 320          * Obtains a textual description of the line info.
 321          *
 322          * @return a string description
 323          */
 324         @Override
 325         public String toString() {
 326 
 327             String fullPackagePath = "javax.sound.sampled.";
 328             String initialString = new String(getLineClass().toString());
 329             String finalString;
 330 
 331             int index = initialString.indexOf(fullPackagePath);
 332 
 333             if (index != -1) {
 334                 finalString = initialString.substring(0, index) + initialString.substring( (index + fullPackagePath.length()), initialString.length() );
 335             } else {
 336                 finalString = initialString;
 337             }
 338 
 339             return finalString;
 340         }
 341     }
 342 }