1 /*
2  * Copyright (c) 2002, 2019, 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 com.sun.media.sound;
27 
28 import javax.sound.sampled.Mixer;
29 import javax.sound.sampled.spi.MixerProvider;
30 
31 /**
32  * DirectAudioDevice provider.
33  *
34  * @author Florian Bomers
35  */
36 public final class DirectAudioDeviceProvider extends MixerProvider {
37 
38     /**
39      * Set of info objects for all port input devices on the system.
40      */
41     private static DirectAudioDeviceInfo[] infos;
42 
43     /**
44      * Set of all port input devices on the system.
45      */
46     private static DirectAudioDevice[] devices;
47 
48     static {
49         // initialize
Platform.initialize()50         Platform.initialize();
51     }
52 
53     /**
54      * Required public no-arg constructor.
55      */
DirectAudioDeviceProvider()56     public DirectAudioDeviceProvider() {
57         synchronized (DirectAudioDeviceProvider.class) {
58             if (Platform.isDirectAudioEnabled()) {
59                 init();
60             } else {
61                 infos = new DirectAudioDeviceInfo[0];
62                 devices = new DirectAudioDevice[0];
63             }
64         }
65     }
66 
init()67     private static void init() {
68         // get the number of input devices
69         int numDevices = nGetNumDevices();
70 
71         if (infos == null || infos.length != numDevices) {
72             // initialize the arrays
73             infos = new DirectAudioDeviceInfo[numDevices];
74             devices = new DirectAudioDevice[numDevices];
75 
76             // fill in the info objects now.
77             for (int i = 0; i < infos.length; i++) {
78                 infos[i] = nNewDirectAudioDeviceInfo(i);
79             }
80         }
81     }
82 
83     @Override
getMixerInfo()84     public Mixer.Info[] getMixerInfo() {
85         synchronized (DirectAudioDeviceProvider.class) {
86             Mixer.Info[] localArray = new Mixer.Info[infos.length];
87             System.arraycopy(infos, 0, localArray, 0, infos.length);
88             return localArray;
89         }
90     }
91 
92     @Override
getMixer(Mixer.Info info)93     public Mixer getMixer(Mixer.Info info) {
94         synchronized (DirectAudioDeviceProvider.class) {
95             // if the default device is asked, we provide the mixer
96             // with SourceDataLine's
97             if (info == null) {
98                 for (int i = 0; i < infos.length; i++) {
99                     Mixer mixer = getDevice(infos[i]);
100                     if (mixer.getSourceLineInfo().length > 0) {
101                         return mixer;
102                     }
103                 }
104             }
105             // otherwise get the first mixer that matches
106             // the requested info object
107             for (int i = 0; i < infos.length; i++) {
108                 if (infos[i].equals(info)) {
109                     return getDevice(infos[i]);
110                 }
111             }
112         }
113         throw new IllegalArgumentException(
114                 String.format("Mixer %s not supported by this provider", info));
115     }
116 
getDevice(DirectAudioDeviceInfo info)117     private static Mixer getDevice(DirectAudioDeviceInfo info) {
118         int index = info.getIndex();
119         if (devices[index] == null) {
120             devices[index] = new DirectAudioDevice(info);
121         }
122         return devices[index];
123     }
124 
125     /**
126      * Info class for DirectAudioDevices.  Adds an index value and a string for
127      * making native references to a particular device.
128      * This constructor is called from native.
129      */
130     static final class DirectAudioDeviceInfo extends Mixer.Info {
131         private final int index;
132         private final int maxSimulLines;
133 
134         // For ALSA, the deviceID contains the encoded card index, device index, and sub-device-index
135         private final int deviceID;
136 
DirectAudioDeviceInfo(int index, int deviceID, int maxSimulLines, String name, String vendor, String description, String version)137         private DirectAudioDeviceInfo(int index, int deviceID, int maxSimulLines,
138                                       String name, String vendor,
139                                       String description, String version) {
140             super(name, vendor, "Direct Audio Device: "+description, version);
141             this.index = index;
142             this.maxSimulLines = maxSimulLines;
143             this.deviceID = deviceID;
144         }
145 
getIndex()146         int getIndex() {
147             return index;
148         }
149 
getMaxSimulLines()150         int getMaxSimulLines() {
151             return maxSimulLines;
152         }
153 
getDeviceID()154         int getDeviceID() {
155             return deviceID;
156         }
157     } // class DirectAudioDeviceInfo
158 
nGetNumDevices()159     private static native int nGetNumDevices();
160     // index: [0..nGetNumDevices()-1]
nNewDirectAudioDeviceInfo(int deviceIndex)161     private static native DirectAudioDeviceInfo nNewDirectAudioDeviceInfo(int deviceIndex);
162 }
163