From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; 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. --- .../gnu/javax/sound/sampled/AU/AUReader.java | 210 +++++++++++ .../gnu/javax/sound/sampled/WAV/WAVReader.java | 236 ++++++++++++ .../sound/sampled/gstreamer/GStreamerMixer.java | 248 ++++++++++++ .../sampled/gstreamer/GStreamerMixerProvider.java | 71 ++++ .../sampled/gstreamer/io/GstAudioFileReader.java | 185 +++++++++ .../gstreamer/io/GstAudioFileReaderNativePeer.java | 284 ++++++++++++++ .../sampled/gstreamer/io/GstAudioFileWriter.java | 80 ++++ .../sound/sampled/gstreamer/io/GstInputStream.java | 119 ++++++ .../sound/sampled/gstreamer/lines/GstDataLine.java | 151 ++++++++ .../sampled/gstreamer/lines/GstNativeDataLine.java | 77 ++++ .../sound/sampled/gstreamer/lines/GstPipeline.java | 415 +++++++++++++++++++++ .../sampled/gstreamer/lines/GstSourceDataLine.java | 153 ++++++++ 12 files changed, 2229 insertions(+) create mode 100644 libjava/classpath/gnu/javax/sound/sampled/AU/AUReader.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/WAV/WAVReader.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixer.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/GStreamerMixerProvider.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReader.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileReaderNativePeer.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstAudioFileWriter.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/io/GstInputStream.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstDataLine.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstNativeDataLine.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstPipeline.java create mode 100644 libjava/classpath/gnu/javax/sound/sampled/gstreamer/lines/GstSourceDataLine.java (limited to 'libjava/classpath/gnu/javax/sound/sampled') 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 + */ +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 + */ +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 + */ +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 properties = new HashMap(); + 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. + * + * Note: 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 + */ +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 + */ +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); + } +} -- cgit v1.2.3