From ef79c4f14a52a437d4b3154221bd63a434eec9de Mon Sep 17 00:00:00 2001 From: Anthony Green Date: Mon, 26 Sep 2005 16:34:59 +0000 Subject: * javax/sound/midi/InvalidMidiDataException.java javax/sound/midi/MidiFileFormat.java javax/sound/midi/ControllerEventListener.java javax/sound/midi/Patch.java javax/sound/midi/Sequence.java javax/sound/midi/SysexMessage.java javax/sound/midi/Sequencer.java javax/sound/midi/spi/MidiFileReader.java javax/sound/midi/spi/MidiFileWriter.java javax/sound/midi/spi/SoundbankReader.java javax/sound/midi/spi/MidiDeviceProvider.java javax/sound/midi/Track.java javax/sound/midi/MidiChannel.java javax/sound/midi/MetaMessage.java javax/sound/midi/Instrument.java javax/sound/midi/MidiMessage.java javax/sound/midi/MidiUnavailableException.java javax/sound/midi/Transmitter.java javax/sound/midi/MidiEvent.java javax/sound/midi/VoiceStatus.java javax/sound/midi/MidiDevice.java javax/sound/midi/SoundbankResource.java javax/sound/midi/Soundbank.java javax/sound/midi/Receiver.java javax/sound/midi/MetaEventListener.java javax/sound/midi/ShortMessage.java javax/sound/midi/Synthesizer.java javax/sound/midi/MidiSystem.java: New files. --- javax/sound/midi/ControllerEventListener.java | 58 +++ javax/sound/midi/Instrument.java | 77 ++++ javax/sound/midi/InvalidMidiDataException.java | 88 +++++ javax/sound/midi/MetaEventListener.java | 58 +++ javax/sound/midi/MetaMessage.java | 176 +++++++++ javax/sound/midi/MidiChannel.java | 236 ++++++++++++ javax/sound/midi/MidiDevice.java | 220 +++++++++++ javax/sound/midi/MidiEvent.java | 95 +++++ javax/sound/midi/MidiFileFormat.java | 157 ++++++++ javax/sound/midi/MidiMessage.java | 125 +++++++ javax/sound/midi/MidiSystem.java | 492 +++++++++++++++++++++++++ javax/sound/midi/MidiUnavailableException.java | 88 +++++ javax/sound/midi/Patch.java | 86 +++++ javax/sound/midi/Receiver.java | 66 ++++ javax/sound/midi/Sequence.java | 247 +++++++++++++ javax/sound/midi/Sequencer.java | 396 ++++++++++++++++++++ javax/sound/midi/ShortMessage.java | 316 ++++++++++++++++ javax/sound/midi/Soundbank.java | 101 +++++ javax/sound/midi/SoundbankResource.java | 104 ++++++ javax/sound/midi/Synthesizer.java | 180 +++++++++ javax/sound/midi/SysexMessage.java | 139 +++++++ javax/sound/midi/Track.java | 160 ++++++++ javax/sound/midi/Transmitter.java | 70 ++++ javax/sound/midi/VoiceStatus.java | 79 ++++ javax/sound/midi/spi/MidiDeviceProvider.java | 90 +++++ javax/sound/midi/spi/MidiFileReader.java | 125 +++++++ javax/sound/midi/spi/MidiFileWriter.java | 143 +++++++ javax/sound/midi/spi/SoundbankReader.java | 97 +++++ 28 files changed, 4269 insertions(+) create mode 100644 javax/sound/midi/ControllerEventListener.java create mode 100644 javax/sound/midi/Instrument.java create mode 100644 javax/sound/midi/InvalidMidiDataException.java create mode 100644 javax/sound/midi/MetaEventListener.java create mode 100644 javax/sound/midi/MetaMessage.java create mode 100644 javax/sound/midi/MidiChannel.java create mode 100644 javax/sound/midi/MidiDevice.java create mode 100644 javax/sound/midi/MidiEvent.java create mode 100644 javax/sound/midi/MidiFileFormat.java create mode 100644 javax/sound/midi/MidiMessage.java create mode 100644 javax/sound/midi/MidiSystem.java create mode 100644 javax/sound/midi/MidiUnavailableException.java create mode 100644 javax/sound/midi/Patch.java create mode 100644 javax/sound/midi/Receiver.java create mode 100644 javax/sound/midi/Sequence.java create mode 100644 javax/sound/midi/Sequencer.java create mode 100644 javax/sound/midi/ShortMessage.java create mode 100644 javax/sound/midi/Soundbank.java create mode 100644 javax/sound/midi/SoundbankResource.java create mode 100644 javax/sound/midi/Synthesizer.java create mode 100644 javax/sound/midi/SysexMessage.java create mode 100644 javax/sound/midi/Track.java create mode 100644 javax/sound/midi/Transmitter.java create mode 100644 javax/sound/midi/VoiceStatus.java create mode 100644 javax/sound/midi/spi/MidiDeviceProvider.java create mode 100644 javax/sound/midi/spi/MidiFileReader.java create mode 100644 javax/sound/midi/spi/MidiFileWriter.java create mode 100644 javax/sound/midi/spi/SoundbankReader.java (limited to 'javax/sound') diff --git a/javax/sound/midi/ControllerEventListener.java b/javax/sound/midi/ControllerEventListener.java new file mode 100644 index 000000000..eb075b32f --- /dev/null +++ b/javax/sound/midi/ControllerEventListener.java @@ -0,0 +1,58 @@ +/* ControllerEventListener.java -- Listener for MIDI controller events + 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 java.util.EventListener; + +/** + * The interface defines the methods to be implemented by classes wanting + * to be notified on MIDI controller events from a Sequencer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface ControllerEventListener extends EventListener +{ + /** + * Called on MIDI controller events. + * @param event the controller change event message + */ + public void controlChange(ShortMessage event); +} diff --git a/javax/sound/midi/Instrument.java b/javax/sound/midi/Instrument.java new file mode 100644 index 000000000..3402e8289 --- /dev/null +++ b/javax/sound/midi/Instrument.java @@ -0,0 +1,77 @@ +/* Instrument.java -- A MIDI Instrument + 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; + +/** + * The abstract base class for all MIDI instruments. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class Instrument extends SoundbankResource +{ + // The instrument patch. + private Patch patch; + + /** + * Create a new Instrument. + * + * @param soundbank the Soundbank containing the instrument. + * @param patch the patch for this instrument + * @param name the name of this instrument + * @param dataClass the class used to represent sample data for this instrument + */ + protected Instrument(Soundbank soundbank, Patch patch, + String name, Class dataClass) + { + super(soundbank, name, dataClass); + this.patch = patch; + } + + /** + * Get the patch for this instrument. + * + * @return the patch for this instrument + */ + public Patch getPatch() + { + return patch; + } +} diff --git a/javax/sound/midi/InvalidMidiDataException.java b/javax/sound/midi/InvalidMidiDataException.java new file mode 100644 index 000000000..0ae8c91a8 --- /dev/null +++ b/javax/sound/midi/InvalidMidiDataException.java @@ -0,0 +1,88 @@ +/* InvalidMidiDataException.java -- Thrown for invalid MIDI data. + 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; + +/** + * This exception is thrown when we encounter bad MIDI data. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class InvalidMidiDataException extends Exception +{ + /** + * Create an InvalidMidiDataException object. + */ + public InvalidMidiDataException() + { + super(); + } + + /** + * Create an InvalidMidiDataException object. + * + * @param s the exception message string + */ + public InvalidMidiDataException(String s) + { + super(s); + } + + /** + * Create an InvalidMidiDataException object. + * + * @param s the exception message string + * @param cause the root cause of the exception + */ + public InvalidMidiDataException(String s, Throwable cause) + { + super(s, cause); + } + + /** + * Create an InvalidMidiDataException object. + * + * @param cause the root cause of the exception + */ + public InvalidMidiDataException(Throwable cause) + { + super(cause); + } +} diff --git a/javax/sound/midi/MetaEventListener.java b/javax/sound/midi/MetaEventListener.java new file mode 100644 index 000000000..dd7b8a24b --- /dev/null +++ b/javax/sound/midi/MetaEventListener.java @@ -0,0 +1,58 @@ +/* MetaEventListener.java -- Listener for MIDI meta events + 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 java.util.EventListener; + +/** + * The interface defines the methods to be implemented by classes wanting + * to be notified on MIDI meta events from a Sequencer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface MetaEventListener extends EventListener +{ + /** + * Called on MIDI meta events. + * @param meta the meta event message + */ + public void meta(MetaMessage meta); +} diff --git a/javax/sound/midi/MetaMessage.java b/javax/sound/midi/MetaMessage.java new file mode 100644 index 000000000..2ca93accd --- /dev/null +++ b/javax/sound/midi/MetaMessage.java @@ -0,0 +1,176 @@ +/* MetaMessage.java -- A meta message for MIDI files. + 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; + +/** + * A system exclusive MIDI message. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class MetaMessage extends MidiMessage +{ + /** + * The META status code. Only valid for MIDI files, not the wire protocol. + */ + public static final int META = 0xFF; + + // The length of the variable length data length encoding. + private int lengthLength = 0; + + /** + * Create a default valid meta message. + * + * The official specs don't specify what message is to be + * created. For now, we create a zero length meta message + * with a type code of 0. + */ + public MetaMessage() + { + super(new byte[4]); + data[0] = (byte) META; + data[1] = (byte) 0; // Type + data[2] = (byte) 1; // Length length + data[3] = (byte) 0; // Length + lengthLength = 1; + } + + /** + * Create a MetaMessage object. + * @param data a complete system exclusive message + */ + public MetaMessage(byte[] data) + { + super(data); + int index = 2; + lengthLength = 1; + while ((data[index++] & 0x80) > 0) + lengthLength++; + } + + /** + * Set the meta message. + * + * @param type the meta type byte (< 128) + * @param data the message data + * @param length the length of the message data + * @throws InvalidMidiDataException if this message is invalid + */ + public void setMessage(int type, byte[] data, int length) + throws InvalidMidiDataException + { + if (type > 127) + throw new InvalidMidiDataException("Meta type 0x" + + Integer.toHexString(type) + + " must be less than 128"); + + // For a nice description of how variable length values are handled, + // see http://www.borg.com/~jglatt/tech/midifile.htm + + // First compute the length of the length value + lengthLength = 0; + int lengthValue = length; + do { + lengthValue = lengthValue >> 7; + lengthLength++; + } while (lengthValue > 0); + + // Now allocate our data array + this.length = 2 + lengthLength + length; + this.data = new byte[this.length]; + this.data[0] = (byte) META; + this.data[1] = (byte) type; + + // Now compute the length representation + long buffer = length & 0x7F; + while ((length >>= 7) > 0) + { + buffer <<= 8; + buffer |= ((length & 0x7F) | 0x80); + } + + // Now store the variable length length value + int index = 2; + do + { + this.data[index++] = (byte) (buffer & 0xFF); + if ((buffer & 0x80) == 0) + break; + buffer >>= 8; + } while (true); + + // Now copy the real data. + System.arraycopy(data, 0, this.data, index, length); + } + + /** + * Get the meta message type. + * + * @return the meta message type + */ + public int getType() + { + return data[1]; + } + + /** + * Get the data for this message, not including the status, + * type, or length information. + * + * @return the message data, not including status, type or lenght info + */ + public byte[] getData() + { + int dataLength = length - 2 - lengthLength; + byte[] result = new byte[dataLength]; + System.arraycopy(data, 2 + lengthLength, result, 0, dataLength); + return result; + } + + /* Create a deep-copy clone of this object. + * @see java.lang.Object#clone() + */ + public Object clone() + { + byte message[] = new byte[length]; + System.arraycopy(data, 0, message, 0, length); + return new MetaMessage(message); + } +} diff --git a/javax/sound/midi/MidiChannel.java b/javax/sound/midi/MidiChannel.java new file mode 100644 index 000000000..fe3b5111a --- /dev/null +++ b/javax/sound/midi/MidiChannel.java @@ -0,0 +1,236 @@ +/* MidiChannel.java -- A MIDI channel + 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; + +/** + * A MIDI channel. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface MidiChannel +{ + + /** + * Start playing a note. + * + * @param noteNumber the MIDI note number + * @param velocity the velocity at which the key was pressed + */ + public void noteOn(int noteNumber, int velocity); + + /** + * Stop playing a note. + * + * @param noteNumber the MIDI note number + * @param velocity the volcity at which the ket was released + */ + public void noteOff(int noteNumber, int velocity); + + /** + * Stop playing a note. + * + * @param noteNumber the MIDI note number + */ + public void noteOff(int noteNumber); + + /** + * Change in a key pressure for a note. + * + * @param noteNumber the MIDI note number + * @param pressure the key pressure + */ + public void setPolyPressure(int noteNumber, int pressure); + + /** + * Get the key pressure for a note. + * + * @param noteNumber the MIDI note number + * @return the key pressure + */ + public int getPolyPressure(int noteNumber); + + /** + * Set the key pressure for the channel. + * + * @param pressure the key pressure + */ + public void setChannelPressure(int pressure); + + /** + * Get the key pressure for the channel. + * + * @return the key pressure + */ + public int getChannelPressure(); + + /** + * Set a change in a controller's value. + * + * @param controller the MIDI controller number (0 to 127) + * @param value the new value (0 to 127) + */ + public void controlChange(int controller, int value); + + /** + * Get a controller's value. + * + * @param controller the MIDI controller number (0 to 127) + * @return the controller's value (0 to 127) + */ + public int getController(int controller); + + /** + * Change the patch for this channel. + * + * @param program the patch number to switch to (0 to 127) + */ + public void programChange(int program); + + /** + * Change the bank and patch for this channel. + * + * @param bank the bank to switch to (0 to 16383) + * @param program the patch to switch to (0 to 127) + */ + public void programChange(int bank, int program); + + /** + * Get the current patch for this channel. + * + * @return current patch (0 to 127) + */ + public int getProgram(); + + /** + * Change the pitch bend for this channel using a positive 14-bit value. + * + * @param bend the new pitch bend value + */ + public void setPitchBend(int bend); + + /** + * Get the pitch bend for this channel as a positive 14-bit value. + * + * @return the current patch bend value + */ + public int getPitchBend(); + + /** + * Reset all MIDI controllers to their default values. + */ + public void resetAllControllers(); + + /** + * Stop playing all notes. Sound may not stop. + */ + public void allNotesOff(); + + /** + * Stop all sound. + */ + public void allSoundOff(); + + /** + * Set whether or not local controls are on or off. They are on by + * default. + * + * @param on true to enable local controls, false to disable + * @return the new value + */ + public boolean localControl(boolean on); + + /** + * Turns mono mode on or off. + * + * @param on true to enable mono mode, false to disable + */ + public void setMono(boolean on); + + /** + * Get the current mono mode. + * + * @return true if mono is enabled, false otherwise + */ + public boolean getMono(); + + /** + * Turns omni mode on or off. + * + * @param on true to enable omni mode, false to disable + */ + public void setOmni(boolean on); + + /** + * Get the current omni mode. + * + * @return true if omni is enabled, false otherwise + */ + public boolean getOmni(); + + /** + * Turns mute mode on or off. + * + * @param mute true to enable mute mode, false to disable + */ + public void setMute(boolean mute); + + /** + * Get the current mute mode. + * + * @return true if mute is enabled, false otherwise + */ + public boolean getMute(); + + /** + * Turns solo mode on or off. If any channels are soloed, then only those + * channels make sounds, otherwise all channels will make sound. + * + * @param solo true to enable solo mode, false to disable + */ + public void setSolo(boolean solo); + + /** + * Get the current solo mode. + * + * @return true is solo is enabled, false otherwise. + */ + public boolean getSolo(); +} diff --git a/javax/sound/midi/MidiDevice.java b/javax/sound/midi/MidiDevice.java new file mode 100644 index 000000000..6f43c2548 --- /dev/null +++ b/javax/sound/midi/MidiDevice.java @@ -0,0 +1,220 @@ +/* MidiDevice.java -- Interface for MIDI devices + 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; + +/** + * Interface for all MIDI devices. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface MidiDevice +{ + /** + * Get the Info object describing this device. + * @return the Info object describing this device + */ + public Info getDeviceInfo(); + + /** + * Open this MIDI device and allocate any system resource we need. + * + * @throws MidiUnavailableException if we're not able to open for some reason + */ + public void open() throws MidiUnavailableException; + + /** + * Close this MIDI device, and release any system resources we're using. + */ + public void close(); + + /** + * Returns true if this MIDI device is open and false otherwise. + * + * @return true if this is open, false otherwise + */ + public boolean isOpen(); + + /** + * If this device supports time-stamps, then it will return the number + * of microseconds since this device has been open, and -1 otherwise. + * + * @return -1 or the number of microseconds since this was opened + */ + public long getMicrosecondPosition(); + + /** + * The maximum number of MIDI IN connections we can get as Receivers, + * or -1 if there is no maximum. + * + * @return -1 or the maximum number of Receivers we can get + */ + public int getMaxReceivers(); + + /** + * The maximum number of MIDI OUT connections we can get as Transmitters, + * or -1 if there is no maximum. + * + * @return -1 or the maximum number of Transmitters we can get + */ + public int getMaxTransmitters(); + + /** + * Get a MIDI IN Receiver for this device. + * + * @return a MIDI IN Receiver for this device + * @throws MidiUnavailableException if we can't get a Receiver + */ + public Receiver getReceiver() throws MidiUnavailableException; + + /** + * Get a MIDI OUT Transmitter for this device. + * + * @return a MIDI OUT Transmitter for this device + * @throws MidiUnavailableException if we can't get a Transmitter + */ + public Transmitter getTransmitter() throws MidiUnavailableException; + + /** + * A MIDI device descriptor object. + * + * @author green@redhat.com + * + */ + public static class Info + { + // Private data describing this device + private String name; + private String vendor; + private String description; + private String version; + + /** + * Create an Info object for a MIDI device + * + * @param name the device name + * @param vendor the vendor name + * @param description the device description + * @param version the device version string + */ + public Info(String name, String vendor, String description, String version) + { + this.name = name; + this.vendor = vendor; + this.description = description; + this.version = version; + } + + /** + * This equals method only returns true if this object + * is the same as obj. + * + * @param obj the object we're comparing to + * @return true if this is the same object + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) + { + return super.equals(obj); + } + + /** + * A hash code for this object. + * + * @return the hash code for this object + * @see java.lang.Object#hashCode() + */ + public int hashCode() + { + return super.hashCode(); + } + + /** + * Get the device name. + * + * @return the device name + */ + public String getName() + { + return name; + } + + /** + * Get the device vendor. + * + * @return the device vendor + */ + public String getVendor() + { + return vendor; + } + + /** + * Get the device description + * + * @return the device description + */ + public String getDescription() + { + return description; + } + + /** + * get the device version + * + * @return the device version + */ + public String getVersion() + { + return version; + } + + /** + * Simple return the name of the device. + * + * @return the device name + * @see java.lang.Object#toString() + */ + public String toString() + { + return name; + } + } +} diff --git a/javax/sound/midi/MidiEvent.java b/javax/sound/midi/MidiEvent.java new file mode 100644 index 000000000..3ca5c21ea --- /dev/null +++ b/javax/sound/midi/MidiEvent.java @@ -0,0 +1,95 @@ +/* MidiEvent.java -- A MIDI Event + 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; + +/** + * A MIDI event is the combination of a MIDI message and a timestamp specified + * in MIDI ticks. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class MidiEvent +{ + private final MidiMessage message; + private long tick; + + /** + * Create a MIDI event object from the given MIDI message and timestamp. + * + * @param message the MidiMessage for this event + * @param tick the timestamp for this event + */ + public MidiEvent(MidiMessage message, long tick) + { + this.message = message; + this.tick = tick; + } + + /** + * Get the MIDI message for this event. + * + * @return the MidiMessage for this event + */ + public MidiMessage getMessage() + { + return message; + } + + /** + * Set the timestemp for this event in MIDI ticks. + * + * @param tick the timestamp + */ + public void setTick(long tick) + { + this.tick = tick; + } + + /** + * Get the timestamp for this event in MIDI ticks. + * + * @return the timestamp for this even in MIDI ticks + */ + public long getTick() + { + return tick; + } +} diff --git a/javax/sound/midi/MidiFileFormat.java b/javax/sound/midi/MidiFileFormat.java new file mode 100644 index 000000000..a0b4346f6 --- /dev/null +++ b/javax/sound/midi/MidiFileFormat.java @@ -0,0 +1,157 @@ +/* MidiFileFormat.java -- Information about a MIDI file + 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; + +/** + * Describe a MIDI file, including specifics about its type, length and timing. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class MidiFileFormat +{ + /** + * The MIDI file type. This is either 0, 1 or 2. + * + * Type 0 files contain a single track and represents a single song + * performance. + * Type 1 may contain multiple tracks for a single song performance. + * Type 2 may contain multiple tracks, each representing a + * separate song performance. + * + * See http://en.wikipedia.org/wiki/MIDI#MIDI_file_formats for more + * information. + */ + protected int type; + + /** + * The division type of the MIDI file. + */ + protected float divisionType; + + /** + * The timing resolution of the MIDI file. + */ + protected int resolution; + + /** + * The size of the MIDI file in bytes. + */ + protected int bytes = UNKNOWN_LENGTH; + + /** + * The length of the MIDI file in microseconds. + */ + protected long microseconds = UNKNOWN_LENGTH; + + /** + * A special value indicating an unknown quantity. + */ + public static final int UNKNOWN_LENGTH = -1; // FIXME is this really -1? + + /** + * Create a MidiFileFormat object from the given parameters. + * + * @param type the MIDI file type (0, 1, or 2) + * @param divisionType the MIDI file division type + * @param resolution the MIDI file timing resolution + * @param bytes the MIDI file size in bytes + * @param microseconds the MIDI file length in microseconds + */ + public MidiFileFormat(int type, float divisionType, int resolution, int bytes, long microseconds) + { + this.type = type; + this.divisionType = divisionType; + this.resolution = resolution; + this.bytes = bytes; + this.microseconds = microseconds; + } + + /** + * Get the MIDI file type (0, 1, or 2). + * + * @return the MIDI file type (0, 1, or 2) + */ + public int getType() + { + return type; + } + + /** + * Get the file division type. + * + * @return the file divison type + */ + public float getDivisionType() + { + return divisionType; + } + + /** + * Get the file timing resolution. If the division type is PPQ, then this + * is value represents ticks per beat, otherwise it's ticks per frame (SMPTE). + * + * @return the timing resolution in ticks per beat or ticks per frame + */ + public int getResolution() + { + return resolution; + } + + /** + * Get the file length in bytes. + * + * @return the file length in bytes or UNKNOWN_LENGTH + */ + public int getByteLength() + { + return bytes; + } + + /** + * Get the file length in microseconds. + * + * @return the file length in microseconds or UNKNOWN_LENGTH + */ + public long getMicrosecondLength() + { + return microseconds; + } +} diff --git a/javax/sound/midi/MidiMessage.java b/javax/sound/midi/MidiMessage.java new file mode 100644 index 000000000..8111ce119 --- /dev/null +++ b/javax/sound/midi/MidiMessage.java @@ -0,0 +1,125 @@ +/* MidiMessage.java -- base class for MIDI messages. + 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; + +/** + * The base class for all MIDI messages. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class MidiMessage implements Cloneable +{ + /** + * MIDI message data. + */ + protected byte data[]; + + /** + * The total length of the MIDI message. + */ + protected int length; + + /** + * MidiMessage contructor. + * + * @param data a valid MIDI message + */ + protected MidiMessage(byte[] data) + { + this.data = data; + this.length = data.length; + } + + /** + * Set the complete MIDI message. + * + * @param data The complete MIDI message. + * @param length The length of the MIDI message. + * @throws InvalidMidiDataException Thrown when the MIDI message is invalid. + */ + protected void setMessage(byte[] data, int length) throws InvalidMidiDataException + { + this.data = new byte[length]; + System.arraycopy(data, 0, this.data, 0, length); + this.length = length; + } + + /** + * Get the MIDI message data. + * + * @return an array containing the MIDI message data + */ + public byte[] getMessage() + { + byte copy[] = new byte[length]; + System.arraycopy(data, 0, copy, 0, length); + return copy; + } + + /** + * Get the status byte of the MIDI message (as an int) + * + * @return the status byte of the MIDI message (as an int), or zero if the message length is zero. + */ + public int getStatus() + { + if (length > 0) + return (data[0] & 0xff); + else + return 0; + } + + /** + * Get the length of the MIDI message. + * + * @return the length of the MIDI messsage + */ + public int getLength() + { + return length; + } + + /* Create a clone of this object. + * + * @see java.lang.Object#clone() + */ + public abstract Object clone(); +} diff --git a/javax/sound/midi/MidiSystem.java b/javax/sound/midi/MidiSystem.java new file mode 100644 index 000000000..bdc516a81 --- /dev/null +++ b/javax/sound/midi/MidiSystem.java @@ -0,0 +1,492 @@ +/* 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 +{ + /** + * 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, IllegalArgumentException + { + 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("Cannot 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("Cannot read MidiFileFormat 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, IllegalArgumentException + { + 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, IllegalArgumentException + { + 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"); + } +} + diff --git a/javax/sound/midi/MidiUnavailableException.java b/javax/sound/midi/MidiUnavailableException.java new file mode 100644 index 000000000..1c85f574e --- /dev/null +++ b/javax/sound/midi/MidiUnavailableException.java @@ -0,0 +1,88 @@ +/* MidiUnavailableException.java -- MIDI resources are not available + 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; + +/** + * This exception is thrown when MIDI resources are not available. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class MidiUnavailableException extends Exception +{ + /** + * Create a MidiUnavailableException. + */ + public MidiUnavailableException() + { + super(); + } + + /** + * Create an MidiUnavailableException object. + * + * @param s the exception message string + */ + public MidiUnavailableException(String s) + { + super(s); + } + + /** + * Create an MidiUnavailableException object. + * + * @param s the exception message string + * @param cause the root cause of the exception + */ + public MidiUnavailableException(String s, Throwable cause) + { + super(s, cause); + } + + /** + * Create an MidiUnavailableException object. + * + * @param cause the root cause of the exception + */ + public MidiUnavailableException(Throwable cause) + { + super(cause); + } +} diff --git a/javax/sound/midi/Patch.java b/javax/sound/midi/Patch.java new file mode 100644 index 000000000..eb9d8bc3b --- /dev/null +++ b/javax/sound/midi/Patch.java @@ -0,0 +1,86 @@ +/* Patch.java -- A MIDI patch. + 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; + +/** + * A Patch describes where an Instrument is loaded on a Synthesizer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class Patch +{ + // Private data describing the patch + private int bank = 0; + private int program = 0; + + /** + * Create a Patch object, specifying the bank and program in which this Patch + * is located. + * + * @param bank the bank in which this Patch is located + * @param program the program in which this Patch is located + */ + public Patch(int bank, int program) + { + this.bank = bank; + this.program = program; + } + + /** + * Get the bank in which this Patch is located. + * + * @return the bank in which this Patch is located + */ + public int getBank() + { + return bank; + } + + /** + * Get the program in which this Patch is located. + * + * @return the program in which this Patch is located + */ + public int getProgram() + { + return program; + } +} diff --git a/javax/sound/midi/Receiver.java b/javax/sound/midi/Receiver.java new file mode 100644 index 000000000..0e70b2809 --- /dev/null +++ b/javax/sound/midi/Receiver.java @@ -0,0 +1,66 @@ +/* Receiver.java -- An interface for objects receiving MIDI data + 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; + +/** + * This interface describes the methods required by objects receiving MIDI + * messages. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface Receiver +{ + /** + * Send a MIDI message and timestamp. Some receivers don't support + * timestamps, in which case timeStamp should be -1. + * + * @param message the MIDI message to send + * @param timeStamp time timestamp for this message in microseconds (or -1) + * @throws IllegalStateException if the receiver is closed + */ + public void send(MidiMessage message, long timeStamp) + throws IllegalStateException; + + /** + * Close this receiver, possibly freeing system resources. + */ + public void close(); +} diff --git a/javax/sound/midi/Sequence.java b/javax/sound/midi/Sequence.java new file mode 100644 index 000000000..5552cde3e --- /dev/null +++ b/javax/sound/midi/Sequence.java @@ -0,0 +1,247 @@ +/* Sequence.java -- A sequence of MIDI events + 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 java.util.Iterator; +import java.util.Vector; + +/** + * Objects of this type represent sequences of MIDI messages that can be + * played back by a Sequencer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class Sequence +{ + /** + * The timing division type for this sequence (PPQ or SMPTE*) + */ + protected float divisionType; + + /** + * The timing resolution in ticks/beat or ticks/frame, depending on the + * division type. + */ + protected int resolution; + + /** + * The MIDI tracks used by this sequence. + */ + protected Vector tracks; + + /** + * Tempo-based timing. Resolution is specified in ticks per beat. + */ + public static final float PPQ = 0.0f; + + /** + * 24 frames/second timing. Resolution is specific in ticks per frame. + */ + public static final float SMPTE_24 = 24.0f; + + /** + * 25 frames/second timing. Resolution is specific in ticks per frame. + */ + public static final float SMPTE_25 = 25.0f; + + /** + * 30 frames/second timing. Resolution is specific in ticks per frame. + */ + public static final float SMPTE_30 = 30.0f; + + /** + * 29.97 frames/second timing. Resolution is specific in ticks per frame. + */ + public static final float SMPTE_30DROP = 29.97f; + + // Private helper class + private void init(float divisionType, int resolution, int numTracks) + throws InvalidMidiDataException + { + if (divisionType != PPQ + && divisionType != SMPTE_24 + && divisionType != SMPTE_25 + && divisionType != SMPTE_30 + && divisionType != SMPTE_30DROP) + throw new InvalidMidiDataException("Invalid division type (" + + divisionType + ")"); + + this.divisionType = divisionType; + this.resolution = resolution; + + tracks = new Vector(numTracks); + while (numTracks > 0) + tracks.set(--numTracks, new Track()); + } + + /** + * Create a MIDI sequence object with no initial tracks. + * + * @param divisionType the division type (must be one of PPQ or SMPTE_*) + * @param resolution the timing resolution + * @throws InvalidMidiDataException if the division type is invalid + */ + public Sequence(float divisionType, int resolution) + throws InvalidMidiDataException + { + init(divisionType, resolution, 0); + } + + /** + * Create a MIDI seqence object. + * + * @param divisionType the division type (must be one of PPQ or SMPTE_*) + * @param resolution the timing resolution + * @param numTracks the number of initial tracks + * @throws InvalidMidiDataException if the division type is invalid + */ + public Sequence(float divisionType, int resolution, int numTracks) + throws InvalidMidiDataException + { + init(divisionType, resolution, 0); + } + + /** + * The division type of this sequence. + * + * @return division type of this sequence + */ + public float getDivisionType() + { + return divisionType; + } + + /** + * The timing resolution for this sequence, relative to the division type. + * + * @return the timing resolution for this sequence + */ + public int getResolution() + { + return resolution; + } + + /** + * Create a new empty MIDI track and add it to this sequence. + * + * @return the newly create MIDI track + */ + public Track createTrack() + { + Track track = new Track(); + tracks.add(track); + return track; + } + + /** + * Remove the specified MIDI track from this sequence. + * + * @param track the track to remove + * @return true if track was removed and false othewise + */ + public boolean deleteTrack(Track track) + { + return tracks.remove(track); + } + + /** + * Get an array of MIDI tracks used in this sequence. + * + * @return a possibly empty array of tracks + */ + public Track[] getTracks() + { + return (Track[]) tracks.toArray(new Track[tracks.size()]); + } + + /** + * The length of this sequence in microseconds. + * + * @return the length of this sequence in microseconds + */ + public long getMicrosecondLength() + { + long tickLength = getTickLength(); + + if (divisionType == PPQ) + { + // FIXME + // How can this possible be computed? PPQ is pulses per quarter-note, + // which is dependent on the tempo of the Sequencer. + throw new UnsupportedOperationException("Can't compute PPQ based lengths yet"); + } + else + { + // This is a fixed tick per frame computation + return (long) ((tickLength * 1000000) / (divisionType * resolution)); + } + } + + /** + * The length of this sequence in MIDI ticks. + * + * @return the length of this sequence in MIDI ticks + */ + public long getTickLength() + { + long length = 0; + Iterator itr = tracks.iterator(); + while (itr.hasNext()) + { + Track track = (Track) itr.next(); + long trackTicks = track.ticks(); + if (trackTicks > length) + length = trackTicks; + } + return length; + } + + /** + * Get an array of patches used in this sequence. + * + * @return an array of patches used in this sequence + */ + public Patch[] getPatchList() + { + // FIXE: not quite sure how to do this yet. + throw new UnsupportedOperationException("Can't get patch list yet"); + } +} diff --git a/javax/sound/midi/Sequencer.java b/javax/sound/midi/Sequencer.java new file mode 100644 index 000000000..55810c81d --- /dev/null +++ b/javax/sound/midi/Sequencer.java @@ -0,0 +1,396 @@ +/* Sequencer.java -- A MIDI sequencer object + 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 java.io.IOException; +import java.io.InputStream; + +/** + * A Sequencer object plays MIDI sequences described as Sequence objects. + * This class provides methods for loading and unloading sequences, as well + * as basic transport controls. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface Sequencer extends MidiDevice +{ + /** + * Set the Sequence object for this sequencer. + * + * @param seq the Sequence to process + * @throws InvalidMidiDataException if the sequence is invalid for any reason + */ + public void setSequence(Sequence seq) throws InvalidMidiDataException; + + /** + * Set the sequence for this sequencer. istream reads on a valid MIDI file. + * + * @param istream an input stream for a valid MIDI file + * @throws IOException if an I/O exception happens + * @throws InvalidMidiDataException if the MIDI file contains bad data + */ + public void setSequence(InputStream istream) throws IOException, InvalidMidiDataException; + + /** + * Get the current sequence object for this sequencer. + * + * @return the current sequence object. May be null. + */ + public Sequence getSequence(); + + /** + * Start playback of the current sequence. + */ + public void start(); + + /** + * Stop playback of the current sequence. + */ + public void stop(); + + /** + * Returns true if the sequence is playing. + * + * @return true if the sequence is playing and false otherwise + */ + public boolean isRunning(); + + /** + * Start playback and record of MIDI events. + * Any tracks enabled for recording will have their events replaced. + * Any newly recorded events, and all events from non-recording tracks + * will be sent to the sequencer's transmitter. + */ + public void startRecording(); + + /** + * Returns true if sequence is recording. + * + * @return true if the sequence is recording and false otherwise + */ + public boolean isRecording(); + + /** + * Enable recording for a specific track using data from a specific channel. + * + * @param track the track to enable for recording + * @param channel the channel from which to record + */ + public void recordEnable(Track track, int channel); + + /** + * Disable recording for a specific track. + * + * @param track the track to disable recording for + */ + public void recordDisable(Track track); + + /** + * Get the current tempo in beats per minute. + * + * @return the current tempo in beats per minute + */ + public float getTempoInBPM(); + + /** + * Sets the current tempo in beats per minute. + * + * @param bpm the new tempo in bears per minutes + */ + public void setTempoInBPM(float bpm); + + /** + * Get the current tempo in microseconds per quarter note. + * + * @return the current tempo in microseconds per quarter note. + */ + public float getTempoInMPQ(); + + /** + * Sets the current tempo in microseconds per quarter note. + * + * @param mpq the new tempo in microseconds per quarter note. + */ + public void setTempoInMPQ(float mpq); + + /** + * Set a scaling factor for the playback tempo, which is 1.0 by default. + * + * @param factor the new tempo scaling factor + */ + public void setTempoFactor(float factor); + + /** + * Get the current scaling factor for the playback tempo. + * + * @return the current tempo scaling factor + */ + public float getTempoFactor(); + + /** + * Get the length of the current sequence in MIDI ticks. + * + * @return the length of the current sequence in MIDI ticks + */ + public long getTickLength(); + + /** + * Get the current playback position of the sequencer in MIDI ticks. + * + * @return the current playback position of the sequencer in MIDI ticks + */ + public long getTickPosition(); + + /** + * Set the current playback position of the sequencer in MIDI ticks. + * + * @param tick the new playback position of the sequencer in MIDI ticks + */ + public void setTickPosition(long tick); + + /** + * Get the length of the current sequence in microseconds. + * + * @return the length of the current sequence in microseconds + */ + public long getMicrosecondLength(); + + /** + * Get the current playback position of the sequencer in microseconds. + * + * @return the current playback position of the sequencer in microseconds + */ + public long getMicrosecondPosition(); + + /** + * Set the current playback position of the sequencer in microseconds. + * + * @param microsecond the new playback position of the sequencer in microseconds + */ + public void setMicrosecondPosition(long microsecond); + + /** + * Set the source of timing information. sync must be found in the array + * returned by getMasterSyncModes(). + * FIXME: What happens if it isn't? + * + * @param sync the new source of timing information + */ + public void setMasterSyncMode(SyncMode sync); + + /** + * Get the source of timing information. + * + * @return the current source of timing information + */ + public SyncMode getMasterSyncMode(); + + /** + * Get an array of timing sources supported by this sequencer. + * + * @return an array of timing sources supported by this sequencer + */ + public SyncMode[] getMasterSyncModes(); + + /** + * Set the slave synchronization mode for this sequencer. sync must be + * found in the array returned by getSlaveSyncModes(). + * FIXME: What happens if it isn't? + * + * @param sync the new slave sync mode for this sequencer + */ + public void setSlaveSyncMode(SyncMode sync); + + /** + * Get the current slave synchronization mode. + * + * @return the current slave synchronization mode + */ + public SyncMode getSlaveSyncMode(); + + /** + * Get an array of slave sync modes supported by this sequencer. + * + * @return an array of slave sync modes supported by this sequencer + */ + public SyncMode[] getSlaveSyncModes(); + + /** + * Sets the mute state for a specific track. + * + * @param track the track to modify + * @param mute the new mute state + */ + public void setTrackMute(int track, boolean mute); + + /** + * Get the mute state of a specific track. + * + * @param track the track to query + * @return the mute state for track + */ + public boolean getTrackMute(int track); + + /** + * Sets the solo state for a specific track. + * + * @param track the track to modify + * @param solo the new solo state + */ + public void setTrackSolo(int track, boolean solo); + + /** + * Get the solo state for a specific track. + * + * @param track the track to query + * @return the solo state for track + */ + public boolean getTrackSolo(int track); + + /** + * Add a meta event listening object to this sequencer. It will receive + * notification whenever the sequencer processes a meta event. + * A listener may fail to get added if this sequencer doesn't support + * meta events. + * + * @param listener the listener to add + * @return true if listener was added, false othewise + */ + public boolean addMetaEventListener(MetaEventListener listener); + + /** + * Remove a meta event listener from this sequencer. + * + * @param listener the listener to remove + */ + public void removeMetaEventListener(MetaEventListener listener); + + /** + * Add a controller event listening object to this sequencer. It will + * receive notification whenever the sequencer processes a controller + * event for a specified controller number.. + * + * @param listener the listener to add + * @param controllers the conroller numbers to listen to + * @return the controller numbers being listened to + */ + public int[] addControllerEventListener(ControllerEventListener listener, + int controllers[]); + + /** + * Remove a controller listener from this sequencer for the specified + * controller numbers. + * + * @param listener the listener to remove + * @param controllers the controllers to unlisten + * @return the controller numbers being unlistened + */ + public int[] removeControllerEventListener(ControllerEventListener listener, + int controllers[]); + + /** + * A SyncMode object represents the mechanism by which a MIDI sequencer + * synchronizes time with a master or slave device. + * + * @author green@redhat.com + * + */ + public static class SyncMode + { + /** + * A master sync mode indicating the use of an internal sequencer clock. + */ + public static final SyncMode INTERNAL_CLOCK = new SyncMode("Internal Clock"); + + /** + * A master or slave sync mode indicating the use of MIDI clock messages. + */ + public static final SyncMode MIDI_SYNC = new SyncMode("MIDI Sync"); + + /** + * A master or slave sync mode indicating the use of MIDI Time Code + * messages. + */ + public static final SyncMode MIDI_TIME_CODE = new SyncMode("MIDI Time Code"); + + /** + * A slave sync mode indicating that no timing info will be transmitted. + */ + public static final SyncMode NO_SYNC = new SyncMode("No Timing"); + + // The name + private String name; + + /** + * Create a new SyncMode object + * @param name the SyncMode name + */ + protected SyncMode(String name) + { + this.name = name; + } + + /** + * SyncMode objects are only equal when identical. + */ + public final boolean equals(Object o) + { + return super.equals(o); + } + + /** + * SyncMode objects use the Object hashCode. + */ + public int hashCode() + { + return super.hashCode(); + } + + /** + * Use the SyncMode name as the string representation. + * @see java.lang.Object#toString() + */ + public final String toString() + { + return name; + } + } +} diff --git a/javax/sound/midi/ShortMessage.java b/javax/sound/midi/ShortMessage.java new file mode 100644 index 000000000..1557c9ca9 --- /dev/null +++ b/javax/sound/midi/ShortMessage.java @@ -0,0 +1,316 @@ +/* ShortMessage.java -- A MIDI message no longer than 3 bytes + 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; + +/** + * A short MIDI message that is no longer than 3 bytes long. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class ShortMessage extends MidiMessage +{ + /** + * Status byte for System Exclusive message. + */ + public static final int SYSTEM_EXCLUSIVE = 0xF0; + + /** + * Status byte for Time Code message. + */ + public static final int MIDI_TIME_CODE = 0xF1; + + /** + * Status byte for Song Position Pointer message. + */ + public static final int SONG_POSITION_POINTER = 0xF2; + + /** + * Status byte for Song Select message. + */ + public static final int SONG_SELECT = 0xF3; + + /** + * Status byte for Tune Request message. + */ + public static final int TUNE_REQUEST = 0xF6; + + /** + * Status byte for End Of Exclusive message. + */ + public static final int END_OF_EXCLUSIVE = 0xF7; + + /** + * Status byte for Timing Clock message. + */ + public static final int TIMING_CLOCK = 0xF8; + + /** + * Status byte for Start message. + */ + public static final int START = 0xFA; + + /** + * Status byte for Continue message. + */ + public static final int CONTINUE = 0xFB; + + /** + * Status byte for Stop message. + */ + public static final int STOP = 0xFC; + + /** + * Status byte for Active Sensing message. + */ + public static final int ACTIVE_SENSING = 0xFE; + + /** + * Status byte for System Reset message. + */ + public static final int SYSTEM_RESET = 0xFF; + + /** + * Status nibble for Note Off message. + */ + public static final int NOTE_OFF = 0x80; + + /** + * Status nibble for Note On message. + */ + public static final int NOTE_ON = 0x90; + + /** + * Status nibble for Poly Pressure message. + */ + public static final int POLY_PRESSURE = 0xA0; + + /** + * Status nibble for Control Change message. + */ + public static final int CONTROL_CHANGE = 0xB0; + + /** + * Status nibble for Program Change message. + */ + public static final int PROGRAM_CHANGE = 0xC0; + + /** + * Statue nibble for Channel Pressure message. + */ + public static final int CHANNEL_PRESSURE = 0xD0; + + /** + * Status nibble for Pitch Bend message. + */ + public static final int PITCH_BEND = 0xE0; + + /** + * Create a short MIDI message. + * + * The data argument should be a valid MIDI message. Unfortunately the spec + * does not allow us to throw an InvalidMidiDataException if data is invalid. + * + * @param data the message data + */ + public ShortMessage(byte[] data) + { + super(data); + } + + /** + * Set the MIDI message. + * + * @param status the status byte for this message + * @param data1 the first data byte for this message + * @param data2 the second data byte for this message + * @throws InvalidMidiDataException if status is bad, or data is out of range + */ + private void setMessage(int status, int data1, int data2) + throws InvalidMidiDataException + { + length = getDataLength(status); + length++; + if (data == null || data.length < length) + data = new byte[length]; + data[0] = (byte) status; + if (length > 1) + { + if (data1 < 0 || data1 > 127) + throw new InvalidMidiDataException("data1 (" + data1 + + ") must be between 0 and 127."); + data[1] = (byte) data1; + if (length > 2) + { + if (data2 < 0 || data2 > 127) + throw new InvalidMidiDataException("data2 (" + data2 + + ") must be between 0 and 127."); + data[2] = (byte) data2; + } + } + } + + /** + * Set the MIDI message to one that requires no data bytes. + * + * @param status the status byte for this message + * @throws InvalidMidiDataException if status is bad, or requires data + */ + public void setMessage(int status) throws InvalidMidiDataException + { + int length = getDataLength(status); + if (length != 0) + throw new InvalidMidiDataException("Status byte 0x" + + Integer.toHexString(status) + + " requires " + + length + " bytes of data."); + setMessage(status, 0, 0); + } + + + /** + * Return the number of data bytes needed for a given MIDI status byte. + * + * @param status the status byte for a short MIDI message + * @return the number of data bytes needed for this status byte + * @throws InvalidMidiDataException if status is an invalid status byte + */ + protected final int getDataLength(int status) throws InvalidMidiDataException + { + int originalStatus = status; + + if ((status & 0xF0) != 0xF0) + status &= 0xF0; + + switch (status) + { + case NOTE_OFF: + case NOTE_ON: + case POLY_PRESSURE: + case CONTROL_CHANGE: + case PITCH_BEND: + case SONG_POSITION_POINTER: + return 2; + + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + case SONG_SELECT: + case 0xF5: // FIXME: unofficial bus select. Not in spec?? + return 1; + + case SYSTEM_EXCLUSIVE: + return 0; // FIXME: is this correct? + + case TUNE_REQUEST: + case END_OF_EXCLUSIVE: + case TIMING_CLOCK: + case START: + case CONTINUE: + case STOP: + case ACTIVE_SENSING: + case SYSTEM_RESET: + return 0; + + default: + throw new InvalidMidiDataException ("Invalid status: 0x" + + Integer.toHexString(originalStatus)); + } + } + + /** + * Get the channel information from this MIDI message, assuming it is a + * MIDI channel message. + * + * @return the MIDI channel for this message + */ + public int getChannel() + { + return data[0] & 0x0F; + } + + /** + * Get the command nibble from this MIDI message, assuming it is a MIDI + * channel message. + * + * @return the MIDI command for this message + */ + public int getCommand() + { + return data[0] & 0xF0; + } + + /** + * Get the first data byte from this message, assuming it exists, and + * zero otherwise. + * + * @return the first data byte or zero if none exists. + */ + public int getData1() + { + if (length > 1) + return data[1]; + else + return 0; + } + + /** + * Get the second data byte from this message, assuming it exists, and + * zero otherwise. + * + * @return the second date byte or zero if none exists. + */ + public int getData2() + { + if (length > 2) + return data[2]; + else + return 0; + } + + /* Create a deep-copy clone of this object. + * @see java.lang.Object#clone() + */ + public Object clone() + { + byte message[] = new byte[length]; + System.arraycopy(data, 0, message, 0, length); + return new ShortMessage(message); + } +} diff --git a/javax/sound/midi/Soundbank.java b/javax/sound/midi/Soundbank.java new file mode 100644 index 000000000..16d9d79ea --- /dev/null +++ b/javax/sound/midi/Soundbank.java @@ -0,0 +1,101 @@ +/* Soundbank.java -- Container of Instruments to be loaded into a Synthesizer + 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; + +/** + * A Soundbank is a container for instruments which may be loaded into + * a Synthesizer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface Soundbank +{ + /** + * Get the sound bank name. + * + * @return the sound bank name + */ + String getName(); + + /** + * Get the sound bank version. + * + * @return the sound bank version + */ + String getVersion(); + + /** + * Get the sound bank vendor. + * + * @return the sound bank vendor + */ + String getVendor(); + + + /** + * Get the sound bank description. + * + * @return the sound bank description + */ + String getDescription(); + + /** + * Get an array of non-Instrument resources in this sound bank. + * + * @return an array of non-instrument resources in this sound bank + */ + SoundbankResource[] getResources(); + + /** + * Get an array of Instruments in this sound bank. + * + * @return an array of instruments in this sound bank + */ + Instrument[] getInstruments(); + + /** + * Get the Instrument for the given Patch. + * + * @param patch the Patch to search for + * @return the Instrument corresponding to patch + */ + Instrument getInstrument(Patch patch); +} diff --git a/javax/sound/midi/SoundbankResource.java b/javax/sound/midi/SoundbankResource.java new file mode 100644 index 000000000..03a751993 --- /dev/null +++ b/javax/sound/midi/SoundbankResource.java @@ -0,0 +1,104 @@ +/* SoundbankResource.java -- An audio resource from a sound bank + 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; + +/** + * SoundbankResource objects represent audio data stored in a sound bank. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class SoundbankResource +{ + private final Soundbank soundBank; + private final String name; + private final Class dataClass; + + /** + * Create a SoundbankResource object. + * + * @param soundBank the soundbank object containing this resource + * @param name the name of the resource + * @param dataClass the class used to represent the audio data + */ + protected SoundbankResource(Soundbank soundBank, String name, Class dataClass) + { + this.soundBank = soundBank; + this.name = name; + this.dataClass = dataClass; + } + + /** + * Get the sound bank containing this resource. + * + * @return the sound bank in which this resource resides + */ + public Soundbank getSoundBank() + { + return soundBank; + } + + /** + * Get the name of this resource. + * + * @return the name of this resource + */ + public String getName() + { + return name; + } + + /** + * Get the class used to represent the audio data for this resource. + * + * @return the class used to represent the audio data for this resource + */ + public Class getDataClass() + { + return dataClass; + } + + /** + * Get the audio data for this resource. + * + * @return the audio data object for this resource + */ + public abstract Object getData(); +} diff --git a/javax/sound/midi/Synthesizer.java b/javax/sound/midi/Synthesizer.java new file mode 100644 index 000000000..f8ea87579 --- /dev/null +++ b/javax/sound/midi/Synthesizer.java @@ -0,0 +1,180 @@ +/* Synthesizer.java -- A MIDI audio synthesizer interface + 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; + +/** + * Interface for MIDI audio synthesizer devices. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface Synthesizer extends MidiDevice +{ + /** + * Get the maximum number of notes that the synth can play at once. + * + * @return the maximum number of notes that the synth can play at once + */ + public int getMaxPolyphony(); + + /** + * The processing latency for this synth in microseconds. + * + * @return the processing latency for this synth in microseconds + */ + public long getLatency(); + + /** + * Get the set of MIDI channels controlled by this synth. + * + * @return an array of MIDI channels controlled by this synth + */ + public MidiChannel[] getChannels(); + + /** + * Get the current status for the voices produced by this synth. + * + * @return an array of VoiceStatus objects, getMaxPolyphony() in length + */ + public VoiceStatus[] getVoiceStatus(); + + /** + * Returns true is this synth is capable of loading soundbank. + * + * @param soundbank the Soundbank to examine + * @return true if soundbank can be loaded, false otherwise + */ + public boolean isSoundbankSupported(Soundbank soundbank); + + /** + * Load an instrument into this synth. The instrument must be part of a + * supported soundbank. + * + * @param instrument the Instrument to load + * @return true if the instrument was loaded and false otherwise + * @throws IllegalArgumentException if this synth doesn't support instrument + */ + public boolean loadInstrument(Instrument instrument) + throws IllegalArgumentException; + + /** + * Unload an instrument from this synth. + * + * @param instrument the Instrument to unload + * @throws IllegalArgumentException if this synth doesn't support instrument + */ + public void unloadInstrument(Instrument instrument) + throws IllegalArgumentException; + + /** + * Move an intrument from one place to another. The instrument at the + * target location is unloaded. + * + * @param from the instrument source + * @param to the instrument target + * @return if from was remapped + * @throws IllegalArgumentException + */ + public boolean remapInstrument(Instrument from, Instrument to) + throws IllegalArgumentException; + + /** + * Get the default Soundbank for this synth. Return null if there is no + * default. + * + * @return the default Soundbank for this synth, possibly null. + */ + public Soundbank getDefaultSoundbank(); + + /** + * Get an array containing all instruments in this synthesizer. + * + * @return an array containing all instruments in this synthesizer + */ + public Instrument[] getAvailableInstruments(); + + /** + * Get an array containing all instruments loaded in this synthesizer. + * + * @return an array containing all instruments loaded in this synthesizer + */ + public Instrument[] getLoadedInstruments(); + + /** + * Load all soundbank instruments into this synthesizer. + * + * @param soundbank the Soundbank from which to load instruments + * @return true if all instruments were loaded, false othewise + * @throws IllegalArgumentException if the soundbank isn't supported by this + */ + public boolean loadAllInstruments(Soundbank soundbank) + throws IllegalArgumentException; + + /** + * Unload all soundbank instruments from this synthesizer. + * + * @param soundbank the Soundbank containing the instruments to unload + * @throws IllegalArgumentException if the soundbank isn't supported by this + */ + public void unloadAllInstruments(Soundbank soundbank) + throws IllegalArgumentException; + + /** + * Load a subset of soundbank instruments into this synthesizer. The + * subset is defined by an array of Patch objects. + * + * @param soundbank the Soundbank from which to load instruments + * @param patchList the array of patches identifying instruments to load + * @return true if instruments were loaded, false otherwise + * @throws IllegalArgumentException if the soundbank isn't supported by this + */ + public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) + throws IllegalArgumentException; + + /** + * Unload a subset of soundbank instruments from this synthesizer. + * + * @param soundbank the Soundbank containing the instruments to unload + * @param patchList the array of patches identifying instruments to unload + * @throws IllegalArgumentException if the soundbank isn't supported by this + */ + public void unloadInstruments(Soundbank soundbank, Patch[] patchList) + throws IllegalArgumentException; +} diff --git a/javax/sound/midi/SysexMessage.java b/javax/sound/midi/SysexMessage.java new file mode 100644 index 000000000..7ab60f4b6 --- /dev/null +++ b/javax/sound/midi/SysexMessage.java @@ -0,0 +1,139 @@ +/* SysexMessage.java -- System Exclusive MIDI message. + 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; + +/** + * A system exclusive MIDI message. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class SysexMessage extends MidiMessage +{ + public static final int SYSTEM_EXCLUSIVE = 0xF0; + + public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; + + /** + * Create a default valid system exclusive message. + * + * The official specs don't specify what message is to be + * created. Our implementation creates an empty + * system exclusive message. + */ + public SysexMessage() + { + super(new byte[2]); + data[0] = (byte) SYSTEM_EXCLUSIVE; + data[1] = (byte) ShortMessage.END_OF_EXCLUSIVE; + } + + /** + * Create a SysexMessage object. + * @param data a complete system exclusive message + */ + public SysexMessage(byte[] data) + { + super(data); + } + + /** + * Set the sysex message. The first data byte (status) must be + * 0xF0 or 0xF7. + * + * @param data the message data + * @param length the length of the message data + * @throws InvalidMidiDataException if the status byte is not 0xF0 or 0xF7 + */ + public void setMessage(byte[] data, int length) + throws InvalidMidiDataException + { + if (data[0] != SYSTEM_EXCLUSIVE + || data[0] != SPECIAL_SYSTEM_EXCLUSIVE) + throw new InvalidMidiDataException("Sysex message starts with 0x" + + Integer.toHexString(data[0]) + + " instead of 0xF0 or 0xF7"); + super.setMessage(data, length); + } + + /** + * Set the sysex message. status must be either 0xF0 or 0xF7. + * + * @param status the sysex statys byte (0xF0 or 0xF7) + * @param data the message data + * @param length the length of the message data + * @throws InvalidMidiDataException if status is not 0xF0 or 0xF7 + */ + public void setMessage(int status, byte[] data, int length) + throws InvalidMidiDataException + { + if (status != SYSTEM_EXCLUSIVE + || status != SPECIAL_SYSTEM_EXCLUSIVE) + throw new InvalidMidiDataException("Sysex message starts with 0x" + + Integer.toHexString(status) + + " instead of 0xF0 or 0xF7"); + this.data = new byte[length+1]; + this.data[0] = (byte) status; + System.arraycopy(data, 0, this.data, 1, length); + this.length = length+1; + } + + /** + * Get the data for this message, not including the status byte. + * @return the message data, not including the status byte + */ + public byte[] getData() + { + byte[] result = new byte[length - 1]; + System.arraycopy(data, 1, result, 0, length - 1); + return result; + } + + /* Create a deep-copy clone of this object. + * @see java.lang.Object#clone() + */ + public Object clone() + { + byte message[] = new byte[length]; + System.arraycopy(data, 0, message, 0, length); + return new SysexMessage(message); + } +} + diff --git a/javax/sound/midi/Track.java b/javax/sound/midi/Track.java new file mode 100644 index 000000000..da7ef2ef3 --- /dev/null +++ b/javax/sound/midi/Track.java @@ -0,0 +1,160 @@ +/* Track.java -- A track of MIDI events + 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 java.util.HashSet; +import java.util.Vector; + +/** + * A Track contains a list of timecoded MIDI events for processing + * by a Sequencer. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class Track +{ + /** + * The list of MidiEvents for this track. + */ + protected Vector events; + + // A HashSet to speed processing + private HashSet eventSet; + + /** + * Add a new event to this track. Specific events may only be added once. + * The event will be inserted into the appropriate spot in the event list + * based on its timecode. + * + * @param event the event to add + * @return true if the event was added, false otherwise + */ + public boolean add(MidiEvent event) + { + synchronized (events) + { + if (eventSet.contains(event)) + return false; + + eventSet.add(event); + + long targetTick = event.getTick(); + int i = events.size() - 1; + while (i >= 0 && (((MidiEvent)events.get(i)).getTick() > targetTick)) + i--; + events.add(i+1, event); + return true; + } + } + + /** + * Remove an event from this track. + * + * @param event the event to remove + * @return true if the event was removed, false otherwise + */ + public boolean remove(MidiEvent event) + { + synchronized (events) + { + if (! eventSet.remove(event)) + return false; + + int i = events.indexOf(event); + if (i >= 0) + { + events.remove(i); + return true; + } + + throw new InternalError("event in set but not list"); + } + } + + /** + * Get an event idetified by its order index + * + * @param index the location of the event to get + * @return the event at index + * @throws ArrayIndexOutOfBoundsException if index is out of bounds + */ + public MidiEvent get(int index) throws ArrayIndexOutOfBoundsException + { + synchronized (events) + { + try + { + return (MidiEvent) events.get(index); + } + catch (IndexOutOfBoundsException e) + { + throw (ArrayIndexOutOfBoundsException) + new ArrayIndexOutOfBoundsException().initCause(e); + } + } + } + + + /** + * Get the number events in this track. + * + * @return the number of events in this track + */ + public int size() + { + return events.size(); + } + + /** + * Get the length of the track in MIDI ticks. + * + * @return the length of the track in MIDI ticks + */ + public long ticks() + { + synchronized (events) + { + int size = events.size(); + return ((MidiEvent) events.get(size - 1)).getTick(); + } + } + } + diff --git a/javax/sound/midi/Transmitter.java b/javax/sound/midi/Transmitter.java new file mode 100644 index 000000000..d788725e0 --- /dev/null +++ b/javax/sound/midi/Transmitter.java @@ -0,0 +1,70 @@ +/* Transmitter.java -- A interface for objects sending MIDI events + 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; + +/** + * This interface specifies the methods required by objects which send + * MIDI events to Receivers, including MIDI IN ports and Sequencers. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public interface Transmitter +{ + /** + * Set the Receiver to which MIDI events will be sent. + * + * @param receiver the Receiver to which MIDI events will be sent + */ + public void setReceiver(Receiver receiver); + + /** + * Get the Receiver to which MIDI events will be sent (possibly null) + * + * @return the Receiver to which MIDI events will be sent (possibly null) + */ + public Receiver getReceiver(); + + /** + * Close this Transmitter, possibly releasing system resources. + * FIXME: Does this mean the Receiver is closed? I think it must. + */ + public void close(); +} diff --git a/javax/sound/midi/VoiceStatus.java b/javax/sound/midi/VoiceStatus.java new file mode 100644 index 000000000..a6a9c3f87 --- /dev/null +++ b/javax/sound/midi/VoiceStatus.java @@ -0,0 +1,79 @@ +/* VoiceStatus.java -- the current status of a Synthesizer voice + 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; + +/** + * Objects of this type define the status of a Synthesizer voice. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public class VoiceStatus +{ + /** + * True if this voice is processing a MIDI note. + */ + public boolean active = false; + + /** + * The channel for this voice when active. + */ + public int channel = 0; + + /** + * The bank of the voice when active. + */ + public int bank = 0; + + /** + * The program for this voice when active. + */ + public int program = 0; + + /** + * The note for this voice when active. + */ + public int note = 0; + + /** + * The volume for this voice when active. + */ + public int volume = 0; +} diff --git a/javax/sound/midi/spi/MidiDeviceProvider.java b/javax/sound/midi/spi/MidiDeviceProvider.java new file mode 100644 index 000000000..537edb2b3 --- /dev/null +++ b/javax/sound/midi/spi/MidiDeviceProvider.java @@ -0,0 +1,90 @@ +/* MidiDeviceProvider.java -- Abstract parent for a MIDI device provider. + 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.spi; + +import javax.sound.midi.*; + +/** + * The abstract base class for all MidiDeviceProvider types. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class MidiDeviceProvider +{ + /** + * Returns true if this provider supports a specific MIDI device. + * + * @param info the MIDI device descriptor + * @return true if this provider supports info + */ + public boolean isDeviceSupported(MidiDevice.Info info) + { + MidiDevice.Info infos[] = getDeviceInfo(); + + int i = infos.length; + + while (i > 0) + { + if (info.equals(infos[--i])) + return true; + } + + return false; + } + + /** + * Get the list descriptors for all MIDI devices supported by + * this provider. + * + * @return an array of descriptors for all supported MIDI devices. + */ + public abstract MidiDevice.Info[] getDeviceInfo(); + + /** + * Get the MidiDevice for the MIDI device described by info + * + * @param info the descriptor for the MIDI device we want + * @return the MidiDevice we're looking for + * @throws IllegalArgumentException is this provider doesn't support info + */ + public abstract MidiDevice getDevice(MidiDevice.Info info) + throws IllegalArgumentException; +} diff --git a/javax/sound/midi/spi/MidiFileReader.java b/javax/sound/midi/spi/MidiFileReader.java new file mode 100644 index 000000000..4342ebf5e --- /dev/null +++ b/javax/sound/midi/spi/MidiFileReader.java @@ -0,0 +1,125 @@ +/* MidiFilerReader.java -- MIDI file reading services + 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.spi; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MidiFileFormat; +import javax.sound.midi.Sequence; + +/** + * The MidiFileReader abstract class defines the methods to be provided + * by a MIDI file reader. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class MidiFileReader +{ + /** + * Read a MidiFileFormat from the given stream. + * + * @param stream the stream from which to read the MIDI data + * @return the MidiFileFormat object + * @throws InvalidMidiDataException if the stream refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract MidiFileFormat getMidiFileFormat(InputStream stream) + throws InvalidMidiDataException, IOException; + + /** + * Read a MidiFileFormat from the given stream. + * + * @param url the url from which to read the MIDI data + * @return the MidiFileFormat object + * @throws InvalidMidiDataException if the url refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract MidiFileFormat getMidiFileFormat(URL url) + throws InvalidMidiDataException, IOException; + + /** + * Read a MidiFileFormat from the given stream. + * + * @param file the file from which to read the MIDI data + * @return the MidiFileFormat object + * @throws InvalidMidiDataException if the file refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract MidiFileFormat getMidiFileFormat(File file) + throws InvalidMidiDataException, IOException; + + /** + * Read a Sequence from the given stream. + * + * @param stream the stream from which to read the MIDI data + * @return the Sequence object + * @throws InvalidMidiDataException if the stream refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract Sequence getSequence(InputStream stream) + throws InvalidMidiDataException, IOException; + + /** + * Read a Sequence from the given stream. + * + * @param url the url from which to read the MIDI data + * @return the Sequence object + * @throws InvalidMidiDataException if the url refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract Sequence getSequence(URL url) + throws InvalidMidiDataException, IOException; + + /** + * Read a Sequence from the given stream. + * + * @param file the file from which to read the MIDI data + * @return the Sequence object + * @throws InvalidMidiDataException if the file refers to invalid data + * @throws IOException if an I/O exception occurs while reading + */ + public abstract Sequence getSequence(File file) + throws InvalidMidiDataException, IOException; +} diff --git a/javax/sound/midi/spi/MidiFileWriter.java b/javax/sound/midi/spi/MidiFileWriter.java new file mode 100644 index 000000000..e2a1f55c6 --- /dev/null +++ b/javax/sound/midi/spi/MidiFileWriter.java @@ -0,0 +1,143 @@ +/* MidiFileWriter.java -- MIDI file writing services + 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.spi; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.sound.midi.Sequence; + +/** + * MidiFileWriter provides MIDI file writing services. + * + * There are three types of Standard MIDI File (SMF) formats, + * represented by integers 0, 1, and 2. + * + * Type 0 files contain a single track and represents a single song + * performance. + * Type 1 may contain multiple tracks for a single song performance. + * Type 2 may contain multiple tracks, each representing a + * separate song performance. + * + * See http://en.wikipedia.org/wiki/MIDI#MIDI_file_formats for more + * information. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class MidiFileWriter +{ + /** + * Return the MIDI file types supported by this writer. + * + * @return the MIDI file types, or an empty array + */ + public abstract int[] getMidiFileTypes(); + + /** + * Return the MIDI file types supported by this writer for the + * given sequence. + * + * @param sequence the sequence we'd like to write + * @return the MIDI file types, or an empty array + */ + public abstract int[] getMidiFileTypes(Sequence sequence); + + /** + * Returns true if this writer supports the given file type. + * + * @param fileType the file type we're asking about + * @return true if this writer supports fileType, false otherwise + */ + public boolean isFileTypeSupported(int fileType) + { + int types[] = getMidiFileTypes(); + for (int i = types.length; i > 0;) + { + if (types[--i] == fileType) + return true; + } + return false; + } + + /** + * Returns true if this writer supports the given file type for the + * given sequence. + * + * @param fileType the file type we're asking about + * @param sequence the sequence we'd like to write + * @return true if this writer supports fileType, false otherwise + */ + public boolean isFileTypeSupported(int fileType, Sequence sequence) + { + int types[] = getMidiFileTypes(sequence); + for (int i = types.length; i > 0;) + { + if (types[--i] == fileType) + return true; + } + return false; + } + + /** + * Write a sequence to a stream using the specified MIDI file type. + * + * @param in the sequence to write + * @param fileType the MIDI file type to use + * @param out the output stream to write to + * @return the number of byte written + * @throws IOException if an I/O exception happens + */ + public abstract int write(Sequence in, int fileType, OutputStream out) + throws IOException; + + /** + * Write a sequence to a file using the specified MIDI file type. + * + * @param in the sequence to write + * @param fileType the MIDI file type to use + * @param out the file to write to + * @return the number of byte written + * @throws IOException if an I/O exception happens + */ + public abstract int write(Sequence in, int fileType, File out) + throws IOException; +} diff --git a/javax/sound/midi/spi/SoundbankReader.java b/javax/sound/midi/spi/SoundbankReader.java new file mode 100644 index 000000000..dbf2bb018 --- /dev/null +++ b/javax/sound/midi/spi/SoundbankReader.java @@ -0,0 +1,97 @@ +/* SoundbankReader.java -- Soundbank file reading services + 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.spi; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; + +/** + * The SoundbankReader abstract class defines the methods to be provided + * by a soundbank file reader. + * + * @author Anthony Green (green@redhat.com) + * @since 1.3 + * + */ +public abstract class SoundbankReader +{ + /** + * Get a Soundbank from the given URL. + * + * @param url from which to read the Soundbank + * + * @return the Soundbank object + * + * @throws InvalidMidiDataException if the data provided by url cannot be recognized + * @throws IOException if the data provided by url cannot be read + */ + public abstract Soundbank getSoundbank(URL url) + throws InvalidMidiDataException, IOException; + + /** + * Get a Soundbank from the given InputStream. + * + * @param stream from which to read the Soundbank + * + * @return the Soundbank object + * + * @throws InvalidMidiDataException if the data provided by InputStream cannot be recognized + * @throws IOException if the data provided by InputStream cannot be read + */ + public abstract Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException; + + /** + * Get a Soundbank from the given File. + * + * @param file from which to read the Soundbank + * + * @return the Soundbank object + * + * @throws InvalidMidiDataException if the data provided by File cannot be recognized + * @throws IOException if the data provided by File cannot be read + */ + public abstract Soundbank getSoundbank(File file) + throws InvalidMidiDataException, IOException; +} -- cgit v1.2.1