diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/javax/sound | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/javax/sound')
25 files changed, 5245 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java b/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java new file mode 100644 index 000000000..1daea2db5 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java @@ -0,0 +1,112 @@ +/* AudioSecurityManager.java -- Manages Security requests for Sound classes. + + Copyright (C) 2007 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; + +import javax.sound.sampled.AudioPermission; + +/** + * This class handles security requests for classes in the Sound API. + * + * A class that needs to check against a particular permission type may use this + * class to query the <code>SecurityManager</code>. + * + * For example, to check for a read permission, a class can simply pass the + * <code>Permission.READ</code> constant to + * {@link #checkPermissions(gnu.javax.sound.AudioSecurityManager.Permission))}, + * like the following code demonstrates: + * + * <pre> + * AudioSecurityManager.checkPermissions(Permission.PLAY); + * </pre> + * + * If there is need to query for all the defined permissions type, the constant + * <code>Permission.ALL</code> can be used. In alternative, the + * {@link #checkPermissions()} is presented as a shorthand. + * + * @author Mario Torre <neugens@limasoftware.net> + */ +public class AudioSecurityManager +{ + /** + * Defines a common set of permission allowed by the specification. + */ + public static enum Permission + { + PLAY, RECORD, ALL + } + + /** + * Shorthand to <code>checkPermissions(Permission.ALL)</code>. + */ + public static final void checkPermissions() + { + checkPermissions(Permission.ALL); + } + + /** + * Query the <code>SecurityManager</code> agains the given + * <code>Permission</code>. + * + * @param permission + */ + public static final void checkPermissions(Permission permission) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + String perm = null; + switch (permission) + { + case PLAY: + perm = "play"; + break; + + case RECORD: + perm = "record"; + break; + + case ALL: default: + perm = "*"; + break; + } + + sm.checkPermission(new AudioPermission(perm)); + } + } +} 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(); + } + } + +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java b/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java new file mode 100644 index 000000000..fe0df6eb1 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java @@ -0,0 +1,210 @@ +/* AUReader.java -- Read AU 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.sampled.AU; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; +import java.io.File; +import java.io.IOException; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.FileInputStream; +import java.net.URL; +import java.nio.ByteBuffer; + +public class AUReader extends AudioFileReader +{ + private static class AUHeader + { + // Magic number identifying the file. '.snd' + private static final int MAGIC = 0x2e736e64; + + public static final int SIZE = 24; // size of the header + + // Encoding types + public static final int ULAW = 1; // 8-bit u-law + public static final int PCM8 = 2; // 8-bit PCM + public static final int PCM16 = 3; // 16-bit PCM + public static final int PCM24 = 4; // 24-bit PCM + public static final int PCM32 = 5; // 32-bit PCM + public static final int IEEE32 = 6; // 32-bit IEEE f.p. + public static final int IEEE64 = 7; // 64-bit IEEE f.p. + public static final int G721 = 23; + public static final int G722 = 24; + public static final int G723 = 25; + public static final int G723_5BIT = 26; + public static final int ALAW = 27; // 8-bit a-law + + // Header data. + public int headerSize; + public int fileSize; // this value may not be set. + public int encoding; + public int sampleRate; + public int channels; + public int sampleSizeInBits; + + public AUHeader(InputStream stream) + throws IOException, UnsupportedAudioFileException + { + byte[] hdr = new byte[24]; + stream.read( hdr ); + ByteBuffer buf = ByteBuffer.wrap(hdr); + + if( buf.getInt() != MAGIC ) + throw new UnsupportedAudioFileException("Not an AU format audio file."); + headerSize = buf.getInt(); + fileSize = buf.getInt(); + encoding = buf.getInt(); + sampleRate = buf.getInt(); + channels = buf.getInt(); + + switch(encoding) + { + case ULAW: + case PCM8: + case ALAW: + sampleSizeInBits = 8; + break; + case PCM16: + sampleSizeInBits = 16; + break; + case PCM24: + sampleSizeInBits = 24; + break; + case PCM32: + sampleSizeInBits = 32; + break; + default: // other types exist but are not supported. Yet. + throw new UnsupportedAudioFileException("Unsupported encoding."); + } + } + + public AudioFormat getAudioFormat() + { + AudioFormat.Encoding encType = AudioFormat.Encoding.PCM_SIGNED; + if(encoding == 1) + encType = AudioFormat.Encoding.ULAW; + if(encoding == 27) + encType = AudioFormat.Encoding.ALAW; + + return new AudioFormat(encType, + (float)sampleRate, + sampleSizeInBits, + channels, + (sampleSizeInBits >> 3) * channels, + (float)sampleRate, + true); + } + + public AudioFileFormat getAudioFileFormat() + { + return new AudioFileFormat(new AUFormatType(), + getAudioFormat(), + AudioSystem.NOT_SPECIFIED); + } + } + + public static class AUFormatType extends AudioFileFormat.Type + { + public AUFormatType() + { + super("AU", ".au"); + } + } + + public AudioFileFormat getAudioFileFormat(File file) + throws IOException, UnsupportedAudioFileException + { + return getAudioFileFormat(new FileInputStream(file)); + } + + public AudioFileFormat getAudioFileFormat(InputStream stream) + throws IOException, UnsupportedAudioFileException + { + if(!stream.markSupported()) + throw new IOException("Stream must support marking."); + + stream.mark(25); + AUHeader header = new AUHeader(stream); + stream.reset(); + + return header.getAudioFileFormat(); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws IOException, UnsupportedAudioFileException + { + return getAudioFileFormat(new BufferedInputStream(url.openStream())); + } + + public AudioInputStream getAudioInputStream(File file) + throws IOException, UnsupportedAudioFileException + { + InputStream stream = new FileInputStream(file); + long length = file.length(); + + AUHeader header = new AUHeader( stream ); + if( header.headerSize > AUHeader.SIZE ) + stream.skip(header.headerSize - AUHeader.SIZE); + + length -= header.headerSize; + + return new AudioInputStream(stream, header.getAudioFormat(), length); + } + + public AudioInputStream getAudioInputStream(InputStream stream) + throws IOException, UnsupportedAudioFileException + { + AUHeader header = new AUHeader( stream ); + if( header.headerSize > AUHeader.SIZE ) + stream.skip(header.headerSize - AUHeader.SIZE); + + return new AudioInputStream(stream, header.getAudioFormat(), + AudioSystem.NOT_SPECIFIED); + } + + public AudioInputStream getAudioInputStream(URL url) + throws IOException, UnsupportedAudioFileException + { + return getAudioInputStream(new BufferedInputStream(url.openStream())); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/WAV/WAVReader.java b/libjava/classpath/gnu/javax/sound/sampled/WAV/WAVReader.java new file mode 100644 index 000000000..5cd6efe5e --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/WAV/WAVReader.java @@ -0,0 +1,236 @@ +/* WAVReader.java -- Read WAV 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.sampled.WAV; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * A WAV file reader. + * + * This code reads WAV files. + * + * There are many decent documents on the web describing the WAV 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. I used + * http://www.sonicspot.com/guide/wavefiles.html + * + * @author Anthony Green (green@redhat.com) + * + */ +public class WAVReader extends AudioFileReader +{ + private static long readUnsignedIntLE (DataInputStream is) + throws IOException + { + byte[] buf = new byte[4]; + is.readFully(buf); + return (buf[0] & 0xFF + | ((buf[1] & 0xFF) << 8) + | ((buf[2] & 0xFF) << 16) + | ((buf[3] & 0xFF) << 24)); + } + + private static short readUnsignedShortLE (DataInputStream is) + throws IOException + { + byte[] buf = new byte[2]; + is.readFully(buf); + return (short) (buf[0] & 0xFF + | ((buf[1] & 0xFF) << 8)); + } + + /* Get an AudioFileFormat from the given File. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.File) + */ + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException + { + InputStream is = new FileInputStream(file); + try + { + return getAudioFileFormat(is); + } + finally + { + is.close(); + } + } + + /* Get an AudioFileFormat from the given InputStream. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.InputStream) + */ + public AudioFileFormat getAudioFileFormat(InputStream in) + throws UnsupportedAudioFileException, IOException + { + DataInputStream din; + + if (in instanceof DataInputStream) + din = (DataInputStream) in; + else + din = new DataInputStream(in); + + if (din.readInt() != 0x52494646) // "RIFF" + throw new UnsupportedAudioFileException("Invalid WAV chunk header."); + + // Read the length of this RIFF thing. + readUnsignedIntLE(din); + + if (din.readInt() != 0x57415645) // "WAVE" + throw new UnsupportedAudioFileException("Invalid WAV chunk header."); + + boolean foundFmt = false; + boolean foundData = false; + + short compressionCode = 0, numberChannels = 0, blockAlign = 0, bitsPerSample = 0; + long sampleRate = 0, bytesPerSecond = 0; + long chunkLength = 0; + + while (! foundData) + { + int chunkId = din.readInt(); + chunkLength = readUnsignedIntLE(din); + switch (chunkId) + { + case 0x666D7420: // "fmt " + foundFmt = true; + compressionCode = readUnsignedShortLE(din); + numberChannels = readUnsignedShortLE(din); + sampleRate = readUnsignedIntLE(din); + bytesPerSecond = readUnsignedIntLE(din); + blockAlign = readUnsignedShortLE(din); + bitsPerSample = readUnsignedShortLE(din); + din.skip(chunkLength - 16); + break; + case 0x66616374: // "fact" + // FIXME: hold compression format dependent data. + din.skip(chunkLength); + break; + case 0x64617461: // "data" + if (! foundFmt) + throw new UnsupportedAudioFileException("This implementation requires WAV fmt chunks precede data chunks."); + foundData = true; + break; + default: + // Unrecognized chunk. Skip it. + din.skip(chunkLength); + } + } + + AudioFormat.Encoding encoding; + + switch (compressionCode) + { + case 1: // PCM/uncompressed + if (bitsPerSample <= 8) + encoding = AudioFormat.Encoding.PCM_UNSIGNED; + else + encoding = AudioFormat.Encoding.PCM_SIGNED; + break; + + default: + throw new UnsupportedAudioFileException("Unrecognized WAV compression code: 0x" + + Integer.toHexString(compressionCode)); + } + + return new AudioFileFormat (AudioFileFormat.Type.WAVE, + new AudioFormat(encoding, + (float) sampleRate, + bitsPerSample, + numberChannels, + ((bitsPerSample + 7) / 8) * numberChannels, + (float) bytesPerSecond, false), + (int) chunkLength); + } + + /* Get an AudioFileFormat from the given URL. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.net.URL) + */ + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException + { + InputStream is = url.openStream(); + try + { + return getAudioFileFormat(is); + } + finally + { + is.close(); + } + } + + /* Get an AudioInputStream from the given File. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.File) + */ + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException + { + return getAudioInputStream(new FileInputStream(file)); + } + + /* Get an AudioInputStream from the given InputStream. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.InputStream) + */ + public AudioInputStream getAudioInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException + { + AudioFileFormat aff = getAudioFileFormat(stream); + return new AudioInputStream(stream, aff.getFormat(), (long) aff.getFrameLength()); + } + + /* Get an AudioInputStream from the given URL. + * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.net.URL) + */ + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException + { + return getAudioInputStream(url.openStream()); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java new file mode 100644 index 000000000..1910ea655 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java @@ -0,0 +1,248 @@ +/* GStreamerMixer.java -- Mixer implementation. + Copyright (C) 2007 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.sampled.gstreamer; + +import gnu.javax.sound.sampled.gstreamer.lines.GstSourceDataLine; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.Control.Type; + +/** + * @author Mario Torre <neugens@limasoftware.net> + */ +public class GStreamerMixer + implements Mixer +{ + public static class GstInfo extends Info + { + /* Mixer Properties */ + + /** Name */ + private static final String name = "Classpath GStreamer Sound Audio Engine"; + + /** Vendor */ + private static final String vendor = "GNU Classpath"; + + /** Description */ + private static final String desc = "GStreamer-based software mixer"; + + /** Version */ + private static final String vers = "0.0.1"; + + protected GstInfo() + { + super(name, vendor, desc, vers); + } + } + + public static final String GST_BACKEND = GstInfo.name; + public static final String GST_DECODER = "decoder"; + public static final String GST_TYPE_NAME = "type"; + public static final String GST_FILE_EXTENSION = "ext"; + + /** Mixer Info */ + private static final Mixer.Info INFO = new GStreamerMixer.GstInfo(); + + public Line getLine(Line.Info info) + throws LineUnavailableException + { + // get all the lines formats supported by this mixer and + // and see if there is one matching the given line + // if the format comes from the gstreamer backend + // gstreamer will be able to deal with it + Class clazz = info.getLineClass(); + DataLine.Info _info = (DataLine.Info) info; + + if (clazz == SourceDataLine.class) + { + for (AudioFormat format : _info.getFormats()) + { + // see if we are a gstreamer child :) + if (format.properties().containsKey(GST_BACKEND)); + { + // we got it + return new GstSourceDataLine(format); + } + } + } + + // TODO: we also support basic PCM + + throw new LineUnavailableException("Cannot open a line"); + } + + public int getMaxLines(Line.Info info) + { + // TODO + return 1; + } + + public Info getMixerInfo() + { + return INFO; + } + + public javax.sound.sampled.Line.Info[] getSourceLineInfo() + { + // TODO Auto-generated method stub + return null; + } + + public Line.Info[] getSourceLineInfo(Line.Info info) + { + // TODO Auto-generated method stub + return null; + } + + public Line[] getSourceLines() + { + // TODO Auto-generated method stub + return null; + } + + public javax.sound.sampled.Line.Info[] getTargetLineInfo() + { + // TODO Auto-generated method stub + return null; + } + + public Line.Info[] getTargetLineInfo(Line.Info info) + { + // TODO Auto-generated method stub + return null; + } + + public Line[] getTargetLines() + { + // TODO Auto-generated method stub + return null; + } + + public boolean isLineSupported(Line.Info info) + { + // We support any kind of mixer that comes + // from our gstreamer backend. + // In addition, we support PCM based audio streams for + // direct playback. + if (info instanceof DataLine.Info) + { + DataLine.Info _dinfo = (DataLine.Info) info; + _dinfo.getFormats(); + } + + return true; + } + + public boolean isSynchronizationSupported(Line[] lines, boolean sync) + { + // TODO Auto-generated method stub + return false; + } + + public void synchronize(Line[] lines, boolean sync) + { + // TODO Auto-generated method stub + + } + + public void unsynchronize(Line[] lines) + { + // TODO Auto-generated method stub + + } + + public void addLineListener(LineListener listener) + { + // TODO Auto-generated method stub + + } + + public void close() + { + // TODO Auto-generated method stub + + } + + public Control getControl(Type what) + { + // TODO Auto-generated method stub + return null; + } + + public Control[] getControls() + { + // TODO Auto-generated method stub + return null; + } + + public javax.sound.sampled.Line.Info getLineInfo() + { + // TODO Auto-generated method stub + return null; + } + + public boolean isControlSupported(Type what) + { + // TODO Auto-generated method stub + return false; + } + + public boolean isOpen() + { + // TODO Auto-generated method stub + return false; + } + + public void open() throws LineUnavailableException + { + // TODO Auto-generated method stub + + } + + public void removeLineListener(LineListener listener) + { + // TODO Auto-generated method stub + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixerProvider.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixerProvider.java new file mode 100644 index 000000000..6a0d7faa7 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixerProvider.java @@ -0,0 +1,71 @@ +/*GStreamerMixerProvider -- GNU Classpath GStreamer Mixer provider. + Copyright (C) 2007 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.sampled.gstreamer; + +import javax.sound.sampled.Mixer; +import javax.sound.sampled.Mixer.Info; +import javax.sound.sampled.spi.MixerProvider; + +/** + * Concrete provider class for GStreamerMixer. + * + * @author Mario Torre + */ +public class GStreamerMixerProvider + extends MixerProvider +{ + private static final GStreamerMixer mixer = new GStreamerMixer(); + + @Override + public Mixer getMixer(Info info) + { + if (info.equals(mixer.getMixerInfo())) + return mixer; + + throw new + IllegalArgumentException("This provider cannot handle a mixer or type: " + + info.getName()); + } + + @Override + public Info[] getMixerInfo() + { + Info[] info = { mixer.getMixerInfo() }; + return info; + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java new file mode 100644 index 000000000..26fb12b09 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java @@ -0,0 +1,185 @@ +/*GstAudioFileReader -- GNU Classpath GStreamer AudioFileReader. + Copyright (C) 2007 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.sampled.gstreamer.io; + +import gnu.java.lang.CPStringBuilder; + +import gnu.javax.sound.sampled.gstreamer.GStreamerMixer; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * An implementation of a general AudioFileReader. Uses GStreamer to + * parse and retrieve informations about the file passed as input. + * + * @author Mario Torre <neugens@limasoftware.net> + */ +public class GstAudioFileReader + extends AudioFileReader +{ + @Override + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException + { + CPStringBuilder name = new CPStringBuilder(file.getName()); + String _name = name.substring(name.lastIndexOf(".") + 1); + + return getAudioFileFormat( + new BufferedInputStream(new FileInputStream(file)), _name); + } + + @Override + public AudioFileFormat getAudioFileFormat(InputStream is) + throws UnsupportedAudioFileException, IOException + { + return getAudioFileFormat(is, null); + } + + private AudioFileFormat getAudioFileFormat(InputStream is, String extension) + throws UnsupportedAudioFileException + { + AudioFormat format = null; + try + { + format = GstAudioFileReaderNativePeer.getAudioFormat(is); + } + catch (Exception e) + { + UnsupportedAudioFileException ex = + new UnsupportedAudioFileException("Unsupported encoding."); + + ex.initCause(ex.getCause()); + throw ex; + } + + if (format == null) + throw new UnsupportedAudioFileException("Unsupported encoding."); + + String name = format.getProperty(GStreamerMixer.GST_DECODER).toString(); + + if (extension == null) + { + extension = + format.getProperty(GStreamerMixer.GST_FILE_EXTENSION).toString(); + } + + AudioFileFormat.Type type = + new AudioFileFormat.Type(name, extension); + + // TODO: we should calculate this in some way. We don't need it, but + // application may want to use this data. + return new AudioFileFormat(type, format, AudioSystem.NOT_SPECIFIED); + } + + @Override + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException + { + return getAudioFileFormat(new BufferedInputStream(url.openStream())); + } + + @Override + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException + { + InputStream stream = new FileInputStream(file); + long length = file.length(); + + AudioFormat format = null; + + try + { + format = GstAudioFileReaderNativePeer.getAudioFormat(file); + } + catch (Exception e) + { + UnsupportedAudioFileException ex = + new UnsupportedAudioFileException("Unsupported encoding."); + + ex.initCause(ex.getCause()); + throw ex; + } + + // get the header size + if (format == null) + throw new UnsupportedAudioFileException("Unsupported encoding."); + + return new AudioInputStream(stream, format, length); + } + + @Override + public AudioInputStream getAudioInputStream(InputStream is) + throws UnsupportedAudioFileException, IOException + { + AudioFormat format = null; + + try + { + format = GstAudioFileReaderNativePeer.getAudioFormat(is); + } + catch (Exception e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + // get the header size + if (format == null) + throw new UnsupportedAudioFileException("Unsupported encoding."); + + return new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED); + } + + @Override + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException + { + return getAudioInputStream(new BufferedInputStream(url.openStream())); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java new file mode 100644 index 000000000..6345d7654 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java @@ -0,0 +1,284 @@ +/*GstAudioFileReaderNativePeer -- GNU Classpath GStreamer AudioFileReader + native peer class. + Copyright (C) 2007 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.sampled.gstreamer.io; + +import gnu.classpath.Pointer; +import gnu.javax.sound.sampled.gstreamer.GStreamerMixer; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * GStreamer native peer for GstAudioFileReader. + * + * @author Mario Torre <neugens@limasoftware.net> + */ +final class GstAudioFileReaderNativePeer +{ + private static final String GST_ENCODING = "GStreamer Generic Audio Reader"; + + private static class GstHeader + { + /* + * NOTE: these properties are accessed by the native code, be careful + * if you change them. + * Not all the fields are necessarily set. + * + */ + public String file = null; + + public String suffix = null; + + public String name = null; + + public String mimetype = null; + + public String endianness = null; + + public String channels = null; + + public String rate = null; + + public String width = null; + + public String depth = null; + + public String isSigned = null; + + public String layer = null; + + public String bitrate = null; + + public String framed = null; + + public String type = null; + } + + public static AudioFormat getAudioFormat(File file) throws Exception + { + GstHeader header = new GstHeader(); + header.file = file.getAbsolutePath(); + + if (!gstreamer_get_audio_format_file(header)) + return null; + + return getAudioFormat(header); + } + + public static AudioFormat getAudioFormat(InputStream is) throws Exception + { + return getAudioFormat(is, new GstHeader()); + } + + public static AudioFormat getAudioFormat(URL url) throws Exception + { + GstHeader header = new GstHeader(); + header.file = url.toExternalForm(); + + return getAudioFormat(url.openStream(), header); + } + + private static AudioFormat getAudioFormat(InputStream is, GstHeader header) + throws Exception + { + BufferedInputStream stream = new BufferedInputStream(is); + if(!stream.markSupported()) + throw new IOException("Stream must support marking."); + + stream.mark(0); + + if (!gstreamer_get_audio_format_stream(header, new GstInputStream(stream). + getNativeClass())) + return null; + + return getAudioFormat(header); + } + + private static Encoding getEncoding(GstHeader header) + { + StringBuilder buffer = new StringBuilder(); + + if (header.name == null) + { + buffer.append(GST_ENCODING); + if (header.mimetype != null) + { + buffer.append(" "); + buffer.append(header.mimetype); + } + + header.name = buffer.toString(); + } + else + { + // strip the "decoder" word from the name, if any + // this is a bit ugly, the alternative would be to still output the + // full name of the decoder/demuxer + String lowerCase = header.name.toLowerCase(); + int index = lowerCase.indexOf("decoder"); + if (index == -1) + { + index = lowerCase.indexOf("demuxer"); + } + + if (index == -1) + index = lowerCase.length(); + + buffer.append(header.name.substring(0, index)); + + } + + return new Encoding(buffer.toString().trim()); + } + + private static AudioFormat getAudioFormat(GstHeader header) + throws Exception + { + int na = AudioSystem.NOT_SPECIFIED; + + /* we use mimetype as an header, but this could have some side effects */ + Encoding encoding = getEncoding(header); + + float sampleRate = ((header.rate != null) ? + new Float(header.rate).floatValue() : na); + + int sampleSizeInBits = ((header.depth != null) ? + new Integer(header.depth).intValue() : na); + + int channels = ((header.channels != null) ? + new Integer(header.channels).intValue() : na); + + boolean bigEndian = false; + if (header.endianness != null) + { + if (header.endianness.compareTo("4321") == 0) + bigEndian = true; + } + + String ext = null; + + int frameSize = na; + float frameRate = na; + String lowerCase = header.name.toLowerCase(); + + // FIXME: frameRate = sampleRate in these cases under all the tests so far + // but I'm not sure if this is always correct... + if (lowerCase.contains("law") || lowerCase.contains("au")) + { + frameSize = (sampleSizeInBits >> 3) * channels; + frameRate = sampleRate; + ext = "au"; + } + else if (lowerCase.contains("wav")) + { + frameSize = ((sampleSizeInBits + 7) / 8) * channels; + frameRate = sampleRate; + ext = "wav"; + } + else if (lowerCase.contains("iff")) + { + frameSize = (sampleSizeInBits * channels) / 8; + frameRate = sampleRate; + ext = "aiff"; + } + + // write all the additional properties we got to identify + // the gstreamer plugin actually used to deal with this stream + Map<String, Object> properties = new HashMap<String, Object>(); + properties.put(GStreamerMixer.GST_BACKEND, true); + properties.put(GStreamerMixer.GST_DECODER, header.name); + properties.put(GStreamerMixer.GST_TYPE_NAME, encoding.toString()); + if (ext != null) + properties.put(GStreamerMixer.GST_FILE_EXTENSION, ext); + + /* now we put in some of the additional properties if we have them */ + if (header.type != null) properties.put("type", header.type); + if (header.framed != null) properties.put("framed", header.framed); + if (header.bitrate != null) properties.put("bitrate", header.bitrate); + if (header.isSigned != null) properties.put("isSigned", header.isSigned); + if (header.depth != null) properties.put("depth", header.depth); + if (header.mimetype != null) properties.put("mimetype", header.mimetype); + + AudioFormat format = new AudioFormat(encoding, + sampleRate, + sampleSizeInBits, + channels, + frameSize, + frameRate, + bigEndian, + properties); + return format; + } + + /* ***** native methods ***** */ + + /** + * Retrieve header information about the stream being played. + */ + native static final + protected boolean gstreamer_get_audio_format_stream(GstHeader info, + Pointer pointer); + + /** + * Retrieve header information about the file being played. + */ + native static final + protected boolean gstreamer_get_audio_format_file(GstHeader info); + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the static initializer. + */ + native private static final void init_id_cache(); + + static + { + System.loadLibrary("gstreamerpeer"); //$NON-NLS-1$ + init_id_cache(); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileWriter.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileWriter.java new file mode 100644 index 000000000..9b395dca2 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileWriter.java @@ -0,0 +1,80 @@ +/*GstAudioFileWriter -- GNU Classpath GStreamer AudioFileReader. + Copyright (C) 2007 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.sampled.gstreamer.io; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioFileFormat.Type; +import javax.sound.sampled.spi.AudioFileWriter; + +public class GstAudioFileWriter + extends AudioFileWriter +{ + @Override + public Type[] getAudioFileTypes() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Type[] getAudioFileTypes(AudioInputStream ais) + { + // TODO Auto-generated method stub + return null; + } + + @Override + public int write(AudioInputStream ais, Type type, File out) + throws IOException + { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int write(AudioInputStream ais, Type type, OutputStream os) + throws IOException + { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstInputStream.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstInputStream.java new file mode 100644 index 000000000..56bddcaad --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstInputStream.java @@ -0,0 +1,119 @@ +/* GstInputStream.java -- Trampoline class for an InputStream, mean to be used + by native code. + Copyright (C) 2007 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.sampled.gstreamer.io; + +import gnu.classpath.Pointer; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Encapsulates the functionality of an InputStream Object. + * + * This class is only meant to be used by the native code, to allow reading + * of the given InputStream as part of a the GStreamer InputStream Source + * Plugin. + * + * <strong>Note:</strong> this class will be not garbage collected as the + * native code contains strong references to internal fields. + * The native layer provides a method that can be called by the C code to + * free the resources and to let the garbage collected to handle this class + * when not needed anymore. + * + * @author Mario Torre <neugens@limasoftware.net> + */ +public class GstInputStream +{ + /** The real InputStream on which to perform reading operations. */ + private InputStream istream; + + /** + * Initialized in the native code, don't change without changes + * in the native layer. + */ + private Pointer gstInputStream = null; + + public GstInputStream(InputStream istream) + { + this.istream = istream; + init_instance(); + } + + public int read(byte[] buf, int off, int len) throws IOException + { + return this.istream.read(buf, off, len); + } + + public int available() throws IOException + { + return this.istream.available(); + } + + /** + * Return a reference to the GstInputStream native class as a Pointer object. + * This method is intended as an helper accessor and the returned pointer + * needs to be casted and used in the native code only. + * + * @return Pointer to the native GstInputStream class. + */ + public Pointer getNativeClass() + { + return this.gstInputStream; + } + + /* native methods */ + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the class constructor. + */ + native private final void init_instance(); + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the static initializer. + */ + native private static final void init_id_cache(); + + static + { + System.loadLibrary("gstreamerpeer"); //$NON-NLS-1$ + init_id_cache(); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java new file mode 100644 index 000000000..4e8cb1bb2 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java @@ -0,0 +1,151 @@ +/* GstDataLine.java -- Abstract DataLine. + Copyright (C) 2007 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.sampled.gstreamer.lines; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.Control.Type; + +public abstract class GstDataLine + implements DataLine +{ + public static final int DEFAULT_BUFFER_SIZE = 1024; + + /** Represents if this Line is opened or not. */ + protected Boolean open = false; + + private AudioFormat format = null; + private int bufferSize = 0; + + public GstDataLine(AudioFormat format) + { + this.format = format; + this.bufferSize = DEFAULT_BUFFER_SIZE; + } + + public GstDataLine(AudioFormat format, int bufferSize) + { + this.format = format; + this.bufferSize = bufferSize; + } + + public int getBufferSize() + { + return this.bufferSize; + } + + public AudioFormat getFormat() + { + return this.format; + } + + public float getLevel() + { + // TODO Auto-generated method stub + return 0; + } + + public void addLineListener(LineListener listener) + { + // TODO Auto-generated method stub + + } + + public Control getControl(Type what) + { + // TODO Auto-generated method stub + return null; + } + + public Control[] getControls() + { + // TODO Auto-generated method stub + return null; + } + + public javax.sound.sampled.Line.Info getLineInfo() + { + // TODO Auto-generated method stub + return null; + } + + public boolean isControlSupported(Type what) + { + return false; + } + + public boolean isOpen() + { + // TODO Auto-generated method stub + return false; + } + + public void removeLineListener(LineListener listener) + { + // TODO Auto-generated method stub + + } + + /* protected methods for subclasses */ + + /** + * @param open the open to set + */ + protected void setOpen(Boolean open) + { + this.open = open; + } + + /** + * @param bufferSize the bufferSize to set + */ + protected void setBufferSize(int bufferSize) + { + this.bufferSize = bufferSize; + } + + /** + * @param format the format to set + */ + protected void setFormat(AudioFormat format) + { + this.format = format; + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java new file mode 100644 index 000000000..896f0cb85 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java @@ -0,0 +1,77 @@ +/* GstNativeDataLine.java -- SourceDataLine implementation. + Copyright (C) 2007 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.sampled.gstreamer.lines; + +import gnu.classpath.Pointer; + +import javax.sound.sampled.LineUnavailableException; + +public class GstNativeDataLine +{ + public static final GstPipeline createSourcePipeline(int bufferSize) + throws LineUnavailableException + { + GstPipeline pipeline = new GstPipeline(bufferSize); + + pipeline.createForWrite(); + + if (!setup_sink_pipeline(pipeline.getNativeClass())) + throw new LineUnavailableException("Line unavailable"); + + return pipeline; + } + + /* native methods */ + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the static initializer. + */ + native static final private void init_id_cache(); + + /** + * Setup a new GStreamer Pipeline + */ + native static final private boolean setup_sink_pipeline(Pointer pipeline); + + static + { + System.loadLibrary("gstreamerpeer"); //$NON-NLS-1$ + init_id_cache(); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java new file mode 100644 index 000000000..9280e9f15 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java @@ -0,0 +1,415 @@ +/* GstPipeline.java -- Represents a Gstreamer Pipeline. + Copyright (C) 2007 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.sampled.gstreamer.lines; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.prefs.Preferences; + +import javax.sound.sampled.LineUnavailableException; + +import gnu.classpath.Pointer; + +/** + * This class represent a GStreamer pipeline and is resposible to handle the + * flow of data to and from the GStreamer native backend. + * + * @author Mario Torre <neugens@limasoftware.net> + */ +public class GstPipeline +{ + /* + * Implementation note: + * This class is at first a bit confusing as it serves as a gateway + * to a real filesystem named pipe. + * The pipelines is shared by the gstreamer backend and by the java code. + * If the operation we are performing is to play a given stream of bytes, + * we need to open the java side of the pipeline for writing, which is done + * in the prepareWrite method. At the same time, the native side of the code + * need to open the pipeline in read mode, to get access to the data, + * and hence, act as a source element. This is why you will see terms + * like "read" or "source" in methods that are used to write in the pipeline, + * in other words, each the native operation is the opposite of the java + * side operation. + * Opening the pipe to record audio data from the sound card works the same + * except that all the operation are inverted. + */ + + // These enums are used in the native code also, changes here must reflect + // changes in the native code. + public static enum State + { + PLAY, PAUSE, STOP, CLOSE + } + + private static final int READ = 0; + private static final int WRITE = 1; + private static final int QUEUED = 1; + + private static final String CAPACITY_KEY = "Capacity"; + + private static final Object [] lock = new Object[0]; + + /* + * Preference subsystem. We use this to store some system specific settings. + */ + protected Preferences prefs = + Preferences.userNodeForPackage(GstPipeline.class).node("GStreamer"); + + // used by the native code, stores the size of the named pipeline + // created by the operating system. + private long capacity = -1; + + /** Represents the playing state of this Line. */ + private State state = State.STOP; + + /** The name of the named pipe. */ + // Will be setup and filled in the native code. See the native library + // for details. + private String name = null; + + /** This is the named pipe that will be read by the gstreamer backend. */ + private FileOutputStream output = null; + + /** + * Defines if we are getting data from a sink pipe + * or writing to a source pipe. + */ + private boolean source = true; + + /** Indicate that we are ready to process audio data to/from the pipe. */ + private boolean ready = false; + + /** + * This is the native GStreamer Pipeline. + */ + // This field is used by the native code, so any change to it must be + // followed by similar changes in the native peer. + private Pointer pipeline = null; + + /** + * Creates a new GstPipeline with a capacity of + * {@link GstDataLine#DEFAULT_BUFFER_SIZE}. + * + * @see GstDataLine#DEFAULT_BUFFER_SIZE + */ + public GstPipeline() + { + this(GstDataLine.DEFAULT_BUFFER_SIZE); + } + + /** + * Creates a new GstPipeline with a capacity of bufferSize. + * @see GstDataLine#DEFAULT_BUFFER_SIZE + */ + public GstPipeline(int bufferSize) + { + // see if we need to detect the size of the named pipe or we can use + // an already computet default for this system. + // Note that this is very different from the bufferSize parameter, + // see below. + capacity = prefs.getLong(CAPACITY_KEY, -1); + if (capacity == -1) + { + synchronized (lock) + { + capacity = detect_pipe_size(); + } + + prefs.putLong(CAPACITY_KEY, capacity); + } + + // FIXME: bufferSize actually not used nor needed by the backend. + // Applications that expects a buffer of different size will be a + // bit disappointed by that.. + init_instance(); + + // need to remove the named pipe in case of abnormal termination + Runtime.getRuntime().addShutdownHook(new CleanPipeline()); + } + + /** + * Creates a source pipeline. A source pipeline is a pipe you send data for + * processing using the write method. + */ + public void createForWrite() throws LineUnavailableException + { + // create the named pipe + if (!create_named_pipe(this.pipeline)) + throw new LineUnavailableException("Unable to create filesystem pipe"); + + open_native_pipe(this.pipeline, READ); + prepareWrite(); + + this.source = true; + } + + /** + * @return the state + */ + public State getState() + { + return this.state; + } + + /** + * Closes this pipeline. + * Short hand for #setState(State.STOP). + */ + public void close() + { + setState(State.STOP); + } + + /** + * @param state the state to set + */ + public void setState(final State state) + { + int _state = -1; + switch (state) + { + case PLAY: + _state = 0; + break; + + case PAUSE: + _state = 1; + break; + + case STOP: case CLOSE: + _state = 2; + closePipe(); + break; + } + + if (set_state(pipeline, _state)) + GstPipeline.this.state = state; + } + + /** + * Return a reference to the GstPipeline native class as a Pointer object. + * This method is intended as an helper accessor and the returned pointer + * needs to be casted and used in the native code only. + * + * @return Pointer to the native GstPipeline class. + */ + public Pointer getNativeClass() + { + return this.pipeline; + } + + /** + * Write length bytes from the given buffer into this pipeline, + * starting at offset. + * This method block if the pipeline can't accept more data. + * + * @param buffer + * @param offset + * @param length + * @return + */ + public int write(byte[] buffer, int offset, int length) + { + if (this.state == State.STOP) + return -1; + else if (this.state == State.PAUSE) + return 0; + else if (!ready) + return -1; + + try + { + if (output != null) + { + output.write(buffer, offset, length); + return length; + } + return 0; + } + catch (Exception e) + { + /* nothing to do */ + } + + return -1; + } + + public int read(byte[] buffer, int offset, int length) + { + return 0; + } + + public int available() + { + if (this.source) + return available(this.pipeline, READ); + else + return available(this.pipeline, WRITE); + } + + /** + * Wait for remaining data to be enqueued in the pipeline. + */ + public void drain() + { + if (this.state == State.STOP) + return; + + try + { + // wait untill there is anymore data in the pipe + while (available(this.pipeline, QUEUED) > 0) + Thread.sleep(3000); + + // plus a bit to allow data to be processed + Thread.sleep(1000); + } + catch (InterruptedException e) + { + /* nothing to do*/ + } + } + + /** + * Flush all the data currently waiting to be processed. + */ + public void flush() + { + try + { + if (source) + this.output.flush(); + } + catch (IOException e) + { + /* nothing */ + } + } + + private void closePipe() + { + try + { + GstPipeline.this.flush(); + if (source) + GstPipeline.this.output.close(); + } + catch (IOException e) + { + /* nothing to do */ + } + } + + private void prepareWrite() + { + try + { + // if this is not completed for some reason, we will catch + // in the write method. As this call can block, we assume we will + // succeed and that the dataline can get data. + GstPipeline.this.ready = true; + GstPipeline.this.output = new FileOutputStream(name); + } + catch (Exception e) + { + GstPipeline.this.ready = false; + } + } + + /* ***** native ***** */ + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the static initializer. + */ + native private static final void init_id_cache(); + + /** + * Set the playing state of this pipeline. + */ + native private static final boolean set_state(Pointer pipeline, int state); + + /** + * Get the number of bytes currently available for reading or writing + * from the pipeline. + */ + native private static final int available(Pointer pipeline, int mode); + + /** + * Open the native pipeline with the given mode. + */ + native private static final void open_native_pipe(Pointer jpipeline, + int mode); + + /** + * Close the native pipeline. + */ + native private static final void close_native_pipe(Pointer jpipeline); + + /** + * Initialize the native peer and enables the object cache. + * It is meant to be used by the class constructor. + */ + native private final void init_instance(); + + /** + * Crates the named pipe used to pass data between the application code + * and gstreamer. + */ + native private final boolean create_named_pipe(Pointer jpipeline); + + /** + * Detect and return the size of the filesystem named pipe. + */ + native private final long detect_pipe_size(); + + private class CleanPipeline extends Thread + { + public void run() + { + GstPipeline.close_native_pipe(GstPipeline.this.pipeline); + } + } + + static + { + System.loadLibrary("gstreamerpeer"); //$NON-NLS-1$ + init_id_cache(); + } +} diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java new file mode 100644 index 000000000..2bc2de454 --- /dev/null +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java @@ -0,0 +1,153 @@ +/* GstSourceDataLine.java -- SourceDataLine implementation. + Copyright (C) 2007 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.sampled.gstreamer.lines; + +import gnu.javax.sound.AudioSecurityManager; +import gnu.javax.sound.sampled.gstreamer.lines.GstPipeline.State; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +import static gnu.javax.sound.AudioSecurityManager.Permission; + +public class GstSourceDataLine + extends GstDataLine implements SourceDataLine +{ + private GstPipeline pipeline = null; + private boolean open = false; + + public GstSourceDataLine(AudioFormat format) + { + super(format); + } + + public void open() throws LineUnavailableException + { + AudioSecurityManager.checkPermissions(Permission.PLAY); + + if (open) + throw new IllegalStateException("Line already opened"); + + // create the pipeline + pipeline = GstNativeDataLine.createSourcePipeline(getBufferSize()); + + this.open = true; + } + + public void open(AudioFormat fmt) throws LineUnavailableException + { + AudioSecurityManager.checkPermissions(Permission.PLAY); + + setFormat(fmt); + this.open(); + } + + public void open(AudioFormat fmt, int size) throws LineUnavailableException + { + AudioSecurityManager.checkPermissions(Permission.PLAY); + + setBufferSize(size); + this.open(fmt); + } + + public int write(byte[] buf, int offset, int length) + { + return this.pipeline.write(buf, offset, length); + } + + public int available() + { + return this.pipeline.available(); + } + + public void drain() + { + this.pipeline.drain(); + } + + public void flush() + { + this.pipeline.flush(); + } + + public int getFramePosition() + { + System.out.println("getFramePosition -: IMPLEMENT ME!!"); + return 0; + } + + public long getLongFramePosition() + { + System.out.println("getLongFramePosition -: IMPLEMENT ME!!"); + return 0; + } + + public long getMicrosecondPosition() + { + System.out.println("getMicrosecondPosition -: IMPLEMENT ME!!"); + return 0; + } + + public boolean isActive() + { + State state = pipeline.getState(); + return (state == State.PLAY || state == State.PAUSE); + } + + public void start() + { + pipeline.setState(State.PLAY); + } + + public void stop() + { + pipeline.setState(State.PAUSE); + } + + public void close() + { + pipeline.close(); + this.open = false; + } + + public boolean isRunning() + { + return (pipeline.getState() == State.PLAY); + } +} |