| /* MidiSystem.java -- Access system MIDI resources |
| Copyright (C) 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.sound.midi; |
| |
| import gnu.classpath.ServiceFactory; |
| |
| 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.List; |
| import java.util.Iterator; |
| |
| import javax.sound.midi.spi.MidiDeviceProvider; |
| import javax.sound.midi.spi.MidiFileReader; |
| import javax.sound.midi.spi.MidiFileWriter; |
| import javax.sound.midi.spi.SoundbankReader; |
| |
| /** |
| * MidiSystem provides access to the computer system's MIDI resources, |
| * as well as utility routines for reading MIDI files and more. |
| * |
| * @author Anthony Green (green@redhat.com) |
| * @since 1.3 |
| * |
| */ |
| public class MidiSystem |
| { |
| private MidiSystem() |
| { |
| // Not instantiable. |
| } |
| |
| /** |
| * Get an array of all available MIDI devices. |
| * |
| * @return a possibly empty array of all available MIDI devices |
| */ |
| public static MidiDevice.Info[] getMidiDeviceInfo() |
| { |
| Iterator deviceProviders = |
| ServiceFactory.lookupProviders(MidiDeviceProvider.class); |
| List infoList = new ArrayList(); |
| |
| while (deviceProviders.hasNext()) |
| { |
| MidiDeviceProvider provider = (MidiDeviceProvider) deviceProviders.next(); |
| MidiDevice.Info[] infos = provider.getDeviceInfo(); |
| for (int i = infos.length; i > 0; ) |
| infoList.add(infos[--i]); |
| } |
| |
| return (MidiDevice.Info[]) |
| infoList.toArray(new MidiDevice.Info[infoList.size()]); |
| } |
| |
| /** |
| * Get the specified MIDI device. |
| * |
| * @param info a description of the device we're looking for |
| * @return the requested MIDI device |
| * @throws MidiUnavailableException if no MIDI devices are configured or found |
| * @throws IllegalArgumentException if the device described by info is not found |
| */ |
| public static MidiDevice getMidiDevice(MidiDevice.Info info) |
| throws MidiUnavailableException |
| { |
| Iterator deviceProviders = |
| ServiceFactory.lookupProviders(MidiDeviceProvider.class); |
| |
| if (! deviceProviders.hasNext()) |
| throw new MidiUnavailableException("No MIDI device providers available."); |
| |
| do |
| { |
| MidiDeviceProvider provider = |
| (MidiDeviceProvider) deviceProviders.next(); |
| if (provider.isDeviceSupported(info)) |
| return provider.getDevice(info); |
| } while (deviceProviders.hasNext()); |
| |
| throw new IllegalArgumentException("MIDI device " |
| + info + " not available."); |
| } |
| |
| /** |
| * Get the default Receiver instance. This just picks the first one |
| * it finds for now. |
| * |
| * @return the default Receiver instance |
| * @throws MidiUnavailableException if no Receiver is found |
| */ |
| public static Receiver getReceiver() throws MidiUnavailableException |
| { |
| // TODO: The 1.5 spec has a fancy mechanism to specify the default |
| // receiver device. For now, well just return the first one we find. |
| MidiDevice.Info[] infos = getMidiDeviceInfo(); |
| for (int i = 0; i < infos.length; i++) |
| { |
| MidiDevice device = getMidiDevice(infos[i]); |
| if (device instanceof Receiver) |
| return (Receiver) device; |
| } |
| throw new MidiUnavailableException("No Receiver device available"); |
| } |
| |
| /** |
| * Get the default Transmitter instance. This just picks the first one |
| * it finds for now. |
| * |
| * @return the default Transmitter instance |
| * @throws MidiUnavailableException if no Transmitter is found |
| */ |
| public static Transmitter getTransmitter() throws MidiUnavailableException |
| { |
| // TODO: The 1.5 spec has a fancy mechanism to specify the default |
| // Transmitter device. For now, well just return the first one we find. |
| MidiDevice.Info[] infos = getMidiDeviceInfo(); |
| for (int i = 0; i < infos.length; i++) |
| { |
| MidiDevice device = getMidiDevice(infos[i]); |
| if (device instanceof Transmitter) |
| return (Transmitter) device; |
| } |
| throw new MidiUnavailableException("No Transmitter device available"); |
| } |
| |
| /** |
| * Get the default Synthesizer instance. This just picks the first one |
| * it finds for now. |
| * |
| * @return the default Synthesizer instance |
| * @throws MidiUnavailableException if no Synthesizer is found |
| */ |
| public static Synthesizer getSynthesizer() throws MidiUnavailableException |
| { |
| // TODO: The 1.5 spec has a fancy mechanism to specify the default |
| // Synthesizer device. For now, well just return the first one we find. |
| MidiDevice.Info[] infos = getMidiDeviceInfo(); |
| for (int i = 0; i < infos.length; i++) |
| { |
| MidiDevice device = getMidiDevice(infos[i]); |
| if (device instanceof Synthesizer) |
| return (Synthesizer) device; |
| } |
| throw new MidiUnavailableException("No Synthesizer device available"); |
| } |
| |
| /** |
| * Get the default Sequencer instance. This just picks the first one |
| * it finds for now. |
| * |
| * @return the default Sequencer instance |
| * @throws MidiUnavailableException if no Sequencer is found |
| */ |
| public static Sequencer getSequencer() throws MidiUnavailableException |
| { |
| // TODO: The 1.5 spec has a fancy mechanism to specify the default |
| // Sequencer device. For now, well just return the first one we find. |
| MidiDevice.Info[] infos = getMidiDeviceInfo(); |
| for (int i = 0; i < infos.length; i++) |
| { |
| MidiDevice device = getMidiDevice(infos[i]); |
| if (device instanceof Sequencer) |
| return (Sequencer) device; |
| } |
| throw new MidiUnavailableException("No Sequencer device available"); |
| } |
| |
| /** |
| * Read a Soundbank object from the given stream. |
| * |
| * @param stream the stream from which to read the Soundbank |
| * @return the Soundbank object |
| * @throws InvalidMidiDataException if we were unable to read the soundbank |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Soundbank getSoundbank(InputStream stream) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(SoundbankReader.class); |
| while (readers.hasNext()) |
| { |
| SoundbankReader sr = (SoundbankReader) readers.next(); |
| Soundbank sb = sr.getSoundbank(stream); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Cannot read soundbank from stream"); |
| } |
| |
| /** |
| * Read a Soundbank object from the given url. |
| * |
| * @param url the url from which to read the Soundbank |
| * @return the Soundbank object |
| * @throws InvalidMidiDataException if we were unable to read the soundbank |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Soundbank getSoundbank(URL url) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(SoundbankReader.class); |
| while (readers.hasNext()) |
| { |
| SoundbankReader sr = (SoundbankReader) readers.next(); |
| Soundbank sb = sr.getSoundbank(url); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Cannot read from url " + url); |
| } |
| |
| /** |
| * Read a Soundbank object from the given file. |
| * |
| * @param file the file from which to read the Soundbank |
| * @return the Soundbank object |
| * @throws InvalidMidiDataException if we were unable to read the soundbank |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Soundbank getSoundbank(File file) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(SoundbankReader.class); |
| while (readers.hasNext()) |
| { |
| SoundbankReader sr = (SoundbankReader) readers.next(); |
| Soundbank sb = sr.getSoundbank(file); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Cannot read soundbank from file " |
| + file); |
| } |
| |
| /** |
| * Read a MidiFileFormat object from the given stream. |
| * |
| * @param stream the stream from which to read the MidiFileFormat |
| * @return the MidiFileFormat object |
| * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static MidiFileFormat getMidiFileFormat(InputStream stream) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| MidiFileFormat sb = sr.getMidiFileFormat(stream); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Can't read MidiFileFormat from stream"); |
| } |
| |
| /** |
| * Read a MidiFileFormat object from the given url. |
| * |
| * @param url the url from which to read the MidiFileFormat |
| * @return the MidiFileFormat object |
| * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static MidiFileFormat getMidiFileFormat(URL url) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| MidiFileFormat sb = sr.getMidiFileFormat(url); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Cannot read from url " + url); |
| } |
| |
| /** |
| * Read a MidiFileFormat object from the given file. |
| * |
| * @param file the file from which to read the MidiFileFormat |
| * @return the MidiFileFormat object |
| * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static MidiFileFormat getMidiFileFormat(File file) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| MidiFileFormat sb = sr.getMidiFileFormat(file); |
| if (sb != null) |
| return sb; |
| } |
| throw new InvalidMidiDataException("Can't read MidiFileFormat from file " |
| + file); |
| } |
| |
| /** |
| * Read a Sequence object from the given stream. |
| * |
| * @param stream the stream from which to read the Sequence |
| * @return the Sequence object |
| * @throws InvalidMidiDataException if we were unable to read the Sequence |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Sequence getSequence(InputStream stream) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| Sequence sq = sr.getSequence(stream); |
| if (sq != null) |
| return sq; |
| } |
| throw new InvalidMidiDataException("Can't read Sequence from stream"); |
| } |
| |
| /** |
| * Read a Sequence object from the given url. |
| * |
| * @param url the url from which to read the Sequence |
| * @return the Sequence object |
| * @throws InvalidMidiDataException if we were unable to read the Sequence |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Sequence getSequence(URL url) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| Sequence sq = sr.getSequence(url); |
| if (sq != null) |
| return sq; |
| } |
| throw new InvalidMidiDataException("Cannot read from url " + url); |
| } |
| |
| /** |
| * Read a Sequence object from the given file. |
| * |
| * @param file the file from which to read the Sequence |
| * @return the Sequence object |
| * @throws InvalidMidiDataException if we were unable to read the Sequence |
| * @throws IOException if an I/O error happened while reading |
| */ |
| public static Sequence getSequence(File file) |
| throws InvalidMidiDataException, IOException |
| { |
| Iterator readers = ServiceFactory.lookupProviders(MidiFileReader.class); |
| while (readers.hasNext()) |
| { |
| MidiFileReader sr = (MidiFileReader) readers.next(); |
| Sequence sq = sr.getSequence(file); |
| if (sq != null) |
| return sq; |
| } |
| throw new InvalidMidiDataException("Can't read Sequence from file " |
| + file); |
| } |
| |
| /** |
| * Return an array of supported MIDI file types on this system. |
| * |
| * @return the array of supported MIDI file types |
| */ |
| public static int[] getMidiFileTypes() |
| { |
| // We only support a max of 3 MIDI file types. |
| boolean supported[] = new boolean[3]; |
| // The number of supported formats. |
| int count = 0; |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| int types[] = fw.getMidiFileTypes(); |
| for (int i = types.length; i > 0;) |
| { |
| int type = types[--i]; |
| if (supported[type] == false) |
| { |
| count++; |
| supported[type] = true; |
| } |
| } |
| } |
| int result[] = new int[count]; |
| for (int i = supported.length; i > 0;) |
| { |
| if (supported[--i]) |
| result[--count] = i; |
| } |
| return result; |
| } |
| |
| /** |
| * Return true if the system supports writing files of type fileType. |
| * |
| * @param fileType the MIDI file type we want to write |
| * @return true if we can write fileType files, false otherwise |
| */ |
| public static boolean isFileTypeSupported(int fileType) |
| { |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| |
| if (fw.isFileTypeSupported(fileType)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Return an array of supported MIDI file types on this system |
| * for the given sequnce. |
| * |
| * @param sequence the sequnce to write |
| * @return the array of supported MIDI file types |
| */ |
| public static int[] getMidiFileTypes(Sequence sequence) |
| { |
| // We only support a max of 3 MIDI file types. |
| boolean supported[] = new boolean[3]; |
| // The number of supported formats. |
| int count = 0; |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| int types[] = fw.getMidiFileTypes(sequence); |
| for (int i = types.length; i > 0;) |
| { |
| int type = types[--i]; |
| if (supported[type] == false) |
| { |
| count++; |
| supported[type] = true; |
| } |
| } |
| } |
| int result[] = new int[count]; |
| for (int i = supported.length; i > 0;) |
| { |
| if (supported[--i]) |
| result[--count] = i; |
| } |
| return result; |
| } |
| |
| /** |
| * Return true if the system supports writing files of type fileType |
| * for the given sequence. |
| * |
| * @param fileType the MIDI file type we want to write |
| * @param sequence the Sequence we want to write |
| * @return true if we can write fileType files for sequence, false otherwise |
| */ |
| public static boolean isFileTypeSupported(int fileType, Sequence sequence) |
| { |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| |
| if (fw.isFileTypeSupported(fileType, sequence)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Write a sequence to an output stream using a specific MIDI file format. |
| * |
| * @param in the sequence to write |
| * @param fileType the MIDI file format to use |
| * @param out the output stream to write to |
| * @return the number of bytes written |
| * @throws IOException if an I/O exception happens |
| * @throws IllegalArgumentException if fileType is not supported for in |
| */ |
| public static int write(Sequence in, int fileType, OutputStream out) |
| throws IOException |
| { |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| |
| if (fw.isFileTypeSupported(fileType, in)) |
| return fw.write(in, fileType, out); |
| } |
| throw new IllegalArgumentException("File type " |
| + fileType + " is not supported"); |
| } |
| |
| /** |
| * Write a sequence to a file using a specific MIDI file format. |
| * |
| * @param in the sequence to write |
| * @param fileType the MIDI file format to use |
| * @param out the file to write to |
| * @return the number of bytes written |
| * @throws IOException if an I/O exception happens |
| * @throws IllegalArgumentException if fileType is not supported for in |
| */ |
| public static int write(Sequence in, int fileType, File out) |
| throws IOException |
| { |
| Iterator writers = ServiceFactory.lookupProviders(MidiFileWriter.class); |
| while (writers.hasNext()) |
| { |
| MidiFileWriter fw = (MidiFileWriter) writers.next(); |
| |
| if (fw.isFileTypeSupported(fileType, in)) |
| return fw.write(in, fileType, out); |
| } |
| throw new IllegalArgumentException("File type " |
| + fileType + " is not supported"); |
| } |
| } |
| |