6660470: RealTimeSequencer incorrectly opens (implicitly) synthesizer
authoramenkov
Thu, 03 Mar 2011 15:57:53 +0300
changeset 8528 f496950c5d98
parent 8527 4b82a41f91bc
child 8529 041fad0cabfc
6660470: RealTimeSequencer incorrectly opens (implicitly) synthesizer Reviewed-by: stayer
jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java
jdk/src/share/classes/javax/sound/midi/MidiSystem.java
jdk/test/javax/sound/midi/Sequencer/SequencerImplicitSynthOpen.java
--- a/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java	Thu Mar 03 15:45:47 2011 +0300
+++ b/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java	Thu Mar 03 15:57:53 2011 +0300
@@ -775,15 +775,22 @@
         Receiver rec = null;
         // first try to connect to the default synthesizer
         // IMPORTANT: this code needs to be synch'ed with
-        //            MidiSystem.getReceiver(boolean), because the same
+        //            MidiSystem.getSequencer(boolean), because the same
         //            algorithm needs to be used!
         try {
             Synthesizer synth = MidiSystem.getSynthesizer();
-            synth.open();
             if (synth instanceof ReferenceCountingDevice) {
                 rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
             } else {
-                rec = synth.getReceiver();
+                synth.open();
+                try {
+                    rec = synth.getReceiver();
+                } finally {
+                    // make sure that the synth is properly closed
+                    if (rec == null) {
+                        synth.close();
+                    }
+                }
             }
         } catch (Exception e) {
             // something went wrong with synth
--- a/jdk/src/share/classes/javax/sound/midi/MidiSystem.java	Thu Mar 03 15:45:47 2011 +0300
+++ b/jdk/src/share/classes/javax/sound/midi/MidiSystem.java	Thu Mar 03 15:57:53 2011 +0300
@@ -441,13 +441,6 @@
                 Synthesizer synth = getSynthesizer();
                 if (synth instanceof ReferenceCountingDevice) {
                     rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
-                    // only use MixerSynth if it could successfully load a soundbank
-                    if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth")
-                        && (synth.getDefaultSoundbank() == null)) {
-                        // don't use this receiver if no soundbank available
-                        rec = null;
-                        synth.close();
-                    }
                 } else {
                     synth.open();
                     try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerImplicitSynthOpen.java	Thu Mar 03 15:57:53 2011 +0300
@@ -0,0 +1,110 @@
+/**
+ * @test
+ * @bug 6660470
+ * @summary Tests that sequencer correctly opens/closes (implicitly) devices
+ * @author Alex Menkov
+ */
+
+import java.util.List;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiDeviceReceiver;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Transmitter;
+
+public class SequencerImplicitSynthOpen {
+
+    static int TEST_COUNT   = 5;
+
+    public static void main(String[] args) {
+        try {
+            log("getting sequencer...");
+            Sequencer sequencer = MidiSystem.getSequencer();
+            log("  - got " + getDeviceStr(sequencer));
+
+            // obtain connected device (usually synthesizer)
+            MidiDevice synth = getConnectedDevice(sequencer);
+            if (synth == null) {
+                log("could not get connected device, returning");
+                return;
+            }
+
+            log("connected device: " + getDeviceStr(synth));
+
+            int success = 0;
+            for (int i=0; i<TEST_COUNT; i++) {
+                if (test(sequencer)) {
+                    success++;
+                }
+            }
+
+            if (success != TEST_COUNT) {
+                throw new RuntimeException("test FAILS");
+            }
+        } catch (MidiUnavailableException ex) {
+            // this is not a failure
+            log("Could not get Sequencer");
+        }
+        log("test PASSED.");
+    }
+
+    static boolean test(Sequencer sequencer) throws MidiUnavailableException {
+        log("");
+        log("opening sequencer...");
+        sequencer.open();   // opens connected synthesizer implicitly
+        MidiDevice synth = getConnectedDevice(sequencer);
+        log("  connected device: " + getDeviceStr(synth));
+
+        log("closing sequencer...");
+        sequencer.close();  // closes the synth implicitly
+        log("  synth is " + getDeviceStr(synth));
+        MidiDevice synth2 = getConnectedDevice(sequencer);
+        log("  currently connected device: " + getDeviceStr(synth2));
+
+        if (synth != null && synth.isOpen()) {
+            log("FAIL.");
+            return false;
+        }
+        log("OK.");
+        return true;
+    }
+
+    static MidiDevice getConnectedDevice(Sequencer sequencer) {
+        List<Transmitter> trans = sequencer.getTransmitters();
+        log("  sequencer has " + trans.size() + " opened transmitters:");
+        for (Transmitter tr: trans) {
+            Receiver r = tr.getReceiver();
+            log("    " + getClassStr(tr) + " connected to " + getClassStr(r));
+            if (r instanceof MidiDeviceReceiver) {
+                MidiDeviceReceiver recv = (MidiDeviceReceiver)r;
+                MidiDevice dev = recv.getMidiDevice();
+                log("      - receiver of " + getClassStr(dev));
+                return dev;
+            } else {
+                log("      - does NOT implement MidiDeviceReceiver");
+            }
+        }
+        return null;
+    }
+
+    static String getClassStr(Object o) {
+        if (o == null) {
+            return "<null>";
+        }
+        return o.getClass().getName();
+    }
+
+    static String getDeviceStr(MidiDevice dev) {
+        if (dev == null) {
+            return "NULL";
+        }
+        return getClassStr(dev) + ", " + (dev.isOpen() ? "OPENED" : "CLOSED");
+    }
+
+    static void log(String s) {
+        System.out.println(s);
+    }
+
+}