diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/sound/midi')
12 files changed, 2904 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaInputPortDevice.java b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaInputPortDevice.java new file mode 100644 index 000000000..d37a8fd6b --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaInputPortDevice.java @@ -0,0 +1,130 @@ +/* AlsaInputPortDevice.java -- ALSA MIDI In Port + 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 gnu.javax.sound.midi.alsa; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; +import gnu.javax.sound.midi.alsa.AlsaMidiDeviceProvider.AlsaPortInfo; + +/** + * ALSA MIDI In Port. + * + * @author Anthony Green (green@redhat.com) + * + */ +public class AlsaInputPortDevice extends AlsaPortDevice +{ + + AlsaInputPortDevice (AlsaPortInfo info) + { + super(info); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#open() + */ + public void open() throws MidiUnavailableException + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#close() + */ + public void close() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#isOpen() + */ + public boolean isOpen() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMicrosecondPosition() + */ + public long getMicrosecondPosition() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxReceivers() + */ + public int getMaxReceivers() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxTransmitters() + */ + public int getMaxTransmitters() + { + // TODO Auto-generated method stub + return 1; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getReceiver() + */ + public Receiver getReceiver() throws MidiUnavailableException + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getTransmitter() + */ + public Transmitter getTransmitter() throws MidiUnavailableException + { + return new AlsaTransmitter(); + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiDeviceProvider.java b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiDeviceProvider.java new file mode 100644 index 000000000..33181b6d5 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiDeviceProvider.java @@ -0,0 +1,216 @@ +/* AlsaMidiDeviceProvider.java -- The ALSA 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 gnu.javax.sound.midi.alsa; + +import gnu.classpath.Configuration; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDevice.Info; +import javax.sound.midi.spi.MidiDeviceProvider; + +/** + * Provide ALSA MIDI devices. + * + * @author Anthony Green (green@redhat.com) + * + */ +public class AlsaMidiDeviceProvider extends MidiDeviceProvider +{ + /** + * Abstract base for ALSA specific MIDI device info. + * + * @author Anthony Green (green@redhat.com) + * + */ + private static abstract class AlsaInfo extends Info + { + /** + * Create an ALSA specific MIDI device info object. + * + * @param name the device name + * @param description the device description + */ + public AlsaInfo(String name, String description) + { + super(name, "Alsa", description, "0.0"); + } + + abstract MidiDevice getDevice (); + } + + /** + * ALSA MIDI Port. + * + * @author Anthony Green (green@redhat.com) + * + */ + public static abstract class AlsaPortInfo extends AlsaInfo + { + long client; + long port; + + /** + * Create ALSA MIDI In Port. + * + * @param name the device name + * @param description the device description + * @param client the client ID + * @param port the port ID + */ + public AlsaPortInfo(String name, String description, long client, long port) + { + super(name, description); + this.client = client; + this.port = port; + } + } + + /** + * ALSA Sequencer specific info. + * + * @author Anthony Green (green@redhat.com) + * + */ + private static class AlsaSequencerInfo extends AlsaInfo + { + public AlsaSequencerInfo(String name, String description) + { + super(name, description); + } + + MidiDevice getDevice() + { + return AlsaMidiSequencerDevice.getInstance(); + } + } + + /** + * ALSA MIDI In Port. + * + * @author Anthony Green (green@redhat.com) + * + */ + private static class AlsaInputPortInfo extends AlsaPortInfo + { + public AlsaInputPortInfo(String name, String description, long client, long port) + { + super(name, description, client, port); + } + + MidiDevice getDevice() + { + return new AlsaInputPortDevice(this); + } + } + + /** + * ALSA MIDI Out Port. + * + * @author Anthony Green (green@redhat.com) + * + */ + private static class AlsaOutputPortInfo extends AlsaPortInfo + { + public AlsaOutputPortInfo(String name, String description, long client, long port) + { + super(name, description, client, port); + } + + MidiDevice getDevice() + { + return new AlsaOutputPortDevice(this); + } + } + + private static AlsaInfo[] infos; + + private static native AlsaInfo[] getInputDeviceInfo_(); + private static native AlsaInfo[] getOutputDeviceInfo_(); + + /** + * Initialize the ALSA system + */ + private static native void init_(); + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("gjsmalsa"); + } + + init_(); + + AlsaInfo inputs[] = getInputDeviceInfo_(); + AlsaInfo outputs[] = getOutputDeviceInfo_(); + + infos = new AlsaInfo[inputs.length + outputs.length + 1]; + infos[0] = new AlsaSequencerInfo ("/dev/snd/seq", "ALSA Sequencer"); + System.arraycopy(inputs, 0, infos, 1, inputs.length); + System.arraycopy(outputs, 0, infos, 1 + inputs.length, outputs.length); + } + + public AlsaMidiDeviceProvider() + { + // Nothing. + } + + /* (non-Javadoc) + * @see javax.sound.midi.spi.MidiDeviceProvider#getDeviceInfo() + */ + public Info[] getDeviceInfo() + { + return infos; + } + + /* (non-Javadoc) + * @see javax.sound.midi.spi.MidiDeviceProvider#getDevice(javax.sound.midi.MidiDevice.Info) + */ + public MidiDevice getDevice(Info info) + { + for (int i = 0; i < infos.length; i++) + { + if (info.equals(infos[i])) + { + return infos[i].getDevice(); + } + } + throw new IllegalArgumentException("Don't recognize MIDI device " + info); + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiSequencerDevice.java b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiSequencerDevice.java new file mode 100644 index 000000000..3603bb5a7 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaMidiSequencerDevice.java @@ -0,0 +1,515 @@ +/* AlsaMidiSequencerDevice.java -- The ALSA MIDI sequencer device + Copyright (C) 2005, 2006 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 gnu.javax.sound.midi.alsa; + +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.ControllerEventListener; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaEventListener; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Track; +import javax.sound.midi.Transmitter; + +/** + * The ALSA MIDI sequencer device. This is a singleton device. + * + * @author green@redhat.com + * + */ +public class AlsaMidiSequencerDevice implements Sequencer +{ + // The singleton instance. + public final static AlsaMidiSequencerDevice instance = new AlsaMidiSequencerDevice(); + + // A pointer to a native chunk of memory + private long nativeState; + + // The sequence to process + private Sequence sequence; + + /** + * A private constructor. There should only be one instance of this + * device. + */ + private AlsaMidiSequencerDevice() + { + super(); + } + + /** + * Return the sequencer singleton. + * + * @return the sequencer singleton + */ + public static AlsaMidiSequencerDevice getInstance() + { + return instance; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setSequence(javax.sound.midi.Sequence) + */ + public void setSequence(Sequence seq) throws InvalidMidiDataException + { + sequence = seq; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setSequence(java.io.InputStream) + */ + public void setSequence(InputStream istream) throws IOException, + InvalidMidiDataException + { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getSequence() + */ + public Sequence getSequence() + { + return sequence; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#start() + */ + public void start() + { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#stop() + */ + public void stop() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#isRunning() + */ + public boolean isRunning() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#startRecording() + */ + public void startRecording() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#stopRecording() + */ + public void stopRecording() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#isRecording() + */ + public boolean isRecording() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#recordEnable(javax.sound.midi.Track, int) + */ + public void recordEnable(Track track, int channel) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#recordDisable(javax.sound.midi.Track) + */ + public void recordDisable(Track track) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTempoInBPM() + */ + public float getTempoInBPM() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTempoInBPM(float) + */ + public void setTempoInBPM(float bpm) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTempoInMPQ() + */ + public float getTempoInMPQ() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTempoInMPQ(float) + */ + public void setTempoInMPQ(float mpq) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTempoFactor(float) + */ + public void setTempoFactor(float factor) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTempoFactor() + */ + public float getTempoFactor() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTickLength() + */ + public long getTickLength() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTickPosition() + */ + public long getTickPosition() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTickPosition(long) + */ + public void setTickPosition(long tick) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getMicrosecondLength() + */ + public long getMicrosecondLength() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getMicrosecondPosition() + */ + public long getMicrosecondPosition() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setMicrosecondPosition(long) + */ + public void setMicrosecondPosition(long microsecond) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setMasterSyncMode(javax.sound.midi.Sequencer.SyncMode) + */ + public void setMasterSyncMode(SyncMode sync) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getMasterSyncMode() + */ + public SyncMode getMasterSyncMode() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getMasterSyncModes() + */ + public SyncMode[] getMasterSyncModes() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setSlaveSyncMode(javax.sound.midi.Sequencer.SyncMode) + */ + public void setSlaveSyncMode(SyncMode sync) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getSlaveSyncMode() + */ + public SyncMode getSlaveSyncMode() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getSlaveSyncModes() + */ + public SyncMode[] getSlaveSyncModes() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTrackMute(int, boolean) + */ + public void setTrackMute(int track, boolean mute) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTrackMute(int) + */ + public boolean getTrackMute(int track) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#setTrackSolo(int, boolean) + */ + public void setTrackSolo(int track, boolean solo) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#getTrackSolo(int) + */ + public boolean getTrackSolo(int track) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#addMetaEventListener(javax.sound.midi.MetaEventListener) + */ + public boolean addMetaEventListener(MetaEventListener listener) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#removeMetaEventListener(javax.sound.midi.MetaEventListener) + */ + public void removeMetaEventListener(MetaEventListener listener) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#addControllerEventListener(javax.sound.midi.ControllerEventListener, int[]) + */ + public int[] addControllerEventListener(ControllerEventListener listener, + int[] controllers) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Sequencer#removeControllerEventListener(javax.sound.midi.ControllerEventListener, int[]) + */ + public int[] removeControllerEventListener(ControllerEventListener listener, + int[] controllers) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getDeviceInfo() + */ + public Info getDeviceInfo() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#open() + */ + public void open() throws MidiUnavailableException + { + synchronized(this) + { + // Check to see if we're open already. + if (nativeState != 0) + return; + + nativeState = open_(); + } + } + + /** + * Allocate the native state object, and open the sequencer. + * + * @return a long representation of a pointer to the nativeState. + */ + private native long open_(); + + /** + * Close the sequencer and free the native state object. + */ + private native void close_(long nativeState); + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#close() + */ + public void close() + { + synchronized(this) + { + close_(nativeState); + nativeState = 0; + } + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#isOpen() + */ + public boolean isOpen() + { + synchronized(this) + { + return (nativeState != 0); + } + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxReceivers() + */ + public int getMaxReceivers() + { + return -1; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxTransmitters() + */ + public int getMaxTransmitters() + { + return -1; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getReceiver() + */ + public Receiver getReceiver() throws MidiUnavailableException + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getTransmitter() + */ + public Transmitter getTransmitter() throws MidiUnavailableException + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaOutputPortDevice.java b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaOutputPortDevice.java new file mode 100644 index 000000000..9140d59ad --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaOutputPortDevice.java @@ -0,0 +1,131 @@ +/* AlsaOutputPortDevice.java -- ALSA MIDI Output Port Device + 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 gnu.javax.sound.midi.alsa; + +import gnu.javax.sound.midi.alsa.AlsaMidiDeviceProvider.AlsaPortInfo; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + +/** + * ALSA MIDI Out Device + * + * @author Anthony Green (green@redhat.com) + * + */ +public class AlsaOutputPortDevice extends AlsaPortDevice +{ + AlsaOutputPortDevice (AlsaPortInfo info) + { + super(info); + } + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#open() + */ + public void open() throws MidiUnavailableException + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#close() + */ + public void close() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#isOpen() + */ + public boolean isOpen() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMicrosecondPosition() + */ + public long getMicrosecondPosition() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxReceivers() + */ + public int getMaxReceivers() + { + // TODO Auto-generated method stub + return 1; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMaxTransmitters() + */ + public int getMaxTransmitters() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getReceiver() + */ + public Receiver getReceiver() throws MidiUnavailableException + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getTransmitter() + */ + public Transmitter getTransmitter() throws MidiUnavailableException + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaPortDevice.java b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaPortDevice.java new file mode 100644 index 000000000..f55941ba5 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/alsa/AlsaPortDevice.java @@ -0,0 +1,150 @@ +/* AlsaPortDevice.java -- ALSA MIDI Port Devices + Copyright (C) 2005, 2006 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 gnu.javax.sound.midi.alsa; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Receiver; +import javax.sound.midi.Transmitter; + +import gnu.javax.sound.midi.alsa.AlsaMidiDeviceProvider.AlsaPortInfo; + +/** + * ALSA Port Device + * + * @author Anthony Green (green@redhat.com) + * + */ +public abstract class AlsaPortDevice implements MidiDevice +{ + /** + * The ALSA Receiver class. + * + * @author Anthony Green (green@redhat.com) + * + */ + public class AlsaReceiver implements Receiver + { + /* (non-Javadoc) + * @see javax.sound.midi.Receiver#send(javax.sound.midi.MidiMessage, long) + */ + public void send(MidiMessage message, long timeStamp) + throws IllegalStateException + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Receiver#close() + */ + public void close() + { + // TODO Auto-generated method stub + + } + } + + AlsaMidiDeviceProvider.AlsaPortInfo info; + + public AlsaPortDevice (AlsaPortInfo info) + { + this.info = info; + } + + public Info getDeviceInfo() + { + return info; + } + + native void run_receiver_thread_ (long client, long port, Receiver receiver); + + /** + * The ALSA Transmitter class. + * + * @author Anthony Green (green@redhat.com) + * + */ + protected class AlsaTransmitter implements Transmitter, Runnable + { + private Receiver receiver; + + public void run() + { + run_receiver_thread_ (info.client, info.port, receiver); + } + + /* (non-Javadoc) + * @see javax.sound.midi.Transmitter#setReceiver(javax.sound.midi.Receiver) + */ + public void setReceiver(Receiver receiver) + { + synchronized (this) + { + this.receiver = receiver; + } + + // Create the processing thread + new Thread(this).start(); + } + + /* (non-Javadoc) + * @see javax.sound.midi.Transmitter#getReceiver() + */ + public Receiver getReceiver() + { + synchronized (this) + { + return receiver; + } + } + + /* (non-Javadoc) + * @see javax.sound.midi.Transmitter#close() + */ + public void close() + { + synchronized (this) + { + receiver.close(); + receiver = null; + } + } + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java new file mode 100644 index 000000000..605c6dfb7 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java @@ -0,0 +1,171 @@ +/* DSSIMidiDeviceProvider.java -- DSSI 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 gnu.javax.sound.midi.dssi; + +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.io.FilenameFilter; + +import gnu.classpath.Configuration; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDevice.Info; +import javax.sound.midi.spi.MidiDeviceProvider; + +/** + * A DSSI MIDI device provider. + * + * DSSI (pronounced "dizzy") is an API for audio plugins, with particular + * application for software synthesis plugins with native user interfaces. + * + * Read about DSSI at http://dssi.sourceforge.net + * + * @author Anthony Green (green@redhat.com) + * + */ +public class DSSIMidiDeviceProvider extends MidiDeviceProvider +{ + /** + * The MidiDevice.Info specialized for DSSI synthesizers. + * + * @author Anthony Green (green@redhat.com) + * + */ + private static class DSSIInfo extends Info + { + String soname; + long index; + + public DSSIInfo(String name, String vendor, String description, + String version, String soname, long index) + { + super(name, vendor, description, version); + this.soname = soname; + this.index = index; + } + } + + static native long dlopen_(String soname); + static native void dlclose_(long sohandle); + static native long getDSSIHandle_(long sohandle, long index); + static native String getDSSIName_(long handle); + static native String getDSSICopyright_(long handle); + static native String getDSSIVendor_(long handle); + static native String getDSSILabel_(long handle); + + private static List examineLibrary(String soname) + { + List list = new ArrayList(); + long index = 0; + long handle; + + long sohandle = dlopen_(soname); + if (sohandle == 0) + return list; + do + { + handle = getDSSIHandle_(sohandle, index); + if (handle == 0) + break; + String name = getDSSILabel_(handle); + String copyright = getDSSICopyright_(handle); + String label = getDSSIName_(handle); + String vendor = getDSSIVendor_(handle); + list.add(new DSSIInfo(name, vendor, label, + "DSSI-1", soname, index)); + index++; + } while (true); + + // Close the library and free memory + dlclose_(sohandle); + + return list; + } + + private static DSSIInfo[] infos; + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + System.loadLibrary("gjsmdssi"); + + File dssidir = new File("/usr/lib/dssi/"); + String sofiles[] = dssidir.list(new FilenameFilter() + { + public boolean accept(File dir, String n) + { + return n.endsWith(".so"); + } + }); + List ilist = new ArrayList(); + for (int i = 0; i < sofiles.length; i++) + ilist.addAll(examineLibrary(new File(dssidir, sofiles[i]).getAbsolutePath())); + infos = (DSSIInfo[]) ilist.toArray(new DSSIInfo[ilist.size()]); + } + + public DSSIMidiDeviceProvider() + { + // Empty. + } + + /* Return the Info array. + * @see javax.sound.midi.spi.MidiDeviceProvider#getDeviceInfo() + */ + public Info[] getDeviceInfo() + { + return infos; + } + + /* Get a MIDI Device for info. + * @see javax.sound.midi.spi.MidiDeviceProvider#getDevice(javax.sound.midi.MidiDevice.Info) + */ + public MidiDevice getDevice(Info info) + { + for (int i = 0; i < infos.length; i++) + { + if (info.equals(infos[i])) + { + return new DSSISynthesizer(infos[i], + infos[i].soname, + infos[i].index); + } + } + throw new IllegalArgumentException("Don't recognize MIDI device " + info); + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/dssi/DSSISynthesizer.java b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSISynthesizer.java new file mode 100644 index 000000000..9472ee4ad --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSISynthesizer.java @@ -0,0 +1,742 @@ +/* DSSISynthesizer.java -- DSSI Synthesizer Provider + Copyright (C) 2005, 2006 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 gnu.javax.sound.midi.dssi; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Transmitter; +import javax.sound.midi.VoiceStatus; + +/** + * DSSI soft-synth support. + * + * All DSSI soft-synths are expected to be installed in /usr/lib/dssi. + * + * @author Anthony Green (green@redhat.com) + * + */ +public class DSSISynthesizer implements Synthesizer +{ + /** + * The DSSI Instrument class. + * + * @author Anthony Green (green@redhat.com) + * + */ + class DSSIInstrument extends Instrument + { + DSSIInstrument (Soundbank soundbank, Patch patch, String name) + { + super (soundbank, patch, name, null); + } + + /* @see javax.sound.midi.SoundbankResource#getData() + */ + public Object getData() + { + return null; + } + + } + +/** + * DSSISoundbank holds all instruments. + * + * @author Anthony Green (green@redhat.com) + * + */ + class DSSISoundbank implements Soundbank + { + private String name; + private String description; + private List instruments = new ArrayList(); + private List resources = new ArrayList(); + private String vendor; + private String version; + + public DSSISoundbank(String name, String description, String vendor, String version) + { + this.name = name; + this.description = description; + this.vendor = vendor; + this.version = version; + } + + void add(Instrument instrument) + { + instruments.add(instrument); + } + + /* @see javax.sound.midi.Soundbank#getName() + */ + public String getName() + { + return name; + } + + /* @see javax.sound.midi.Soundbank#getVersion() + */ + public String getVersion() + { + return version; + } + + /* @see javax.sound.midi.Soundbank#getVendor() + */ + public String getVendor() + { + return vendor; + } + + /* @see javax.sound.midi.Soundbank#getDescription() + */ + public String getDescription() + { + return description; + } + + /* @see javax.sound.midi.Soundbank#getResources() + */ + public SoundbankResource[] getResources() + { + return (SoundbankResource[]) + resources.toArray(new SoundbankResource[resources.size()]); + } + + /* @see javax.sound.midi.Soundbank#getInstruments() + */ + public Instrument[] getInstruments() + { + return (Instrument[]) + instruments.toArray(new Instrument[instruments.size()]); + } + + /* @see javax.sound.midi.Soundbank#getInstrument(javax.sound.midi.Patch) + */ + public Instrument getInstrument(Patch patch) + { + Iterator itr = instruments.iterator(); + + while (itr.hasNext()) + { + Instrument i = (Instrument) itr.next(); + if (i.getPatch().equals(patch)) + return i; + } + + return null; + } + } + +/** + * The Receiver class receives all MIDI messages from a connected + * Transmitter. + * + * @author Anthony Green (green@redhat.com) + * + */ + class DSSIReceiver implements Receiver + { + /* (non-Javadoc) + * @see javax.sound.midi.Receiver#send(javax.sound.midi.MidiMessage, long) + */ + public void send(MidiMessage message, long timeStamp) + throws IllegalStateException + { + if (message instanceof ShortMessage) + { + ShortMessage smessage = (ShortMessage) message; + + switch (message.getStatus()) + { + case ShortMessage.NOTE_ON: + int velocity = smessage.getData2(); + if (velocity > 0) + channels[smessage.getChannel()].noteOn(smessage.getData1(), + smessage.getData2()); + else + channels[smessage.getChannel()].noteOff(smessage.getData1()); + break; + case ShortMessage.CONTROL_CHANGE: + channels[smessage.getChannel()].controlChange(smessage.getData1(), + smessage.getData2()); + break; + default: + System.out.println ("Unhandled message: " + message.getStatus()); + break; + } + } + } + + /* (non-Javadoc) + * @see javax.sound.midi.Receiver#close() + */ + public void close() + { + // TODO Auto-generated method stub + } + + } + + static native void noteOn_(long handle, int channel, int noteNumber, int velocity); + static native void noteOff_(long handle, int channel, int noteNumber, int velocity); + static native void setPolyPressure_(long handle, int channel, int noteNumber, int pressure); + static native int getPolyPressure_(long handle, int channel, int noteNumber); + static native void controlChange_(long handle, int channel, int control, int value); + static native void open_(long handle); + static native void close_(long handle); + static native String getProgramName_(long handle, int index); + static native int getProgramBank_(long handle, int index); + static native int getProgramProgram_(long handle, int index); + static native void selectProgram_(long handle, int bank, int program); + + /** + * @author Anthony Green (green@redhat.com) + * + */ + public class DSSIMidiChannel implements MidiChannel + { + int channel = 0; + + /** + * Default contructor. + */ + public DSSIMidiChannel(int channel) + { + super(); + this.channel = channel; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#noteOn(int, int) + */ + public void noteOn(int noteNumber, int velocity) + { + noteOn_(sohandle, channel, noteNumber, velocity); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#noteOff(int, int) + */ + public void noteOff(int noteNumber, int velocity) + { + noteOff_(sohandle, channel, noteNumber, velocity); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#noteOff(int) + */ + public void noteOff(int noteNumber) + { + noteOff_(sohandle, channel, noteNumber, -1); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setPolyPressure(int, int) + */ + public void setPolyPressure(int noteNumber, int pressure) + { + setPolyPressure_(sohandle, channel, noteNumber, pressure); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getPolyPressure(int) + */ + public int getPolyPressure(int noteNumber) + { + return getPolyPressure_(sohandle, channel, noteNumber); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setChannelPressure(int) + */ + public void setChannelPressure(int pressure) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getChannelPressure() + */ + public int getChannelPressure() + { + // TODO Auto-generated method stub + return 0; + } + + /* @see javax.sound.midi.MidiChannel#controlChange(int, int) */ + public void controlChange(int controller, int value) + { + controlChange_(sohandle, channel, controller, value); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getController(int) + */ + public int getController(int controller) + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#programChange(int) + */ + public void programChange(int program) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#programChange(int, int) + */ + public void programChange(int bank, int program) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getProgram() + */ + public int getProgram() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setPitchBend(int) + */ + public void setPitchBend(int bend) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getPitchBend() + */ + public int getPitchBend() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#resetAllControllers() + */ + public void resetAllControllers() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#allNotesOff() + */ + public void allNotesOff() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#allSoundOff() + */ + public void allSoundOff() + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#localControl(boolean) + */ + public boolean localControl(boolean on) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setMono(boolean) + */ + public void setMono(boolean on) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getMono() + */ + public boolean getMono() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setOmni(boolean) + */ + public void setOmni(boolean on) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getOmni() + */ + public boolean getOmni() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setMute(boolean) + */ + public void setMute(boolean mute) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getMute() + */ + public boolean getMute() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#setSolo(boolean) + */ + public void setSolo(boolean solo) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiChannel#getSolo() + */ + public boolean getSolo() + { + // TODO Auto-generated method stub + return false; + } + + } + + long sohandle; + long handle; + private Info info; + + MidiChannel channels[] = new MidiChannel[16]; + + // The list of known soundbanks, and the default one. + List soundbanks = new ArrayList(); + DSSISoundbank defaultSoundbank; + + /** + * Create a DSSI Synthesizer. + * + * @param info the DSSIInfo for this soft-synth + * @param soname the name of the .so file for this DSSI synth + * @param index the DSSI index for this soft-synth + */ + public DSSISynthesizer(Info info, String soname, long index) + { + super(); + this.info = info; + sohandle = DSSIMidiDeviceProvider.dlopen_(soname); + handle = DSSIMidiDeviceProvider.getDSSIHandle_(sohandle, index); + channels[0] = new DSSIMidiChannel(0); + defaultSoundbank = new DSSISoundbank("name", "description", + "vendor", "version"); + soundbanks.add(defaultSoundbank); + + int i = 0; + String name; + do + { + name = getProgramName_(sohandle, i); + if (name != null) + { + defaultSoundbank. + add(new DSSIInstrument(defaultSoundbank, + new Patch(getProgramBank_(sohandle, i), + getProgramProgram_(sohandle, i)), + name)); + i++; + } + } while (name != null); + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#getMaxPolyphony() + */ + public int getMaxPolyphony() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#getLatency() + */ + public long getLatency() + { + // DSSI and LADSPA provide no way to determine the latency. + // Let's just return 0 for now. + return 0; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#getChannels() + */ + public MidiChannel[] getChannels() + { + return channels; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#getVoiceStatus() + */ + public VoiceStatus[] getVoiceStatus() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#isSoundbankSupported(javax.sound.midi.Soundbank) + */ + public boolean isSoundbankSupported(Soundbank soundbank) + { + // TODO Auto-generated method stub + return false; + } + + /* @see javax.sound.midi.Synthesizer#loadInstrument(javax.sound.midi.Instrument) + */ + public boolean loadInstrument(Instrument instrument) + { + // FIXME: perhaps this isn't quite right. It can probably + // be in any soundbank. + if (instrument.getSoundbank() != defaultSoundbank) + throw new IllegalArgumentException ("Synthesizer doesn't support this instrument's soundbank"); + + Patch patch = instrument.getPatch(); + selectProgram_(sohandle, patch.getBank(), patch.getProgram()); + return true; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#unloadInstrument(javax.sound.midi.Instrument) + */ + public void unloadInstrument(Instrument instrument) + { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#remapInstrument(javax.sound.midi.Instrument, javax.sound.midi.Instrument) + */ + public boolean remapInstrument(Instrument from, Instrument to) + { + // TODO Auto-generated method stub + return false; + } + + /* @see javax.sound.midi.Synthesizer#getDefaultSoundbank() + */ + public Soundbank getDefaultSoundbank() + { + return defaultSoundbank; + } + + /* @see javax.sound.midi.Synthesizer#getAvailableInstruments() + */ + public Instrument[] getAvailableInstruments() + { + List instruments = new ArrayList(); + Iterator itr = soundbanks.iterator(); + while (itr.hasNext()) + { + Soundbank sb = (Soundbank) itr.next(); + Instrument ins[] = sb.getInstruments(); + for (int i = 0; i < ins.length; i++) + instruments.add(ins[i]); + } + return (Instrument[]) + instruments.toArray(new Instrument[instruments.size()]); + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#getLoadedInstruments() + */ + public Instrument[] getLoadedInstruments() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#loadAllInstruments(javax.sound.midi.Soundbank) + */ + public boolean loadAllInstruments(Soundbank soundbank) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#unloadAllInstruments(javax.sound.midi.Soundbank) + */ + public void unloadAllInstruments(Soundbank soundbank) + { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#loadInstruments(javax.sound.midi.Soundbank, javax.sound.midi.Patch[]) + */ + public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.Synthesizer#unloadInstruments(javax.sound.midi.Soundbank, javax.sound.midi.Patch[]) + */ + public void unloadInstruments(Soundbank soundbank, Patch[] patchList) + { + // TODO Auto-generated method stub + + } + + /* @see javax.sound.midi.MidiDevice#getDeviceInfo() + */ + public Info getDeviceInfo() + { + return info; + } + + /* @see javax.sound.midi.MidiDevice#open() + */ + public void open() throws MidiUnavailableException + { + open_(sohandle); + } + + /* @see javax.sound.midi.MidiDevice#close() + */ + public void close() + { + close_(sohandle); + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#isOpen() + */ + public boolean isOpen() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.sound.midi.MidiDevice#getMicrosecondPosition() + */ + public long getMicrosecondPosition() + { + // TODO Auto-generated method stub + return 0; + } + + /* @see javax.sound.midi.MidiDevice#getMaxReceivers() + */ + public int getMaxReceivers() + { + return 1; + } + + /* @see javax.sound.midi.MidiDevice#getMaxTransmitters() + */ + public int getMaxTransmitters() + { + return 0; + } + + /* @see javax.sound.midi.MidiDevice#getReceiver() + */ + public Receiver getReceiver() throws MidiUnavailableException + { + return new DSSIReceiver(); + } + + /* @see javax.sound.midi.MidiDevice#getTransmitter() + */ + public Transmitter getTransmitter() throws MidiUnavailableException + { + return null; + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/file/ExtendedMidiFileFormat.java b/libjava/classpath/gnu/javax/sound/midi/file/ExtendedMidiFileFormat.java new file mode 100644 index 000000000..4b065f3dc --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/file/ExtendedMidiFileFormat.java @@ -0,0 +1,77 @@ +/* ExtendedMidiFileFormat.java -- extended with track count info. + Copyright (C) 2006 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 gnu.javax.sound.midi.file; + +/** + * ExtendedMidiFileFormat is a package private class that simply + * adds the number of MIDI tracks for the MidiFileFormat class. + * + * @author Anthony Green (green@redhat.com) + */ +class ExtendedMidiFileFormat + extends javax.sound.midi.MidiFileFormat +{ + private int ntracks; + + /** + * Get the number of tracks for this MIDI file. + * + * @return the number of tracks for this MIDI file + */ + public int getNumberTracks() + { + return ntracks; + } + + /** + * Create an ExtendedMidiFileFormat 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 + * @param ntracks the number of tracks + */ + public ExtendedMidiFileFormat(int type, float divisionType, int resolution, + int bytes, long microseconds, int ntracks) + { + super(type, divisionType, resolution, bytes, microseconds); + this.ntracks = ntracks; + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/file/MidiDataInputStream.java b/libjava/classpath/gnu/javax/sound/midi/file/MidiDataInputStream.java new file mode 100644 index 000000000..d91970b9f --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/file/MidiDataInputStream.java @@ -0,0 +1,83 @@ +/* MidiDataInputStream.java -- adds variable length MIDI ints + Copyright (C) 2006 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 gnu.javax.sound.midi.file; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * MidiDataInputStream is simply a DataInputStream with the addition + * of special variable length int reading as defined by the MIDI spec. + * + * @author Anthony Green (green@redhat.com) + */ +public class MidiDataInputStream + extends DataInputStream +{ + /** + * Create a MidiDataInputStream. + */ + public MidiDataInputStream(InputStream is) + { + super(is); + } + + /** + * Read an int encoded in the MIDI-style variable length + * encoding format. + * + * @return an int + */ + public int readVariableLengthInt() + throws IOException + { + int c, value = readByte(); + + if ((value & 0x80) != 0) + { + value &= 0x7F; + do + { + value = (value << 7) + ((c = readByte()) & 0x7F); + } while ((c & 0x80) != 0); + } + + return value; + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/file/MidiDataOutputStream.java b/libjava/classpath/gnu/javax/sound/midi/file/MidiDataOutputStream.java new file mode 100644 index 000000000..79c66e8a2 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/file/MidiDataOutputStream.java @@ -0,0 +1,114 @@ +/* MidiDataOutputStream.java -- adds variable length MIDI ints + Copyright (C) 2006 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 gnu.javax.sound.midi.file; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * MidiDataOutputStream is simply a DataOutputStream with the addition + * of special variable length int writing as defined by the MIDI spec. + * + * @author Anthony Green (green@redhat.com) + */ +public class MidiDataOutputStream + extends DataOutputStream +{ + /** + * Create a MidiDataOutputStream. + */ + public MidiDataOutputStream(OutputStream os) + { + super(os); + } + + /** + * Return the length of a variable length encoded int without + * writing it out. + * + * @return the length of the encoding + */ + public int variableLengthIntLength (int value) + { + int length = 0; + int buffer = value & 0x7F; + + while ((value >>= 7) != 0) + { + buffer <<= 8; + buffer |= ((value & 0x7F) | 0x80); + } + + while (true) + { + length++; + if ((buffer & 0x80) != 0) + buffer >>>= 8; + else + break; + } + + return length; + } + + /** + * Write an int encoded in the MIDI-style variable length + * encoding format. + */ + public synchronized void writeVariableLengthInt (int value) + throws IOException + { + int buffer = value & 0x7F; + + while ((value >>= 7) != 0) + { + buffer <<= 8; + buffer |= ((value & 0x7F) | 0x80); + } + + while (true) + { + writeByte(buffer & 0xff); + if ((buffer & 0x80) != 0) + buffer >>>= 8; + else + break; + } + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/file/MidiFileReader.java b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileReader.java new file mode 100644 index 000000000..fb2a472fa --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileReader.java @@ -0,0 +1,378 @@ +/* MidiFileReader.java -- Read MIDI files. + Copyright (C) 2006 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 gnu.javax.sound.midi.file; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiFileFormat; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Sequence; +import javax.sound.midi.ShortMessage; +import javax.sound.midi.SysexMessage; +import javax.sound.midi.Track; + +/** + * A MIDI file reader. + * + * This code reads MIDI file types 0 and 1. + * + * There are many decent documents on the web describing the MIDI file + * format. I didn't bother looking for the official document. If it + * exists, I'm not even sure if it is freely available. We should + * update this comment if we find out anything helpful here. + * + * @author Anthony Green (green@redhat.com) + * + */ +public class MidiFileReader extends javax.sound.midi.spi.MidiFileReader +{ + /* Get the MidiFileFormat for the given input stream. + * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.io.InputStream) + */ + public MidiFileFormat getMidiFileFormat(InputStream in) + throws InvalidMidiDataException, IOException + { + DataInputStream din; + if (in instanceof DataInputStream) + din = (DataInputStream) in; + else + din = new DataInputStream(in); + + int type, ntracks, division, resolution, bytes; + float divisionType; + + if (din.readInt() != 0x4d546864) // "MThd" + throw new InvalidMidiDataException("Invalid MIDI chunk header."); + + bytes = din.readInt(); + if (bytes < 6) + throw new + InvalidMidiDataException("Invalid MIDI chunk header length: " + bytes); + + type = din.readShort(); + if (type < 0 || type > 2) + throw new + InvalidMidiDataException("Invalid MIDI file type value: " + type); + + ntracks = din.readShort(); + if (ntracks <= 0) + throw new + InvalidMidiDataException("Invalid number of MIDI tracks: " + ntracks); + + division = din.readShort(); + if ((division & 0x8000) != 0) + { + division = -((division >>> 8) & 0xFF); + switch (division) + { + case 24: + divisionType = Sequence.SMPTE_24; + break; + + case 25: + divisionType = Sequence.SMPTE_25; + break; + + case 29: + divisionType = Sequence.SMPTE_30DROP; + break; + + case 30: + divisionType = Sequence.SMPTE_30; + break; + + default: + throw new + InvalidMidiDataException("Invalid MIDI frame division type: " + + division); + } + resolution = division & 0xff; + } + else + { + divisionType = Sequence.PPQ; + resolution = division & 0x7fff; + } + + // If we haven't read every byte in the header now, just skip the rest. + din.skip(bytes - 6); + + return new ExtendedMidiFileFormat(type, divisionType, resolution, + MidiFileFormat.UNKNOWN_LENGTH, + MidiFileFormat.UNKNOWN_LENGTH, ntracks); + } + + /* Get the MidiFileFormat from the given URL. + * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.net.URL) + */ + public MidiFileFormat getMidiFileFormat(URL url) + throws InvalidMidiDataException, IOException + { + InputStream is = url.openStream(); + try + { + return getMidiFileFormat(is); + } + finally + { + is.close(); + } + } + + /* Get the MidiFileFormat from the given file. + * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.io.File) + */ + public MidiFileFormat getMidiFileFormat(File file) + throws InvalidMidiDataException, IOException + { + InputStream is = new FileInputStream(file); + try + { + return getMidiFileFormat(is); + } + finally + { + is.close(); + } + } + + /* Get the MIDI Sequence found in this input stream. + * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.io.InputStream) + */ + public Sequence getSequence(InputStream is) throws InvalidMidiDataException, + IOException + { + MidiDataInputStream din = new MidiDataInputStream(is); + ExtendedMidiFileFormat mff = (ExtendedMidiFileFormat) getMidiFileFormat(din); + + Sequence seq = new Sequence(mff.getDivisionType(), mff.getResolution()); + + int ntracks = mff.getNumberTracks(); + + while (ntracks-- > 0) + { + Track track = seq.createTrack(); + int Mtrk = din.readInt(); + if (Mtrk != 0x4d54726b) + throw new InvalidMidiDataException("Invalid MIDI track header."); + int length = din.readInt(); + + int runningStatus = -1; + int click = 0; + + // Set this to true when we've hit an End of Track meta event. + boolean done = false; + + // Read all events. + while (! done) + { + MidiMessage mm; + int dtime = din.readVariableLengthInt(); + click += dtime; + + int sbyte = din.readUnsignedByte(); + + if (sbyte < 0xf0) + { + ShortMessage sm; + switch (sbyte & 0xf0) + { + case ShortMessage.NOTE_OFF: + case ShortMessage.NOTE_ON: + case ShortMessage.POLY_PRESSURE: + case ShortMessage.CONTROL_CHANGE: + case ShortMessage.PITCH_BEND: + case ShortMessage.SONG_POSITION_POINTER: + sm = new ShortMessage(); + sm.setMessage(sbyte, din.readByte(), din.readByte()); + runningStatus = sbyte; + break; + + case ShortMessage.PROGRAM_CHANGE: + case ShortMessage.CHANNEL_PRESSURE: + case ShortMessage.SONG_SELECT: + case 0xF5: // FIXME: unofficial bus select. Not in spec?? + sm = new ShortMessage(); + sm.setMessage(sbyte, din.readByte(), 0); + runningStatus = sbyte; + break; + + case ShortMessage.TUNE_REQUEST: + case ShortMessage.END_OF_EXCLUSIVE: + case ShortMessage.TIMING_CLOCK: + case ShortMessage.START: + case ShortMessage.CONTINUE: + case ShortMessage.STOP: + case ShortMessage.ACTIVE_SENSING: + case ShortMessage.SYSTEM_RESET: + sm = new ShortMessage(); + sm.setMessage(sbyte, 0, 0); + runningStatus = sbyte; + break; + + default: + if (runningStatus != - 1) + { + switch (runningStatus & 0xf0) + { + case ShortMessage.NOTE_OFF: + case ShortMessage.NOTE_ON: + case ShortMessage.POLY_PRESSURE: + case ShortMessage.CONTROL_CHANGE: + case ShortMessage.PITCH_BEND: + case ShortMessage.SONG_POSITION_POINTER: + sm = new ShortMessage(); + sm.setMessage(runningStatus, sbyte, din.readByte()); + break; + + case ShortMessage.PROGRAM_CHANGE: + case ShortMessage.CHANNEL_PRESSURE: + case ShortMessage.SONG_SELECT: + case 0xF5: // FIXME: unofficial bus select. Not in + // spec?? + sm = new ShortMessage(); + sm.setMessage(runningStatus, sbyte, 0); + continue; + + case ShortMessage.TUNE_REQUEST: + case ShortMessage.END_OF_EXCLUSIVE: + case ShortMessage.TIMING_CLOCK: + case ShortMessage.START: + case ShortMessage.CONTINUE: + case ShortMessage.STOP: + case ShortMessage.ACTIVE_SENSING: + case ShortMessage.SYSTEM_RESET: + sm = new ShortMessage(); + sm.setMessage(runningStatus, 0, 0); + continue; + + default: + throw new + InvalidMidiDataException("Invalid Short MIDI Event: " + + sbyte); + } + } + else + throw new + InvalidMidiDataException("Invalid Short MIDI Event: " + + sbyte); + } + mm = sm; + } + else if (sbyte == 0xf0 || sbyte == 0xf7) + { + // System Exclusive event + int slen = din.readVariableLengthInt(); + byte sysex[] = new byte[slen]; + din.readFully(sysex); + SysexMessage sm = new SysexMessage(); + sm.setMessage(sbyte, sysex, slen); + mm = sm; + runningStatus = - 1; + } + else if (sbyte == 0xff) + { + // Meta Message + byte mtype = din.readByte(); + int mlen = din.readVariableLengthInt(); + byte meta[] = new byte[mlen]; + din.readFully(meta); + MetaMessage metam = new MetaMessage(); + metam.setMessage(mtype, meta, mlen); + mm = metam; + + if (mtype == 0x2f) // End of Track + done = true; + + runningStatus = - 1; + } + else + { + throw new InvalidMidiDataException("Invalid status byte: " + + sbyte); + } + + track.add(new MidiEvent(mm, click)); + } + } + + return seq; + } + + /* Get the MIDI Sequence found at the given URL. + * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.net.URL) + */ + public Sequence getSequence(URL url) throws InvalidMidiDataException, + IOException + { + InputStream is = url.openStream(); + try + { + return getSequence(is); + } + finally + { + is.close(); + } + } + + /* Get the MIDI Sequence found in the given file. + * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.io.File) + */ + public Sequence getSequence(File file) throws InvalidMidiDataException, + IOException + { + InputStream is = new FileInputStream(file); + try + { + return getSequence(is); + } + finally + { + is.close(); + } + } +} diff --git a/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java new file mode 100644 index 000000000..5170fc1e7 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java @@ -0,0 +1,197 @@ +/* MidiFileWriter.java -- Write MIDI files. + Copyright (C) 2006 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 gnu.javax.sound.midi.file; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + +/** + * A MIDI file writer. + * + * This code writes MIDI file types 0 and 1. + * + * There are many decent documents on the web describing the MIDI file + * format. I didn't bother looking for the official document. If it + * exists, I'm not even sure if it is freely available. We should + * update this comment if we find out anything helpful here. + * + * @author Anthony Green (green@redhat.com) + * + */ +public class MidiFileWriter + extends javax.sound.midi.spi.MidiFileWriter +{ + /* Return an array indicating which midi file types are supported. + * @see javax.sound.midi.spi.MidiFileWriter#getMidiFileTypes() + */ + public int[] getMidiFileTypes() + { + return new int[]{0, 1}; + } + + /* Return an array indicating which midi file types are supported + * for a given Sequence. + * @see javax.sound.midi.spi.MidiFileWriter#getMidiFileTypes(javax.sound.midi.Sequence) + */ + public int[] getMidiFileTypes(Sequence sequence) + { + if (sequence.getTracks().length == 1) + return new int[]{0}; + else + return new int[]{1}; + } + + /* Write a sequence to an output stream in standard midi format. + * @see javax.sound.midi.spi.MidiFileWriter#write(javax.sound.midi.Sequence, int, java.io.OutputStream) + */ + public int write(Sequence in, int fileType, OutputStream out) + throws IOException + { + MidiDataOutputStream dos = new MidiDataOutputStream (out); + Track[] tracks = in.getTracks(); + dos.writeInt(0x4d546864); // MThd + dos.writeInt(6); + dos.writeShort(fileType); + dos.writeShort(tracks.length); + float divisionType = in.getDivisionType(); + int resolution = in.getResolution(); + // FIXME: division computation is incomplete. + int division = 0; + if (divisionType == Sequence.PPQ) + division = resolution & 0x7fff; + dos.writeShort(division); + int length = 14; + for (int i = 0; i < tracks.length; i++) + length += writeTrack(tracks[i], dos); + return length; + } + + /** + * Compute the length of a track as it will be written to the + * output stream. + * + * @param track the track to measure + * @param dos a MidiDataOutputStream used for helper method + * @return the length of the track + */ + private int computeTrackLength(Track track, MidiDataOutputStream dos) + { + int count = 0, length = 0, i = 0, eventCount = track.size(); + long ptick = 0; + while (i < eventCount) + { + MidiEvent me = track.get(i); + long tick = me.getTick(); + length += dos.variableLengthIntLength((int) (tick - ptick)); + ptick = tick; + length += me.getMessage().getLength(); + i++; + } + return length; + } + + /** + * Write a track to an output stream. + * + * @param track the track to write + * @param dos a MidiDataOutputStream to write to + * @return the number of bytes written + */ + private int writeTrack(Track track, MidiDataOutputStream dos) + throws IOException + { + int i = 0, elength = track.size(), trackLength; + MidiEvent pme = null; + dos.writeInt(0x4d54726b); // "MTrk" + trackLength = computeTrackLength(track, dos); + dos.writeInt(trackLength); + while (i < elength) + { + MidiEvent me = track.get(i); + int dtime = 0; + if (pme != null) + dtime = (int) (me.getTick() - pme.getTick()); + dos.writeVariableLengthInt(dtime); + // FIXME: use running status byte + byte msg[] = me.getMessage().getMessage(); + dos.write(msg); + pme = me; + i++; + } + + // We're done if the last event was an End of Track meta message. + if (pme != null && (pme.getMessage() instanceof MetaMessage)) + { + MetaMessage mm = (MetaMessage) pme.getMessage(); + if (mm.getType() == 0x2f) // End of Track message + return trackLength + 8; + } + + // Write End of Track meta message + dos.writeVariableLengthInt(0); // Delta time of 0 + dos.writeByte(0xff); // Meta Message + dos.writeByte(0x2f); // End of Track message + dos.writeVariableLengthInt(0); // Length of 0 + + return trackLength + 8 + 4; + } + + /* Write a Sequence to a file. + * @see javax.sound.midi.spi.MidiFileWriter#write(javax.sound.midi.Sequence, int, java.io.File) + */ + public int write(Sequence in, int fileType, File out) throws IOException + { + OutputStream os = new FileOutputStream(out); + try + { + return write(in, fileType, os); + } + finally + { + os.close(); + } + } + +} |