1 /*
   2  * Copyright (c) 2003, 2016, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.util.List;
  25 
  26 import javax.sound.sampled.AudioFormat;
  27 import javax.sound.sampled.AudioSystem;
  28 import javax.sound.sampled.Clip;
  29 import javax.sound.sampled.DataLine;
  30 import javax.sound.sampled.Line;
  31 import javax.sound.sampled.Mixer;
  32 import javax.sound.sampled.Port;
  33 import javax.sound.sampled.SourceDataLine;
  34 import javax.sound.sampled.TargetDataLine;
  35 import javax.sound.sampled.spi.MixerProvider;
  36 
  37 import com.sun.media.sound.JDK13Services;
  38 
  39 /**
  40  * @test
  41  * @bug 4776511
  42  * @summary RFE: Setting the default MixerProvider. Test the retrieving of lines
  43  *          with defaut mixer properties.
  44  * @modules java.desktop/com.sun.media.sound
  45  */
  46 public class DefaultMixers {
  47 
  48     private static final String ERROR_PROVIDER_CLASS_NAME = "abc";
  49     private static final String ERROR_INSTANCE_NAME = "def";
  50 
  51     private static final Class[] lineClasses = {
  52         SourceDataLine.class,
  53         TargetDataLine.class,
  54         Clip.class,
  55         Port.class,
  56     };
  57 
  58     public static void main(String[] args) throws Exception {
  59         boolean allOk = true;
  60         Mixer.Info[] infos;
  61 
  62         out("Testing Mixers retrieved via AudioSystem");
  63         infos = AudioSystem.getMixerInfo();
  64         allOk &= testMixers(infos, null);
  65 
  66         out("Testing MixerProviders");
  67         List providers = JDK13Services.getProviders(MixerProvider.class);
  68         for (int i = 0; i < providers.size(); i++) {
  69             MixerProvider provider = (MixerProvider) providers.get(i);
  70             infos = provider.getMixerInfo();
  71             allOk &= testMixers(infos, provider.getClass().getName());
  72         }
  73 
  74         if (! allOk) {
  75             throw new Exception("Test failed");
  76         } else {
  77             out("Test passed");
  78         }
  79     }
  80 
  81     private static boolean testMixers(Mixer.Info[] infos,
  82                                       String providerClassName) {
  83         boolean allOk = true;
  84 
  85         for (int i = 0; i < infos.length; i++) {
  86             Mixer mixer = null;
  87             try {
  88                 mixer = AudioSystem.getMixer(infos[i]);
  89             } catch (NullPointerException e) {
  90                 out("Exception thrown; Test NOT failed.");
  91                 e.printStackTrace();
  92             }
  93             for (int j = 0; j < lineClasses.length; j++) {
  94                 if (mixer.isLineSupported(new Line.Info(lineClasses[j]))) {
  95                     allOk &= testMixer(mixer, lineClasses[j],
  96                                        providerClassName);
  97                 }
  98             }
  99         }
 100         return allOk;
 101     }
 102 
 103     private static boolean testMixer(Mixer mixer, Class lineType,
 104                                       String providerClassName) {
 105         boolean allOk = true;
 106         String instanceName = mixer.getMixerInfo().getName();
 107 
 108         // no error
 109         allOk &= testMixer(mixer, lineType,
 110                            providerClassName, instanceName);
 111 
 112         // erroneous provider class name, correct instance name
 113         allOk &= testMixer(mixer, lineType,
 114                            ERROR_PROVIDER_CLASS_NAME, instanceName);
 115 
 116         // erroneous provider class name, no instance name
 117         allOk &= testMixer(mixer, lineType,
 118                            ERROR_PROVIDER_CLASS_NAME, "");
 119 
 120         // erroneous provider class name, erroneous instance name
 121         allOk &= testMixer(mixer, lineType,
 122                            ERROR_PROVIDER_CLASS_NAME, ERROR_INSTANCE_NAME);
 123 
 124         return allOk;
 125     }
 126 
 127     private static boolean testMixer(Mixer mixer, Class lineType,
 128                                      String providerClassName,
 129                                      String instanceName) {
 130         boolean allOk = true;
 131 
 132         try {
 133             String propertyValue = (providerClassName != null) ? providerClassName: "" ;
 134             propertyValue += "#" + instanceName;
 135             out("property value: " + propertyValue);
 136             System.setProperty(lineType.getName(), propertyValue);
 137             Line line = null;
 138             Line.Info info = null;
 139             Line.Info[] infos;
 140             AudioFormat format = null;
 141             if (lineType == SourceDataLine.class || lineType == Clip.class) {
 142                 infos = mixer.getSourceLineInfo();
 143                 format = getFirstLinearFormat(infos);
 144                 info = new DataLine.Info(lineType, format);
 145             } else if (lineType == TargetDataLine.class) {
 146                 infos = mixer.getTargetLineInfo();
 147                 format = getFirstLinearFormat(infos);
 148                 info = new DataLine.Info(lineType, format);
 149             } else if (lineType == Port.class) {
 150                 /* Actually, a Ports Mixer commonly has source infos
 151                    as well as target infos. We ignore this here, since we
 152                    just need a random one. */
 153                 infos = mixer.getSourceLineInfo();
 154                 for (int i = 0; i < infos.length; i++) {
 155                     if (infos[i] instanceof Port.Info) {
 156                         info = infos[i];
 157                         break;
 158                     }
 159                 }
 160             }
 161             out("Line.Info: " + info);
 162             line = AudioSystem.getLine(info);
 163             out("line: " + line);
 164             if (! lineType.isInstance(line)) {
 165                 out("type " + lineType + " failed: class should be '" +
 166                     lineType + "' but is '" + line.getClass() + "'!");
 167                 allOk = false;
 168             }
 169         } catch (Exception e) {
 170             out("Exception thrown; Test NOT failed.");
 171             e.printStackTrace();
 172         }
 173         return allOk;
 174     }
 175 
 176     private static AudioFormat getFirstLinearFormat(Line.Info[] infos) {
 177         for (int i = 0; i < infos.length; i++) {
 178             if (infos[i] instanceof DataLine.Info) {
 179                 AudioFormat[] formats = ((DataLine.Info) infos[i]).getFormats();
 180                 for (int j = 0; j < formats.length; j++) {
 181                     AudioFormat.Encoding encoding = formats[j].getEncoding();
 182                     int sampleSizeInBits = formats[j].getSampleSizeInBits();
 183                     if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) &&
 184                         sampleSizeInBits == 16 ||
 185                         encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED) &&
 186                         sampleSizeInBits == 16) {
 187                         return formats[j];
 188                     }
 189                 }
 190             }
 191         }
 192         return null;
 193     }
 194 
 195     private static void out(String message) {
 196         System.out.println(message);
 197     }
 198 }