diff options
| author | doko <doko@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-06-28 13:29:13 +0000 |
|---|---|---|
| committer | doko <doko@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-06-28 13:29:13 +0000 |
| commit | 1020ce5944edde4364baef4d371cd4f9b0dae721 (patch) | |
| tree | 602cd7aa7c947386134690d8e0f6b53abcdeacb9 /libjava/classpath/gnu/javax/sound | |
| parent | 9f41ce98ce6f4f7c8ac5e2c4b6e5d27e10201015 (diff) | |
| download | ppe42-gcc-1020ce5944edde4364baef4d371cd4f9b0dae721.tar.gz ppe42-gcc-1020ce5944edde4364baef4d371cd4f9b0dae721.zip | |
libjava/
2008-06-28 Matthias Klose <doko@ubuntu.com>
Import GNU Classpath (classpath-0_97_2-release).
* Regenerate class and header files.
* Regenerate auto* files.
* gcj/javaprims.h: Define jobjectRefType.
* jni.cc (_Jv_JNI_GetObjectRefType): New (stub only).
(_Jv_JNIFunctions): Initialize GetObjectRefType.
* gnu/classpath/jdwp/VMVirtualMachine.java,
java/security/VMSecureRandom.java: Merge from classpath.
* HACKING: Fix typo.
* ChangeLog-2007: New file.
* configure.ac: Set JAVAC, pass --disable-regen-headers to classpath.
libjava/classpath/
2008-06-28 Matthias Klose <doko@ubuntu.com>
* m4/ac_prog_javac.m4: Disable check for JAVAC, when
not configured with --enable-java-maintainer-mode.
* aclocal.m4, configure: Regenerate.
* native/jni/gstreamer-peer/Makefile.am: Do not link with
libclasspathnative.
* native/jni/gstreamer-peer/Makefile.in: Regenerate.
* tools/Makefile.am, lib/Makefile.am: Use JAVAC for setting
JCOMPILER, drop flags not understood by gcj.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@137223 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/classpath/gnu/javax/sound')
12 files changed, 734 insertions, 107 deletions
diff --git a/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java b/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java index cd10e510665..a6dce60b394 100644 --- a/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java +++ b/libjava/classpath/gnu/javax/sound/AudioSecurityManager.java @@ -1,19 +1,90 @@ +/* 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(); diff --git a/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java index baf61732d18..740b124eb65 100644 --- a/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java +++ b/libjava/classpath/gnu/javax/sound/midi/dssi/DSSIMidiDeviceProvider.java @@ -44,8 +44,6 @@ import java.io.File; import java.io.FilenameFilter; import gnu.classpath.Configuration; -import gnu.javax.sound.midi.alsa.AlsaMidiSequencerDevice; - import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiDevice.Info; import javax.sound.midi.spi.MidiDeviceProvider; diff --git a/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java index 71970d5ba6e..b9b6fe87a10 100644 --- a/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java +++ b/libjava/classpath/gnu/javax/sound/midi/file/MidiFileWriter.java @@ -38,10 +38,8 @@ exception statement from your version. */ package gnu.javax.sound.midi.file; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import javax.sound.midi.MetaMessage; diff --git a/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java b/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java index c9035df7338..ed5852e6c9a 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java +++ b/libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java @@ -47,7 +47,6 @@ import java.io.File; import java.io.IOException; import java.io.BufferedInputStream; import java.io.InputStream; -import java.io.DataInputStream; import java.io.FileInputStream; import java.net.URL; import java.nio.ByteBuffer; diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java index b32db0f353c..aa42a4c3da8 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java @@ -37,13 +37,9 @@ exception statement from your version. */ package gnu.javax.sound.sampled.gstreamer; -import java.awt.AWTPermission; - import gnu.javax.sound.sampled.gstreamer.lines.GstSourceDataLine; import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioPermission; -import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Control; import javax.sound.sampled.DataLine; import javax.sound.sampled.Line; @@ -52,7 +48,6 @@ import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.Control.Type; -import javax.sound.sampled.Line.Info; /** * @author Mario Torre <neugens@limasoftware.net> @@ -81,32 +76,15 @@ public class GStreamerMixer super(name, vendor, desc, vers); } } - + public static final String GST_BACKEND = GstInfo.name; public static final String GST_DECODER = "decoder"; - - private static AudioFormat[] BASIC_FORMATS = - { - new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - true), - - new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - AudioSystem.NOT_SPECIFIED, - false), - }; + 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 { diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java index 53b2155d8ec..b90caef24b5 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java @@ -37,13 +37,14 @@ exception statement from your version. */ package gnu.javax.sound.sampled.gstreamer.io; +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; @@ -59,21 +60,61 @@ import javax.sound.sampled.spi.AudioFileReader; */ public class GstAudioFileReader extends AudioFileReader -{ +{ @Override public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException { - throw new UnsupportedAudioFileException("Unsupported encoding."); + StringBuffer name = new StringBuffer(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 { - throw new UnsupportedAudioFileException("Unsupported encoding."); + 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 @@ -96,8 +137,11 @@ public class GstAudioFileReader } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); + UnsupportedAudioFileException ex = + new UnsupportedAudioFileException("Unsupported encoding."); + + ex.initCause(ex.getCause()); + throw ex; } // get the header size diff --git a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java index 45ae4ff8588..761720fee5d 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java @@ -38,6 +38,7 @@ 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; @@ -90,8 +91,11 @@ final class GstAudioFileReaderNativePeer public String isSigned = null; public String layer = null; + public String bitrate = null; + public String framed = null; + public String type = null; } @@ -108,18 +112,7 @@ final class GstAudioFileReaderNativePeer public static AudioFormat getAudioFormat(InputStream is) throws Exception { - GstHeader header = new GstHeader(); - - 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, stream)) - return null; - - return getAudioFormat(header); + return getAudioFormat(is, new GstHeader()); } public static AudioFormat getAudioFormat(URL url) throws Exception @@ -127,13 +120,20 @@ final class GstAudioFileReaderNativePeer GstHeader header = new GstHeader(); header.file = url.toExternalForm(); - BufferedInputStream stream = new BufferedInputStream(url.openStream()); + 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, stream)) + if (!gstreamer_get_audio_format_stream(header, new GstInputStream(stream). + getNativeClass())) return null; return getAudioFormat(header); @@ -200,27 +200,31 @@ final class GstAudioFileReaderNativePeer 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") || - lowerCase.contains("x-au")) + 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 @@ -228,6 +232,9 @@ final class GstAudioFileReaderNativePeer 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); @@ -251,26 +258,27 @@ final class GstAudioFileReaderNativePeer /* ***** native methods ***** */ /** - * Retrieve header information about the file being played. - * - * @param info - * @return + * Retrieve header information about the stream being played. */ native static final protected boolean gstreamer_get_audio_format_stream(GstHeader info, - BufferedInputStream istream); + Pointer pointer); /** * Retrieve header information about the file being played. - * - * @param info - * @return */ 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/GstInputStream.java b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstInputStream.java new file mode 100644 index 00000000000..0702eded7e8 --- /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 index 0467c955905..33be15c58b8 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java @@ -41,22 +41,13 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.Control; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineListener; -import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Control.Type; public abstract class GstDataLine implements DataLine { - public static enum State - { - PLAY, PAUSE, STOP - } - public static final int DEFAULT_BUFFER_SIZE = 1024; - /** Represents the playing state of this Line. */ - protected State state = State.STOP; - /** Represents if this Line is opened or not. */ protected Boolean open = false; @@ -90,12 +81,7 @@ public abstract class GstDataLine // TODO Auto-generated method stub return 0; } - - public boolean isRunning() - { - return (state == State.PLAY || state == State.PAUSE); - } - + public void addLineListener(LineListener listener) { // TODO Auto-generated method stub @@ -131,15 +117,35 @@ public abstract class GstDataLine return false; } - public void open() throws LineUnavailableException + public void removeLineListener(LineListener listener) { // TODO Auto-generated method stub } - public void removeLineListener(LineListener listener) + /* protected methods for subclasses */ + + /** + * @param open the open to set + */ + protected void setOpen(Boolean open) { - // TODO Auto-generated method stub + 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 index 2b41a118672..84007ac97e7 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java @@ -37,12 +37,41 @@ 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 index d1460e5090f..f561f71c2fa 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java @@ -34,24 +34,382 @@ 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}. * - * This field is used by the native code, so any change to it must be - * followed by similar changes in the native peer. + * @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 */ - private Pointer pipeline; + 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; + } - native private void setState(); + 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 index d1a0262e5b5..f149ab39df2 100644 --- a/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java +++ b/libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java @@ -38,6 +38,7 @@ 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; @@ -48,87 +49,105 @@ 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); - throw new LineUnavailableException("Line unavailable"); + + setFormat(fmt); + this.open(); } public void open(AudioFormat fmt, int size) throws LineUnavailableException { AudioSecurityManager.checkPermissions(Permission.PLAY); - throw new LineUnavailableException("Line unavailable"); + + setBufferSize(size); + this.open(fmt); } public int write(byte[] buf, int offset, int length) - { - // TODO Auto-generated method stub - return 0; + { + return this.pipeline.write(buf, offset, length); } public int available() { - // TODO Auto-generated method stub - return 0; + return this.pipeline.available(); } public void drain() { - // TODO Auto-generated method stub - + this.pipeline.drain(); } public void flush() { - // TODO Auto-generated method stub - + this.pipeline.flush(); } public int getFramePosition() { - // TODO Auto-generated method stub + System.out.println("getFramePosition -: IMPLEMENT ME!!"); return 0; } public long getLongFramePosition() { - // TODO Auto-generated method stub + System.out.println("getLongFramePosition -: IMPLEMENT ME!!"); return 0; } public long getMicrosecondPosition() { - // TODO Auto-generated method stub + System.out.println("getMicrosecondPosition -: IMPLEMENT ME!!"); return 0; } public boolean isActive() { - // TODO Auto-generated method stub - return false; + State state = pipeline.getState(); + return (state == State.PLAY || state == State.PAUSE); } public void start() { - // TODO Auto-generated method stub - + pipeline.setState(State.PLAY); } public void stop() { - // TODO Auto-generated method stub - + pipeline.setState(State.PAUSE); } public void close() { - // TODO Auto-generated method stub - + pipeline.close(); + this.open = false; + } + + public boolean isRunning() + { + return (pipeline.getState() == State.PLAY); } - } |

