1/*
2 * Copyright (c) 2002, 2015, 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
26package com.sun.media.sound;
27
28import javax.sound.sampled.Mixer;
29import javax.sound.sampled.spi.MixerProvider;
30
31/**
32 * Port provider.
33 *
34 * @author Florian Bomers
35 */
36public final class PortMixerProvider extends MixerProvider {
37
38    /**
39     * Set of info objects for all port input devices on the system.
40     */
41    private static PortMixerInfo[] infos;
42
43    /**
44     * Set of all port input devices on the system.
45     */
46    private static PortMixer[] devices;
47
48    static {
49        // initialize
50        Platform.initialize();
51    }
52
53    /**
54     * Required public no-arg constructor.
55     */
56    public PortMixerProvider() {
57        synchronized (PortMixerProvider.class) {
58            if (Platform.isPortsEnabled()) {
59                init();
60            } else {
61                infos = new PortMixerInfo[0];
62                devices = new PortMixer[0];
63            }
64        }
65    }
66
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            if (Printer.trace) Printer.trace("PortMixerProvider: init()");
73            // initialize the arrays
74            infos = new PortMixerInfo[numDevices];
75            devices = new PortMixer[numDevices];
76
77            // fill in the info objects now.
78            // we'll fill in the device objects as they're requested.
79            for (int i = 0; i < infos.length; i++) {
80                infos[i] = nNewPortMixerInfo(i);
81            }
82            if (Printer.trace) Printer.trace("PortMixerProvider: init(): found numDevices: " + numDevices);
83        }
84    }
85
86    @Override
87    public Mixer.Info[] getMixerInfo() {
88        synchronized (PortMixerProvider.class) {
89            Mixer.Info[] localArray = new Mixer.Info[infos.length];
90            System.arraycopy(infos, 0, localArray, 0, infos.length);
91            return localArray;
92        }
93    }
94
95    @Override
96    public Mixer getMixer(Mixer.Info info) {
97        synchronized (PortMixerProvider.class) {
98            for (int i = 0; i < infos.length; i++) {
99                if (infos[i].equals(info)) {
100                    return getDevice(infos[i]);
101                }
102            }
103        }
104        throw new IllegalArgumentException(
105                String.format("Mixer %s not supported by this provider", info));
106    }
107
108    private static Mixer getDevice(PortMixerInfo info) {
109        int index = info.getIndex();
110        if (devices[index] == null) {
111            devices[index] = new PortMixer(info);
112        }
113        return devices[index];
114    }
115
116    /**
117     * Info class for PortMixers.  Adds an index value for
118     * making native references to a particular device.
119     * This constructor is called from native.
120     */
121    static final class PortMixerInfo extends Mixer.Info {
122        private final int index;
123
124        private PortMixerInfo(int index, String name, String vendor, String description, String version) {
125            super("Port " + name, vendor, description, version);
126            this.index = index;
127        }
128
129        int getIndex() {
130            return index;
131        }
132
133    } // class PortMixerInfo
134
135    private static native int nGetNumDevices();
136    private static native PortMixerInfo nNewPortMixerInfo(int mixerIndex);
137}
138