/*
* Copyright (c) 1999, 2018, 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;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import javax.sound.midi.spi.MidiDeviceProvider;
import javax.sound.midi.spi.MidiFileReader;
import javax.sound.midi.spi.MidiFileWriter;
import javax.sound.midi.spi.SoundbankReader;
import com.sun.media.sound.AutoConnectSequencer;
import com.sun.media.sound.JDK13Services;
import com.sun.media.sound.MidiDeviceReceiverEnvelope;
import com.sun.media.sound.MidiDeviceTransmitterEnvelope;
import com.sun.media.sound.ReferenceCountingDevice;
The MidiSystem
class provides access to the installed MIDI system resources, including devices such as synthesizers, sequencers, and MIDI input and output ports. A typical simple MIDI application might begin by invoking one or more MidiSystem
methods to learn what devices are installed and to obtain the ones needed in that application. The class also has methods for reading files, streams, and URLs that contain standard MIDI file data or soundbanks. You can query the MidiSystem
for the format of a specified MIDI file.
You cannot instantiate a MidiSystem
; all the methods are static.
Properties can be used to specify default MIDI devices. Both system properties and a properties file are considered. The "sound.properties" properties file is read from an implementation-specific location (typically it is the conf
directory in the Java installation directory). The optional "javax.sound.config.file" system property can be used to specify the properties file that will be read as the initial configuration. If a property exists both as a system property and in the properties file, the system property takes precedence. If none is specified, a suitable default is chosen among the available devices. The syntax of the properties file is specified in Properties.load
. The following table lists the available property keys and which methods consider them:
MIDI System Property Keys
Property Key
Interface
Affected Method
javax.sound.midi.Receiver
Receiver
getReceiver
javax.sound.midi.Sequencer
Sequencer
getSequencer
javax.sound.midi.Synthesizer
Synthesizer
getSynthesizer
javax.sound.midi.Transmitter
Transmitter
getTransmitter
The property value consists of the provider class name and the device name, separated by the hash mark ("#"). The provider class name is the fully-qualified name of a concrete MIDI device provider
class. The device name is matched against the String
returned by the getName
method of MidiDevice.Info
. Either the class name, or the device name may be omitted. If only the class name is specified, the trailing hash mark is optional. If the provider class is specified, and it can be successfully retrieved from the installed providers, the list of MidiDevice.Info
objects is retrieved from the provider. Otherwise, or when these devices do not provide a subsequent match, the list is retrieved from getMidiDeviceInfo
to contain all available MidiDevice.Info
objects.
If a device name is specified, the resulting list of MidiDevice.Info
objects is searched: the first one with a matching name, and whose MidiDevice
implements the respective interface, will be returned. If no matching MidiDevice.Info
object is found, or the device name is not specified, the first suitable device from the resulting list will be returned. For Sequencer and Synthesizer, a device is suitable if it implements the respective interface; whereas for Receiver and Transmitter, a device is suitable if it implements neither Sequencer nor Synthesizer and provides at least one Receiver or Transmitter, respectively.
For example, the property javax.sound.midi.Receiver
with a value "com.sun.media.sound.MidiProvider#SunMIDI1"
will have the following consequences when getReceiver
is called: if the class com.sun.media.sound.MidiProvider
exists in the list of installed MIDI device providers, the first Receiver
device with name "SunMIDI1"
will be returned. If it cannot be found, the first Receiver
from that provider will be returned, regardless of name. If there is none, the first Receiver
with name "SunMIDI1"
in the list of all devices (as returned by getMidiDeviceInfo
) will be returned, or, if not found, the first Receiver
that can be found in the list of all devices is returned. If that fails, too, a MidiUnavailableException
is thrown.
Author: Kara Kytle, Florian Bomers, Matthias Pfisterer
/**
* The {@code MidiSystem} class provides access to the installed MIDI system
* resources, including devices such as synthesizers, sequencers, and MIDI input
* and output ports. A typical simple MIDI application might begin by invoking
* one or more {@code MidiSystem} methods to learn what devices are installed
* and to obtain the ones needed in that application.
* <p>
* The class also has methods for reading files, streams, and URLs that contain
* standard MIDI file data or soundbanks. You can query the {@code MidiSystem}
* for the format of a specified MIDI file.
* <p>
* You cannot instantiate a {@code MidiSystem}; all the methods are static.
* <p>
* Properties can be used to specify default MIDI devices. Both system
* properties and a properties file are considered. The "sound.properties"
* properties file is read from an implementation-specific location (typically
* it is the {@code conf} directory in the Java installation directory).
* The optional "javax.sound.config.file" system property can be used to specify
* the properties file that will be read as the initial configuration. If a
* property exists both as a system property and in the properties file, the
* system property takes precedence. If none is specified, a suitable default is
* chosen among the available devices. The syntax of the properties file is
* specified in {@link Properties#load(InputStream) Properties.load}. The
* following table lists the available property keys and which methods consider
* them:
*
* <table class="striped">
* <caption>MIDI System Property Keys</caption>
* <thead>
* <tr>
* <th scope="col">Property Key
* <th scope="col">Interface
* <th scope="col">Affected Method
* </thead>
* <tbody>
* <tr>
* <th scope="row">{@code javax.sound.midi.Receiver}
* <td>{@link Receiver}
* <td>{@link #getReceiver}
* <tr>
* <th scope="row">{@code javax.sound.midi.Sequencer}
* <td>{@link Sequencer}
* <td>{@link #getSequencer}
* <tr>
* <th scope="row">{@code javax.sound.midi.Synthesizer}
* <td>{@link Synthesizer}
* <td>{@link #getSynthesizer}
* <tr>
* <th scope="row">{@code javax.sound.midi.Transmitter}
* <td>{@link Transmitter}
* <td>{@link #getTransmitter}
* </tbody>
* </table>
*
* The property value consists of the provider class name and the device name,
* separated by the hash mark ("#"). The provider class name is the
* fully-qualified name of a concrete
* {@link MidiDeviceProvider MIDI device provider} class. The device name is
* matched against the {@code String} returned by the {@code getName} method of
* {@code MidiDevice.Info}. Either the class name, or the device name may be
* omitted. If only the class name is specified, the trailing hash mark is
* optional.
* <p>
* If the provider class is specified, and it can be successfully retrieved from
* the installed providers, the list of {@code MidiDevice.Info} objects is
* retrieved from the provider. Otherwise, or when these devices do not provide
* a subsequent match, the list is retrieved from {@link #getMidiDeviceInfo} to
* contain all available {@code MidiDevice.Info} objects.
* <p>
* If a device name is specified, the resulting list of {@code MidiDevice.Info}
* objects is searched: the first one with a matching name, and whose
* {@code MidiDevice} implements the respective interface, will be returned. If
* no matching {@code MidiDevice.Info} object is found, or the device name is
* not specified, the first suitable device from the resulting list will be
* returned. For Sequencer and Synthesizer, a device is suitable if it
* implements the respective interface; whereas for Receiver and Transmitter, a
* device is suitable if it implements neither Sequencer nor Synthesizer and
* provides at least one Receiver or Transmitter, respectively.
* <p>
* For example, the property {@code javax.sound.midi.Receiver} with a value
* {@code "com.sun.media.sound.MidiProvider#SunMIDI1"} will have the following
* consequences when {@code getReceiver} is called: if the class
* {@code com.sun.media.sound.MidiProvider} exists in the list of installed MIDI
* device providers, the first {@code Receiver} device with name
* {@code "SunMIDI1"} will be returned. If it cannot be found, the first
* {@code Receiver} from that provider will be returned, regardless of name. If
* there is none, the first {@code Receiver} with name {@code "SunMIDI1"} in the
* list of all devices (as returned by {@code getMidiDeviceInfo}) will be
* returned, or, if not found, the first {@code Receiver} that can be found in
* the list of all devices is returned. If that fails, too, a
* {@code MidiUnavailableException} is thrown.
*
* @author Kara Kytle
* @author Florian Bomers
* @author Matthias Pfisterer
*/
public class MidiSystem {
Private no-args constructor for ensuring against instantiation.
/**
* Private no-args constructor for ensuring against instantiation.
*/
private MidiSystem() {
}
Obtains an array of information objects representing the set of all MIDI devices available on the system. A returned information object can then be used to obtain the corresponding device object, by invoking getMidiDevice
. Returns: an array of MidiDevice.Info
objects, one for each installed MIDI device. If no such devices are installed, an array of length 0 is returned.
/**
* Obtains an array of information objects representing the set of all MIDI
* devices available on the system. A returned information object can then
* be used to obtain the corresponding device object, by invoking
* {@link #getMidiDevice(MidiDevice.Info) getMidiDevice}.
*
* @return an array of {@code MidiDevice.Info} objects, one for each
* installed MIDI device. If no such devices are installed, an array
* of length 0 is returned.
*/
public static MidiDevice.Info[] getMidiDeviceInfo() {
final List<MidiDevice.Info> allInfos = new ArrayList<>();
for (final MidiDeviceProvider provider : getMidiDeviceProviders()) {
Collections.addAll(allInfos, provider.getDeviceInfo());
}
return allInfos.toArray(new MidiDevice.Info[allInfos.size()]);
}
Obtains the requested MIDI device.
Params: - info – a device information object representing the desired device
Throws: - MidiUnavailableException – if the requested device is not available
due to resource restrictions
- IllegalArgumentException – if the info object does not represent a
MIDI device installed on the system
- NullPointerException – if
info
is null
See Also: Returns: the requested device
/**
* Obtains the requested MIDI device.
*
* @param info a device information object representing the desired device
* @return the requested device
* @throws MidiUnavailableException if the requested device is not available
* due to resource restrictions
* @throws IllegalArgumentException if the info object does not represent a
* MIDI device installed on the system
* @throws NullPointerException if {@code info} is {@code null}
* @see #getMidiDeviceInfo
*/
public static MidiDevice getMidiDevice(final MidiDevice.Info info)
throws MidiUnavailableException {
Objects.requireNonNull(info);
for (final MidiDeviceProvider provider : getMidiDeviceProviders()) {
if (provider.isDeviceSupported(info)) {
return provider.getDevice(info);
}
}
throw new IllegalArgumentException(String.format(
"Requested device not installed: %s", info));
}
Obtains a MIDI receiver from an external MIDI port or other default device. The returned receiver always implements the MidiDeviceReceiver
interface. If the system property javax.sound.midi.Receiver
is defined or it is defined in the file "sound.properties", it is used to identify the device that provides the default receiver. For details, refer to the class description
.
If a suitable MIDI port is not available, the Receiver is retrieved from
an installed synthesizer.
If a native receiver provided by the default device does not implement the MidiDeviceReceiver
interface, it will be wrapped in a wrapper class that implements the MidiDeviceReceiver
interface. The corresponding Receiver
method calls will be forwarded to the native receiver.
If this method returns successfully, the MidiDevice
the Receiver
belongs to is opened implicitly, if it is not already open. It is possible to close an implicitly opened device by calling close
on the returned Receiver
. All open Receiver
instances have to be closed in order to release system resources hold by the MidiDevice
. For a detailed description of open/close behaviour see the class description of MidiDevice
.
Throws: - MidiUnavailableException – if the default receiver is not available
due to resource restrictions, or no device providing receivers is
installed in the system
Returns: the default MIDI receiver
/**
* Obtains a MIDI receiver from an external MIDI port or other default
* device. The returned receiver always implements the
* {@code MidiDeviceReceiver} interface.
* <p>
* If the system property {@code javax.sound.midi.Receiver} is defined or it
* is defined in the file "sound.properties", it is used to identify the
* device that provides the default receiver. For details, refer to the
* {@link MidiSystem class description}.
* <p>
* If a suitable MIDI port is not available, the Receiver is retrieved from
* an installed synthesizer.
* <p>
* If a native receiver provided by the default device does not implement
* the {@code MidiDeviceReceiver} interface, it will be wrapped in a wrapper
* class that implements the {@code MidiDeviceReceiver} interface. The
* corresponding {@code Receiver} method calls will be forwarded to the
* native receiver.
* <p>
* If this method returns successfully, the {@link MidiDevice MidiDevice}
* the {@code Receiver} belongs to is opened implicitly, if it is not
* already open. It is possible to close an implicitly opened device by
* calling {@link Receiver#close close} on the returned {@code Receiver}.
* All open {@code Receiver} instances have to be closed in order to release
* system resources hold by the {@code MidiDevice}. For a detailed
* description of open/close behaviour see the class description of
* {@link MidiDevice MidiDevice}.
*
* @return the default MIDI receiver
* @throws MidiUnavailableException if the default receiver is not available
* due to resource restrictions, or no device providing receivers is
* installed in the system
*/
public static Receiver getReceiver() throws MidiUnavailableException {
// may throw MidiUnavailableException
MidiDevice device = getDefaultDeviceWrapper(Receiver.class);
Receiver receiver;
if (device instanceof ReferenceCountingDevice) {
receiver = ((ReferenceCountingDevice) device).getReceiverReferenceCounting();
} else {
receiver = device.getReceiver();
}
if (!(receiver instanceof MidiDeviceReceiver)) {
receiver = new MidiDeviceReceiverEnvelope(device, receiver);
}
return receiver;
}
Obtains a MIDI transmitter from an external MIDI port or other default source. The returned transmitter always implements the MidiDeviceTransmitter
interface. If the system property javax.sound.midi.Transmitter
is defined or it is defined in the file "sound.properties", it is used to identify the device that provides the default transmitter. For details, refer to the class description
.
If a native transmitter provided by the default device does not implement the MidiDeviceTransmitter
interface, it will be wrapped in a wrapper class that implements the MidiDeviceTransmitter
interface. The corresponding Transmitter
method calls will be forwarded to the native transmitter.
If this method returns successfully, the MidiDevice
the Transmitter
belongs to is opened implicitly, if it is not already open. It is possible to close an implicitly opened device by calling close
on the returned Transmitter
. All open Transmitter
instances have to be closed in order to release system resources hold by the MidiDevice
. For a detailed description of open/close behaviour see the class description of MidiDevice
.
Throws: - MidiUnavailableException – if the default transmitter is not
available due to resource restrictions, or no device providing
transmitters is installed in the system
Returns: the default MIDI transmitter
/**
* Obtains a MIDI transmitter from an external MIDI port or other default
* source. The returned transmitter always implements the
* {@code MidiDeviceTransmitter} interface.
* <p>
* If the system property {@code javax.sound.midi.Transmitter} is defined or
* it is defined in the file "sound.properties", it is used to identify the
* device that provides the default transmitter. For details, refer to the
* {@link MidiSystem class description}.
* <p>
* If a native transmitter provided by the default device does not implement
* the {@code MidiDeviceTransmitter} interface, it will be wrapped in a
* wrapper class that implements the {@code MidiDeviceTransmitter}
* interface. The corresponding {@code Transmitter} method calls will be
* forwarded to the native transmitter.
* <p>
* If this method returns successfully, the {@link MidiDevice MidiDevice}
* the {@code Transmitter} belongs to is opened implicitly, if it is not
* already open. It is possible to close an implicitly opened device by
* calling {@link Transmitter#close close} on the returned
* {@code Transmitter}. All open {@code Transmitter} instances have to be
* closed in order to release system resources hold by the
* {@code MidiDevice}. For a detailed description of open/close behaviour
* see the class description of {@link MidiDevice MidiDevice}.
*
* @return the default MIDI transmitter
* @throws MidiUnavailableException if the default transmitter is not
* available due to resource restrictions, or no device providing
* transmitters is installed in the system
*/
public static Transmitter getTransmitter() throws MidiUnavailableException {
// may throw MidiUnavailableException
MidiDevice device = getDefaultDeviceWrapper(Transmitter.class);
Transmitter transmitter;
if (device instanceof ReferenceCountingDevice) {
transmitter = ((ReferenceCountingDevice) device).getTransmitterReferenceCounting();
} else {
transmitter = device.getTransmitter();
}
if (!(transmitter instanceof MidiDeviceTransmitter)) {
transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter);
}
return transmitter;
}
Obtains the default synthesizer.
If the system property javax.sound.midi.Synthesizer
is defined or it is defined in the file "sound.properties", it is used to identify the default synthesizer. For details, refer to the class description
.
Throws: - MidiUnavailableException – if the synthesizer is not available due
to resource restrictions, or no synthesizer is installed in the
system
Returns: the default synthesizer
/**
* Obtains the default synthesizer.
* <p>
* If the system property {@code javax.sound.midi.Synthesizer} is defined or
* it is defined in the file "sound.properties", it is used to identify the
* default synthesizer. For details, refer to the
* {@link MidiSystem class description}.
*
* @return the default synthesizer
* @throws MidiUnavailableException if the synthesizer is not available due
* to resource restrictions, or no synthesizer is installed in the
* system
*/
public static Synthesizer getSynthesizer() throws MidiUnavailableException {
// may throw MidiUnavailableException
return (Synthesizer) getDefaultDeviceWrapper(Synthesizer.class);
}
Obtains the default Sequencer
, connected to a default device. The returned Sequencer
instance is connected to the default Synthesizer
, as returned by getSynthesizer
. If there is no Synthesizer
available, or the default Synthesizer
cannot be opened, the sequencer
is connected to the default Receiver
, as returned by getReceiver
. The connection is made by retrieving a Transmitter
instance from the Sequencer
and setting its Receiver
. Closing and re-opening the sequencer will restore the connection to the default device. This method is equivalent to calling getSequencer(true)
.
If the system property javax.sound.midi.Sequencer
is defined or it is defined in the file "sound.properties", it is used to identify the default sequencer. For details, refer to the class description
.
Throws: - MidiUnavailableException – if the sequencer is not available due to resource restrictions, or there is no
Receiver
available by any installed MidiDevice
, or no sequencer is installed in the system
See Also: Returns: the default sequencer, connected to a default Receiver
/**
* Obtains the default {@code Sequencer}, connected to a default device. The
* returned {@code Sequencer} instance is connected to the default
* {@code Synthesizer}, as returned by {@link #getSynthesizer}. If there is
* no {@code Synthesizer} available, or the default {@code Synthesizer}
* cannot be opened, the {@code sequencer} is connected to the default
* {@code Receiver}, as returned by {@link #getReceiver}. The connection is
* made by retrieving a {@code Transmitter} instance from the
* {@code Sequencer} and setting its {@code Receiver}. Closing and
* re-opening the sequencer will restore the connection to the default
* device.
* <p>
* This method is equivalent to calling {@code getSequencer(true)}.
* <p>
* If the system property {@code javax.sound.midi.Sequencer} is defined or
* it is defined in the file "sound.properties", it is used to identify the
* default sequencer. For details, refer to the
* {@link MidiSystem class description}.
*
* @return the default sequencer, connected to a default Receiver
* @throws MidiUnavailableException if the sequencer is not available due to
* resource restrictions, or there is no {@code Receiver} available
* by any installed {@code MidiDevice}, or no sequencer is installed
* in the system
* @see #getSequencer(boolean)
* @see #getSynthesizer
* @see #getReceiver
*/
public static Sequencer getSequencer() throws MidiUnavailableException {
return getSequencer(true);
}
Obtains the default Sequencer
, optionally connected to a default device. If connected
is true, the returned Sequencer
instance is connected to the default Synthesizer
, as returned by getSynthesizer
. If there is no Synthesizer
available, or the default Synthesizer
cannot be opened, the sequencer
is connected to the default Receiver
, as returned by getReceiver
. The connection is made by retrieving a Transmitter
instance from the Sequencer
and setting its Receiver
. Closing and re-opening the sequencer will restore the connection to the default device.
If connected
is false, the returned Sequencer
instance is not connected, it has no open Transmitters
. In order to play the sequencer on a MIDI device, or a Synthesizer
, it is necessary to get a Transmitter
and set its Receiver
.
If the system property javax.sound.midi.Sequencer
is defined or it is defined in the file "sound.properties", it is used to identify the default sequencer. For details, refer to the class description
.
Params: - connected – whether or not the returned
Sequencer
is connected to the default Synthesizer
Throws: - MidiUnavailableException – if the sequencer is not available due to resource restrictions, or no sequencer is installed in the system, or if
connected
is true, and there is no Receiver
available by any installed MidiDevice
See Also: Returns: the default sequencer Since: 1.5
/**
* Obtains the default {@code Sequencer}, optionally connected to a default
* device.
* <p>
* If {@code connected} is true, the returned {@code Sequencer} instance is
* connected to the default {@code Synthesizer}, as returned by
* {@link #getSynthesizer}. If there is no {@code Synthesizer} available, or
* the default {@code Synthesizer} cannot be opened, the {@code sequencer}
* is connected to the default {@code Receiver}, as returned by
* {@link #getReceiver}. The connection is made by retrieving a
* {@code Transmitter} instance from the {@code Sequencer} and setting its
* {@code Receiver}. Closing and re-opening the sequencer will restore the
* connection to the default device.
* <p>
* If {@code connected} is false, the returned {@code Sequencer} instance is
* not connected, it has no open {@code Transmitters}. In order to play the
* sequencer on a MIDI device, or a {@code Synthesizer}, it is necessary to
* get a {@code Transmitter} and set its {@code Receiver}.
* <p>
* If the system property {@code javax.sound.midi.Sequencer} is defined or
* it is defined in the file "sound.properties", it is used to identify the
* default sequencer. For details, refer to the
* {@link MidiSystem class description}.
*
* @param connected whether or not the returned {@code Sequencer} is
* connected to the default {@code Synthesizer}
* @return the default sequencer
* @throws MidiUnavailableException if the sequencer is not available due to
* resource restrictions, or no sequencer is installed in the
* system, or if {@code connected} is true, and there is no
* {@code Receiver} available by any installed {@code MidiDevice}
* @see #getSynthesizer
* @see #getReceiver
* @since 1.5
*/
public static Sequencer getSequencer(boolean connected)
throws MidiUnavailableException {
Sequencer seq = (Sequencer) getDefaultDeviceWrapper(Sequencer.class);
if (connected) {
// IMPORTANT: this code needs to be synch'ed with
// all AutoConnectSequencer instances,
// (e.g. RealTimeSequencer) because the
// same algorithm for synth retrieval
// needs to be used!
Receiver rec = null;
MidiUnavailableException mue = null;
// first try to connect to the default synthesizer
try {
Synthesizer synth = getSynthesizer();
if (synth instanceof ReferenceCountingDevice) {
rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
} else {
synth.open();
try {
rec = synth.getReceiver();
} finally {
// make sure that the synth is properly closed
if (rec == null) {
synth.close();
}
}
}
} catch (MidiUnavailableException e) {
// something went wrong with synth
if (e instanceof MidiUnavailableException) {
mue = e;
}
}
if (rec == null) {
// then try to connect to the default Receiver
try {
rec = MidiSystem.getReceiver();
} catch (Exception e) {
// something went wrong. Nothing to do then!
if (e instanceof MidiUnavailableException) {
mue = (MidiUnavailableException) e;
}
}
}
if (rec != null) {
seq.getTransmitter().setReceiver(rec);
if (seq instanceof AutoConnectSequencer) {
((AutoConnectSequencer) seq).setAutoConnect(rec);
}
} else {
if (mue != null) {
throw mue;
}
throw new MidiUnavailableException("no receiver available");
}
}
return seq;
}
Constructs a MIDI sound bank by reading it from the specified stream. The stream must point to a valid MIDI soundbank file. In general, MIDI soundbank providers may need to read some data from the stream before determining whether they support it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support this, this method may fail with an IOException
. Params: - stream – the source of the sound bank data
Throws: - InvalidMidiDataException – if the stream does not point to valid
MIDI soundbank data recognized by the system
- IOException – if an I/O error occurred when loading the soundbank
- NullPointerException – if
stream
is null
See Also: Returns: the sound bank
/**
* Constructs a MIDI sound bank by reading it from the specified stream. The
* stream must point to a valid MIDI soundbank file. In general, MIDI
* soundbank providers may need to read some data from the stream before
* determining whether they support it. These parsers must be able to mark
* the stream, read enough data to determine whether they support the
* stream, and, if not, reset the stream's read pointer to its original
* position. If the input stream does not support this, this method may fail
* with an {@code IOException}.
*
* @param stream the source of the sound bank data
* @return the sound bank
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
* @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static Soundbank getSoundbank(final InputStream stream)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(stream);
SoundbankReader sp = null;
Soundbank s = null;
List<SoundbankReader> providers = getSoundbankReaders();
for(int i = 0; i < providers.size(); i++) {
sp = providers.get(i);
s = sp.getSoundbank(stream);
if( s!= null) {
return s;
}
}
throw new InvalidMidiDataException("cannot get soundbank from stream");
}
Constructs a Soundbank
by reading it from the specified URL. The URL must point to a valid MIDI soundbank file. Params: - url – the source of the sound bank data
Throws: - InvalidMidiDataException – if the URL does not point to valid MIDI
soundbank data recognized by the system
- IOException – if an I/O error occurred when loading the soundbank
- NullPointerException – if
url
is null
Returns: the sound bank
/**
* Constructs a {@code Soundbank} by reading it from the specified URL. The
* URL must point to a valid MIDI soundbank file.
*
* @param url the source of the sound bank data
* @return the sound bank
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
* @throws NullPointerException if {@code url} is {@code null}
*/
public static Soundbank getSoundbank(final URL url)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(url);
SoundbankReader sp = null;
Soundbank s = null;
List<SoundbankReader> providers = getSoundbankReaders();
for(int i = 0; i < providers.size(); i++) {
sp = providers.get(i);
s = sp.getSoundbank(url);
if( s!= null) {
return s;
}
}
throw new InvalidMidiDataException("cannot get soundbank from stream");
}
Constructs a Soundbank
by reading it from the specified File
. The File
must point to a valid MIDI soundbank file. Params: - file – the source of the sound bank data
Throws: - InvalidMidiDataException – if the
File
does not point to valid MIDI soundbank data recognized by the system - IOException – if an I/O error occurred when loading the soundbank
- NullPointerException – if
file
is null
Returns: the sound bank
/**
* Constructs a {@code Soundbank} by reading it from the specified
* {@code File}. The {@code File} must point to a valid MIDI soundbank file.
*
* @param file the source of the sound bank data
* @return the sound bank
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
* @throws NullPointerException if {@code file} is {@code null}
*/
public static Soundbank getSoundbank(final File file)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(file);
SoundbankReader sp = null;
Soundbank s = null;
List<SoundbankReader> providers = getSoundbankReaders();
for(int i = 0; i < providers.size(); i++) {
sp = providers.get(i);
s = sp.getSoundbank(file);
if( s!= null) {
return s;
}
}
throw new InvalidMidiDataException("cannot get soundbank from stream");
}
Obtains the MIDI file format of the data in the specified input stream.
The stream must point to valid MIDI file data for a file type recognized
by the system.
This method and/or the code it invokes may need to read some data from the stream to determine whether its data format is supported. The implementation may therefore need to mark the stream, read enough data to determine whether it is in a supported format, and reset the stream's read pointer to its original position. If the input stream does not permit this set of operations, this method may fail with an IOException
.
This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while determining the file format.
Params: - stream – the input stream from which file format information should
be extracted
Throws: - InvalidMidiDataException – if the stream does not point to valid
MIDI file data recognized by the system
- IOException – if an I/O exception occurs while accessing the stream
- NullPointerException – if
stream
is null
See Also: Returns: an MidiFileFormat
object describing the MIDI file format
/**
* Obtains the MIDI file format of the data in the specified input stream.
* The stream must point to valid MIDI file data for a file type recognized
* by the system.
* <p>
* This method and/or the code it invokes may need to read some data from
* the stream to determine whether its data format is supported. The
* implementation may therefore need to mark the stream, read enough data to
* determine whether it is in a supported format, and reset the stream's
* read pointer to its original position. If the input stream does not
* permit this set of operations, this method may fail with an
* {@code IOException}.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while determining the file format.
*
* @param stream the input stream from which file format information should
* be extracted
* @return an {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the stream
* @throws NullPointerException if {@code stream} is {@code null}
* @see #getMidiFileFormat(URL)
* @see #getMidiFileFormat(File)
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static MidiFileFormat getMidiFileFormat(final InputStream stream)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(stream);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
format = reader.getMidiFileFormat( stream ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( format==null ) {
throw new InvalidMidiDataException("input stream is not a supported file type");
} else {
return format;
}
}
Obtains the MIDI file format of the data in the specified URL. The URL
must point to valid MIDI file data for a file type recognized by the
system.
This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while determining the file format.
Params: - url – the URL from which file format information should be
extracted
Throws: - InvalidMidiDataException – if the URL does not point to valid MIDI
file data recognized by the system
- IOException – if an I/O exception occurs while accessing the URL
- NullPointerException – if
url
is null
See Also: Returns: a MidiFileFormat
object describing the MIDI file format
/**
* Obtains the MIDI file format of the data in the specified URL. The URL
* must point to valid MIDI file data for a file type recognized by the
* system.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while determining the file format.
*
* @param url the URL from which file format information should be
* extracted
* @return a {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the URL
* @throws NullPointerException if {@code url} is {@code null}
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(File)
*/
public static MidiFileFormat getMidiFileFormat(final URL url)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(url);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
format = reader.getMidiFileFormat( url ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( format==null ) {
throw new InvalidMidiDataException("url is not a supported file type");
} else {
return format;
}
}
Obtains the MIDI file format of the specified File
. The File
must point to valid MIDI file data for a file type recognized by the system. This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while determining the file format.
Params: - file – the
File
from which file format information should be extracted
Throws: - InvalidMidiDataException – if the
File
does not point to valid MIDI file data recognized by the system - IOException – if an I/O exception occurs while accessing the file
- NullPointerException – if
file
is null
See Also: Returns: a MidiFileFormat
object describing the MIDI file format
/**
* Obtains the MIDI file format of the specified {@code File}. The
* {@code File} must point to valid MIDI file data for a file type
* recognized by the system.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while determining the file format.
*
* @param file the {@code File} from which file format information should
* be extracted
* @return a {@code MidiFileFormat} object describing the MIDI file format
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the file
* @throws NullPointerException if {@code file} is {@code null}
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(URL)
*/
public static MidiFileFormat getMidiFileFormat(final File file)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(file);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
format = reader.getMidiFileFormat( file ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( format==null ) {
throw new InvalidMidiDataException("file is not a supported file type");
} else {
return format;
}
}
Obtains a MIDI sequence from the specified input stream. The stream must
point to valid MIDI file data for a file type recognized by the system.
This method and/or the code it invokes may need to read some data from the stream to determine whether its data format is supported. The implementation may therefore need to mark the stream, read enough data to determine whether it is in a supported format, and reset the stream's read pointer to its original position. If the input stream does not permit this set of operations, this method may fail with an IOException
.
This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while constructing the Sequence
object from the file data.
Params: - stream – the input stream from which the
Sequence
should be constructed
Throws: - InvalidMidiDataException – if the stream does not point to valid
MIDI file data recognized by the system
- IOException – if an I/O exception occurs while accessing the stream
- NullPointerException – if
stream
is null
See Also: Returns: a Sequence
object based on the MIDI file data contained in the input stream
/**
* Obtains a MIDI sequence from the specified input stream. The stream must
* point to valid MIDI file data for a file type recognized by the system.
* <p>
* This method and/or the code it invokes may need to read some data from
* the stream to determine whether its data format is supported. The
* implementation may therefore need to mark the stream, read enough data to
* determine whether it is in a supported format, and reset the stream's
* read pointer to its original position. If the input stream does not
* permit this set of operations, this method may fail with an
* {@code IOException}.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while constructing the {@code Sequence}
* object from the file data.
*
* @param stream the input stream from which the {@code Sequence} should be
* constructed
* @return a {@code Sequence} object based on the MIDI file data contained
* in the input stream
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the stream
* @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static Sequence getSequence(final InputStream stream)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(stream);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
sequence = reader.getSequence( stream ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( sequence==null ) {
throw new InvalidMidiDataException("could not get sequence from input stream");
} else {
return sequence;
}
}
Obtains a MIDI sequence from the specified URL. The URL must point to
valid MIDI file data for a file type recognized by the system.
This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while constructing the Sequence
object from the file data.
Params: - url – the URL from which the
Sequence
should be constructed
Throws: - InvalidMidiDataException – if the URL does not point to valid MIDI
file data recognized by the system
- IOException – if an I/O exception occurs while accessing the URL
- NullPointerException – if
url
is null
Returns: a Sequence
object based on the MIDI file data pointed to by the URL
/**
* Obtains a MIDI sequence from the specified URL. The URL must point to
* valid MIDI file data for a file type recognized by the system.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while constructing the {@code Sequence}
* object from the file data.
*
* @param url the URL from which the {@code Sequence} should be constructed
* @return a {@code Sequence} object based on the MIDI file data pointed to
* by the URL
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the URL
* @throws NullPointerException if {@code url} is {@code null}
*/
public static Sequence getSequence(final URL url)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(url);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
sequence = reader.getSequence( url ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( sequence==null ) {
throw new InvalidMidiDataException("could not get sequence from URL");
} else {
return sequence;
}
}
Obtains a MIDI sequence from the specified File
. The File
must point to valid MIDI file data for a file type recognized by the system. This operation can only succeed for files of a type which can be parsed by an installed file reader. It may fail with an InvalidMidiDataException
even for valid files if no compatible file reader is installed. It will also fail with an InvalidMidiDataException
if a compatible file reader is installed, but encounters errors while constructing the Sequence
object from the file data.
Params: - file – the
File
from which the Sequence
should be constructed
Throws: - InvalidMidiDataException – if the File does not point to valid MIDI
file data recognized by the system
- IOException – if an I/O exception occurs
- NullPointerException – if
file
is null
Returns: a Sequence
object based on the MIDI file data pointed to by the File
/**
* Obtains a MIDI sequence from the specified {@code File}. The {@code File}
* must point to valid MIDI file data for a file type recognized by the
* system.
* <p>
* This operation can only succeed for files of a type which can be parsed
* by an installed file reader. It may fail with an
* {@code InvalidMidiDataException} even for valid files if no compatible
* file reader is installed. It will also fail with an
* {@code InvalidMidiDataException} if a compatible file reader is
* installed, but encounters errors while constructing the {@code Sequence}
* object from the file data.
*
* @param file the {@code File} from which the {@code Sequence} should be
* constructed
* @return a {@code Sequence} object based on the MIDI file data pointed to
* by the File
* @throws InvalidMidiDataException if the File does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
* @throws NullPointerException if {@code file} is {@code null}
*/
public static Sequence getSequence(final File file)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(file);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
for(int i = 0; i < providers.size(); i++) {
MidiFileReader reader = providers.get(i);
try {
sequence = reader.getSequence( file ); // throws IOException
break;
} catch (InvalidMidiDataException e) {
continue;
}
}
if( sequence==null ) {
throw new InvalidMidiDataException("could not get sequence from file");
} else {
return sequence;
}
}
Obtains the set of MIDI file types for which file writing support is
provided by the system.
Returns: array of unique file types. If no file types are supported, an
array of length 0 is returned.
/**
* Obtains the set of MIDI file types for which file writing support is
* provided by the system.
*
* @return array of unique file types. If no file types are supported, an
* array of length 0 is returned.
*/
public static int[] getMidiFileTypes() {
List<MidiFileWriter> providers = getMidiFileWriters();
Set<Integer> allTypes = new HashSet<>();
// gather from all the providers
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
int[] types = writer.getMidiFileTypes();
for (int j = 0; j < types.length; j++ ) {
allTypes.add(types[j]);
}
}
int[] resultTypes = new int[allTypes.size()];
int index = 0;
Iterator<Integer> iterator = allTypes.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
resultTypes[index++] = integer.intValue();
}
return resultTypes;
}
Indicates whether file writing support for the specified MIDI file type
is provided by the system.
Params: - fileType – the file type for which write capabilities are queried
Returns: true
if the file type is supported, otherwise false
/**
* Indicates whether file writing support for the specified MIDI file type
* is provided by the system.
*
* @param fileType the file type for which write capabilities are queried
* @return {@code true} if the file type is supported, otherwise
* {@code false}
*/
public static boolean isFileTypeSupported(int fileType) {
List<MidiFileWriter> providers = getMidiFileWriters();
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
if( writer.isFileTypeSupported(fileType)) {
return true;
}
}
return false;
}
Obtains the set of MIDI file types that the system can write from the
sequence specified.
Params: - sequence – the sequence for which MIDI file type support is queried
Throws: - NullPointerException – if
sequence
is null
Returns: the set of unique supported file types. If no file types are
supported, returns an array of length 0.
/**
* Obtains the set of MIDI file types that the system can write from the
* sequence specified.
*
* @param sequence the sequence for which MIDI file type support is queried
* @return the set of unique supported file types. If no file types are
* supported, returns an array of length 0.
* @throws NullPointerException if {@code sequence} is {@code null}
*/
public static int[] getMidiFileTypes(final Sequence sequence) {
Objects.requireNonNull(sequence);
List<MidiFileWriter> providers = getMidiFileWriters();
Set<Integer> allTypes = new HashSet<>();
// gather from all the providers
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
int[] types = writer.getMidiFileTypes(sequence);
for (int j = 0; j < types.length; j++ ) {
allTypes.add(types[j]);
}
}
int[] resultTypes = new int[allTypes.size()];
int index = 0;
Iterator<Integer> iterator = allTypes.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
resultTypes[index++] = integer.intValue();
}
return resultTypes;
}
Indicates whether a MIDI file of the file type specified can be written
from the sequence indicated.
Params: - fileType – the file type for which write capabilities are queried
- sequence – the sequence for which file writing support is queried
Throws: - NullPointerException – if
sequence
is null
Returns: true
if the file type is supported for this sequence, otherwise false
/**
* Indicates whether a MIDI file of the file type specified can be written
* from the sequence indicated.
*
* @param fileType the file type for which write capabilities are queried
* @param sequence the sequence for which file writing support is queried
* @return {@code true} if the file type is supported for this sequence,
* otherwise {@code false}
* @throws NullPointerException if {@code sequence} is {@code null}
*/
public static boolean isFileTypeSupported(final int fileType,
final Sequence sequence) {
Objects.requireNonNull(sequence);
List<MidiFileWriter> providers = getMidiFileWriters();
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
if( writer.isFileTypeSupported(fileType,sequence)) {
return true;
}
}
return false;
}
Writes a stream of bytes representing a file of the MIDI file type
indicated to the output stream provided.
Params: - in – sequence containing MIDI data to be written to the file
- fileType – the file type of the file to be written to the output
stream
- out – stream to which the file data should be written
Throws: - IOException – if an I/O exception occurs
- IllegalArgumentException – if the file format is not supported by
the system
- NullPointerException – if
in
or out
are null
See Also: Returns: the number of bytes written to the output stream
/**
* Writes a stream of bytes representing a file of the MIDI file type
* indicated to the output stream provided.
*
* @param in sequence containing MIDI data to be written to the file
* @param fileType the file type of the file to be written to the output
* stream
* @param out stream to which the file data should be written
* @return the number of bytes written to the output stream
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file format is not supported by
* the system
* @throws NullPointerException if {@code in} or {@code out} are
* {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public static int write(final Sequence in, final int fileType,
final OutputStream out) throws IOException {
Objects.requireNonNull(in);
Objects.requireNonNull(out);
List<MidiFileWriter> providers = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
int bytesWritten = -2;
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
if( writer.isFileTypeSupported( fileType, in ) ) {
bytesWritten = writer.write(in, fileType, out);
break;
}
}
if (bytesWritten == -2) {
throw new IllegalArgumentException("MIDI file type is not supported");
}
return bytesWritten;
}
Writes a stream of bytes representing a file of the MIDI file type
indicated to the external file provided.
Params: - in – sequence containing MIDI data to be written to the file
- type – the file type of the file to be written to the output stream
- out – external file to which the file data should be written
Throws: - IOException – if an I/O exception occurs
- IllegalArgumentException – if the file type is not supported by the
system
- NullPointerException – if
in
or out
are null
See Also: Returns: the number of bytes written to the file
/**
* Writes a stream of bytes representing a file of the MIDI file type
* indicated to the external file provided.
*
* @param in sequence containing MIDI data to be written to the file
* @param type the file type of the file to be written to the output stream
* @param out external file to which the file data should be written
* @return the number of bytes written to the file
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by the
* system
* @throws NullPointerException if {@code in} or {@code out} are
* {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public static int write(final Sequence in, final int type, final File out)
throws IOException {
Objects.requireNonNull(in);
Objects.requireNonNull(out);
List<MidiFileWriter> providers = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
int bytesWritten = -2;
for (int i = 0; i < providers.size(); i++ ) {
MidiFileWriter writer = providers.get(i);
if( writer.isFileTypeSupported( type, in ) ) {
bytesWritten = writer.write(in, type, out);
break;
}
}
if (bytesWritten == -2) {
throw new IllegalArgumentException("MIDI file type is not supported");
}
return bytesWritten;
}
// HELPER METHODS
Obtains the list of MidiDeviceProviders installed on the system.
Returns: the list of MidiDeviceProviders installed on the system
/**
* Obtains the list of MidiDeviceProviders installed on the system.
*
* @return the list of MidiDeviceProviders installed on the system
*/
@SuppressWarnings("unchecked")
private static List<MidiDeviceProvider> getMidiDeviceProviders() {
return (List<MidiDeviceProvider>) getProviders(MidiDeviceProvider.class);
}
Obtains the list of SoundbankReaders installed on the system.
Returns: the list of SoundbankReaders installed on the system
/**
* Obtains the list of SoundbankReaders installed on the system.
*
* @return the list of SoundbankReaders installed on the system
*/
@SuppressWarnings("unchecked")
private static List<SoundbankReader> getSoundbankReaders() {
return (List<SoundbankReader>) getProviders(SoundbankReader.class);
}
Obtains the list of MidiFileWriters installed on the system.
Returns: the list of MidiFileWriters installed on the system
/**
* Obtains the list of MidiFileWriters installed on the system.
*
* @return the list of MidiFileWriters installed on the system
*/
@SuppressWarnings("unchecked")
private static List<MidiFileWriter> getMidiFileWriters() {
return (List<MidiFileWriter>) getProviders(MidiFileWriter.class);
}
Obtains the list of MidiFileReaders installed on the system.
Returns: the list of MidiFileReaders installed on the system
/**
* Obtains the list of MidiFileReaders installed on the system.
*
* @return the list of MidiFileReaders installed on the system
*/
@SuppressWarnings("unchecked")
private static List<MidiFileReader> getMidiFileReaders() {
return (List<MidiFileReader>) getProviders(MidiFileReader.class);
}
Attempts to locate and return a default MidiDevice of the specified type. This method wraps getDefaultDevice
. It catches the IllegalArgumentException
thrown by getDefaultDevice
and instead throws a MidiUnavailableException
, with the catched exception chained. Params: - deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Throws: - MidiUnavailableException – on failure
Returns: default MidiDevice of the specified type
/**
* Attempts to locate and return a default MidiDevice of the specified type.
* This method wraps {@link #getDefaultDevice}. It catches the
* {@code IllegalArgumentException} thrown by {@code getDefaultDevice} and
* instead throws a {@code MidiUnavailableException}, with the catched
* exception chained.
*
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return default MidiDevice of the specified type
* @throws MidiUnavailableException on failure
*/
private static MidiDevice getDefaultDeviceWrapper(Class<?> deviceClass)
throws MidiUnavailableException{
try {
return getDefaultDevice(deviceClass);
} catch (IllegalArgumentException iae) {
MidiUnavailableException mae = new MidiUnavailableException();
mae.initCause(iae);
throw mae;
}
}
Attempts to locate and return a default MidiDevice of the specified type.
Params: - deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Throws: - IllegalArgumentException – on failure
Returns: default MidiDevice of the specified type.
/**
* Attempts to locate and return a default MidiDevice of the specified type.
*
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return default MidiDevice of the specified type.
* @throws IllegalArgumentException on failure
*/
private static MidiDevice getDefaultDevice(Class<?> deviceClass) {
List<MidiDeviceProvider> providers = getMidiDeviceProviders();
String providerClassName = JDK13Services.getDefaultProviderClassName(deviceClass);
String instanceName = JDK13Services.getDefaultInstanceName(deviceClass);
MidiDevice device;
if (providerClassName != null) {
MidiDeviceProvider defaultProvider = getNamedProvider(providerClassName, providers);
if (defaultProvider != null) {
if (instanceName != null) {
device = getNamedDevice(instanceName, defaultProvider, deviceClass);
if (device != null) {
return device;
}
}
device = getFirstDevice(defaultProvider, deviceClass);
if (device != null) {
return device;
}
}
}
/*
* - Provider class not specified or cannot be found, or
* - provider class specified, and no appropriate device available, or
* - provider class and instance specified and instance cannot be found
* or is not appropriate
*/
if (instanceName != null) {
device = getNamedDevice(instanceName, providers, deviceClass);
if (device != null) {
return device;
}
}
/*
* No defaults are specified, or if something is specified, everything
* failed
*/
device = getFirstDevice(providers, deviceClass);
if (device != null) {
return device;
}
throw new IllegalArgumentException("Requested device not installed");
}
Return a MidiDeviceProvider of a given class from the list of
MidiDeviceProviders.
Params: - providerClassName – The class name of the provider to be returned
- providers – The list of MidiDeviceProviders that is searched
Returns: A MidiDeviceProvider of the requested class, or null if none is
found
/**
* Return a MidiDeviceProvider of a given class from the list of
* MidiDeviceProviders.
*
* @param providerClassName The class name of the provider to be returned
* @param providers The list of MidiDeviceProviders that is searched
* @return A MidiDeviceProvider of the requested class, or null if none is
* found
*/
private static MidiDeviceProvider getNamedProvider(String providerClassName,
List<MidiDeviceProvider> providers) {
for(int i = 0; i < providers.size(); i++) {
MidiDeviceProvider provider = providers.get(i);
if (provider.getClass().getName().equals(providerClassName)) {
return provider;
}
}
return null;
}
Return a MidiDevice with a given name from a given MidiDeviceProvider.
Params: - deviceName – The name of the MidiDevice to be returned
- provider – The MidiDeviceProvider to check for MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Returns: A MidiDevice matching the requirements, or null if none is found
/**
* Return a MidiDevice with a given name from a given MidiDeviceProvider.
*
* @param deviceName The name of the MidiDevice to be returned
* @param provider The MidiDeviceProvider to check for MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return A MidiDevice matching the requirements, or null if none is found
*/
private static MidiDevice getNamedDevice(String deviceName,
MidiDeviceProvider provider,
Class<?> deviceClass) {
MidiDevice device;
// try to get MIDI port
device = getNamedDevice(deviceName, provider, deviceClass,
false, false);
if (device != null) {
return device;
}
if (deviceClass == Receiver.class) {
// try to get Synthesizer
device = getNamedDevice(deviceName, provider, deviceClass,
true, false);
if (device != null) {
return device;
}
}
return null;
}
Return a MidiDevice with a given name from a given MidiDeviceProvider.
Params: - deviceName – The name of the MidiDevice to be returned
- provider – The MidiDeviceProvider to check for MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
- allowSynthesizer – if true, Synthesizers are considered
appropriate. Otherwise only pure MidiDevices are considered
appropriate (unless allowSequencer is true). This flag only has
an effect for deviceClass Receiver and Transmitter. For other
device classes (Sequencer and Synthesizer), this flag has no
effect.
- allowSequencer – if true, Sequencers are considered appropriate.
Otherwise only pure MidiDevices are considered appropriate
(unless allowSynthesizer is true). This flag only has an effect
for deviceClass Receiver and Transmitter. For other device
classes (Sequencer and Synthesizer), this flag has no effect.
Returns: A MidiDevice matching the requirements, or null if none is found
/**
* Return a MidiDevice with a given name from a given MidiDeviceProvider.
*
* @param deviceName The name of the MidiDevice to be returned
* @param provider The MidiDeviceProvider to check for MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @param allowSynthesizer if true, Synthesizers are considered
* appropriate. Otherwise only pure MidiDevices are considered
* appropriate (unless allowSequencer is true). This flag only has
* an effect for deviceClass Receiver and Transmitter. For other
* device classes (Sequencer and Synthesizer), this flag has no
* effect.
* @param allowSequencer if true, Sequencers are considered appropriate.
* Otherwise only pure MidiDevices are considered appropriate
* (unless allowSynthesizer is true). This flag only has an effect
* for deviceClass Receiver and Transmitter. For other device
* classes (Sequencer and Synthesizer), this flag has no effect.
* @return A MidiDevice matching the requirements, or null if none is found
*/
private static MidiDevice getNamedDevice(String deviceName,
MidiDeviceProvider provider,
Class<?> deviceClass,
boolean allowSynthesizer,
boolean allowSequencer) {
MidiDevice.Info[] infos = provider.getDeviceInfo();
for (int i = 0; i < infos.length; i++) {
if (infos[i].getName().equals(deviceName)) {
MidiDevice device = provider.getDevice(infos[i]);
if (isAppropriateDevice(device, deviceClass,
allowSynthesizer, allowSequencer)) {
return device;
}
}
}
return null;
}
Return a MidiDevice with a given name from a list of MidiDeviceProviders.
Params: - deviceName – The name of the MidiDevice to be returned
- providers – The List of MidiDeviceProviders to check for
MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Returns: A Mixer matching the requirements, or null if none is found
/**
* Return a MidiDevice with a given name from a list of MidiDeviceProviders.
*
* @param deviceName The name of the MidiDevice to be returned
* @param providers The List of MidiDeviceProviders to check for
* MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return A Mixer matching the requirements, or null if none is found
*/
private static MidiDevice getNamedDevice(String deviceName,
List<MidiDeviceProvider> providers,
Class<?> deviceClass) {
MidiDevice device;
// try to get MIDI port
device = getNamedDevice(deviceName, providers, deviceClass,
false, false);
if (device != null) {
return device;
}
if (deviceClass == Receiver.class) {
// try to get Synthesizer
device = getNamedDevice(deviceName, providers, deviceClass,
true, false);
if (device != null) {
return device;
}
}
return null;
}
Return a MidiDevice with a given name from a list of MidiDeviceProviders.
Params: - deviceName – The name of the MidiDevice to be returned
- providers – The List of MidiDeviceProviders to check for
MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
- allowSynthesizer – if true, Synthesizers are considered
appropriate. Otherwise only pure MidiDevices are considered
appropriate (unless allowSequencer is true). This flag only has
an effect for deviceClass Receiver and Transmitter. For other
device classes (Sequencer and Synthesizer), this flag has no
effect.
- allowSequencer – if true, Sequencers are considered appropriate.
Otherwise only pure MidiDevices are considered appropriate
(unless allowSynthesizer is true). This flag only has an effect
for deviceClass Receiver and Transmitter. For other device
classes (Sequencer and Synthesizer), this flag has no effect.
Returns: A Mixer matching the requirements, or null if none is found
/**
* Return a MidiDevice with a given name from a list of MidiDeviceProviders.
*
* @param deviceName The name of the MidiDevice to be returned
* @param providers The List of MidiDeviceProviders to check for
* MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @param allowSynthesizer if true, Synthesizers are considered
* appropriate. Otherwise only pure MidiDevices are considered
* appropriate (unless allowSequencer is true). This flag only has
* an effect for deviceClass Receiver and Transmitter. For other
* device classes (Sequencer and Synthesizer), this flag has no
* effect.
* @param allowSequencer if true, Sequencers are considered appropriate.
* Otherwise only pure MidiDevices are considered appropriate
* (unless allowSynthesizer is true). This flag only has an effect
* for deviceClass Receiver and Transmitter. For other device
* classes (Sequencer and Synthesizer), this flag has no effect.
* @return A Mixer matching the requirements, or null if none is found
*/
private static MidiDevice getNamedDevice(String deviceName,
List<MidiDeviceProvider> providers,
Class<?> deviceClass,
boolean allowSynthesizer,
boolean allowSequencer) {
for(int i = 0; i < providers.size(); i++) {
MidiDeviceProvider provider = providers.get(i);
MidiDevice device = getNamedDevice(deviceName, provider,
deviceClass,
allowSynthesizer,
allowSequencer);
if (device != null) {
return device;
}
}
return null;
}
From a given MidiDeviceProvider, return the first appropriate device.
Params: - provider – The MidiDeviceProvider to check for MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Returns: A MidiDevice is considered appropriate, or null if no appropriate
device is found
/**
* From a given MidiDeviceProvider, return the first appropriate device.
*
* @param provider The MidiDeviceProvider to check for MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return A MidiDevice is considered appropriate, or null if no appropriate
* device is found
*/
private static MidiDevice getFirstDevice(MidiDeviceProvider provider,
Class<?> deviceClass) {
MidiDevice device;
// try to get MIDI port
device = getFirstDevice(provider, deviceClass,
false, false);
if (device != null) {
return device;
}
if (deviceClass == Receiver.class) {
// try to get Synthesizer
device = getFirstDevice(provider, deviceClass,
true, false);
if (device != null) {
return device;
}
}
return null;
}
From a given MidiDeviceProvider, return the first appropriate device.
Params: - provider – The MidiDeviceProvider to check for MidiDevices
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
- allowSynthesizer – if true, Synthesizers are considered
appropriate. Otherwise only pure MidiDevices are considered
appropriate (unless allowSequencer is true). This flag only has
an effect for deviceClass Receiver and Transmitter. For other
device classes (Sequencer and Synthesizer), this flag has no
effect.
- allowSequencer – if true, Sequencers are considered appropriate.
Otherwise only pure MidiDevices are considered appropriate
(unless allowSynthesizer is true). This flag only has an effect
for deviceClass Receiver and Transmitter. For other device
classes (Sequencer and Synthesizer), this flag has no effect.
Returns: A MidiDevice is considered appropriate, or null if no appropriate
device is found
/**
* From a given MidiDeviceProvider, return the first appropriate device.
*
* @param provider The MidiDeviceProvider to check for MidiDevices
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @param allowSynthesizer if true, Synthesizers are considered
* appropriate. Otherwise only pure MidiDevices are considered
* appropriate (unless allowSequencer is true). This flag only has
* an effect for deviceClass Receiver and Transmitter. For other
* device classes (Sequencer and Synthesizer), this flag has no
* effect.
* @param allowSequencer if true, Sequencers are considered appropriate.
* Otherwise only pure MidiDevices are considered appropriate
* (unless allowSynthesizer is true). This flag only has an effect
* for deviceClass Receiver and Transmitter. For other device
* classes (Sequencer and Synthesizer), this flag has no effect.
* @return A MidiDevice is considered appropriate, or null if no appropriate
* device is found
*/
private static MidiDevice getFirstDevice(MidiDeviceProvider provider,
Class<?> deviceClass,
boolean allowSynthesizer,
boolean allowSequencer) {
MidiDevice.Info[] infos = provider.getDeviceInfo();
for (int j = 0; j < infos.length; j++) {
MidiDevice device = provider.getDevice(infos[j]);
if (isAppropriateDevice(device, deviceClass,
allowSynthesizer, allowSequencer)) {
return device;
}
}
return null;
}
From a List of MidiDeviceProviders, return the first appropriate
MidiDevice.
Params: - providers – The List of MidiDeviceProviders to search
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
Returns: A MidiDevice that is considered appropriate, or null if none is
found
/**
* From a List of MidiDeviceProviders, return the first appropriate
* MidiDevice.
*
* @param providers The List of MidiDeviceProviders to search
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @return A MidiDevice that is considered appropriate, or null if none is
* found
*/
private static MidiDevice getFirstDevice(List<MidiDeviceProvider> providers,
Class<?> deviceClass) {
MidiDevice device;
// try to get MIDI port
device = getFirstDevice(providers, deviceClass,
false, false);
if (device != null) {
return device;
}
if (deviceClass == Receiver.class) {
// try to get Synthesizer
device = getFirstDevice(providers, deviceClass,
true, false);
if (device != null) {
return device;
}
}
return null;
}
From a List of MidiDeviceProviders, return the first appropriate
MidiDevice.
Params: - providers – The List of MidiDeviceProviders to search
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
- allowSynthesizer – if true, Synthesizers are considered
appropriate. Otherwise only pure MidiDevices are considered
appropriate (unless allowSequencer is true). This flag only has
an effect for deviceClass Receiver and Transmitter. For other
device classes (Sequencer and Synthesizer), this flag has no
effect.
- allowSequencer – if true, Sequencers are considered appropriate.
Otherwise only pure MidiDevices are considered appropriate
(unless allowSynthesizer is true). This flag only has an effect
for deviceClass Receiver and Transmitter. For other device
classes (Sequencer and Synthesizer), this flag has no effect.
Returns: A MidiDevice that is considered appropriate, or null if none is
found
/**
* From a List of MidiDeviceProviders, return the first appropriate
* MidiDevice.
*
* @param providers The List of MidiDeviceProviders to search
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @param allowSynthesizer if true, Synthesizers are considered
* appropriate. Otherwise only pure MidiDevices are considered
* appropriate (unless allowSequencer is true). This flag only has
* an effect for deviceClass Receiver and Transmitter. For other
* device classes (Sequencer and Synthesizer), this flag has no
* effect.
* @param allowSequencer if true, Sequencers are considered appropriate.
* Otherwise only pure MidiDevices are considered appropriate
* (unless allowSynthesizer is true). This flag only has an effect
* for deviceClass Receiver and Transmitter. For other device
* classes (Sequencer and Synthesizer), this flag has no effect.
* @return A MidiDevice that is considered appropriate, or null if none is
* found
*/
private static MidiDevice getFirstDevice(List<MidiDeviceProvider> providers,
Class<?> deviceClass,
boolean allowSynthesizer,
boolean allowSequencer) {
for(int i = 0; i < providers.size(); i++) {
MidiDeviceProvider provider = providers.get(i);
MidiDevice device = getFirstDevice(provider, deviceClass,
allowSynthesizer,
allowSequencer);
if (device != null) {
return device;
}
}
return null;
}
Checks if a MidiDevice is appropriate. If deviceClass is Synthesizer or
Sequencer, a device implementing the respective interface is considered
appropriate. If deviceClass is Receiver or Transmitter, a device is
considered appropriate if it implements neither Synthesizer nor
Transmitter, and if it can provide at least one Receiver or Transmitter,
respectively.
Params: - device – the MidiDevice to test
- deviceClass – The requested device type, one of Synthesizer.class,
Sequencer.class, Receiver.class or Transmitter.class
- allowSynthesizer – if true, Synthesizers are considered
appropriate. Otherwise only pure MidiDevices are considered
appropriate (unless allowSequencer is true). This flag only has
an effect for deviceClass Receiver and Transmitter. For other
device classes (Sequencer and Synthesizer), this flag has no
effect.
- allowSequencer – if true, Sequencers are considered appropriate.
Otherwise only pure MidiDevices are considered appropriate
(unless allowSynthesizer is true). This flag only has an effect
for deviceClass Receiver and Transmitter. For other device
classes (Sequencer and Synthesizer), this flag has no effect.
Returns: true if the device is considered appropriate according to the
rules given above, false otherwise
/**
* Checks if a MidiDevice is appropriate. If deviceClass is Synthesizer or
* Sequencer, a device implementing the respective interface is considered
* appropriate. If deviceClass is Receiver or Transmitter, a device is
* considered appropriate if it implements neither Synthesizer nor
* Transmitter, and if it can provide at least one Receiver or Transmitter,
* respectively.
*
* @param device the MidiDevice to test
* @param deviceClass The requested device type, one of Synthesizer.class,
* Sequencer.class, Receiver.class or Transmitter.class
* @param allowSynthesizer if true, Synthesizers are considered
* appropriate. Otherwise only pure MidiDevices are considered
* appropriate (unless allowSequencer is true). This flag only has
* an effect for deviceClass Receiver and Transmitter. For other
* device classes (Sequencer and Synthesizer), this flag has no
* effect.
* @param allowSequencer if true, Sequencers are considered appropriate.
* Otherwise only pure MidiDevices are considered appropriate
* (unless allowSynthesizer is true). This flag only has an effect
* for deviceClass Receiver and Transmitter. For other device
* classes (Sequencer and Synthesizer), this flag has no effect.
* @return true if the device is considered appropriate according to the
* rules given above, false otherwise
*/
private static boolean isAppropriateDevice(MidiDevice device,
Class<?> deviceClass,
boolean allowSynthesizer,
boolean allowSequencer) {
if (deviceClass.isInstance(device)) {
// This clause is for deviceClass being either Synthesizer
// or Sequencer.
return true;
} else {
// Now the case that deviceClass is Transmitter or
// Receiver. If neither allowSynthesizer nor allowSequencer is
// true, we require device instances to be
// neither Synthesizer nor Sequencer, since we only want
// devices representing MIDI ports.
// Otherwise, the respective type is accepted, too
if ( (! (device instanceof Sequencer) &&
! (device instanceof Synthesizer) ) ||
((device instanceof Sequencer) && allowSequencer) ||
((device instanceof Synthesizer) && allowSynthesizer)) {
// And of cource, the device has to be able to provide
// Receivers or Transmitters.
if ((deviceClass == Receiver.class &&
device.getMaxReceivers() != 0) ||
(deviceClass == Transmitter.class &&
device.getMaxTransmitters() != 0)) {
return true;
}
}
}
return false;
}
Obtains the set of services currently installed on the system using the
SPI mechanism in 1.3.
Params: - providerClass – The type of providers requested. This should be one
of AudioFileReader.class, AudioFileWriter.class,
FormatConversionProvider.class, MixerProvider.class,
MidiDeviceProvider.class, MidiFileReader.class,
MidiFileWriter.class or SoundbankReader.class.
Returns: a List of instances of providers for the requested service. If no
providers are available, a List of length 0 will be returned.
/**
* Obtains the set of services currently installed on the system using the
* SPI mechanism in 1.3.
*
* @param providerClass The type of providers requested. This should be one
* of AudioFileReader.class, AudioFileWriter.class,
* FormatConversionProvider.class, MixerProvider.class,
* MidiDeviceProvider.class, MidiFileReader.class,
* MidiFileWriter.class or SoundbankReader.class.
* @return a List of instances of providers for the requested service. If no
* providers are available, a List of length 0 will be returned.
*/
private static List<?> getProviders(Class<?> providerClass) {
return JDK13Services.getProviders(providerClass);
}
}