197 lines
6.9 KiB
Java
197 lines
6.9 KiB
Java
/*
|
|
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package com.sun.media.sound;
|
|
|
|
import javax.sound.midi.MidiDevice;
|
|
import javax.sound.midi.spi.MidiDeviceProvider;
|
|
|
|
|
|
/**
|
|
* Super class for MIDI input or output device provider.
|
|
*
|
|
* @author Florian Bomers
|
|
*/
|
|
public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider {
|
|
|
|
private static final boolean enabled;
|
|
|
|
/**
|
|
* Create objects representing all MIDI output devices on the system.
|
|
*/
|
|
static {
|
|
if (Printer.trace) Printer.trace("AbstractMidiDeviceProvider: static");
|
|
Platform.initialize();
|
|
enabled = Platform.isMidiIOEnabled();
|
|
if (Printer.trace) Printer.trace("AbstractMidiDeviceProvider: enabled: " + enabled);
|
|
|
|
// $$fb number of MIDI devices may change with time
|
|
// also for memory's sake, do not initialize the arrays here
|
|
}
|
|
|
|
|
|
final synchronized void readDeviceInfos() {
|
|
Info[] infos = getInfoCache();
|
|
MidiDevice[] devices = getDeviceCache();
|
|
if (!enabled) {
|
|
if (infos == null || infos.length != 0) {
|
|
setInfoCache(new Info[0]);
|
|
}
|
|
if (devices == null || devices.length != 0) {
|
|
setDeviceCache(new MidiDevice[0]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
int oldNumDevices = (infos==null)?-1:infos.length;
|
|
int newNumDevices = getNumDevices();
|
|
if (oldNumDevices != newNumDevices) {
|
|
if (Printer.trace) Printer.trace(getClass().toString()
|
|
+": readDeviceInfos: old numDevices: "+oldNumDevices
|
|
+" newNumDevices: "+ newNumDevices);
|
|
|
|
// initialize the arrays
|
|
Info[] newInfos = new Info[newNumDevices];
|
|
MidiDevice[] newDevices = new MidiDevice[newNumDevices];
|
|
|
|
for (int i = 0; i < newNumDevices; i++) {
|
|
Info newInfo = createInfo(i);
|
|
|
|
// in case that we are re-reading devices, try to find
|
|
// the previous one and reuse it
|
|
if (infos != null) {
|
|
for (int ii = 0; ii < infos.length; ii++) {
|
|
Info info = infos[ii];
|
|
if (info != null && info.equalStrings(newInfo)) {
|
|
// new info matches the still existing info. Use old one
|
|
newInfos[i] = info;
|
|
info.setIndex(i);
|
|
infos[ii] = null; // prevent re-use
|
|
newDevices[i] = devices[ii];
|
|
devices[ii] = null;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (newInfos[i] == null) {
|
|
newInfos[i] = newInfo;
|
|
}
|
|
}
|
|
// the remaining MidiDevice.Info instances in the infos array
|
|
// have become obsolete.
|
|
if (infos != null) {
|
|
for (int i = 0; i < infos.length; i++) {
|
|
if (infos[i] != null) {
|
|
// disable this device info
|
|
infos[i].setIndex(-1);
|
|
}
|
|
// what to do with the MidiDevice instances that are left
|
|
// in the devices array ?? Close them ?
|
|
}
|
|
}
|
|
// commit new list of infos.
|
|
setInfoCache(newInfos);
|
|
setDeviceCache(newDevices);
|
|
}
|
|
}
|
|
|
|
|
|
public final MidiDevice.Info[] getDeviceInfo() {
|
|
readDeviceInfos();
|
|
Info[] infos = getInfoCache();
|
|
MidiDevice.Info[] localArray = new MidiDevice.Info[infos.length];
|
|
System.arraycopy(infos, 0, localArray, 0, infos.length);
|
|
return localArray;
|
|
}
|
|
|
|
|
|
public final MidiDevice getDevice(MidiDevice.Info info) {
|
|
if (info instanceof Info) {
|
|
readDeviceInfos();
|
|
MidiDevice[] devices = getDeviceCache();
|
|
Info[] infos = getInfoCache();
|
|
Info thisInfo = (Info) info;
|
|
int index = thisInfo.getIndex();
|
|
if (index >= 0 && index < devices.length && infos[index] == info) {
|
|
if (devices[index] == null) {
|
|
devices[index] = createDevice(thisInfo);
|
|
}
|
|
if (devices[index] != null) {
|
|
return devices[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new IllegalArgumentException("MidiDevice " + info.toString()
|
|
+ " not supported by this provider.");
|
|
}
|
|
|
|
|
|
// INNER CLASSES
|
|
|
|
|
|
/**
|
|
* Info class for MidiDevices. Adds an index value for
|
|
* making native references to a particular device.
|
|
*/
|
|
static class Info extends MidiDevice.Info {
|
|
private int index;
|
|
|
|
Info(String name, String vendor, String description, String version, int index) {
|
|
super(name, vendor, description, version);
|
|
this.index = index;
|
|
}
|
|
|
|
final boolean equalStrings(Info info) {
|
|
return (info != null
|
|
&& getName().equals(info.getName())
|
|
&& getVendor().equals(info.getVendor())
|
|
&& getDescription().equals(info.getDescription())
|
|
&& getVersion().equals(info.getVersion()));
|
|
}
|
|
|
|
final int getIndex() {
|
|
return index;
|
|
}
|
|
|
|
final void setIndex(int index) {
|
|
this.index = index;
|
|
}
|
|
|
|
} // class Info
|
|
|
|
|
|
// ABSTRACT METHODS
|
|
|
|
abstract int getNumDevices();
|
|
abstract MidiDevice[] getDeviceCache();
|
|
abstract void setDeviceCache(MidiDevice[] devices);
|
|
abstract Info[] getInfoCache();
|
|
abstract void setInfoCache(Info[] infos);
|
|
|
|
abstract Info createInfo(int index);
|
|
abstract MidiDevice createDevice(Info info);
|
|
}
|