1125 lines
39 KiB
Java
Raw Permalink Normal View History

2021-07-16 17:12:20 -05:00
/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
**
* Comment: not really modified but is a part of JSound "front-end".
*/
/*
* @(#)MidiSystem.java 1.49 03/01/27
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package javax.sound.midi;
import java.io.FileInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Vector;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import javax.sound.midi.spi.MidiFileWriter;
import javax.sound.midi.spi.MidiFileReader;
import javax.sound.midi.spi.SoundbankReader;
import javax.sound.midi.spi.MidiDeviceProvider;
/**
* The <code>MidiSystem</code> 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</code> 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</code> for the format of a specified MIDI file.
* <p>
* You cannot instantiate a <code>MidiSystem</code>; all the methods are
* static.
*
* @version 1.49, 03/01/27
* @author Kara Kytle
*/
public class MidiSystem {
/**
* Private strings for default services class and method
*/
private static final String defaultServicesClassName =
"com.sun.media.sound.DefaultServices";
private static final String jdk13ServicesClassName =
"com.sun.media.sound.JDK13Services";
private static final String servicesMethodName =
"getProviders";
private static final Class[] servicesParamTypes =
new Class[] { String.class };
/**
* 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
* {@link #getMidiDevice(MidiDevice.Info) getMidiDevice}.
*
* @return an array of <code>MidiDevice.Info</code> 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() {
return getGenericDeviceInfo( MidiDevice.class );
}
/**
* 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
* @see #getMidiDeviceInfo
*/
public static MidiDevice getMidiDevice(MidiDevice.Info info) throws MidiUnavailableException {
return (MidiDevice)getGenericDevice( null, info );
}
/*
* re-deleted
*/
/*
* un-deleted, AbstractPlayer.addPlatformSynth() conflict
*/
/**
* Obtains an array of information objects representing
* the set of MIDI devices available on the system that support
* one or more receivers.
* A returned information object can then be used to obtain a
* receiver from the corresponding device object, by invoking
* {@link #getReceiver(MidiDevice.Info) getReceiver}.
*
* @return an array of <code>MidiDevice.Info</code> objects, one
* for each installed device that supports one or more
* {@link Receiver Receivers}.
* If no such devices are installed, an array of length
* 0 is returned.
*/
/*
public static MidiDevice.Info[] getReceiverInfo() {
return getGenericDeviceInfo( Receiver.class );
}
*/
/*
* re-changed
*/
/*
* un-changed, AbstractPlayer.addPlatformSynth() conflict
*/
/**
* Obtains a MIDI receiver from an external MIDI port
* or other default source.
* @return the default MIDI receiver
* @throws MidiUnavailableException if the default receiver is not
* available due to resource restrictions
*/
public static Receiver getReceiver() throws MidiUnavailableException {
return ( ((MidiDevice)getGenericDevice(Receiver.class, null)).getReceiver() );
}
/*
public static Receiver getReceiver(MidiDevice.Info info) throws MidiUnavailableException {
return ( ((MidiDevice)getGenericDevice(Receiver.class, info)).getReceiver() );
}
*/
/*
* deleted
*/
/**
* Obtains an array of information objects representing
* the set of MIDI devices available on the system that support
* one or more transmitters.
* A returned information object can then be used to obtain a
* transmitter from the corresponding device object, by invoking
* {@link #getTransmitter(MidiDevice.Info) getTransmitter}.
*
* @return an array of <code>MidiDevice.Info</code> objects, one
* for each installed device that supports one or more
* {@link Transmitter Transmitters}.
* If no such devices are installed, an array of length
* 0 is returned.
*/
/* public static MidiDevice.Info[] getTransmitterInfo() {
return getGenericDeviceInfo( Transmitter.class );
}
*/
/**
* Obtains a MIDI transmitter from an external MIDI port
* or other default source.
* @return the default MIDI transmitter
* @throws MidiUnavailableException if the default transmitter is not
* available due to resource restrictions
*/
public static Transmitter getTransmitter() throws MidiUnavailableException {
return ( ((MidiDevice)getGenericDevice(Transmitter.class, null)).getTransmitter() );
}
/* public static Transmitter getTransmitter(MidiDevice.Info info) throws MidiUnavailableException {
return ( ((MidiDevice)getGenericDevice(Transmitter.class, info)).getTransmitter() );
}
*/
/*
* deleted
*/
/**
* Obtains an array of information objects representing
* the set of synthesizers available on the system. A
* returned information object can then be used to obtain the corresponding
* synthesizer, by invoking
* {@link #getSynthesizer(MidiDevice.Info) getSynthesizer}.
*
* @return an array of <code>MidiDevice.Info</code> objects, one
* for each installed device that is a {@link Synthesizer}.
* If no synthesizers are installed, an array of length
* 0 is returned.
*/
/* public static MidiDevice.Info[] getSynthesizerInfo() {
return getGenericDeviceInfo( Synthesizer.class );
}
*/
/**
* Obtains the default synthesizer.
* @return the default synthesizer
* @throws MidiUnavailableException if the synthesizer is not
* available due to resource restrictions
*/
public static Synthesizer getSynthesizer() throws MidiUnavailableException {
return (Synthesizer) getGenericDevice( Synthesizer.class, null );
}
/* public static Synthesizer getSynthesizer(MidiDevice.Info info) {
return (Synthesizer) getGenericDevice( Synthesizer.class, info );
}
*/
/*
* deleted
*/
/**
* Obtains an array of information objects representing
* the set of sequencers available on the system. A
* returned information object can then be used to obtain the corresponding
* sequencer, by invoking
* {@link #getSequencer(MidiDevice.Info) getSequencer}.
*
* @return an array of <code>MidiDevice.Info</code> objects, one
* for each installed device that is a {@link Sequencer}.
* If no sequencers are installed, an array of length
* 0 is returned.
*/
/* public static MidiDevice.Info[] getSequencerInfo() {
return getGenericDeviceInfo( Sequencer.class );
}
*/
/**
* Obtains the default sequencer.
* @return the default sequencer
* @throws MidiUnavailableException if the sequencer is not
* available due to resource restrictions
*/
public static Sequencer getSequencer() throws MidiUnavailableException {
return (Sequencer) getGenericDevice( Sequencer.class, null );
}
/* public static Sequencer getSequencer(MidiDevice.Info info) {
return (Sequencer) getGenericDevice( Sequencer.class, info );
}
*/
/**
* 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.
* @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
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static Soundbank getSoundbank(InputStream stream)
throws InvalidMidiDataException, IOException {
SoundbankReader sp = null;
Soundbank s = null;
Vector providers = getSoundbankReaders();
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.size()-1; i >= 0; i-- ) {
sp = (SoundbankReader)providers.elementAt(i);
s = sp.getSoundbank(stream);
if( s!= null) {
return s;
}
}
throw new InvalidMidiDataException("cannot get soundbank from stream");
}
/**
* Constructs a <code>Soundbank</code> 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
*/
public static Soundbank getSoundbank(URL url)
throws InvalidMidiDataException, IOException {
SoundbankReader sp = null;
Soundbank s = null;
Vector providers = getSoundbankReaders();
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.size()-1; i >= 0; i-- ) {
sp = (SoundbankReader)providers.elementAt(i);
s = sp.getSoundbank(url);
if( s!= null) {
return s;
}
}
throw new InvalidMidiDataException("cannot get soundbank from stream");
}
/**
* Constructs a <code>Soundbank</code> by reading it from the specified
* <code>File</code>.
* The <code>File</code> 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</code> does not
* point to valid MIDI soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
*/
public static Soundbank getSoundbank(File file)
throws InvalidMidiDataException, IOException {
FileInputStream fis = new FileInputStream( file );
return getSoundbank( fis );
}
/**
* 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</code>.
* <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 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.
*
* @param stream the input stream from which file format information
* should be extracted
* @return an <code>MidiFileFormat</code> 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
* @see #getMidiFileFormat(URL)
* @see #getMidiFileFormat(File)
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static MidiFileFormat getMidiFileFormat(InputStream stream)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
MidiFileFormat format = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
format = providers[i].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.
* <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 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.
*
* @param url the URL from which file format information should be
* extracted
* @return a <code>MidiFileFormat</code> 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
*
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(File)
*/
public static MidiFileFormat getMidiFileFormat(URL url)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
MidiFileFormat format = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
format = providers[i].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 <code>File</code>. The
* <code>File</code> 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 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.
*
* @param file the <code>File</code> from which file format information
* should be extracted
* @return a <code>MidiFileFormat</code> object describing the MIDI file
* format
* @throws InvalidMidiDataException if the <code>File</code> does not point
* to valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the file
*
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(URL)
*/
public static MidiFileFormat getMidiFileFormat(File file)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
MidiFileFormat format = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
format = providers[i].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.
* <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</code>.
* <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 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 <code>Sequence</code>
* object from the file data.
*
* @param stream the input stream from which the <code>Sequence</code>
* should be constructed
* @return a <code>Sequence</code> 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
* @see InputStream#markSupported
* @see InputStream#mark
*/
public static Sequence getSequence(InputStream stream)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
Sequence sequence = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
sequence = providers[i].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.
* <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 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 <code>Sequence</code>
* object from the file data.
*
* @param url the URL from which the <code>Sequence</code> should be
* constructed
* @return a <code>Sequence</code> 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
*/
public static Sequence getSequence(URL url)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
Sequence sequence = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
sequence = providers[i].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 <code>File</code>.
* The <code>File</code> 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 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 <code>Sequence</code>
* object from the file data.
*
* @param file the <code>File</code> from which the <code>Sequence</code>
* should be constructed
* @return a <code>Sequence</code> 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
*/
public static Sequence getSequence(File file)
throws InvalidMidiDataException, IOException {
MidiFileReader providers[] = getMidiFileReaders();
Sequence sequence = null;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
try {
sequence = providers[i].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.
* @return array of file types. If no file types are supported,
* an array of length 0 is returned.
*/
public static int[] getMidiFileTypes() {
MidiFileWriter providers[] = getMidiFileWriters();
Vector allTypes = new Vector();
int size = 0;
int index = 0;
int types[] = null;
// gather from all the providers
for(int i=0; i<providers.length; i++ ) {
types = providers[i].getMidiFileTypes();
size += types.length;
allTypes.addElement( types );
}
// now build a new array
int types2[] = new int[size];
for(int i=0; i<allTypes.size(); i++ ) {
types = (int [])(allTypes.elementAt(i));
for(int j=0; j<types.length; j++ ) {
types2[index++] = types[j];
}
}
return types2;
}
/**
* 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</code> if the file type is supported,
* otherwise <code>false</code>
*/
public static boolean isFileTypeSupported(int fileType) {
MidiFileWriter providers[] = getMidiFileWriters();
for(int i=0; i<providers.length; i++) {
if( providers[i].isFileTypeSupported(fileType) == true ) {
return true;
}
}
return false;
}
/**
* 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 supported file types. If no file types are supported,
* returns an array of length 0.
*/
public static int[] getMidiFileTypes(Sequence sequence) {
MidiFileWriter providers[] = getMidiFileWriters();
int types[][] = new int[ providers.length ][];
int returnTypes[] = null;
int numTypes = 0;
int index = 0;
// Get all supported file types
for(int i=0; i < providers.length; i++) {
types[i] = providers[i].getMidiFileTypes(sequence);
numTypes += types[i].length;
}
// Now put them in a 1-D array
returnTypes = new int[ numTypes ];
for(int i=0; i < providers.length; i++) {
for(int j=0; j < types[i].length; j++) {
returnTypes[ index ] = types[i][j];
index++;
}
}
return returnTypes;
}
/**
* 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</code> if the file type is supported for this
* sequence, otherwise <code>false</code>
*/
public static boolean isFileTypeSupported(int fileType, Sequence sequence) {
MidiFileWriter providers[] = getMidiFileWriters();
for(int i=0; i<providers.length; i++) {
if( providers[i].isFileTypeSupported(fileType,sequence) == true ) {
return true;
}
}
return false;
}
/**
* 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
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public static int write(Sequence in, int fileType, OutputStream out) throws IOException {
MidiFileWriter providers[] = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
int bytesWritten = -2;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
if( providers[i].isFileTypeSupported( fileType, in ) == true ) {
bytesWritten = providers[i].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.
* @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
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
public static int write(Sequence in, int type, File out) throws IOException {
MidiFileWriter providers[] = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
int bytesWritten = -2;
//$$fb 2001-08-03: reverse this loop to give external providers more priority (Bug #4487550)
for(int i = providers.length-1; i >= 0; i-- ) {
if( providers[i].isFileTypeSupported( type, in ) == true ) {
bytesWritten = providers[i].write(in, type, out);
break;
}
}
if (bytesWritten == -2) {
throw new IllegalArgumentException("MIDI file type is not supported");
}
return bytesWritten;
}
// HELPER METHODS
private static synchronized boolean isA( Class testClass, Class targetClass ) {
return (targetClass.isAssignableFrom(testClass)) ? true : false;
}
private static Vector getMidiDeviceProviders() {
Vector providers = null;
try {
Class.forName( "sun.misc.Service" );
providers = getJDK13Services("javax.sound.midi.spi.MidiDeviceProvider");
} catch (Exception e) {
// we're not running with 1.3's SPI mechanism
providers = getDefaultServices("javax.sound.midi.spi.MidiDeviceProvider");
}
return providers;
}
private static Vector getSoundbankReaders() {
Vector providers = null;
try {
Class.forName( "sun.misc.Service" );
providers = getJDK13Services("javax.sound.midi.spi.SoundbankReader");
} catch (Exception e) {
// we're not running with 1.3's SPI mechanism
providers = getDefaultServices("javax.sound.midi.spi.SoundbankReader");
}
return providers;
}
private static MidiFileWriter[] getMidiFileWriters() {
Vector v = new Vector();
MidiFileWriter varray[];
try {
Class.forName( "sun.misc.Service" );
v = getJDK13Services("javax.sound.midi.spi.MidiFileWriter");
} catch (Exception e) {
// we're not running with 1.3's SPI mechanism
v = getDefaultServices("javax.sound.midi.spi.MidiFileWriter");
}
varray = new MidiFileWriter[ v.size() ];
for( int i=0; i < varray.length; i++ ) {
varray[i] = (MidiFileWriter)(v.elementAt(i));
}
return varray;
}
private static MidiFileReader[] getMidiFileReaders() {
Vector v = new Vector();
MidiFileReader varray[];
try {
Class.forName( "sun.misc.Service" );
v = getJDK13Services("javax.sound.midi.spi.MidiFileReader");
} catch (Exception e) {
// we're not running with 1.3's SPI mechanism
v = getDefaultServices("javax.sound.midi.spi.MidiFileReader");
}
varray = new MidiFileReader[ v.size() ];
for( int i=0; i < varray.length; i++ ) {
varray[i] = (MidiFileReader)(v.elementAt(i));
}
return varray;
}
private static MidiDevice.Info[] getGenericDeviceInfo( Class deviceClass ) {
int i;
int j;
Vector v = new Vector();
MidiDevice.Info[] tmpinfo;
MidiDevice.Info[] varray;
Vector v1;
v1 = getMidiDeviceProviders();
for(i = 0; i < v1.size(); i++) {
tmpinfo = ((MidiDeviceProvider) v1.elementAt(i)).getDeviceInfo();
for (j = 0; j < tmpinfo.length; j++) {
// $$kk: 10.12.99: ugh! i have wrecked this!!
//if( isA( tmpinfo[j].getDeviceClass(), deviceClass ) ) {
MidiDevice device = ((MidiDeviceProvider) v1.elementAt(i)).getDevice(tmpinfo[j]);
if (isA(deviceClass, Receiver.class)) {
if(device.getMaxReceivers() != 0) {
v.addElement( tmpinfo[j] );
}
} else if (isA(deviceClass, Transmitter.class)) {
if(device.getMaxTransmitters() != 0) {
v.addElement( tmpinfo[j] );
}
} else if (deviceClass.isInstance(device)) {
v.addElement( tmpinfo[j] );
}
}
}
varray = new MidiDevice.Info[ v.size() ];
for(i = 0; i < varray.length; i++ ) {
varray[i] = (MidiDevice.Info)(v.elementAt(i));
}
return varray;
}
/**
* Attempts to locate and return the specified device
* @throws IllegalArgumentException on failure.
*/
private static Object getGenericDevice( Class deviceClass, MidiDevice.Info info) {
int i;
int j;
MidiDevice s = null;
MidiDevice.Info[] tmpinfo = null;
Vector v1 = new Vector();
v1 = getMidiDeviceProviders();
for(i = 0; i < v1.size(); i++) {
tmpinfo = ((MidiDeviceProvider) v1.elementAt(i)).getDeviceInfo();
if( info == null ) {
// $$jb: 06.04.99: Should we do more to guarantee which
// device is the default?
for (j = 0; j < tmpinfo.length; j++) {
// $$kk: 10.12.99: ugh! i have wrecked this!!
//if( isA(tmpinfo[j].getDeviceClass(), deviceClass ) ) {
// return ((MidiDeviceProvider) v1.elementAt(i)).getDevice(tmpinfo[j]);
//}
MidiDevice device = ((MidiDeviceProvider) v1.elementAt(i)).getDevice(tmpinfo[j]);
if (isA(deviceClass, Receiver.class)) {
if(device.getMaxReceivers() != 0) {
return device;
}
} else if (isA(deviceClass, Transmitter.class)) {
if(device.getMaxTransmitters() != 0) {
return device;
}
} else if (deviceClass.isInstance(device)) {
return device;
}
}
} else {
for (j = 0; j < tmpinfo.length; j++) {
if( tmpinfo[j].equals( info ) ) {
// $$kk: 10.12.99: ugh! i have wrecked this!!
// $$kk: 10.12.99: shouldn't need this check?
//if( isA(tmpinfo[j].getDeviceClass(), deviceClass ) ) {
// return ((MidiDeviceProvider) v1.elementAt(i)).getDevice(tmpinfo[j]);
//}
MidiDevice device = ((MidiDeviceProvider) v1.elementAt(i)).getDevice(tmpinfo[j]);
if (deviceClass == null) {
return device;
}
if (isA(deviceClass, Receiver.class)) {
if(device.getMaxReceivers() != 0) {
return device;
}
} else if (isA(deviceClass, Transmitter.class)) {
if(device.getMaxTransmitters() != 0) {
return device;
}
}
}
}
}
}
throw new IllegalArgumentException("Requested device not installed: " + info);
}
/**
* Obtains the set of services currently installed on the system
* using sun.misc.Service, the SPI mechanism in 1.3.
* @return a Vector of instances of providers for the requested service.
* If no providers are available, a vector of length 0 will be returned.
*/
private static Vector getJDK13Services( String serviceName ) {
Vector v = null;
try {
Class jdk13Services =
Class.forName( jdk13ServicesClassName );
Method m = jdk13Services.getMethod(
servicesMethodName,
servicesParamTypes);
Object[] arguments = new Object[] { serviceName };
v = (Vector) m.invoke(jdk13Services,arguments);
} catch(InvocationTargetException e1) {
v = new Vector();
} catch(ClassNotFoundException e2) {
v = new Vector();
} catch(IllegalAccessException e3) {
v = new Vector();
} catch(NoSuchMethodException e4) {
v = new Vector();
}
return v;
}
/**
* Obtains the default set of services currently installed on the system.
* This method is only invoked if sun.misc.Service is not available.
* @return a Vector of instances of providers for the requested service.
* If no providers are available, a vector of length 0 will be returned.
*/
private static Vector getDefaultServices( String serviceName ) {
Vector v = null;
try {
Class defaultServices =
Class.forName( defaultServicesClassName );
Method m = defaultServices.getMethod(
servicesMethodName,
servicesParamTypes);
Object[] arguments = new Object[] { serviceName };
v = (Vector) m.invoke(defaultServices,arguments);
} catch(InvocationTargetException e1) {
v = new Vector();
} catch(ClassNotFoundException e2) {
v = new Vector();
} catch(IllegalAccessException e3) {
v = new Vector();
} catch(NoSuchMethodException e4) {
v = new Vector();
}
return v;
}
}