From a50f40f7c588446ea57e6babdf345c3d59a78233 Mon Sep 17 00:00:00 2001 From: amenkov Date: Tue, 14 Sep 2010 14:14:18 +0400 Subject: [PATCH] 4933700: RFE: Add way to get device from Receiver and Transmitter Reviewed-by: art --- .../sun/media/sound/AbstractMidiDevice.java | 11 +- .../sound/MidiDeviceReceiverEnvelope.java | 80 ++++++++++ .../sound/MidiDeviceTransmitterEnvelope.java | 85 +++++++++++ .../com/sun/media/sound/SoftReceiver.java | 1 + .../classes/javax/sound/midi/MidiDevice.java | 14 ++ .../sound/midi}/MidiDeviceReceiver.java | 16 +- .../sound/midi/MidiDeviceTransmitter.java | 41 +++++ .../classes/javax/sound/midi/MidiSystem.java | 12 ++ .../MidiDeviceConnectors/TestAllDevices.java | 143 ++++++++++++++++++ 9 files changed, 392 insertions(+), 11 deletions(-) create mode 100644 src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java create mode 100644 src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java rename src/share/classes/{com/sun/media/sound => javax/sound/midi}/MidiDeviceReceiver.java (78%) create mode 100644 src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java create mode 100644 test/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java diff --git a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java index 4a4734d24..97bafe3f9 100644 --- a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice This is necessary for Receivers retrieved via MidiSystem.getReceiver() (which opens the device implicitely). */ - protected abstract class AbstractReceiver implements Receiver { + protected abstract class AbstractReceiver implements MidiDeviceReceiver { private boolean open = true; @@ -508,6 +508,10 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice AbstractMidiDevice.this.closeInternal(this); } + public MidiDevice getMidiDevice() { + return AbstractMidiDevice.this; + } + protected boolean isOpen() { return open; } @@ -529,7 +533,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice * Also, it has some optimizations regarding sending to the Receivers, * for known Receivers, and managing itself in the TransmitterList. */ - protected class BasicTransmitter implements Transmitter { + protected class BasicTransmitter implements MidiDeviceTransmitter { private Receiver receiver = null; TransmitterList tlist = null; @@ -568,6 +572,9 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice } } + public MidiDevice getMidiDevice() { + return AbstractMidiDevice.this; + } } // class BasicTransmitter diff --git a/src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java b/src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java new file mode 100644 index 000000000..9a962bbd4 --- /dev/null +++ b/src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010, 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.*; + + +/** + * Helper class which allows to convert {@code Receiver} + * to {@code MidiDeviceReceiver}. + * + * @author Alex Menkov + */ +public class MidiDeviceReceiverEnvelope implements MidiDeviceReceiver { + + private final MidiDevice device; + private final Receiver receiver; + + /** + * Creates a new {@code MidiDeviceReceiverEnvelope} object which + * envelops the specified {@code Receiver} + * and is owned by the specified {@code MidiDevice}. + * + * @param device the owner {@code MidiDevice} + * @param receiver the {@code Receiver} to be enveloped + */ + public MidiDeviceReceiverEnvelope(MidiDevice device, Receiver receiver) { + if (device == null || receiver == null) { + throw new NullPointerException(); + } + this.device = device; + this.receiver = receiver; + } + + // Receiver implementation + public void close() { + receiver.close(); + } + + public void send(MidiMessage message, long timeStamp) { + receiver.send(message, timeStamp); + } + + // MidiDeviceReceiver implementation + public MidiDevice getMidiDevice() { + return device; + } + + /** + * Obtains the receiver enveloped + * by this {@code MidiDeviceReceiverEnvelope} object. + * + * @return the enveloped receiver + */ + public Receiver getReceiver() { + return receiver; + } +} diff --git a/src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java b/src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java new file mode 100644 index 000000000..e20d430a0 --- /dev/null +++ b/src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010, 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.*; + + +/** + * Helper class which allows to convert {@code Transmitter} + * to {@code MidiDeviceTransmitter}. + * + * @author Alex Menkov + */ +public class MidiDeviceTransmitterEnvelope implements MidiDeviceTransmitter { + + private final MidiDevice device; + private final Transmitter transmitter; + + /** + * Creates a new {@code MidiDeviceTransmitterEnvelope} object which + * envelops the specified {@code Transmitter} + * and is owned by the specified {@code MidiDevice}. + * + * @param device the owner {@code MidiDevice} + * @param transmitter the {@code Transmitter} to be enveloped + */ + public MidiDeviceTransmitterEnvelope(MidiDevice device, Transmitter transmitter) { + if (device == null || transmitter == null) { + throw new NullPointerException(); + } + this.device = device; + this.transmitter = transmitter; + } + + // Transmitter implementation + public void setReceiver(Receiver receiver) { + transmitter.setReceiver(receiver); + } + + public Receiver getReceiver() { + return transmitter.getReceiver(); + } + + public void close() { + transmitter.close(); + } + + + // MidiDeviceReceiver implementation + public MidiDevice getMidiDevice() { + return device; + } + + /** + * Obtains the transmitter enveloped + * by this {@code MidiDeviceTransmitterEnvelope} object. + * + * @return the enveloped transmitter + */ + public Transmitter getTransmitter() { + return transmitter; + } +} diff --git a/src/share/classes/com/sun/media/sound/SoftReceiver.java b/src/share/classes/com/sun/media/sound/SoftReceiver.java index e7c230e51..03a0067f4 100644 --- a/src/share/classes/com/sun/media/sound/SoftReceiver.java +++ b/src/share/classes/com/sun/media/sound/SoftReceiver.java @@ -27,6 +27,7 @@ package com.sun.media.sound; import java.util.TreeMap; import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDeviceReceiver; import javax.sound.midi.MidiMessage; import javax.sound.midi.ShortMessage; diff --git a/src/share/classes/javax/sound/midi/MidiDevice.java b/src/share/classes/javax/sound/midi/MidiDevice.java index 0a8fed478..1e9f225d9 100644 --- a/src/share/classes/javax/sound/midi/MidiDevice.java +++ b/src/share/classes/javax/sound/midi/MidiDevice.java @@ -204,6 +204,9 @@ public interface MidiDevice extends AutoCloseable { * MIDI data. The returned receiver must be closed when the application * has finished using it. * + *

