jdk/src/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2002-2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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 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
+    }
+
+
+    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 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 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;
+        }
+
+        boolean equalStrings(Info info) {
+            return      (info != null
+                         && getName().equals(info.getName())
+                         && getVendor().equals(info.getVendor())
+                         && getDescription().equals(info.getDescription())
+                         && getVersion().equals(info.getVersion()));
+        }
+
+        int getIndex() {
+            return index;
+        }
+
+        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);
+}