DefaultMixers.java revision 16009:5445b9413d9d
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
24import java.util.List;
25
26import javax.sound.sampled.AudioFormat;
27import javax.sound.sampled.AudioSystem;
28import javax.sound.sampled.Clip;
29import javax.sound.sampled.DataLine;
30import javax.sound.sampled.Line;
31import javax.sound.sampled.Mixer;
32import javax.sound.sampled.Port;
33import javax.sound.sampled.SourceDataLine;
34import javax.sound.sampled.TargetDataLine;
35import javax.sound.sampled.spi.MixerProvider;
36
37import 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 */
46public 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}
199