Usually the returned receiver implements + * the {@code MidiDeviceReceiver} interface. + * *

Obtaining a Receiver with this method does not * open the device. To be able to use the device, it has to be * opened explicitly by calling {@link #open}. Also, closing the @@ -223,6 +226,10 @@ public interface MidiDevice extends AutoCloseable { * connected with this MidiDevice. * A receiver can be removed * from the device by closing it. + * + *

Usually the returned receivers implement + * the {@code MidiDeviceReceiver} interface. + * * @return an unmodifiable list of the open receivers * @since 1.5 */ @@ -234,6 +241,9 @@ public interface MidiDevice extends AutoCloseable { * MIDI data The returned transmitter must be closed when the application * has finished using it. * + *

Usually the returned transmitter implements + * the {@code MidiDeviceTransmitter} interface. + * *

Obtaining a Transmitter with this method does not * open the device. To be able to use the device, it has to be * opened explicitly by calling {@link #open}. Also, closing the @@ -253,6 +263,10 @@ public interface MidiDevice extends AutoCloseable { * connected with this MidiDevice. * A transmitter can be removed * from the device by closing it. + * + *

Usually the returned transmitters implement + * the {@code MidiDeviceTransmitter} interface. + * * @return an unmodifiable list of the open transmitters * @since 1.5 */ diff --git a/src/share/classes/com/sun/media/sound/MidiDeviceReceiver.java b/src/share/classes/javax/sound/midi/MidiDeviceReceiver.java similarity index 78% rename from src/share/classes/com/sun/media/sound/MidiDeviceReceiver.java rename to src/share/classes/javax/sound/midi/MidiDeviceReceiver.java index 9c76783db..9ea1df7c3 100644 --- a/src/share/classes/com/sun/media/sound/MidiDeviceReceiver.java +++ b/src/share/classes/javax/sound/midi/MidiDeviceReceiver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -22,20 +22,18 @@ * 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.Receiver; +package javax.sound.midi; /** - * A Receiver with reference to it's MidiDevice object. + *

{@code MidiDeviceReceiver} is a {@code Receiver} which represents + * a MIDI input connector of a {@code MidiDevice} + * (see {@link MidiDevice#getReceiver()}). * - * @author Karl Helgason + * @since 1.7 */ public interface MidiDeviceReceiver extends Receiver { - - /** Obtains the MidiDevice object associated with this Receiver. + /** Obtains a MidiDevice object which is an owner of this Receiver. */ public MidiDevice getMidiDevice(); - } diff --git a/src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java b/src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java new file mode 100644 index 000000000..b6a827188 --- /dev/null +++ b/src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010, 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 javax.sound.midi; + + +/** + *

{@code MidiDeviceTransmitter} is a {@code Transmitter} which represents + * a MIDI input connector of a {@code MidiDevice} + * (see {@link MidiDevice#getTransmitter()}). + * + * @since 1.7 + */ +public interface MidiDeviceTransmitter extends Transmitter { + + /** Obtains a MidiDevice object which is an owner of this Transmitter. + */ + public MidiDevice getMidiDevice(); +} diff --git a/src/share/classes/javax/sound/midi/MidiSystem.java b/src/share/classes/javax/sound/midi/MidiSystem.java index f865d92eb..8c0b5d9eb 100644 --- a/src/share/classes/javax/sound/midi/MidiSystem.java +++ b/src/share/classes/javax/sound/midi/MidiSystem.java @@ -47,6 +47,8 @@ import javax.sound.midi.spi.MidiDeviceProvider; import com.sun.media.sound.JDK13Services; import com.sun.media.sound.ReferenceCountingDevice; import com.sun.media.sound.AutoConnectSequencer; +import com.sun.media.sound.MidiDeviceReceiverEnvelope; +import com.sun.media.sound.MidiDeviceTransmitterEnvelope; /** @@ -225,6 +227,8 @@ public class MidiSystem { /** * Obtains a MIDI receiver from an external MIDI port * or other default device. + * The returned receiver always implements + * the {@code MidiDeviceReceiver} interface. * *

If the system property * javax.sound.midi.Receiver @@ -261,6 +265,9 @@ public class MidiSystem { } else { receiver = device.getReceiver(); } + if (!(receiver instanceof MidiDeviceReceiver)) { + receiver = new MidiDeviceReceiverEnvelope(device, receiver); + } return receiver; } @@ -268,6 +275,8 @@ public class MidiSystem { /** * Obtains a MIDI transmitter from an external MIDI port * or other default source. + * The returned transmitter always implements + * the {@code MidiDeviceTransmitter} interface. * *

If the system property * javax.sound.midi.Transmitter @@ -301,6 +310,9 @@ public class MidiSystem { } else { transmitter = device.getTransmitter(); } + if (!(transmitter instanceof MidiDeviceReceiver)) { + transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter); + } return transmitter; } diff --git a/test/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java b/test/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java new file mode 100644 index 000000000..fa1d964e1 --- /dev/null +++ b/test/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2010, 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. + */ + +/** + * @test + * @bug 4933700 + * @summary Tests that default devices return MidiDeviceTransmitter/Receiver and returned objects return correct MidiDevice + * @compile -source 1.7 TestAllDevices.java + * @run main TestAllDevices + * @author Alex Menkov + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDeviceReceiver; +import javax.sound.midi.MidiDeviceTransmitter; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + + +public class TestAllDevices { + + static boolean failed = false; + + public static void main(String[] args) throws Exception { + out("default receiver:"); + try { + Receiver recv = MidiSystem.getReceiver(); + out(" receiver: " + recv); + if (recv instanceof MidiDeviceReceiver) { + out(" OK"); + } else { + out(" ERROR: not an instance of MidiDeviceReceiver"); + failed = true; + } + } catch (MidiUnavailableException ex) { + // this is not an error + out(" receiver: MidiUnavailableException (test NOT failed)"); + } + + out("default transmitter:"); + try { + Transmitter tran = MidiSystem.getTransmitter(); + out(" transmitter: " + tran); + if (tran instanceof MidiDeviceTransmitter) { + out(" OK"); + } else { + out(" ERROR: not an instance of MidiDeviceTransmitter"); + failed = true; + } + } catch (MidiUnavailableException ex) { + // this is not an error + out(" transmitter: MidiUnavailableException (test NOT failed)"); + } + + MidiDevice.Info[] infos = MidiSystem .getMidiDeviceInfo(); + for (MidiDevice.Info info: infos) { + out(info.toString() + ":"); + try { + MidiDevice dev = MidiSystem.getMidiDevice(info); + dev.open(); + + try { + Receiver recv = dev.getReceiver(); + out(" receiver: " + recv); + if (recv instanceof MidiDeviceReceiver) { + MidiDeviceReceiver devRecv = (MidiDeviceReceiver)recv; + MidiDevice retDev = devRecv.getMidiDevice(); + if (retDev == dev) { + out(" OK"); + } else { + out(" ERROR: getMidiDevice returned incorrect device: " + retDev); + failed = true; + } + } else { + out(" ERROR: not an instance of MidiDeviceReceiver"); + failed = true; + } + } catch (MidiUnavailableException ex) { + // this is not an error + out(" receiver: MidiUnavailableException (test NOT failed)"); + } + + try { + Transmitter tran = dev.getTransmitter(); + out(" transmitter: " + tran); + if (tran instanceof MidiDeviceTransmitter) { + MidiDeviceTransmitter devTran = (MidiDeviceTransmitter)tran; + MidiDevice retDev = devTran.getMidiDevice(); + if (retDev == dev) { + out(" OK"); + } else { + out(" ERROR: getMidiDevice retur4ned incorrect device: " + retDev); + failed = true; + } + } else { + out(" ERROR: not an instance of MidiDeviceTransmitter"); + failed = true; + } + } catch (MidiUnavailableException ex) { + // this is not an error + out(" transmitter: MidiUnavailableException (test NOT failed)"); + } + + dev.close(); + } catch (MidiUnavailableException ex) { + out(" device: MidiUnavailableException (test NOT failed)"); + } + } + + if (failed) { + throw new Exception("Test failed."); + } + } + + static void out(String s) { + System.out.println(s); + } + +} -- GitLab