jdk/src/java.desktop/share/classes/com/sun/media/sound/PortMixer.java
changeset 40444 afabcfc2f3ef
parent 32865 f9cb6e427f9e
equal deleted inserted replaced
40442:e97e9982be6d 40444:afabcfc2f3ef
    25 
    25 
    26 package com.sun.media.sound;
    26 package com.sun.media.sound;
    27 
    27 
    28 import java.util.Vector;
    28 import java.util.Vector;
    29 
    29 
       
    30 import javax.sound.sampled.BooleanControl;
       
    31 import javax.sound.sampled.CompoundControl;
    30 import javax.sound.sampled.Control;
    32 import javax.sound.sampled.Control;
       
    33 import javax.sound.sampled.FloatControl;
    31 import javax.sound.sampled.Line;
    34 import javax.sound.sampled.Line;
    32 import javax.sound.sampled.LineUnavailableException;
    35 import javax.sound.sampled.LineUnavailableException;
    33 import javax.sound.sampled.Port;
    36 import javax.sound.sampled.Port;
    34 import javax.sound.sampled.BooleanControl;
       
    35 import javax.sound.sampled.CompoundControl;
       
    36 import javax.sound.sampled.FloatControl;
       
    37 
       
    38 
    37 
    39 /**
    38 /**
    40  * A Mixer which only provides Ports.
    39  * A Mixer which only provides Ports.
    41  *
    40  *
    42  * @author Florian Bomers
    41  * @author Florian Bomers
    43  */
    42  */
    44 final class PortMixer extends AbstractMixer {
    43 final class PortMixer extends AbstractMixer {
    45 
    44 
    46     // CONSTANTS
       
    47     private static final int SRC_UNKNOWN      = 0x01;
    45     private static final int SRC_UNKNOWN      = 0x01;
    48     private static final int SRC_MICROPHONE   = 0x02;
    46     private static final int SRC_MICROPHONE   = 0x02;
    49     private static final int SRC_LINE_IN      = 0x03;
    47     private static final int SRC_LINE_IN      = 0x03;
    50     private static final int SRC_COMPACT_DISC = 0x04;
    48     private static final int SRC_COMPACT_DISC = 0x04;
    51     private static final int SRC_MASK         = 0xFF;
    49     private static final int SRC_MASK         = 0xFF;
    54     private static final int DST_SPEAKER      = 0x0200;
    52     private static final int DST_SPEAKER      = 0x0200;
    55     private static final int DST_HEADPHONE    = 0x0300;
    53     private static final int DST_HEADPHONE    = 0x0300;
    56     private static final int DST_LINE_OUT     = 0x0400;
    54     private static final int DST_LINE_OUT     = 0x0400;
    57     private static final int DST_MASK         = 0xFF00;
    55     private static final int DST_MASK         = 0xFF00;
    58 
    56 
    59     // INSTANCE VARIABLES
    57     private final Port.Info[] portInfos;
    60     private Port.Info[] portInfos;
       
    61     // cache of instantiated ports
    58     // cache of instantiated ports
    62     private PortMixerPort[] ports;
    59     private PortMixerPort[] ports;
    63 
    60 
    64     // instance ID of the native implementation
    61     // instance ID of the native implementation
    65     private long id = 0;
    62     private long id = 0;
    66 
    63 
    67     // CONSTRUCTOR
       
    68     PortMixer(PortMixerProvider.PortMixerInfo portMixerInfo) {
    64     PortMixer(PortMixerProvider.PortMixerInfo portMixerInfo) {
    69         // pass in Line.Info, mixer, controls
    65         // pass in Line.Info, mixer, controls
    70         super(portMixerInfo,              // Mixer.Info
    66         super(portMixerInfo,              // Mixer.Info
    71               null,                       // Control[]
    67               null,                       // Control[]
    72               null,                       // Line.Info[] sourceLineInfo
    68               null,                       // Line.Info[] sourceLineInfo
   119         }
   115         }
   120 
   116 
   121         if (Printer.trace) Printer.trace("<< PortMixer: constructor completed");
   117         if (Printer.trace) Printer.trace("<< PortMixer: constructor completed");
   122     }
   118     }
   123 
   119 
   124 
   120     @Override
   125     // ABSTRACT MIXER: ABSTRACT METHOD IMPLEMENTATIONS
       
   126 
       
   127     public Line getLine(Line.Info info) throws LineUnavailableException {
   121     public Line getLine(Line.Info info) throws LineUnavailableException {
   128         Line.Info fullInfo = getLineInfo(info);
   122         Line.Info fullInfo = getLineInfo(info);
   129 
   123 
   130         if ((fullInfo != null) && (fullInfo instanceof Port.Info)) {
   124         if ((fullInfo != null) && (fullInfo instanceof Port.Info)) {
   131             for (int i = 0; i < portInfos.length; i++) {
   125             for (int i = 0; i < portInfos.length; i++) {
   135             }
   129             }
   136         }
   130         }
   137         throw new IllegalArgumentException("Line unsupported: " + info);
   131         throw new IllegalArgumentException("Line unsupported: " + info);
   138     }
   132     }
   139 
   133 
   140 
   134     @Override
   141     public int getMaxLines(Line.Info info) {
   135     public int getMaxLines(Line.Info info) {
   142         Line.Info fullInfo = getLineInfo(info);
   136         Line.Info fullInfo = getLineInfo(info);
   143 
   137 
   144         // if it's not supported at all, return 0.
   138         // if it's not supported at all, return 0.
   145         if (fullInfo == null) {
   139         if (fullInfo == null) {
   151             return 1;
   145             return 1;
   152         }
   146         }
   153         return 0;
   147         return 0;
   154     }
   148     }
   155 
   149 
   156 
   150     @Override
   157     protected void implOpen() throws LineUnavailableException {
   151     protected void implOpen() throws LineUnavailableException {
   158         if (Printer.trace) Printer.trace(">> PortMixer: implOpen (id="+id+")");
   152         if (Printer.trace) Printer.trace(">> PortMixer: implOpen (id="+id+")");
   159 
   153 
   160         // open the mixer device
   154         // open the mixer device
   161         id = nOpen(getMixerIndex());
   155         id = nOpen(getMixerIndex());
   162 
   156 
   163         if (Printer.trace) Printer.trace("<< PortMixer: implOpen succeeded.");
   157         if (Printer.trace) Printer.trace("<< PortMixer: implOpen succeeded.");
   164     }
   158     }
   165 
   159 
       
   160     @Override
   166     protected void implClose() {
   161     protected void implClose() {
   167         if (Printer.trace) Printer.trace(">> PortMixer: implClose");
   162         if (Printer.trace) Printer.trace(">> PortMixer: implClose");
   168 
   163 
   169         // close the mixer device
   164         // close the mixer device
   170         long thisID = id;
   165         long thisID = id;
   179         }
   174         }
   180 
   175 
   181         if (Printer.trace) Printer.trace("<< PortMixer: implClose succeeded");
   176         if (Printer.trace) Printer.trace("<< PortMixer: implClose succeeded");
   182     }
   177     }
   183 
   178 
       
   179     @Override
   184     protected void implStart() {}
   180     protected void implStart() {}
       
   181     @Override
   185     protected void implStop() {}
   182     protected void implStop() {}
   186 
       
   187     // IMPLEMENTATION HELPERS
       
   188 
   183 
   189     private Port.Info getPortInfo(int portIndex, int type) {
   184     private Port.Info getPortInfo(int portIndex, int type) {
   190         switch (type) {
   185         switch (type) {
   191         case SRC_UNKNOWN:      return new PortInfo(nGetPortName(getID(), portIndex), true);
   186         case SRC_UNKNOWN:      return new PortInfo(nGetPortName(getID(), portIndex), true);
   192         case SRC_MICROPHONE:   return Port.Info.MICROPHONE;
   187         case SRC_MICROPHONE:   return Port.Info.MICROPHONE;
   221 
   216 
   222     long getID() {
   217     long getID() {
   223         return id;
   218         return id;
   224     }
   219     }
   225 
   220 
   226     // INNER CLASSES
       
   227 
       
   228     /**
   221     /**
   229      * Private inner class representing a Port for the PortMixer.
   222      * Private inner class representing a Port for the PortMixer.
   230      */
   223      */
   231     private static final class PortMixerPort extends AbstractLine
   224     private static final class PortMixerPort extends AbstractLine
   232             implements Port {
   225             implements Port {
   233 
   226 
   234         private final int portIndex;
   227         private final int portIndex;
   235         private long id;
   228         private long id;
   236 
   229 
   237         // CONSTRUCTOR
       
   238         private PortMixerPort(Port.Info info,
   230         private PortMixerPort(Port.Info info,
   239                               PortMixer mixer,
   231                               PortMixer mixer,
   240                               int portIndex) {
   232                               int portIndex) {
   241             super(info, mixer, null);
   233             super(info, mixer, null);
   242             if (Printer.trace) Printer.trace("PortMixerPort CONSTRUCTOR: info: " + info);
   234             if (Printer.trace) Printer.trace("PortMixerPort CONSTRUCTOR: info: " + info);
   243             this.portIndex = portIndex;
   235             this.portIndex = portIndex;
   244         }
   236         }
   245 
       
   246 
       
   247         // ABSTRACT METHOD IMPLEMENTATIONS
       
   248 
       
   249         // ABSTRACT LINE
       
   250 
   237 
   251         void implOpen() throws LineUnavailableException {
   238         void implOpen() throws LineUnavailableException {
   252             if (Printer.trace) Printer.trace(">> PortMixerPort: implOpen().");
   239             if (Printer.trace) Printer.trace(">> PortMixerPort: implOpen().");
   253             long newID = ((PortMixer) mixer).getID();
   240             long newID = ((PortMixer) mixer).getID();
   254             if ((id == 0) || (newID != id) || (controls.length == 0)) {
   241             if ((id == 0) || (newID != id) || (controls.length == 0)) {
   284         private void disposeControls() {
   271         private void disposeControls() {
   285             enableControls(controls, false);
   272             enableControls(controls, false);
   286             controls = new Control[0];
   273             controls = new Control[0];
   287         }
   274         }
   288 
   275 
   289 
       
   290         void implClose() {
   276         void implClose() {
   291             if (Printer.trace) Printer.trace(">> PortMixerPort: implClose()");
   277             if (Printer.trace) Printer.trace(">> PortMixerPort: implClose()");
   292             // get rid of controls
   278             // get rid of controls
   293             enableControls(controls, false);
   279             enableControls(controls, false);
   294             if (Printer.trace) Printer.trace("<< PortMixerPort: implClose() succeeded");
   280             if (Printer.trace) Printer.trace("<< PortMixerPort: implClose() succeeded");
   295         }
   281         }
   296 
   282 
   297         // METHOD OVERRIDES
       
   298 
       
   299         // this is very similar to open(AudioFormat, int) in AbstractDataLine...
   283         // this is very similar to open(AudioFormat, int) in AbstractDataLine...
       
   284         @Override
   300         public void open() throws LineUnavailableException {
   285         public void open() throws LineUnavailableException {
   301             synchronized (mixer) {
   286             synchronized (mixer) {
   302                 // if the line is not currently open, try to open it with this format and buffer size
   287                 // if the line is not currently open, try to open it with this format and buffer size
   303                 if (!isOpen()) {
   288                 if (!isOpen()) {
   304                     if (Printer.trace) Printer.trace("> PortMixerPort: open");
   289                     if (Printer.trace) Printer.trace("> PortMixerPort: open");
   319                 }
   304                 }
   320             }
   305             }
   321         }
   306         }
   322 
   307 
   323         // this is very similar to close() in AbstractDataLine...
   308         // this is very similar to close() in AbstractDataLine...
       
   309         @Override
   324         public void close() {
   310         public void close() {
   325             synchronized (mixer) {
   311             synchronized (mixer) {
   326                 if (isOpen()) {
   312                 if (isOpen()) {
   327                     if (Printer.trace) Printer.trace("> PortMixerPort.close()");
   313                     if (Printer.trace) Printer.trace("> PortMixerPort.close()");
   328 
   314 
   340         }
   326         }
   341 
   327 
   342     } // class PortMixerPort
   328     } // class PortMixerPort
   343 
   329 
   344     /**
   330     /**
   345      * Private inner class representing a BooleanControl for PortMixerPort
   331      * Private inner class representing a BooleanControl for PortMixerPort.
   346      */
   332      */
   347     private static final class BoolCtrl extends BooleanControl {
   333     private static final class BoolCtrl extends BooleanControl {
   348         // the handle to the native control function
   334         // the handle to the native control function
   349         private final long controlID;
   335         private final long controlID;
   350         private boolean closed = false;
   336         private boolean closed = false;
   358                 //return BooleanControl.Type.SELECT;
   344                 //return BooleanControl.Type.SELECT;
   359             }
   345             }
   360             return new BCT(name);
   346             return new BCT(name);
   361         }
   347         }
   362 
   348 
   363 
       
   364         private BoolCtrl(long controlID, String name) {
   349         private BoolCtrl(long controlID, String name) {
   365             this(controlID, createType(name));
   350             this(controlID, createType(name));
   366         }
   351         }
   367 
   352 
   368         private BoolCtrl(long controlID, BooleanControl.Type typ) {
   353         private BoolCtrl(long controlID, BooleanControl.Type typ) {
   369             super(typ, false);
   354             super(typ, false);
   370             this.controlID = controlID;
   355             this.controlID = controlID;
   371         }
   356         }
   372 
   357 
       
   358         @Override
   373         public void setValue(boolean value) {
   359         public void setValue(boolean value) {
   374             if (!closed) {
   360             if (!closed) {
   375                 nControlSetIntValue(controlID, value?1:0);
   361                 nControlSetIntValue(controlID, value?1:0);
   376             }
   362             }
   377         }
   363         }
   378 
   364 
       
   365         @Override
   379         public boolean getValue() {
   366         public boolean getValue() {
   380             if (!closed) {
   367             if (!closed) {
   381                 // never use any cached values
   368                 // never use any cached values
   382                 return (nControlGetIntValue(controlID)!=0)?true:false;
   369                 return (nControlGetIntValue(controlID)!=0)?true:false;
   383             }
   370             }
   384             // ??
   371             // ??
   385             return false;
   372             return false;
   386         }
   373         }
   387 
   374 
   388         /**
   375         /**
   389          * inner class for custom types
   376          * inner class for custom types.
   390          */
   377          */
   391         private static final class BCT extends BooleanControl.Type {
   378         private static final class BCT extends BooleanControl.Type {
   392             private BCT(String name) {
   379             private BCT(String name) {
   393                 super(name);
   380                 super(name);
   394             }
   381             }
   395         }
   382         }
   396     }
   383     }
   397 
   384 
   398     /**
   385     /**
   399      * Private inner class representing a CompoundControl for PortMixerPort
   386      * Private inner class representing a CompoundControl for PortMixerPort.
   400      */
   387      */
   401     private static final class CompCtrl extends CompoundControl {
   388     private static final class CompCtrl extends CompoundControl {
   402         private CompCtrl(String name, Control[] controls) {
   389         private CompCtrl(String name, Control[] controls) {
   403             super(new CCT(name), controls);
   390             super(new CCT(name), controls);
   404         }
   391         }
   405 
   392 
   406         /**
   393         /**
   407          * inner class for custom compound control types
   394          * inner class for custom compound control types.
   408          */
   395          */
   409         private static final class CCT extends CompoundControl.Type {
   396         private static final class CCT extends CompoundControl.Type {
   410             private CCT(String name) {
   397             private CCT(String name) {
   411                 super(name);
   398                 super(name);
   412             }
   399             }
   413         }
   400         }
   414     }
   401     }
   415 
   402 
   416     /**
   403     /**
   417      * Private inner class representing a BooleanControl for PortMixerPort
   404      * Private inner class representing a BooleanControl for PortMixerPort.
   418      */
   405      */
   419     private static final class FloatCtrl extends FloatControl {
   406     private static final class FloatCtrl extends FloatControl {
   420         // the handle to the native control function
   407         // the handle to the native control function
   421         private final long controlID;
   408         private final long controlID;
   422         private boolean closed = false;
   409         private boolean closed = false;
   444                          float min, float max, float precision, String units) {
   431                          float min, float max, float precision, String units) {
   445             super(typ, min, max, precision, 1000, min, units);
   432             super(typ, min, max, precision, 1000, min, units);
   446             this.controlID = controlID;
   433             this.controlID = controlID;
   447         }
   434         }
   448 
   435 
       
   436         @Override
   449         public void setValue(float value) {
   437         public void setValue(float value) {
   450             if (!closed) {
   438             if (!closed) {
   451                 nControlSetFloatValue(controlID, value);
   439                 nControlSetFloatValue(controlID, value);
   452             }
   440             }
   453         }
   441         }
   454 
   442 
       
   443         @Override
   455         public float getValue() {
   444         public float getValue() {
   456             if (!closed) {
   445             if (!closed) {
   457                 // never use any cached values
   446                 // never use any cached values
   458                 return nControlGetFloatValue(controlID);
   447                 return nControlGetFloatValue(controlID);
   459             }
   448             }
   460             // ??
   449             // ??
   461             return getMinimum();
   450             return getMinimum();
   462         }
   451         }
   463 
   452 
   464         /**
   453         /**
   465          * inner class for custom types
   454          * inner class for custom types.
   466          */
   455          */
   467         private static final class FCT extends FloatControl.Type {
   456         private static final class FCT extends FloatControl.Type {
   468             private FCT(String name) {
   457             private FCT(String name) {
   469                 super(name);
   458                 super(name);
   470             }
   459             }
   471         }
   460         }
   472     }
   461     }
   473 
   462 
   474     /**
   463     /**
   475      * Private inner class representing a port info
   464      * Private inner class representing a port info.
   476      */
   465      */
   477     private static final class PortInfo extends Port.Info {
   466     private static final class PortInfo extends Port.Info {
   478         private PortInfo(String name, boolean isSource) {
   467         private PortInfo(String name, boolean isSource) {
   479             super(Port.class, name, isSource);
   468             super(Port.class, name, isSource);
   480         }
   469         }