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